1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Haniel Barbosa, Morgan Deters |
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 |
|
* Implementation of the propositional engine of cvc5. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "prop/prop_engine.h" |
17 |
|
|
18 |
|
#include <iomanip> |
19 |
|
#include <map> |
20 |
|
#include <utility> |
21 |
|
|
22 |
|
#include "base/check.h" |
23 |
|
#include "base/output.h" |
24 |
|
#include "decision/decision_engine_old.h" |
25 |
|
#include "decision/justification_strategy.h" |
26 |
|
#include "options/base_options.h" |
27 |
|
#include "options/decision_options.h" |
28 |
|
#include "options/main_options.h" |
29 |
|
#include "options/options.h" |
30 |
|
#include "options/proof_options.h" |
31 |
|
#include "options/smt_options.h" |
32 |
|
#include "prop/cnf_stream.h" |
33 |
|
#include "prop/minisat/minisat.h" |
34 |
|
#include "prop/prop_proof_manager.h" |
35 |
|
#include "prop/sat_solver.h" |
36 |
|
#include "prop/sat_solver_factory.h" |
37 |
|
#include "prop/theory_proxy.h" |
38 |
|
#include "smt/env.h" |
39 |
|
#include "smt/smt_statistics_registry.h" |
40 |
|
#include "theory/output_channel.h" |
41 |
|
#include "theory/theory_engine.h" |
42 |
|
#include "util/resource_manager.h" |
43 |
|
#include "util/result.h" |
44 |
|
|
45 |
|
namespace cvc5 { |
46 |
|
namespace prop { |
47 |
|
|
48 |
|
/** Keeps a boolean flag scoped */ |
49 |
|
class ScopedBool { |
50 |
|
|
51 |
|
private: |
52 |
|
|
53 |
|
bool d_original; |
54 |
|
bool& d_reference; |
55 |
|
|
56 |
|
public: |
57 |
|
|
58 |
15192 |
ScopedBool(bool& reference) : |
59 |
15192 |
d_reference(reference) { |
60 |
15192 |
d_original = reference; |
61 |
15192 |
} |
62 |
|
|
63 |
30384 |
~ScopedBool() { |
64 |
15192 |
d_reference = d_original; |
65 |
15192 |
} |
66 |
|
}; |
67 |
|
|
68 |
9908 |
PropEngine::PropEngine(TheoryEngine* te, |
69 |
|
Env& env, |
70 |
|
OutputManager& outMgr, |
71 |
9908 |
ProofNodeManager* pnm) |
72 |
|
: d_inCheckSat(false), |
73 |
|
d_theoryEngine(te), |
74 |
|
d_env(env), |
75 |
9908 |
d_skdm(new SkolemDefManager(d_env.getContext(), d_env.getUserContext())), |
76 |
|
d_theoryProxy(nullptr), |
77 |
|
d_satSolver(nullptr), |
78 |
|
d_pnm(pnm), |
79 |
|
d_cnfStream(nullptr), |
80 |
|
d_pfCnfStream(nullptr), |
81 |
|
d_ppm(nullptr), |
82 |
|
d_interrupted(false), |
83 |
|
d_outMgr(outMgr), |
84 |
19816 |
d_assumptions(d_env.getUserContext()) |
85 |
|
{ |
86 |
9908 |
Debug("prop") << "Constructing the PropEngine" << std::endl; |
87 |
9908 |
context::Context* satContext = d_env.getContext(); |
88 |
9908 |
context::UserContext* userContext = d_env.getUserContext(); |
89 |
9908 |
ResourceManager* rm = d_env.getResourceManager(); |
90 |
|
|
91 |
9908 |
options::DecisionMode dmode = options::decisionMode(); |
92 |
9908 |
if (dmode == options::DecisionMode::JUSTIFICATION |
93 |
2596 |
|| dmode == options::DecisionMode::STOPONLY) |
94 |
|
{ |
95 |
15456 |
d_decisionEngine.reset(new decision::JustificationStrategy( |
96 |
7728 |
satContext, userContext, d_skdm.get(), rm)); |
97 |
|
} |
98 |
2180 |
else if (dmode == options::DecisionMode::JUSTIFICATION_OLD |
99 |
2178 |
|| dmode == options::DecisionMode::STOPONLY_OLD) |
100 |
|
{ |
101 |
2 |
d_decisionEngine.reset(new DecisionEngineOld(satContext, userContext, rm)); |
102 |
|
} |
103 |
|
else |
104 |
|
{ |
105 |
2178 |
d_decisionEngine.reset(new decision::DecisionEngineEmpty(satContext, rm)); |
106 |
|
} |
107 |
|
|
108 |
9908 |
d_satSolver = SatSolverFactory::createCDCLTMinisat(smtStatisticsRegistry()); |
109 |
|
|
110 |
|
// CNF stream and theory proxy required pointers to each other, make the |
111 |
|
// theory proxy first |
112 |
9908 |
d_theoryProxy = new TheoryProxy(this, |
113 |
|
d_theoryEngine, |
114 |
9908 |
d_decisionEngine.get(), |
115 |
9908 |
d_skdm.get(), |
116 |
|
satContext, |
117 |
|
userContext, |
118 |
9908 |
pnm); |
119 |
29724 |
d_cnfStream = new CnfStream(d_satSolver, |
120 |
9908 |
d_theoryProxy, |
121 |
|
userContext, |
122 |
9908 |
&d_outMgr, |
123 |
|
rm, |
124 |
|
FormulaLitPolicy::TRACK, |
125 |
19816 |
"prop"); |
126 |
|
|
127 |
|
// connect theory proxy |
128 |
9908 |
d_theoryProxy->finishInit(d_cnfStream); |
129 |
|
// connect SAT solver |
130 |
39632 |
d_satSolver->initialize( |
131 |
9908 |
d_env.getContext(), |
132 |
|
d_theoryProxy, |
133 |
9908 |
d_env.getUserContext(), |
134 |
9908 |
options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS |
135 |
|
? pnm |
136 |
9908 |
: nullptr); |
137 |
|
|
138 |
9908 |
d_decisionEngine->finishInit(d_satSolver, d_cnfStream); |
139 |
9908 |
if (pnm && options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS) |
140 |
|
{ |
141 |
2498 |
d_pfCnfStream.reset(new ProofCnfStream( |
142 |
|
userContext, |
143 |
1249 |
*d_cnfStream, |
144 |
1249 |
static_cast<MinisatSatSolver*>(d_satSolver)->getProofManager(), |
145 |
2498 |
pnm)); |
146 |
2498 |
d_ppm.reset( |
147 |
1249 |
new PropPfManager(userContext, pnm, d_satSolver, d_pfCnfStream.get())); |
148 |
|
} |
149 |
9908 |
} |
150 |
|
|
151 |
9908 |
void PropEngine::finishInit() |
152 |
|
{ |
153 |
9908 |
NodeManager* nm = NodeManager::currentNM(); |
154 |
9908 |
d_cnfStream->convertAndAssert(nm->mkConst(true), false, false); |
155 |
|
// this is necessary because if True is later asserted to the prop engine the |
156 |
|
// CNF stream will ignore it since the SAT solver already had it registered, |
157 |
|
// thus not having True as an assumption for the SAT proof. To solve this |
158 |
|
// issue we track it directly here |
159 |
9908 |
if (isProofEnabled()) |
160 |
|
{ |
161 |
1249 |
static_cast<MinisatSatSolver*>(d_satSolver) |
162 |
|
->getProofManager() |
163 |
1249 |
->registerSatAssumptions({nm->mkConst(true)}); |
164 |
|
} |
165 |
9908 |
d_cnfStream->convertAndAssert(nm->mkConst(false).notNode(), false, false); |
166 |
9908 |
} |
167 |
|
|
168 |
19816 |
PropEngine::~PropEngine() { |
169 |
9908 |
Debug("prop") << "Destructing the PropEngine" << std::endl; |
170 |
9908 |
d_decisionEngine.reset(nullptr); |
171 |
9908 |
delete d_cnfStream; |
172 |
9908 |
delete d_satSolver; |
173 |
9908 |
delete d_theoryProxy; |
174 |
9908 |
} |
175 |
|
|
176 |
106400 |
TrustNode PropEngine::preprocess(TNode node, |
177 |
|
std::vector<TrustNode>& newLemmas, |
178 |
|
std::vector<Node>& newSkolems) |
179 |
|
{ |
180 |
106400 |
return d_theoryProxy->preprocess(node, newLemmas, newSkolems); |
181 |
|
} |
182 |
|
|
183 |
4 |
TrustNode PropEngine::removeItes(TNode node, |
184 |
|
std::vector<TrustNode>& newLemmas, |
185 |
|
std::vector<Node>& newSkolems) |
186 |
|
{ |
187 |
4 |
return d_theoryProxy->removeItes(node, newLemmas, newSkolems); |
188 |
|
} |
189 |
|
|
190 |
13728 |
void PropEngine::assertInputFormulas( |
191 |
|
const std::vector<Node>& assertions, |
192 |
|
std::unordered_map<size_t, Node>& skolemMap) |
193 |
|
{ |
194 |
13728 |
Assert(!d_inCheckSat) << "Sat solver in solve()!"; |
195 |
|
// notify the theory engine of preprocessed assertions |
196 |
13728 |
d_theoryEngine->notifyPreprocessedAssertions(assertions); |
197 |
|
// Now, notify the theory proxy of the assertions and skolem definitions. |
198 |
|
// Notice we do this before asserting the formulas to the CNF stream below, |
199 |
|
// since (preregistration) lemmas may occur during calls to assertInternal. |
200 |
|
// These lemmas we want to be notified about after the theory proxy has |
201 |
|
// been notified about all input assertions. |
202 |
13728 |
std::unordered_map<size_t, Node>::iterator it; |
203 |
139073 |
for (size_t i = 0, asize = assertions.size(); i < asize; i++) |
204 |
|
{ |
205 |
|
// is the assertion a skolem definition? |
206 |
125345 |
it = skolemMap.find(i); |
207 |
250690 |
Node skolem; |
208 |
125345 |
if (it != skolemMap.end()) |
209 |
|
{ |
210 |
19607 |
skolem = it->second; |
211 |
|
} |
212 |
125345 |
d_theoryProxy->notifyAssertion(assertions[i], skolem); |
213 |
|
} |
214 |
139063 |
for (const Node& node : assertions) |
215 |
|
{ |
216 |
125339 |
Debug("prop") << "assertFormula(" << node << ")" << std::endl; |
217 |
125343 |
assertInternal(node, false, false, true); |
218 |
|
} |
219 |
13724 |
} |
220 |
|
|
221 |
445043 |
void PropEngine::assertLemma(TrustNode tlemma, theory::LemmaProperty p) |
222 |
|
{ |
223 |
445043 |
bool removable = isLemmaPropertyRemovable(p); |
224 |
|
|
225 |
|
// call preprocessor |
226 |
890086 |
std::vector<TrustNode> ppLemmas; |
227 |
890086 |
std::vector<Node> ppSkolems; |
228 |
|
TrustNode tplemma = |
229 |
890086 |
d_theoryProxy->preprocessLemma(tlemma, ppLemmas, ppSkolems); |
230 |
|
|
231 |
445041 |
Assert(ppSkolems.size() == ppLemmas.size()); |
232 |
|
|
233 |
|
// do final checks on the lemmas we are about to send |
234 |
445041 |
if (isProofEnabled() && options::proofEagerChecking()) |
235 |
|
{ |
236 |
|
Assert(tplemma.getGenerator() != nullptr); |
237 |
|
// ensure closed, make the proof node eagerly here to debug |
238 |
|
tplemma.debugCheckClosed("te-proof-debug", "TheoryEngine::lemma"); |
239 |
|
for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i) |
240 |
|
{ |
241 |
|
Assert(ppLemmas[i].getGenerator() != nullptr); |
242 |
|
ppLemmas[i].debugCheckClosed("te-proof-debug", "TheoryEngine::lemma_new"); |
243 |
|
} |
244 |
|
} |
245 |
|
|
246 |
445041 |
if (Trace.isOn("te-lemma")) |
247 |
|
{ |
248 |
|
Trace("te-lemma") << "Lemma, output: " << tplemma.getProven() << std::endl; |
249 |
|
for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i) |
250 |
|
{ |
251 |
|
Trace("te-lemma") << "Lemma, new lemma: " << ppLemmas[i].getProven() |
252 |
|
<< " (skolem is " << ppSkolems[i] << ")" << std::endl; |
253 |
|
} |
254 |
|
} |
255 |
|
|
256 |
|
// now, assert the lemmas |
257 |
445041 |
assertLemmasInternal(tplemma, ppLemmas, ppSkolems, removable); |
258 |
445041 |
} |
259 |
|
|
260 |
455332 |
void PropEngine::assertTrustedLemmaInternal(TrustNode trn, bool removable) |
261 |
|
{ |
262 |
910664 |
Node node = trn.getNode(); |
263 |
455332 |
Debug("prop::lemmas") << "assertLemma(" << node << ")" << std::endl; |
264 |
455332 |
bool negated = trn.getKind() == TrustNodeKind::CONFLICT; |
265 |
455332 |
Assert( |
266 |
|
!isProofEnabled() || trn.getGenerator() != nullptr |
267 |
|
|| options::unsatCores() |
268 |
|
|| (options::unsatCores() |
269 |
|
&& options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF)); |
270 |
455332 |
assertInternal(trn.getNode(), negated, removable, false, trn.getGenerator()); |
271 |
455332 |
} |
272 |
|
|
273 |
580671 |
void PropEngine::assertInternal( |
274 |
|
TNode node, bool negated, bool removable, bool input, ProofGenerator* pg) |
275 |
|
{ |
276 |
|
// Assert as (possibly) removable |
277 |
580671 |
if (options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS) |
278 |
|
{ |
279 |
171509 |
if (input) |
280 |
|
{ |
281 |
33483 |
d_cnfStream->ensureLiteral(node); |
282 |
33483 |
if (negated) |
283 |
|
{ |
284 |
|
d_assumptions.push_back(node.notNode()); |
285 |
|
} |
286 |
|
else |
287 |
|
{ |
288 |
33483 |
d_assumptions.push_back(node); |
289 |
|
} |
290 |
|
} |
291 |
|
else |
292 |
|
{ |
293 |
138026 |
d_cnfStream->convertAndAssert(node, removable, negated, input); |
294 |
|
} |
295 |
|
} |
296 |
409162 |
else if (isProofEnabled()) |
297 |
|
{ |
298 |
93644 |
d_pfCnfStream->convertAndAssert(node, negated, removable, pg); |
299 |
|
// if input, register the assertion in the proof manager |
300 |
93644 |
if (input) |
301 |
|
{ |
302 |
20433 |
d_ppm->registerAssertion(node); |
303 |
|
} |
304 |
|
} |
305 |
|
else |
306 |
|
{ |
307 |
315522 |
d_cnfStream->convertAndAssert(node, removable, negated, input); |
308 |
|
} |
309 |
580667 |
} |
310 |
|
|
311 |
641983 |
void PropEngine::assertLemmasInternal(TrustNode trn, |
312 |
|
const std::vector<TrustNode>& ppLemmas, |
313 |
|
const std::vector<Node>& ppSkolems, |
314 |
|
bool removable) |
315 |
|
{ |
316 |
641983 |
if (!trn.isNull()) |
317 |
|
{ |
318 |
445041 |
assertTrustedLemmaInternal(trn, removable); |
319 |
|
} |
320 |
652274 |
for (const TrustNode& tnl : ppLemmas) |
321 |
|
{ |
322 |
10291 |
assertTrustedLemmaInternal(tnl, removable); |
323 |
|
} |
324 |
|
// assert to decision engine |
325 |
641983 |
if (!removable) |
326 |
|
{ |
327 |
|
// also add to the decision engine, where notice we don't need proofs |
328 |
526665 |
if (!trn.isNull()) |
329 |
|
{ |
330 |
|
// notify the theory proxy of the lemma |
331 |
329723 |
d_theoryProxy->notifyAssertion(trn.getProven()); |
332 |
|
} |
333 |
526665 |
Assert(ppSkolems.size() == ppLemmas.size()); |
334 |
536956 |
for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i) |
335 |
|
{ |
336 |
20582 |
Node lem = ppLemmas[i].getProven(); |
337 |
10291 |
d_theoryProxy->notifyAssertion(ppLemmas[i].getProven(), ppSkolems[i]); |
338 |
|
} |
339 |
|
} |
340 |
641983 |
} |
341 |
|
|
342 |
66319 |
void PropEngine::requirePhase(TNode n, bool phase) { |
343 |
66319 |
Debug("prop") << "requirePhase(" << n << ", " << phase << ")" << std::endl; |
344 |
|
|
345 |
66319 |
Assert(n.getType().isBoolean()); |
346 |
66319 |
SatLiteral lit = d_cnfStream->getLiteral(n); |
347 |
66319 |
d_satSolver->requirePhase(phase ? lit : ~lit); |
348 |
66319 |
} |
349 |
|
|
350 |
176861 |
bool PropEngine::isDecision(Node lit) const { |
351 |
176861 |
Assert(isSatLiteral(lit)); |
352 |
176861 |
return d_satSolver->isDecision(d_cnfStream->getLiteral(lit).getSatVariable()); |
353 |
|
} |
354 |
|
|
355 |
16 |
int32_t PropEngine::getDecisionLevel(Node lit) const |
356 |
|
{ |
357 |
16 |
Assert(isSatLiteral(lit)); |
358 |
32 |
return d_satSolver->getDecisionLevel( |
359 |
32 |
d_cnfStream->getLiteral(lit).getSatVariable()); |
360 |
|
} |
361 |
|
|
362 |
8 |
int32_t PropEngine::getIntroLevel(Node lit) const |
363 |
|
{ |
364 |
8 |
Assert(isSatLiteral(lit)); |
365 |
16 |
return d_satSolver->getIntroLevel( |
366 |
16 |
d_cnfStream->getLiteral(lit).getSatVariable()); |
367 |
|
} |
368 |
|
|
369 |
|
void PropEngine::printSatisfyingAssignment(){ |
370 |
|
const CnfStream::NodeToLiteralMap& transCache = |
371 |
|
d_cnfStream->getTranslationCache(); |
372 |
|
Debug("prop-value") << "Literal | Value | Expr" << std::endl |
373 |
|
<< "----------------------------------------" |
374 |
|
<< "-----------------" << std::endl; |
375 |
|
for(CnfStream::NodeToLiteralMap::const_iterator i = transCache.begin(), |
376 |
|
end = transCache.end(); |
377 |
|
i != end; |
378 |
|
++i) { |
379 |
|
std::pair<Node, SatLiteral> curr = *i; |
380 |
|
SatLiteral l = curr.second; |
381 |
|
if(!l.isNegated()) { |
382 |
|
Node n = curr.first; |
383 |
|
SatValue value = d_satSolver->modelValue(l); |
384 |
|
Debug("prop-value") << "'" << l << "' " << value << " " << n << std::endl; |
385 |
|
} |
386 |
|
} |
387 |
|
} |
388 |
|
|
389 |
15192 |
Result PropEngine::checkSat() { |
390 |
15192 |
Assert(!d_inCheckSat) << "Sat solver in solve()!"; |
391 |
15192 |
Debug("prop") << "PropEngine::checkSat()" << std::endl; |
392 |
|
|
393 |
|
// Mark that we are in the checkSat |
394 |
30384 |
ScopedBool scopedBool(d_inCheckSat); |
395 |
15192 |
d_inCheckSat = true; |
396 |
|
|
397 |
|
// TODO This currently ignores conflicts (a dangerous practice). |
398 |
15192 |
d_decisionEngine->presolve(); |
399 |
15192 |
d_theoryEngine->presolve(); |
400 |
|
|
401 |
30384 |
if(options::preprocessOnly()) { |
402 |
3 |
return Result(Result::SAT_UNKNOWN, Result::REQUIRES_FULL_CHECK); |
403 |
|
} |
404 |
|
|
405 |
|
// Reset the interrupted flag |
406 |
15189 |
d_interrupted = false; |
407 |
|
|
408 |
|
// Check the problem |
409 |
|
SatValue result; |
410 |
15189 |
if (d_assumptions.size() == 0) |
411 |
|
{ |
412 |
11562 |
result = d_satSolver->solve(); |
413 |
|
} |
414 |
|
else |
415 |
|
{ |
416 |
7254 |
std::vector<SatLiteral> assumptions; |
417 |
51927 |
for (const Node& node : d_assumptions) |
418 |
|
{ |
419 |
48300 |
assumptions.push_back(d_cnfStream->getLiteral(node)); |
420 |
|
} |
421 |
3627 |
result = d_satSolver->solve(assumptions); |
422 |
|
} |
423 |
|
|
424 |
15173 |
if( result == SAT_VALUE_UNKNOWN ) { |
425 |
|
ResourceManager* rm = d_env.getResourceManager(); |
426 |
|
Result::UnknownExplanation why = Result::INTERRUPTED; |
427 |
|
if (rm->outOfTime()) |
428 |
|
{ |
429 |
|
why = Result::TIMEOUT; |
430 |
|
} |
431 |
|
if (rm->outOfResources()) |
432 |
|
{ |
433 |
|
why = Result::RESOURCEOUT; |
434 |
|
} |
435 |
|
return Result(Result::SAT_UNKNOWN, why); |
436 |
|
} |
437 |
|
|
438 |
15173 |
if( result == SAT_VALUE_TRUE && Debug.isOn("prop") ) { |
439 |
|
printSatisfyingAssignment(); |
440 |
|
} |
441 |
|
|
442 |
15173 |
Debug("prop") << "PropEngine::checkSat() => " << result << std::endl; |
443 |
15173 |
if(result == SAT_VALUE_TRUE && d_theoryEngine->isIncomplete()) { |
444 |
107 |
return Result(Result::SAT_UNKNOWN, Result::INCOMPLETE); |
445 |
|
} |
446 |
15066 |
return Result(result == SAT_VALUE_TRUE ? Result::SAT : Result::UNSAT); |
447 |
|
} |
448 |
|
|
449 |
35076 |
Node PropEngine::getValue(TNode node) const |
450 |
|
{ |
451 |
35076 |
Assert(node.getType().isBoolean()); |
452 |
35076 |
Assert(d_cnfStream->hasLiteral(node)); |
453 |
|
|
454 |
35076 |
SatLiteral lit = d_cnfStream->getLiteral(node); |
455 |
|
|
456 |
35076 |
SatValue v = d_satSolver->value(lit); |
457 |
35076 |
if (v == SAT_VALUE_TRUE) |
458 |
|
{ |
459 |
35060 |
return NodeManager::currentNM()->mkConst(true); |
460 |
|
} |
461 |
16 |
else if (v == SAT_VALUE_FALSE) |
462 |
|
{ |
463 |
16 |
return NodeManager::currentNM()->mkConst(false); |
464 |
|
} |
465 |
|
else |
466 |
|
{ |
467 |
|
Assert(v == SAT_VALUE_UNKNOWN); |
468 |
|
return Node::null(); |
469 |
|
} |
470 |
|
} |
471 |
|
|
472 |
23513324 |
bool PropEngine::isSatLiteral(TNode node) const |
473 |
|
{ |
474 |
23513324 |
return d_cnfStream->hasLiteral(node); |
475 |
|
} |
476 |
|
|
477 |
9029262 |
bool PropEngine::hasValue(TNode node, bool& value) const |
478 |
|
{ |
479 |
9029262 |
Assert(node.getType().isBoolean()); |
480 |
9029262 |
Assert(d_cnfStream->hasLiteral(node)) << node; |
481 |
|
|
482 |
9029262 |
SatLiteral lit = d_cnfStream->getLiteral(node); |
483 |
|
|
484 |
9029262 |
SatValue v = d_satSolver->value(lit); |
485 |
9029262 |
if (v == SAT_VALUE_TRUE) |
486 |
|
{ |
487 |
5786907 |
value = true; |
488 |
5786907 |
return true; |
489 |
|
} |
490 |
3242355 |
else if (v == SAT_VALUE_FALSE) |
491 |
|
{ |
492 |
180635 |
value = false; |
493 |
180635 |
return true; |
494 |
|
} |
495 |
|
else |
496 |
|
{ |
497 |
3061720 |
Assert(v == SAT_VALUE_UNKNOWN); |
498 |
3061720 |
return false; |
499 |
|
} |
500 |
|
} |
501 |
|
|
502 |
16515 |
void PropEngine::getBooleanVariables(std::vector<TNode>& outputVariables) const |
503 |
|
{ |
504 |
16515 |
d_cnfStream->getBooleanVariables(outputVariables); |
505 |
16515 |
} |
506 |
|
|
507 |
192673 |
Node PropEngine::ensureLiteral(TNode n) |
508 |
|
{ |
509 |
|
// must preprocess |
510 |
192673 |
Node preprocessed = getPreprocessedTerm(n); |
511 |
385346 |
Trace("ensureLiteral") << "ensureLiteral preprocessed: " << preprocessed |
512 |
192673 |
<< std::endl; |
513 |
192673 |
if (isProofEnabled()) |
514 |
|
{ |
515 |
23788 |
d_pfCnfStream->ensureLiteral(preprocessed); |
516 |
|
} |
517 |
|
else |
518 |
|
{ |
519 |
168885 |
d_cnfStream->ensureLiteral(preprocessed); |
520 |
|
} |
521 |
192673 |
return preprocessed; |
522 |
|
} |
523 |
|
|
524 |
196942 |
Node PropEngine::getPreprocessedTerm(TNode n) |
525 |
|
{ |
526 |
|
// must preprocess |
527 |
393884 |
std::vector<TrustNode> newLemmas; |
528 |
393884 |
std::vector<Node> newSkolems; |
529 |
393884 |
TrustNode tpn = d_theoryProxy->preprocess(n, newLemmas, newSkolems); |
530 |
|
// send lemmas corresponding to the skolems introduced by preprocessing n |
531 |
393884 |
TrustNode trnNull; |
532 |
196942 |
assertLemmasInternal(trnNull, newLemmas, newSkolems, false); |
533 |
393884 |
return tpn.isNull() ? Node(n) : tpn.getNode(); |
534 |
|
} |
535 |
|
|
536 |
1611 |
Node PropEngine::getPreprocessedTerm(TNode n, |
537 |
|
std::vector<Node>& skAsserts, |
538 |
|
std::vector<Node>& sks) |
539 |
|
{ |
540 |
|
// get the preprocessed form of the term |
541 |
1611 |
Node pn = getPreprocessedTerm(n); |
542 |
|
// initialize the set of skolems and assertions to process |
543 |
3222 |
std::vector<Node> toProcessAsserts; |
544 |
3222 |
std::vector<Node> toProcess; |
545 |
1611 |
d_theoryProxy->getSkolems(pn, toProcessAsserts, toProcess); |
546 |
1611 |
size_t index = 0; |
547 |
|
// until fixed point is reached |
548 |
6427 |
while (index < toProcess.size()) |
549 |
|
{ |
550 |
3531 |
Node ka = toProcessAsserts[index]; |
551 |
3531 |
Node k = toProcess[index]; |
552 |
2408 |
index++; |
553 |
2408 |
if (std::find(sks.begin(), sks.end(), k) != sks.end()) |
554 |
|
{ |
555 |
|
// already added the skolem to the list |
556 |
1285 |
continue; |
557 |
|
} |
558 |
|
// must preprocess lemmas as well |
559 |
2246 |
Node kap = getPreprocessedTerm(ka); |
560 |
1123 |
skAsserts.push_back(kap); |
561 |
1123 |
sks.push_back(k); |
562 |
|
// get the skolems in the preprocessed form of the lemma ka |
563 |
1123 |
d_theoryProxy->getSkolems(kap, toProcessAsserts, toProcess); |
564 |
|
} |
565 |
|
// return the preprocessed term |
566 |
3222 |
return pn; |
567 |
|
} |
568 |
|
|
569 |
4869 |
void PropEngine::push() |
570 |
|
{ |
571 |
4869 |
Assert(!d_inCheckSat) << "Sat solver in solve()!"; |
572 |
4869 |
d_satSolver->push(); |
573 |
4869 |
Debug("prop") << "push()" << std::endl; |
574 |
4869 |
} |
575 |
|
|
576 |
4869 |
void PropEngine::pop() |
577 |
|
{ |
578 |
4869 |
Assert(!d_inCheckSat) << "Sat solver in solve()!"; |
579 |
4869 |
d_satSolver->pop(); |
580 |
4869 |
Debug("prop") << "pop()" << std::endl; |
581 |
4869 |
} |
582 |
|
|
583 |
15176 |
void PropEngine::resetTrail() |
584 |
|
{ |
585 |
15176 |
d_satSolver->resetTrail(); |
586 |
15176 |
Debug("prop") << "resetTrail()" << std::endl; |
587 |
15176 |
} |
588 |
|
|
589 |
18865 |
unsigned PropEngine::getAssertionLevel() const |
590 |
|
{ |
591 |
18865 |
return d_satSolver->getAssertionLevel(); |
592 |
|
} |
593 |
|
|
594 |
|
bool PropEngine::isRunning() const { return d_inCheckSat; } |
595 |
|
void PropEngine::interrupt() |
596 |
|
{ |
597 |
|
if (!d_inCheckSat) |
598 |
|
{ |
599 |
|
return; |
600 |
|
} |
601 |
|
|
602 |
|
d_interrupted = true; |
603 |
|
d_satSolver->interrupt(); |
604 |
|
Debug("prop") << "interrupt()" << std::endl; |
605 |
|
} |
606 |
|
|
607 |
2738 |
void PropEngine::spendResource(Resource r) |
608 |
|
{ |
609 |
2738 |
d_env.getResourceManager()->spendResource(r); |
610 |
2738 |
} |
611 |
|
|
612 |
|
bool PropEngine::properExplanation(TNode node, TNode expl) const |
613 |
|
{ |
614 |
|
if (!d_cnfStream->hasLiteral(node)) |
615 |
|
{ |
616 |
|
Trace("properExplanation") |
617 |
|
<< "properExplanation(): Failing because node " |
618 |
|
<< "being explained doesn't have a SAT literal ?!" << std::endl |
619 |
|
<< "properExplanation(): The node is: " << node << std::endl; |
620 |
|
return false; |
621 |
|
} |
622 |
|
|
623 |
|
SatLiteral nodeLit = d_cnfStream->getLiteral(node); |
624 |
|
|
625 |
|
for (TNode::kinded_iterator i = expl.begin(kind::AND), |
626 |
|
i_end = expl.end(kind::AND); |
627 |
|
i != i_end; |
628 |
|
++i) |
629 |
|
{ |
630 |
|
if (!d_cnfStream->hasLiteral(*i)) |
631 |
|
{ |
632 |
|
Trace("properExplanation") |
633 |
|
<< "properExplanation(): Failing because one of explanation " |
634 |
|
<< "nodes doesn't have a SAT literal" << std::endl |
635 |
|
<< "properExplanation(): The explanation node is: " << *i |
636 |
|
<< std::endl; |
637 |
|
return false; |
638 |
|
} |
639 |
|
|
640 |
|
SatLiteral iLit = d_cnfStream->getLiteral(*i); |
641 |
|
|
642 |
|
if (iLit == nodeLit) |
643 |
|
{ |
644 |
|
Trace("properExplanation") |
645 |
|
<< "properExplanation(): Failing because the node" << std::endl |
646 |
|
<< "properExplanation(): " << node << std::endl |
647 |
|
<< "properExplanation(): cannot be made to explain itself!" |
648 |
|
<< std::endl; |
649 |
|
return false; |
650 |
|
} |
651 |
|
|
652 |
|
if (!d_satSolver->properExplanation(nodeLit, iLit)) |
653 |
|
{ |
654 |
|
Trace("properExplanation") |
655 |
|
<< "properExplanation(): SAT solver told us that node" << std::endl |
656 |
|
<< "properExplanation(): " << *i << std::endl |
657 |
|
<< "properExplanation(): is not part of a proper explanation node for" |
658 |
|
<< std::endl |
659 |
|
<< "properExplanation(): " << node << std::endl |
660 |
|
<< "properExplanation(): Perhaps it one of the two isn't assigned or " |
661 |
|
"the explanation" |
662 |
|
<< std::endl |
663 |
|
<< "properExplanation(): node wasn't propagated before the node " |
664 |
|
"being explained" |
665 |
|
<< std::endl; |
666 |
|
return false; |
667 |
|
} |
668 |
|
} |
669 |
|
|
670 |
|
return true; |
671 |
|
} |
672 |
|
|
673 |
|
void PropEngine::checkProof(context::CDList<Node>* assertions) |
674 |
|
{ |
675 |
|
if (!d_pnm) |
676 |
|
{ |
677 |
|
return; |
678 |
|
} |
679 |
|
return d_ppm->checkProof(assertions); |
680 |
|
} |
681 |
|
|
682 |
18235 |
ProofCnfStream* PropEngine::getProofCnfStream() { return d_pfCnfStream.get(); } |
683 |
|
|
684 |
2799 |
std::shared_ptr<ProofNode> PropEngine::getProof() |
685 |
|
{ |
686 |
2799 |
if (!d_pnm) |
687 |
|
{ |
688 |
|
return nullptr; |
689 |
|
} |
690 |
2799 |
return d_ppm->getProof(); |
691 |
|
} |
692 |
|
|
693 |
1512116 |
bool PropEngine::isProofEnabled() const { return d_pfCnfStream != nullptr; } |
694 |
|
|
695 |
1369 |
void PropEngine::getUnsatCore(std::vector<Node>& core) |
696 |
|
{ |
697 |
1369 |
Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS); |
698 |
2738 |
std::vector<SatLiteral> unsat_assumptions; |
699 |
1369 |
d_satSolver->getUnsatAssumptions(unsat_assumptions); |
700 |
8106 |
for (const SatLiteral& lit : unsat_assumptions) |
701 |
|
{ |
702 |
6737 |
core.push_back(d_cnfStream->getNode(lit)); |
703 |
|
} |
704 |
1369 |
} |
705 |
|
|
706 |
1369 |
std::shared_ptr<ProofNode> PropEngine::getRefutation() |
707 |
|
{ |
708 |
1369 |
Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS); |
709 |
2738 |
std::vector<Node> core; |
710 |
1369 |
getUnsatCore(core); |
711 |
2738 |
CDProof cdp(d_pnm); |
712 |
2738 |
Node fnode = NodeManager::currentNM()->mkConst(false); |
713 |
1369 |
cdp.addStep(fnode, PfRule::SAT_REFUTATION, core, {}); |
714 |
2738 |
return cdp.getProofFor(fnode); |
715 |
|
} |
716 |
|
|
717 |
|
} // namespace prop |
718 |
29286 |
} // namespace cvc5 |