GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/check_models.cpp Lines: 28 43 65.1 %
Date: 2021-09-17 Branches: 51 182 28.0 %

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/node_command.h"
22
#include "smt/preprocessor.h"
23
#include "smt/smt_solver.h"
24
#include "theory/rewriter.h"
25
#include "theory/substitutions.h"
26
#include "theory/theory_engine.h"
27
#include "theory/theory_model.h"
28
29
using namespace cvc5::theory;
30
31
namespace cvc5 {
32
namespace smt {
33
34
9942
CheckModels::CheckModels(Env& e) : d_env(e) {}
35
9939
CheckModels::~CheckModels() {}
36
37
2157
void CheckModels::checkModel(TheoryModel* 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
2157
  if (m->hasApproximations())
49
  {
50
    throw RecoverableModalException(
51
1
        "Cannot run check-model on a model with approximate values.");
52
  }
53
54
2156
  theory::SubstitutionMap& sm = d_env.getTopLevelSubstitutions().get();
55
2156
  Trace("check-model") << "checkModel: Check assertions..." << std::endl;
56
2198
  std::unordered_map<Node, Node> cache;
57
  // the list of assertions that did not rewrite to true
58
2198
  std::vector<Node> noCheckList;
59
  // Now go through all our user assertions checking if they're satisfied.
60
23863
  for (const Node& assertion : *al)
61
  {
62
21707
    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
21707
    Node n = sm.apply(assertion, false);
71
21707
    Notice() << "SmtEngine::checkModel(): -- substitutes to " << n << std::endl;
72
73
21707
    n = Rewriter::rewrite(n);
74
21707
    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
21707
    n = m->getValue(n);
80
21707
    Notice() << "SmtEngine::checkModel(): -- get value : " << n << std::endl;
81
82
21707
    if (n.isConst() && n.getConst<bool>())
83
    {
84
      // assertion is true, everything is fine
85
21659
      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
    // One example is the occurrence of partial operators. Another example
92
    // are quantified formulas, which are not checkable, although we assign
93
    // them to true/false based on the satisfying assignment. However,
94
    // quantified formulas can be modified during preprocess, so they may not
95
    // correspond to those in the satisfying assignment. Hence we throw
96
    // warnings for assertions that do not simplify to either true or false.
97
    // Other theories such as non-linear arithmetic (in particular,
98
    // transcendental functions) also have the property of not being able to
99
    // be checked precisely here.
100
    // Note that warnings like these can be avoided for quantified formulas
101
    // by making preprocessing passes explicitly record how they
102
    // rewrite quantified formulas (see cvc4-wishues#43).
103
96
    if (!n.isConst())
104
    {
105
      // Not constant, print a less severe warning message here.
106
48
      Warning() << "Warning : SmtEngine::checkModel(): cannot check simplified "
107
                   "assertion : "
108
                << n << std::endl;
109
48
      noCheckList.push_back(n);
110
48
      continue;
111
    }
112
    // Assertions that simplify to false result in an InternalError or
113
    // Warning being thrown below (when hardFailure is false).
114
    Notice() << "SmtEngine::checkModel(): *** PROBLEM: EXPECTED `TRUE' ***"
115
             << std::endl;
116
    std::stringstream ss;
117
    ss << "SmtEngine::checkModel(): "
118
       << "ERRORS SATISFYING ASSERTIONS WITH MODEL:" << std::endl
119
       << "assertion:     " << assertion << std::endl
120
       << "simplifies to: " << n << std::endl
121
       << "expected `true'." << std::endl
122
       << "Run with `--check-models -v' for additional diagnostics.";
123
    if (hardFailure)
124
    {
125
      // internal error if hardFailure is true
126
      InternalError() << ss.str();
127
    }
128
    else
129
    {
130
      Warning() << ss.str() << std::endl;
131
    }
132
  }
133
2156
  if (noCheckList.empty())
134
  {
135
2114
    Notice() << "SmtEngine::checkModel(): all assertions checked out OK !"
136
             << std::endl;
137
2114
    return;
138
  }
139
  // if the noCheckList is non-empty, we could expand definitions on this list
140
  // and check satisfiability
141
142
42
  Trace("check-model") << "checkModel: Finish" << std::endl;
143
}
144
145
}  // namespace smt
146
29577
}  // namespace cvc5