GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/assertions.cpp Lines: 80 91 87.9 %
Date: 2021-05-22 Branches: 103 228 45.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Andres Noetzli, Haniel Barbosa
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
 * The module for storing assertions for an SMT engine.
14
 */
15
16
#include "smt/assertions.h"
17
18
#include <sstream>
19
20
#include "base/modal_exception.h"
21
#include "expr/node_algorithm.h"
22
#include "options/base_options.h"
23
#include "options/expr_options.h"
24
#include "options/language.h"
25
#include "options/smt_options.h"
26
#include "smt/abstract_values.h"
27
#include "smt/env.h"
28
#include "smt/smt_engine.h"
29
#include "theory/trust_substitutions.h"
30
31
using namespace cvc5::theory;
32
using namespace cvc5::kind;
33
34
namespace cvc5 {
35
namespace smt {
36
37
10093
Assertions::Assertions(Env& env, AbstractValues& absv)
38
    : d_env(env),
39
      d_absValues(absv),
40
      d_produceAssertions(false),
41
10093
      d_assertionList(env.getUserContext()),
42
      d_globalNegation(false),
43
20186
      d_assertions()
44
{
45
10093
}
46
47
10093
Assertions::~Assertions()
48
{
49
10093
}
50
51
9459
void Assertions::finishInit()
52
{
53
  // [MGD 10/20/2011] keep around in incremental mode, due to a
54
  // cleanup ordering issue and Nodes/TNodes.  If SAT is popped
55
  // first, some user-context-dependent TNodes might still exist
56
  // with rc == 0.
57
28504
  if (options::produceAssertions() || options::incrementalSolving())
58
  {
59
    // In the case of incremental solving, we appear to need these to
60
    // ensure the relevant Nodes remain live.
61
7209
    d_produceAssertions = true;
62
7209
    d_globalDefineFunLemmas.reset(new std::vector<Node>());
63
  }
64
9459
}
65
66
15905
void Assertions::clearCurrent()
67
{
68
15905
  d_assertions.clear();
69
15905
  d_assertions.getIteSkolemMap().clear();
70
15905
}
71
72
14323
void Assertions::initializeCheckSat(const std::vector<Node>& assumptions,
73
                                    bool inUnsatCore,
74
                                    bool isEntailmentCheck)
75
{
76
14323
  NodeManager* nm = NodeManager::currentNM();
77
  // reset global negation
78
14323
  d_globalNegation = false;
79
  // clear the assumptions
80
14323
  d_assumptions.clear();
81
14323
  if (isEntailmentCheck)
82
  {
83
666
    size_t size = assumptions.size();
84
666
    if (size > 1)
85
    {
86
      /* Assume: not (BIGAND assumptions)  */
87
2
      d_assumptions.push_back(nm->mkNode(AND, assumptions).notNode());
88
    }
89
664
    else if (size == 1)
90
    {
91
      /* Assume: not expr  */
92
664
      d_assumptions.push_back(assumptions[0].notNode());
93
    }
94
  }
95
  else
96
  {
97
    /* Assume: BIGAND assumptions  */
98
13657
    d_assumptions = assumptions;
99
  }
100
101
28646
  Result r(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
102
16801
  for (const Node& e : d_assumptions)
103
  {
104
    // Substitute out any abstract values in ex.
105
4956
    Node n = d_absValues.substituteAbstractValues(e);
106
    // Ensure expr is type-checked at this point.
107
2478
    ensureBoolean(n);
108
2478
    addFormula(n, inUnsatCore, true, true, false, false);
109
  }
110
14323
  if (d_globalDefineFunLemmas != nullptr)
111
  {
112
    // Global definitions are asserted at check-sat-time because we have to
113
    // make sure that they are always present (they are essentially level
114
    // zero assertions)
115
12382
    for (const Node& lemma : *d_globalDefineFunLemmas)
116
    {
117
297
      addFormula(lemma, false, true, false, true, false);
118
    }
119
  }
120
14323
}
121
122
89066
void Assertions::assertFormula(const Node& n, bool inUnsatCore)
123
{
124
89066
  ensureBoolean(n);
125
89066
  bool maybeHasFv = language::isInputLangSygus(options::inputLanguage());
126
89066
  addFormula(n, inUnsatCore, true, false, false, maybeHasFv);
127
89066
}
128
129
13
std::vector<Node>& Assertions::getAssumptions() { return d_assumptions; }
130
14294
bool Assertions::isGlobalNegated() const { return d_globalNegation; }
131
6
void Assertions::flipGlobalNegated() { d_globalNegation = !d_globalNegation; }
132
133
48052
preprocessing::AssertionPipeline& Assertions::getAssertionPipeline()
134
{
135
48052
  return d_assertions;
136
}
137
138
6375
context::CDList<Node>* Assertions::getAssertionList()
139
{
140
6375
  return d_produceAssertions ? &d_assertionList : nullptr;
141
}
142
143
94067
void Assertions::addFormula(TNode n,
144
                            bool inUnsatCore,
145
                            bool inInput,
146
                            bool isAssumption,
147
                            bool isFunDef,
148
                            bool maybeHasFv)
149
{
150
  // add to assertion list if it exists
151
94067
  if (d_produceAssertions)
152
  {
153
63273
    d_assertionList.push_back(n);
154
  }
155
94067
  if (n.isConst() && n.getConst<bool>())
156
  {
157
    // true, nothing to do
158
496
    return;
159
  }
160
187142
  Trace("smt") << "SmtEnginePrivate::addFormula(" << n
161
93571
               << "), inUnsatCore = " << inUnsatCore
162
93571
               << ", inInput = " << inInput
163
93571
               << ", isAssumption = " << isAssumption
164
93571
               << ", isFunDef = " << isFunDef << std::endl;
165
93571
  if (isFunDef)
166
  {
167
    // if a non-recursive define-fun, just add as a top-level substitution
168
2523
    if (n.getKind() == EQUAL && n[0].isVar())
169
    {
170
      // A define-fun is an assumption in the overall proof, thus
171
      // we justify the substitution with ASSUME here.
172
4686
      d_env.getTopLevelSubstitutions().addSubstitution(
173
2343
          n[0], n[1], PfRule::ASSUME, {}, {n});
174
2343
      return;
175
    }
176
  }
177
178
  // Ensure that it does not contain free variables
179
91228
  if (maybeHasFv)
180
  {
181
686
    if (expr::hasFreeVar(n))
182
    {
183
      std::stringstream se;
184
      se << "Cannot process assertion with free variable.";
185
      if (language::isInputLangSygus(options::inputLanguage()))
186
      {
187
        // Common misuse of SyGuS is to use top-level assert instead of
188
        // constraint when defining the synthesis conjecture.
189
        se << " Perhaps you meant `constraint` instead of `assert`?";
190
      }
191
      throw ModalException(se.str().c_str());
192
    }
193
  }
194
195
  // Add the normalized formula to the queue
196
91228
  d_assertions.push_back(n, isAssumption, true);
197
}
198
199
2443
void Assertions::addDefineFunDefinition(Node n, bool global)
200
{
201
2443
  n = d_absValues.substituteAbstractValues(n);
202
2443
  if (global && d_globalDefineFunLemmas != nullptr)
203
  {
204
    // Global definitions are asserted at check-sat-time because we have to
205
    // make sure that they are always present
206
217
    Assert(!language::isInputLangSygus(options::inputLanguage()));
207
217
    d_globalDefineFunLemmas->emplace_back(n);
208
  }
209
  else
210
  {
211
    // we don't check for free variables here, since even if we are sygus,
212
    // we could contain functions-to-synthesize within definitions.
213
2226
    addFormula(n, false, true, false, true, false);
214
  }
215
2443
}
216
217
91544
void Assertions::ensureBoolean(const Node& n)
218
{
219
281696
  TypeNode type = n.getType(options::typeChecking());
220
91544
  if (!type.isBoolean())
221
  {
222
    std::stringstream ss;
223
    ss << "Expected Boolean type\n"
224
       << "The assertion : " << n << "\n"
225
       << "Its type      : " << type;
226
    throw TypeCheckingExceptionPrivate(n, ss.str());
227
  }
228
91544
}
229
230
3600
void Assertions::setProofGenerator(smt::PreprocessProofGenerator* pppg)
231
{
232
3600
  d_assertions.setProofGenerator(pppg);
233
3600
}
234
235
bool Assertions::isProofEnabled() const
236
{
237
  return d_assertions.isProofEnabled();
238
}
239
240
}  // namespace smt
241
145844
}  // namespace cvc5