GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/check_models.cpp Lines: 28 43 65.1 %
Date: 2021-08-06 Branches: 51 184 27.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Andres Noetzli
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Utility for constructing and maintaining abstract values.
14
 */
15
16
#include "smt/check_models.h"
17
18
#include "base/modal_exception.h"
19
#include "options/smt_options.h"
20
#include "smt/env.h"
21
#include "smt/model.h"
22
#include "smt/node_command.h"
23
#include "smt/preprocessor.h"
24
#include "smt/smt_solver.h"
25
#include "theory/rewriter.h"
26
#include "theory/substitutions.h"
27
#include "theory/theory_engine.h"
28
29
using namespace cvc5::theory;
30
31
namespace cvc5 {
32
namespace smt {
33
34
9853
CheckModels::CheckModels(Env& e) : d_env(e) {}
35
9853
CheckModels::~CheckModels() {}
36
37
2151
void CheckModels::checkModel(Model* m,
38
                             context::CDList<Node>* al,
39
                             bool hardFailure)
40
{
41
  // Throughout, we use Notice() to give diagnostic output.
42
  //
43
  // If this function is running, the user gave --check-model (or equivalent),
44
  // and if Notice() is on, the user gave --verbose (or equivalent).
45
46
  // check-model is not guaranteed to succeed if approximate values were used.
47
  // Thus, we intentionally abort here.
48
2151
  if (m->hasApproximations())
49
  {
50
    throw RecoverableModalException(
51
1
        "Cannot run check-model on a model with approximate values.");
52
  }
53
54
2150
  theory::SubstitutionMap& sm = d_env.getTopLevelSubstitutions().get();
55
2150
  Trace("check-model") << "checkModel: Check assertions..." << std::endl;
56
2191
  std::unordered_map<Node, Node> cache;
57
  // the list of assertions that did not rewrite to true
58
2191
  std::vector<Node> noCheckList;
59
  // Now go through all our user assertions checking if they're satisfied.
60
23806
  for (const Node& assertion : *al)
61
  {
62
21656
    Notice() << "SmtEngine::checkModel(): checking assertion " << assertion
63
             << std::endl;
64
65
    // Apply any define-funs from the problem. We do not expand theory symbols
66
    // like integer division here. Hence, the code below is not able to properly
67
    // evaluate e.g. divide-by-zero. This is intentional since the evaluation
68
    // is not trustworthy, since the UF introduced by expanding definitions may
69
    // not be properly constrained.
70
21656
    Node n = sm.apply(assertion, false);
71
21656
    Notice() << "SmtEngine::checkModel(): -- substitutes to " << n << std::endl;
72
73
21656
    n = Rewriter::rewrite(n);
74
21656
    Notice() << "SmtEngine::checkModel(): -- rewrites to " << n << std::endl;
75
76
    // We look up the value before simplifying. If n contains quantifiers,
77
    // this may increases the chance of finding its value before the node is
78
    // altered by simplification below.
79
21656
    n = m->getValue(n);
80
21656
    Notice() << "SmtEngine::checkModel(): -- get value : " << n << std::endl;
81
82
21656
    if (n.isConst() && n.getConst<bool>())
83
    {
84
      // assertion is true, everything is fine
85
21609
      continue;
86
    }
87
88
    // Otherwise, we did not succeed in showing the current assertion to be
89
    // true. This may either indicate that our model is wrong, or that we cannot
90
    // check it. The latter may be the case for several reasons.
91
    // For example, quantified formulas are not checkable, although we assign
92
    // them to true/false based on the satisfying assignment. However,
93
    // quantified formulas can be modified during preprocess, so they may not
94
    // correspond to those in the satisfying assignment. Hence we throw
95
    // warnings for assertions that do not simplify to either true or false.
96
    // Other theories such as non-linear arithmetic (in particular,
97
    // transcendental functions) also have the property of not being able to
98
    // be checked precisely here.
99
    // Note that warnings like these can be avoided for quantified formulas
100
    // by making preprocessing passes explicitly record how they
101
    // rewrite quantified formulas (see cvc4-wishues#43).
102
94
    if (!n.isConst())
103
    {
104
      // Not constant, print a less severe warning message here.
105
47
      Warning() << "Warning : SmtEngine::checkModel(): cannot check simplified "
106
                   "assertion : "
107
                << n << std::endl;
108
47
      noCheckList.push_back(n);
109
47
      continue;
110
    }
111
    // Assertions that simplify to false result in an InternalError or
112
    // Warning being thrown below (when hardFailure is false).
113
    Notice() << "SmtEngine::checkModel(): *** PROBLEM: EXPECTED `TRUE' ***"
114
             << std::endl;
115
    std::stringstream ss;
116
    ss << "SmtEngine::checkModel(): "
117
       << "ERRORS SATISFYING ASSERTIONS WITH MODEL:" << std::endl
118
       << "assertion:     " << assertion << std::endl
119
       << "simplifies to: " << n << std::endl
120
       << "expected `true'." << std::endl
121
       << "Run with `--check-models -v' for additional diagnostics.";
122
    if (hardFailure)
123
    {
124
      // internal error if hardFailure is true
125
      InternalError() << ss.str();
126
    }
127
    else
128
    {
129
      Warning() << ss.str() << std::endl;
130
    }
131
  }
132
2150
  if (noCheckList.empty())
133
  {
134
2109
    Notice() << "SmtEngine::checkModel(): all assertions checked out OK !"
135
             << std::endl;
136
2109
    return;
137
  }
138
  // if the noCheckList is non-empty, we could expand definitions on this list
139
  // and check satisfiability
140
141
41
  Trace("check-model") << "checkModel: Finish" << std::endl;
142
}
143
144
}  // namespace smt
145
29322
}  // namespace cvc5