dcfc526eca3fbb9dd8799be6a1b9d1274103c29c
[cvc5.git] / src / smt / smt_engine.cpp
1 /********************* */
2 /*! \file smt_engine.cpp
3 ** \verbatim
4 ** Original author: Morgan Deters
5 ** Major contributors: Clark Barrett
6 ** Minor contributors (to current version): Christopher L. Conway, Tianyi Liang, Martin Brain <>, Kshitij Bansal, Liana Hadarean, Dejan Jovanovic, Tim King, Andrew Reynolds
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2014 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
11 **
12 ** \brief The main entry point into the CVC4 library's SMT interface
13 **
14 ** The main entry point into the CVC4 library's SMT interface.
15 **/
16
17 #include <vector>
18 #include <string>
19 #include <iterator>
20 #include <utility>
21 #include <sstream>
22 #include <stack>
23 #include <cctype>
24 #include <algorithm>
25 #include <ext/hash_map>
26
27 #include "context/cdlist.h"
28 #include "context/cdhashset.h"
29 #include "context/context.h"
30 #include "decision/decision_engine.h"
31 #include "decision/decision_mode.h"
32 #include "decision/options.h"
33 #include "expr/command.h"
34 #include "expr/expr.h"
35 #include "expr/kind.h"
36 #include "expr/metakind.h"
37 #include "expr/node_builder.h"
38 #include "expr/node.h"
39 #include "expr/node_self_iterator.h"
40 #include "prop/prop_engine.h"
41 #include "proof/theory_proof.h"
42 #include "smt/modal_exception.h"
43 #include "smt/smt_engine.h"
44 #include "smt/smt_engine_scope.h"
45 #include "smt/model_postprocessor.h"
46 #include "smt/logic_request.h"
47 #include "theory/theory_engine.h"
48 #include "theory/bv/theory_bv_rewriter.h"
49 #include "proof/proof_manager.h"
50 #include "main/options.h"
51 #include "util/proof.h"
52 #include "proof/proof.h"
53 #include "proof/proof_manager.h"
54 #include "util/boolean_simplification.h"
55 #include "util/node_visitor.h"
56 #include "util/configuration.h"
57 #include "util/exception.h"
58 #include "util/nary_builder.h"
59 #include "smt/command_list.h"
60 #include "smt/boolean_terms.h"
61 #include "smt/options.h"
62 #include "options/option_exception.h"
63 #include "util/output.h"
64 #include "util/hash.h"
65 #include "theory/substitutions.h"
66 #include "theory/uf/options.h"
67 #include "theory/arith/options.h"
68 #include "theory/strings/options.h"
69 #include "theory/bv/options.h"
70 #include "theory/theory_traits.h"
71 #include "theory/logic_info.h"
72 #include "theory/options.h"
73 #include "theory/booleans/circuit_propagator.h"
74 #include "theory/booleans/boolean_term_conversion_mode.h"
75 #include "theory/booleans/options.h"
76 #include "util/ite_removal.h"
77 #include "theory/theory_model.h"
78 #include "printer/printer.h"
79 #include "prop/options.h"
80 #include "theory/arrays/options.h"
81 #include "util/sort_inference.h"
82 #include "theory/quantifiers/quant_conflict_find.h"
83 #include "theory/quantifiers/macros.h"
84 #include "theory/quantifiers/first_order_reasoning.h"
85 #include "theory/quantifiers/quantifiers_rewriter.h"
86 #include "theory/quantifiers/options.h"
87 #include "theory/datatypes/options.h"
88 #include "theory/strings/theory_strings_preprocess.h"
89 #include "printer/options.h"
90
91 #include "theory/arith/pseudoboolean_proc.h"
92 #include "theory/bv/bvintropow2.h"
93
94 using namespace std;
95 using namespace CVC4;
96 using namespace CVC4::smt;
97 using namespace CVC4::prop;
98 using namespace CVC4::context;
99 using namespace CVC4::theory;
100
101 namespace CVC4 {
102
103 namespace smt {
104
105 /** Useful for counting the number of recursive calls. */
106 class ScopeCounter {
107 private:
108 unsigned& d_depth;
109 public:
110 ScopeCounter(unsigned& d) : d_depth(d) {
111 ++d_depth;
112 }
113 ~ScopeCounter(){
114 --d_depth;
115 }
116 };
117
118 /**
119 * Representation of a defined function. We keep these around in
120 * SmtEngine to permit expanding definitions late (and lazily), to
121 * support getValue() over defined functions, to support user output
122 * in terms of defined functions, etc.
123 */
124 class DefinedFunction {
125 Node d_func;
126 vector<Node> d_formals;
127 Node d_formula;
128 public:
129 DefinedFunction() {}
130 DefinedFunction(Node func, vector<Node> formals, Node formula) :
131 d_func(func),
132 d_formals(formals),
133 d_formula(formula) {
134 }
135 Node getFunction() const { return d_func; }
136 vector<Node> getFormals() const { return d_formals; }
137 Node getFormula() const { return d_formula; }
138 };/* class DefinedFunction */
139
140 struct SmtEngineStatistics {
141 /** time spent in definition-expansion */
142 TimerStat d_definitionExpansionTime;
143 /** time spent in Boolean term rewriting */
144 TimerStat d_rewriteBooleanTermsTime;
145 /** time spent in non-clausal simplification */
146 TimerStat d_nonclausalSimplificationTime;
147 /** time spent in miplib pass */
148 TimerStat d_miplibPassTime;
149 /** number of assertions removed by miplib pass */
150 IntStat d_numMiplibAssertionsRemoved;
151 /** number of constant propagations found during nonclausal simp */
152 IntStat d_numConstantProps;
153 /** time spent in static learning */
154 TimerStat d_staticLearningTime;
155 /** time spent in simplifying ITEs */
156 TimerStat d_simpITETime;
157 /** time spent in simplifying ITEs */
158 TimerStat d_unconstrainedSimpTime;
159 /** time spent removing ITEs */
160 TimerStat d_iteRemovalTime;
161 /** time spent in theory preprocessing */
162 TimerStat d_theoryPreprocessTime;
163 /** time spent converting to CNF */
164 TimerStat d_cnfConversionTime;
165 /** Num of assertions before ite removal */
166 IntStat d_numAssertionsPre;
167 /** Num of assertions after ite removal */
168 IntStat d_numAssertionsPost;
169 /** time spent in checkModel() */
170 TimerStat d_checkModelTime;
171 /** time spent in checkProof() */
172 TimerStat d_checkProofTime;
173 /** time spent in PropEngine::checkSat() */
174 TimerStat d_solveTime;
175 /** time spent in pushing/popping */
176 TimerStat d_pushPopTime;
177 /** time spent in processAssertions() */
178 TimerStat d_processAssertionsTime;
179
180 /** Has something simplified to false? */
181 IntStat d_simplifiedToFalse;
182
183 SmtEngineStatistics() :
184 d_definitionExpansionTime("smt::SmtEngine::definitionExpansionTime"),
185 d_rewriteBooleanTermsTime("smt::SmtEngine::rewriteBooleanTermsTime"),
186 d_nonclausalSimplificationTime("smt::SmtEngine::nonclausalSimplificationTime"),
187 d_miplibPassTime("smt::SmtEngine::miplibPassTime"),
188 d_numMiplibAssertionsRemoved("smt::SmtEngine::numMiplibAssertionsRemoved", 0),
189 d_numConstantProps("smt::SmtEngine::numConstantProps", 0),
190 d_staticLearningTime("smt::SmtEngine::staticLearningTime"),
191 d_simpITETime("smt::SmtEngine::simpITETime"),
192 d_unconstrainedSimpTime("smt::SmtEngine::unconstrainedSimpTime"),
193 d_iteRemovalTime("smt::SmtEngine::iteRemovalTime"),
194 d_theoryPreprocessTime("smt::SmtEngine::theoryPreprocessTime"),
195 d_cnfConversionTime("smt::SmtEngine::cnfConversionTime"),
196 d_numAssertionsPre("smt::SmtEngine::numAssertionsPreITERemoval", 0),
197 d_numAssertionsPost("smt::SmtEngine::numAssertionsPostITERemoval", 0),
198 d_checkModelTime("smt::SmtEngine::checkModelTime"),
199 d_checkProofTime("smt::SmtEngine::checkProofTime"),
200 d_solveTime("smt::SmtEngine::solveTime"),
201 d_pushPopTime("smt::SmtEngine::pushPopTime"),
202 d_processAssertionsTime("smt::SmtEngine::processAssertionsTime"),
203 d_simplifiedToFalse("smt::SmtEngine::simplifiedToFalse", 0)
204 {
205
206 StatisticsRegistry::registerStat(&d_definitionExpansionTime);
207 StatisticsRegistry::registerStat(&d_rewriteBooleanTermsTime);
208 StatisticsRegistry::registerStat(&d_nonclausalSimplificationTime);
209 StatisticsRegistry::registerStat(&d_miplibPassTime);
210 StatisticsRegistry::registerStat(&d_numMiplibAssertionsRemoved);
211 StatisticsRegistry::registerStat(&d_numConstantProps);
212 StatisticsRegistry::registerStat(&d_staticLearningTime);
213 StatisticsRegistry::registerStat(&d_simpITETime);
214 StatisticsRegistry::registerStat(&d_unconstrainedSimpTime);
215 StatisticsRegistry::registerStat(&d_iteRemovalTime);
216 StatisticsRegistry::registerStat(&d_theoryPreprocessTime);
217 StatisticsRegistry::registerStat(&d_cnfConversionTime);
218 StatisticsRegistry::registerStat(&d_numAssertionsPre);
219 StatisticsRegistry::registerStat(&d_numAssertionsPost);
220 StatisticsRegistry::registerStat(&d_checkModelTime);
221 StatisticsRegistry::registerStat(&d_solveTime);
222 StatisticsRegistry::registerStat(&d_pushPopTime);
223 StatisticsRegistry::registerStat(&d_processAssertionsTime);
224 StatisticsRegistry::registerStat(&d_simplifiedToFalse);
225 }
226
227 ~SmtEngineStatistics() {
228 StatisticsRegistry::unregisterStat(&d_definitionExpansionTime);
229 StatisticsRegistry::unregisterStat(&d_rewriteBooleanTermsTime);
230 StatisticsRegistry::unregisterStat(&d_nonclausalSimplificationTime);
231 StatisticsRegistry::unregisterStat(&d_miplibPassTime);
232 StatisticsRegistry::unregisterStat(&d_numMiplibAssertionsRemoved);
233 StatisticsRegistry::unregisterStat(&d_numConstantProps);
234 StatisticsRegistry::unregisterStat(&d_staticLearningTime);
235 StatisticsRegistry::unregisterStat(&d_simpITETime);
236 StatisticsRegistry::unregisterStat(&d_unconstrainedSimpTime);
237 StatisticsRegistry::unregisterStat(&d_iteRemovalTime);
238 StatisticsRegistry::unregisterStat(&d_theoryPreprocessTime);
239 StatisticsRegistry::unregisterStat(&d_cnfConversionTime);
240 StatisticsRegistry::unregisterStat(&d_numAssertionsPre);
241 StatisticsRegistry::unregisterStat(&d_numAssertionsPost);
242 StatisticsRegistry::unregisterStat(&d_checkModelTime);
243 StatisticsRegistry::unregisterStat(&d_solveTime);
244 StatisticsRegistry::unregisterStat(&d_pushPopTime);
245 StatisticsRegistry::unregisterStat(&d_processAssertionsTime);
246 StatisticsRegistry::unregisterStat(&d_simplifiedToFalse);
247 }
248 };/* struct SmtEngineStatistics */
249
250 /**
251 * This is an inelegant solution, but for the present, it will work.
252 * The point of this is to separate the public and private portions of
253 * the SmtEngine class, so that smt_engine.h doesn't
254 * include "expr/node.h", which is a private CVC4 header (and can lead
255 * to linking errors due to the improper inlining of non-visible symbols
256 * into user code!).
257 *
258 * The "real" solution (that which is usually implemented) is to move
259 * ALL the implementation to SmtEnginePrivate and maintain a
260 * heap-allocated instance of it in SmtEngine. SmtEngine (the public
261 * one) becomes an "interface shell" which simply acts as a forwarder
262 * of method calls.
263 */
264 class SmtEnginePrivate : public NodeManagerListener {
265 SmtEngine& d_smt;
266
267 /** The assertions yet to be preprocessed */
268 vector<Node> d_assertionsToPreprocess;
269
270 /** Learned literals */
271 vector<Node> d_nonClausalLearnedLiterals;
272
273 /** Size of assertions array when preprocessing starts */
274 unsigned d_realAssertionsEnd;
275
276 /** The converter for Boolean terms -> BITVECTOR(1). */
277 BooleanTermConverter* d_booleanTermConverter;
278
279 /** A circuit propagator for non-clausal propositional deduction */
280 booleans::CircuitPropagator d_propagator;
281 bool d_propagatorNeedsFinish;
282 std::vector<Node> d_boolVars;
283
284 /** Assertions to push to sat */
285 vector<Node> d_assertionsToCheck;
286
287 /** Whether any assertions have been processed */
288 CDO<bool> d_assertionsProcessed;
289
290 /** Index for where to store substitutions */
291 CDO<unsigned> d_substitutionsIndex;
292
293 // Cached true value
294 Node d_true;
295
296 /**
297 * A context that never pushes/pops, for use by CD structures (like
298 * SubstitutionMaps) that should be "global".
299 */
300 context::Context d_fakeContext;
301
302 /**
303 * A map of AbsractValues to their actual constants. Only used if
304 * options::abstractValues() is on.
305 */
306 SubstitutionMap d_abstractValueMap;
307
308 /**
309 * A mapping of all abstract values (actual value |-> abstract) that
310 * we've handed out. This is necessary to ensure that we give the
311 * same AbstractValues for the same real constants. Only used if
312 * options::abstractValues() is on.
313 */
314 hash_map<Node, Node, NodeHashFunction> d_abstractValues;
315
316 /** Number of calls of simplify assertions active.
317 */
318 unsigned d_simplifyAssertionsDepth;
319
320 public:
321 /**
322 * Map from skolem variables to index in d_assertionsToCheck containing
323 * corresponding introduced Boolean ite
324 */
325 IteSkolemMap d_iteSkolemMap;
326
327 /** Instance of the ITE remover */
328 RemoveITE d_iteRemover;
329
330 private:
331
332 theory::arith::PseudoBooleanProcessor d_pbsProcessor;
333
334 /** The top level substitutions */
335 SubstitutionMap d_topLevelSubstitutions;
336
337 static const bool d_doConstantProp = true;
338
339 /**
340 * Runs the nonclausal solver and tries to solve all the assigned
341 * theory literals.
342 *
343 * Returns false if the formula simplifies to "false"
344 */
345 bool nonClausalSimplify();
346
347 /**
348 * Performs static learning on the assertions.
349 */
350 void staticLearning();
351
352 /**
353 * Remove ITEs from the assertions.
354 */
355 void removeITEs();
356
357 /**
358 * Helper function to fix up assertion list to restore invariants needed after ite removal
359 */
360 void collectSkolems(TNode n, set<TNode>& skolemSet, hash_map<Node, bool, NodeHashFunction>& cache);
361
362 /**
363 * Helper function to fix up assertion list to restore invariants needed after ite removal
364 */
365 bool checkForBadSkolems(TNode n, TNode skolem, hash_map<Node, bool, NodeHashFunction>& cache);
366
367 // Lift bit-vectors of size 1 to booleans
368 void bvToBool();
369
370 // Abstract common structure over small domains to UF
371 // return true if changes were made.
372 void bvAbstraction();
373
374 // Simplify ITE structure
375 bool simpITE();
376
377 // Simplify based on unconstrained values
378 void unconstrainedSimp(std::vector<Node>& assertions);
379
380 // Ensures the assertions asserted after before now
381 // effectively come before d_realAssertionsEnd
382 void compressBeforeRealAssertions(size_t before);
383
384 /**
385 * Any variable in an assertion that is declared as a subtype type
386 * (predicate subtype or integer subrange type) must be constrained
387 * to be in that type.
388 */
389 void constrainSubtypes(TNode n, std::vector<Node>& assertions)
390 throw();
391
392 // trace nodes back to their assertions using CircuitPropagator's BackEdgesMap
393 void traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions);
394 // remove conjuncts in toRemove from conjunction n; return # of removed conjuncts
395 size_t removeFromConjunction(Node& n, const std::hash_set<unsigned long>& toRemove);
396
397 // scrub miplib encodings
398 void doMiplibTrick();
399
400 /**
401 * Perform non-clausal simplification of a Node. This involves
402 * Theory implementations, but does NOT involve the SAT solver in
403 * any way.
404 *
405 * Returns false if the formula simplifies to "false"
406 */
407 bool simplifyAssertions() throw(TypeCheckingException, LogicException);
408
409 public:
410
411 SmtEnginePrivate(SmtEngine& smt) :
412 d_smt(smt),
413 d_assertionsToPreprocess(),
414 d_nonClausalLearnedLiterals(),
415 d_realAssertionsEnd(0),
416 d_booleanTermConverter(NULL),
417 d_propagator(d_nonClausalLearnedLiterals, true, true),
418 d_propagatorNeedsFinish(false),
419 d_assertionsToCheck(),
420 d_assertionsProcessed(smt.d_userContext, false),
421 d_substitutionsIndex(smt.d_userContext, 0),
422 d_fakeContext(),
423 d_abstractValueMap(&d_fakeContext),
424 d_abstractValues(),
425 d_simplifyAssertionsDepth(0),
426 d_iteSkolemMap(),
427 d_iteRemover(smt.d_userContext),
428 d_pbsProcessor(smt.d_userContext),
429 d_topLevelSubstitutions(smt.d_userContext)
430 {
431 d_smt.d_nodeManager->subscribeEvents(this);
432 d_true = NodeManager::currentNM()->mkConst(true);
433 }
434
435 ~SmtEnginePrivate() {
436 if(d_propagatorNeedsFinish) {
437 d_propagator.finish();
438 d_propagatorNeedsFinish = false;
439 }
440 if(d_booleanTermConverter != NULL) {
441 delete d_booleanTermConverter;
442 d_booleanTermConverter = NULL;
443 }
444 d_smt.d_nodeManager->unsubscribeEvents(this);
445 }
446
447 void nmNotifyNewSort(TypeNode tn, uint32_t flags) {
448 DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
449 0,
450 tn.toType());
451 if((flags & ExprManager::SORT_FLAG_PLACEHOLDER) == 0) {
452 d_smt.addToModelCommandAndDump(c, flags);
453 }
454 }
455
456 void nmNotifyNewSortConstructor(TypeNode tn) {
457 DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
458 tn.getAttribute(expr::SortArityAttr()),
459 tn.toType());
460 d_smt.addToModelCommandAndDump(c);
461 }
462
463 void nmNotifyNewDatatypes(const std::vector<DatatypeType>& dtts) {
464 DatatypeDeclarationCommand c(dtts);
465 d_smt.addToModelCommandAndDump(c);
466 }
467
468 void nmNotifyNewVar(TNode n, uint32_t flags) {
469 DeclareFunctionCommand c(n.getAttribute(expr::VarNameAttr()),
470 n.toExpr(),
471 n.getType().toType());
472 if((flags & ExprManager::VAR_FLAG_DEFINED) == 0) {
473 d_smt.addToModelCommandAndDump(c, flags);
474 }
475 if(n.getType().isBoolean() && !options::incrementalSolving()) {
476 d_boolVars.push_back(n);
477 }
478 }
479
480 void nmNotifyNewSkolem(TNode n, const std::string& comment, uint32_t flags) {
481 string id = n.getAttribute(expr::VarNameAttr());
482 DeclareFunctionCommand c(id,
483 n.toExpr(),
484 n.getType().toType());
485 if(Dump.isOn("skolems") && comment != "") {
486 Dump("skolems") << CommentCommand(id + " is " + comment);
487 }
488 if((flags & ExprManager::VAR_FLAG_DEFINED) == 0) {
489 d_smt.addToModelCommandAndDump(c, flags, false, "skolems");
490 }
491 if(n.getType().isBoolean() && !options::incrementalSolving()) {
492 d_boolVars.push_back(n);
493 }
494 }
495
496 Node applySubstitutions(TNode node) const {
497 return Rewriter::rewrite(d_topLevelSubstitutions.apply(node));
498 }
499
500 /**
501 * Process the assertions that have been asserted.
502 */
503 void processAssertions();
504
505 /**
506 * Process a user pop. Clears out the non-context-dependent stuff in this
507 * SmtEnginePrivate. Necessary to clear out our assertion vectors in case
508 * someone does a push-assert-pop without a check-sat.
509 */
510 void notifyPop() {
511 d_assertionsToPreprocess.clear();
512 d_nonClausalLearnedLiterals.clear();
513 d_assertionsToCheck.clear();
514 d_realAssertionsEnd = 0;
515 d_iteSkolemMap.clear();
516 }
517
518 /**
519 * Adds a formula to the current context. Action here depends on
520 * the SimplificationMode (in the current Options scope); the
521 * formula might be pushed out to the propositional layer
522 * immediately, or it might be simplified and kept, or it might not
523 * even be simplified.
524 */
525 void addFormula(TNode n)
526 throw(TypeCheckingException, LogicException);
527
528 /**
529 * Expand definitions in n.
530 */
531 Node expandDefinitions(TNode n, hash_map<Node, Node, NodeHashFunction>& cache, bool expandOnly = false)
532 throw(TypeCheckingException, LogicException);
533
534 /**
535 * Rewrite Boolean terms in a Node.
536 */
537 Node rewriteBooleanTerms(TNode n);
538
539 /**
540 * Simplify node "in" by expanding definitions and applying any
541 * substitutions learned from preprocessing.
542 */
543 Node simplify(TNode in) {
544 // Substitute out any abstract values in ex.
545 // Expand definitions.
546 hash_map<Node, Node, NodeHashFunction> cache;
547 Node n = expandDefinitions(in, cache).toExpr();
548 // Make sure we've done all preprocessing, etc.
549 Assert(d_assertionsToCheck.size() == 0 && d_assertionsToPreprocess.size() == 0);
550 return applySubstitutions(n).toExpr();
551 }
552
553 /**
554 * Substitute away all AbstractValues in a node.
555 */
556 Node substituteAbstractValues(TNode n) {
557 // We need to do this even if options::abstractValues() is off,
558 // since the setting might have changed after we already gave out
559 // some abstract values.
560 return d_abstractValueMap.apply(n);
561 }
562
563 /**
564 * Make a new (or return an existing) abstract value for a node.
565 * Can only use this if options::abstractValues() is on.
566 */
567 Node mkAbstractValue(TNode n) {
568 Assert(options::abstractValues());
569 Node& val = d_abstractValues[n];
570 if(val.isNull()) {
571 val = d_smt.d_nodeManager->mkAbstractValue(n.getType());
572 d_abstractValueMap.addSubstitution(val, n);
573 }
574 return val;
575 }
576
577 std::hash_map<Node, Node, NodeHashFunction> rewriteApplyToConstCache;
578 Node rewriteApplyToConst(TNode n) {
579 Trace("rewriteApplyToConst") << "rewriteApplyToConst :: " << n << std::endl;
580
581 if(n.getMetaKind() == kind::metakind::CONSTANT || n.getMetaKind() == kind::metakind::VARIABLE) {
582 return n;
583 }
584
585 if(rewriteApplyToConstCache.find(n) != rewriteApplyToConstCache.end()) {
586 Trace("rewriteApplyToConst") << "in cache :: " << rewriteApplyToConstCache[n] << std::endl;
587 return rewriteApplyToConstCache[n];
588 }
589 if(n.getKind() == kind::APPLY_UF) {
590 if(n.getNumChildren() == 1 && n[0].isConst() && n[0].getType().isInteger()) {
591 stringstream ss;
592 ss << n.getOperator() << "_";
593 if(n[0].getConst<Rational>() < 0) {
594 ss << "m" << -n[0].getConst<Rational>();
595 } else {
596 ss << n[0];
597 }
598 Node newvar = NodeManager::currentNM()->mkSkolem(ss.str(), n.getType(), "rewriteApplyToConst skolem", NodeManager::SKOLEM_EXACT_NAME);
599 rewriteApplyToConstCache[n] = newvar;
600 Trace("rewriteApplyToConst") << "made :: " << newvar << std::endl;
601 return newvar;
602 } else {
603 stringstream ss;
604 ss << "The rewrite-apply-to-const preprocessor is currently limited;\n"
605 << "it only works if all function symbols are unary and with Integer\n"
606 << "domain, and all applications are to integer values.\n"
607 << "Found application: " << n;
608 Unhandled(ss.str());
609 }
610 }
611
612 NodeBuilder<> builder(n.getKind());
613 if(n.getMetaKind() == kind::metakind::PARAMETERIZED) {
614 builder << n.getOperator();
615 }
616 for(unsigned i = 0; i < n.getNumChildren(); ++i) {
617 builder << rewriteApplyToConst(n[i]);
618 }
619 Node rewr = builder;
620 rewriteApplyToConstCache[n] = rewr;
621 Trace("rewriteApplyToConst") << "built :: " << rewr << std::endl;
622 return rewr;
623 }
624
625 };/* class SmtEnginePrivate */
626
627 }/* namespace CVC4::smt */
628
629 SmtEngine::SmtEngine(ExprManager* em) throw() :
630 d_context(em->getContext()),
631 d_userLevels(),
632 d_userContext(new UserContext()),
633 d_exprManager(em),
634 d_nodeManager(d_exprManager->getNodeManager()),
635 d_decisionEngine(NULL),
636 d_theoryEngine(NULL),
637 d_propEngine(NULL),
638 d_proofManager(NULL),
639 d_definedFunctions(NULL),
640 d_assertionList(NULL),
641 d_assignments(NULL),
642 d_modelGlobalCommands(),
643 d_modelCommands(NULL),
644 d_dumpCommands(),
645 d_logic(),
646 d_pendingPops(0),
647 d_fullyInited(false),
648 d_problemExtended(false),
649 d_queryMade(false),
650 d_needPostsolve(false),
651 d_earlyTheoryPP(true),
652 d_timeBudgetCumulative(0),
653 d_timeBudgetPerCall(0),
654 d_resourceBudgetCumulative(0),
655 d_resourceBudgetPerCall(0),
656 d_cumulativeTimeUsed(0),
657 d_cumulativeResourceUsed(0),
658 d_status(),
659 d_private(NULL),
660 d_statisticsRegistry(NULL),
661 d_stats(NULL) {
662
663 SmtScope smts(this);
664 d_private = new smt::SmtEnginePrivate(*this);
665 d_statisticsRegistry = new StatisticsRegistry();
666 d_stats = new SmtEngineStatistics();
667
668 PROOF( d_proofManager = new ProofManager(); );
669
670 // We have mutual dependency here, so we add the prop engine to the theory
671 // engine later (it is non-essential there)
672 d_theoryEngine = new TheoryEngine(d_context, d_userContext, d_private->d_iteRemover, const_cast<const LogicInfo&>(d_logic));
673
674 // Add the theories
675 for(TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
676 TheoryConstructor::addTheory(d_theoryEngine, id);
677 }
678
679 // global push/pop around everything, to ensure proper destruction
680 // of context-dependent data structures
681 d_userContext->push();
682 d_context->push();
683
684 d_definedFunctions = new(true) DefinedFunctionMap(d_userContext);
685 d_modelCommands = new(true) smt::CommandList(d_userContext);
686 }
687
688 void SmtEngine::finishInit() {
689 // ensure that our heuristics are properly set up
690 setDefaults();
691
692 d_decisionEngine = new DecisionEngine(d_context, d_userContext);
693 d_decisionEngine->init(); // enable appropriate strategies
694
695 d_propEngine = new PropEngine(d_theoryEngine, d_decisionEngine, d_context, d_userContext);
696
697 d_theoryEngine->setPropEngine(d_propEngine);
698 d_theoryEngine->setDecisionEngine(d_decisionEngine);
699 d_theoryEngine->finishInit();
700
701 // [MGD 10/20/2011] keep around in incremental mode, due to a
702 // cleanup ordering issue and Nodes/TNodes. If SAT is popped
703 // first, some user-context-dependent TNodes might still exist
704 // with rc == 0.
705 if(options::interactive() ||
706 options::incrementalSolving()) {
707 // In the case of incremental solving, we appear to need these to
708 // ensure the relevant Nodes remain live.
709 d_assertionList = new(true) AssertionList(d_userContext);
710 }
711
712 // dump out a set-logic command
713 if(Dump.isOn("benchmark")) {
714 // Dump("benchmark") << SetBenchmarkLogicCommand(logic.getLogicString());
715 LogicInfo everything;
716 everything.lock();
717 Dump("benchmark") << CommentCommand("CVC4 always dumps the most general, \"all-supported\" logic (below), as some internals might require the use of a logic more general than the input.")
718 << SetBenchmarkLogicCommand(everything.getLogicString());
719 }
720
721 // dump out any pending declaration commands
722 for(unsigned i = 0; i < d_dumpCommands.size(); ++i) {
723 Dump("declarations") << *d_dumpCommands[i];
724 delete d_dumpCommands[i];
725 }
726 d_dumpCommands.clear();
727
728 if(options::perCallResourceLimit() != 0) {
729 setResourceLimit(options::perCallResourceLimit(), false);
730 }
731 if(options::cumulativeResourceLimit() != 0) {
732 setResourceLimit(options::cumulativeResourceLimit(), true);
733 }
734 if(options::perCallMillisecondLimit() != 0) {
735 setTimeLimit(options::perCallMillisecondLimit(), false);
736 }
737 if(options::cumulativeMillisecondLimit() != 0) {
738 setTimeLimit(options::cumulativeMillisecondLimit(), true);
739 }
740
741 PROOF( ProofManager::currentPM()->setLogic(d_logic.getLogicString()); );
742 }
743
744 void SmtEngine::finalOptionsAreSet() {
745 if(d_fullyInited) {
746 return;
747 }
748
749 if(! d_logic.isLocked()) {
750 setLogicInternal();
751 }
752
753 // finish initialization, create the prop engine, etc.
754 finishInit();
755
756 AlwaysAssert( d_propEngine->getAssertionLevel() == 0,
757 "The PropEngine has pushed but the SmtEngine "
758 "hasn't finished initializing!" );
759
760 d_fullyInited = true;
761 Assert(d_logic.isLocked());
762
763 d_propEngine->assertFormula(NodeManager::currentNM()->mkConst<bool>(true));
764 d_propEngine->assertFormula(NodeManager::currentNM()->mkConst<bool>(false).notNode());
765 }
766
767 void SmtEngine::shutdown() {
768 doPendingPops();
769
770 while(options::incrementalSolving() && d_userContext->getLevel() > 1) {
771 internalPop(true);
772 }
773
774 // check to see if a postsolve() is pending
775 if(d_needPostsolve) {
776 d_theoryEngine->postsolve();
777 d_needPostsolve = false;
778 }
779
780 if(d_propEngine != NULL) {
781 d_propEngine->shutdown();
782 }
783 if(d_theoryEngine != NULL) {
784 d_theoryEngine->shutdown();
785 }
786 if(d_decisionEngine != NULL) {
787 d_decisionEngine->shutdown();
788 }
789 }
790
791 SmtEngine::~SmtEngine() throw() {
792 SmtScope smts(this);
793
794 try {
795 shutdown();
796
797 // global push/pop around everything, to ensure proper destruction
798 // of context-dependent data structures
799 d_context->popto(0);
800 d_userContext->popto(0);
801
802 if(d_assignments != NULL) {
803 d_assignments->deleteSelf();
804 }
805
806 if(d_assertionList != NULL) {
807 d_assertionList->deleteSelf();
808 }
809
810 for(unsigned i = 0; i < d_dumpCommands.size(); ++i) {
811 delete d_dumpCommands[i];
812 d_dumpCommands[i] = NULL;
813 }
814 d_dumpCommands.clear();
815
816 if(d_modelCommands != NULL) {
817 d_modelCommands->deleteSelf();
818 }
819
820 d_definedFunctions->deleteSelf();
821
822 delete d_theoryEngine;
823 d_theoryEngine = NULL;
824 delete d_propEngine;
825 d_propEngine = NULL;
826 delete d_decisionEngine;
827 d_decisionEngine = NULL;
828
829 delete d_stats;
830 d_stats = NULL;
831 delete d_statisticsRegistry;
832 d_statisticsRegistry = NULL;
833
834 delete d_private;
835 d_private = NULL;
836
837 delete d_userContext;
838 d_userContext = NULL;
839
840 } catch(Exception& e) {
841 Warning() << "CVC4 threw an exception during cleanup." << endl
842 << e << endl;
843 }
844 }
845
846 void SmtEngine::setLogic(const LogicInfo& logic) throw(ModalException) {
847 SmtScope smts(this);
848 if(d_fullyInited) {
849 throw ModalException("Cannot set logic in SmtEngine after the engine has finished initializing");
850 }
851 d_logic = logic;
852 setLogicInternal();
853 }
854
855 void SmtEngine::setLogic(const std::string& s) throw(ModalException, LogicException) {
856 SmtScope smts(this);
857 try {
858 setLogic(LogicInfo(s));
859 } catch(IllegalArgumentException& e) {
860 throw LogicException(e.what());
861 }
862 }
863
864 void SmtEngine::setLogic(const char* logic) throw(ModalException, LogicException) {
865 setLogic(string(logic));
866 }
867
868 LogicInfo SmtEngine::getLogicInfo() const {
869 return d_logic;
870 }
871
872 void SmtEngine::setLogicInternal() throw() {
873 Assert(!d_fullyInited, "setting logic in SmtEngine but the engine has already finished initializing for this run");
874 d_logic.lock();
875 }
876
877 void SmtEngine::setDefaults() {
878 if(options::forceLogic.wasSetByUser()) {
879 d_logic = options::forceLogic();
880 }
881
882 // set strings-exp
883 /* - disabled for 1.4 release [MGD 2014.06.25]
884 if(!d_logic.hasEverything() && d_logic.isTheoryEnabled(THEORY_STRINGS) ) {
885 if(! options::stringExp.wasSetByUser()) {
886 options::stringExp.set( true );
887 Trace("smt") << "turning on strings-exp, for the theory of strings" << std::endl;
888 }
889 }
890 */
891 // for strings
892 if(options::stringExp()) {
893 if( !d_logic.isQuantified() ) {
894 d_logic = d_logic.getUnlockedCopy();
895 d_logic.enableQuantifiers();
896 d_logic.lock();
897 Trace("smt") << "turning on quantifier logic, for strings-exp" << std::endl;
898 }
899 if(! options::finiteModelFind.wasSetByUser()) {
900 options::finiteModelFind.set( true );
901 Trace("smt") << "turning on finite-model-find, for strings-exp" << std::endl;
902 }
903 if(! options::fmfBoundInt.wasSetByUser()) {
904 if(! options::fmfBoundIntLazy.wasSetByUser()) {
905 options::fmfBoundIntLazy.set( true );
906 }
907 options::fmfBoundInt.set( true );
908 Trace("smt") << "turning on fmf-bound-int, for strings-exp" << std::endl;
909 }
910 /*
911 if(! options::rewriteDivk.wasSetByUser()) {
912 options::rewriteDivk.set( true );
913 Trace("smt") << "turning on rewrite-divk, for strings-exp" << std::endl;
914 }*/
915 /*
916 if(! options::stringFMF.wasSetByUser()) {
917 options::stringFMF.set( true );
918 Trace("smt") << "turning on strings-fmf, for strings-exp" << std::endl;
919 }
920 */
921 }
922
923 if(options::checkModels()) {
924 if(! options::interactive()) {
925 Notice() << "SmtEngine: turning on interactive-mode to support check-models" << endl;
926 setOption("interactive-mode", SExpr("true"));
927 }
928 }
929
930 if(options::produceAssignments() && !options::produceModels()) {
931 Notice() << "SmtEngine: turning on produce-models to support produce-assignments" << endl;
932 setOption("produce-models", SExpr("true"));
933 }
934
935 // Set the options for the theoryOf
936 if(!options::theoryOfMode.wasSetByUser()) {
937 if(d_logic.isSharingEnabled() && !d_logic.isTheoryEnabled(THEORY_BV) && !d_logic.isTheoryEnabled(THEORY_STRINGS)) {
938 Trace("smt") << "setting theoryof-mode to term-based" << endl;
939 options::theoryOfMode.set(THEORY_OF_TERM_BASED);
940 }
941 }
942
943 // by default, symmetry breaker is on only for QF_UF
944 if(! options::ufSymmetryBreaker.wasSetByUser()) {
945 bool qf_uf = d_logic.isPure(THEORY_UF) && !d_logic.isQuantified();
946 Trace("smt") << "setting uf symmetry breaker to " << qf_uf << endl;
947 options::ufSymmetryBreaker.set(qf_uf);
948 }
949 // by default, nonclausal simplification is off for QF_SAT
950 if(! options::simplificationMode.wasSetByUser()) {
951 bool qf_sat = d_logic.isPure(THEORY_BOOL) && !d_logic.isQuantified();
952 Trace("smt") << "setting simplification mode to <" << d_logic.getLogicString() << "> " << (!qf_sat) << endl;
953 //simplification=none works better for SMT LIB benchmarks with quantifiers, not others
954 //options::simplificationMode.set(qf_sat || quantifiers ? SIMPLIFICATION_MODE_NONE : SIMPLIFICATION_MODE_BATCH);
955 options::simplificationMode.set(qf_sat ? SIMPLIFICATION_MODE_NONE : SIMPLIFICATION_MODE_BATCH);
956 }
957
958 // If in arrays, set the UF handler to arrays
959 if(d_logic.isTheoryEnabled(THEORY_ARRAY) && ( !d_logic.isQuantified() ||
960 (d_logic.isQuantified() && !d_logic.isTheoryEnabled(THEORY_UF)))) {
961 Theory::setUninterpretedSortOwner(THEORY_ARRAY);
962 } else {
963 Theory::setUninterpretedSortOwner(THEORY_UF);
964 }
965 // Turn on ite simplification for QF_LIA and QF_AUFBV
966 if(! options::doITESimp.wasSetByUser()) {
967 bool qf_aufbv = !d_logic.isQuantified() &&
968 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
969 d_logic.isTheoryEnabled(THEORY_UF) &&
970 d_logic.isTheoryEnabled(THEORY_BV);
971 bool qf_lia = !d_logic.isQuantified() &&
972 d_logic.isPure(THEORY_ARITH) &&
973 d_logic.isLinear() &&
974 !d_logic.isDifferenceLogic() &&
975 !d_logic.areRealsUsed();
976
977 bool iteSimp = (qf_aufbv || qf_lia);
978 Trace("smt") << "setting ite simplification to " << iteSimp << endl;
979 options::doITESimp.set(iteSimp);
980 }
981 if(! options::compressItes.wasSetByUser() ){
982 bool qf_lia = !d_logic.isQuantified() &&
983 d_logic.isPure(THEORY_ARITH) &&
984 d_logic.isLinear() &&
985 !d_logic.isDifferenceLogic() &&
986 !d_logic.areRealsUsed();
987
988 bool compressIte = qf_lia;
989 Trace("smt") << "setting ite compression to " << compressIte << endl;
990 options::compressItes.set(compressIte);
991 }
992 if(! options::simplifyWithCareEnabled.wasSetByUser() ){
993 bool qf_aufbv = !d_logic.isQuantified() &&
994 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
995 d_logic.isTheoryEnabled(THEORY_UF) &&
996 d_logic.isTheoryEnabled(THEORY_BV);
997
998 bool withCare = qf_aufbv;
999 Trace("smt") << "setting ite simplify with care to " << withCare << endl;
1000 options::simplifyWithCareEnabled.set(withCare);
1001 }
1002 // Turn off array eager index splitting for QF_AUFLIA
1003 if(! options::arraysEagerIndexSplitting.wasSetByUser()) {
1004 if (not d_logic.isQuantified() &&
1005 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1006 d_logic.isTheoryEnabled(THEORY_UF) &&
1007 d_logic.isTheoryEnabled(THEORY_ARITH)) {
1008 Trace("smt") << "setting array eager index splitting to false" << endl;
1009 options::arraysEagerIndexSplitting.set(false);
1010 }
1011 }
1012 // Turn on model-based arrays for QF_AX (unless models are enabled)
1013 // if(! options::arraysModelBased.wasSetByUser()) {
1014 // if (not d_logic.isQuantified() &&
1015 // d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1016 // d_logic.isPure(THEORY_ARRAY) &&
1017 // !options::produceModels() &&
1018 // !options::checkModels()) {
1019 // Trace("smt") << "turning on model-based array solver" << endl;
1020 // options::arraysModelBased.set(true);
1021 // }
1022 // }
1023 // Turn on multiple-pass non-clausal simplification for QF_AUFBV
1024 if(! options::repeatSimp.wasSetByUser()) {
1025 bool repeatSimp = !d_logic.isQuantified() &&
1026 (d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_UF) && d_logic.isTheoryEnabled(THEORY_BV));
1027 Trace("smt") << "setting repeat simplification to " << repeatSimp << endl;
1028 options::repeatSimp.set(repeatSimp);
1029 }
1030 // Turn on unconstrained simplification for QF_AUFBV
1031 if(! options::unconstrainedSimp.wasSetByUser() || options::incrementalSolving()) {
1032 // bool qf_sat = d_logic.isPure(THEORY_BOOL) && !d_logic.isQuantified();
1033 // bool uncSimp = false && !qf_sat && !options::incrementalSolving();
1034 bool uncSimp = !options::incrementalSolving() && !d_logic.isQuantified() && !options::produceModels() && !options::produceAssignments() && !options::checkModels() &&
1035 (d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_BV));
1036 Trace("smt") << "setting unconstrained simplification to " << uncSimp << endl;
1037 options::unconstrainedSimp.set(uncSimp);
1038 }
1039 // Unconstrained simp currently does *not* support model generation
1040 if (options::unconstrainedSimp.wasSetByUser() && options::unconstrainedSimp()) {
1041 if (options::produceModels()) {
1042 if (options::produceModels.wasSetByUser()) {
1043 throw OptionException("Cannot use unconstrained-simp with model generation.");
1044 }
1045 Notice() << "SmtEngine: turning off produce-models to support unconstrainedSimp" << endl;
1046 setOption("produce-models", SExpr("false"));
1047 }
1048 if (options::produceAssignments()) {
1049 if (options::produceAssignments.wasSetByUser()) {
1050 throw OptionException("Cannot use unconstrained-simp with model generation (produce-assignments).");
1051 }
1052 Notice() << "SmtEngine: turning off produce-assignments to support unconstrainedSimp" << endl;
1053 setOption("produce-assignments", SExpr("false"));
1054 }
1055 if (options::checkModels()) {
1056 if (options::checkModels.wasSetByUser()) {
1057 throw OptionException("Cannot use unconstrained-simp with model generation (check-models).");
1058 }
1059 Notice() << "SmtEngine: turning off check-models to support unconstrainedSimp" << endl;
1060 setOption("check-models", SExpr("false"));
1061 }
1062 }
1063
1064
1065 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
1066 options::incrementalSolving()) {
1067 if (options::incrementalSolving.wasSetByUser()) {
1068 throw OptionException(std::string("Eager bit-blasting does not currently support incremental mode. \n\
1069 Try --bitblast=lazy"));
1070 }
1071 Notice() << "SmtEngine: turning off incremental to support eager bit-blasting" << endl;
1072 setOption("incremental", SExpr("false"));
1073 }
1074
1075 if (! options::bvEagerExplanations.wasSetByUser() &&
1076 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1077 d_logic.isTheoryEnabled(THEORY_BV)) {
1078 Trace("smt") << "enabling eager bit-vector explanations " << endl;
1079 options::bvEagerExplanations.set(true);
1080 }
1081
1082 // Turn on arith rewrite equalities only for pure arithmetic
1083 if(! options::arithRewriteEq.wasSetByUser()) {
1084 bool arithRewriteEq = d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified();
1085 Trace("smt") << "setting arith rewrite equalities " << arithRewriteEq << endl;
1086 options::arithRewriteEq.set(arithRewriteEq);
1087 }
1088 if(! options::arithHeuristicPivots.wasSetByUser()) {
1089 int16_t heuristicPivots = 5;
1090 if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()) {
1091 if(d_logic.isDifferenceLogic()) {
1092 heuristicPivots = -1;
1093 } else if(!d_logic.areIntegersUsed()) {
1094 heuristicPivots = 0;
1095 }
1096 }
1097 Trace("smt") << "setting arithHeuristicPivots " << heuristicPivots << endl;
1098 options::arithHeuristicPivots.set(heuristicPivots);
1099 }
1100 if(! options::arithPivotThreshold.wasSetByUser()){
1101 uint16_t pivotThreshold = 2;
1102 if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()){
1103 if(d_logic.isDifferenceLogic()){
1104 pivotThreshold = 16;
1105 }
1106 }
1107 Trace("smt") << "setting arith arithPivotThreshold " << pivotThreshold << endl;
1108 options::arithPivotThreshold.set(pivotThreshold);
1109 }
1110 if(! options::arithStandardCheckVarOrderPivots.wasSetByUser()){
1111 int16_t varOrderPivots = -1;
1112 if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()){
1113 varOrderPivots = 200;
1114 }
1115 Trace("smt") << "setting arithStandardCheckVarOrderPivots " << varOrderPivots << endl;
1116 options::arithStandardCheckVarOrderPivots.set(varOrderPivots);
1117 }
1118 // Turn off early theory preprocessing if arithRewriteEq is on
1119 if (options::arithRewriteEq()) {
1120 d_earlyTheoryPP = false;
1121 }
1122 // Turn on justification heuristic of the decision engine for QF_BV and QF_AUFBV
1123 // and also use it in stop-only mode for QF_AUFLIA, QF_LRA and Quantifiers
1124 // BUT use neither in ALL_SUPPORTED mode (since it doesn't yet work well
1125 // with incrementality)
1126 if(!options::decisionMode.wasSetByUser()) {
1127 decision::DecisionMode decMode =
1128 // ALL_SUPPORTED
1129 d_logic.hasEverything() ? decision::DECISION_STRATEGY_JUSTIFICATION :
1130 ( // QF_BV
1131 (not d_logic.isQuantified() &&
1132 d_logic.isPure(THEORY_BV)
1133 ) ||
1134 // QF_AUFBV or QF_ABV or QF_UFBV
1135 (not d_logic.isQuantified() &&
1136 (d_logic.isTheoryEnabled(THEORY_ARRAY) ||
1137 d_logic.isTheoryEnabled(THEORY_UF)) &&
1138 d_logic.isTheoryEnabled(THEORY_BV)
1139 ) ||
1140 // QF_AUFLIA (and may be ends up enabling QF_AUFLRA?)
1141 (not d_logic.isQuantified() &&
1142 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1143 d_logic.isTheoryEnabled(THEORY_UF) &&
1144 d_logic.isTheoryEnabled(THEORY_ARITH)
1145 ) ||
1146 // QF_LRA
1147 (not d_logic.isQuantified() &&
1148 d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areIntegersUsed()
1149 ) ||
1150 // Quantifiers
1151 d_logic.isQuantified() ||
1152 // Strings
1153 d_logic.isTheoryEnabled(THEORY_STRINGS)
1154 ? decision::DECISION_STRATEGY_JUSTIFICATION
1155 : decision::DECISION_STRATEGY_INTERNAL
1156 );
1157
1158 bool stoponly =
1159 // ALL_SUPPORTED
1160 d_logic.hasEverything() || d_logic.isTheoryEnabled(THEORY_STRINGS) ? false :
1161 ( // QF_AUFLIA
1162 (not d_logic.isQuantified() &&
1163 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1164 d_logic.isTheoryEnabled(THEORY_UF) &&
1165 d_logic.isTheoryEnabled(THEORY_ARITH)
1166 ) ||
1167 // QF_LRA
1168 (not d_logic.isQuantified() &&
1169 d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areIntegersUsed()
1170 )
1171 ? true : false
1172 );
1173
1174 Trace("smt") << "setting decision mode to " << decMode << endl;
1175 options::decisionMode.set(decMode);
1176 options::decisionStopOnly.set(stoponly);
1177 }
1178
1179 //for finite model finding
1180 if( ! options::instWhenMode.wasSetByUser()){
1181 //instantiate only on last call
1182 if( options::fmfInstEngine() ){
1183 Trace("smt") << "setting inst when mode to LAST_CALL" << endl;
1184 options::instWhenMode.set( quantifiers::INST_WHEN_LAST_CALL );
1185 }
1186 }
1187 if( d_logic.hasCardinalityConstraints() ){
1188 //must have finite model finding on
1189 options::finiteModelFind.set( true );
1190 }
1191 if( options::recurseCbqi() ){
1192 options::cbqi.set( true );
1193 }
1194 if(options::fmfBoundIntLazy.wasSetByUser() && options::fmfBoundIntLazy()) {
1195 options::fmfBoundInt.set( true );
1196 }
1197 if( options::fmfBoundInt() ){
1198 //must have finite model finding on
1199 options::finiteModelFind.set( true );
1200 if( ! options::mbqiMode.wasSetByUser() ||
1201 ( options::mbqiMode()!=quantifiers::MBQI_NONE &&
1202 options::mbqiMode()!=quantifiers::MBQI_FMC &&
1203 options::mbqiMode()!=quantifiers::MBQI_FMC_INTERVAL ) ){
1204 //if bounded integers are set, use no MBQI by default
1205 options::mbqiMode.set( quantifiers::MBQI_NONE );
1206 }
1207 }
1208 if( options::mbqiMode()==quantifiers::MBQI_INTERVAL ){
1209 //must do pre-skolemization
1210 options::preSkolemQuant.set( true );
1211 }
1212 if( options::ufssSymBreak() ){
1213 options::sortInference.set( true );
1214 }
1215 if( options::qcfMode.wasSetByUser() || options::qcfTConstraint() ){
1216 options::quantConflictFind.set( true );
1217 }
1218
1219 //until bugs 371,431 are fixed
1220 if( ! options::minisatUseElim.wasSetByUser()){
1221 if( d_logic.isQuantified() || options::produceModels() || options::produceAssignments() || options::checkModels() ){
1222 options::minisatUseElim.set( false );
1223 }
1224 }
1225 else if (options::minisatUseElim()) {
1226 if (options::produceModels()) {
1227 Notice() << "SmtEngine: turning off produce-models to support minisatUseElim" << endl;
1228 setOption("produce-models", SExpr("false"));
1229 }
1230 if (options::produceAssignments()) {
1231 Notice() << "SmtEngine: turning off produce-assignments to support minisatUseElim" << endl;
1232 setOption("produce-assignments", SExpr("false"));
1233 }
1234 if (options::checkModels()) {
1235 Notice() << "SmtEngine: turning off check-models to support minisatUseElim" << endl;
1236 setOption("check-models", SExpr("false"));
1237 }
1238 }
1239
1240 // For now, these array theory optimizations do not support model-building
1241 if (options::produceModels() || options::produceAssignments() || options::checkModels()) {
1242 options::arraysOptimizeLinear.set(false);
1243 options::arraysLazyRIntro1.set(false);
1244 }
1245
1246 // Non-linear arithmetic does not support models
1247 if (d_logic.isTheoryEnabled(THEORY_ARITH) &&
1248 !d_logic.isLinear()) {
1249 if (options::produceModels()) {
1250 Warning() << "SmtEngine: turning off produce-models because unsupported for nonlinear arith" << endl;
1251 setOption("produce-models", SExpr("false"));
1252 }
1253 if (options::produceAssignments()) {
1254 Warning() << "SmtEngine: turning off produce-assignments because unsupported for nonlinear arith" << endl;
1255 setOption("produce-assignments", SExpr("false"));
1256 }
1257 if (options::checkModels()) {
1258 Warning() << "SmtEngine: turning off check-models because unsupported for nonlinear arith" << endl;
1259 setOption("check-models", SExpr("false"));
1260 }
1261 }
1262
1263 if (options::incrementalSolving() && options::proof()) {
1264 Warning() << "SmtEngine: turning off incremental solving mode (not yet supported with --proof" << endl;
1265 setOption("incremental", SExpr("false"));
1266 }
1267
1268 // datatypes theory should assign values to all datatypes terms if logic is quantified
1269 if (d_logic.isQuantified() && d_logic.isTheoryEnabled(THEORY_DATATYPES)) {
1270 if( !options::dtForceAssignment.wasSetByUser() ){
1271 options::dtForceAssignment.set(true);
1272 }
1273 }
1274 }
1275
1276 void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
1277 throw(OptionException, ModalException) {
1278
1279 SmtScope smts(this);
1280
1281 Trace("smt") << "SMT setInfo(" << key << ", " << value << ")" << endl;
1282 if(Dump.isOn("benchmark")) {
1283 if(key == "status") {
1284 string s = value.getValue();
1285 BenchmarkStatus status =
1286 (s == "sat") ? SMT_SATISFIABLE :
1287 ((s == "unsat") ? SMT_UNSATISFIABLE : SMT_UNKNOWN);
1288 Dump("benchmark") << SetBenchmarkStatusCommand(status);
1289 } else {
1290 Dump("benchmark") << SetInfoCommand(key, value);
1291 }
1292 }
1293
1294 // Check for CVC4-specific info keys (prefixed with "cvc4-" or "cvc4_")
1295 if(key.length() > 5) {
1296 string prefix = key.substr(0, 5);
1297 if(prefix == "cvc4-" || prefix == "cvc4_") {
1298 string cvc4key = key.substr(5);
1299 if(cvc4key == "logic") {
1300 if(! value.isAtom()) {
1301 throw OptionException("argument to (set-info :cvc4-logic ..) must be a string");
1302 }
1303 SmtScope smts(this);
1304 d_logic = value.getValue();
1305 setLogicInternal();
1306 return;
1307 } else {
1308 throw UnrecognizedOptionException();
1309 }
1310 }
1311 }
1312
1313 // Check for standard info keys (SMT-LIB v1, SMT-LIB v2, ...)
1314 if(key == "source" ||
1315 key == "category" ||
1316 key == "difficulty" ||
1317 key == "notes") {
1318 // ignore these
1319 return;
1320 } else if(key == "name") {
1321 d_filename = value.getValue();
1322 return;
1323 } else if(key == "smt-lib-version") {
1324 if( (value.isInteger() && value.getIntegerValue() == Integer(2)) ||
1325 (value.isRational() && value.getRationalValue() == Rational(2)) ||
1326 (value.getValue() == "2") ) {
1327 // supported SMT-LIB version
1328 return;
1329 }
1330 Warning() << "Warning: unsupported smt-lib-version: " << value << endl;
1331 throw UnrecognizedOptionException();
1332 } else if(key == "status") {
1333 string s;
1334 if(value.isAtom()) {
1335 s = value.getValue();
1336 }
1337 if(s != "sat" && s != "unsat" && s != "unknown") {
1338 throw OptionException("argument to (set-info :status ..) must be "
1339 "`sat' or `unsat' or `unknown'");
1340 }
1341 d_status = Result(s, d_filename);
1342 return;
1343 }
1344 throw UnrecognizedOptionException();
1345 }
1346
1347 CVC4::SExpr SmtEngine::getInfo(const std::string& key) const
1348 throw(OptionException, ModalException) {
1349
1350 SmtScope smts(this);
1351
1352 Trace("smt") << "SMT getInfo(" << key << ")" << endl;
1353 if(key == "all-statistics") {
1354 vector<SExpr> stats;
1355 for(StatisticsRegistry::const_iterator i = NodeManager::fromExprManager(d_exprManager)->getStatisticsRegistry()->begin();
1356 i != NodeManager::fromExprManager(d_exprManager)->getStatisticsRegistry()->end();
1357 ++i) {
1358 vector<SExpr> v;
1359 v.push_back((*i).first);
1360 v.push_back((*i).second);
1361 stats.push_back(v);
1362 }
1363 for(StatisticsRegistry::const_iterator i = d_statisticsRegistry->begin();
1364 i != d_statisticsRegistry->end();
1365 ++i) {
1366 vector<SExpr> v;
1367 v.push_back((*i).first);
1368 v.push_back((*i).second);
1369 stats.push_back(v);
1370 }
1371 return stats;
1372 } else if(key == "error-behavior") {
1373 // immediate-exit | continued-execution
1374 if( options::continuedExecution() || options::interactive() ) {
1375 return SExpr::Keyword("continued-execution");
1376 } else {
1377 return SExpr::Keyword("immediate-exit");
1378 }
1379 } else if(key == "name") {
1380 return Configuration::getName();
1381 } else if(key == "version") {
1382 return Configuration::getVersionString();
1383 } else if(key == "authors") {
1384 return Configuration::about();
1385 } else if(key == "status") {
1386 // sat | unsat | unknown
1387 switch(d_status.asSatisfiabilityResult().isSat()) {
1388 case Result::SAT:
1389 return SExpr::Keyword("sat");
1390 case Result::UNSAT:
1391 return SExpr::Keyword("unsat");
1392 default:
1393 return SExpr::Keyword("unknown");
1394 }
1395 } else if(key == "reason-unknown") {
1396 if(!d_status.isNull() && d_status.isUnknown()) {
1397 stringstream ss;
1398 ss << d_status.whyUnknown();
1399 string s = ss.str();
1400 transform(s.begin(), s.end(), s.begin(), ::tolower);
1401 return SExpr::Keyword(s);
1402 } else {
1403 throw ModalException("Can't get-info :reason-unknown when the "
1404 "last result wasn't unknown!");
1405 }
1406 } else if(key == "all-options") {
1407 // get the options, like all-statistics
1408 return Options::current().getOptions();
1409 } else {
1410 throw UnrecognizedOptionException();
1411 }
1412 }
1413
1414 void SmtEngine::defineFunction(Expr func,
1415 const std::vector<Expr>& formals,
1416 Expr formula) {
1417 Trace("smt") << "SMT defineFunction(" << func << ")" << endl;
1418 for(std::vector<Expr>::const_iterator i = formals.begin(); i != formals.end(); ++i) {
1419 if((*i).getKind() != kind::BOUND_VARIABLE) {
1420 stringstream ss;
1421 ss << "All formal arguments to defined functions must be BOUND_VARIABLEs, but in the\n"
1422 << "definition of function " << func << ", formal\n"
1423 << " " << *i << "\n"
1424 << "has kind " << (*i).getKind();
1425 throw TypeCheckingException(func, ss.str());
1426 }
1427 }
1428
1429 stringstream ss;
1430 ss << Expr::setlanguage(Expr::setlanguage::getLanguage(Dump.getStream()))
1431 << func;
1432 DefineFunctionCommand c(ss.str(), func, formals, formula);
1433 addToModelCommandAndDump(c, ExprManager::VAR_FLAG_DEFINED, true, "declarations");
1434
1435 SmtScope smts(this);
1436
1437 // Substitute out any abstract values in formula
1438 Expr form = d_private->substituteAbstractValues(Node::fromExpr(formula)).toExpr();
1439
1440 // type check body
1441 Type formulaType = form.getType(options::typeChecking());
1442
1443 Type funcType = func.getType();
1444 // We distinguish here between definitions of constants and functions,
1445 // because the type checking for them is subtly different. Perhaps we
1446 // should instead have SmtEngine::defineFunction() and
1447 // SmtEngine::defineConstant() for better clarity, although then that
1448 // doesn't match the SMT-LIBv2 standard...
1449 if(formals.size() > 0) {
1450 Type rangeType = FunctionType(funcType).getRangeType();
1451 if(! formulaType.isComparableTo(rangeType)) {
1452 stringstream ss;
1453 ss << "Type of defined function does not match its declaration\n"
1454 << "The function : " << func << "\n"
1455 << "Declared type : " << rangeType << "\n"
1456 << "The body : " << formula << "\n"
1457 << "Body type : " << formulaType;
1458 throw TypeCheckingException(func, ss.str());
1459 }
1460 } else {
1461 if(! formulaType.isComparableTo(funcType)) {
1462 stringstream ss;
1463 ss << "Declared type of defined constant does not match its definition\n"
1464 << "The constant : " << func << "\n"
1465 << "Declared type : " << funcType << " " << Type::getTypeNode(funcType)->getId() << "\n"
1466 << "The definition : " << formula << "\n"
1467 << "Definition type: " << formulaType << " " << Type::getTypeNode(formulaType)->getId();
1468 throw TypeCheckingException(func, ss.str());
1469 }
1470 }
1471 TNode funcNode = func.getTNode();
1472 vector<Node> formalsNodes;
1473 for(vector<Expr>::const_iterator i = formals.begin(),
1474 iend = formals.end();
1475 i != iend;
1476 ++i) {
1477 formalsNodes.push_back((*i).getNode());
1478 }
1479 TNode formNode = form.getTNode();
1480 DefinedFunction def(funcNode, formalsNodes, formNode);
1481 // Permit (check-sat) (define-fun ...) (get-value ...) sequences.
1482 // Otherwise, (check-sat) (get-value ((! foo :named bar))) breaks
1483 // d_haveAdditions = true;
1484 Debug("smt") << "definedFunctions insert " << funcNode << " " << formNode << endl;
1485 d_definedFunctions->insert(funcNode, def);
1486 }
1487
1488 Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashFunction>& cache, bool expandOnly)
1489 throw(TypeCheckingException, LogicException) {
1490
1491 stack< triple<Node, Node, bool> > worklist;
1492 stack<Node> result;
1493 worklist.push(make_triple(Node(n), Node(n), false));
1494 // The worklist is made of triples, each is input / original node then the output / rewritten node
1495 // and finally a flag tracking whether the children have been explored (i.e. if this is a downward
1496 // or upward pass).
1497
1498 do {
1499 n = worklist.top().first; // n is the input / original
1500 Node node = worklist.top().second; // node is the output / result
1501 bool childrenPushed = worklist.top().third;
1502 worklist.pop();
1503
1504 // Working downwards
1505 if(!childrenPushed) {
1506 Kind k = n.getKind();
1507
1508 // Apart from apply, we can short circuit leaves
1509 if(k != kind::APPLY && n.getNumChildren() == 0) {
1510 SmtEngine::DefinedFunctionMap::const_iterator i = d_smt.d_definedFunctions->find(n);
1511 if(i != d_smt.d_definedFunctions->end()) {
1512 // replacement must be closed
1513 if((*i).second.getFormals().size() > 0) {
1514 result.push(d_smt.d_nodeManager->mkNode(kind::LAMBDA, d_smt.d_nodeManager->mkNode(kind::BOUND_VAR_LIST, (*i).second.getFormals()), (*i).second.getFormula()));
1515 continue;
1516 }
1517 // don't bother putting in the cache
1518 result.push((*i).second.getFormula());
1519 continue;
1520 }
1521 // don't bother putting in the cache
1522 result.push(n);
1523 continue;
1524 }
1525
1526 // maybe it's in the cache
1527 hash_map<Node, Node, NodeHashFunction>::iterator cacheHit = cache.find(n);
1528 if(cacheHit != cache.end()) {
1529 TNode ret = (*cacheHit).second;
1530 result.push(ret.isNull() ? n : ret);
1531 continue;
1532 }
1533
1534 // otherwise expand it
1535 if (k == kind::APPLY) {
1536 // application of a user-defined symbol
1537 TNode func = n.getOperator();
1538 SmtEngine::DefinedFunctionMap::const_iterator i =
1539 d_smt.d_definedFunctions->find(func);
1540 DefinedFunction def = (*i).second;
1541 vector<Node> formals = def.getFormals();
1542
1543 if(Debug.isOn("expand")) {
1544 Debug("expand") << "found: " << n << endl;
1545 Debug("expand") << " func: " << func << endl;
1546 string name = func.getAttribute(expr::VarNameAttr());
1547 Debug("expand") << " : \"" << name << "\"" << endl;
1548 }
1549 if(i == d_smt.d_definedFunctions->end()) {
1550 throw TypeCheckingException(n.toExpr(), string("Undefined function: `") + func.toString() + "'");
1551 }
1552 if(Debug.isOn("expand")) {
1553 Debug("expand") << " defn: " << def.getFunction() << endl
1554 << " [";
1555 if(formals.size() > 0) {
1556 copy( formals.begin(), formals.end() - 1,
1557 ostream_iterator<Node>(Debug("expand"), ", ") );
1558 Debug("expand") << formals.back();
1559 }
1560 Debug("expand") << "]" << endl
1561 << " " << def.getFunction().getType() << endl
1562 << " " << def.getFormula() << endl;
1563 }
1564
1565 TNode fm = def.getFormula();
1566 Node instance = fm.substitute(formals.begin(), formals.end(),
1567 n.begin(), n.end());
1568 Debug("expand") << "made : " << instance << endl;
1569
1570 Node expanded = expandDefinitions(instance, cache, expandOnly);
1571 cache[n] = (n == expanded ? Node::null() : expanded);
1572 result.push(expanded);
1573 continue;
1574
1575 } else if(! expandOnly) {
1576 // do not do any theory stuff if expandOnly is true
1577
1578 theory::Theory* t = d_smt.d_theoryEngine->theoryOf(node);
1579
1580 Assert(t != NULL);
1581 LogicRequest req(d_smt);
1582 node = t->expandDefinition(req, n);
1583 }
1584
1585 // there should be children here, otherwise we short-circuited a result-push/continue, above
1586 if (node.getNumChildren() == 0) {
1587 Debug("expand") << "Unexpectedly no children..." << node << endl;
1588 }
1589 // This invariant holds at the moment but it is concievable that a new theory
1590 // might introduce a kind which can have children before definition expansion but doesn't
1591 // afterwards. If this happens, remove this assertion.
1592 Assert(node.getNumChildren() > 0);
1593
1594 // the partial functions can fall through, in which case we still
1595 // consider their children
1596 worklist.push(make_triple(Node(n), node, true)); // Original and rewritten result
1597
1598 for(size_t i = 0; i < node.getNumChildren(); ++i) {
1599 worklist.push(make_triple(node[i], node[i], false)); // Rewrite the children of the result only
1600 }
1601
1602 } else {
1603 // Working upwards
1604 // Reconstruct the node from it's (now rewritten) children on the stack
1605
1606 Debug("expand") << "cons : " << node << endl;
1607 //cout << "cons : " << node << endl;
1608 NodeBuilder<> nb(node.getKind());
1609 if(node.getMetaKind() == kind::metakind::PARAMETERIZED) {
1610 Debug("expand") << "op : " << node.getOperator() << endl;
1611 //cout << "op : " << node.getOperator() << endl;
1612 nb << node.getOperator();
1613 }
1614 for(size_t i = 0; i < node.getNumChildren(); ++i) {
1615 Assert(!result.empty());
1616 Node expanded = result.top();
1617 result.pop();
1618 //cout << "exchld : " << expanded << endl;
1619 Debug("expand") << "exchld : " << expanded << endl;
1620 nb << expanded;
1621 }
1622 node = nb;
1623 cache[n] = n == node ? Node::null() : node; // Only cache once all subterms are expanded
1624 result.push(node);
1625 }
1626 } while(!worklist.empty());
1627
1628 AlwaysAssert(result.size() == 1);
1629
1630 return result.top();
1631 }
1632
1633 void SmtEnginePrivate::removeITEs() {
1634 d_smt.finalOptionsAreSet();
1635
1636 Trace("simplify") << "SmtEnginePrivate::removeITEs()" << endl;
1637
1638 // Remove all of the ITE occurrences and normalize
1639 d_iteRemover.run(d_assertionsToCheck, d_iteSkolemMap);
1640 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
1641 d_assertionsToCheck[i] = Rewriter::rewrite(d_assertionsToCheck[i]);
1642 }
1643
1644 }
1645
1646 void SmtEnginePrivate::staticLearning() {
1647 d_smt.finalOptionsAreSet();
1648
1649 TimerStat::CodeTimer staticLearningTimer(d_smt.d_stats->d_staticLearningTime);
1650
1651 Trace("simplify") << "SmtEnginePrivate::staticLearning()" << endl;
1652
1653 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
1654
1655 NodeBuilder<> learned(kind::AND);
1656 learned << d_assertionsToCheck[i];
1657 d_smt.d_theoryEngine->ppStaticLearn(d_assertionsToCheck[i], learned);
1658 if(learned.getNumChildren() == 1) {
1659 learned.clear();
1660 } else {
1661 d_assertionsToCheck[i] = learned;
1662 }
1663 }
1664 }
1665
1666 // do dumping (before/after any preprocessing pass)
1667 static void dumpAssertions(const char* key,
1668 const std::vector<Node>& assertionList) {
1669 if( Dump.isOn("assertions") &&
1670 Dump.isOn(string("assertions:") + key) ) {
1671 // Push the simplified assertions to the dump output stream
1672 for(unsigned i = 0; i < assertionList.size(); ++ i) {
1673 TNode n = assertionList[i];
1674 Dump("assertions") << AssertCommand(Expr(n.toExpr()));
1675 }
1676 }
1677 }
1678
1679 // returns false if it learns a conflict
1680 bool SmtEnginePrivate::nonClausalSimplify() {
1681 d_smt.finalOptionsAreSet();
1682
1683 TimerStat::CodeTimer nonclausalTimer(d_smt.d_stats->d_nonclausalSimplificationTime);
1684
1685
1686 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify()" << endl;
1687
1688 if(d_propagatorNeedsFinish) {
1689 d_propagator.finish();
1690 d_propagatorNeedsFinish = false;
1691 }
1692 d_propagator.initialize();
1693
1694 // Assert all the assertions to the propagator
1695 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1696 << "asserting to propagator" << endl;
1697 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
1698 Assert(Rewriter::rewrite(d_assertionsToPreprocess[i]) == d_assertionsToPreprocess[i]);
1699 // Don't reprocess substitutions
1700 if (d_substitutionsIndex > 0 && i == d_substitutionsIndex) {
1701 continue;
1702 }
1703 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): asserting " << d_assertionsToPreprocess[i] << endl;
1704 d_propagator.assertTrue(d_assertionsToPreprocess[i]);
1705 }
1706
1707 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1708 << "propagating" << endl;
1709 if (d_propagator.propagate()) {
1710 // If in conflict, just return false
1711 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1712 << "conflict in non-clausal propagation" << endl;
1713 d_assertionsToPreprocess.clear();
1714 d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
1715 d_propagatorNeedsFinish = true;
1716 return false;
1717 }
1718
1719 // No conflict, go through the literals and solve them
1720 SubstitutionMap constantPropagations(d_smt.d_context);
1721 SubstitutionMap newSubstitutions(d_smt.d_context);
1722 SubstitutionMap::iterator pos;
1723 unsigned j = 0;
1724 for(unsigned i = 0, i_end = d_nonClausalLearnedLiterals.size(); i < i_end; ++ i) {
1725 // Simplify the literal we learned wrt previous substitutions
1726 Node learnedLiteral = d_nonClausalLearnedLiterals[i];
1727 Assert(Rewriter::rewrite(learnedLiteral) == learnedLiteral);
1728 Assert(d_topLevelSubstitutions.apply(learnedLiteral) == learnedLiteral);
1729 Node learnedLiteralNew = newSubstitutions.apply(learnedLiteral);
1730 if (learnedLiteral != learnedLiteralNew) {
1731 learnedLiteral = Rewriter::rewrite(learnedLiteralNew);
1732 }
1733 for (;;) {
1734 learnedLiteralNew = constantPropagations.apply(learnedLiteral);
1735 if (learnedLiteralNew == learnedLiteral) {
1736 break;
1737 }
1738 ++d_smt.d_stats->d_numConstantProps;
1739 learnedLiteral = Rewriter::rewrite(learnedLiteralNew);
1740 }
1741 // It might just simplify to a constant
1742 if (learnedLiteral.isConst()) {
1743 if (learnedLiteral.getConst<bool>()) {
1744 // If the learned literal simplifies to true, it's redundant
1745 continue;
1746 } else {
1747 // If the learned literal simplifies to false, we're in conflict
1748 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1749 << "conflict with "
1750 << d_nonClausalLearnedLiterals[i] << endl;
1751 d_assertionsToPreprocess.clear();
1752 d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
1753 d_propagatorNeedsFinish = true;
1754 return false;
1755 }
1756 }
1757
1758 // Solve it with the corresponding theory, possibly adding new
1759 // substitutions to newSubstitutions
1760 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1761 << "solving " << learnedLiteral << endl;
1762
1763 Theory::PPAssertStatus solveStatus =
1764 d_smt.d_theoryEngine->solve(learnedLiteral, newSubstitutions);
1765
1766 switch (solveStatus) {
1767 case Theory::PP_ASSERT_STATUS_SOLVED: {
1768 // The literal should rewrite to true
1769 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1770 << "solved " << learnedLiteral << endl;
1771 Assert(Rewriter::rewrite(newSubstitutions.apply(learnedLiteral)).isConst());
1772 // vector<pair<Node, Node> > equations;
1773 // constantPropagations.simplifyLHS(d_topLevelSubstitutions, equations, true);
1774 // if (equations.empty()) {
1775 // break;
1776 // }
1777 // Assert(equations[0].first.isConst() && equations[0].second.isConst() && equations[0].first != equations[0].second);
1778 // else fall through
1779 break;
1780 }
1781 case Theory::PP_ASSERT_STATUS_CONFLICT:
1782 // If in conflict, we return false
1783 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1784 << "conflict while solving "
1785 << learnedLiteral << endl;
1786 d_assertionsToPreprocess.clear();
1787 d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
1788 d_propagatorNeedsFinish = true;
1789 return false;
1790 default:
1791 if (d_doConstantProp && learnedLiteral.getKind() == kind::EQUAL && (learnedLiteral[0].isConst() || learnedLiteral[1].isConst())) {
1792 // constant propagation
1793 TNode t;
1794 TNode c;
1795 if (learnedLiteral[0].isConst()) {
1796 t = learnedLiteral[1];
1797 c = learnedLiteral[0];
1798 }
1799 else {
1800 t = learnedLiteral[0];
1801 c = learnedLiteral[1];
1802 }
1803 Assert(!t.isConst());
1804 Assert(constantPropagations.apply(t) == t);
1805 Assert(d_topLevelSubstitutions.apply(t) == t);
1806 Assert(newSubstitutions.apply(t) == t);
1807 constantPropagations.addSubstitution(t, c);
1808 // vector<pair<Node,Node> > equations;
1809 // constantPropagations.simplifyLHS(t, c, equations, true);
1810 // if (!equations.empty()) {
1811 // Assert(equations[0].first.isConst() && equations[0].second.isConst() && equations[0].first != equations[0].second);
1812 // d_assertionsToPreprocess.clear();
1813 // d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
1814 // return;
1815 // }
1816 // d_topLevelSubstitutions.simplifyRHS(constantPropagations);
1817 }
1818 else {
1819 // Keep the literal
1820 d_nonClausalLearnedLiterals[j++] = d_nonClausalLearnedLiterals[i];
1821 }
1822 break;
1823 }
1824
1825 #ifdef CVC4_ASSERTIONS
1826 // Check data structure invariants:
1827 // 1. for each lhs of d_topLevelSubstitutions, does not appear anywhere in rhs of d_topLevelSubstitutions or anywhere in constantPropagations
1828 // 2. each lhs of constantPropagations rewrites to itself
1829 // 3. if l -> r is a constant propagation and l is a subterm of l' with l' -> r' another constant propagation, then l'[l/r] -> r' should be a
1830 // constant propagation too
1831 // 4. each lhs of constantPropagations is different from each rhs
1832 for (pos = newSubstitutions.begin(); pos != newSubstitutions.end(); ++pos) {
1833 Assert((*pos).first.isVar());
1834 Assert(d_topLevelSubstitutions.apply((*pos).first) == (*pos).first);
1835 Assert(d_topLevelSubstitutions.apply((*pos).second) == (*pos).second);
1836 Assert(newSubstitutions.apply(newSubstitutions.apply((*pos).second)) == newSubstitutions.apply((*pos).second));
1837 }
1838 for (pos = constantPropagations.begin(); pos != constantPropagations.end(); ++pos) {
1839 Assert((*pos).second.isConst());
1840 Assert(Rewriter::rewrite((*pos).first) == (*pos).first);
1841 // Node newLeft = d_topLevelSubstitutions.apply((*pos).first);
1842 // if (newLeft != (*pos).first) {
1843 // newLeft = Rewriter::rewrite(newLeft);
1844 // Assert(newLeft == (*pos).second ||
1845 // (constantPropagations.hasSubstitution(newLeft) && constantPropagations.apply(newLeft) == (*pos).second));
1846 // }
1847 // newLeft = constantPropagations.apply((*pos).first);
1848 // if (newLeft != (*pos).first) {
1849 // newLeft = Rewriter::rewrite(newLeft);
1850 // Assert(newLeft == (*pos).second ||
1851 // (constantPropagations.hasSubstitution(newLeft) && constantPropagations.apply(newLeft) == (*pos).second));
1852 // }
1853 Assert(constantPropagations.apply((*pos).second) == (*pos).second);
1854 }
1855 #endif /* CVC4_ASSERTIONS */
1856 }
1857 // Resize the learnt
1858 d_nonClausalLearnedLiterals.resize(j);
1859
1860 hash_set<TNode, TNodeHashFunction> s;
1861 Trace("debugging") << "NonClausal simplify pre-preprocess\n";
1862 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
1863 Node assertion = d_assertionsToPreprocess[i];
1864 Node assertionNew = newSubstitutions.apply(assertion);
1865 Trace("debugging") << "assertion = " << assertion << endl;
1866 Trace("debugging") << "assertionNew = " << assertionNew << endl;
1867 if (assertion != assertionNew) {
1868 assertion = Rewriter::rewrite(assertionNew);
1869 Trace("debugging") << "rewrite(assertion) = " << assertion << endl;
1870 }
1871 Assert(Rewriter::rewrite(assertion) == assertion);
1872 for (;;) {
1873 assertionNew = constantPropagations.apply(assertion);
1874 if (assertionNew == assertion) {
1875 break;
1876 }
1877 ++d_smt.d_stats->d_numConstantProps;
1878 Trace("debugging") << "assertionNew = " << assertionNew << endl;
1879 assertion = Rewriter::rewrite(assertionNew);
1880 Trace("debugging") << "assertionNew = " << assertionNew << endl;
1881 }
1882 Trace("debugging") << "\n";
1883 s.insert(assertion);
1884 d_assertionsToCheck.push_back(assertion);
1885 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1886 << "non-clausal preprocessed: "
1887 << assertion << endl;
1888 }
1889 d_assertionsToPreprocess.clear();
1890
1891 // If in incremental mode, add substitutions to the list of assertions
1892 if (d_substitutionsIndex > 0) {
1893 NodeBuilder<> substitutionsBuilder(kind::AND);
1894 substitutionsBuilder << d_assertionsToCheck[d_substitutionsIndex];
1895 pos = newSubstitutions.begin();
1896 for (; pos != newSubstitutions.end(); ++pos) {
1897 // Add back this substitution as an assertion
1898 TNode lhs = (*pos).first, rhs = newSubstitutions.apply((*pos).second);
1899 Node n = NodeManager::currentNM()->mkNode(lhs.getType().isBoolean() ? kind::IFF : kind::EQUAL, lhs, rhs);
1900 substitutionsBuilder << n;
1901 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): will notify SAT layer of substitution: " << n << endl;
1902 }
1903 if (substitutionsBuilder.getNumChildren() > 1) {
1904 d_assertionsToCheck[d_substitutionsIndex] =
1905 Rewriter::rewrite(Node(substitutionsBuilder));
1906 }
1907 } else {
1908 // If not in incremental mode, must add substitutions to model
1909 TheoryModel* m = d_smt.d_theoryEngine->getModel();
1910 if(m != NULL) {
1911 for(pos = newSubstitutions.begin(); pos != newSubstitutions.end(); ++pos) {
1912 Node n = (*pos).first;
1913 Node v = newSubstitutions.apply((*pos).second);
1914 Trace("model") << "Add substitution : " << n << " " << v << endl;
1915 m->addSubstitution( n, v );
1916 }
1917 }
1918 }
1919
1920 NodeBuilder<> learnedBuilder(kind::AND);
1921 Assert(d_realAssertionsEnd <= d_assertionsToCheck.size());
1922 learnedBuilder << d_assertionsToCheck[d_realAssertionsEnd - 1];
1923
1924 for (unsigned i = 0; i < d_nonClausalLearnedLiterals.size(); ++ i) {
1925 Node learned = d_nonClausalLearnedLiterals[i];
1926 Assert(d_topLevelSubstitutions.apply(learned) == learned);
1927 Node learnedNew = newSubstitutions.apply(learned);
1928 if (learned != learnedNew) {
1929 learned = Rewriter::rewrite(learnedNew);
1930 }
1931 Assert(Rewriter::rewrite(learned) == learned);
1932 for (;;) {
1933 learnedNew = constantPropagations.apply(learned);
1934 if (learnedNew == learned) {
1935 break;
1936 }
1937 ++d_smt.d_stats->d_numConstantProps;
1938 learned = Rewriter::rewrite(learnedNew);
1939 }
1940 if (s.find(learned) != s.end()) {
1941 continue;
1942 }
1943 s.insert(learned);
1944 learnedBuilder << learned;
1945 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1946 << "non-clausal learned : "
1947 << learned << endl;
1948 }
1949 d_nonClausalLearnedLiterals.clear();
1950
1951
1952 for (pos = constantPropagations.begin(); pos != constantPropagations.end(); ++pos) {
1953 Node cProp = (*pos).first.eqNode((*pos).second);
1954 Assert(d_topLevelSubstitutions.apply(cProp) == cProp);
1955 Node cPropNew = newSubstitutions.apply(cProp);
1956 if (cProp != cPropNew) {
1957 cProp = Rewriter::rewrite(cPropNew);
1958 Assert(Rewriter::rewrite(cProp) == cProp);
1959 }
1960 if (s.find(cProp) != s.end()) {
1961 continue;
1962 }
1963 s.insert(cProp);
1964 learnedBuilder << cProp;
1965 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
1966 << "non-clausal constant propagation : "
1967 << cProp << endl;
1968 }
1969
1970 // Add new substitutions to topLevelSubstitutions
1971 // Note that we don't have to keep rhs's in full solved form
1972 // because SubstitutionMap::apply does a fixed-point iteration when substituting
1973 d_topLevelSubstitutions.addSubstitutions(newSubstitutions);
1974
1975 if(learnedBuilder.getNumChildren() > 1) {
1976 d_assertionsToCheck[d_realAssertionsEnd - 1] =
1977 Rewriter::rewrite(Node(learnedBuilder));
1978 }
1979
1980 d_propagatorNeedsFinish = true;
1981 return true;
1982 }
1983
1984 void SmtEnginePrivate::bvAbstraction() {
1985 Trace("bv-abstraction") << "SmtEnginePrivate::bvAbstraction()" << endl;
1986 std::vector<Node> new_assertions;
1987 bool changed = d_smt.d_theoryEngine->ppBvAbstraction(d_assertionsToPreprocess, new_assertions);
1988 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
1989 d_assertionsToPreprocess[i] = Rewriter::rewrite(new_assertions[i]);
1990 }
1991 // if we are using the lazy solver and the abstraction
1992 // applies, then UF symbols were introduced
1993 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY &&
1994 changed) {
1995 LogicRequest req(d_smt);
1996 req.widenLogic(THEORY_UF);
1997 }
1998 }
1999
2000
2001 void SmtEnginePrivate::bvToBool() {
2002 Trace("bv-to-bool") << "SmtEnginePrivate::bvToBool()" << endl;
2003 std::vector<Node> new_assertions;
2004 d_smt.d_theoryEngine->ppBvToBool(d_assertionsToPreprocess, new_assertions);
2005 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
2006 d_assertionsToPreprocess[i] = Rewriter::rewrite(new_assertions[i]);
2007 }
2008 }
2009
2010 bool SmtEnginePrivate::simpITE() {
2011 TimerStat::CodeTimer simpITETimer(d_smt.d_stats->d_simpITETime);
2012
2013 Trace("simplify") << "SmtEnginePrivate::simpITE()" << endl;
2014
2015 unsigned numAssertionOnEntry = d_assertionsToCheck.size();
2016 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++i) {
2017 Node result = d_smt.d_theoryEngine->ppSimpITE(d_assertionsToCheck[i]);
2018 d_assertionsToCheck[i] = result;
2019 if(result.isConst() && !result.getConst<bool>()){
2020 return false;
2021 }
2022 }
2023 bool result = d_smt.d_theoryEngine->donePPSimpITE(d_assertionsToCheck);
2024 if(numAssertionOnEntry < d_assertionsToCheck.size()){
2025 compressBeforeRealAssertions(numAssertionOnEntry);
2026 }
2027 return result;
2028 }
2029
2030 void SmtEnginePrivate::compressBeforeRealAssertions(size_t before){
2031 size_t curr = d_assertionsToCheck.size();
2032 if(before >= curr ||
2033 d_realAssertionsEnd <= 0 ||
2034 d_realAssertionsEnd >= curr){
2035 return;
2036 }
2037
2038 // assertions
2039 // original: [0 ... d_realAssertionsEnd)
2040 // can be modified
2041 // ites skolems [d_realAssertionsEnd, before)
2042 // cannot be moved
2043 // added [before, curr)
2044 // can be modified
2045 Assert(0 < d_realAssertionsEnd);
2046 Assert(d_realAssertionsEnd <= before);
2047 Assert(before < curr);
2048
2049 std::vector<Node> intoConjunction;
2050 for(size_t i = before; i<curr; ++i){
2051 intoConjunction.push_back(d_assertionsToCheck[i]);
2052 }
2053 d_assertionsToCheck.resize(before);
2054 size_t lastBeforeItes = d_realAssertionsEnd - 1;
2055 intoConjunction.push_back(d_assertionsToCheck[lastBeforeItes]);
2056 Node newLast = util::NaryBuilder::mkAssoc(kind::AND, intoConjunction);
2057 d_assertionsToCheck[lastBeforeItes] = newLast;
2058 Assert(d_assertionsToCheck.size() == before);
2059 }
2060
2061 void SmtEnginePrivate::unconstrainedSimp(std::vector<Node>& assertions) {
2062 TimerStat::CodeTimer unconstrainedSimpTimer(d_smt.d_stats->d_unconstrainedSimpTime);
2063 Trace("simplify") << "SmtEnginePrivate::unconstrainedSimp()" << endl;
2064 d_smt.d_theoryEngine->ppUnconstrainedSimp(assertions);
2065 }
2066
2067
2068 void SmtEnginePrivate::constrainSubtypes(TNode top, std::vector<Node>& assertions)
2069 throw() {
2070
2071 Trace("constrainSubtypes") << "constrainSubtypes(): looking at " << top << endl;
2072
2073 set<TNode> done;
2074 stack<TNode> worklist;
2075 worklist.push(top);
2076 done.insert(top);
2077
2078 do {
2079 TNode n = worklist.top();
2080 worklist.pop();
2081
2082 TypeNode t = n.getType();
2083 if(t.isPredicateSubtype()) {
2084 WarningOnce() << "Warning: CVC4 doesn't yet do checking that predicate subtypes are nonempty domains" << endl;
2085 Node pred = t.getSubtypePredicate();
2086 Kind k;
2087 // pred can be a LAMBDA, a function constant, or a datatype tester
2088 Trace("constrainSubtypes") << "constrainSubtypes(): pred.getType() == " << pred.getType() << endl;
2089 if(d_smt.d_definedFunctions->find(pred) != d_smt.d_definedFunctions->end()) {
2090 k = kind::APPLY;
2091 } else if(pred.getType().isTester()) {
2092 k = kind::APPLY_TESTER;
2093 } else {
2094 k = kind::APPLY_UF;
2095 }
2096 Node app = NodeManager::currentNM()->mkNode(k, pred, n);
2097 Trace("constrainSubtypes") << "constrainSubtypes(): assert(" << k << ") " << app << endl;
2098 assertions.push_back(app);
2099 } else if(t.isSubrange()) {
2100 SubrangeBounds bounds = t.getSubrangeBounds();
2101 Trace("constrainSubtypes") << "constrainSubtypes(): got bounds " << bounds << endl;
2102 if(bounds.lower.hasBound()) {
2103 Node c = NodeManager::currentNM()->mkConst(Rational(bounds.lower.getBound()));
2104 Node lb = NodeManager::currentNM()->mkNode(kind::LEQ, c, n);
2105 Trace("constrainSubtypes") << "constrainSubtypes(): assert " << lb << endl;
2106 assertions.push_back(lb);
2107 }
2108 if(bounds.upper.hasBound()) {
2109 Node c = NodeManager::currentNM()->mkConst(Rational(bounds.upper.getBound()));
2110 Node ub = NodeManager::currentNM()->mkNode(kind::LEQ, n, c);
2111 Trace("constrainSubtypes") << "constrainSubtypes(): assert " << ub << endl;
2112 assertions.push_back(ub);
2113 }
2114 }
2115
2116 for(TNode::iterator i = n.begin(); i != n.end(); ++i) {
2117 if(done.find(*i) == done.end()) {
2118 worklist.push(*i);
2119 done.insert(*i);
2120 }
2121 }
2122 } while(! worklist.empty());
2123 }
2124
2125 void SmtEnginePrivate::traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions) {
2126 const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
2127 for(vector<Node>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
2128 booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
2129 // term must appear in map, otherwise how did we get here?!
2130 Assert(j != backEdges.end());
2131 // if term maps to empty, that means it's a top-level assertion
2132 if(!(*j).second.empty()) {
2133 traceBackToAssertions((*j).second, assertions);
2134 } else {
2135 assertions.push_back(*i);
2136 }
2137 }
2138 }
2139
2140 size_t SmtEnginePrivate::removeFromConjunction(Node& n, const std::hash_set<unsigned long>& toRemove) {
2141 Assert(n.getKind() == kind::AND);
2142 size_t removals = 0;
2143 for(Node::iterator j = n.begin(); j != n.end(); ++j) {
2144 size_t subremovals = 0;
2145 Node sub = *j;
2146 if(toRemove.find(sub.getId()) != toRemove.end() ||
2147 (sub.getKind() == kind::AND && (subremovals = removeFromConjunction(sub, toRemove)) > 0)) {
2148 NodeBuilder<> b(kind::AND);
2149 b.append(n.begin(), j);
2150 if(subremovals > 0) {
2151 removals += subremovals;
2152 b << sub;
2153 } else {
2154 ++removals;
2155 }
2156 for(++j; j != n.end(); ++j) {
2157 if(toRemove.find((*j).getId()) != toRemove.end()) {
2158 ++removals;
2159 } else if((*j).getKind() == kind::AND) {
2160 sub = *j;
2161 if((subremovals = removeFromConjunction(sub, toRemove)) > 0) {
2162 removals += subremovals;
2163 b << sub;
2164 } else {
2165 b << *j;
2166 }
2167 } else {
2168 b << *j;
2169 }
2170 }
2171 if(b.getNumChildren() == 0) {
2172 n = d_true;
2173 b.clear();
2174 } else if(b.getNumChildren() == 1) {
2175 n = b[0];
2176 b.clear();
2177 } else {
2178 n = b;
2179 }
2180 n = Rewriter::rewrite(n);
2181 return removals;
2182 }
2183 }
2184
2185 Assert(removals == 0);
2186 return 0;
2187 }
2188
2189 void SmtEnginePrivate::doMiplibTrick() {
2190 Assert(d_assertionsToPreprocess.empty());
2191 Assert(d_realAssertionsEnd == d_assertionsToCheck.size());
2192 Assert(!options::incrementalSolving());
2193
2194 const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
2195 hash_set<unsigned long> removeAssertions;
2196
2197 NodeManager* nm = NodeManager::currentNM();
2198 Node zero = nm->mkConst(Rational(0)), one = nm->mkConst(Rational(1));
2199
2200 hash_map<TNode, Node, TNodeHashFunction> intVars;
2201 for(vector<Node>::const_iterator i = d_boolVars.begin(); i != d_boolVars.end(); ++i) {
2202 if(d_propagator.isAssigned(*i)) {
2203 Debug("miplib") << "ineligible: " << *i << " because assigned " << d_propagator.getAssignment(*i) << endl;
2204 continue;
2205 }
2206
2207 vector<TNode> assertions;
2208 booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
2209 // if not in back edges map, the bool var is unconstrained, showing up in no assertions.
2210 // if maps to an empty vector, that means the bool var was asserted itself.
2211 if(j != backEdges.end()) {
2212 if(!(*j).second.empty()) {
2213 traceBackToAssertions((*j).second, assertions);
2214 } else {
2215 assertions.push_back(*i);
2216 }
2217 }
2218 Debug("miplib") << "for " << *i << endl;
2219 bool eligible = true;
2220 map<pair<Node, Node>, uint64_t> marks;
2221 map<pair<Node, Node>, vector<Rational> > coef;
2222 map<pair<Node, Node>, vector<Rational> > checks;
2223 map<pair<Node, Node>, vector<TNode> > asserts;
2224 for(vector<TNode>::const_iterator j = assertions.begin(); j != assertions.end(); ++j) {
2225 Debug("miplib") << " found: " << *j << endl;
2226 if((*j).getKind() != kind::IMPLIES) {
2227 eligible = false;
2228 Debug("miplib") << " -- INELIGIBLE -- (not =>)" << endl;
2229 break;
2230 }
2231 Node conj = BooleanSimplification::simplify((*j)[0]);
2232 if(conj.getKind() == kind::AND && conj.getNumChildren() > 6) {
2233 eligible = false;
2234 Debug("miplib") << " -- INELIGIBLE -- (N-ary /\\ too big)" << endl;
2235 break;
2236 }
2237 if(conj.getKind() != kind::AND && !conj.isVar() && !(conj.getKind() == kind::NOT && conj[0].isVar())) {
2238 eligible = false;
2239 Debug("miplib") << " -- INELIGIBLE -- (not /\\ or literal)" << endl;
2240 break;
2241 }
2242 if((*j)[1].getKind() != kind::EQUAL ||
2243 !( ( (*j)[1][0].isVar() &&
2244 (*j)[1][1].getKind() == kind::CONST_RATIONAL ) ||
2245 ( (*j)[1][0].getKind() == kind::CONST_RATIONAL &&
2246 (*j)[1][1].isVar() ) )) {
2247 eligible = false;
2248 Debug("miplib") << " -- INELIGIBLE -- (=> (and X X) X)" << endl;
2249 break;
2250 }
2251 if(conj.getKind() == kind::AND) {
2252 vector<Node> posv;
2253 bool found_x = false;
2254 map<TNode, bool> neg;
2255 for(Node::iterator ii = conj.begin(); ii != conj.end(); ++ii) {
2256 if((*ii).isVar()) {
2257 posv.push_back(*ii);
2258 neg[*ii] = false;
2259 found_x = found_x || *i == *ii;
2260 } else if((*ii).getKind() == kind::NOT && (*ii)[0].isVar()) {
2261 posv.push_back((*ii)[0]);
2262 neg[(*ii)[0]] = true;
2263 found_x = found_x || *i == (*ii)[0];
2264 } else {
2265 eligible = false;
2266 Debug("miplib") << " -- INELIGIBLE -- (non-var: " << *ii << ")" << endl;
2267 break;
2268 }
2269 if(d_propagator.isAssigned(posv.back())) {
2270 eligible = false;
2271 Debug("miplib") << " -- INELIGIBLE -- (" << posv.back() << " asserted)" << endl;
2272 break;
2273 }
2274 }
2275 if(!eligible) {
2276 break;
2277 }
2278 if(!found_x) {
2279 eligible = false;
2280 Debug("miplib") << " --INELIGIBLE -- (couldn't find " << *i << " in conjunction)" << endl;
2281 break;
2282 }
2283 sort(posv.begin(), posv.end());
2284 const Node pos = NodeManager::currentNM()->mkNode(kind::AND, posv);
2285 const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
2286 const pair<Node, Node> pos_var(pos, var);
2287 const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
2288 uint64_t mark = 0;
2289 unsigned countneg = 0, thepos = 0;
2290 for(unsigned ii = 0; ii < pos.getNumChildren(); ++ii) {
2291 if(neg[pos[ii]]) {
2292 ++countneg;
2293 } else {
2294 thepos = ii;
2295 mark |= (0x1 << ii);
2296 }
2297 }
2298 if((marks[pos_var] & (1lu << mark)) != 0) {
2299 eligible = false;
2300 Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
2301 break;
2302 }
2303 Debug("miplib") << "mark is " << mark << " -- " << (1lu << mark) << endl;
2304 marks[pos_var] |= (1lu << mark);
2305 Debug("miplib") << "marks[" << pos << "," << var << "] now " << marks[pos_var] << endl;
2306 if(countneg == pos.getNumChildren()) {
2307 if(constant != 0) {
2308 eligible = false;
2309 Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
2310 break;
2311 }
2312 } else if(countneg == pos.getNumChildren() - 1) {
2313 Assert(coef[pos_var].size() <= 6 && thepos < 6);
2314 if(coef[pos_var].size() <= thepos) {
2315 coef[pos_var].resize(thepos + 1);
2316 }
2317 coef[pos_var][thepos] = constant;
2318 } else {
2319 if(checks[pos_var].size() <= mark) {
2320 checks[pos_var].resize(mark + 1);
2321 }
2322 checks[pos_var][mark] = constant;
2323 }
2324 asserts[pos_var].push_back(*j);
2325 } else {
2326 TNode x = conj;
2327 if(x != *i && x != (*i).notNode()) {
2328 eligible = false;
2329 Debug("miplib") << " -- INELIGIBLE -- (x not present where I expect it)" << endl;
2330 break;
2331 }
2332 const bool xneg = (x.getKind() == kind::NOT);
2333 x = xneg ? x[0] : x;
2334 Debug("miplib") << " x:" << x << " " << xneg << endl;
2335 const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
2336 const pair<Node, Node> x_var(x, var);
2337 const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
2338 unsigned mark = (xneg ? 0 : 1);
2339 if((marks[x_var] & (1u << mark)) != 0) {
2340 eligible = false;
2341 Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
2342 break;
2343 }
2344 marks[x_var] |= (1u << mark);
2345 if(xneg) {
2346 if(constant != 0) {
2347 eligible = false;
2348 Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
2349 break;
2350 }
2351 } else {
2352 Assert(coef[x_var].size() <= 6);
2353 coef[x_var].resize(6);
2354 coef[x_var][0] = constant;
2355 }
2356 asserts[x_var].push_back(*j);
2357 }
2358 }
2359 if(eligible) {
2360 for(map<pair<Node, Node>, uint64_t>::const_iterator j = marks.begin(); j != marks.end(); ++j) {
2361 const TNode pos = (*j).first.first;
2362 const TNode var = (*j).first.second;
2363 const pair<Node, Node>& pos_var = (*j).first;
2364 const uint64_t mark = (*j).second;
2365 const unsigned numVars = pos.getKind() == kind::AND ? pos.getNumChildren() : 1;
2366 uint64_t expected = (uint64_t(1) << (1 << numVars)) - 1;
2367 expected = (expected == 0) ? -1 : expected; // fix for overflow
2368 Debug("miplib") << "[" << pos << "] => " << hex << mark << " expect " << expected << dec << endl;
2369 Assert(pos.getKind() == kind::AND || pos.isVar());
2370 if(mark != expected) {
2371 Debug("miplib") << " -- INELIGIBLE " << pos << " -- (insufficiently marked, got " << mark << " for " << numVars << " vars, expected " << expected << endl;
2372 } else {
2373 if(mark != 3) { // exclude single-var case; nothing to check there
2374 uint64_t sz = (uint64_t(1) << checks[pos_var].size()) - 1;
2375 sz = (sz == 0) ? -1 : sz; // fix for overflow
2376 Assert(sz == mark, "expected size %u == mark %u", sz, mark);
2377 for(size_t k = 0; k < checks[pos_var].size(); ++k) {
2378 if((k & (k - 1)) != 0) {
2379 Rational sum = 0;
2380 Debug("miplib") << k << " => " << checks[pos_var][k] << endl;
2381 for(size_t v = 1, kk = k; kk != 0; ++v, kk >>= 1) {
2382 if((kk & 0x1) == 1) {
2383 Assert(pos.getKind() == kind::AND);
2384 Debug("miplib") << "var " << v << " : " << pos[v - 1] << " coef:" << coef[pos_var][v - 1] << endl;
2385 sum += coef[pos_var][v - 1];
2386 }
2387 }
2388 Debug("miplib") << "checkSum is " << sum << " input says " << checks[pos_var][k] << endl;
2389 if(sum != checks[pos_var][k]) {
2390 eligible = false;
2391 Debug("miplib") << " -- INELIGIBLE " << pos << " -- (nonlinear combination)" << endl;
2392 break;
2393 }
2394 } else {
2395 Assert(checks[pos_var][k] == 0, "checks[(%s,%s)][%u] should be 0, but it's %s", pos.toString().c_str(), var.toString().c_str(), k, checks[pos_var][k].toString().c_str()); // we never set for single-positive-var
2396 }
2397 }
2398 }
2399 if(!eligible) {
2400 eligible = true; // next is still eligible
2401 continue;
2402 }
2403
2404 Debug("miplib") << " -- ELIGIBLE " << *i << " , " << pos << " --" << endl;
2405 vector<Node> newVars;
2406 expr::NodeSelfIterator ii, iiend;
2407 if(pos.getKind() == kind::AND) {
2408 ii = pos.begin();
2409 iiend = pos.end();
2410 } else {
2411 ii = expr::NodeSelfIterator::self(pos);
2412 iiend = expr::NodeSelfIterator::selfEnd(pos);
2413 }
2414 for(; ii != iiend; ++ii) {
2415 Node& varRef = intVars[*ii];
2416 if(varRef.isNull()) {
2417 stringstream ss;
2418 ss << "mipvar_" << *ii;
2419 Node newVar = nm->mkSkolem(ss.str(), nm->integerType(), "a variable introduced due to scrubbing a miplib encoding", NodeManager::SKOLEM_EXACT_NAME);
2420 Node geq = Rewriter::rewrite(nm->mkNode(kind::GEQ, newVar, zero));
2421 Node leq = Rewriter::rewrite(nm->mkNode(kind::LEQ, newVar, one));
2422 d_assertionsToCheck.push_back(Rewriter::rewrite(geq.andNode(leq)));
2423 SubstitutionMap nullMap(&d_fakeContext);
2424 Theory::PPAssertStatus status CVC4_UNUSED; // just for assertions
2425 status = d_smt.d_theoryEngine->solve(geq, nullMap);
2426 Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
2427 "unexpected solution from arith's ppAssert()");
2428 Assert(nullMap.empty(),
2429 "unexpected substitution from arith's ppAssert()");
2430 status = d_smt.d_theoryEngine->solve(leq, nullMap);
2431 Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
2432 "unexpected solution from arith's ppAssert()");
2433 Assert(nullMap.empty(),
2434 "unexpected substitution from arith's ppAssert()");
2435 d_smt.d_theoryEngine->getModel()->addSubstitution(*ii, newVar.eqNode(one));
2436 newVars.push_back(newVar);
2437 varRef = newVar;
2438 } else {
2439 newVars.push_back(varRef);
2440 }
2441 if(!d_smt.d_logic.areIntegersUsed()) {
2442 d_smt.d_logic = d_smt.d_logic.getUnlockedCopy();
2443 d_smt.d_logic.enableIntegers();
2444 d_smt.d_logic.lock();
2445 }
2446 }
2447 Node sum;
2448 if(pos.getKind() == kind::AND) {
2449 NodeBuilder<> sumb(kind::PLUS);
2450 for(size_t ii = 0; ii < pos.getNumChildren(); ++ii) {
2451 sumb << nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][ii]), newVars[ii]);
2452 }
2453 sum = sumb;
2454 } else {
2455 sum = nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][0]), newVars[0]);
2456 }
2457 Debug("miplib") << "vars[] " << var << endl
2458 << " eq " << Rewriter::rewrite(sum) << endl;
2459 Node newAssertion = var.eqNode(Rewriter::rewrite(sum));
2460 if(d_topLevelSubstitutions.hasSubstitution(newAssertion[0])) {
2461 //Warning() << "RE-SUBSTITUTION " << newAssertion[0] << endl;
2462 //Warning() << "REPLACE " << newAssertion[1] << endl;
2463 //Warning() << "ORIG " << d_topLevelSubstitutions.getSubstitution(newAssertion[0]) << endl;
2464 Assert(d_topLevelSubstitutions.getSubstitution(newAssertion[0]) == newAssertion[1]);
2465 } else if(pos.getNumChildren() <= options::arithMLTrickSubstitutions()) {
2466 d_topLevelSubstitutions.addSubstitution(newAssertion[0], newAssertion[1]);
2467 Debug("miplib") << "addSubs: " << newAssertion[0] << " to " << newAssertion[1] << endl;
2468 } else {
2469 Debug("miplib") << "skipSubs: " << newAssertion[0] << " to " << newAssertion[1] << " (threshold is " << options::arithMLTrickSubstitutions() << ")" << endl;
2470 }
2471 newAssertion = Rewriter::rewrite(newAssertion);
2472 Debug("miplib") << " " << newAssertion << endl;
2473 d_assertionsToCheck.push_back(newAssertion);
2474 Debug("miplib") << " assertions to remove: " << endl;
2475 for(vector<TNode>::const_iterator k = asserts[pos_var].begin(), k_end = asserts[pos_var].end(); k != k_end; ++k) {
2476 Debug("miplib") << " " << *k << endl;
2477 removeAssertions.insert((*k).getId());
2478 }
2479 }
2480 }
2481 }
2482 }
2483 if(!removeAssertions.empty()) {
2484 Debug("miplib") << "SmtEnginePrivate::simplify(): scrubbing miplib encoding..." << endl;
2485 for(size_t i = 0; i < d_realAssertionsEnd; ++i) {
2486 if(removeAssertions.find(d_assertionsToCheck[i].getId()) != removeAssertions.end()) {
2487 Debug("miplib") << "SmtEnginePrivate::simplify(): - removing " << d_assertionsToCheck[i] << endl;
2488 d_assertionsToCheck[i] = d_true;
2489 ++d_smt.d_stats->d_numMiplibAssertionsRemoved;
2490 } else if(d_assertionsToCheck[i].getKind() == kind::AND) {
2491 size_t removals = removeFromConjunction(d_assertionsToCheck[i], removeAssertions);
2492 if(removals > 0) {
2493 Debug("miplib") << "SmtEnginePrivate::simplify(): - reduced " << d_assertionsToCheck[i] << endl;
2494 Debug("miplib") << "SmtEnginePrivate::simplify(): - by " << removals << " conjuncts" << endl;
2495 d_smt.d_stats->d_numMiplibAssertionsRemoved += removals;
2496 }
2497 }
2498 Debug("miplib") << "had: " << d_assertionsToCheck[i] << endl;
2499 d_assertionsToCheck[i] = Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertionsToCheck[i]));
2500 Debug("miplib") << "now: " << d_assertionsToCheck[i] << endl;
2501 }
2502 } else {
2503 Debug("miplib") << "SmtEnginePrivate::simplify(): miplib pass found nothing." << endl;
2504 }
2505 d_realAssertionsEnd = d_assertionsToCheck.size();
2506 }
2507
2508
2509 // returns false if simplification led to "false"
2510 bool SmtEnginePrivate::simplifyAssertions()
2511 throw(TypeCheckingException, LogicException) {
2512 Assert(d_smt.d_pendingPops == 0);
2513 try {
2514 ScopeCounter depth(d_simplifyAssertionsDepth);
2515
2516 Trace("simplify") << "SmtEnginePrivate::simplify()" << endl;
2517
2518 if(options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
2519 // Perform non-clausal simplification
2520 Chat() << "...performing nonclausal simplification..." << endl;
2521 Trace("simplify") << "SmtEnginePrivate::simplify(): "
2522 << "performing non-clausal simplification" << endl;
2523 bool noConflict = nonClausalSimplify();
2524 if(!noConflict) {
2525 return false;
2526 }
2527
2528 // We piggy-back off of the BackEdgesMap in the CircuitPropagator to
2529 // do the miplib trick.
2530 if( // check that option is on
2531 options::arithMLTrick() &&
2532 // miplib rewrites aren't safe in incremental mode
2533 ! options::incrementalSolving() &&
2534 // only useful in arith
2535 d_smt.d_logic.isTheoryEnabled(THEORY_ARITH) &&
2536 // we add new assertions and need this (in practice, this
2537 // restriction only disables miplib processing during
2538 // re-simplification, which we don't expect to be useful anyway)
2539 d_realAssertionsEnd == d_assertionsToCheck.size() ) {
2540 Chat() << "...fixing miplib encodings..." << endl;
2541 Trace("simplify") << "SmtEnginePrivate::simplify(): "
2542 << "looking for miplib pseudobooleans..." << endl;
2543
2544 TimerStat::CodeTimer miplibTimer(d_smt.d_stats->d_miplibPassTime);
2545
2546 doMiplibTrick();
2547 } else {
2548 Trace("simplify") << "SmtEnginePrivate::simplify(): "
2549 << "skipping miplib pseudobooleans pass (either incrementalSolving is on, or miplib pbs are turned off)..." << endl;
2550 }
2551 } else {
2552 Assert(d_assertionsToCheck.empty());
2553 d_assertionsToCheck.swap(d_assertionsToPreprocess);
2554 }
2555
2556 dumpAssertions("post-nonclausal", d_assertionsToCheck);
2557 Trace("smt") << "POST nonClausalSimplify" << endl;
2558 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2559 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2560
2561 // before ppRewrite check if only core theory for BV theory
2562 d_smt.d_theoryEngine->staticInitializeBVOptions(d_assertionsToCheck);
2563
2564 // Theory preprocessing
2565 if (d_smt.d_earlyTheoryPP) {
2566 Chat() << "...doing early theory preprocessing..." << endl;
2567 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
2568 // Call the theory preprocessors
2569 d_smt.d_theoryEngine->preprocessStart();
2570 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
2571 Assert(Rewriter::rewrite(d_assertionsToCheck[i]) == d_assertionsToCheck[i]);
2572 d_assertionsToCheck[i] = d_smt.d_theoryEngine->preprocess(d_assertionsToCheck[i]);
2573 Assert(Rewriter::rewrite(d_assertionsToCheck[i]) == d_assertionsToCheck[i]);
2574 }
2575 }
2576
2577 dumpAssertions("post-theorypp", d_assertionsToCheck);
2578 Trace("smt") << "POST theoryPP" << endl;
2579 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2580 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2581
2582 // ITE simplification
2583 if(options::doITESimp() &&
2584 (d_simplifyAssertionsDepth <= 1 || options::doITESimpOnRepeat())) {
2585 Chat() << "...doing ITE simplification..." << endl;
2586 bool noConflict = simpITE();
2587 if(!noConflict){
2588 Chat() << "...ITE simplification found unsat..." << endl;
2589 return false;
2590 }
2591 }
2592
2593 dumpAssertions("post-itesimp", d_assertionsToCheck);
2594 Trace("smt") << "POST iteSimp" << endl;
2595 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2596 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2597
2598 // Unconstrained simplification
2599 if(options::unconstrainedSimp()) {
2600 Chat() << "...doing unconstrained simplification..." << endl;
2601 unconstrainedSimp(d_assertionsToCheck);
2602 }
2603
2604 dumpAssertions("post-unconstrained", d_assertionsToCheck);
2605 Trace("smt") << "POST unconstrainedSimp" << endl;
2606 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2607 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2608
2609 if(options::repeatSimp() && options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
2610 Chat() << "...doing another round of nonclausal simplification..." << endl;
2611 Trace("simplify") << "SmtEnginePrivate::simplify(): "
2612 << " doing repeated simplification" << endl;
2613 d_assertionsToCheck.swap(d_assertionsToPreprocess);
2614 Assert(d_assertionsToCheck.empty());
2615 bool noConflict = nonClausalSimplify();
2616 if(!noConflict) {
2617 return false;
2618 }
2619 }
2620
2621 dumpAssertions("post-repeatsimp", d_assertionsToCheck);
2622 Trace("smt") << "POST repeatSimp" << endl;
2623 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2624 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2625
2626 } catch(TypeCheckingExceptionPrivate& tcep) {
2627 // Calls to this function should have already weeded out any
2628 // typechecking exceptions via (e.g.) ensureBoolean(). But a
2629 // theory could still create a new expression that isn't
2630 // well-typed, and we don't want the C++ runtime to abort our
2631 // process without any error notice.
2632 stringstream ss;
2633 ss << "A bad expression was produced. Original exception follows:\n"
2634 << tcep;
2635 InternalError(ss.str().c_str());
2636 }
2637 return true;
2638 }
2639
2640 Result SmtEngine::check() {
2641 Assert(d_fullyInited);
2642 Assert(d_pendingPops == 0);
2643
2644 Trace("smt") << "SmtEngine::check()" << endl;
2645
2646 // Make sure the prop layer has all of the assertions
2647 Trace("smt") << "SmtEngine::check(): processing assertions" << endl;
2648 d_private->processAssertions();
2649
2650 // Turn off stop only for QF_LRA
2651 // TODO: Bring up in a meeting where to put this
2652 if(options::decisionStopOnly() && !options::decisionMode.wasSetByUser() ){
2653 if( // QF_LRA
2654 (not d_logic.isQuantified() &&
2655 d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areIntegersUsed()
2656 )){
2657 if(d_private->d_iteSkolemMap.empty()){
2658 options::decisionStopOnly.set(false);
2659 d_decisionEngine->clearStrategies();
2660 Trace("smt") << "SmtEngine::check(): turning off stop only" << endl;
2661 }
2662 }
2663 }
2664
2665 unsigned long millis = 0;
2666 if(d_timeBudgetCumulative != 0) {
2667 millis = getTimeRemaining();
2668 if(millis == 0) {
2669 return Result(Result::VALIDITY_UNKNOWN, Result::TIMEOUT, d_filename);
2670 }
2671 }
2672 if(d_timeBudgetPerCall != 0 && (millis == 0 || d_timeBudgetPerCall < millis)) {
2673 millis = d_timeBudgetPerCall;
2674 }
2675
2676 unsigned long resource = 0;
2677 if(d_resourceBudgetCumulative != 0) {
2678 resource = getResourceRemaining();
2679 if(resource == 0) {
2680 return Result(Result::VALIDITY_UNKNOWN, Result::RESOURCEOUT, d_filename);
2681 }
2682 }
2683 if(d_resourceBudgetPerCall != 0 && (resource == 0 || d_resourceBudgetPerCall < resource)) {
2684 resource = d_resourceBudgetPerCall;
2685 }
2686
2687 TimerStat::CodeTimer solveTimer(d_stats->d_solveTime);
2688
2689 Chat() << "solving..." << endl;
2690 Trace("smt") << "SmtEngine::check(): running check" << endl;
2691 Result result = d_propEngine->checkSat(millis, resource);
2692
2693 // PropEngine::checkSat() returns the actual amount used in these
2694 // variables.
2695 d_cumulativeTimeUsed += millis;
2696 d_cumulativeResourceUsed += resource;
2697
2698 Trace("limit") << "SmtEngine::check(): cumulative millis " << d_cumulativeTimeUsed
2699 << ", conflicts " << d_cumulativeResourceUsed << endl;
2700
2701 return Result(result, d_filename);
2702 }
2703
2704 Result SmtEngine::quickCheck() {
2705 Assert(d_fullyInited);
2706 Trace("smt") << "SMT quickCheck()" << endl;
2707 return Result(Result::VALIDITY_UNKNOWN, Result::REQUIRES_FULL_CHECK, d_filename);
2708 }
2709
2710
2711 void SmtEnginePrivate::collectSkolems(TNode n, set<TNode>& skolemSet, hash_map<Node, bool, NodeHashFunction>& cache)
2712 {
2713 hash_map<Node, bool, NodeHashFunction>::iterator it;
2714 it = cache.find(n);
2715 if (it != cache.end()) {
2716 return;
2717 }
2718
2719 size_t sz = n.getNumChildren();
2720 if (sz == 0) {
2721 IteSkolemMap::iterator it = d_iteSkolemMap.find(n);
2722 if (it != d_iteSkolemMap.end()) {
2723 skolemSet.insert(n);
2724 }
2725 cache[n] = true;
2726 return;
2727 }
2728
2729 size_t k = 0;
2730 for (; k < sz; ++k) {
2731 collectSkolems(n[k], skolemSet, cache);
2732 }
2733 cache[n] = true;
2734 }
2735
2736
2737 bool SmtEnginePrivate::checkForBadSkolems(TNode n, TNode skolem, hash_map<Node, bool, NodeHashFunction>& cache)
2738 {
2739 hash_map<Node, bool, NodeHashFunction>::iterator it;
2740 it = cache.find(n);
2741 if (it != cache.end()) {
2742 return (*it).second;
2743 }
2744
2745 size_t sz = n.getNumChildren();
2746 if (sz == 0) {
2747 IteSkolemMap::iterator it = d_iteSkolemMap.find(n);
2748 bool bad = false;
2749 if (it != d_iteSkolemMap.end()) {
2750 if (!((*it).first < n)) {
2751 bad = true;
2752 }
2753 }
2754 cache[n] = bad;
2755 return bad;
2756 }
2757
2758 size_t k = 0;
2759 for (; k < sz; ++k) {
2760 if (checkForBadSkolems(n[k], skolem, cache)) {
2761 cache[n] = true;
2762 return true;
2763 }
2764 }
2765
2766 cache[n] = false;
2767 return false;
2768 }
2769
2770 Node SmtEnginePrivate::rewriteBooleanTerms(TNode n) {
2771 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_rewriteBooleanTermsTime);
2772 if(d_booleanTermConverter == NULL) {
2773 // This needs to be initialized _after_ the whole SMT framework is in place, subscribed
2774 // to ExprManager notifications, etc. Otherwise we might miss the "BooleanTerm" datatype
2775 // definition, and not dump it properly.
2776 d_booleanTermConverter = new BooleanTermConverter(d_smt);
2777 }
2778 Node retval = d_booleanTermConverter->rewriteBooleanTerms(n);
2779 if(retval != n) {
2780 switch(booleans::BooleanTermConversionMode mode = options::booleanTermConversionMode()) {
2781 case booleans::BOOLEAN_TERM_CONVERT_TO_BITVECTORS:
2782 case booleans::BOOLEAN_TERM_CONVERT_NATIVE:
2783 if(!d_smt.d_logic.isTheoryEnabled(THEORY_BV)) {
2784 d_smt.d_logic = d_smt.d_logic.getUnlockedCopy();
2785 d_smt.d_logic.enableTheory(THEORY_BV);
2786 d_smt.d_logic.lock();
2787 }
2788 break;
2789 case booleans::BOOLEAN_TERM_CONVERT_TO_DATATYPES:
2790 if(!d_smt.d_logic.isTheoryEnabled(THEORY_DATATYPES)) {
2791 d_smt.d_logic = d_smt.d_logic.getUnlockedCopy();
2792 d_smt.d_logic.enableTheory(THEORY_DATATYPES);
2793 d_smt.d_logic.lock();
2794 }
2795 break;
2796 default:
2797 Unhandled(mode);
2798 }
2799 }
2800 return retval;
2801 }
2802
2803 void SmtEnginePrivate::processAssertions() {
2804 TimerStat::CodeTimer paTimer(d_smt.d_stats->d_processAssertionsTime);
2805
2806 Assert(d_smt.d_fullyInited);
2807 Assert(d_smt.d_pendingPops == 0);
2808
2809 // Dump the assertions
2810 dumpAssertions("pre-everything", d_assertionsToPreprocess);
2811
2812 Trace("smt") << "SmtEnginePrivate::processAssertions()" << endl;
2813
2814 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2815 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2816
2817 Assert(d_assertionsToCheck.size() == 0);
2818
2819 if (d_assertionsToPreprocess.size() == 0) {
2820 // nothing to do
2821 return;
2822 }
2823
2824 if (d_assertionsProcessed &&
2825 ( options::incrementalSolving() ||
2826 options::simplificationMode() == SIMPLIFICATION_MODE_INCREMENTAL )) {
2827 // Placeholder for storing substitutions
2828 d_substitutionsIndex = d_assertionsToPreprocess.size();
2829 d_assertionsToPreprocess.push_back(NodeManager::currentNM()->mkConst<bool>(true));
2830 }
2831
2832 // Add dummy assertion in last position - to be used as a
2833 // placeholder for any new assertions to get added
2834 d_assertionsToPreprocess.push_back(NodeManager::currentNM()->mkConst<bool>(true));
2835 // any assertions added beyond realAssertionsEnd must NOT affect the
2836 // equisatisfiability
2837 d_realAssertionsEnd = d_assertionsToPreprocess.size();
2838
2839 // Assertions are NOT guaranteed to be rewritten by this point
2840
2841 dumpAssertions("pre-definition-expansion", d_assertionsToPreprocess);
2842 {
2843 Chat() << "expanding definitions..." << endl;
2844 Trace("simplify") << "SmtEnginePrivate::simplify(): expanding definitions" << endl;
2845 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_definitionExpansionTime);
2846 hash_map<Node, Node, NodeHashFunction> cache;
2847 for(unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
2848 d_assertionsToPreprocess[i] =
2849 expandDefinitions(d_assertionsToPreprocess[i], cache);
2850 }
2851 }
2852 dumpAssertions("post-definition-expansion", d_assertionsToPreprocess);
2853
2854 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2855 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2856
2857 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
2858 !d_smt.d_logic.isPure(THEORY_BV)) {
2859 throw ModalException("Eager bit-blasting does not currently support theory combination. "
2860 "Note that in a QF_BV problem UF symbols can be introduced for division. "
2861 "Try --bv-div-zero-const to interpret division by zero as a constant.");
2862 }
2863
2864 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
2865 d_smt.d_theoryEngine->mkAckermanizationAsssertions(d_assertionsToPreprocess);
2866 }
2867
2868 if ( options::bvAbstraction() &&
2869 !options::incrementalSolving()) {
2870 dumpAssertions("pre-bv-abstraction", d_assertionsToPreprocess);
2871 bvAbstraction();
2872 dumpAssertions("post-bv-abstraction", d_assertionsToPreprocess);
2873 }
2874
2875 dumpAssertions("pre-boolean-terms", d_assertionsToPreprocess);
2876 {
2877 Chat() << "rewriting Boolean terms..." << endl;
2878 for(unsigned i = 0, i_end = d_assertionsToPreprocess.size(); i != i_end; ++i) {
2879 d_assertionsToPreprocess[i] = rewriteBooleanTerms(d_assertionsToPreprocess[i]);
2880 }
2881 }
2882 dumpAssertions("post-boolean-terms", d_assertionsToPreprocess);
2883
2884 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2885 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2886
2887 dumpAssertions("pre-constrain-subtypes", d_assertionsToPreprocess);
2888 {
2889 // Any variables of subtype types need to be constrained properly.
2890 // Careful, here: constrainSubtypes() adds to the back of
2891 // d_assertionsToPreprocess, but we don't need to reprocess those.
2892 // We also can't use an iterator, because the vector may be moved in
2893 // memory during this loop.
2894 Chat() << "constraining subtypes..." << endl;
2895 for(unsigned i = 0, i_end = d_assertionsToPreprocess.size(); i != i_end; ++i) {
2896 constrainSubtypes(d_assertionsToPreprocess[i], d_assertionsToPreprocess);
2897 }
2898 }
2899 dumpAssertions("post-constrain-subtypes", d_assertionsToPreprocess);
2900
2901 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
2902 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
2903
2904
2905 // Unconstrained simplification
2906 if(options::unconstrainedSimp()) {
2907 dumpAssertions("pre-unconstrained-simp", d_assertionsToPreprocess);
2908 Chat() << "...doing unconstrained simplification..." << endl;
2909 unconstrainedSimp(d_assertionsToPreprocess);
2910 dumpAssertions("post-unconstrained-simp", d_assertionsToPreprocess);
2911 }
2912
2913 if(options::bvIntroducePow2()){
2914 theory::bv::BVIntroducePow2::pow2Rewrite(d_assertionsToPreprocess);
2915 }
2916
2917 dumpAssertions("pre-substitution", d_assertionsToPreprocess);
2918
2919 // Apply the substitutions we already have, and normalize
2920 Chat() << "applying substitutions..." << endl;
2921 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2922 << "applying substitutions" << endl;
2923 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
2924 Trace("simplify") << "applying to " << d_assertionsToPreprocess[i] << endl;
2925 d_assertionsToPreprocess[i] =
2926 Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertionsToPreprocess[i]));
2927 Trace("simplify") << " got " << d_assertionsToPreprocess[i] << endl;
2928 }
2929 dumpAssertions("post-substitution", d_assertionsToPreprocess);
2930
2931 // Assertions ARE guaranteed to be rewritten by this point
2932
2933
2934 // Lift bit-vectors of size 1 to bool
2935 if(options::bitvectorToBool()) {
2936 dumpAssertions("pre-bv-to-bool", d_assertionsToPreprocess);
2937 Chat() << "...doing bvToBool..." << endl;
2938 bvToBool();
2939 dumpAssertions("post-bv-to-bool", d_assertionsToPreprocess);
2940 }
2941
2942 if( d_smt.d_logic.isTheoryEnabled(THEORY_STRINGS) ) {
2943 dumpAssertions("pre-strings-pp", d_assertionsToPreprocess);
2944 CVC4::theory::strings::StringsPreprocess sp;
2945 std::vector<Node> newNodes;
2946 newNodes.push_back(d_assertionsToPreprocess[d_realAssertionsEnd - 1]);
2947 sp.simplify( d_assertionsToPreprocess, newNodes );
2948 if(newNodes.size() > 1) {
2949 d_assertionsToPreprocess[d_realAssertionsEnd - 1] = NodeManager::currentNM()->mkNode(kind::AND, newNodes);
2950 }
2951 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
2952 d_assertionsToPreprocess[i] = Rewriter::rewrite( d_assertionsToPreprocess[i] );
2953 }
2954 dumpAssertions("post-strings-pp", d_assertionsToPreprocess);
2955 }
2956 if( d_smt.d_logic.isQuantified() ){
2957 //remove rewrite rules
2958 for( unsigned i=0; i < d_assertionsToPreprocess.size(); i++ ) {
2959 if( d_assertionsToPreprocess[i].getKind() == kind::REWRITE_RULE ){
2960 Node prev = d_assertionsToPreprocess[i];
2961 Trace("quantifiers-rewrite-debug") << "Rewrite rewrite rule " << prev << "..." << std::endl;
2962 d_assertionsToPreprocess[i] = Rewriter::rewrite( quantifiers::QuantifiersRewriter::rewriteRewriteRule( d_assertionsToPreprocess[i] ) );
2963 Trace("quantifiers-rewrite") << "*** rr-rewrite " << prev << endl;
2964 Trace("quantifiers-rewrite") << " ...got " << d_assertionsToPreprocess[i] << endl;
2965 }
2966 }
2967
2968 dumpAssertions("pre-skolem-quant", d_assertionsToPreprocess);
2969 if( options::preSkolemQuant() ){
2970 //apply pre-skolemization to existential quantifiers
2971 for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
2972 Node prev = d_assertionsToPreprocess[i];
2973 Trace("quantifiers-rewrite-debug") << "Pre-skolemize " << prev << "..." << std::endl;
2974 vector< TypeNode > fvTypes;
2975 vector< TNode > fvs;
2976 d_assertionsToPreprocess[i] = quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
2977 if( prev!=d_assertionsToPreprocess[i] ){
2978 d_assertionsToPreprocess[i] = Rewriter::rewrite( d_assertionsToPreprocess[i] );
2979 Trace("quantifiers-rewrite") << "*** Pre-skolemize " << prev << endl;
2980 Trace("quantifiers-rewrite") << " ...got " << d_assertionsToPreprocess[i] << endl;
2981 }
2982 }
2983 }
2984 dumpAssertions("post-skolem-quant", d_assertionsToPreprocess);
2985 if( options::macrosQuant() ){
2986 //quantifiers macro expansion
2987 bool success;
2988 do{
2989 quantifiers::QuantifierMacros qm;
2990 success = qm.simplify( d_assertionsToPreprocess, true );
2991 }while( success );
2992 }
2993
2994 Trace("fo-rsn-enable") << std::endl;
2995 if( options::foPropQuant() ){
2996 quantifiers::FirstOrderPropagation fop;
2997 fop.simplify( d_assertionsToPreprocess );
2998 }
2999 }
3000
3001 if( options::sortInference() ){
3002 //sort inference technique
3003 SortInference * si = d_smt.d_theoryEngine->getSortInference();
3004 si->simplify( d_assertionsToPreprocess );
3005 for( std::map< Node, Node >::iterator it = si->d_model_replace_f.begin(); it != si->d_model_replace_f.end(); ++it ){
3006 d_smt.setPrintFuncInModel( it->first.toExpr(), false );
3007 d_smt.setPrintFuncInModel( it->second.toExpr(), true );
3008 }
3009 }
3010
3011 //if( options::quantConflictFind() ){
3012 // d_smt.d_theoryEngine->getQuantConflictFind()->registerAssertions( d_assertionsToPreprocess );
3013 //}
3014
3015 if( options::pbRewrites() ){
3016 d_pbsProcessor.learn(d_assertionsToPreprocess);
3017 if(d_pbsProcessor.likelyToHelp()){
3018 d_pbsProcessor.applyReplacements(d_assertionsToPreprocess);
3019 }
3020 }
3021
3022 dumpAssertions("pre-simplify", d_assertionsToPreprocess);
3023 Chat() << "simplifying assertions..." << endl;
3024 bool noConflict = simplifyAssertions();
3025 if(!noConflict){
3026 ++(d_smt.d_stats->d_simplifiedToFalse);
3027 }
3028 dumpAssertions("post-simplify", d_assertionsToCheck);
3029
3030 dumpAssertions("pre-static-learning", d_assertionsToCheck);
3031 if(options::doStaticLearning()) {
3032 // Perform static learning
3033 Chat() << "doing static learning..." << endl;
3034 Trace("simplify") << "SmtEnginePrivate::simplify(): "
3035 << "performing static learning" << endl;
3036 staticLearning();
3037 }
3038 dumpAssertions("post-static-learning", d_assertionsToCheck);
3039
3040 Trace("smt") << "POST bvToBool" << endl;
3041 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
3042 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
3043
3044
3045 dumpAssertions("pre-ite-removal", d_assertionsToCheck);
3046 {
3047 Chat() << "removing term ITEs..." << endl;
3048 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_iteRemovalTime);
3049 // Remove ITEs, updating d_iteSkolemMap
3050 d_smt.d_stats->d_numAssertionsPre += d_assertionsToCheck.size();
3051 removeITEs();
3052 d_smt.d_stats->d_numAssertionsPost += d_assertionsToCheck.size();
3053 }
3054 dumpAssertions("post-ite-removal", d_assertionsToCheck);
3055
3056 dumpAssertions("pre-repeat-simplify", d_assertionsToCheck);
3057 if(options::repeatSimp()) {
3058 d_assertionsToCheck.swap(d_assertionsToPreprocess);
3059 Chat() << "re-simplifying assertions..." << endl;
3060 ScopeCounter depth(d_simplifyAssertionsDepth);
3061 noConflict &= simplifyAssertions();
3062 if (noConflict) {
3063 // Need to fix up assertion list to maintain invariants:
3064 // Let Sk be the set of Skolem variables introduced by ITE's. Let <_sk be the order in which these variables were introduced
3065 // during ite removal.
3066 // For each skolem variable sk, let iteExpr = iteMap(sk) be the ite expr mapped to by sk.
3067
3068 // cache for expression traversal
3069 hash_map<Node, bool, NodeHashFunction> cache;
3070
3071 // First, find all skolems that appear in the substitution map - their associated iteExpr will need
3072 // to be moved to the main assertion set
3073 set<TNode> skolemSet;
3074 SubstitutionMap::iterator pos = d_topLevelSubstitutions.begin();
3075 for (; pos != d_topLevelSubstitutions.end(); ++pos) {
3076 collectSkolems((*pos).first, skolemSet, cache);
3077 collectSkolems((*pos).second, skolemSet, cache);
3078 }
3079
3080 // We need to ensure:
3081 // 1. iteExpr has the form (ite cond (sk = t) (sk = e))
3082 // 2. if some sk' in Sk appears in cond, t, or e, then sk' <_sk sk
3083 // If either of these is violated, we must add iteExpr as a proper assertion
3084 IteSkolemMap::iterator it = d_iteSkolemMap.begin();
3085 IteSkolemMap::iterator iend = d_iteSkolemMap.end();
3086 NodeBuilder<> builder(kind::AND);
3087 builder << d_assertionsToCheck[d_realAssertionsEnd - 1];
3088 vector<TNode> toErase;
3089 for (; it != iend; ++it) {
3090 if (skolemSet.find((*it).first) == skolemSet.end()) {
3091 TNode iteExpr = d_assertionsToCheck[(*it).second];
3092 if (iteExpr.getKind() == kind::ITE &&
3093 iteExpr[1].getKind() == kind::EQUAL &&
3094 iteExpr[1][0] == (*it).first &&
3095 iteExpr[2].getKind() == kind::EQUAL &&
3096 iteExpr[2][0] == (*it).first) {
3097 cache.clear();
3098 bool bad = checkForBadSkolems(iteExpr[0], (*it).first, cache);
3099 bad = bad || checkForBadSkolems(iteExpr[1][1], (*it).first, cache);
3100 bad = bad || checkForBadSkolems(iteExpr[2][1], (*it).first, cache);
3101 if (!bad) {
3102 continue;
3103 }
3104 }
3105 }
3106 // Move this iteExpr into the main assertions
3107 builder << d_assertionsToCheck[(*it).second];
3108 d_assertionsToCheck[(*it).second] = NodeManager::currentNM()->mkConst<bool>(true);
3109 toErase.push_back((*it).first);
3110 }
3111 if(builder.getNumChildren() > 1) {
3112 while (!toErase.empty()) {
3113 d_iteSkolemMap.erase(toErase.back());
3114 toErase.pop_back();
3115 }
3116 d_assertionsToCheck[d_realAssertionsEnd - 1] =
3117 Rewriter::rewrite(Node(builder));
3118 }
3119 // For some reason this is needed for some benchmarks, such as
3120 // http://cvc4.cs.nyu.edu/benchmarks/smtlib2/QF_AUFBV/dwp_formulas/try5_small_difret_functions_dwp_tac.re_node_set_remove_at.il.dwp.smt2
3121 // Figure it out later
3122 removeITEs();
3123 // Assert(iteRewriteAssertionsEnd == d_assertionsToCheck.size());
3124 }
3125 }
3126 dumpAssertions("post-repeat-simplify", d_assertionsToCheck);
3127
3128 dumpAssertions("pre-rewrite-apply-to-const", d_assertionsToCheck);
3129 if(options::rewriteApplyToConst()) {
3130 Chat() << "Rewriting applies to constants..." << endl;
3131 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
3132 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
3133 d_assertionsToCheck[i] = Rewriter::rewrite(rewriteApplyToConst(d_assertionsToCheck[i]));
3134 }
3135 }
3136 dumpAssertions("post-rewrite-apply-to-const", d_assertionsToCheck);
3137
3138 // begin: INVARIANT to maintain: no reordering of assertions or
3139 // introducing new ones
3140 #ifdef CVC4_ASSERTIONS
3141 unsigned iteRewriteAssertionsEnd = d_assertionsToCheck.size();
3142 #endif
3143
3144 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
3145 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
3146
3147 Debug("smt") << "SmtEnginePrivate::processAssertions() POST SIMPLIFICATION" << endl;
3148 Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
3149 Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
3150
3151 dumpAssertions("pre-theory-preprocessing", d_assertionsToCheck);
3152 {
3153 Chat() << "theory preprocessing..." << endl;
3154 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
3155 // Call the theory preprocessors
3156 d_smt.d_theoryEngine->preprocessStart();
3157 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
3158 d_assertionsToCheck[i] = d_smt.d_theoryEngine->preprocess(d_assertionsToCheck[i]);
3159 }
3160 }
3161 dumpAssertions("post-theory-preprocessing", d_assertionsToCheck);
3162
3163 // If we are using eager bit-blasting wrap assertions in fake atom so that
3164 // everything gets bit-blasted to internal SAT solver
3165 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
3166 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++i) {
3167 TNode atom = d_assertionsToCheck[i];
3168 Node eager_atom = NodeManager::currentNM()->mkNode(kind::BITVECTOR_EAGER_ATOM, atom);
3169 d_assertionsToCheck[i] = eager_atom;
3170 TheoryModel* m = d_smt.d_theoryEngine->getModel();
3171 m->addSubstitution(eager_atom, atom);
3172 }
3173 }
3174
3175 // Push the formula to decision engine
3176 if(noConflict) {
3177 Chat() << "pushing to decision engine..." << endl;
3178 Assert(iteRewriteAssertionsEnd == d_assertionsToCheck.size());
3179 d_smt.d_decisionEngine->addAssertions
3180 (d_assertionsToCheck, d_realAssertionsEnd, d_iteSkolemMap);
3181 }
3182
3183 // end: INVARIANT to maintain: no reordering of assertions or
3184 // introducing new ones
3185
3186 dumpAssertions("post-everything", d_assertionsToCheck);
3187
3188 // Push the formula to SAT
3189 {
3190 Chat() << "converting to CNF..." << endl;
3191 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_cnfConversionTime);
3192 for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
3193 d_smt.d_propEngine->assertFormula(d_assertionsToCheck[i]);
3194 }
3195 }
3196
3197 d_assertionsProcessed = true;
3198
3199 d_assertionsToCheck.clear();
3200 d_iteSkolemMap.clear();
3201 }
3202
3203 void SmtEnginePrivate::addFormula(TNode n)
3204 throw(TypeCheckingException, LogicException) {
3205
3206 if (n == d_true) {
3207 // nothing to do
3208 return;
3209 }
3210
3211 Trace("smt") << "SmtEnginePrivate::addFormula(" << n << ")" << endl;
3212
3213 // Add the normalized formula to the queue
3214 d_assertionsToPreprocess.push_back(n);
3215 //d_assertionsToPreprocess.push_back(Rewriter::rewrite(n));
3216
3217 // If the mode of processing is incremental prepreocess and assert immediately
3218 if (options::simplificationMode() == SIMPLIFICATION_MODE_INCREMENTAL) {
3219 processAssertions();
3220 }
3221 }
3222
3223 void SmtEngine::ensureBoolean(const Expr& e) throw(TypeCheckingException) {
3224 Type type = e.getType(options::typeChecking());
3225 Type boolType = d_exprManager->booleanType();
3226 if(type != boolType) {
3227 stringstream ss;
3228 ss << "Expected " << boolType << "\n"
3229 << "The assertion : " << e << "\n"
3230 << "Its type : " << type;
3231 throw TypeCheckingException(e, ss.str());
3232 }
3233 }
3234
3235 Result SmtEngine::checkSat(const Expr& ex) throw(TypeCheckingException, ModalException, LogicException) {
3236 Assert(ex.isNull() || ex.getExprManager() == d_exprManager);
3237 SmtScope smts(this);
3238 finalOptionsAreSet();
3239 doPendingPops();
3240
3241 Trace("smt") << "SmtEngine::checkSat(" << ex << ")" << endl;
3242
3243 if(d_queryMade && !options::incrementalSolving()) {
3244 throw ModalException("Cannot make multiple queries unless "
3245 "incremental solving is enabled "
3246 "(try --incremental)");
3247 }
3248
3249 Expr e;
3250 if(!ex.isNull()) {
3251 // Substitute out any abstract values in ex.
3252 e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3253 // Ensure expr is type-checked at this point.
3254 ensureBoolean(e);
3255 // Give it to proof manager
3256 PROOF( ProofManager::currentPM()->addAssertion(e); );
3257 }
3258
3259 // check to see if a postsolve() is pending
3260 if(d_needPostsolve) {
3261 d_theoryEngine->postsolve();
3262 d_needPostsolve = false;
3263 }
3264
3265 // Push the context
3266 internalPush();
3267
3268 // Note that a query has been made
3269 d_queryMade = true;
3270
3271 // Add the formula
3272 if(!e.isNull()) {
3273 d_problemExtended = true;
3274 if(d_assertionList != NULL) {
3275 d_assertionList->push_back(e);
3276 }
3277 d_private->addFormula(e.getNode());
3278 }
3279
3280 // Run the check
3281 Result r = check().asSatisfiabilityResult();
3282 d_needPostsolve = true;
3283
3284 // Dump the query if requested
3285 if(Dump.isOn("benchmark")) {
3286 // the expr already got dumped out if assertion-dumping is on
3287 Dump("benchmark") << CheckSatCommand();
3288 }
3289
3290 // Pop the context
3291 internalPop();
3292
3293 // Remember the status
3294 d_status = r;
3295
3296 d_problemExtended = false;
3297
3298 Trace("smt") << "SmtEngine::checkSat(" << e << ") => " << r << endl;
3299
3300 // Check that SAT results generate a model correctly.
3301 if(options::checkModels()) {
3302 if(r.asSatisfiabilityResult().isSat() == Result::SAT ||
3303 (r.isUnknown() && r.whyUnknown() == Result::INCOMPLETE) ){
3304 checkModel(/* hard failure iff */ ! r.isUnknown());
3305 }
3306 }
3307 // Check that UNSAT results generate a proof correctly.
3308 if(options::checkProofs()) {
3309 if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
3310 TimerStat::CodeTimer checkProofTimer(d_stats->d_checkProofTime);
3311 checkProof();
3312 }
3313 }
3314
3315 return r;
3316 }/* SmtEngine::checkSat() */
3317
3318 Result SmtEngine::query(const Expr& ex) throw(TypeCheckingException, ModalException, LogicException) {
3319 Assert(!ex.isNull());
3320 Assert(ex.getExprManager() == d_exprManager);
3321 SmtScope smts(this);
3322 finalOptionsAreSet();
3323 doPendingPops();
3324 Trace("smt") << "SMT query(" << ex << ")" << endl;
3325
3326 if(d_queryMade && !options::incrementalSolving()) {
3327 throw ModalException("Cannot make multiple queries unless "
3328 "incremental solving is enabled "
3329 "(try --incremental)");
3330 }
3331
3332 // Substitute out any abstract values in ex
3333 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3334 // Ensure that the expression is type-checked at this point, and Boolean
3335 ensureBoolean(e);
3336 // Give it to proof manager
3337 PROOF( ProofManager::currentPM()->addAssertion(e.notExpr()); );
3338
3339 // check to see if a postsolve() is pending
3340 if(d_needPostsolve) {
3341 d_theoryEngine->postsolve();
3342 d_needPostsolve = false;
3343 }
3344
3345 // Push the context
3346 internalPush();
3347
3348 // Note that a query has been made
3349 d_queryMade = true;
3350
3351 // Add the formula
3352 d_problemExtended = true;
3353 if(d_assertionList != NULL) {
3354 d_assertionList->push_back(e.notExpr());
3355 }
3356 d_private->addFormula(e.getNode().notNode());
3357
3358 // Run the check
3359 Result r = check().asValidityResult();
3360 d_needPostsolve = true;
3361
3362 // Dump the query if requested
3363 if(Dump.isOn("benchmark")) {
3364 // the expr already got dumped out if assertion-dumping is on
3365 Dump("benchmark") << CheckSatCommand();
3366 }
3367
3368 // Pop the context
3369 internalPop();
3370
3371 // Remember the status
3372 d_status = r;
3373
3374 d_problemExtended = false;
3375
3376 Trace("smt") << "SMT query(" << e << ") ==> " << r << endl;
3377
3378 // Check that SAT results generate a model correctly.
3379 if(options::checkModels()) {
3380 if(r.asSatisfiabilityResult().isSat() == Result::SAT ||
3381 (r.isUnknown() && r.whyUnknown() == Result::INCOMPLETE) ){
3382 checkModel(/* hard failure iff */ ! r.isUnknown());
3383 }
3384 }
3385 // Check that UNSAT results generate a proof correctly.
3386 if(options::checkProofs()) {
3387 if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
3388 TimerStat::CodeTimer checkProofTimer(d_stats->d_checkProofTime);
3389 checkProof();
3390 }
3391 }
3392
3393 return r;
3394 }/* SmtEngine::query() */
3395
3396 Result SmtEngine::assertFormula(const Expr& ex) throw(TypeCheckingException, LogicException) {
3397 Assert(ex.getExprManager() == d_exprManager);
3398 SmtScope smts(this);
3399 finalOptionsAreSet();
3400 doPendingPops();
3401
3402 PROOF( ProofManager::currentPM()->addAssertion(ex); );
3403
3404 Trace("smt") << "SmtEngine::assertFormula(" << ex << ")" << endl;
3405
3406 // Substitute out any abstract values in ex
3407 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3408
3409 ensureBoolean(e);
3410 if(d_assertionList != NULL) {
3411 d_assertionList->push_back(e);
3412 }
3413 d_private->addFormula(e.getNode());
3414 return quickCheck().asValidityResult();
3415 }
3416
3417 Node SmtEngine::postprocess(TNode node, TypeNode expectedType) const {
3418 ModelPostprocessor mpost;
3419 NodeVisitor<ModelPostprocessor> visitor;
3420 Node value = visitor.run(mpost, node);
3421 Debug("boolean-terms") << "postproc: got " << value << " expect type " << expectedType << endl;
3422 Node realValue = mpost.rewriteAs(value, expectedType);
3423 Debug("boolean-terms") << "postproc: realval " << realValue << " expect type " << expectedType << endl;
3424 return realValue;
3425 }
3426
3427 Expr SmtEngine::simplify(const Expr& ex) throw(TypeCheckingException, LogicException) {
3428 Assert(ex.getExprManager() == d_exprManager);
3429 SmtScope smts(this);
3430 finalOptionsAreSet();
3431 doPendingPops();
3432 Trace("smt") << "SMT simplify(" << ex << ")" << endl;
3433
3434 if(Dump.isOn("benchmark")) {
3435 Dump("benchmark") << SimplifyCommand(ex);
3436 }
3437
3438 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3439 if( options::typeChecking() ) {
3440 e.getType(true); // ensure expr is type-checked at this point
3441 }
3442
3443 // Make sure all preprocessing is done
3444 d_private->processAssertions();
3445 Node n = d_private->simplify(Node::fromExpr(e));
3446 n = postprocess(n, TypeNode::fromType(e.getType()));
3447 return n.toExpr();
3448 }
3449
3450 Expr SmtEngine::expandDefinitions(const Expr& ex) throw(TypeCheckingException, LogicException) {
3451 Assert(ex.getExprManager() == d_exprManager);
3452 SmtScope smts(this);
3453 finalOptionsAreSet();
3454 doPendingPops();
3455 Trace("smt") << "SMT expandDefinitions(" << ex << ")" << endl;
3456
3457 // Substitute out any abstract values in ex.
3458 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3459 if(options::typeChecking()) {
3460 // Ensure expr is type-checked at this point.
3461 e.getType(true);
3462 }
3463 if(Dump.isOn("benchmark")) {
3464 Dump("benchmark") << ExpandDefinitionsCommand(e);
3465 }
3466 hash_map<Node, Node, NodeHashFunction> cache;
3467 Node n = d_private->expandDefinitions(Node::fromExpr(e), cache, /* expandOnly = */ true);
3468 n = postprocess(n, TypeNode::fromType(e.getType()));
3469
3470 return n.toExpr();
3471 }
3472
3473 Expr SmtEngine::getValue(const Expr& ex) const throw(ModalException, TypeCheckingException, LogicException) {
3474 Assert(ex.getExprManager() == d_exprManager);
3475 SmtScope smts(this);
3476
3477 Trace("smt") << "SMT getValue(" << ex << ")" << endl;
3478 if(Dump.isOn("benchmark")) {
3479 Dump("benchmark") << GetValueCommand(ex);
3480 }
3481
3482 if(!options::produceModels()) {
3483 const char* msg =
3484 "Cannot get value when produce-models options is off.";
3485 throw ModalException(msg);
3486 }
3487 if(d_status.isNull() ||
3488 d_status.asSatisfiabilityResult() == Result::UNSAT ||
3489 d_problemExtended) {
3490 const char* msg =
3491 "Cannot get value unless immediately preceded by SAT/INVALID or UNKNOWN response.";
3492 throw ModalException(msg);
3493 }
3494
3495 // Substitute out any abstract values in ex.
3496 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3497
3498 // Ensure expr is type-checked at this point.
3499 e.getType(options::typeChecking());
3500
3501 // do not need to apply preprocessing substitutions (should be recorded
3502 // in model already)
3503
3504 Node n = Node::fromExpr(e);
3505 Trace("smt") << "--- getting value of " << n << endl;
3506 TypeNode expectedType = n.getType();
3507
3508 // Expand, then normalize
3509 hash_map<Node, Node, NodeHashFunction> cache;
3510 n = d_private->expandDefinitions(n, cache);
3511 // There are two ways model values for terms are computed (for historical
3512 // reasons). One way is that used in check-model; the other is that
3513 // used by the Model classes. It's not clear to me exactly how these
3514 // two are different, but they need to be unified. This ugly hack here
3515 // is to fix bug 554 until we can revamp boolean-terms and models [MGD]
3516 if(!n.getType().isFunction()) {
3517 n = d_private->rewriteBooleanTerms(n);
3518 n = Rewriter::rewrite(n);
3519 }
3520
3521 Trace("smt") << "--- getting value of " << n << endl;
3522 TheoryModel* m = d_theoryEngine->getModel();
3523 Node resultNode;
3524 if(m != NULL) {
3525 resultNode = m->getValue(n);
3526 }
3527 Trace("smt") << "--- got value " << n << " = " << resultNode << endl;
3528 resultNode = postprocess(resultNode, expectedType);
3529 Trace("smt") << "--- model-post returned " << resultNode << endl;
3530 Trace("smt") << "--- model-post returned " << resultNode.getType() << endl;
3531 Trace("smt") << "--- model-post expected " << expectedType << endl;
3532
3533 // type-check the result we got
3534 Assert(resultNode.isNull() || resultNode.getType().isSubtypeOf(expectedType),
3535 "Run with -t smt for details.");
3536
3537 // ensure it's a constant
3538 Assert(resultNode.getKind() == kind::LAMBDA || resultNode.isConst());
3539
3540 if(options::abstractValues() && resultNode.getType().isArray()) {
3541 resultNode = d_private->mkAbstractValue(resultNode);
3542 }
3543
3544 return resultNode.toExpr();
3545 }
3546
3547 bool SmtEngine::addToAssignment(const Expr& ex) throw() {
3548 SmtScope smts(this);
3549 finalOptionsAreSet();
3550 doPendingPops();
3551 // Substitute out any abstract values in ex
3552 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
3553 Type type = e.getType(options::typeChecking());
3554 // must be Boolean
3555 CheckArgument( type.isBoolean(), e,
3556 "expected Boolean-typed variable or function application "
3557 "in addToAssignment()" );
3558 Node n = e.getNode();
3559 // must be an APPLY of a zero-ary defined function, or a variable
3560 CheckArgument( ( ( n.getKind() == kind::APPLY &&
3561 ( d_definedFunctions->find(n.getOperator()) !=
3562 d_definedFunctions->end() ) &&
3563 n.getNumChildren() == 0 ) ||
3564 n.isVar() ), e,
3565 "expected variable or defined-function application "
3566 "in addToAssignment(),\ngot %s", e.toString().c_str() );
3567 if(!options::produceAssignments()) {
3568 return false;
3569 }
3570 if(d_assignments == NULL) {
3571 d_assignments = new(true) AssignmentSet(d_context);
3572 }
3573 d_assignments->insert(n);
3574
3575 return true;
3576 }
3577
3578 CVC4::SExpr SmtEngine::getAssignment() throw(ModalException) {
3579 Trace("smt") << "SMT getAssignment()" << endl;
3580 SmtScope smts(this);
3581 finalOptionsAreSet();
3582 if(Dump.isOn("benchmark")) {
3583 Dump("benchmark") << GetAssignmentCommand();
3584 }
3585 if(!options::produceAssignments()) {
3586 const char* msg =
3587 "Cannot get the current assignment when "
3588 "produce-assignments option is off.";
3589 throw ModalException(msg);
3590 }
3591 if(d_status.isNull() ||
3592 d_status.asSatisfiabilityResult() == Result::UNSAT ||
3593 d_problemExtended) {
3594 const char* msg =
3595 "Cannot get the current assignment unless immediately "
3596 "preceded by SAT/INVALID or UNKNOWN response.";
3597 throw ModalException(msg);
3598 }
3599
3600 if(d_assignments == NULL) {
3601 return SExpr(vector<SExpr>());
3602 }
3603
3604 vector<SExpr> sexprs;
3605 TypeNode boolType = d_nodeManager->booleanType();
3606 TheoryModel* m = d_theoryEngine->getModel();
3607 for(AssignmentSet::const_iterator i = d_assignments->begin(),
3608 iend = d_assignments->end();
3609 i != iend;
3610 ++i) {
3611 Assert((*i).getType() == boolType);
3612
3613 Trace("smt") << "--- getting value of " << *i << endl;
3614
3615 // Expand, then normalize
3616 hash_map<Node, Node, NodeHashFunction> cache;
3617 Node n = d_private->expandDefinitions(*i, cache);
3618 n = d_private->rewriteBooleanTerms(n);
3619 n = Rewriter::rewrite(n);
3620
3621 Trace("smt") << "--- getting value of " << n << endl;
3622 Node resultNode;
3623 if(m != NULL) {
3624 resultNode = m->getValue(n);
3625 }
3626
3627 // type-check the result we got
3628 Assert(resultNode.isNull() || resultNode.getType() == boolType);
3629
3630 // ensure it's a constant
3631 Assert(resultNode.isConst());
3632
3633 vector<SExpr> v;
3634 if((*i).getKind() == kind::APPLY) {
3635 Assert((*i).getNumChildren() == 0);
3636 v.push_back(SExpr::Keyword((*i).getOperator().toString()));
3637 } else {
3638 Assert((*i).isVar());
3639 v.push_back(SExpr::Keyword((*i).toString()));
3640 }
3641 v.push_back(SExpr::Keyword(resultNode.toString()));
3642 sexprs.push_back(v);
3643 }
3644 return SExpr(sexprs);
3645 }
3646
3647 void SmtEngine::addToModelCommandAndDump(const Command& c, uint32_t flags, bool userVisible, const char* dumpTag) {
3648 Trace("smt") << "SMT addToModelCommandAndDump(" << c << ")" << endl;
3649 SmtScope smts(this);
3650 // If we aren't yet fully inited, the user might still turn on
3651 // produce-models. So let's keep any commands around just in
3652 // case. This is useful in two cases: (1) SMT-LIBv1 auto-declares
3653 // sort "U" in QF_UF before setLogic() is run and we still want to
3654 // support finding card(U) with --finite-model-find, and (2) to
3655 // decouple SmtEngine and ExprManager if the user does a few
3656 // ExprManager::mkSort() before SmtEngine::setOption("produce-models")
3657 // and expects to find their cardinalities in the model.
3658 if(/* userVisible && */
3659 (!d_fullyInited || options::produceModels()) &&
3660 (flags & ExprManager::VAR_FLAG_DEFINED) == 0) {
3661 doPendingPops();
3662 if(flags & ExprManager::VAR_FLAG_GLOBAL) {
3663 d_modelGlobalCommands.push_back(c.clone());
3664 } else {
3665 d_modelCommands->push_back(c.clone());
3666 }
3667 }
3668 if(Dump.isOn(dumpTag)) {
3669 if(d_fullyInited) {
3670 Dump(dumpTag) << c;
3671 } else {
3672 d_dumpCommands.push_back(c.clone());
3673 }
3674 }
3675 }
3676
3677 Model* SmtEngine::getModel() throw(ModalException) {
3678 Trace("smt") << "SMT getModel()" << endl;
3679 SmtScope smts(this);
3680
3681 finalOptionsAreSet();
3682
3683 if(Dump.isOn("benchmark")) {
3684 Dump("benchmark") << GetModelCommand();
3685 }
3686
3687 if(d_status.isNull() ||
3688 d_status.asSatisfiabilityResult() == Result::UNSAT ||
3689 d_problemExtended) {
3690 const char* msg =
3691 "Cannot get the current model unless immediately "
3692 "preceded by SAT/INVALID or UNKNOWN response.";
3693 throw ModalException(msg);
3694 }
3695 if(!options::produceModels()) {
3696 const char* msg =
3697 "Cannot get model when produce-models options is off.";
3698 throw ModalException(msg);
3699 }
3700 TheoryModel* m = d_theoryEngine->getModel();
3701 m->d_inputName = d_filename;
3702 return m;
3703 }
3704
3705 void SmtEngine::checkModel(bool hardFailure) {
3706 // --check-model implies --interactive, which enables the assertion list,
3707 // so we should be ok.
3708 Assert(d_assertionList != NULL, "don't have an assertion list to check in SmtEngine::checkModel()");
3709
3710 TimerStat::CodeTimer checkModelTimer(d_stats->d_checkModelTime);
3711
3712 // Throughout, we use Notice() to give diagnostic output.
3713 //
3714 // If this function is running, the user gave --check-model (or equivalent),
3715 // and if Notice() is on, the user gave --verbose (or equivalent).
3716
3717 Notice() << "SmtEngine::checkModel(): generating model" << endl;
3718 TheoryModel* m = d_theoryEngine->getModel();
3719
3720 // Check individual theory assertions
3721 d_theoryEngine->checkTheoryAssertionsWithModel();
3722
3723 // Output the model
3724 Notice() << *m;
3725
3726 // We have a "fake context" for the substitution map (we don't need it
3727 // to be context-dependent)
3728 context::Context fakeContext;
3729 SubstitutionMap substitutions(&fakeContext, /* substituteUnderQuantifiers = */ false);
3730
3731 for(size_t k = 0; k < m->getNumCommands(); ++k) {
3732 const DeclareFunctionCommand* c = dynamic_cast<const DeclareFunctionCommand*>(m->getCommand(k));
3733 Notice() << "SmtEngine::checkModel(): model command " << k << " : " << m->getCommand(k) << endl;
3734 if(c == NULL) {
3735 // we don't care about DECLARE-DATATYPES, DECLARE-SORT, ...
3736 Notice() << "SmtEngine::checkModel(): skipping..." << endl;
3737 } else {
3738 // We have a DECLARE-FUN:
3739 //
3740 // We'll first do some checks, then add to our substitution map
3741 // the mapping: function symbol |-> value
3742
3743 Expr func = c->getFunction();
3744 Node val = m->getValue(func);
3745
3746 Notice() << "SmtEngine::checkModel(): adding substitution: " << func << " |-> " << val << endl;
3747
3748 // (1) if the value is a lambda, ensure the lambda doesn't contain the
3749 // function symbol (since then the definition is recursive)
3750 if (val.getKind() == kind::LAMBDA) {
3751 // first apply the model substitutions we have so far
3752 Debug("boolean-terms") << "applying subses to " << val[1] << endl;
3753 Node n = substitutions.apply(val[1]);
3754 Debug("boolean-terms") << "++ got " << n << endl;
3755 // now check if n contains func by doing a substitution
3756 // [func->func2] and checking equality of the Nodes.
3757 // (this just a way to check if func is in n.)
3758 SubstitutionMap subs(&fakeContext);
3759 Node func2 = NodeManager::currentNM()->mkSkolem("", TypeNode::fromType(func.getType()), "", NodeManager::SKOLEM_NO_NOTIFY);
3760 subs.addSubstitution(func, func2);
3761 if(subs.apply(n) != n) {
3762 Notice() << "SmtEngine::checkModel(): *** PROBLEM: MODEL VALUE DEFINED IN TERMS OF ITSELF ***" << endl;
3763 stringstream ss;
3764 ss << "SmtEngine::checkModel(): ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
3765 << "considering model value for " << func << endl
3766 << "body of lambda is: " << val << endl;
3767 if(n != val[1]) {
3768 ss << "body substitutes to: " << n << endl;
3769 }
3770 ss << "so " << func << " is defined in terms of itself." << endl
3771 << "Run with `--check-models -v' for additional diagnostics.";
3772 InternalError(ss.str());
3773 }
3774 }
3775
3776 // (2) check that the value is actually a value
3777 else if (!val.isConst()) {
3778 Notice() << "SmtEngine::checkModel(): *** PROBLEM: MODEL VALUE NOT A CONSTANT ***" << endl;
3779 stringstream ss;
3780 ss << "SmtEngine::checkModel(): ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
3781 << "model value for " << func << endl
3782 << " is " << val << endl
3783 << "and that is not a constant (.isConst() == false)." << endl
3784 << "Run with `--check-models -v' for additional diagnostics.";
3785 InternalError(ss.str());
3786 }
3787
3788 // (3) check that it's the correct (sub)type
3789 // This was intended to be a more general check, but for now we can't do that because
3790 // e.g. "1" is an INT, which isn't a subrange type [1..10] (etc.).
3791 else if(func.getType().isInteger() && !val.getType().isInteger()) {
3792 Notice() << "SmtEngine::checkModel(): *** PROBLEM: MODEL VALUE NOT CORRECT TYPE ***" << endl;
3793 stringstream ss;
3794 ss << "SmtEngine::checkModel(): ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
3795 << "model value for " << func << endl
3796 << " is " << val << endl
3797 << "value type is " << val.getType() << endl
3798 << "should be of type " << func.getType() << endl
3799 << "Run with `--check-models -v' for additional diagnostics.";
3800 InternalError(ss.str());
3801 }
3802
3803 // (4) checks complete, add the substitution
3804 Debug("boolean-terms") << "cm: adding subs " << func << " :=> " << val << endl;
3805 substitutions.addSubstitution(func, val);
3806 }
3807 }
3808
3809 // Now go through all our user assertions checking if they're satisfied.
3810 for(AssertionList::const_iterator i = d_assertionList->begin(); i != d_assertionList->end(); ++i) {
3811 Notice() << "SmtEngine::checkModel(): checking assertion " << *i << endl;
3812 Node n = Node::fromExpr(*i);
3813
3814 // Apply any define-funs from the problem.
3815 {
3816 hash_map<Node, Node, NodeHashFunction> cache;
3817 n = d_private->expandDefinitions(n, cache);
3818 }
3819 Notice() << "SmtEngine::checkModel(): -- expands to " << n << endl;
3820
3821 // Apply our model value substitutions.
3822 Debug("boolean-terms") << "applying subses to " << n << endl;
3823 n = substitutions.apply(n);
3824 Debug("boolean-terms") << "++ got " << n << endl;
3825 Notice() << "SmtEngine::checkModel(): -- substitutes to " << n << endl;
3826
3827 //AJR : FIXME need to ignore quantifiers too?
3828 if( n.getKind() != kind::REWRITE_RULE ){
3829 // In case it's a quantifier (or contains one), look up its value before
3830 // simplifying, or the quantifier might be irreparably altered.
3831 n = m->getValue(n);
3832 } else {
3833 // Note this "skip" is done here, rather than above. This is
3834 // because (1) the quantifier could in principle simplify to false,
3835 // which should be reported, and (2) checking for the quantifier
3836 // above, before simplification, doesn't catch buried quantifiers
3837 // anyway (those not at the top-level).
3838 Notice() << "SmtEngine::checkModel(): -- skipping quantifiers/rewrite-rules assertion"
3839 << endl;
3840 continue;
3841 }
3842
3843 // Simplify the result.
3844 n = d_private->simplify(n);
3845 Notice() << "SmtEngine::checkModel(): -- simplifies to " << n << endl;
3846
3847 // Replace the already-known ITEs (this is important for ground ITEs under quantifiers).
3848 n = d_private->d_iteRemover.replace(n);
3849 Notice() << "SmtEngine::checkModel(): -- ite replacement gives " << n << endl;
3850
3851 // Apply our model value substitutions (again), as things may have been simplified.
3852 Debug("boolean-terms") << "applying subses to " << n << endl;
3853 n = substitutions.apply(n);
3854 Debug("boolean-terms") << "++ got " << n << endl;
3855 Notice() << "SmtEngine::checkModel(): -- re-substitutes to " << n << endl;
3856
3857 // As a last-ditch effort, ask model to simplify it.
3858 // Presently, this is only an issue for quantifiers, which can have a value
3859 // but don't show up in our substitution map above.
3860 n = m->getValue(n);
3861 Notice() << "SmtEngine::checkModel(): -- model-substitutes to " << n << endl;
3862 AlwaysAssert(!hardFailure || n.isConst() || n.getKind() == kind::LAMBDA);
3863
3864 // The result should be == true.
3865 if(n != NodeManager::currentNM()->mkConst(true)) {
3866 Notice() << "SmtEngine::checkModel(): *** PROBLEM: EXPECTED `TRUE' ***"
3867 << endl;
3868 stringstream ss;
3869 ss << "SmtEngine::checkModel(): "
3870 << "ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
3871 << "assertion: " << *i << endl
3872 << "simplifies to: " << n << endl
3873 << "expected `true'." << endl
3874 << "Run with `--check-models -v' for additional diagnostics.";
3875 if(hardFailure) {
3876 InternalError(ss.str());
3877 } else {
3878 Warning() << ss.str() << endl;
3879 }
3880 }
3881 }
3882 Notice() << "SmtEngine::checkModel(): all assertions checked out OK !" << endl;
3883 }
3884
3885 Proof* SmtEngine::getProof() throw(ModalException) {
3886 Trace("smt") << "SMT getProof()" << endl;
3887 SmtScope smts(this);
3888 finalOptionsAreSet();
3889 if(Dump.isOn("benchmark")) {
3890 Dump("benchmark") << GetProofCommand();
3891 }
3892 #ifdef CVC4_PROOF
3893 if(!options::proof()) {
3894 const char* msg =
3895 "Cannot get a proof when produce-proofs option is off.";
3896 throw ModalException(msg);
3897 }
3898 if(d_status.isNull() ||
3899 d_status.asSatisfiabilityResult() != Result::UNSAT ||
3900 d_problemExtended) {
3901 const char* msg =
3902 "Cannot get a proof unless immediately preceded by UNSAT/VALID response.";
3903 throw ModalException(msg);
3904 }
3905
3906 return ProofManager::getProof(this);
3907 #else /* CVC4_PROOF */
3908 throw ModalException("This build of CVC4 doesn't have proof support.");
3909 #endif /* CVC4_PROOF */
3910 }
3911
3912 void SmtEngine::printInstantiations( std::ostream& out ) {
3913 SmtScope smts(this);
3914 if( options::instFormatMode()==INST_FORMAT_MODE_SZS ){
3915 out << "% SZS output start Proof for " << d_filename.c_str() << std::endl;
3916 }
3917 if( d_theoryEngine ){
3918 d_theoryEngine->printInstantiations( out );
3919 }
3920 if( options::instFormatMode()==INST_FORMAT_MODE_SZS ){
3921 out << "% SZS output end Proof for " << d_filename.c_str() << std::endl;
3922 }
3923 }
3924
3925 vector<Expr> SmtEngine::getAssertions() throw(ModalException) {
3926 SmtScope smts(this);
3927 finalOptionsAreSet();
3928 if(Dump.isOn("benchmark")) {
3929 Dump("benchmark") << GetAssertionsCommand();
3930 }
3931 Trace("smt") << "SMT getAssertions()" << endl;
3932 if(!options::interactive()) {
3933 const char* msg =
3934 "Cannot query the current assertion list when not in interactive mode.";
3935 throw ModalException(msg);
3936 }
3937 Assert(d_assertionList != NULL);
3938 // copy the result out
3939 return vector<Expr>(d_assertionList->begin(), d_assertionList->end());
3940 }
3941
3942 void SmtEngine::push() throw(ModalException, LogicException) {
3943 SmtScope smts(this);
3944 finalOptionsAreSet();
3945 doPendingPops();
3946 Trace("smt") << "SMT push()" << endl;
3947 d_private->processAssertions();
3948 if(Dump.isOn("benchmark")) {
3949 Dump("benchmark") << PushCommand();
3950 }
3951 if(!options::incrementalSolving()) {
3952 throw ModalException("Cannot push when not solving incrementally (use --incremental)");
3953 }
3954
3955 // check to see if a postsolve() is pending
3956 if(d_needPostsolve) {
3957 d_theoryEngine->postsolve();
3958 d_needPostsolve = false;
3959 }
3960
3961 // The problem isn't really "extended" yet, but this disallows
3962 // get-model after a push, simplifying our lives somewhat and
3963 // staying symmtric with pop.
3964 d_problemExtended = true;
3965
3966 d_userLevels.push_back(d_userContext->getLevel());
3967 internalPush();
3968 Trace("userpushpop") << "SmtEngine: pushed to level "
3969 << d_userContext->getLevel() << endl;
3970 }
3971
3972 void SmtEngine::pop() throw(ModalException) {
3973 SmtScope smts(this);
3974 finalOptionsAreSet();
3975 Trace("smt") << "SMT pop()" << endl;
3976 if(Dump.isOn("benchmark")) {
3977 Dump("benchmark") << PopCommand();
3978 }
3979 if(!options::incrementalSolving()) {
3980 throw ModalException("Cannot pop when not solving incrementally (use --incremental)");
3981 }
3982 if(d_userLevels.size() == 0) {
3983 throw ModalException("Cannot pop beyond the first user frame");
3984 }
3985
3986 // check to see if a postsolve() is pending
3987 if(d_needPostsolve) {
3988 d_theoryEngine->postsolve();
3989 d_needPostsolve = false;
3990 }
3991
3992 // The problem isn't really "extended" yet, but this disallows
3993 // get-model after a pop, simplifying our lives somewhat. It might
3994 // not be strictly necessary to do so, since the pops occur lazily,
3995 // but also it would be weird to have a legally-executed (get-model)
3996 // that only returns a subset of the assignment (because the rest
3997 // is no longer in scope!).
3998 d_problemExtended = true;
3999
4000 AlwaysAssert(d_userContext->getLevel() > 0);
4001 AlwaysAssert(d_userLevels.back() < d_userContext->getLevel());
4002 while (d_userLevels.back() < d_userContext->getLevel()) {
4003 internalPop(true);
4004 }
4005 d_userLevels.pop_back();
4006
4007 // Clear out assertion queues etc., in case anything is still in there
4008 d_private->notifyPop();
4009
4010 Trace("userpushpop") << "SmtEngine: popped to level "
4011 << d_userContext->getLevel() << endl;
4012 // FIXME: should we reset d_status here?
4013 // SMT-LIBv2 spec seems to imply no, but it would make sense to..
4014 }
4015
4016 void SmtEngine::internalPush() {
4017 Assert(d_fullyInited);
4018 Trace("smt") << "SmtEngine::internalPush()" << endl;
4019 doPendingPops();
4020 if(options::incrementalSolving()) {
4021 d_private->processAssertions();
4022 TimerStat::CodeTimer pushPopTimer(d_stats->d_pushPopTime);
4023 d_userContext->push();
4024 // the d_context push is done inside of the SAT solver
4025 d_propEngine->push();
4026 }
4027 }
4028
4029 void SmtEngine::internalPop(bool immediate) {
4030 Assert(d_fullyInited);
4031 Trace("smt") << "SmtEngine::internalPop()" << endl;
4032 if(options::incrementalSolving()) {
4033 ++d_pendingPops;
4034 }
4035 if(immediate) {
4036 doPendingPops();
4037 }
4038 }
4039
4040 void SmtEngine::doPendingPops() {
4041 Assert(d_pendingPops == 0 || options::incrementalSolving());
4042 while(d_pendingPops > 0) {
4043 TimerStat::CodeTimer pushPopTimer(d_stats->d_pushPopTime);
4044 d_propEngine->pop();
4045 // the d_context pop is done inside of the SAT solver
4046 d_userContext->pop();
4047 --d_pendingPops;
4048 }
4049 }
4050
4051 void SmtEngine::interrupt() throw(ModalException) {
4052 if(!d_fullyInited) {
4053 return;
4054 }
4055 d_propEngine->interrupt();
4056 d_theoryEngine->interrupt();
4057 }
4058
4059 void SmtEngine::setResourceLimit(unsigned long units, bool cumulative) {
4060 if(cumulative) {
4061 Trace("limit") << "SmtEngine: setting cumulative resource limit to " << units << endl;
4062 d_resourceBudgetCumulative = (units == 0) ? 0 : (d_cumulativeResourceUsed + units);
4063 } else {
4064 Trace("limit") << "SmtEngine: setting per-call resource limit to " << units << endl;
4065 d_resourceBudgetPerCall = units;
4066 }
4067 }
4068
4069 void SmtEngine::setTimeLimit(unsigned long millis, bool cumulative) {
4070 if(cumulative) {
4071 Trace("limit") << "SmtEngine: setting cumulative time limit to " << millis << " ms" << endl;
4072 d_timeBudgetCumulative = (millis == 0) ? 0 : (d_cumulativeTimeUsed + millis);
4073 } else {
4074 Trace("limit") << "SmtEngine: setting per-call time limit to " << millis << " ms" << endl;
4075 d_timeBudgetPerCall = millis;
4076 }
4077 }
4078
4079 unsigned long SmtEngine::getResourceUsage() const {
4080 return d_cumulativeResourceUsed;
4081 }
4082
4083 unsigned long SmtEngine::getTimeUsage() const {
4084 return d_cumulativeTimeUsed;
4085 }
4086
4087 unsigned long SmtEngine::getResourceRemaining() const throw(ModalException) {
4088 if(d_resourceBudgetCumulative == 0) {
4089 throw ModalException("No cumulative resource limit is currently set");
4090 }
4091
4092 return d_resourceBudgetCumulative <= d_cumulativeResourceUsed ? 0 :
4093 d_resourceBudgetCumulative - d_cumulativeResourceUsed;
4094 }
4095
4096 unsigned long SmtEngine::getTimeRemaining() const throw(ModalException) {
4097 if(d_timeBudgetCumulative == 0) {
4098 throw ModalException("No cumulative time limit is currently set");
4099 }
4100
4101 return d_timeBudgetCumulative <= d_cumulativeTimeUsed ? 0 :
4102 d_timeBudgetCumulative - d_cumulativeTimeUsed;
4103 }
4104
4105 Statistics SmtEngine::getStatistics() const throw() {
4106 return Statistics(*d_statisticsRegistry);
4107 }
4108
4109 SExpr SmtEngine::getStatistic(std::string name) const throw() {
4110 return d_statisticsRegistry->getStatistic(name);
4111 }
4112
4113 void SmtEngine::setUserAttribute(const std::string& attr, Expr expr) {
4114 SmtScope smts(this);
4115 d_theoryEngine->setUserAttribute(attr, expr.getNode());
4116 }
4117
4118 void SmtEngine::setPrintFuncInModel(Expr f, bool p) {
4119 Trace("setp-model") << "Set printInModel " << f << " to " << p << std::endl;
4120 for( unsigned i=0; i<d_modelGlobalCommands.size(); i++ ){
4121 Command * c = d_modelGlobalCommands[i];
4122 DeclareFunctionCommand* dfc = dynamic_cast<DeclareFunctionCommand*>(c);
4123 if(dfc != NULL) {
4124 if( dfc->getFunction()==f ){
4125 dfc->setPrintInModel( p );
4126 }
4127 }
4128 }
4129 for( unsigned i=0; i<d_modelCommands->size(); i++ ){
4130 Command * c = (*d_modelCommands)[i];
4131 DeclareFunctionCommand* dfc = dynamic_cast<DeclareFunctionCommand*>(c);
4132 if(dfc != NULL) {
4133 if( dfc->getFunction()==f ){
4134 dfc->setPrintInModel( p );
4135 }
4136 }
4137 }
4138 }
4139
4140 }/* CVC4 namespace */