Fix issue #1074, improve non-fatal error handling (#1075)
[cvc5.git] / src / smt / smt_engine.cpp
1 /********************* */
2 /*! \file smt_engine.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Morgan Deters, Tim King, Andrew Reynolds
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2017 by the authors listed in the file AUTHORS
8 ** in the top-level source directory) and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\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 "smt/smt_engine.h"
18
19 #include <algorithm>
20 #include <cctype>
21 #include <unordered_map>
22 #include <unordered_set>
23 #include <iterator>
24 #include <sstream>
25 #include <stack>
26 #include <string>
27 #include <utility>
28 #include <vector>
29
30 #include "base/configuration.h"
31 #include "base/configuration_private.h"
32 #include "base/exception.h"
33 #include "base/listener.h"
34 #include "base/modal_exception.h"
35 #include "base/output.h"
36 #include "context/cdhashset.h"
37 #include "context/cdlist.h"
38 #include "context/context.h"
39 #include "decision/decision_engine.h"
40 #include "expr/attribute.h"
41 #include "expr/expr.h"
42 #include "expr/kind.h"
43 #include "expr/metakind.h"
44 #include "expr/node.h"
45 #include "expr/node_builder.h"
46 #include "expr/node_self_iterator.h"
47 #include "options/arith_options.h"
48 #include "options/arrays_options.h"
49 #include "options/base_options.h"
50 #include "options/booleans_options.h"
51 #include "options/bv_options.h"
52 #include "options/datatypes_options.h"
53 #include "options/decision_mode.h"
54 #include "options/decision_options.h"
55 #include "options/main_options.h"
56 #include "options/open_ostream.h"
57 #include "options/option_exception.h"
58 #include "options/printer_options.h"
59 #include "options/proof_options.h"
60 #include "options/prop_options.h"
61 #include "options/quantifiers_options.h"
62 #include "options/set_language.h"
63 #include "options/smt_options.h"
64 #include "options/strings_options.h"
65 #include "options/theory_options.h"
66 #include "options/uf_options.h"
67 #include "printer/printer.h"
68 #include "proof/proof.h"
69 #include "proof/proof_manager.h"
70 #include "proof/proof_manager.h"
71 #include "proof/theory_proof.h"
72 #include "proof/unsat_core.h"
73 #include "prop/prop_engine.h"
74 #include "smt/command.h"
75 #include "smt/command_list.h"
76 #include "smt/term_formula_removal.h"
77 #include "smt/logic_request.h"
78 #include "smt/managed_ostreams.h"
79 #include "smt/smt_engine_scope.h"
80 #include "smt/update_ostream.h"
81 #include "smt_util/boolean_simplification.h"
82 #include "smt_util/nary_builder.h"
83 #include "smt_util/node_visitor.h"
84 #include "theory/arith/pseudoboolean_proc.h"
85 #include "theory/booleans/circuit_propagator.h"
86 #include "theory/bv/bvintropow2.h"
87 #include "theory/bv/theory_bv_rewriter.h"
88 #include "theory/logic_info.h"
89 #include "theory/quantifiers/ce_guided_instantiation.h"
90 #include "theory/quantifiers/fun_def_process.h"
91 #include "theory/quantifiers/macros.h"
92 #include "theory/quantifiers/quantifiers_rewriter.h"
93 #include "theory/quantifiers/term_database.h"
94 #include "theory/sort_inference.h"
95 #include "theory/strings/theory_strings.h"
96 #include "theory/substitutions.h"
97 #include "theory/theory_engine.h"
98 #include "theory/theory_model.h"
99 #include "theory/theory_traits.h"
100 #include "util/hash.h"
101 #include "util/proof.h"
102 #include "util/resource_manager.h"
103 #include "options/sep_options.h"
104
105 using namespace std;
106 using namespace CVC4;
107 using namespace CVC4::smt;
108 using namespace CVC4::prop;
109 using namespace CVC4::context;
110 using namespace CVC4::theory;
111
112 namespace CVC4 {
113 namespace smt {
114
115 struct DeleteCommandFunction : public std::unary_function<const Command*, void>
116 {
117 void operator()(const Command* command) { delete command; }
118 };
119
120 void DeleteAndClearCommandVector(std::vector<Command*>& commands) {
121 std::for_each(commands.begin(), commands.end(), DeleteCommandFunction());
122 commands.clear();
123 }
124
125 /** Useful for counting the number of recursive calls. */
126 class ScopeCounter {
127 private:
128 unsigned& d_depth;
129 public:
130 ScopeCounter(unsigned& d) : d_depth(d) {
131 ++d_depth;
132 }
133 ~ScopeCounter(){
134 --d_depth;
135 }
136 };
137
138 /**
139 * Representation of a defined function. We keep these around in
140 * SmtEngine to permit expanding definitions late (and lazily), to
141 * support getValue() over defined functions, to support user output
142 * in terms of defined functions, etc.
143 */
144 class DefinedFunction {
145 Node d_func;
146 vector<Node> d_formals;
147 Node d_formula;
148 public:
149 DefinedFunction() {}
150 DefinedFunction(Node func, vector<Node> formals, Node formula) :
151 d_func(func),
152 d_formals(formals),
153 d_formula(formula) {
154 }
155 Node getFunction() const { return d_func; }
156 vector<Node> getFormals() const { return d_formals; }
157 Node getFormula() const { return d_formula; }
158 };/* class DefinedFunction */
159
160 class AssertionPipeline {
161 vector<Node> d_nodes;
162
163 public:
164
165 size_t size() const { return d_nodes.size(); }
166
167 void resize(size_t n) { d_nodes.resize(n); }
168 void clear() { d_nodes.clear(); }
169
170 Node& operator[](size_t i) { return d_nodes[i]; }
171 const Node& operator[](size_t i) const { return d_nodes[i]; }
172 void push_back(Node n) { d_nodes.push_back(n); }
173
174 vector<Node>& ref() { return d_nodes; }
175 const vector<Node>& ref() const { return d_nodes; }
176
177 void replace(size_t i, Node n) {
178 PROOF( ProofManager::currentPM()->addDependence(n, d_nodes[i]); );
179 d_nodes[i] = n;
180 }
181 };/* class AssertionPipeline */
182
183 struct SmtEngineStatistics {
184 /** time spent in definition-expansion */
185 TimerStat d_definitionExpansionTime;
186 /** time spent in non-clausal simplification */
187 TimerStat d_nonclausalSimplificationTime;
188 /** time spent in miplib pass */
189 TimerStat d_miplibPassTime;
190 /** number of assertions removed by miplib pass */
191 IntStat d_numMiplibAssertionsRemoved;
192 /** number of constant propagations found during nonclausal simp */
193 IntStat d_numConstantProps;
194 /** time spent in static learning */
195 TimerStat d_staticLearningTime;
196 /** time spent in simplifying ITEs */
197 TimerStat d_simpITETime;
198 /** time spent in simplifying ITEs */
199 TimerStat d_unconstrainedSimpTime;
200 /** time spent removing ITEs */
201 TimerStat d_iteRemovalTime;
202 /** time spent in theory preprocessing */
203 TimerStat d_theoryPreprocessTime;
204 /** time spent in theory preprocessing */
205 TimerStat d_rewriteApplyToConstTime;
206 /** time spent converting to CNF */
207 TimerStat d_cnfConversionTime;
208 /** Num of assertions before ite removal */
209 IntStat d_numAssertionsPre;
210 /** Num of assertions after ite removal */
211 IntStat d_numAssertionsPost;
212 /** time spent in checkModel() */
213 TimerStat d_checkModelTime;
214 /** time spent in checkProof() */
215 TimerStat d_checkProofTime;
216 /** time spent in checkUnsatCore() */
217 TimerStat d_checkUnsatCoreTime;
218 /** time spent in PropEngine::checkSat() */
219 TimerStat d_solveTime;
220 /** time spent in pushing/popping */
221 TimerStat d_pushPopTime;
222 /** time spent in processAssertions() */
223 TimerStat d_processAssertionsTime;
224
225 /** Has something simplified to false? */
226 IntStat d_simplifiedToFalse;
227 /** Number of resource units spent. */
228 ReferenceStat<uint64_t> d_resourceUnitsUsed;
229
230 SmtEngineStatistics() :
231 d_definitionExpansionTime("smt::SmtEngine::definitionExpansionTime"),
232 d_nonclausalSimplificationTime("smt::SmtEngine::nonclausalSimplificationTime"),
233 d_miplibPassTime("smt::SmtEngine::miplibPassTime"),
234 d_numMiplibAssertionsRemoved("smt::SmtEngine::numMiplibAssertionsRemoved", 0),
235 d_numConstantProps("smt::SmtEngine::numConstantProps", 0),
236 d_staticLearningTime("smt::SmtEngine::staticLearningTime"),
237 d_simpITETime("smt::SmtEngine::simpITETime"),
238 d_unconstrainedSimpTime("smt::SmtEngine::unconstrainedSimpTime"),
239 d_iteRemovalTime("smt::SmtEngine::iteRemovalTime"),
240 d_theoryPreprocessTime("smt::SmtEngine::theoryPreprocessTime"),
241 d_rewriteApplyToConstTime("smt::SmtEngine::rewriteApplyToConstTime"),
242 d_cnfConversionTime("smt::SmtEngine::cnfConversionTime"),
243 d_numAssertionsPre("smt::SmtEngine::numAssertionsPreITERemoval", 0),
244 d_numAssertionsPost("smt::SmtEngine::numAssertionsPostITERemoval", 0),
245 d_checkModelTime("smt::SmtEngine::checkModelTime"),
246 d_checkProofTime("smt::SmtEngine::checkProofTime"),
247 d_checkUnsatCoreTime("smt::SmtEngine::checkUnsatCoreTime"),
248 d_solveTime("smt::SmtEngine::solveTime"),
249 d_pushPopTime("smt::SmtEngine::pushPopTime"),
250 d_processAssertionsTime("smt::SmtEngine::processAssertionsTime"),
251 d_simplifiedToFalse("smt::SmtEngine::simplifiedToFalse", 0),
252 d_resourceUnitsUsed("smt::SmtEngine::resourceUnitsUsed")
253 {
254
255 smtStatisticsRegistry()->registerStat(&d_definitionExpansionTime);
256 smtStatisticsRegistry()->registerStat(&d_nonclausalSimplificationTime);
257 smtStatisticsRegistry()->registerStat(&d_miplibPassTime);
258 smtStatisticsRegistry()->registerStat(&d_numMiplibAssertionsRemoved);
259 smtStatisticsRegistry()->registerStat(&d_numConstantProps);
260 smtStatisticsRegistry()->registerStat(&d_staticLearningTime);
261 smtStatisticsRegistry()->registerStat(&d_simpITETime);
262 smtStatisticsRegistry()->registerStat(&d_unconstrainedSimpTime);
263 smtStatisticsRegistry()->registerStat(&d_iteRemovalTime);
264 smtStatisticsRegistry()->registerStat(&d_theoryPreprocessTime);
265 smtStatisticsRegistry()->registerStat(&d_rewriteApplyToConstTime);
266 smtStatisticsRegistry()->registerStat(&d_cnfConversionTime);
267 smtStatisticsRegistry()->registerStat(&d_numAssertionsPre);
268 smtStatisticsRegistry()->registerStat(&d_numAssertionsPost);
269 smtStatisticsRegistry()->registerStat(&d_checkModelTime);
270 smtStatisticsRegistry()->registerStat(&d_checkProofTime);
271 smtStatisticsRegistry()->registerStat(&d_checkUnsatCoreTime);
272 smtStatisticsRegistry()->registerStat(&d_solveTime);
273 smtStatisticsRegistry()->registerStat(&d_pushPopTime);
274 smtStatisticsRegistry()->registerStat(&d_processAssertionsTime);
275 smtStatisticsRegistry()->registerStat(&d_simplifiedToFalse);
276 smtStatisticsRegistry()->registerStat(&d_resourceUnitsUsed);
277 }
278
279 ~SmtEngineStatistics() {
280 smtStatisticsRegistry()->unregisterStat(&d_definitionExpansionTime);
281 smtStatisticsRegistry()->unregisterStat(&d_nonclausalSimplificationTime);
282 smtStatisticsRegistry()->unregisterStat(&d_miplibPassTime);
283 smtStatisticsRegistry()->unregisterStat(&d_numMiplibAssertionsRemoved);
284 smtStatisticsRegistry()->unregisterStat(&d_numConstantProps);
285 smtStatisticsRegistry()->unregisterStat(&d_staticLearningTime);
286 smtStatisticsRegistry()->unregisterStat(&d_simpITETime);
287 smtStatisticsRegistry()->unregisterStat(&d_unconstrainedSimpTime);
288 smtStatisticsRegistry()->unregisterStat(&d_iteRemovalTime);
289 smtStatisticsRegistry()->unregisterStat(&d_theoryPreprocessTime);
290 smtStatisticsRegistry()->unregisterStat(&d_rewriteApplyToConstTime);
291 smtStatisticsRegistry()->unregisterStat(&d_cnfConversionTime);
292 smtStatisticsRegistry()->unregisterStat(&d_numAssertionsPre);
293 smtStatisticsRegistry()->unregisterStat(&d_numAssertionsPost);
294 smtStatisticsRegistry()->unregisterStat(&d_checkModelTime);
295 smtStatisticsRegistry()->unregisterStat(&d_checkProofTime);
296 smtStatisticsRegistry()->unregisterStat(&d_checkUnsatCoreTime);
297 smtStatisticsRegistry()->unregisterStat(&d_solveTime);
298 smtStatisticsRegistry()->unregisterStat(&d_pushPopTime);
299 smtStatisticsRegistry()->unregisterStat(&d_processAssertionsTime);
300 smtStatisticsRegistry()->unregisterStat(&d_simplifiedToFalse);
301 smtStatisticsRegistry()->unregisterStat(&d_resourceUnitsUsed);
302 }
303 };/* struct SmtEngineStatistics */
304
305
306 class SoftResourceOutListener : public Listener {
307 public:
308 SoftResourceOutListener(SmtEngine& smt) : d_smt(&smt) {}
309 virtual void notify() {
310 SmtScope scope(d_smt);
311 Assert(smt::smtEngineInScope());
312 d_smt->interrupt();
313 }
314 private:
315 SmtEngine* d_smt;
316 }; /* class SoftResourceOutListener */
317
318
319 class HardResourceOutListener : public Listener {
320 public:
321 HardResourceOutListener(SmtEngine& smt) : d_smt(&smt) {}
322 virtual void notify() {
323 SmtScope scope(d_smt);
324 theory::Rewriter::clearCaches();
325 }
326 private:
327 SmtEngine* d_smt;
328 }; /* class HardResourceOutListener */
329
330 class SetLogicListener : public Listener {
331 public:
332 SetLogicListener(SmtEngine& smt) : d_smt(&smt) {}
333 virtual void notify() {
334 LogicInfo inOptions(options::forceLogicString());
335 d_smt->setLogic(inOptions);
336 }
337 private:
338 SmtEngine* d_smt;
339 }; /* class SetLogicListener */
340
341 class BeforeSearchListener : public Listener {
342 public:
343 BeforeSearchListener(SmtEngine& smt) : d_smt(&smt) {}
344 virtual void notify() {
345 d_smt->beforeSearch();
346 }
347 private:
348 SmtEngine* d_smt;
349 }; /* class BeforeSearchListener */
350
351 class UseTheoryListListener : public Listener {
352 public:
353 UseTheoryListListener(TheoryEngine* theoryEngine)
354 : d_theoryEngine(theoryEngine)
355 {}
356
357 void notify() {
358 std::stringstream commaList(options::useTheoryList());
359 std::string token;
360
361 Debug("UseTheoryListListener") << "UseTheoryListListener::notify() "
362 << options::useTheoryList() << std::endl;
363
364 while(std::getline(commaList, token, ',')){
365 if(token == "help") {
366 puts(theory::useTheoryHelp);
367 exit(1);
368 }
369 if(theory::useTheoryValidate(token)) {
370 d_theoryEngine->enableTheoryAlternative(token);
371 } else {
372 throw OptionException(
373 std::string("unknown option for --use-theory : `") + token +
374 "'. Try --use-theory=help.");
375 }
376 }
377 }
378
379 private:
380 TheoryEngine* d_theoryEngine;
381 }; /* class UseTheoryListListener */
382
383
384 class SetDefaultExprDepthListener : public Listener {
385 public:
386 virtual void notify() {
387 int depth = options::defaultExprDepth();
388 Debug.getStream() << expr::ExprSetDepth(depth);
389 Trace.getStream() << expr::ExprSetDepth(depth);
390 Notice.getStream() << expr::ExprSetDepth(depth);
391 Chat.getStream() << expr::ExprSetDepth(depth);
392 Message.getStream() << expr::ExprSetDepth(depth);
393 Warning.getStream() << expr::ExprSetDepth(depth);
394 // intentionally exclude Dump stream from this list
395 }
396 };
397
398 class SetDefaultExprDagListener : public Listener {
399 public:
400 virtual void notify() {
401 int dag = options::defaultDagThresh();
402 Debug.getStream() << expr::ExprDag(dag);
403 Trace.getStream() << expr::ExprDag(dag);
404 Notice.getStream() << expr::ExprDag(dag);
405 Chat.getStream() << expr::ExprDag(dag);
406 Message.getStream() << expr::ExprDag(dag);
407 Warning.getStream() << expr::ExprDag(dag);
408 Dump.getStream() << expr::ExprDag(dag);
409 }
410 };
411
412 class SetPrintExprTypesListener : public Listener {
413 public:
414 virtual void notify() {
415 bool value = options::printExprTypes();
416 Debug.getStream() << expr::ExprPrintTypes(value);
417 Trace.getStream() << expr::ExprPrintTypes(value);
418 Notice.getStream() << expr::ExprPrintTypes(value);
419 Chat.getStream() << expr::ExprPrintTypes(value);
420 Message.getStream() << expr::ExprPrintTypes(value);
421 Warning.getStream() << expr::ExprPrintTypes(value);
422 // intentionally exclude Dump stream from this list
423 }
424 };
425
426 class DumpModeListener : public Listener {
427 public:
428 virtual void notify() {
429 const std::string& value = options::dumpModeString();
430 Dump.setDumpFromString(value);
431 }
432 };
433
434 class PrintSuccessListener : public Listener {
435 public:
436 virtual void notify() {
437 bool value = options::printSuccess();
438 Debug.getStream() << Command::printsuccess(value);
439 Trace.getStream() << Command::printsuccess(value);
440 Notice.getStream() << Command::printsuccess(value);
441 Chat.getStream() << Command::printsuccess(value);
442 Message.getStream() << Command::printsuccess(value);
443 Warning.getStream() << Command::printsuccess(value);
444 *options::out() << Command::printsuccess(value);
445 }
446 };
447
448
449
450 /**
451 * This is an inelegant solution, but for the present, it will work.
452 * The point of this is to separate the public and private portions of
453 * the SmtEngine class, so that smt_engine.h doesn't
454 * include "expr/node.h", which is a private CVC4 header (and can lead
455 * to linking errors due to the improper inlining of non-visible symbols
456 * into user code!).
457 *
458 * The "real" solution (that which is usually implemented) is to move
459 * ALL the implementation to SmtEnginePrivate and maintain a
460 * heap-allocated instance of it in SmtEngine. SmtEngine (the public
461 * one) becomes an "interface shell" which simply acts as a forwarder
462 * of method calls.
463 */
464 class SmtEnginePrivate : public NodeManagerListener {
465 SmtEngine& d_smt;
466
467 typedef unordered_map<Node, Node, NodeHashFunction> NodeToNodeHashMap;
468 typedef unordered_map<Node, bool, NodeHashFunction> NodeToBoolHashMap;
469
470 /**
471 * Manager for limiting time and abstract resource usage.
472 */
473 ResourceManager* d_resourceManager;
474
475 /** Manager for the memory of regular-output-channel. */
476 ManagedRegularOutputChannel d_managedRegularChannel;
477
478 /** Manager for the memory of diagnostic-output-channel. */
479 ManagedDiagnosticOutputChannel d_managedDiagnosticChannel;
480
481 /** Manager for the memory of --dump-to. */
482 ManagedDumpOStream d_managedDumpChannel;
483
484 /** Manager for --replay-log. */
485 ManagedReplayLogOstream d_managedReplayLog;
486
487 /**
488 * This list contains:
489 * softResourceOut
490 * hardResourceOut
491 * setForceLogic
492 * beforeSearchListener
493 * UseTheoryListListener
494 *
495 * This needs to be deleted before both NodeManager's Options,
496 * SmtEngine, d_resourceManager, and TheoryEngine.
497 */
498 ListenerRegistrationList* d_listenerRegistrations;
499
500 /** Learned literals */
501 vector<Node> d_nonClausalLearnedLiterals;
502
503 /** Size of assertions array when preprocessing starts */
504 unsigned d_realAssertionsEnd;
505
506 /** A circuit propagator for non-clausal propositional deduction */
507 booleans::CircuitPropagator d_propagator;
508 bool d_propagatorNeedsFinish;
509 std::vector<Node> d_boolVars;
510
511 /** Assertions in the preprocessing pipeline */
512 AssertionPipeline d_assertions;
513
514 /** Whether any assertions have been processed */
515 CDO<bool> d_assertionsProcessed;
516
517 /** Index for where to store substitutions */
518 CDO<unsigned> d_substitutionsIndex;
519
520 // Cached true value
521 Node d_true;
522
523 /**
524 * A context that never pushes/pops, for use by CD structures (like
525 * SubstitutionMaps) that should be "global".
526 */
527 context::Context d_fakeContext;
528
529 /**
530 * A map of AbsractValues to their actual constants. Only used if
531 * options::abstractValues() is on.
532 */
533 SubstitutionMap d_abstractValueMap;
534
535 /**
536 * A mapping of all abstract values (actual value |-> abstract) that
537 * we've handed out. This is necessary to ensure that we give the
538 * same AbstractValues for the same real constants. Only used if
539 * options::abstractValues() is on.
540 */
541 NodeToNodeHashMap d_abstractValues;
542
543 /** Number of calls of simplify assertions active.
544 */
545 unsigned d_simplifyAssertionsDepth;
546
547 /** TODO: whether certain preprocess steps are necessary */
548 //bool d_needsExpandDefs;
549
550 public:
551 /**
552 * Map from skolem variables to index in d_assertions containing
553 * corresponding introduced Boolean ite
554 */
555 IteSkolemMap d_iteSkolemMap;
556
557 /** Instance of the ITE remover */
558 RemoveTermFormulas d_iteRemover;
559
560 private:
561
562 theory::arith::PseudoBooleanProcessor d_pbsProcessor;
563
564 /** The top level substitutions */
565 SubstitutionMap d_topLevelSubstitutions;
566
567 static const bool d_doConstantProp = true;
568
569 /**
570 * Runs the nonclausal solver and tries to solve all the assigned
571 * theory literals.
572 *
573 * Returns false if the formula simplifies to "false"
574 */
575 bool nonClausalSimplify();
576
577 /**
578 * Performs static learning on the assertions.
579 */
580 void staticLearning();
581
582 /**
583 * Remove ITEs from the assertions.
584 */
585 void removeITEs();
586
587 Node realToInt(TNode n, NodeToNodeHashMap& cache, std::vector< Node >& var_eq);
588 Node intToBV(TNode n, NodeToNodeHashMap& cache);
589 Node intToBVMakeBinary(TNode n, NodeToNodeHashMap& cache);
590 Node purifyNlTerms(TNode n, NodeToNodeHashMap& cache, NodeToNodeHashMap& bcache, std::vector< Node >& var_eq, bool beneathMult = false);
591
592 /**
593 * Helper function to fix up assertion list to restore invariants needed after
594 * ite removal.
595 */
596 void collectSkolems(TNode n, set<TNode>& skolemSet, NodeToBoolHashMap& cache);
597
598 /**
599 * Helper function to fix up assertion list to restore invariants needed after
600 * ite removal.
601 */
602 bool checkForBadSkolems(TNode n, TNode skolem, NodeToBoolHashMap& cache);
603
604 // Lift bit-vectors of size 1 to booleans
605 void bvToBool();
606
607 // Convert booleans to bit-vectors of size 1
608 void boolToBv();
609
610 // Abstract common structure over small domains to UF
611 // return true if changes were made.
612 void bvAbstraction();
613
614 // Simplify ITE structure
615 bool simpITE();
616
617 // Simplify based on unconstrained values
618 void unconstrainedSimp();
619
620 /**
621 * Ensures the assertions asserted after before now effectively come before
622 * d_realAssertionsEnd.
623 */
624 void compressBeforeRealAssertions(size_t before);
625
626 /**
627 * Trace nodes back to their assertions using CircuitPropagator's
628 * BackEdgesMap.
629 */
630 void traceBackToAssertions(const std::vector<Node>& nodes,
631 std::vector<TNode>& assertions);
632
633 /**
634 * Remove conjuncts in toRemove from conjunction n. Return # of removed
635 * conjuncts.
636 */
637 size_t removeFromConjunction(Node& n,
638 const std::unordered_set<unsigned long>& toRemove);
639
640 /** Scrub miplib encodings. */
641 void doMiplibTrick();
642
643 /**
644 * Perform non-clausal simplification of a Node. This involves
645 * Theory implementations, but does NOT involve the SAT solver in
646 * any way.
647 *
648 * Returns false if the formula simplifies to "false"
649 */
650 bool simplifyAssertions() throw(TypeCheckingException, LogicException,
651 UnsafeInterruptException);
652
653 public:
654
655 SmtEnginePrivate(SmtEngine& smt) :
656 d_smt(smt),
657 d_managedRegularChannel(),
658 d_managedDiagnosticChannel(),
659 d_managedDumpChannel(),
660 d_managedReplayLog(),
661 d_listenerRegistrations(new ListenerRegistrationList()),
662 d_nonClausalLearnedLiterals(),
663 d_realAssertionsEnd(0),
664 d_propagator(d_nonClausalLearnedLiterals, true, true),
665 d_propagatorNeedsFinish(false),
666 d_assertions(),
667 d_assertionsProcessed(smt.d_userContext, false),
668 d_substitutionsIndex(smt.d_userContext, 0),
669 d_fakeContext(),
670 d_abstractValueMap(&d_fakeContext),
671 d_abstractValues(),
672 d_simplifyAssertionsDepth(0),
673 //d_needsExpandDefs(true), //TODO?
674 d_iteSkolemMap(),
675 d_iteRemover(smt.d_userContext),
676 d_pbsProcessor(smt.d_userContext),
677 d_topLevelSubstitutions(smt.d_userContext)
678 {
679 d_smt.d_nodeManager->subscribeEvents(this);
680 d_true = NodeManager::currentNM()->mkConst(true);
681 d_resourceManager = NodeManager::currentResourceManager();
682
683 d_listenerRegistrations->add(d_resourceManager->registerSoftListener(
684 new SoftResourceOutListener(d_smt)));
685
686 d_listenerRegistrations->add(d_resourceManager->registerHardListener(
687 new HardResourceOutListener(d_smt)));
688
689 Options& nodeManagerOptions = NodeManager::currentNM()->getOptions();
690 d_listenerRegistrations->add(
691 nodeManagerOptions.registerForceLogicListener(
692 new SetLogicListener(d_smt), true));
693
694 // Multiple options reuse BeforeSearchListener so registration requires an
695 // extra bit of care.
696 // We can safely not call notify on this before search listener at
697 // registration time. This d_smt cannot be beforeSearch at construction
698 // time. Therefore the BeforeSearchListener is a no-op. Therefore it does
699 // not have to be called.
700 d_listenerRegistrations->add(
701 nodeManagerOptions.registerBeforeSearchListener(
702 new BeforeSearchListener(d_smt)));
703
704 // These do need registration calls.
705 d_listenerRegistrations->add(
706 nodeManagerOptions.registerSetDefaultExprDepthListener(
707 new SetDefaultExprDepthListener(), true));
708 d_listenerRegistrations->add(
709 nodeManagerOptions.registerSetDefaultExprDagListener(
710 new SetDefaultExprDagListener(), true));
711 d_listenerRegistrations->add(
712 nodeManagerOptions.registerSetPrintExprTypesListener(
713 new SetPrintExprTypesListener(), true));
714 d_listenerRegistrations->add(
715 nodeManagerOptions.registerSetDumpModeListener(
716 new DumpModeListener(), true));
717 d_listenerRegistrations->add(
718 nodeManagerOptions.registerSetPrintSuccessListener(
719 new PrintSuccessListener(), true));
720 d_listenerRegistrations->add(
721 nodeManagerOptions.registerSetRegularOutputChannelListener(
722 new SetToDefaultSourceListener(&d_managedRegularChannel), true));
723 d_listenerRegistrations->add(
724 nodeManagerOptions.registerSetDiagnosticOutputChannelListener(
725 new SetToDefaultSourceListener(&d_managedDiagnosticChannel), true));
726 d_listenerRegistrations->add(
727 nodeManagerOptions.registerDumpToFileNameListener(
728 new SetToDefaultSourceListener(&d_managedDumpChannel), true));
729 d_listenerRegistrations->add(
730 nodeManagerOptions.registerSetReplayLogFilename(
731 new SetToDefaultSourceListener(&d_managedReplayLog), true));
732 }
733
734 ~SmtEnginePrivate() throw() {
735 delete d_listenerRegistrations;
736
737 if(d_propagatorNeedsFinish) {
738 d_propagator.finish();
739 d_propagatorNeedsFinish = false;
740 }
741 d_smt.d_nodeManager->unsubscribeEvents(this);
742 }
743
744 ResourceManager* getResourceManager() { return d_resourceManager; }
745 void spendResource(unsigned amount) throw(UnsafeInterruptException) {
746 d_resourceManager->spendResource(amount);
747 }
748
749 void nmNotifyNewSort(TypeNode tn, uint32_t flags) {
750 DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
751 0,
752 tn.toType());
753 if((flags & ExprManager::SORT_FLAG_PLACEHOLDER) == 0) {
754 d_smt.addToModelCommandAndDump(c, flags);
755 }
756 }
757
758 void nmNotifyNewSortConstructor(TypeNode tn) {
759 DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
760 tn.getAttribute(expr::SortArityAttr()),
761 tn.toType());
762 d_smt.addToModelCommandAndDump(c);
763 }
764
765 void nmNotifyNewDatatypes(const std::vector<DatatypeType>& dtts) {
766 DatatypeDeclarationCommand c(dtts);
767 d_smt.addToModelCommandAndDump(c);
768 }
769
770 void nmNotifyNewVar(TNode n, uint32_t flags) {
771 DeclareFunctionCommand c(n.getAttribute(expr::VarNameAttr()),
772 n.toExpr(),
773 n.getType().toType());
774 if((flags & ExprManager::VAR_FLAG_DEFINED) == 0) {
775 d_smt.addToModelCommandAndDump(c, flags);
776 }
777 if(n.getType().isBoolean() && !options::incrementalSolving()) {
778 d_boolVars.push_back(n);
779 }
780 }
781
782 void nmNotifyNewSkolem(TNode n, const std::string& comment, uint32_t flags) {
783 string id = n.getAttribute(expr::VarNameAttr());
784 DeclareFunctionCommand c(id,
785 n.toExpr(),
786 n.getType().toType());
787 if(Dump.isOn("skolems") && comment != "") {
788 Dump("skolems") << CommentCommand(id + " is " + comment);
789 }
790 if((flags & ExprManager::VAR_FLAG_DEFINED) == 0) {
791 d_smt.addToModelCommandAndDump(c, flags, false, "skolems");
792 }
793 if(n.getType().isBoolean() && !options::incrementalSolving()) {
794 d_boolVars.push_back(n);
795 }
796 }
797
798 void nmNotifyDeleteNode(TNode n) {}
799
800 Node applySubstitutions(TNode node) const {
801 return Rewriter::rewrite(d_topLevelSubstitutions.apply(node));
802 }
803
804 /**
805 * Process the assertions that have been asserted.
806 */
807 void processAssertions();
808
809 /**
810 * Process a user pop. Clears out the non-context-dependent stuff in this
811 * SmtEnginePrivate. Necessary to clear out our assertion vectors in case
812 * someone does a push-assert-pop without a check-sat.
813 */
814 void notifyPop() {
815 d_assertions.clear();
816 d_nonClausalLearnedLiterals.clear();
817 d_realAssertionsEnd = 0;
818 d_iteSkolemMap.clear();
819 }
820
821 /**
822 * Adds a formula to the current context. Action here depends on
823 * the SimplificationMode (in the current Options scope); the
824 * formula might be pushed out to the propositional layer
825 * immediately, or it might be simplified and kept, or it might not
826 * even be simplified.
827 * the 2nd and 3rd arguments added for bookkeeping for proofs
828 */
829 void addFormula(TNode n, bool inUnsatCore, bool inInput = true)
830 throw(TypeCheckingException, LogicException);
831
832 /** Expand definitions in n. */
833 Node expandDefinitions(TNode n, NodeToNodeHashMap& cache,
834 bool expandOnly = false)
835 throw(TypeCheckingException, LogicException, UnsafeInterruptException);
836
837 /**
838 * Simplify node "in" by expanding definitions and applying any
839 * substitutions learned from preprocessing.
840 */
841 Node simplify(TNode in) {
842 // Substitute out any abstract values in ex.
843 // Expand definitions.
844 NodeToNodeHashMap cache;
845 Node n = expandDefinitions(in, cache).toExpr();
846 // Make sure we've done all preprocessing, etc.
847 Assert(d_assertions.size() == 0);
848 return applySubstitutions(n).toExpr();
849 }
850
851 /**
852 * Substitute away all AbstractValues in a node.
853 */
854 Node substituteAbstractValues(TNode n) {
855 // We need to do this even if options::abstractValues() is off,
856 // since the setting might have changed after we already gave out
857 // some abstract values.
858 return d_abstractValueMap.apply(n);
859 }
860
861 /**
862 * Make a new (or return an existing) abstract value for a node.
863 * Can only use this if options::abstractValues() is on.
864 */
865 Node mkAbstractValue(TNode n) {
866 Assert(options::abstractValues());
867 Node& val = d_abstractValues[n];
868 if(val.isNull()) {
869 val = d_smt.d_nodeManager->mkAbstractValue(n.getType());
870 d_abstractValueMap.addSubstitution(val, n);
871 }
872 // We are supposed to ascribe types to all abstract values that go out.
873 NodeManager* current = d_smt.d_nodeManager;
874 Node ascription = current->mkConst(AscriptionType(n.getType().toType()));
875 Node retval = current->mkNode(kind::APPLY_TYPE_ASCRIPTION, ascription, val);
876 return retval;
877 }
878
879 NodeToNodeHashMap d_rewriteApplyToConstCache;
880 Node rewriteApplyToConst(TNode n) {
881 Trace("rewriteApplyToConst") << "rewriteApplyToConst :: " << n << std::endl;
882
883 if(n.getMetaKind() == kind::metakind::CONSTANT ||
884 n.getMetaKind() == kind::metakind::VARIABLE ||
885 n.getMetaKind() == kind::metakind::NULLARY_OPERATOR)
886 {
887 return n;
888 }
889
890 if(d_rewriteApplyToConstCache.find(n) != d_rewriteApplyToConstCache.end()) {
891 Trace("rewriteApplyToConst") << "in cache :: "
892 << d_rewriteApplyToConstCache[n]
893 << std::endl;
894 return d_rewriteApplyToConstCache[n];
895 }
896
897 if(n.getKind() == kind::APPLY_UF) {
898 if(n.getNumChildren() == 1 && n[0].isConst() &&
899 n[0].getType().isInteger())
900 {
901 stringstream ss;
902 ss << n.getOperator() << "_";
903 if(n[0].getConst<Rational>() < 0) {
904 ss << "m" << -n[0].getConst<Rational>();
905 } else {
906 ss << n[0];
907 }
908 Node newvar = NodeManager::currentNM()->mkSkolem(
909 ss.str(), n.getType(), "rewriteApplyToConst skolem",
910 NodeManager::SKOLEM_EXACT_NAME);
911 d_rewriteApplyToConstCache[n] = newvar;
912 Trace("rewriteApplyToConst") << "made :: " << newvar << std::endl;
913 return newvar;
914 } else {
915 stringstream ss;
916 ss << "The rewrite-apply-to-const preprocessor is currently limited;"
917 << std::endl
918 << "it only works if all function symbols are unary and with Integer"
919 << std::endl
920 << "domain, and all applications are to integer values." << std::endl
921 << "Found application: " << n;
922 Unhandled(ss.str());
923 }
924 }
925
926 NodeBuilder<> builder(n.getKind());
927 if(n.getMetaKind() == kind::metakind::PARAMETERIZED) {
928 builder << n.getOperator();
929 }
930 for(unsigned i = 0; i < n.getNumChildren(); ++i) {
931 builder << rewriteApplyToConst(n[i]);
932 }
933 Node rewr = builder;
934 d_rewriteApplyToConstCache[n] = rewr;
935 Trace("rewriteApplyToConst") << "built :: " << rewr << std::endl;
936 return rewr;
937 }
938
939 void addUseTheoryListListener(TheoryEngine* theoryEngine){
940 Options& nodeManagerOptions = NodeManager::currentNM()->getOptions();
941 d_listenerRegistrations->add(
942 nodeManagerOptions.registerUseTheoryListListener(
943 new UseTheoryListListener(theoryEngine), true));
944 }
945
946 std::ostream* getReplayLog() const {
947 return d_managedReplayLog.getReplayLog();
948 }
949
950 };/* class SmtEnginePrivate */
951
952 }/* namespace CVC4::smt */
953
954 SmtEngine::SmtEngine(ExprManager* em) throw() :
955 d_context(new Context()),
956 d_userLevels(),
957 d_userContext(new UserContext()),
958 d_exprManager(em),
959 d_nodeManager(d_exprManager->getNodeManager()),
960 d_decisionEngine(NULL),
961 d_theoryEngine(NULL),
962 d_propEngine(NULL),
963 d_proofManager(NULL),
964 d_definedFunctions(NULL),
965 d_fmfRecFunctionsDefined(NULL),
966 d_assertionList(NULL),
967 d_assignments(NULL),
968 d_modelGlobalCommands(),
969 d_modelCommands(NULL),
970 d_dumpCommands(),
971 d_defineCommands(),
972 d_logic(),
973 d_originalOptions(),
974 d_pendingPops(0),
975 d_fullyInited(false),
976 d_problemExtended(false),
977 d_queryMade(false),
978 d_needPostsolve(false),
979 d_earlyTheoryPP(true),
980 d_status(),
981 d_replayStream(NULL),
982 d_private(NULL),
983 d_statisticsRegistry(NULL),
984 d_stats(NULL),
985 d_channels(new LemmaChannels())
986 {
987 SmtScope smts(this);
988 d_originalOptions.copyValues(em->getOptions());
989 d_private = new smt::SmtEnginePrivate(*this);
990 d_statisticsRegistry = new StatisticsRegistry();
991 d_stats = new SmtEngineStatistics();
992 d_stats->d_resourceUnitsUsed.setData(
993 d_private->getResourceManager()->getResourceUsage());
994
995 // The ProofManager is constructed before any other proof objects such as
996 // SatProof and TheoryProofs. The TheoryProofEngine and the SatProof are
997 // initialized in TheoryEngine and PropEngine respectively.
998 Assert(d_proofManager == NULL);
999
1000 // d_proofManager must be created before Options has been finished
1001 // being parsed from the input file. Because of this, we cannot trust
1002 // that options::proof() is set correctly yet.
1003 #ifdef CVC4_PROOF
1004 d_proofManager = new ProofManager(d_userContext);
1005 #endif
1006
1007 // We have mutual dependency here, so we add the prop engine to the theory
1008 // engine later (it is non-essential there)
1009 d_theoryEngine = new TheoryEngine(d_context, d_userContext,
1010 d_private->d_iteRemover,
1011 const_cast<const LogicInfo&>(d_logic),
1012 d_channels);
1013
1014 // Add the theories
1015 for(TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
1016 TheoryConstructor::addTheory(d_theoryEngine, id);
1017 //register with proof engine if applicable
1018 #ifdef CVC4_PROOF
1019 ProofManager::currentPM()->getTheoryProofEngine()->registerTheory(d_theoryEngine->theoryOf(id));
1020 #endif
1021 }
1022
1023 d_private->addUseTheoryListListener(d_theoryEngine);
1024
1025 // global push/pop around everything, to ensure proper destruction
1026 // of context-dependent data structures
1027 d_userContext->push();
1028 d_context->push();
1029
1030 d_definedFunctions = new(true) DefinedFunctionMap(d_userContext);
1031 d_fmfRecFunctionsDefined = new(true) NodeList(d_userContext);
1032 d_modelCommands = new(true) smt::CommandList(d_userContext);
1033 }
1034
1035 void SmtEngine::finishInit() {
1036 Trace("smt-debug") << "SmtEngine::finishInit" << std::endl;
1037 // ensure that our heuristics are properly set up
1038 setDefaults();
1039
1040 Trace("smt-debug") << "Making decision engine..." << std::endl;
1041
1042 d_decisionEngine = new DecisionEngine(d_context, d_userContext);
1043 d_decisionEngine->init(); // enable appropriate strategies
1044
1045 Trace("smt-debug") << "Making prop engine..." << std::endl;
1046 d_propEngine = new PropEngine(d_theoryEngine, d_decisionEngine, d_context,
1047 d_userContext, d_private->getReplayLog(),
1048 d_replayStream, d_channels);
1049
1050 Trace("smt-debug") << "Setting up theory engine..." << std::endl;
1051 d_theoryEngine->setPropEngine(d_propEngine);
1052 d_theoryEngine->setDecisionEngine(d_decisionEngine);
1053 Trace("smt-debug") << "Finishing init for theory engine..." << std::endl;
1054 d_theoryEngine->finishInit();
1055
1056 Trace("smt-debug") << "Set up assertion list..." << std::endl;
1057 // [MGD 10/20/2011] keep around in incremental mode, due to a
1058 // cleanup ordering issue and Nodes/TNodes. If SAT is popped
1059 // first, some user-context-dependent TNodes might still exist
1060 // with rc == 0.
1061 if(options::produceAssertions() ||
1062 options::incrementalSolving()) {
1063 // In the case of incremental solving, we appear to need these to
1064 // ensure the relevant Nodes remain live.
1065 d_assertionList = new(true) AssertionList(d_userContext);
1066 }
1067
1068 // dump out a set-logic command
1069 if(Dump.isOn("benchmark")) {
1070 if (Dump.isOn("raw-benchmark")) {
1071 Dump("raw-benchmark") << SetBenchmarkLogicCommand(d_logic.getLogicString());
1072 } else {
1073 LogicInfo everything;
1074 everything.lock();
1075 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.")
1076 << SetBenchmarkLogicCommand(everything.getLogicString());
1077 }
1078 }
1079
1080 Trace("smt-debug") << "Dump declaration commands..." << std::endl;
1081 // dump out any pending declaration commands
1082 for(unsigned i = 0; i < d_dumpCommands.size(); ++i) {
1083 Dump("declarations") << *d_dumpCommands[i];
1084 delete d_dumpCommands[i];
1085 }
1086 d_dumpCommands.clear();
1087
1088 PROOF( ProofManager::currentPM()->setLogic(d_logic); );
1089 PROOF({
1090 for(TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
1091 ProofManager::currentPM()->getTheoryProofEngine()->
1092 finishRegisterTheory(d_theoryEngine->theoryOf(id));
1093 }
1094 });
1095
1096 Trace("smt-debug") << "SmtEngine::finishInit done" << std::endl;
1097 }
1098
1099 void SmtEngine::finalOptionsAreSet() {
1100 if(d_fullyInited) {
1101 return;
1102 }
1103
1104 if(! d_logic.isLocked()) {
1105 setLogicInternal();
1106 }
1107
1108 // finish initialization, create the prop engine, etc.
1109 finishInit();
1110
1111 AlwaysAssert( d_propEngine->getAssertionLevel() == 0,
1112 "The PropEngine has pushed but the SmtEngine "
1113 "hasn't finished initializing!" );
1114
1115 d_fullyInited = true;
1116 Assert(d_logic.isLocked());
1117
1118 d_propEngine->assertFormula(NodeManager::currentNM()->mkConst<bool>(true));
1119 d_propEngine->assertFormula(NodeManager::currentNM()->mkConst<bool>(false).notNode());
1120 }
1121
1122 void SmtEngine::shutdown() {
1123 doPendingPops();
1124
1125 while(options::incrementalSolving() && d_userContext->getLevel() > 1) {
1126 internalPop(true);
1127 }
1128
1129 // check to see if a postsolve() is pending
1130 if(d_needPostsolve) {
1131 d_theoryEngine->postsolve();
1132 d_needPostsolve = false;
1133 }
1134
1135 if(d_propEngine != NULL) {
1136 d_propEngine->shutdown();
1137 }
1138 if(d_theoryEngine != NULL) {
1139 d_theoryEngine->shutdown();
1140 }
1141 if(d_decisionEngine != NULL) {
1142 d_decisionEngine->shutdown();
1143 }
1144 }
1145
1146 SmtEngine::~SmtEngine() throw() {
1147 SmtScope smts(this);
1148
1149 try {
1150 shutdown();
1151
1152 // global push/pop around everything, to ensure proper destruction
1153 // of context-dependent data structures
1154 d_context->popto(0);
1155 d_userContext->popto(0);
1156
1157 if(d_assignments != NULL) {
1158 d_assignments->deleteSelf();
1159 }
1160
1161 if(d_assertionList != NULL) {
1162 d_assertionList->deleteSelf();
1163 }
1164
1165 for(unsigned i = 0; i < d_dumpCommands.size(); ++i) {
1166 delete d_dumpCommands[i];
1167 d_dumpCommands[i] = NULL;
1168 }
1169 d_dumpCommands.clear();
1170
1171 DeleteAndClearCommandVector(d_modelGlobalCommands);
1172
1173 if(d_modelCommands != NULL) {
1174 d_modelCommands->deleteSelf();
1175 }
1176
1177 d_definedFunctions->deleteSelf();
1178 d_fmfRecFunctionsDefined->deleteSelf();
1179
1180 delete d_theoryEngine;
1181 d_theoryEngine = NULL;
1182 delete d_propEngine;
1183 d_propEngine = NULL;
1184 delete d_decisionEngine;
1185 d_decisionEngine = NULL;
1186
1187
1188 // d_proofManager is always created when proofs are enabled at configure time.
1189 // Becuase of this, this code should not be wrapped in PROOF() which
1190 // additionally checks flags such as options::proof().
1191 #ifdef CVC4_PROOF
1192 delete d_proofManager;
1193 d_proofManager = NULL;
1194 #endif
1195
1196 delete d_stats;
1197 d_stats = NULL;
1198 delete d_statisticsRegistry;
1199 d_statisticsRegistry = NULL;
1200
1201 delete d_private;
1202 d_private = NULL;
1203
1204 delete d_userContext;
1205 d_userContext = NULL;
1206 delete d_context;
1207 d_context = NULL;
1208
1209 delete d_channels;
1210 d_channels = NULL;
1211
1212 } catch(Exception& e) {
1213 Warning() << "CVC4 threw an exception during cleanup." << endl
1214 << e << endl;
1215 }
1216 }
1217
1218 void SmtEngine::setLogic(const LogicInfo& logic) throw(ModalException) {
1219 SmtScope smts(this);
1220 if(d_fullyInited) {
1221 throw ModalException("Cannot set logic in SmtEngine after the engine has "
1222 "finished initializing.");
1223 }
1224 d_logic = logic;
1225 setLogicInternal();
1226 }
1227
1228 void SmtEngine::setLogic(const std::string& s)
1229 throw(ModalException, LogicException) {
1230 SmtScope smts(this);
1231 try {
1232 setLogic(LogicInfo(s));
1233 } catch(IllegalArgumentException& e) {
1234 throw LogicException(e.what());
1235 }
1236 }
1237
1238 void SmtEngine::setLogic(const char* logic)
1239 throw(ModalException, LogicException) {
1240 setLogic(string(logic));
1241 }
1242
1243 LogicInfo SmtEngine::getLogicInfo() const {
1244 return d_logic;
1245 }
1246
1247 void SmtEngine::setLogicInternal() throw() {
1248 Assert(!d_fullyInited, "setting logic in SmtEngine but the engine has already"
1249 " finished initializing for this run");
1250 d_logic.lock();
1251 }
1252
1253 void SmtEngine::setDefaults() {
1254 if(options::forceLogicString.wasSetByUser()) {
1255 d_logic = LogicInfo(options::forceLogicString());
1256 }else if (options::solveIntAsBV() > 0) {
1257 d_logic = LogicInfo("QF_BV");
1258 }else if (d_logic.getLogicString() == "QF_NRA" && options::solveRealAsInt()) {
1259 d_logic = LogicInfo("QF_NIA");
1260 } else if ((d_logic.getLogicString() == "QF_UFBV" ||
1261 d_logic.getLogicString() == "QF_ABV") &&
1262 options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
1263 d_logic = LogicInfo("QF_BV");
1264 }
1265
1266 // set strings-exp
1267 /* - disabled for 1.4 release [MGD 2014.06.25]
1268 if(!d_logic.hasEverything() && d_logic.isTheoryEnabled(THEORY_STRINGS) ) {
1269 if(! options::stringExp.wasSetByUser()) {
1270 options::stringExp.set( true );
1271 Trace("smt") << "turning on strings-exp, for the theory of strings" << std::endl;
1272 }
1273 }
1274 */
1275 // for strings
1276 if(options::stringExp()) {
1277 if( !d_logic.isQuantified() ) {
1278 d_logic = d_logic.getUnlockedCopy();
1279 d_logic.enableQuantifiers();
1280 d_logic.lock();
1281 Trace("smt") << "turning on quantifier logic, for strings-exp"
1282 << std::endl;
1283 }
1284 if(! options::fmfBound.wasSetByUser()) {
1285 options::fmfBound.set( true );
1286 Trace("smt") << "turning on fmf-bound-int, for strings-exp" << std::endl;
1287 }
1288 if(! options::fmfInstEngine.wasSetByUser()) {
1289 options::fmfInstEngine.set( true );
1290 Trace("smt") << "turning on fmf-inst-engine, for strings-exp" << std::endl;
1291 }
1292 /*
1293 if(! options::rewriteDivk.wasSetByUser()) {
1294 options::rewriteDivk.set( true );
1295 Trace("smt") << "turning on rewrite-divk, for strings-exp" << std::endl;
1296 }*/
1297 /*
1298 if(! options::stringFMF.wasSetByUser()) {
1299 options::stringFMF.set( true );
1300 Trace("smt") << "turning on strings-fmf, for strings-exp" << std::endl;
1301 }
1302 */
1303 }
1304
1305 if(options::checkModels()) {
1306 if(! options::produceAssertions()) {
1307 Notice() << "SmtEngine: turning on produce-assertions to support "
1308 << "check-models." << endl;
1309 setOption("produce-assertions", SExpr("true"));
1310 }
1311 }
1312
1313 if(options::unsatCores()) {
1314 if(options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
1315 if(options::simplificationMode.wasSetByUser()) {
1316 throw OptionException("simplification not supported with unsat cores");
1317 }
1318 Notice() << "SmtEngine: turning off simplification to support unsat-cores"
1319 << endl;
1320 options::simplificationMode.set(SIMPLIFICATION_MODE_NONE);
1321 }
1322
1323 if(options::unconstrainedSimp()) {
1324 if(options::unconstrainedSimp.wasSetByUser()) {
1325 throw OptionException("unconstrained simplification not supported with unsat cores");
1326 }
1327 Notice() << "SmtEngine: turning off unconstrained simplification to support unsat-cores" << endl;
1328 options::unconstrainedSimp.set(false);
1329 }
1330
1331 if(options::pbRewrites()) {
1332 if(options::pbRewrites.wasSetByUser()) {
1333 throw OptionException("pseudoboolean rewrites not supported with unsat cores");
1334 }
1335 Notice() << "SmtEngine: turning off pseudoboolean rewrites to support unsat-cores" << endl;
1336 setOption("pb-rewrites", false);
1337 }
1338
1339 if(options::sortInference()) {
1340 if(options::sortInference.wasSetByUser()) {
1341 throw OptionException("sort inference not supported with unsat cores");
1342 }
1343 Notice() << "SmtEngine: turning off sort inference to support unsat-cores" << endl;
1344 options::sortInference.set(false);
1345 }
1346
1347 if(options::preSkolemQuant()) {
1348 if(options::preSkolemQuant.wasSetByUser()) {
1349 throw OptionException("pre-skolemization not supported with unsat cores");
1350 }
1351 Notice() << "SmtEngine: turning off pre-skolemization to support unsat-cores" << endl;
1352 options::preSkolemQuant.set(false);
1353 }
1354
1355 if(options::bitvectorToBool()) {
1356 if(options::bitvectorToBool.wasSetByUser()) {
1357 throw OptionException("bv-to-bool not supported with unsat cores");
1358 }
1359 Notice() << "SmtEngine: turning off bitvector-to-bool to support unsat-cores" << endl;
1360 options::bitvectorToBool.set(false);
1361 }
1362
1363 if(options::boolToBitvector()) {
1364 if(options::boolToBitvector.wasSetByUser()) {
1365 throw OptionException("bool-to-bv not supported with unsat cores");
1366 }
1367 Notice() << "SmtEngine: turning off bool-to-bitvector to support unsat-cores" << endl;
1368 options::boolToBitvector.set(false);
1369 }
1370
1371 if(options::bvIntroducePow2()) {
1372 if(options::bvIntroducePow2.wasSetByUser()) {
1373 throw OptionException("bv-intro-pow2 not supported with unsat cores");
1374 }
1375 Notice() << "SmtEngine: turning off bv-introduce-pow2 to support unsat-cores" << endl;
1376 setOption("bv-intro-pow2", false);
1377 }
1378 if(options::repeatSimp()) {
1379 if(options::repeatSimp.wasSetByUser()) {
1380 throw OptionException("repeat-simp not supported with unsat cores");
1381 }
1382 Notice() << "SmtEngine: turning off repeat-simp to support unsat-cores" << endl;
1383 setOption("repeat-simp", false);
1384 }
1385
1386 }
1387
1388 if(options::produceAssignments() && !options::produceModels()) {
1389 Notice() << "SmtEngine: turning on produce-models to support produce-assignments" << endl;
1390 setOption("produce-models", SExpr("true"));
1391 }
1392
1393 // Set the options for the theoryOf
1394 if(!options::theoryOfMode.wasSetByUser()) {
1395 if(d_logic.isSharingEnabled() &&
1396 !d_logic.isTheoryEnabled(THEORY_BV) &&
1397 !d_logic.isTheoryEnabled(THEORY_STRINGS) &&
1398 !d_logic.isTheoryEnabled(THEORY_SETS) ) {
1399 Trace("smt") << "setting theoryof-mode to term-based" << endl;
1400 options::theoryOfMode.set(THEORY_OF_TERM_BASED);
1401 }
1402 }
1403
1404 // strings require LIA, UF; widen the logic
1405 if(d_logic.isTheoryEnabled(THEORY_STRINGS)) {
1406 LogicInfo log(d_logic.getUnlockedCopy());
1407 // Strings requires arith for length constraints, and also UF
1408 if(!d_logic.isTheoryEnabled(THEORY_UF)) {
1409 Trace("smt") << "because strings are enabled, also enabling UF" << endl;
1410 log.enableTheory(THEORY_UF);
1411 }
1412 if(!d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isDifferenceLogic() || !d_logic.areIntegersUsed()) {
1413 Trace("smt") << "because strings are enabled, also enabling linear integer arithmetic" << endl;
1414 log.enableTheory(THEORY_ARITH);
1415 log.enableIntegers();
1416 log.arithOnlyLinear();
1417 }
1418 d_logic = log;
1419 d_logic.lock();
1420 }
1421 if(d_logic.isTheoryEnabled(THEORY_ARRAY) || d_logic.isTheoryEnabled(THEORY_DATATYPES) || d_logic.isTheoryEnabled(THEORY_SETS)) {
1422 if(!d_logic.isTheoryEnabled(THEORY_UF)) {
1423 LogicInfo log(d_logic.getUnlockedCopy());
1424 Trace("smt") << "because a theory that permits Boolean terms is enabled, also enabling UF" << endl;
1425 log.enableTheory(THEORY_UF);
1426 d_logic = log;
1427 d_logic.lock();
1428 }
1429 }
1430
1431 // by default, symmetry breaker is on only for QF_UF
1432 if(! options::ufSymmetryBreaker.wasSetByUser()) {
1433 bool qf_uf = d_logic.isPure(THEORY_UF) && !d_logic.isQuantified() && !options::proof();
1434 Trace("smt") << "setting uf symmetry breaker to " << qf_uf << endl;
1435 options::ufSymmetryBreaker.set(qf_uf);
1436 }
1437 // by default, nonclausal simplification is off for QF_SAT
1438 if(! options::simplificationMode.wasSetByUser()) {
1439 bool qf_sat = d_logic.isPure(THEORY_BOOL) && !d_logic.isQuantified();
1440 Trace("smt") << "setting simplification mode to <" << d_logic.getLogicString() << "> " << (!qf_sat) << endl;
1441 //simplification=none works better for SMT LIB benchmarks with quantifiers, not others
1442 //options::simplificationMode.set(qf_sat || quantifiers ? SIMPLIFICATION_MODE_NONE : SIMPLIFICATION_MODE_BATCH);
1443 options::simplificationMode.set(qf_sat ? SIMPLIFICATION_MODE_NONE : SIMPLIFICATION_MODE_BATCH);
1444 }
1445
1446 // If in arrays, set the UF handler to arrays
1447 if(d_logic.isTheoryEnabled(THEORY_ARRAY) && ( !d_logic.isQuantified() ||
1448 (d_logic.isQuantified() && !d_logic.isTheoryEnabled(THEORY_UF)))) {
1449 Theory::setUninterpretedSortOwner(THEORY_ARRAY);
1450 } else {
1451 Theory::setUninterpretedSortOwner(THEORY_UF);
1452 }
1453
1454 // Turn on ite simplification for QF_LIA and QF_AUFBV
1455 // WARNING: These checks match much more than just QF_AUFBV and
1456 // QF_LIA logics. --K [2014/10/15]
1457 if(! options::doITESimp.wasSetByUser()) {
1458 bool qf_aufbv = !d_logic.isQuantified() &&
1459 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1460 d_logic.isTheoryEnabled(THEORY_UF) &&
1461 d_logic.isTheoryEnabled(THEORY_BV);
1462 bool qf_lia = !d_logic.isQuantified() &&
1463 d_logic.isPure(THEORY_ARITH) &&
1464 d_logic.isLinear() &&
1465 !d_logic.isDifferenceLogic() &&
1466 !d_logic.areRealsUsed();
1467
1468 bool iteSimp = (qf_aufbv || qf_lia);
1469 Trace("smt") << "setting ite simplification to " << iteSimp << endl;
1470 options::doITESimp.set(iteSimp);
1471 }
1472 if(! options::compressItes.wasSetByUser() ){
1473 bool qf_lia = !d_logic.isQuantified() &&
1474 d_logic.isPure(THEORY_ARITH) &&
1475 d_logic.isLinear() &&
1476 !d_logic.isDifferenceLogic() &&
1477 !d_logic.areRealsUsed();
1478
1479 bool compressIte = qf_lia;
1480 Trace("smt") << "setting ite compression to " << compressIte << endl;
1481 options::compressItes.set(compressIte);
1482 }
1483 if(! options::simplifyWithCareEnabled.wasSetByUser() ){
1484 bool qf_aufbv = !d_logic.isQuantified() &&
1485 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1486 d_logic.isTheoryEnabled(THEORY_UF) &&
1487 d_logic.isTheoryEnabled(THEORY_BV);
1488
1489 bool withCare = qf_aufbv;
1490 Trace("smt") << "setting ite simplify with care to " << withCare << endl;
1491 options::simplifyWithCareEnabled.set(withCare);
1492 }
1493 // Turn off array eager index splitting for QF_AUFLIA
1494 if(! options::arraysEagerIndexSplitting.wasSetByUser()) {
1495 if (not d_logic.isQuantified() &&
1496 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1497 d_logic.isTheoryEnabled(THEORY_UF) &&
1498 d_logic.isTheoryEnabled(THEORY_ARITH)) {
1499 Trace("smt") << "setting array eager index splitting to false" << endl;
1500 options::arraysEagerIndexSplitting.set(false);
1501 }
1502 }
1503 // Turn on model-based arrays for QF_AX (unless models are enabled)
1504 // if(! options::arraysModelBased.wasSetByUser()) {
1505 // if (not d_logic.isQuantified() &&
1506 // d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1507 // d_logic.isPure(THEORY_ARRAY) &&
1508 // !options::produceModels() &&
1509 // !options::checkModels()) {
1510 // Trace("smt") << "turning on model-based array solver" << endl;
1511 // options::arraysModelBased.set(true);
1512 // }
1513 // }
1514 // Turn on multiple-pass non-clausal simplification for QF_AUFBV
1515 if(! options::repeatSimp.wasSetByUser()) {
1516 bool repeatSimp = !d_logic.isQuantified() &&
1517 (d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1518 d_logic.isTheoryEnabled(THEORY_UF) &&
1519 d_logic.isTheoryEnabled(THEORY_BV)) &&
1520 !options::unsatCores();
1521 Trace("smt") << "setting repeat simplification to " << repeatSimp << endl;
1522 options::repeatSimp.set(repeatSimp);
1523 }
1524 // Turn on unconstrained simplification for QF_AUFBV
1525 if(!options::unconstrainedSimp.wasSetByUser() ||
1526 options::incrementalSolving()) {
1527 // bool qf_sat = d_logic.isPure(THEORY_BOOL) && !d_logic.isQuantified();
1528 // bool uncSimp = false && !qf_sat && !options::incrementalSolving();
1529 bool uncSimp = !options::incrementalSolving() &&
1530 !d_logic.isQuantified() &&
1531 !options::produceModels() &&
1532 !options::produceAssignments() &&
1533 !options::checkModels() &&
1534 !options::unsatCores() &&
1535 (d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_BV));
1536 Trace("smt") << "setting unconstrained simplification to " << uncSimp << endl;
1537 options::unconstrainedSimp.set(uncSimp);
1538 }
1539 // Unconstrained simp currently does *not* support model generation
1540 if (options::unconstrainedSimp.wasSetByUser() && options::unconstrainedSimp()) {
1541 if (options::produceModels()) {
1542 if (options::produceModels.wasSetByUser()) {
1543 throw OptionException("Cannot use unconstrained-simp with model generation.");
1544 }
1545 Notice() << "SmtEngine: turning off produce-models to support unconstrainedSimp" << endl;
1546 setOption("produce-models", SExpr("false"));
1547 }
1548 if (options::produceAssignments()) {
1549 if (options::produceAssignments.wasSetByUser()) {
1550 throw OptionException("Cannot use unconstrained-simp with model generation (produce-assignments).");
1551 }
1552 Notice() << "SmtEngine: turning off produce-assignments to support unconstrainedSimp" << endl;
1553 setOption("produce-assignments", SExpr("false"));
1554 }
1555 if (options::checkModels()) {
1556 if (options::checkModels.wasSetByUser()) {
1557 throw OptionException("Cannot use unconstrained-simp with model generation (check-models).");
1558 }
1559 Notice() << "SmtEngine: turning off check-models to support unconstrainedSimp" << endl;
1560 setOption("check-models", SExpr("false"));
1561 }
1562 }
1563
1564
1565 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
1566 options::incrementalSolving()) {
1567 if (options::incrementalSolving.wasSetByUser()) {
1568 throw OptionException(std::string("Eager bit-blasting does not currently support incremental mode. \n\
1569 Try --bitblast=lazy"));
1570 }
1571 Notice() << "SmtEngine: turning off incremental to support eager bit-blasting" << endl;
1572 setOption("incremental", SExpr("false"));
1573 }
1574
1575 if (! options::bvEagerExplanations.wasSetByUser() &&
1576 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1577 d_logic.isTheoryEnabled(THEORY_BV)) {
1578 Trace("smt") << "enabling eager bit-vector explanations " << endl;
1579 options::bvEagerExplanations.set(true);
1580 }
1581
1582 if( !options::bitvectorEqualitySolver() ){
1583 Trace("smt") << "disabling bvLazyRewriteExtf since equality solver is disabled" << endl;
1584 options::bvLazyRewriteExtf.set(false);
1585 }
1586
1587 // Turn on arith rewrite equalities only for pure arithmetic
1588 if(! options::arithRewriteEq.wasSetByUser()) {
1589 bool arithRewriteEq = d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isQuantified();
1590 Trace("smt") << "setting arith rewrite equalities " << arithRewriteEq << endl;
1591 options::arithRewriteEq.set(arithRewriteEq);
1592 }
1593 if(! options::arithHeuristicPivots.wasSetByUser()) {
1594 int16_t heuristicPivots = 5;
1595 if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()) {
1596 if(d_logic.isDifferenceLogic()) {
1597 heuristicPivots = -1;
1598 } else if(!d_logic.areIntegersUsed()) {
1599 heuristicPivots = 0;
1600 }
1601 }
1602 Trace("smt") << "setting arithHeuristicPivots " << heuristicPivots << endl;
1603 options::arithHeuristicPivots.set(heuristicPivots);
1604 }
1605 if(! options::arithPivotThreshold.wasSetByUser()){
1606 uint16_t pivotThreshold = 2;
1607 if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()){
1608 if(d_logic.isDifferenceLogic()){
1609 pivotThreshold = 16;
1610 }
1611 }
1612 Trace("smt") << "setting arith arithPivotThreshold " << pivotThreshold << endl;
1613 options::arithPivotThreshold.set(pivotThreshold);
1614 }
1615 if(! options::arithStandardCheckVarOrderPivots.wasSetByUser()){
1616 int16_t varOrderPivots = -1;
1617 if(d_logic.isPure(THEORY_ARITH) && !d_logic.isQuantified()){
1618 varOrderPivots = 200;
1619 }
1620 Trace("smt") << "setting arithStandardCheckVarOrderPivots " << varOrderPivots << endl;
1621 options::arithStandardCheckVarOrderPivots.set(varOrderPivots);
1622 }
1623 // Turn off early theory preprocessing if arithRewriteEq is on
1624 if (options::arithRewriteEq()) {
1625 d_earlyTheoryPP = false;
1626 }
1627
1628 // Set decision mode based on logic (if not set by user)
1629 if(!options::decisionMode.wasSetByUser()) {
1630 decision::DecisionMode decMode =
1631 // ALL
1632 d_logic.hasEverything() ? decision::DECISION_STRATEGY_JUSTIFICATION :
1633 ( // QF_BV
1634 (not d_logic.isQuantified() &&
1635 d_logic.isPure(THEORY_BV)
1636 ) ||
1637 // QF_AUFBV or QF_ABV or QF_UFBV
1638 (not d_logic.isQuantified() &&
1639 (d_logic.isTheoryEnabled(THEORY_ARRAY) ||
1640 d_logic.isTheoryEnabled(THEORY_UF)) &&
1641 d_logic.isTheoryEnabled(THEORY_BV)
1642 ) ||
1643 // QF_AUFLIA (and may be ends up enabling QF_AUFLRA?)
1644 (not d_logic.isQuantified() &&
1645 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1646 d_logic.isTheoryEnabled(THEORY_UF) &&
1647 d_logic.isTheoryEnabled(THEORY_ARITH)
1648 ) ||
1649 // QF_LRA
1650 (not d_logic.isQuantified() &&
1651 d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areIntegersUsed()
1652 ) ||
1653 // Quantifiers
1654 d_logic.isQuantified() ||
1655 // Strings
1656 d_logic.isTheoryEnabled(THEORY_STRINGS)
1657 ? decision::DECISION_STRATEGY_JUSTIFICATION
1658 : decision::DECISION_STRATEGY_INTERNAL
1659 );
1660
1661 bool stoponly =
1662 // ALL
1663 d_logic.hasEverything() || d_logic.isTheoryEnabled(THEORY_STRINGS) ? false :
1664 ( // QF_AUFLIA
1665 (not d_logic.isQuantified() &&
1666 d_logic.isTheoryEnabled(THEORY_ARRAY) &&
1667 d_logic.isTheoryEnabled(THEORY_UF) &&
1668 d_logic.isTheoryEnabled(THEORY_ARITH)
1669 ) ||
1670 // QF_LRA
1671 (not d_logic.isQuantified() &&
1672 d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areIntegersUsed()
1673 )
1674 ? true : false
1675 );
1676
1677 Trace("smt") << "setting decision mode to " << decMode << endl;
1678 options::decisionMode.set(decMode);
1679 options::decisionStopOnly.set(stoponly);
1680 }
1681 if( options::incrementalSolving() ){
1682 //disable modes not supported by incremental
1683 options::sortInference.set( false );
1684 options::ufssFairnessMonotone.set( false );
1685 options::quantEpr.set( false );
1686 }
1687 if( d_logic.hasCardinalityConstraints() ){
1688 //must have finite model finding on
1689 options::finiteModelFind.set( true );
1690 }
1691
1692 //if it contains a theory with non-termination, do not strictly enforce that quantifiers and theory combination must be interleaved
1693 if( d_logic.isTheoryEnabled(THEORY_STRINGS) || (d_logic.isTheoryEnabled(THEORY_ARITH) && !d_logic.isLinear()) ){
1694 if( !options::instWhenStrictInterleave.wasSetByUser() ){
1695 options::instWhenStrictInterleave.set( false );
1696 }
1697 }
1698
1699 //local theory extensions
1700 if( options::localTheoryExt() ){
1701 if( !options::instMaxLevel.wasSetByUser() ){
1702 options::instMaxLevel.set( 0 );
1703 }
1704 }
1705 if( options::instMaxLevel()!=-1 ){
1706 Notice() << "SmtEngine: turning off cbqi to support instMaxLevel" << endl;
1707 options::cbqi.set(false);
1708 }
1709 //track instantiations?
1710 if( options::cbqiNestedQE() || ( options::proof() && !options::trackInstLemmas.wasSetByUser() ) ){
1711 options::trackInstLemmas.set( true );
1712 }
1713
1714 if( ( options::fmfBoundLazy.wasSetByUser() && options::fmfBoundLazy() ) ||
1715 ( options::fmfBoundInt.wasSetByUser() && options::fmfBoundInt() ) ) {
1716 options::fmfBound.set( true );
1717 }
1718 //now have determined whether fmfBoundInt is on/off
1719 //apply fmfBoundInt options
1720 if( options::fmfBound() ){
1721 //must have finite model finding on
1722 options::finiteModelFind.set( true );
1723 if( ! options::mbqiMode.wasSetByUser() ||
1724 ( options::mbqiMode()!=quantifiers::MBQI_NONE &&
1725 options::mbqiMode()!=quantifiers::MBQI_FMC &&
1726 options::mbqiMode()!=quantifiers::MBQI_FMC_INTERVAL ) ){
1727 //if bounded integers are set, use no MBQI by default
1728 options::mbqiMode.set( quantifiers::MBQI_NONE );
1729 }
1730 if( ! options::prenexQuant.wasSetByUser() ){
1731 options::prenexQuant.set( quantifiers::PRENEX_QUANT_NONE );
1732 }
1733 }
1734 if( options::mbqiMode()==quantifiers::MBQI_ABS ){
1735 if( !d_logic.isPure(THEORY_UF) ){
1736 //MBQI_ABS is only supported in pure quantified UF
1737 options::mbqiMode.set( quantifiers::MBQI_FMC );
1738 }
1739 }
1740 if( options::ufssSymBreak() ){
1741 options::sortInference.set( true );
1742 }
1743 if( options::fmfFunWellDefinedRelevant() ){
1744 if( !options::fmfFunWellDefined.wasSetByUser() ){
1745 options::fmfFunWellDefined.set( true );
1746 }
1747 }
1748 if( options::fmfFunWellDefined() ){
1749 if( !options::finiteModelFind.wasSetByUser() ){
1750 options::finiteModelFind.set( true );
1751 }
1752 }
1753 //EPR
1754 if( options::quantEpr() ){
1755 if( !options::preSkolemQuant.wasSetByUser() ){
1756 options::preSkolemQuant.set( true );
1757 }
1758 }
1759
1760 //now, have determined whether finite model find is on/off
1761 //apply finite model finding options
1762 if( options::finiteModelFind() ){
1763 //apply conservative quantifiers splitting
1764 if( !options::quantDynamicSplit.wasSetByUser() ){
1765 options::quantDynamicSplit.set( quantifiers::QUANT_DSPLIT_MODE_DEFAULT );
1766 }
1767 //do not eliminate extended arithmetic symbols from quantified formulas
1768 if( !options::elimExtArithQuant.wasSetByUser() ){
1769 options::elimExtArithQuant.set( false );
1770 }
1771 if( !options::eMatching.wasSetByUser() ){
1772 options::eMatching.set( options::fmfInstEngine() );
1773 }
1774 if( !options::instWhenMode.wasSetByUser() ){
1775 //instantiate only on last call
1776 if( options::eMatching() ){
1777 options::instWhenMode.set( quantifiers::INST_WHEN_LAST_CALL );
1778 }
1779 }
1780 if( options::mbqiMode()==quantifiers::MBQI_ABS ){
1781 if( !options::preSkolemQuant.wasSetByUser() ){
1782 options::preSkolemQuant.set( true );
1783 }
1784 if( !options::preSkolemQuantNested.wasSetByUser() ){
1785 options::preSkolemQuantNested.set( true );
1786 }
1787 if( !options::fmfOneInstPerRound.wasSetByUser() ){
1788 options::fmfOneInstPerRound.set( true );
1789 }
1790 }
1791 }
1792
1793 //apply counterexample guided instantiation options
1794 if( options::cegqiSingleInvMode()!=quantifiers::CEGQI_SI_MODE_NONE ){
1795 if( !options::ceGuidedInst.wasSetByUser() ){
1796 options::ceGuidedInst.set( true );
1797 }
1798 }
1799 if( options::ceGuidedInst() ){
1800 //counterexample-guided instantiation for sygus
1801 if( !options::cegqiSingleInvMode.wasSetByUser() ){
1802 options::cegqiSingleInvMode.set( quantifiers::CEGQI_SI_MODE_USE );
1803 }
1804 if( !options::quantConflictFind.wasSetByUser() ){
1805 options::quantConflictFind.set( false );
1806 }
1807 if( !options::instNoEntail.wasSetByUser() ){
1808 options::instNoEntail.set( false );
1809 }
1810 //do not allow partial functions
1811 if( !options::bitvectorDivByZeroConst.wasSetByUser() ){
1812 options::bitvectorDivByZeroConst.set( true );
1813 }
1814 if( !options::dtRewriteErrorSel.wasSetByUser() ){
1815 options::dtRewriteErrorSel.set( true );
1816 }
1817 //do not miniscope
1818 if( !options::miniscopeQuant.wasSetByUser() ){
1819 options::miniscopeQuant.set( false );
1820 }
1821 if( !options::miniscopeQuantFreeVar.wasSetByUser() ){
1822 options::miniscopeQuantFreeVar.set( false );
1823 }
1824 //rewrite divk
1825 if( !options::rewriteDivk.wasSetByUser()) {
1826 options::rewriteDivk.set( true );
1827 }
1828 //do not do macros
1829 if( !options::macrosQuant.wasSetByUser()) {
1830 options::macrosQuant.set( false );
1831 }
1832 if( !options::cbqiPreRegInst.wasSetByUser()) {
1833 options::cbqiPreRegInst.set( true );
1834 }
1835 }
1836 //counterexample-guided instantiation for non-sygus
1837 // enable if any possible quantifiers with arithmetic, datatypes or bitvectors
1838 if( d_logic.isQuantified() &&
1839 ( ( options::decisionMode()!=decision::DECISION_STRATEGY_INTERNAL &&
1840 ( d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isTheoryEnabled(THEORY_DATATYPES) || d_logic.isTheoryEnabled(THEORY_BV) ) ) ||
1841 d_logic.isPure(THEORY_ARITH) || d_logic.isPure(THEORY_BV) ||
1842 options::cbqiAll() ) ){
1843 if( !options::cbqi.wasSetByUser() ){
1844 options::cbqi.set( true );
1845 }
1846 }
1847 if( options::cbqi() ){
1848 //must rewrite divk
1849 if( !options::rewriteDivk.wasSetByUser()) {
1850 options::rewriteDivk.set( true );
1851 }
1852 if( d_logic.isPure(THEORY_ARITH) ){
1853 options::cbqiAll.set( false );
1854 if( !options::quantConflictFind.wasSetByUser() ){
1855 options::quantConflictFind.set( false );
1856 }
1857 if( !options::instNoEntail.wasSetByUser() ){
1858 options::instNoEntail.set( false );
1859 }
1860 if( !options::instWhenMode.wasSetByUser() && options::cbqiModel() ){
1861 //only instantiation should happen at last call when model is avaiable
1862 options::instWhenMode.set( quantifiers::INST_WHEN_LAST_CALL );
1863 }
1864 }else{
1865 //only supported in pure arithmetic
1866 options::cbqiNestedQE.set(false);
1867 }
1868 }
1869 //implied options...
1870 if( options::strictTriggers() ){
1871 if( !options::userPatternsQuant.wasSetByUser() ){
1872 options::userPatternsQuant.set( quantifiers::USER_PAT_MODE_TRUST );
1873 }
1874 }
1875 if( options::qcfMode.wasSetByUser() || options::qcfTConstraint() ){
1876 options::quantConflictFind.set( true );
1877 }
1878 if( options::cbqi() &&
1879 ( options::cbqiNestedQE() || options::decisionMode()==decision::DECISION_STRATEGY_INTERNAL ) ){
1880 //only complete with prenex = disj_normal or normal
1881 if( options::prenexQuant()<=quantifiers::PRENEX_QUANT_DISJ_NORMAL ){
1882 options::prenexQuant.set( quantifiers::PRENEX_QUANT_DISJ_NORMAL );
1883 }
1884 }
1885 if( options::cbqiNestedQE() ){
1886 options::prenexQuantUser.set( true );
1887 if( !options::preSkolemQuant.wasSetByUser() ){
1888 options::preSkolemQuant.set( true );
1889 }
1890 }
1891 //for induction techniques
1892 if( options::quantInduction() ){
1893 if( !options::dtStcInduction.wasSetByUser() ){
1894 options::dtStcInduction.set( true );
1895 }
1896 if( !options::intWfInduction.wasSetByUser() ){
1897 options::intWfInduction.set( true );
1898 }
1899 }
1900 if( options::dtStcInduction() ){
1901 //leads to unfairness FIXME
1902 if( !options::dtForceAssignment.wasSetByUser() ){
1903 options::dtForceAssignment.set( true );
1904 }
1905 //try to remove ITEs from quantified formulas
1906 if( !options::iteDtTesterSplitQuant.wasSetByUser() ){
1907 options::iteDtTesterSplitQuant.set( true );
1908 }
1909 if( !options::iteLiftQuant.wasSetByUser() ){
1910 options::iteLiftQuant.set( quantifiers::ITE_LIFT_QUANT_MODE_ALL );
1911 }
1912 }
1913 if( options::intWfInduction() ){
1914 if( !options::purifyTriggers.wasSetByUser() ){
1915 options::purifyTriggers.set( true );
1916 }
1917 }
1918 if( options::conjectureNoFilter() ){
1919 if( !options::conjectureFilterActiveTerms.wasSetByUser() ){
1920 options::conjectureFilterActiveTerms.set( false );
1921 }
1922 if( !options::conjectureFilterCanonical.wasSetByUser() ){
1923 options::conjectureFilterCanonical.set( false );
1924 }
1925 if( !options::conjectureFilterModel.wasSetByUser() ){
1926 options::conjectureFilterModel.set( false );
1927 }
1928 }
1929 if( options::conjectureGenPerRound.wasSetByUser() ){
1930 if( options::conjectureGenPerRound()>0 ){
1931 options::conjectureGen.set( true );
1932 }else{
1933 options::conjectureGen.set( false );
1934 }
1935 }
1936 //can't pre-skolemize nested quantifiers without UF theory
1937 if( !d_logic.isTheoryEnabled(THEORY_UF) && options::preSkolemQuant() ){
1938 if( !options::preSkolemQuantNested.wasSetByUser() ){
1939 options::preSkolemQuantNested.set( false );
1940 }
1941 }
1942 if( !d_logic.isTheoryEnabled(THEORY_DATATYPES) ){
1943 options::quantDynamicSplit.set( quantifiers::QUANT_DSPLIT_MODE_NONE );
1944 }
1945
1946 //until bugs 371,431 are fixed
1947 if( ! options::minisatUseElim.wasSetByUser()){
1948 //AJR: cannot use minisat elim for new implementation of sets TODO: why?
1949 if( d_logic.isTheoryEnabled(THEORY_SETS) || d_logic.isQuantified() || options::produceModels() || options::produceAssignments() || options::checkModels() ){
1950 options::minisatUseElim.set( false );
1951 }
1952 }
1953 else if (options::minisatUseElim()) {
1954 if (options::produceModels()) {
1955 Notice() << "SmtEngine: turning off produce-models to support minisatUseElim" << endl;
1956 setOption("produce-models", SExpr("false"));
1957 }
1958 if (options::produceAssignments()) {
1959 Notice() << "SmtEngine: turning off produce-assignments to support minisatUseElim" << endl;
1960 setOption("produce-assignments", SExpr("false"));
1961 }
1962 if (options::checkModels()) {
1963 Notice() << "SmtEngine: turning off check-models to support minisatUseElim" << endl;
1964 setOption("check-models", SExpr("false"));
1965 }
1966 }
1967
1968 // For now, these array theory optimizations do not support model-building
1969 if (options::produceModels() || options::produceAssignments() || options::checkModels()) {
1970 options::arraysOptimizeLinear.set(false);
1971 options::arraysLazyRIntro1.set(false);
1972 }
1973
1974 // Non-linear arithmetic does not support models unless nlExt is enabled
1975 if (d_logic.isTheoryEnabled(THEORY_ARITH) && !d_logic.isLinear() && !options::nlExt() ) {
1976 if (options::produceModels()) {
1977 if(options::produceModels.wasSetByUser()) {
1978 throw OptionException("produce-model not supported with nonlinear arith");
1979 }
1980 Warning() << "SmtEngine: turning off produce-models because unsupported for nonlinear arith" << endl;
1981 setOption("produce-models", SExpr("false"));
1982 }
1983 if (options::produceAssignments()) {
1984 if(options::produceAssignments.wasSetByUser()) {
1985 throw OptionException("produce-assignments not supported with nonlinear arith");
1986 }
1987 Warning() << "SmtEngine: turning off produce-assignments because unsupported for nonlinear arith" << endl;
1988 setOption("produce-assignments", SExpr("false"));
1989 }
1990 if (options::checkModels()) {
1991 if(options::checkModels.wasSetByUser()) {
1992 throw OptionException("check-models not supported with nonlinear arith");
1993 }
1994 Warning() << "SmtEngine: turning off check-models because unsupported for nonlinear arith" << endl;
1995 setOption("check-models", SExpr("false"));
1996 }
1997 }
1998
1999 if(options::incrementalSolving() && options::proof()) {
2000 Warning() << "SmtEngine: turning off incremental solving mode (not yet supported with --proof, try --tear-down-incremental instead)" << endl;
2001 setOption("incremental", SExpr("false"));
2002 }
2003 }
2004
2005 void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
2006 throw(OptionException, ModalException) {
2007
2008 SmtScope smts(this);
2009
2010 Trace("smt") << "SMT setInfo(" << key << ", " << value << ")" << endl;
2011
2012 if(Dump.isOn("benchmark")) {
2013 if(key == "status") {
2014 string s = value.getValue();
2015 BenchmarkStatus status =
2016 (s == "sat") ? SMT_SATISFIABLE :
2017 ((s == "unsat") ? SMT_UNSATISFIABLE : SMT_UNKNOWN);
2018 Dump("benchmark") << SetBenchmarkStatusCommand(status);
2019 } else {
2020 Dump("benchmark") << SetInfoCommand(key, value);
2021 }
2022 }
2023
2024 // Check for CVC4-specific info keys (prefixed with "cvc4-" or "cvc4_")
2025 if(key.length() > 5) {
2026 string prefix = key.substr(0, 5);
2027 if(prefix == "cvc4-" || prefix == "cvc4_") {
2028 string cvc4key = key.substr(5);
2029 if(cvc4key == "logic") {
2030 if(! value.isAtom()) {
2031 throw OptionException("argument to (set-info :cvc4-logic ..) must be a string");
2032 }
2033 SmtScope smts(this);
2034 d_logic = value.getValue();
2035 setLogicInternal();
2036 return;
2037 } else {
2038 throw UnrecognizedOptionException();
2039 }
2040 }
2041 }
2042
2043 // Check for standard info keys (SMT-LIB v1, SMT-LIB v2, ...)
2044 if(key == "source" ||
2045 key == "category" ||
2046 key == "difficulty" ||
2047 key == "notes") {
2048 // ignore these
2049 return;
2050 } else if(key == "name") {
2051 d_filename = value.getValue();
2052 return;
2053 } else if(key == "smt-lib-version") {
2054 if( (value.isInteger() && value.getIntegerValue() == Integer(2)) ||
2055 (value.isRational() && value.getRationalValue() == Rational(2)) ||
2056 value.getValue() == "2" ||
2057 value.getValue() == "2.0" ) {
2058 // supported SMT-LIB version
2059 if(!options::outputLanguage.wasSetByUser() &&
2060 ( options::outputLanguage() == language::output::LANG_SMTLIB_V2_5 || options::outputLanguage() == language::output::LANG_SMTLIB_V2_6 )) {
2061 options::outputLanguage.set(language::output::LANG_SMTLIB_V2_0);
2062 *options::out() << language::SetLanguage(language::output::LANG_SMTLIB_V2_0);
2063 }
2064 return;
2065 } else if( (value.isRational() && value.getRationalValue() == Rational(5, 2)) ||
2066 value.getValue() == "2.5" ) {
2067 // supported SMT-LIB version
2068 if(!options::outputLanguage.wasSetByUser() &&
2069 options::outputLanguage() == language::output::LANG_SMTLIB_V2_0) {
2070 options::outputLanguage.set(language::output::LANG_SMTLIB_V2_5);
2071 *options::out() << language::SetLanguage(language::output::LANG_SMTLIB_V2_5);
2072 }
2073 return;
2074 } else if( (value.isRational() && value.getRationalValue() == Rational(13, 5)) ||
2075 value.getValue() == "2.6" ) {
2076 // supported SMT-LIB version
2077 if(!options::outputLanguage.wasSetByUser() &&
2078 options::outputLanguage() == language::output::LANG_SMTLIB_V2_0) {
2079 options::outputLanguage.set(language::output::LANG_SMTLIB_V2_6);
2080 *options::out() << language::SetLanguage(language::output::LANG_SMTLIB_V2_6);
2081 }
2082 return;
2083 }
2084 Warning() << "Warning: unsupported smt-lib-version: " << value << endl;
2085 throw UnrecognizedOptionException();
2086 } else if(key == "status") {
2087 string s;
2088 if(value.isAtom()) {
2089 s = value.getValue();
2090 }
2091 if(s != "sat" && s != "unsat" && s != "unknown") {
2092 throw OptionException("argument to (set-info :status ..) must be "
2093 "`sat' or `unsat' or `unknown'");
2094 }
2095 d_status = Result(s, d_filename);
2096 return;
2097 }
2098 throw UnrecognizedOptionException();
2099 }
2100
2101 CVC4::SExpr SmtEngine::getInfo(const std::string& key) const {
2102
2103 SmtScope smts(this);
2104
2105 Trace("smt") << "SMT getInfo(" << key << ")" << endl;
2106 if(key == "all-statistics") {
2107 vector<SExpr> stats;
2108 for(StatisticsRegistry::const_iterator i = NodeManager::fromExprManager(d_exprManager)->getStatisticsRegistry()->begin();
2109 i != NodeManager::fromExprManager(d_exprManager)->getStatisticsRegistry()->end();
2110 ++i) {
2111 vector<SExpr> v;
2112 v.push_back((*i).first);
2113 v.push_back((*i).second);
2114 stats.push_back(v);
2115 }
2116 for(StatisticsRegistry::const_iterator i = d_statisticsRegistry->begin();
2117 i != d_statisticsRegistry->end();
2118 ++i) {
2119 vector<SExpr> v;
2120 v.push_back((*i).first);
2121 v.push_back((*i).second);
2122 stats.push_back(v);
2123 }
2124 return SExpr(stats);
2125 } else if(key == "error-behavior") {
2126 // immediate-exit | continued-execution
2127 if( options::continuedExecution() || options::interactive() ) {
2128 return SExpr(SExpr::Keyword("continued-execution"));
2129 } else {
2130 return SExpr(SExpr::Keyword("immediate-exit"));
2131 }
2132 } else if(key == "name") {
2133 return SExpr(Configuration::getName());
2134 } else if(key == "version") {
2135 return SExpr(Configuration::getVersionString());
2136 } else if(key == "authors") {
2137 return SExpr(Configuration::about());
2138 } else if(key == "status") {
2139 // sat | unsat | unknown
2140 switch(d_status.asSatisfiabilityResult().isSat()) {
2141 case Result::SAT:
2142 return SExpr(SExpr::Keyword("sat"));
2143 case Result::UNSAT:
2144 return SExpr(SExpr::Keyword("unsat"));
2145 default:
2146 return SExpr(SExpr::Keyword("unknown"));
2147 }
2148 } else if(key == "reason-unknown") {
2149 if(!d_status.isNull() && d_status.isUnknown()) {
2150 stringstream ss;
2151 ss << d_status.whyUnknown();
2152 string s = ss.str();
2153 transform(s.begin(), s.end(), s.begin(), ::tolower);
2154 return SExpr(SExpr::Keyword(s));
2155 } else {
2156 throw ModalException("Can't get-info :reason-unknown when the "
2157 "last result wasn't unknown!");
2158 }
2159 } else if(key == "assertion-stack-levels") {
2160 AlwaysAssert(d_userLevels.size() <=
2161 std::numeric_limits<unsigned long int>::max());
2162 return SExpr(static_cast<unsigned long int>(d_userLevels.size()));
2163 } else if(key == "all-options") {
2164 // get the options, like all-statistics
2165 std::vector< std::vector<std::string> > current_options =
2166 Options::current()->getOptions();
2167 return SExpr::parseListOfListOfAtoms(current_options);
2168 } else {
2169 throw UnrecognizedOptionException();
2170 }
2171 }
2172
2173 void SmtEngine::defineFunction(Expr func,
2174 const std::vector<Expr>& formals,
2175 Expr formula) {
2176 SmtScope smts(this);
2177 doPendingPops();
2178 Trace("smt") << "SMT defineFunction(" << func << ")" << endl;
2179 for(std::vector<Expr>::const_iterator i = formals.begin(); i != formals.end(); ++i) {
2180 if((*i).getKind() != kind::BOUND_VARIABLE) {
2181 stringstream ss;
2182 ss << "All formal arguments to defined functions must be BOUND_VARIABLEs, but in the\n"
2183 << "definition of function " << func << ", formal\n"
2184 << " " << *i << "\n"
2185 << "has kind " << (*i).getKind();
2186 throw TypeCheckingException(func, ss.str());
2187 }
2188 }
2189
2190 stringstream ss;
2191 ss << language::SetLanguage(language::SetLanguage::getLanguage(Dump.getStream()))
2192 << func;
2193 DefineFunctionCommand c(ss.str(), func, formals, formula);
2194 addToModelCommandAndDump(c, ExprManager::VAR_FLAG_DEFINED, true, "declarations");
2195
2196
2197 PROOF( if (options::checkUnsatCores()) {
2198 d_defineCommands.push_back(c.clone());
2199 });
2200
2201
2202 // Substitute out any abstract values in formula
2203 Expr form = d_private->substituteAbstractValues(Node::fromExpr(formula)).toExpr();
2204
2205 // type check body
2206 Type formulaType = form.getType(options::typeChecking());
2207
2208 Type funcType = func.getType();
2209 // We distinguish here between definitions of constants and functions,
2210 // because the type checking for them is subtly different. Perhaps we
2211 // should instead have SmtEngine::defineFunction() and
2212 // SmtEngine::defineConstant() for better clarity, although then that
2213 // doesn't match the SMT-LIBv2 standard...
2214 if(formals.size() > 0) {
2215 Type rangeType = FunctionType(funcType).getRangeType();
2216 if(! formulaType.isComparableTo(rangeType)) {
2217 stringstream ss;
2218 ss << "Type of defined function does not match its declaration\n"
2219 << "The function : " << func << "\n"
2220 << "Declared type : " << rangeType << "\n"
2221 << "The body : " << formula << "\n"
2222 << "Body type : " << formulaType;
2223 throw TypeCheckingException(func, ss.str());
2224 }
2225 } else {
2226 if(! formulaType.isComparableTo(funcType)) {
2227 stringstream ss;
2228 ss << "Declared type of defined constant does not match its definition\n"
2229 << "The constant : " << func << "\n"
2230 << "Declared type : " << funcType << " " << Type::getTypeNode(funcType)->getId() << "\n"
2231 << "The definition : " << formula << "\n"
2232 << "Definition type: " << formulaType << " " << Type::getTypeNode(formulaType)->getId();
2233 throw TypeCheckingException(func, ss.str());
2234 }
2235 }
2236 TNode funcNode = func.getTNode();
2237 vector<Node> formalsNodes;
2238 for(vector<Expr>::const_iterator i = formals.begin(),
2239 iend = formals.end();
2240 i != iend;
2241 ++i) {
2242 formalsNodes.push_back((*i).getNode());
2243 }
2244 TNode formNode = form.getTNode();
2245 DefinedFunction def(funcNode, formalsNodes, formNode);
2246 // Permit (check-sat) (define-fun ...) (get-value ...) sequences.
2247 // Otherwise, (check-sat) (get-value ((! foo :named bar))) breaks
2248 // d_haveAdditions = true;
2249 Debug("smt") << "definedFunctions insert " << funcNode << " " << formNode << endl;
2250 d_definedFunctions->insert(funcNode, def);
2251 }
2252
2253 bool SmtEngine::isDefinedFunction( Expr func ){
2254 Node nf = Node::fromExpr( func );
2255 Debug("smt") << "isDefined function " << nf << "?" << std::endl;
2256 return d_definedFunctions->find(nf) != d_definedFunctions->end();
2257 }
2258
2259 Node SmtEnginePrivate::expandDefinitions(TNode n, unordered_map<Node, Node, NodeHashFunction>& cache, bool expandOnly)
2260 throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
2261
2262 stack< triple<Node, Node, bool> > worklist;
2263 stack<Node> result;
2264 worklist.push(make_triple(Node(n), Node(n), false));
2265 // The worklist is made of triples, each is input / original node then the output / rewritten node
2266 // and finally a flag tracking whether the children have been explored (i.e. if this is a downward
2267 // or upward pass).
2268
2269 do {
2270 spendResource(options::preprocessStep());
2271 n = worklist.top().first; // n is the input / original
2272 Node node = worklist.top().second; // node is the output / result
2273 bool childrenPushed = worklist.top().third;
2274 worklist.pop();
2275
2276 // Working downwards
2277 if(!childrenPushed) {
2278 Kind k = n.getKind();
2279
2280 // we can short circuit (variable) leaves
2281 if(n.isVar()) {
2282 SmtEngine::DefinedFunctionMap::const_iterator i = d_smt.d_definedFunctions->find(n);
2283 if(i != d_smt.d_definedFunctions->end()) {
2284 // replacement must be closed
2285 if((*i).second.getFormals().size() > 0) {
2286 result.push(d_smt.d_nodeManager->mkNode(kind::LAMBDA, d_smt.d_nodeManager->mkNode(kind::BOUND_VAR_LIST, (*i).second.getFormals()), (*i).second.getFormula()));
2287 continue;
2288 }
2289 // don't bother putting in the cache
2290 result.push((*i).second.getFormula());
2291 continue;
2292 }
2293 // don't bother putting in the cache
2294 result.push(n);
2295 continue;
2296 }
2297
2298 // maybe it's in the cache
2299 unordered_map<Node, Node, NodeHashFunction>::iterator cacheHit = cache.find(n);
2300 if(cacheHit != cache.end()) {
2301 TNode ret = (*cacheHit).second;
2302 result.push(ret.isNull() ? n : ret);
2303 continue;
2304 }
2305
2306 // otherwise expand it
2307 bool doExpand = k == kind::APPLY;
2308 if( !doExpand ){
2309 if( options::macrosQuant() ){
2310 //expand if we have inferred an operator corresponds to a defined function
2311 doExpand = k==kind::APPLY_UF && d_smt.isDefinedFunction( n.getOperator().toExpr() );
2312 }
2313 }
2314 if (doExpand) {
2315 vector<Node> formals;
2316 TNode fm;
2317 if( n.getOperator().getKind() == kind::LAMBDA ){
2318 TNode op = n.getOperator();
2319 // lambda
2320 for( unsigned i=0; i<op[0].getNumChildren(); i++ ){
2321 formals.push_back( op[0][i] );
2322 }
2323 fm = op[1];
2324 }else{
2325 // application of a user-defined symbol
2326 TNode func = n.getOperator();
2327 SmtEngine::DefinedFunctionMap::const_iterator i = d_smt.d_definedFunctions->find(func);
2328 if(i == d_smt.d_definedFunctions->end()) {
2329 throw TypeCheckingException(n.toExpr(), string("Undefined function: `") + func.toString() + "'");
2330 }
2331 DefinedFunction def = (*i).second;
2332 formals = def.getFormals();
2333
2334 if(Debug.isOn("expand")) {
2335 Debug("expand") << "found: " << n << endl;
2336 Debug("expand") << " func: " << func << endl;
2337 string name = func.getAttribute(expr::VarNameAttr());
2338 Debug("expand") << " : \"" << name << "\"" << endl;
2339 }
2340 if(Debug.isOn("expand")) {
2341 Debug("expand") << " defn: " << def.getFunction() << endl
2342 << " [";
2343 if(formals.size() > 0) {
2344 copy( formals.begin(), formals.end() - 1,
2345 ostream_iterator<Node>(Debug("expand"), ", ") );
2346 Debug("expand") << formals.back();
2347 }
2348 Debug("expand") << "]" << endl
2349 << " " << def.getFunction().getType() << endl
2350 << " " << def.getFormula() << endl;
2351 }
2352
2353 fm = def.getFormula();
2354 }
2355
2356 Node instance = fm.substitute(formals.begin(), formals.end(),
2357 n.begin(), n.end());
2358 Debug("expand") << "made : " << instance << endl;
2359
2360 Node expanded = expandDefinitions(instance, cache, expandOnly);
2361 cache[n] = (n == expanded ? Node::null() : expanded);
2362 result.push(expanded);
2363 continue;
2364
2365 } else if(! expandOnly) {
2366 // do not do any theory stuff if expandOnly is true
2367
2368 theory::Theory* t = d_smt.d_theoryEngine->theoryOf(node);
2369
2370 Assert(t != NULL);
2371 LogicRequest req(d_smt);
2372 node = t->expandDefinition(req, n);
2373 }
2374
2375 // the partial functions can fall through, in which case we still
2376 // consider their children
2377 worklist.push(make_triple(Node(n), node, true)); // Original and rewritten result
2378
2379 for(size_t i = 0; i < node.getNumChildren(); ++i) {
2380 worklist.push(make_triple(node[i], node[i], false)); // Rewrite the children of the result only
2381 }
2382
2383 } else {
2384 // Working upwards
2385 // Reconstruct the node from it's (now rewritten) children on the stack
2386
2387 Debug("expand") << "cons : " << node << endl;
2388 if(node.getNumChildren()>0) {
2389 //cout << "cons : " << node << endl;
2390 NodeBuilder<> nb(node.getKind());
2391 if(node.getMetaKind() == kind::metakind::PARAMETERIZED) {
2392 Debug("expand") << "op : " << node.getOperator() << endl;
2393 //cout << "op : " << node.getOperator() << endl;
2394 nb << node.getOperator();
2395 }
2396 for(size_t i = 0; i < node.getNumChildren(); ++i) {
2397 Assert(!result.empty());
2398 Node expanded = result.top();
2399 result.pop();
2400 //cout << "exchld : " << expanded << endl;
2401 Debug("expand") << "exchld : " << expanded << endl;
2402 nb << expanded;
2403 }
2404 node = nb;
2405 }
2406 cache[n] = n == node ? Node::null() : node; // Only cache once all subterms are expanded
2407 result.push(node);
2408 }
2409 } while(!worklist.empty());
2410
2411 AlwaysAssert(result.size() == 1);
2412
2413 return result.top();
2414 }
2415
2416 //TODO: clean this up
2417 struct intToBV_stack_element {
2418 TNode node;
2419 bool children_added;
2420 intToBV_stack_element(TNode node)
2421 : node(node), children_added(false) {}
2422 };/* struct intToBV_stack_element */
2423
2424 typedef std::unordered_map<Node, Node, NodeHashFunction> NodeMap;
2425
2426 Node SmtEnginePrivate::intToBVMakeBinary(TNode n, NodeMap& cache) {
2427 // Do a topological sort of the subexpressions and substitute them
2428 vector<intToBV_stack_element> toVisit;
2429 toVisit.push_back(n);
2430
2431 while (!toVisit.empty())
2432 {
2433 // The current node we are processing
2434 intToBV_stack_element& stackHead = toVisit.back();
2435 TNode current = stackHead.node;
2436
2437 NodeMap::iterator find = cache.find(current);
2438 if (find != cache.end()) {
2439 toVisit.pop_back();
2440 continue;
2441 }
2442 if (stackHead.children_added) {
2443 // Children have been processed, so rebuild this node
2444 Node result;
2445 NodeManager* nm = NodeManager::currentNM();
2446 if (current.getNumChildren() > 2 && (current.getKind() == kind::PLUS || current.getKind() == kind::MULT)) {
2447 Assert(cache.find(current[0]) != cache.end());
2448 result = cache[current[0]];
2449 for (unsigned i = 1; i < current.getNumChildren(); ++ i) {
2450 Assert(cache.find(current[i]) != cache.end());
2451 Node child = current[i];
2452 Node childRes = cache[current[i]];
2453 result = nm->mkNode(current.getKind(), result, childRes);
2454 }
2455 }
2456 else {
2457 NodeBuilder<> builder(current.getKind());
2458 for (unsigned i = 0; i < current.getNumChildren(); ++ i) {
2459 Assert(cache.find(current[i]) != cache.end());
2460 builder << cache[current[i]];
2461 }
2462 result = builder;
2463 }
2464 cache[current] = result;
2465 toVisit.pop_back();
2466 } else {
2467 // Mark that we have added the children if any
2468 if (current.getNumChildren() > 0) {
2469 stackHead.children_added = true;
2470 // We need to add the children
2471 for(TNode::iterator child_it = current.begin(); child_it != current.end(); ++ child_it) {
2472 TNode childNode = *child_it;
2473 NodeMap::iterator childFind = cache.find(childNode);
2474 if (childFind == cache.end()) {
2475 toVisit.push_back(childNode);
2476 }
2477 }
2478 } else {
2479 cache[current] = current;
2480 toVisit.pop_back();
2481 }
2482 }
2483 }
2484 return cache[n];
2485 }
2486
2487 Node SmtEnginePrivate::intToBV(TNode n, NodeMap& cache) {
2488 int size = options::solveIntAsBV();
2489 AlwaysAssert(size > 0);
2490 AlwaysAssert(!options::incrementalSolving());
2491
2492 vector<intToBV_stack_element> toVisit;
2493 NodeMap binaryCache;
2494 Node n_binary = intToBVMakeBinary(n, binaryCache);
2495 toVisit.push_back(TNode(n_binary));
2496
2497 while (!toVisit.empty())
2498 {
2499 // The current node we are processing
2500 intToBV_stack_element& stackHead = toVisit.back();
2501 TNode current = stackHead.node;
2502
2503 // If node is already in the cache we're done, pop from the stack
2504 NodeMap::iterator find = cache.find(current);
2505 if (find != cache.end()) {
2506 toVisit.pop_back();
2507 continue;
2508 }
2509
2510 // Not yet substituted, so process
2511 NodeManager* nm = NodeManager::currentNM();
2512 if (stackHead.children_added) {
2513 // Children have been processed, so rebuild this node
2514 vector<Node> children;
2515 unsigned max = 0;
2516 for (unsigned i = 0; i < current.getNumChildren(); ++ i) {
2517 Assert(cache.find(current[i]) != cache.end());
2518 TNode childRes = cache[current[i]];
2519 TypeNode type = childRes.getType();
2520 if (type.isBitVector()) {
2521 unsigned bvsize = type.getBitVectorSize();
2522 if (bvsize > max) {
2523 max = bvsize;
2524 }
2525 }
2526 children.push_back(childRes);
2527 }
2528
2529 kind::Kind_t newKind = current.getKind();
2530 if (max > 0) {
2531 switch (newKind) {
2532 case kind::PLUS:
2533 Assert(children.size() == 2);
2534 newKind = kind::BITVECTOR_PLUS;
2535 max = max + 1;
2536 break;
2537 case kind::MULT:
2538 Assert(children.size() == 2);
2539 newKind = kind::BITVECTOR_MULT;
2540 max = max * 2;
2541 break;
2542 case kind::MINUS:
2543 Assert(children.size() == 2);
2544 newKind = kind::BITVECTOR_SUB;
2545 max = max + 1;
2546 break;
2547 case kind::UMINUS:
2548 Assert(children.size() == 1);
2549 newKind = kind::BITVECTOR_NEG;
2550 max = max + 1;
2551 break;
2552 case kind::LT:
2553 newKind = kind::BITVECTOR_SLT;
2554 break;
2555 case kind::LEQ:
2556 newKind = kind::BITVECTOR_SLE;
2557 break;
2558 case kind::GT:
2559 newKind = kind::BITVECTOR_SGT;
2560 break;
2561 case kind::GEQ:
2562 newKind = kind::BITVECTOR_SGE;
2563 break;
2564 case kind::EQUAL:
2565 case kind::ITE:
2566 break;
2567 default:
2568 if (Theory::theoryOf(current) == THEORY_BOOL) {
2569 break;
2570 }
2571 throw TypeCheckingException(current.toExpr(), string("Cannot translate to BV: ") + current.toString());
2572 }
2573 for (unsigned i = 0; i < children.size(); ++i) {
2574 TypeNode type = children[i].getType();
2575 if (!type.isBitVector()) {
2576 continue;
2577 }
2578 unsigned bvsize = type.getBitVectorSize();
2579 if (bvsize < max) {
2580 // sign extend
2581 Node signExtendOp = nm->mkConst<BitVectorSignExtend>(BitVectorSignExtend(max - bvsize));
2582 children[i] = nm->mkNode(signExtendOp, children[i]);
2583 }
2584 }
2585 }
2586 NodeBuilder<> builder(newKind);
2587 for (unsigned i = 0; i < children.size(); ++i) {
2588 builder << children[i];
2589 }
2590 // Mark the substitution and continue
2591 Node result = builder;
2592
2593 result = Rewriter::rewrite(result);
2594 cache[current] = result;
2595 toVisit.pop_back();
2596 } else {
2597 // Mark that we have added the children if any
2598 if (current.getNumChildren() > 0) {
2599 stackHead.children_added = true;
2600 // We need to add the children
2601 for(TNode::iterator child_it = current.begin(); child_it != current.end(); ++ child_it) {
2602 TNode childNode = *child_it;
2603 NodeMap::iterator childFind = cache.find(childNode);
2604 if (childFind == cache.end()) {
2605 toVisit.push_back(childNode);
2606 }
2607 }
2608 } else {
2609 // It's a leaf: could be a variable or a numeral
2610 Node result = current;
2611 if (current.isVar()) {
2612 if (current.getType() == nm->integerType()) {
2613 result = nm->mkSkolem("__intToBV_var", nm->mkBitVectorType(size),
2614 "Variable introduced in intToBV pass");
2615 }
2616 else {
2617 AlwaysAssert(current.getType() == nm->booleanType());
2618 }
2619 }
2620 else if (current.isConst()) {
2621 switch (current.getKind()) {
2622 case kind::CONST_RATIONAL: {
2623 Rational constant = current.getConst<Rational>();
2624 AlwaysAssert(constant.isIntegral());
2625 AlwaysAssert(constant >= 0);
2626 BitVector bv(size, constant.getNumerator());
2627 if (bv.toSignedInt() != constant.getNumerator()) {
2628 throw TypeCheckingException(current.toExpr(), string("Not enough bits for constant in intToBV: ") + current.toString());
2629 }
2630 result = nm->mkConst(bv);
2631 break;
2632 }
2633 case kind::CONST_BOOLEAN:
2634 break;
2635 default:
2636 throw TypeCheckingException(current.toExpr(), string("Cannot translate const to BV: ") + current.toString());
2637 }
2638 }
2639 else {
2640 throw TypeCheckingException(current.toExpr(), string("Cannot translate to BV: ") + current.toString());
2641 }
2642 cache[current] = result;
2643 toVisit.pop_back();
2644 }
2645 }
2646 }
2647 return cache[n_binary];
2648 }
2649
2650 Node SmtEnginePrivate::realToInt(TNode n, NodeMap& cache, std::vector< Node >& var_eq) {
2651 Trace("real-as-int-debug") << "Convert : " << n << std::endl;
2652 NodeMap::iterator find = cache.find(n);
2653 if (find != cache.end()) {
2654 return (*find).second;
2655 }else{
2656 Node ret = n;
2657 if( n.getNumChildren()>0 ){
2658 if( n.getKind()==kind::EQUAL || n.getKind()==kind::GEQ || n.getKind()==kind::LT || n.getKind()==kind::GT || n.getKind()==kind::LEQ ){
2659 ret = Rewriter::rewrite( n );
2660 Trace("real-as-int-debug") << "Now looking at : " << ret << std::endl;
2661 if( !ret.isConst() ){
2662 Node ret_lit = ret.getKind()==kind::NOT ? ret[0] : ret;
2663 bool ret_pol = ret.getKind()!=kind::NOT;
2664 std::map< Node, Node > msum;
2665 if( QuantArith::getMonomialSumLit( ret_lit, msum ) ){
2666 //get common coefficient
2667 std::vector< Node > coeffs;
2668 for( std::map< Node, Node >::iterator itm = msum.begin(); itm != msum.end(); ++itm ){
2669 Node v = itm->first;
2670 Node c = itm->second;
2671 if( !c.isNull() ){
2672 Assert( c.isConst() );
2673 coeffs.push_back( NodeManager::currentNM()->mkConst( Rational( c.getConst<Rational>().getDenominator() ) ) );
2674 }
2675 }
2676 Node cc = coeffs.empty() ? Node::null() : ( coeffs.size()==1 ? coeffs[0] : Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::MULT, coeffs ) ) );
2677 std::vector< Node > sum;
2678 for( std::map< Node, Node >::iterator itm = msum.begin(); itm != msum.end(); ++itm ){
2679 Node v = itm->first;
2680 Node c = itm->second;
2681 Node s;
2682 if( c.isNull() ){
2683 c = cc.isNull() ? NodeManager::currentNM()->mkConst( Rational( 1 ) ) : cc;
2684 }else{
2685 if( !cc.isNull() ){
2686 c = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::MULT, c, cc ) );
2687 }
2688 }
2689 Assert( c.getType().isInteger() );
2690 if( v.isNull() ){
2691 sum.push_back( c );
2692 }else{
2693 Node vv = realToInt( v, cache, var_eq );
2694 if( vv.getType().isInteger() ){
2695 sum.push_back( NodeManager::currentNM()->mkNode( kind::MULT, c, vv ) );
2696 }else{
2697 throw TypeCheckingException(v.toExpr(), string("Cannot translate to Int: ") + v.toString());
2698 }
2699 }
2700 }
2701 Node sumt = sum.empty() ? NodeManager::currentNM()->mkConst( Rational( 0 ) ) : ( sum.size()==1 ? sum[0] : NodeManager::currentNM()->mkNode( kind::PLUS, sum ) );
2702 ret = NodeManager::currentNM()->mkNode( ret_lit.getKind(), sumt, NodeManager::currentNM()->mkConst( Rational( 0 ) ) );
2703 if( !ret_pol ){
2704 ret = ret.negate();
2705 }
2706 Trace("real-as-int") << "Convert : " << std::endl;
2707 Trace("real-as-int") << " " << n << std::endl;
2708 Trace("real-as-int") << " " << ret << std::endl;
2709 }else{
2710 throw TypeCheckingException(n.toExpr(), string("Cannot translate to Int: ") + n.toString());
2711 }
2712 }
2713 }else{
2714 bool childChanged = false;
2715 std::vector< Node > children;
2716 for( unsigned i=0; i<n.getNumChildren(); i++ ){
2717 Node nc = realToInt( n[i], cache, var_eq );
2718 childChanged = childChanged || nc!=n[i];
2719 children.push_back( nc );
2720 }
2721 if( childChanged ){
2722 ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
2723 }
2724 }
2725 }else{
2726 if( n.isVar() ){
2727 if( !n.getType().isInteger() ){
2728 ret = NodeManager::currentNM()->mkSkolem("__realToInt_var", NodeManager::currentNM()->integerType(), "Variable introduced in realToInt pass");
2729 var_eq.push_back( n.eqNode( ret ) );
2730 }
2731 }
2732 }
2733 cache[n] = ret;
2734 return ret;
2735 }
2736 }
2737
2738 Node SmtEnginePrivate::purifyNlTerms(TNode n, NodeMap& cache, NodeMap& bcache, std::vector< Node >& var_eq, bool beneathMult) {
2739 if( beneathMult ){
2740 NodeMap::iterator find = bcache.find(n);
2741 if (find != bcache.end()) {
2742 return (*find).second;
2743 }
2744 }else{
2745 NodeMap::iterator find = cache.find(n);
2746 if (find != cache.end()) {
2747 return (*find).second;
2748 }
2749 }
2750 Node ret = n;
2751 if( n.getNumChildren()>0 ){
2752 if( beneathMult && n.getKind()!=kind::MULT ){
2753 //new variable
2754 ret = NodeManager::currentNM()->mkSkolem("__purifyNl_var", n.getType(), "Variable introduced in purifyNl pass");
2755 Node np = purifyNlTerms( n, cache, bcache, var_eq, false );
2756 var_eq.push_back( np.eqNode( ret ) );
2757 }else{
2758 bool beneathMultNew = beneathMult || n.getKind()==kind::MULT;
2759 bool childChanged = false;
2760 std::vector< Node > children;
2761 for( unsigned i=0; i<n.getNumChildren(); i++ ){
2762 Node nc = purifyNlTerms( n[i], cache, bcache, var_eq, beneathMultNew );
2763 childChanged = childChanged || nc!=n[i];
2764 children.push_back( nc );
2765 }
2766 if( childChanged ){
2767 ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
2768 }
2769 }
2770 }
2771 if( beneathMult ){
2772 bcache[n] = ret;
2773 }else{
2774 cache[n] = ret;
2775 }
2776 return ret;
2777 }
2778
2779 void SmtEnginePrivate::removeITEs() {
2780 d_smt.finalOptionsAreSet();
2781 spendResource(options::preprocessStep());
2782 Trace("simplify") << "SmtEnginePrivate::removeITEs()" << endl;
2783
2784 // Remove all of the ITE occurrences and normalize
2785 d_iteRemover.run(d_assertions.ref(), d_iteSkolemMap, true);
2786 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
2787 d_assertions.replace(i, Rewriter::rewrite(d_assertions[i]));
2788 }
2789 }
2790
2791 void SmtEnginePrivate::staticLearning() {
2792 d_smt.finalOptionsAreSet();
2793 spendResource(options::preprocessStep());
2794
2795 TimerStat::CodeTimer staticLearningTimer(d_smt.d_stats->d_staticLearningTime);
2796
2797 Trace("simplify") << "SmtEnginePrivate::staticLearning()" << endl;
2798
2799 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
2800
2801 NodeBuilder<> learned(kind::AND);
2802 learned << d_assertions[i];
2803 d_smt.d_theoryEngine->ppStaticLearn(d_assertions[i], learned);
2804 if(learned.getNumChildren() == 1) {
2805 learned.clear();
2806 } else {
2807 d_assertions.replace(i, learned);
2808 }
2809 }
2810 }
2811
2812 // do dumping (before/after any preprocessing pass)
2813 static void dumpAssertions(const char* key, const AssertionPipeline& assertionList) {
2814 if( Dump.isOn("assertions") &&
2815 Dump.isOn(string("assertions:") + key) ) {
2816 // Push the simplified assertions to the dump output stream
2817 for(unsigned i = 0; i < assertionList.size(); ++ i) {
2818 TNode n = assertionList[i];
2819 Dump("assertions") << AssertCommand(Expr(n.toExpr()));
2820 }
2821 }
2822 }
2823
2824 // returns false if it learns a conflict
2825 bool SmtEnginePrivate::nonClausalSimplify() {
2826 spendResource(options::preprocessStep());
2827 d_smt.finalOptionsAreSet();
2828
2829 if(options::unsatCores() || options::fewerPreprocessingHoles()) {
2830 return true;
2831 }
2832
2833 TimerStat::CodeTimer nonclausalTimer(d_smt.d_stats->d_nonclausalSimplificationTime);
2834
2835 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify()" << endl;
2836 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
2837 Trace("simplify") << "Assertion #" << i << " : " << d_assertions[i] << std::endl;
2838 }
2839
2840 if(d_propagatorNeedsFinish) {
2841 d_propagator.finish();
2842 d_propagatorNeedsFinish = false;
2843 }
2844 d_propagator.initialize();
2845
2846 // Assert all the assertions to the propagator
2847 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2848 << "asserting to propagator" << endl;
2849 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
2850 Assert(Rewriter::rewrite(d_assertions[i]) == d_assertions[i]);
2851 // Don't reprocess substitutions
2852 if (d_substitutionsIndex > 0 && i == d_substitutionsIndex) {
2853 continue;
2854 }
2855 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): asserting " << d_assertions[i] << endl;
2856 Debug("cores") << "d_propagator assertTrue: " << d_assertions[i] << std::endl;
2857 d_propagator.assertTrue(d_assertions[i]);
2858 }
2859
2860 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2861 << "propagating" << endl;
2862 if (d_propagator.propagate()) {
2863 // If in conflict, just return false
2864 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2865 << "conflict in non-clausal propagation" << endl;
2866 Node falseNode = NodeManager::currentNM()->mkConst<bool>(false);
2867 Assert(!options::unsatCores() && !options::fewerPreprocessingHoles());
2868 d_assertions.clear();
2869 addFormula(falseNode, false, false);
2870 d_propagatorNeedsFinish = true;
2871 return false;
2872 }
2873
2874
2875 Trace("simplify") << "Iterate through " << d_nonClausalLearnedLiterals.size() << " learned literals." << std::endl;
2876 // No conflict, go through the literals and solve them
2877 SubstitutionMap constantPropagations(d_smt.d_context);
2878 SubstitutionMap newSubstitutions(d_smt.d_context);
2879 SubstitutionMap::iterator pos;
2880 unsigned j = 0;
2881 for(unsigned i = 0, i_end = d_nonClausalLearnedLiterals.size(); i < i_end; ++ i) {
2882 // Simplify the literal we learned wrt previous substitutions
2883 Node learnedLiteral = d_nonClausalLearnedLiterals[i];
2884 Assert(Rewriter::rewrite(learnedLiteral) == learnedLiteral);
2885 Assert(d_topLevelSubstitutions.apply(learnedLiteral) == learnedLiteral);
2886 Trace("simplify") << "Process learnedLiteral : " << learnedLiteral << std::endl;
2887 Node learnedLiteralNew = newSubstitutions.apply(learnedLiteral);
2888 if (learnedLiteral != learnedLiteralNew) {
2889 learnedLiteral = Rewriter::rewrite(learnedLiteralNew);
2890 }
2891 Trace("simplify") << "Process learnedLiteral, after newSubs : " << learnedLiteral << std::endl;
2892 for (;;) {
2893 learnedLiteralNew = constantPropagations.apply(learnedLiteral);
2894 if (learnedLiteralNew == learnedLiteral) {
2895 break;
2896 }
2897 ++d_smt.d_stats->d_numConstantProps;
2898 learnedLiteral = Rewriter::rewrite(learnedLiteralNew);
2899 }
2900 Trace("simplify") << "Process learnedLiteral, after constProp : " << learnedLiteral << std::endl;
2901 // It might just simplify to a constant
2902 if (learnedLiteral.isConst()) {
2903 if (learnedLiteral.getConst<bool>()) {
2904 // If the learned literal simplifies to true, it's redundant
2905 continue;
2906 } else {
2907 // If the learned literal simplifies to false, we're in conflict
2908 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2909 << "conflict with "
2910 << d_nonClausalLearnedLiterals[i] << endl;
2911 Assert(!options::unsatCores());
2912 d_assertions.clear();
2913 addFormula(NodeManager::currentNM()->mkConst<bool>(false), false, false);
2914 d_propagatorNeedsFinish = true;
2915 return false;
2916 }
2917 }
2918
2919 // Solve it with the corresponding theory, possibly adding new
2920 // substitutions to newSubstitutions
2921 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2922 << "solving " << learnedLiteral << endl;
2923
2924 Theory::PPAssertStatus solveStatus =
2925 d_smt.d_theoryEngine->solve(learnedLiteral, newSubstitutions);
2926
2927 switch (solveStatus) {
2928 case Theory::PP_ASSERT_STATUS_SOLVED: {
2929 // The literal should rewrite to true
2930 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2931 << "solved " << learnedLiteral << endl;
2932 Assert(Rewriter::rewrite(newSubstitutions.apply(learnedLiteral)).isConst());
2933 // vector<pair<Node, Node> > equations;
2934 // constantPropagations.simplifyLHS(d_topLevelSubstitutions, equations, true);
2935 // if (equations.empty()) {
2936 // break;
2937 // }
2938 // Assert(equations[0].first.isConst() && equations[0].second.isConst() && equations[0].first != equations[0].second);
2939 // else fall through
2940 break;
2941 }
2942 case Theory::PP_ASSERT_STATUS_CONFLICT:
2943 // If in conflict, we return false
2944 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
2945 << "conflict while solving "
2946 << learnedLiteral << endl;
2947 Assert(!options::unsatCores());
2948 d_assertions.clear();
2949 addFormula(NodeManager::currentNM()->mkConst<bool>(false), false, false);
2950 d_propagatorNeedsFinish = true;
2951 return false;
2952 default:
2953 if (d_doConstantProp && learnedLiteral.getKind() == kind::EQUAL && (learnedLiteral[0].isConst() || learnedLiteral[1].isConst())) {
2954 // constant propagation
2955 TNode t;
2956 TNode c;
2957 if (learnedLiteral[0].isConst()) {
2958 t = learnedLiteral[1];
2959 c = learnedLiteral[0];
2960 }
2961 else {
2962 t = learnedLiteral[0];
2963 c = learnedLiteral[1];
2964 }
2965 Assert(!t.isConst());
2966 Assert(constantPropagations.apply(t) == t);
2967 Assert(d_topLevelSubstitutions.apply(t) == t);
2968 Assert(newSubstitutions.apply(t) == t);
2969 constantPropagations.addSubstitution(t, c);
2970 // vector<pair<Node,Node> > equations;
2971 // constantPropagations.simplifyLHS(t, c, equations, true);
2972 // if (!equations.empty()) {
2973 // Assert(equations[0].first.isConst() && equations[0].second.isConst() && equations[0].first != equations[0].second);
2974 // d_assertions.clear();
2975 // addFormula(NodeManager::currentNM()->mkConst<bool>(false), false, false);
2976 // return;
2977 // }
2978 // d_topLevelSubstitutions.simplifyRHS(constantPropagations);
2979 }
2980 else {
2981 // Keep the literal
2982 d_nonClausalLearnedLiterals[j++] = d_nonClausalLearnedLiterals[i];
2983 }
2984 break;
2985 }
2986 }
2987
2988 #ifdef CVC4_ASSERTIONS
2989 // NOTE: When debugging this code, consider moving this check inside of the
2990 // loop over d_nonClausalLearnedLiterals. This check has been moved outside
2991 // because it is costly for certain inputs (see bug 508).
2992 //
2993 // Check data structure invariants:
2994 // 1. for each lhs of d_topLevelSubstitutions, does not appear anywhere in rhs of d_topLevelSubstitutions or anywhere in constantPropagations
2995 // 2. each lhs of constantPropagations rewrites to itself
2996 // 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
2997 // constant propagation too
2998 // 4. each lhs of constantPropagations is different from each rhs
2999 for (pos = newSubstitutions.begin(); pos != newSubstitutions.end(); ++pos) {
3000 Assert((*pos).first.isVar());
3001 Assert(d_topLevelSubstitutions.apply((*pos).first) == (*pos).first);
3002 Assert(d_topLevelSubstitutions.apply((*pos).second) == (*pos).second);
3003 Assert(newSubstitutions.apply(newSubstitutions.apply((*pos).second)) == newSubstitutions.apply((*pos).second));
3004 }
3005 for (pos = constantPropagations.begin(); pos != constantPropagations.end(); ++pos) {
3006 Assert((*pos).second.isConst());
3007 Assert(Rewriter::rewrite((*pos).first) == (*pos).first);
3008 // Node newLeft = d_topLevelSubstitutions.apply((*pos).first);
3009 // if (newLeft != (*pos).first) {
3010 // newLeft = Rewriter::rewrite(newLeft);
3011 // Assert(newLeft == (*pos).second ||
3012 // (constantPropagations.hasSubstitution(newLeft) && constantPropagations.apply(newLeft) == (*pos).second));
3013 // }
3014 // newLeft = constantPropagations.apply((*pos).first);
3015 // if (newLeft != (*pos).first) {
3016 // newLeft = Rewriter::rewrite(newLeft);
3017 // Assert(newLeft == (*pos).second ||
3018 // (constantPropagations.hasSubstitution(newLeft) && constantPropagations.apply(newLeft) == (*pos).second));
3019 // }
3020 Assert(constantPropagations.apply((*pos).second) == (*pos).second);
3021 }
3022 #endif /* CVC4_ASSERTIONS */
3023
3024 // Resize the learnt
3025 Trace("simplify") << "Resize non-clausal learned literals to " << j << std::endl;
3026 d_nonClausalLearnedLiterals.resize(j);
3027
3028 unordered_set<TNode, TNodeHashFunction> s;
3029 Trace("debugging") << "NonClausal simplify pre-preprocess\n";
3030 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3031 Node assertion = d_assertions[i];
3032 Node assertionNew = newSubstitutions.apply(assertion);
3033 Trace("debugging") << "assertion = " << assertion << endl;
3034 Trace("debugging") << "assertionNew = " << assertionNew << endl;
3035 if (assertion != assertionNew) {
3036 assertion = Rewriter::rewrite(assertionNew);
3037 Trace("debugging") << "rewrite(assertion) = " << assertion << endl;
3038 }
3039 Assert(Rewriter::rewrite(assertion) == assertion);
3040 for (;;) {
3041 assertionNew = constantPropagations.apply(assertion);
3042 if (assertionNew == assertion) {
3043 break;
3044 }
3045 ++d_smt.d_stats->d_numConstantProps;
3046 Trace("debugging") << "assertionNew = " << assertionNew << endl;
3047 assertion = Rewriter::rewrite(assertionNew);
3048 Trace("debugging") << "assertionNew = " << assertionNew << endl;
3049 }
3050 Trace("debugging") << "\n";
3051 s.insert(assertion);
3052 d_assertions.replace(i, assertion);
3053 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
3054 << "non-clausal preprocessed: "
3055 << assertion << endl;
3056 }
3057
3058 // If in incremental mode, add substitutions to the list of assertions
3059 if (d_substitutionsIndex > 0) {
3060 NodeBuilder<> substitutionsBuilder(kind::AND);
3061 substitutionsBuilder << d_assertions[d_substitutionsIndex];
3062 pos = newSubstitutions.begin();
3063 for (; pos != newSubstitutions.end(); ++pos) {
3064 // Add back this substitution as an assertion
3065 TNode lhs = (*pos).first, rhs = newSubstitutions.apply((*pos).second);
3066 Node n = NodeManager::currentNM()->mkNode(kind::EQUAL, lhs, rhs);
3067 substitutionsBuilder << n;
3068 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): will notify SAT layer of substitution: " << n << endl;
3069 }
3070 if (substitutionsBuilder.getNumChildren() > 1) {
3071 d_assertions.replace(d_substitutionsIndex,
3072 Rewriter::rewrite(Node(substitutionsBuilder)));
3073 }
3074 } else {
3075 // If not in incremental mode, must add substitutions to model
3076 TheoryModel* m = d_smt.d_theoryEngine->getModel();
3077 if(m != NULL) {
3078 for(pos = newSubstitutions.begin(); pos != newSubstitutions.end(); ++pos) {
3079 Node n = (*pos).first;
3080 Node v = newSubstitutions.apply((*pos).second);
3081 Trace("model") << "Add substitution : " << n << " " << v << endl;
3082 m->addSubstitution( n, v );
3083 }
3084 }
3085 }
3086
3087 NodeBuilder<> learnedBuilder(kind::AND);
3088 Assert(d_realAssertionsEnd <= d_assertions.size());
3089 learnedBuilder << d_assertions[d_realAssertionsEnd - 1];
3090
3091 for (unsigned i = 0; i < d_nonClausalLearnedLiterals.size(); ++ i) {
3092 Node learned = d_nonClausalLearnedLiterals[i];
3093 Assert(d_topLevelSubstitutions.apply(learned) == learned);
3094 Node learnedNew = newSubstitutions.apply(learned);
3095 if (learned != learnedNew) {
3096 learned = Rewriter::rewrite(learnedNew);
3097 }
3098 Assert(Rewriter::rewrite(learned) == learned);
3099 for (;;) {
3100 learnedNew = constantPropagations.apply(learned);
3101 if (learnedNew == learned) {
3102 break;
3103 }
3104 ++d_smt.d_stats->d_numConstantProps;
3105 learned = Rewriter::rewrite(learnedNew);
3106 }
3107 if (s.find(learned) != s.end()) {
3108 continue;
3109 }
3110 s.insert(learned);
3111 learnedBuilder << learned;
3112 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
3113 << "non-clausal learned : "
3114 << learned << endl;
3115 }
3116 d_nonClausalLearnedLiterals.clear();
3117
3118 for (pos = constantPropagations.begin(); pos != constantPropagations.end(); ++pos) {
3119 Node cProp = (*pos).first.eqNode((*pos).second);
3120 Assert(d_topLevelSubstitutions.apply(cProp) == cProp);
3121 Node cPropNew = newSubstitutions.apply(cProp);
3122 if (cProp != cPropNew) {
3123 cProp = Rewriter::rewrite(cPropNew);
3124 Assert(Rewriter::rewrite(cProp) == cProp);
3125 }
3126 if (s.find(cProp) != s.end()) {
3127 continue;
3128 }
3129 s.insert(cProp);
3130 learnedBuilder << cProp;
3131 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
3132 << "non-clausal constant propagation : "
3133 << cProp << endl;
3134 }
3135
3136 // Add new substitutions to topLevelSubstitutions
3137 // Note that we don't have to keep rhs's in full solved form
3138 // because SubstitutionMap::apply does a fixed-point iteration when substituting
3139 d_topLevelSubstitutions.addSubstitutions(newSubstitutions);
3140
3141 if(learnedBuilder.getNumChildren() > 1) {
3142 d_assertions.replace(d_realAssertionsEnd - 1,
3143 Rewriter::rewrite(Node(learnedBuilder)));
3144 }
3145
3146 d_propagatorNeedsFinish = true;
3147 return true;
3148 }
3149
3150 void SmtEnginePrivate::bvAbstraction() {
3151 Trace("bv-abstraction") << "SmtEnginePrivate::bvAbstraction()" << endl;
3152 std::vector<Node> new_assertions;
3153 bool changed = d_smt.d_theoryEngine->ppBvAbstraction(d_assertions.ref(), new_assertions);
3154 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3155 d_assertions.replace(i, Rewriter::rewrite(new_assertions[i]));
3156 }
3157 // if we are using the lazy solver and the abstraction
3158 // applies, then UF symbols were introduced
3159 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY &&
3160 changed) {
3161 LogicRequest req(d_smt);
3162 req.widenLogic(THEORY_UF);
3163 }
3164 }
3165
3166
3167 void SmtEnginePrivate::bvToBool() {
3168 Trace("bv-to-bool") << "SmtEnginePrivate::bvToBool()" << endl;
3169 spendResource(options::preprocessStep());
3170 std::vector<Node> new_assertions;
3171 d_smt.d_theoryEngine->ppBvToBool(d_assertions.ref(), new_assertions);
3172 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3173 d_assertions.replace(i, Rewriter::rewrite(new_assertions[i]));
3174 }
3175 }
3176
3177 void SmtEnginePrivate::boolToBv() {
3178 Trace("bool-to-bv") << "SmtEnginePrivate::boolToBv()" << endl;
3179 spendResource(options::preprocessStep());
3180 std::vector<Node> new_assertions;
3181 d_smt.d_theoryEngine->ppBoolToBv(d_assertions.ref(), new_assertions);
3182 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3183 d_assertions.replace(i, Rewriter::rewrite(new_assertions[i]));
3184 }
3185 }
3186
3187 bool SmtEnginePrivate::simpITE() {
3188 TimerStat::CodeTimer simpITETimer(d_smt.d_stats->d_simpITETime);
3189
3190 spendResource(options::preprocessStep());
3191
3192 Trace("simplify") << "SmtEnginePrivate::simpITE()" << endl;
3193
3194 unsigned numAssertionOnEntry = d_assertions.size();
3195 for (unsigned i = 0; i < d_assertions.size(); ++i) {
3196 spendResource(options::preprocessStep());
3197 Node result = d_smt.d_theoryEngine->ppSimpITE(d_assertions[i]);
3198 d_assertions.replace(i, result);
3199 if(result.isConst() && !result.getConst<bool>()){
3200 return false;
3201 }
3202 }
3203 bool result = d_smt.d_theoryEngine->donePPSimpITE(d_assertions.ref());
3204 if(numAssertionOnEntry < d_assertions.size()){
3205 compressBeforeRealAssertions(numAssertionOnEntry);
3206 }
3207 return result;
3208 }
3209
3210 void SmtEnginePrivate::compressBeforeRealAssertions(size_t before){
3211 size_t curr = d_assertions.size();
3212 if(before >= curr ||
3213 d_realAssertionsEnd <= 0 ||
3214 d_realAssertionsEnd >= curr){
3215 return;
3216 }
3217
3218 // assertions
3219 // original: [0 ... d_realAssertionsEnd)
3220 // can be modified
3221 // ites skolems [d_realAssertionsEnd, before)
3222 // cannot be moved
3223 // added [before, curr)
3224 // can be modified
3225 Assert(0 < d_realAssertionsEnd);
3226 Assert(d_realAssertionsEnd <= before);
3227 Assert(before < curr);
3228
3229 std::vector<Node> intoConjunction;
3230 for(size_t i = before; i<curr; ++i){
3231 intoConjunction.push_back(d_assertions[i]);
3232 }
3233 d_assertions.resize(before);
3234 size_t lastBeforeItes = d_realAssertionsEnd - 1;
3235 intoConjunction.push_back(d_assertions[lastBeforeItes]);
3236 Node newLast = util::NaryBuilder::mkAssoc(kind::AND, intoConjunction);
3237 d_assertions.replace(lastBeforeItes, newLast);
3238 Assert(d_assertions.size() == before);
3239 }
3240
3241 void SmtEnginePrivate::unconstrainedSimp() {
3242 TimerStat::CodeTimer unconstrainedSimpTimer(d_smt.d_stats->d_unconstrainedSimpTime);
3243 spendResource(options::preprocessStep());
3244 Trace("simplify") << "SmtEnginePrivate::unconstrainedSimp()" << endl;
3245 d_smt.d_theoryEngine->ppUnconstrainedSimp(d_assertions.ref());
3246 }
3247
3248 void SmtEnginePrivate::traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions) {
3249 const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
3250 for(vector<Node>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
3251 booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
3252 // term must appear in map, otherwise how did we get here?!
3253 Assert(j != backEdges.end());
3254 // if term maps to empty, that means it's a top-level assertion
3255 if(!(*j).second.empty()) {
3256 traceBackToAssertions((*j).second, assertions);
3257 } else {
3258 assertions.push_back(*i);
3259 }
3260 }
3261 }
3262
3263 size_t SmtEnginePrivate::removeFromConjunction(Node& n, const std::unordered_set<unsigned long>& toRemove) {
3264 Assert(n.getKind() == kind::AND);
3265 size_t removals = 0;
3266 for(Node::iterator j = n.begin(); j != n.end(); ++j) {
3267 size_t subremovals = 0;
3268 Node sub = *j;
3269 if(toRemove.find(sub.getId()) != toRemove.end() ||
3270 (sub.getKind() == kind::AND && (subremovals = removeFromConjunction(sub, toRemove)) > 0)) {
3271 NodeBuilder<> b(kind::AND);
3272 b.append(n.begin(), j);
3273 if(subremovals > 0) {
3274 removals += subremovals;
3275 b << sub;
3276 } else {
3277 ++removals;
3278 }
3279 for(++j; j != n.end(); ++j) {
3280 if(toRemove.find((*j).getId()) != toRemove.end()) {
3281 ++removals;
3282 } else if((*j).getKind() == kind::AND) {
3283 sub = *j;
3284 if((subremovals = removeFromConjunction(sub, toRemove)) > 0) {
3285 removals += subremovals;
3286 b << sub;
3287 } else {
3288 b << *j;
3289 }
3290 } else {
3291 b << *j;
3292 }
3293 }
3294 if(b.getNumChildren() == 0) {
3295 n = d_true;
3296 b.clear();
3297 } else if(b.getNumChildren() == 1) {
3298 n = b[0];
3299 b.clear();
3300 } else {
3301 n = b;
3302 }
3303 n = Rewriter::rewrite(n);
3304 return removals;
3305 }
3306 }
3307
3308 Assert(removals == 0);
3309 return 0;
3310 }
3311
3312 void SmtEnginePrivate::doMiplibTrick() {
3313 Assert(d_realAssertionsEnd == d_assertions.size());
3314 Assert(!options::incrementalSolving());
3315
3316 const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
3317 unordered_set<unsigned long> removeAssertions;
3318
3319 NodeManager* nm = NodeManager::currentNM();
3320 Node zero = nm->mkConst(Rational(0)), one = nm->mkConst(Rational(1));
3321
3322 unordered_map<TNode, Node, TNodeHashFunction> intVars;
3323 for(vector<Node>::const_iterator i = d_boolVars.begin(); i != d_boolVars.end(); ++i) {
3324 if(d_propagator.isAssigned(*i)) {
3325 Debug("miplib") << "ineligible: " << *i << " because assigned " << d_propagator.getAssignment(*i) << endl;
3326 continue;
3327 }
3328
3329 vector<TNode> assertions;
3330 booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
3331 // if not in back edges map, the bool var is unconstrained, showing up in no assertions.
3332 // if maps to an empty vector, that means the bool var was asserted itself.
3333 if(j != backEdges.end()) {
3334 if(!(*j).second.empty()) {
3335 traceBackToAssertions((*j).second, assertions);
3336 } else {
3337 assertions.push_back(*i);
3338 }
3339 }
3340 Debug("miplib") << "for " << *i << endl;
3341 bool eligible = true;
3342 map<pair<Node, Node>, uint64_t> marks;
3343 map<pair<Node, Node>, vector<Rational> > coef;
3344 map<pair<Node, Node>, vector<Rational> > checks;
3345 map<pair<Node, Node>, vector<TNode> > asserts;
3346 for(vector<TNode>::const_iterator j = assertions.begin(); j != assertions.end(); ++j) {
3347 Debug("miplib") << " found: " << *j << endl;
3348 if((*j).getKind() != kind::IMPLIES) {
3349 eligible = false;
3350 Debug("miplib") << " -- INELIGIBLE -- (not =>)" << endl;
3351 break;
3352 }
3353 Node conj = BooleanSimplification::simplify((*j)[0]);
3354 if(conj.getKind() == kind::AND && conj.getNumChildren() > 6) {
3355 eligible = false;
3356 Debug("miplib") << " -- INELIGIBLE -- (N-ary /\\ too big)" << endl;
3357 break;
3358 }
3359 if(conj.getKind() != kind::AND && !conj.isVar() && !(conj.getKind() == kind::NOT && conj[0].isVar())) {
3360 eligible = false;
3361 Debug("miplib") << " -- INELIGIBLE -- (not /\\ or literal)" << endl;
3362 break;
3363 }
3364 if((*j)[1].getKind() != kind::EQUAL ||
3365 !( ( (*j)[1][0].isVar() &&
3366 (*j)[1][1].getKind() == kind::CONST_RATIONAL ) ||
3367 ( (*j)[1][0].getKind() == kind::CONST_RATIONAL &&
3368 (*j)[1][1].isVar() ) )) {
3369 eligible = false;
3370 Debug("miplib") << " -- INELIGIBLE -- (=> (and X X) X)" << endl;
3371 break;
3372 }
3373 if(conj.getKind() == kind::AND) {
3374 vector<Node> posv;
3375 bool found_x = false;
3376 map<TNode, bool> neg;
3377 for(Node::iterator ii = conj.begin(); ii != conj.end(); ++ii) {
3378 if((*ii).isVar()) {
3379 posv.push_back(*ii);
3380 neg[*ii] = false;
3381 found_x = found_x || *i == *ii;
3382 } else if((*ii).getKind() == kind::NOT && (*ii)[0].isVar()) {
3383 posv.push_back((*ii)[0]);
3384 neg[(*ii)[0]] = true;
3385 found_x = found_x || *i == (*ii)[0];
3386 } else {
3387 eligible = false;
3388 Debug("miplib") << " -- INELIGIBLE -- (non-var: " << *ii << ")" << endl;
3389 break;
3390 }
3391 if(d_propagator.isAssigned(posv.back())) {
3392 eligible = false;
3393 Debug("miplib") << " -- INELIGIBLE -- (" << posv.back() << " asserted)" << endl;
3394 break;
3395 }
3396 }
3397 if(!eligible) {
3398 break;
3399 }
3400 if(!found_x) {
3401 eligible = false;
3402 Debug("miplib") << " --INELIGIBLE -- (couldn't find " << *i << " in conjunction)" << endl;
3403 break;
3404 }
3405 sort(posv.begin(), posv.end());
3406 const Node pos = NodeManager::currentNM()->mkNode(kind::AND, posv);
3407 const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
3408 const pair<Node, Node> pos_var(pos, var);
3409 const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
3410 uint64_t mark = 0;
3411 unsigned countneg = 0, thepos = 0;
3412 for(unsigned ii = 0; ii < pos.getNumChildren(); ++ii) {
3413 if(neg[pos[ii]]) {
3414 ++countneg;
3415 } else {
3416 thepos = ii;
3417 mark |= (0x1 << ii);
3418 }
3419 }
3420 if((marks[pos_var] & (1lu << mark)) != 0) {
3421 eligible = false;
3422 Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
3423 break;
3424 }
3425 Debug("miplib") << "mark is " << mark << " -- " << (1lu << mark) << endl;
3426 marks[pos_var] |= (1lu << mark);
3427 Debug("miplib") << "marks[" << pos << "," << var << "] now " << marks[pos_var] << endl;
3428 if(countneg == pos.getNumChildren()) {
3429 if(constant != 0) {
3430 eligible = false;
3431 Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
3432 break;
3433 }
3434 } else if(countneg == pos.getNumChildren() - 1) {
3435 Assert(coef[pos_var].size() <= 6 && thepos < 6);
3436 if(coef[pos_var].size() <= thepos) {
3437 coef[pos_var].resize(thepos + 1);
3438 }
3439 coef[pos_var][thepos] = constant;
3440 } else {
3441 if(checks[pos_var].size() <= mark) {
3442 checks[pos_var].resize(mark + 1);
3443 }
3444 checks[pos_var][mark] = constant;
3445 }
3446 asserts[pos_var].push_back(*j);
3447 } else {
3448 TNode x = conj;
3449 if(x != *i && x != (*i).notNode()) {
3450 eligible = false;
3451 Debug("miplib") << " -- INELIGIBLE -- (x not present where I expect it)" << endl;
3452 break;
3453 }
3454 const bool xneg = (x.getKind() == kind::NOT);
3455 x = xneg ? x[0] : x;
3456 Debug("miplib") << " x:" << x << " " << xneg << endl;
3457 const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
3458 const pair<Node, Node> x_var(x, var);
3459 const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
3460 unsigned mark = (xneg ? 0 : 1);
3461 if((marks[x_var] & (1u << mark)) != 0) {
3462 eligible = false;
3463 Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
3464 break;
3465 }
3466 marks[x_var] |= (1u << mark);
3467 if(xneg) {
3468 if(constant != 0) {
3469 eligible = false;
3470 Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
3471 break;
3472 }
3473 } else {
3474 Assert(coef[x_var].size() <= 6);
3475 coef[x_var].resize(6);
3476 coef[x_var][0] = constant;
3477 }
3478 asserts[x_var].push_back(*j);
3479 }
3480 }
3481 if(eligible) {
3482 for(map<pair<Node, Node>, uint64_t>::const_iterator j = marks.begin(); j != marks.end(); ++j) {
3483 const TNode pos = (*j).first.first;
3484 const TNode var = (*j).first.second;
3485 const pair<Node, Node>& pos_var = (*j).first;
3486 const uint64_t mark = (*j).second;
3487 const unsigned numVars = pos.getKind() == kind::AND ? pos.getNumChildren() : 1;
3488 uint64_t expected = (uint64_t(1) << (1 << numVars)) - 1;
3489 expected = (expected == 0) ? -1 : expected; // fix for overflow
3490 Debug("miplib") << "[" << pos << "] => " << hex << mark << " expect " << expected << dec << endl;
3491 Assert(pos.getKind() == kind::AND || pos.isVar());
3492 if(mark != expected) {
3493 Debug("miplib") << " -- INELIGIBLE " << pos << " -- (insufficiently marked, got " << mark << " for " << numVars << " vars, expected " << expected << endl;
3494 } else {
3495 if(mark != 3) { // exclude single-var case; nothing to check there
3496 uint64_t sz = (uint64_t(1) << checks[pos_var].size()) - 1;
3497 sz = (sz == 0) ? -1 : sz; // fix for overflow
3498 Assert(sz == mark, "expected size %u == mark %u", sz, mark);
3499 for(size_t k = 0; k < checks[pos_var].size(); ++k) {
3500 if((k & (k - 1)) != 0) {
3501 Rational sum = 0;
3502 Debug("miplib") << k << " => " << checks[pos_var][k] << endl;
3503 for(size_t v = 1, kk = k; kk != 0; ++v, kk >>= 1) {
3504 if((kk & 0x1) == 1) {
3505 Assert(pos.getKind() == kind::AND);
3506 Debug("miplib") << "var " << v << " : " << pos[v - 1] << " coef:" << coef[pos_var][v - 1] << endl;
3507 sum += coef[pos_var][v - 1];
3508 }
3509 }
3510 Debug("miplib") << "checkSum is " << sum << " input says " << checks[pos_var][k] << endl;
3511 if(sum != checks[pos_var][k]) {
3512 eligible = false;
3513 Debug("miplib") << " -- INELIGIBLE " << pos << " -- (nonlinear combination)" << endl;
3514 break;
3515 }
3516 } else {
3517 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
3518 }
3519 }
3520 }
3521 if(!eligible) {
3522 eligible = true; // next is still eligible
3523 continue;
3524 }
3525
3526 Debug("miplib") << " -- ELIGIBLE " << *i << " , " << pos << " --" << endl;
3527 vector<Node> newVars;
3528 expr::NodeSelfIterator ii, iiend;
3529 if(pos.getKind() == kind::AND) {
3530 ii = pos.begin();
3531 iiend = pos.end();
3532 } else {
3533 ii = expr::NodeSelfIterator::self(pos);
3534 iiend = expr::NodeSelfIterator::selfEnd(pos);
3535 }
3536 for(; ii != iiend; ++ii) {
3537 Node& varRef = intVars[*ii];
3538 if(varRef.isNull()) {
3539 stringstream ss;
3540 ss << "mipvar_" << *ii;
3541 Node newVar = nm->mkSkolem(ss.str(), nm->integerType(), "a variable introduced due to scrubbing a miplib encoding", NodeManager::SKOLEM_EXACT_NAME);
3542 Node geq = Rewriter::rewrite(nm->mkNode(kind::GEQ, newVar, zero));
3543 Node leq = Rewriter::rewrite(nm->mkNode(kind::LEQ, newVar, one));
3544 addFormula(Rewriter::rewrite(geq.andNode(leq)), false, false);
3545 SubstitutionMap nullMap(&d_fakeContext);
3546 Theory::PPAssertStatus status CVC4_UNUSED; // just for assertions
3547 status = d_smt.d_theoryEngine->solve(geq, nullMap);
3548 Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
3549 "unexpected solution from arith's ppAssert()");
3550 Assert(nullMap.empty(),
3551 "unexpected substitution from arith's ppAssert()");
3552 status = d_smt.d_theoryEngine->solve(leq, nullMap);
3553 Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
3554 "unexpected solution from arith's ppAssert()");
3555 Assert(nullMap.empty(),
3556 "unexpected substitution from arith's ppAssert()");
3557 d_smt.d_theoryEngine->getModel()->addSubstitution(*ii, newVar.eqNode(one));
3558 newVars.push_back(newVar);
3559 varRef = newVar;
3560 } else {
3561 newVars.push_back(varRef);
3562 }
3563 if(!d_smt.d_logic.areIntegersUsed()) {
3564 d_smt.d_logic = d_smt.d_logic.getUnlockedCopy();
3565 d_smt.d_logic.enableIntegers();
3566 d_smt.d_logic.lock();
3567 }
3568 }
3569 Node sum;
3570 if(pos.getKind() == kind::AND) {
3571 NodeBuilder<> sumb(kind::PLUS);
3572 for(size_t ii = 0; ii < pos.getNumChildren(); ++ii) {
3573 sumb << nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][ii]), newVars[ii]);
3574 }
3575 sum = sumb;
3576 } else {
3577 sum = nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][0]), newVars[0]);
3578 }
3579 Debug("miplib") << "vars[] " << var << endl
3580 << " eq " << Rewriter::rewrite(sum) << endl;
3581 Node newAssertion = var.eqNode(Rewriter::rewrite(sum));
3582 if(d_topLevelSubstitutions.hasSubstitution(newAssertion[0])) {
3583 //Warning() << "RE-SUBSTITUTION " << newAssertion[0] << endl;
3584 //Warning() << "REPLACE " << newAssertion[1] << endl;
3585 //Warning() << "ORIG " << d_topLevelSubstitutions.getSubstitution(newAssertion[0]) << endl;
3586 Assert(d_topLevelSubstitutions.getSubstitution(newAssertion[0]) == newAssertion[1]);
3587 } else if(pos.getNumChildren() <= options::arithMLTrickSubstitutions()) {
3588 d_topLevelSubstitutions.addSubstitution(newAssertion[0], newAssertion[1]);
3589 Debug("miplib") << "addSubs: " << newAssertion[0] << " to " << newAssertion[1] << endl;
3590 } else {
3591 Debug("miplib") << "skipSubs: " << newAssertion[0] << " to " << newAssertion[1] << " (threshold is " << options::arithMLTrickSubstitutions() << ")" << endl;
3592 }
3593 newAssertion = Rewriter::rewrite(newAssertion);
3594 Debug("miplib") << " " << newAssertion << endl;
3595 addFormula(newAssertion, false, false);
3596 Debug("miplib") << " assertions to remove: " << endl;
3597 for(vector<TNode>::const_iterator k = asserts[pos_var].begin(), k_end = asserts[pos_var].end(); k != k_end; ++k) {
3598 Debug("miplib") << " " << *k << endl;
3599 removeAssertions.insert((*k).getId());
3600 }
3601 }
3602 }
3603 }
3604 }
3605 if(!removeAssertions.empty()) {
3606 Debug("miplib") << "SmtEnginePrivate::simplify(): scrubbing miplib encoding..." << endl;
3607 for(size_t i = 0; i < d_realAssertionsEnd; ++i) {
3608 if(removeAssertions.find(d_assertions[i].getId()) != removeAssertions.end()) {
3609 Debug("miplib") << "SmtEnginePrivate::simplify(): - removing " << d_assertions[i] << endl;
3610 d_assertions[i] = d_true;
3611 ++d_smt.d_stats->d_numMiplibAssertionsRemoved;
3612 } else if(d_assertions[i].getKind() == kind::AND) {
3613 size_t removals = removeFromConjunction(d_assertions[i], removeAssertions);
3614 if(removals > 0) {
3615 Debug("miplib") << "SmtEnginePrivate::simplify(): - reduced " << d_assertions[i] << endl;
3616 Debug("miplib") << "SmtEnginePrivate::simplify(): - by " << removals << " conjuncts" << endl;
3617 d_smt.d_stats->d_numMiplibAssertionsRemoved += removals;
3618 }
3619 }
3620 Debug("miplib") << "had: " << d_assertions[i] << endl;
3621 d_assertions[i] = Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertions[i]));
3622 Debug("miplib") << "now: " << d_assertions[i] << endl;
3623 }
3624 } else {
3625 Debug("miplib") << "SmtEnginePrivate::simplify(): miplib pass found nothing." << endl;
3626 }
3627 d_realAssertionsEnd = d_assertions.size();
3628 }
3629
3630
3631 // returns false if simplification led to "false"
3632 bool SmtEnginePrivate::simplifyAssertions()
3633 throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
3634 spendResource(options::preprocessStep());
3635 Assert(d_smt.d_pendingPops == 0);
3636 try {
3637 ScopeCounter depth(d_simplifyAssertionsDepth);
3638
3639 Trace("simplify") << "SmtEnginePrivate::simplify()" << endl;
3640
3641 dumpAssertions("pre-nonclausal", d_assertions);
3642
3643 if(options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
3644 // Perform non-clausal simplification
3645 Chat() << "...performing nonclausal simplification..." << endl;
3646 Trace("simplify") << "SmtEnginePrivate::simplify(): "
3647 << "performing non-clausal simplification" << endl;
3648 bool noConflict = nonClausalSimplify();
3649 if(!noConflict) {
3650 return false;
3651 }
3652
3653 // We piggy-back off of the BackEdgesMap in the CircuitPropagator to
3654 // do the miplib trick.
3655 if( // check that option is on
3656 options::arithMLTrick() &&
3657 // miplib rewrites aren't safe in incremental mode
3658 ! options::incrementalSolving() &&
3659 // only useful in arith
3660 d_smt.d_logic.isTheoryEnabled(THEORY_ARITH) &&
3661 // we add new assertions and need this (in practice, this
3662 // restriction only disables miplib processing during
3663 // re-simplification, which we don't expect to be useful anyway)
3664 d_realAssertionsEnd == d_assertions.size() ) {
3665 Chat() << "...fixing miplib encodings..." << endl;
3666 Trace("simplify") << "SmtEnginePrivate::simplify(): "
3667 << "looking for miplib pseudobooleans..." << endl;
3668
3669 TimerStat::CodeTimer miplibTimer(d_smt.d_stats->d_miplibPassTime);
3670
3671 doMiplibTrick();
3672 } else {
3673 Trace("simplify") << "SmtEnginePrivate::simplify(): "
3674 << "skipping miplib pseudobooleans pass (either incrementalSolving is on, or miplib pbs are turned off)..." << endl;
3675 }
3676 }
3677
3678 dumpAssertions("post-nonclausal", d_assertions);
3679 Trace("smt") << "POST nonClausalSimplify" << endl;
3680 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3681
3682 // before ppRewrite check if only core theory for BV theory
3683 d_smt.d_theoryEngine->staticInitializeBVOptions(d_assertions.ref());
3684
3685 dumpAssertions("pre-theorypp", d_assertions);
3686
3687 // Theory preprocessing
3688 if (d_smt.d_earlyTheoryPP) {
3689 Chat() << "...doing early theory preprocessing..." << endl;
3690 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
3691 // Call the theory preprocessors
3692 d_smt.d_theoryEngine->preprocessStart();
3693 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3694 Assert(Rewriter::rewrite(d_assertions[i]) == d_assertions[i]);
3695 d_assertions.replace(i, d_smt.d_theoryEngine->preprocess(d_assertions[i]));
3696 Assert(Rewriter::rewrite(d_assertions[i]) == d_assertions[i]);
3697 }
3698 }
3699
3700 dumpAssertions("post-theorypp", d_assertions);
3701 Trace("smt") << "POST theoryPP" << endl;
3702 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3703
3704 // ITE simplification
3705 if(options::doITESimp() &&
3706 (d_simplifyAssertionsDepth <= 1 || options::doITESimpOnRepeat())) {
3707 Chat() << "...doing ITE simplification..." << endl;
3708 bool noConflict = simpITE();
3709 if(!noConflict){
3710 Chat() << "...ITE simplification found unsat..." << endl;
3711 return false;
3712 }
3713 }
3714
3715 dumpAssertions("post-itesimp", d_assertions);
3716 Trace("smt") << "POST iteSimp" << endl;
3717 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3718
3719 // Unconstrained simplification
3720 if(options::unconstrainedSimp()) {
3721 Chat() << "...doing unconstrained simplification..." << endl;
3722 unconstrainedSimp();
3723 }
3724
3725 dumpAssertions("post-unconstrained", d_assertions);
3726 Trace("smt") << "POST unconstrainedSimp" << endl;
3727 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3728
3729 if(options::repeatSimp() && options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
3730 Chat() << "...doing another round of nonclausal simplification..." << endl;
3731 Trace("simplify") << "SmtEnginePrivate::simplify(): "
3732 << " doing repeated simplification" << endl;
3733 bool noConflict = nonClausalSimplify();
3734 if(!noConflict) {
3735 return false;
3736 }
3737 }
3738
3739 dumpAssertions("post-repeatsimp", d_assertions);
3740 Trace("smt") << "POST repeatSimp" << endl;
3741 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3742
3743 } catch(TypeCheckingExceptionPrivate& tcep) {
3744 // Calls to this function should have already weeded out any
3745 // typechecking exceptions via (e.g.) ensureBoolean(). But a
3746 // theory could still create a new expression that isn't
3747 // well-typed, and we don't want the C++ runtime to abort our
3748 // process without any error notice.
3749 stringstream ss;
3750 ss << "A bad expression was produced. Original exception follows:\n"
3751 << tcep;
3752 InternalError(ss.str().c_str());
3753 }
3754 return true;
3755 }
3756
3757 Result SmtEngine::check() {
3758 Assert(d_fullyInited);
3759 Assert(d_pendingPops == 0);
3760
3761 Trace("smt") << "SmtEngine::check()" << endl;
3762
3763 ResourceManager* resourceManager = d_private->getResourceManager();
3764
3765 resourceManager->beginCall();
3766
3767 // Only way we can be out of resource is if cumulative budget is on
3768 if (resourceManager->cumulativeLimitOn() &&
3769 resourceManager->out()) {
3770 Result::UnknownExplanation why = resourceManager->outOfResources() ?
3771 Result::RESOURCEOUT : Result::TIMEOUT;
3772 return Result(Result::VALIDITY_UNKNOWN, why, d_filename);
3773 }
3774
3775 // Make sure the prop layer has all of the assertions
3776 Trace("smt") << "SmtEngine::check(): processing assertions" << endl;
3777 d_private->processAssertions();
3778 Trace("smt") << "SmtEngine::check(): done processing assertions" << endl;
3779
3780 // Turn off stop only for QF_LRA
3781 // TODO: Bring up in a meeting where to put this
3782 if(options::decisionStopOnly() && !options::decisionMode.wasSetByUser() ){
3783 if( // QF_LRA
3784 (not d_logic.isQuantified() &&
3785 d_logic.isPure(THEORY_ARITH) && d_logic.isLinear() && !d_logic.isDifferenceLogic() && !d_logic.areIntegersUsed()
3786 )){
3787 if(d_private->d_iteSkolemMap.empty()){
3788 options::decisionStopOnly.set(false);
3789 d_decisionEngine->clearStrategies();
3790 Trace("smt") << "SmtEngine::check(): turning off stop only" << endl;
3791 }
3792 }
3793 }
3794
3795 TimerStat::CodeTimer solveTimer(d_stats->d_solveTime);
3796
3797 Chat() << "solving..." << endl;
3798 Trace("smt") << "SmtEngine::check(): running check" << endl;
3799 Result result = d_propEngine->checkSat();
3800
3801 resourceManager->endCall();
3802 Trace("limit") << "SmtEngine::check(): cumulative millis " << resourceManager->getTimeUsage()
3803 << ", resources " << resourceManager->getResourceUsage() << endl;
3804
3805
3806 return Result(result, d_filename);
3807 }
3808
3809 Result SmtEngine::quickCheck() {
3810 Assert(d_fullyInited);
3811 Trace("smt") << "SMT quickCheck()" << endl;
3812 return Result(Result::VALIDITY_UNKNOWN, Result::REQUIRES_FULL_CHECK, d_filename);
3813 }
3814
3815
3816 void SmtEnginePrivate::collectSkolems(TNode n, set<TNode>& skolemSet, unordered_map<Node, bool, NodeHashFunction>& cache)
3817 {
3818 unordered_map<Node, bool, NodeHashFunction>::iterator it;
3819 it = cache.find(n);
3820 if (it != cache.end()) {
3821 return;
3822 }
3823
3824 size_t sz = n.getNumChildren();
3825 if (sz == 0) {
3826 IteSkolemMap::iterator it = d_iteSkolemMap.find(n);
3827 if (it != d_iteSkolemMap.end()) {
3828 skolemSet.insert(n);
3829 }
3830 cache[n] = true;
3831 return;
3832 }
3833
3834 size_t k = 0;
3835 for (; k < sz; ++k) {
3836 collectSkolems(n[k], skolemSet, cache);
3837 }
3838 cache[n] = true;
3839 }
3840
3841
3842 bool SmtEnginePrivate::checkForBadSkolems(TNode n, TNode skolem, unordered_map<Node, bool, NodeHashFunction>& cache)
3843 {
3844 unordered_map<Node, bool, NodeHashFunction>::iterator it;
3845 it = cache.find(n);
3846 if (it != cache.end()) {
3847 return (*it).second;
3848 }
3849
3850 size_t sz = n.getNumChildren();
3851 if (sz == 0) {
3852 IteSkolemMap::iterator it = d_iteSkolemMap.find(n);
3853 bool bad = false;
3854 if (it != d_iteSkolemMap.end()) {
3855 if (!((*it).first < n)) {
3856 bad = true;
3857 }
3858 }
3859 cache[n] = bad;
3860 return bad;
3861 }
3862
3863 size_t k = 0;
3864 for (; k < sz; ++k) {
3865 if (checkForBadSkolems(n[k], skolem, cache)) {
3866 cache[n] = true;
3867 return true;
3868 }
3869 }
3870
3871 cache[n] = false;
3872 return false;
3873 }
3874
3875 void SmtEnginePrivate::processAssertions() {
3876 TimerStat::CodeTimer paTimer(d_smt.d_stats->d_processAssertionsTime);
3877 spendResource(options::preprocessStep());
3878 Assert(d_smt.d_fullyInited);
3879 Assert(d_smt.d_pendingPops == 0);
3880
3881 // Dump the assertions
3882 dumpAssertions("pre-everything", d_assertions);
3883
3884 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() begin" << endl;
3885 Trace("smt") << "SmtEnginePrivate::processAssertions()" << endl;
3886
3887 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3888
3889 if (d_assertions.size() == 0) {
3890 // nothing to do
3891 return;
3892 }
3893
3894 if (d_assertionsProcessed && options::incrementalSolving()) {
3895 // Placeholder for storing substitutions
3896 d_substitutionsIndex = d_assertions.size();
3897 d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(true));
3898 }
3899
3900 // Add dummy assertion in last position - to be used as a
3901 // placeholder for any new assertions to get added
3902 d_assertions.push_back(NodeManager::currentNM()->mkConst<bool>(true));
3903 // any assertions added beyond realAssertionsEnd must NOT affect the
3904 // equisatisfiability
3905 d_realAssertionsEnd = d_assertions.size();
3906
3907 // Assertions are NOT guaranteed to be rewritten by this point
3908
3909 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-definition-expansion" << endl;
3910 dumpAssertions("pre-definition-expansion", d_assertions);
3911 {
3912 Chat() << "expanding definitions..." << endl;
3913 Trace("simplify") << "SmtEnginePrivate::simplify(): expanding definitions" << endl;
3914 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_definitionExpansionTime);
3915 unordered_map<Node, Node, NodeHashFunction> cache;
3916 for(unsigned i = 0; i < d_assertions.size(); ++ i) {
3917 d_assertions.replace(i, expandDefinitions(d_assertions[i], cache));
3918 }
3919 }
3920 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-definition-expansion" << endl;
3921 dumpAssertions("post-definition-expansion", d_assertions);
3922
3923 // save the assertions now
3924 THEORY_PROOF
3925 (
3926 for (unsigned i = 0; i < d_assertions.size(); ++i) {
3927 ProofManager::currentPM()->addAssertion(d_assertions[i].toExpr());
3928 }
3929 );
3930
3931 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3932
3933 if( options::nlExtPurify() ){
3934 unordered_map<Node, Node, NodeHashFunction> cache;
3935 unordered_map<Node, Node, NodeHashFunction> bcache;
3936 std::vector< Node > var_eq;
3937 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3938 d_assertions.replace(i, purifyNlTerms(d_assertions[i], cache, bcache, var_eq));
3939 }
3940 if( !var_eq.empty() ){
3941 unsigned lastIndex = d_assertions.size()-1;
3942 var_eq.insert( var_eq.begin(), d_assertions[lastIndex] );
3943 d_assertions.replace(lastIndex, NodeManager::currentNM()->mkNode( kind::AND, var_eq ) );
3944 }
3945 }
3946
3947 if( options::ceGuidedInst() ){
3948 //register sygus conjecture pre-rewrite (motivated by solution reconstruction)
3949 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
3950 d_smt.d_theoryEngine->getQuantifiersEngine()->getCegInstantiation()->preregisterAssertion( d_assertions[i] );
3951 }
3952 }
3953
3954 if (options::solveRealAsInt()) {
3955 Chat() << "converting reals to ints..." << endl;
3956 unordered_map<Node, Node, NodeHashFunction> cache;
3957 std::vector< Node > var_eq;
3958 for(unsigned i = 0; i < d_assertions.size(); ++ i) {
3959 d_assertions.replace(i, realToInt(d_assertions[i], cache, var_eq));
3960 }
3961 /*
3962 if( !var_eq.empty() ){
3963 unsigned lastIndex = d_assertions.size()-1;
3964 var_eq.insert( var_eq.begin(), d_assertions[lastIndex] );
3965 d_assertions.replace(last_index, NodeManager::currentNM()->mkNode( kind::AND, var_eq ) );
3966 }
3967 */
3968 }
3969
3970 if (options::solveIntAsBV() > 0) {
3971 Chat() << "converting ints to bit-vectors..." << endl;
3972 unordered_map<Node, Node, NodeHashFunction> cache;
3973 for(unsigned i = 0; i < d_assertions.size(); ++ i) {
3974 d_assertions.replace(i, intToBV(d_assertions[i], cache));
3975 }
3976 }
3977
3978 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
3979 !d_smt.d_logic.isPure(THEORY_BV) &&
3980 d_smt.d_logic.getLogicString() != "QF_UFBV" &&
3981 d_smt.d_logic.getLogicString() != "QF_ABV") {
3982 throw ModalException("Eager bit-blasting does not currently support theory combination. "
3983 "Note that in a QF_BV problem UF symbols can be introduced for division. "
3984 "Try --bv-div-zero-const to interpret division by zero as a constant.");
3985 }
3986
3987 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
3988 d_smt.d_theoryEngine->mkAckermanizationAssertions(d_assertions.ref());
3989 }
3990
3991 if ( options::bvAbstraction() &&
3992 !options::incrementalSolving()) {
3993 dumpAssertions("pre-bv-abstraction", d_assertions);
3994 bvAbstraction();
3995 dumpAssertions("post-bv-abstraction", d_assertions);
3996 }
3997
3998 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
3999
4000 bool noConflict = true;
4001
4002 // Unconstrained simplification
4003 if(options::unconstrainedSimp()) {
4004 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-unconstrained-simp" << endl;
4005 dumpAssertions("pre-unconstrained-simp", d_assertions);
4006 Chat() << "...doing unconstrained simplification..." << endl;
4007 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4008 d_assertions.replace(i, Rewriter::rewrite(d_assertions[i]));
4009 }
4010 unconstrainedSimp();
4011 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-unconstrained-simp" << endl;
4012 dumpAssertions("post-unconstrained-simp", d_assertions);
4013 }
4014
4015 if(options::bvIntroducePow2()){
4016 theory::bv::BVIntroducePow2::pow2Rewrite(d_assertions.ref());
4017 }
4018
4019 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-substitution" << endl;
4020 dumpAssertions("pre-substitution", d_assertions);
4021
4022 if(options::unsatCores()) {
4023 // special rewriting pass for unsat cores, since many of the passes below are skipped
4024 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4025 d_assertions.replace(i, Rewriter::rewrite(d_assertions[i]));
4026 }
4027 } else {
4028 // Apply the substitutions we already have, and normalize
4029 if(!options::unsatCores()) {
4030 Chat() << "applying substitutions..." << endl;
4031 Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
4032 << "applying substitutions" << endl;
4033 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4034 Trace("simplify") << "applying to " << d_assertions[i] << endl;
4035 spendResource(options::preprocessStep());
4036 d_assertions.replace(i, Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertions[i])));
4037 Trace("simplify") << " got " << d_assertions[i] << endl;
4038 }
4039 }
4040 }
4041 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-substitution" << endl;
4042 dumpAssertions("post-substitution", d_assertions);
4043
4044 // Assertions ARE guaranteed to be rewritten by this point
4045
4046 // Lift bit-vectors of size 1 to bool
4047 if(options::bitvectorToBool()) {
4048 dumpAssertions("pre-bv-to-bool", d_assertions);
4049 Chat() << "...doing bvToBool..." << endl;
4050 bvToBool();
4051 dumpAssertions("post-bv-to-bool", d_assertions);
4052 Trace("smt") << "POST bvToBool" << endl;
4053 }
4054 // Convert non-top-level Booleans to bit-vectors of size 1
4055 if(options::boolToBitvector()) {
4056 dumpAssertions("pre-bool-to-bv", d_assertions);
4057 Chat() << "...doing boolToBv..." << endl;
4058 boolToBv();
4059 dumpAssertions("post-bool-to-bv", d_assertions);
4060 Trace("smt") << "POST boolToBv" << endl;
4061 }
4062 if(options::sepPreSkolemEmp()) {
4063 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4064 Node prev = d_assertions[i];
4065 Node next = sep::TheorySepRewriter::preprocess( prev );
4066 if( next!=prev ){
4067 d_assertions.replace( i, Rewriter::rewrite( next ) );
4068 Trace("sep-preprocess") << "*** Preprocess sep " << prev << endl;
4069 Trace("sep-preprocess") << " ...got " << d_assertions[i] << endl;
4070 }
4071 }
4072 }
4073
4074 if( d_smt.d_logic.isQuantified() ){
4075 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-quant-preprocess" << endl;
4076
4077 dumpAssertions("pre-skolem-quant", d_assertions);
4078 //remove rewrite rules, apply pre-skolemization to existential quantifiers
4079 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4080 Node prev = d_assertions[i];
4081 Node next = quantifiers::QuantifiersRewriter::preprocess( prev );
4082 if( next!=prev ){
4083 d_assertions.replace( i, Rewriter::rewrite( next ) );
4084 Trace("quantifiers-preprocess") << "*** Pre-skolemize " << prev << endl;
4085 Trace("quantifiers-preprocess") << " ...got " << d_assertions[i] << endl;
4086 }
4087 }
4088 dumpAssertions("post-skolem-quant", d_assertions);
4089 if( options::macrosQuant() ){
4090 //quantifiers macro expansion
4091 quantifiers::QuantifierMacros qm( d_smt.d_theoryEngine->getQuantifiersEngine() );
4092 bool success;
4093 do{
4094 success = qm.simplify( d_assertions.ref(), true );
4095 }while( success );
4096 //finalize the definitions
4097 qm.finalizeDefinitions();
4098 }
4099
4100 //fmf-fun : assume admissible functions, applying preprocessing reduction to FMF
4101 if( options::fmfFunWellDefined() ){
4102 quantifiers::FunDefFmf fdf;
4103 Assert( d_smt.d_fmfRecFunctionsDefined!=NULL );
4104 //must carry over current definitions (for incremental)
4105 for( context::CDList<Node>::const_iterator fit = d_smt.d_fmfRecFunctionsDefined->begin();
4106 fit != d_smt.d_fmfRecFunctionsDefined->end(); ++fit ) {
4107 Node f = (*fit);
4108 Assert( d_smt.d_fmfRecFunctionsAbs.find( f )!=d_smt.d_fmfRecFunctionsAbs.end() );
4109 TypeNode ft = d_smt.d_fmfRecFunctionsAbs[f];
4110 fdf.d_sorts[f] = ft;
4111 std::map< Node, std::vector< Node > >::iterator fcit = d_smt.d_fmfRecFunctionsConcrete.find( f );
4112 Assert( fcit!=d_smt.d_fmfRecFunctionsConcrete.end() );
4113 for( unsigned j=0; j<fcit->second.size(); j++ ){
4114 fdf.d_input_arg_inj[f].push_back( fcit->second[j] );
4115 }
4116 }
4117 fdf.simplify( d_assertions.ref() );
4118 //must store new definitions (for incremental)
4119 for( unsigned i=0; i<fdf.d_funcs.size(); i++ ){
4120 Node f = fdf.d_funcs[i];
4121 d_smt.d_fmfRecFunctionsAbs[f] = fdf.d_sorts[f];
4122 d_smt.d_fmfRecFunctionsConcrete[f].clear();
4123 for( unsigned j=0; j<fdf.d_input_arg_inj[f].size(); j++ ){
4124 d_smt.d_fmfRecFunctionsConcrete[f].push_back( fdf.d_input_arg_inj[f][j] );
4125 }
4126 d_smt.d_fmfRecFunctionsDefined->push_back( f );
4127 }
4128 }
4129 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-quant-preprocess" << endl;
4130 }
4131
4132 if( options::sortInference() || options::ufssFairnessMonotone() ){
4133 //sort inference technique
4134 SortInference * si = d_smt.d_theoryEngine->getSortInference();
4135 si->simplify( d_assertions.ref(), options::sortInference(), options::ufssFairnessMonotone() );
4136 for( std::map< Node, Node >::iterator it = si->d_model_replace_f.begin(); it != si->d_model_replace_f.end(); ++it ){
4137 d_smt.setPrintFuncInModel( it->first.toExpr(), false );
4138 d_smt.setPrintFuncInModel( it->second.toExpr(), true );
4139 }
4140 }
4141
4142 if( options::pbRewrites() ){
4143 d_pbsProcessor.learn(d_assertions.ref());
4144 if(d_pbsProcessor.likelyToHelp()){
4145 d_pbsProcessor.applyReplacements(d_assertions.ref());
4146 }
4147 }
4148
4149 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-simplify" << endl;
4150 dumpAssertions("pre-simplify", d_assertions);
4151 Chat() << "simplifying assertions..." << endl;
4152 noConflict = simplifyAssertions();
4153 if(!noConflict){
4154 ++(d_smt.d_stats->d_simplifiedToFalse);
4155 }
4156 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-simplify" << endl;
4157 dumpAssertions("post-simplify", d_assertions);
4158
4159 dumpAssertions("pre-static-learning", d_assertions);
4160 if(options::doStaticLearning()) {
4161 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-static-learning" << endl;
4162 // Perform static learning
4163 Chat() << "doing static learning..." << endl;
4164 Trace("simplify") << "SmtEnginePrivate::simplify(): "
4165 << "performing static learning" << endl;
4166 staticLearning();
4167 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-static-learning" << endl;
4168 }
4169 dumpAssertions("post-static-learning", d_assertions);
4170
4171 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
4172
4173
4174 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-ite-removal" << endl;
4175 dumpAssertions("pre-ite-removal", d_assertions);
4176 {
4177 Chat() << "removing term ITEs..." << endl;
4178 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_iteRemovalTime);
4179 // Remove ITEs, updating d_iteSkolemMap
4180 d_smt.d_stats->d_numAssertionsPre += d_assertions.size();
4181 removeITEs();
4182 d_smt.d_stats->d_numAssertionsPost += d_assertions.size();
4183 }
4184 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-ite-removal" << endl;
4185 dumpAssertions("post-ite-removal", d_assertions);
4186
4187 dumpAssertions("pre-repeat-simplify", d_assertions);
4188 if(options::repeatSimp()) {
4189 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-repeat-simplify" << endl;
4190 Chat() << "re-simplifying assertions..." << endl;
4191 ScopeCounter depth(d_simplifyAssertionsDepth);
4192 noConflict &= simplifyAssertions();
4193 if (noConflict) {
4194 // Need to fix up assertion list to maintain invariants:
4195 // Let Sk be the set of Skolem variables introduced by ITE's. Let <_sk be the order in which these variables were introduced
4196 // during ite removal.
4197 // For each skolem variable sk, let iteExpr = iteMap(sk) be the ite expr mapped to by sk.
4198
4199 // cache for expression traversal
4200 unordered_map<Node, bool, NodeHashFunction> cache;
4201
4202 // First, find all skolems that appear in the substitution map - their associated iteExpr will need
4203 // to be moved to the main assertion set
4204 set<TNode> skolemSet;
4205 SubstitutionMap::iterator pos = d_topLevelSubstitutions.begin();
4206 for (; pos != d_topLevelSubstitutions.end(); ++pos) {
4207 collectSkolems((*pos).first, skolemSet, cache);
4208 collectSkolems((*pos).second, skolemSet, cache);
4209 }
4210
4211 // We need to ensure:
4212 // 1. iteExpr has the form (ite cond (sk = t) (sk = e))
4213 // 2. if some sk' in Sk appears in cond, t, or e, then sk' <_sk sk
4214 // If either of these is violated, we must add iteExpr as a proper assertion
4215 IteSkolemMap::iterator it = d_iteSkolemMap.begin();
4216 IteSkolemMap::iterator iend = d_iteSkolemMap.end();
4217 NodeBuilder<> builder(kind::AND);
4218 builder << d_assertions[d_realAssertionsEnd - 1];
4219 vector<TNode> toErase;
4220 for (; it != iend; ++it) {
4221 if (skolemSet.find((*it).first) == skolemSet.end()) {
4222 TNode iteExpr = d_assertions[(*it).second];
4223 if (iteExpr.getKind() == kind::ITE &&
4224 iteExpr[1].getKind() == kind::EQUAL &&
4225 iteExpr[1][0] == (*it).first &&
4226 iteExpr[2].getKind() == kind::EQUAL &&
4227 iteExpr[2][0] == (*it).first) {
4228 cache.clear();
4229 bool bad = checkForBadSkolems(iteExpr[0], (*it).first, cache);
4230 bad = bad || checkForBadSkolems(iteExpr[1][1], (*it).first, cache);
4231 bad = bad || checkForBadSkolems(iteExpr[2][1], (*it).first, cache);
4232 if (!bad) {
4233 continue;
4234 }
4235 }
4236 }
4237 // Move this iteExpr into the main assertions
4238 builder << d_assertions[(*it).second];
4239 d_assertions[(*it).second] = NodeManager::currentNM()->mkConst<bool>(true);
4240 toErase.push_back((*it).first);
4241 }
4242 if(builder.getNumChildren() > 1) {
4243 while (!toErase.empty()) {
4244 d_iteSkolemMap.erase(toErase.back());
4245 toErase.pop_back();
4246 }
4247 d_assertions[d_realAssertionsEnd - 1] = Rewriter::rewrite(Node(builder));
4248 }
4249 // For some reason this is needed for some benchmarks, such as
4250 // 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
4251 // Figure it out later
4252 removeITEs();
4253 // Assert(iteRewriteAssertionsEnd == d_assertions.size());
4254 }
4255 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-repeat-simplify" << endl;
4256 }
4257 dumpAssertions("post-repeat-simplify", d_assertions);
4258
4259 dumpAssertions("pre-rewrite-apply-to-const", d_assertions);
4260 if(options::rewriteApplyToConst()) {
4261 Chat() << "Rewriting applies to constants..." << endl;
4262 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_rewriteApplyToConstTime);
4263 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4264 d_assertions[i] = Rewriter::rewrite(rewriteApplyToConst(d_assertions[i]));
4265 }
4266 }
4267 dumpAssertions("post-rewrite-apply-to-const", d_assertions);
4268
4269 // begin: INVARIANT to maintain: no reordering of assertions or
4270 // introducing new ones
4271 #ifdef CVC4_ASSERTIONS
4272 unsigned iteRewriteAssertionsEnd = d_assertions.size();
4273 #endif
4274
4275 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
4276
4277 Debug("smt") << "SmtEnginePrivate::processAssertions() POST SIMPLIFICATION" << endl;
4278 Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
4279
4280 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-theory-preprocessing" << endl;
4281 dumpAssertions("pre-theory-preprocessing", d_assertions);
4282 {
4283 Chat() << "theory preprocessing..." << endl;
4284 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
4285 // Call the theory preprocessors
4286 d_smt.d_theoryEngine->preprocessStart();
4287 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4288 d_assertions.replace(i, d_smt.d_theoryEngine->preprocess(d_assertions[i]));
4289 }
4290 }
4291 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-theory-preprocessing" << endl;
4292 dumpAssertions("post-theory-preprocessing", d_assertions);
4293
4294 // If we are using eager bit-blasting wrap assertions in fake atom so that
4295 // everything gets bit-blasted to internal SAT solver
4296 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
4297 for (unsigned i = 0; i < d_assertions.size(); ++i) {
4298 TNode atom = d_assertions[i];
4299 Node eager_atom = NodeManager::currentNM()->mkNode(kind::BITVECTOR_EAGER_ATOM, atom);
4300 d_assertions.replace(i, eager_atom);
4301 TheoryModel* m = d_smt.d_theoryEngine->getModel();
4302 m->addSubstitution(eager_atom, atom);
4303 }
4304 }
4305
4306 //notify theory engine new preprocessed assertions
4307 d_smt.d_theoryEngine->notifyPreprocessedAssertions( d_assertions.ref() );
4308
4309 // Push the formula to decision engine
4310 if(noConflict) {
4311 Chat() << "pushing to decision engine..." << endl;
4312 Assert(iteRewriteAssertionsEnd == d_assertions.size());
4313 d_smt.d_decisionEngine->addAssertions
4314 (d_assertions.ref(), d_realAssertionsEnd, d_iteSkolemMap);
4315 }
4316
4317 // end: INVARIANT to maintain: no reordering of assertions or
4318 // introducing new ones
4319
4320 Trace("smt-proc") << "SmtEnginePrivate::processAssertions() end" << endl;
4321 dumpAssertions("post-everything", d_assertions);
4322
4323 // Push the formula to SAT
4324 {
4325 Chat() << "converting to CNF..." << endl;
4326 TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_cnfConversionTime);
4327 for (unsigned i = 0; i < d_assertions.size(); ++ i) {
4328 Chat() << "+ " << d_assertions[i] << std::endl;
4329 d_smt.d_propEngine->assertFormula(d_assertions[i]);
4330 }
4331 }
4332
4333 d_assertionsProcessed = true;
4334
4335 d_assertions.clear();
4336 d_iteSkolemMap.clear();
4337 }
4338
4339 void SmtEnginePrivate::addFormula(TNode n, bool inUnsatCore, bool inInput)
4340 throw(TypeCheckingException, LogicException) {
4341
4342 if (n == d_true) {
4343 // nothing to do
4344 return;
4345 }
4346
4347 Trace("smt") << "SmtEnginePrivate::addFormula(" << n << "), inUnsatCore = " << inUnsatCore << ", inInput = " << inInput << endl;
4348
4349 // Give it to proof manager
4350 PROOF(
4351 if( inInput ){
4352 // n is an input assertion
4353 if (inUnsatCore || options::unsatCores() || options::dumpUnsatCores() || options::checkUnsatCores() || options::fewerPreprocessingHoles()) {
4354
4355 ProofManager::currentPM()->addCoreAssertion(n.toExpr());
4356 }
4357 }else{
4358 // n is the result of an unknown preprocessing step, add it to dependency map to null
4359 ProofManager::currentPM()->addDependence(n, Node::null());
4360 }
4361 // rewrite rules are by default in the unsat core because
4362 // they need to be applied until saturation
4363 if(options::unsatCores() &&
4364 n.getKind() == kind::REWRITE_RULE ){
4365 ProofManager::currentPM()->addUnsatCore(n.toExpr());
4366 }
4367 );
4368
4369 // Add the normalized formula to the queue
4370 d_assertions.push_back(n);
4371 //d_assertions.push_back(Rewriter::rewrite(n));
4372 }
4373
4374 void SmtEngine::ensureBoolean(const Expr& e) throw(TypeCheckingException) {
4375 Type type = e.getType(options::typeChecking());
4376 Type boolType = d_exprManager->booleanType();
4377 if(type != boolType) {
4378 stringstream ss;
4379 ss << "Expected " << boolType << "\n"
4380 << "The assertion : " << e << "\n"
4381 << "Its type : " << type;
4382 throw TypeCheckingException(e, ss.str());
4383 }
4384 }
4385
4386 Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(Exception) {
4387 return checkSatisfiability(ex, inUnsatCore, false);
4388 } /* SmtEngine::checkSat() */
4389
4390 Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(Exception) {
4391 Assert(!ex.isNull());
4392 return checkSatisfiability(ex, inUnsatCore, true);
4393 } /* SmtEngine::query() */
4394
4395 Result SmtEngine::checkSatisfiability(const Expr& ex, bool inUnsatCore, bool isQuery) {
4396 try {
4397 Assert(ex.isNull() || ex.getExprManager() == d_exprManager);
4398 SmtScope smts(this);
4399 finalOptionsAreSet();
4400 doPendingPops();
4401
4402 Trace("smt") << "SmtEngine::" << (isQuery ? "query" : "checkSat") << "(" << ex << ")" << endl;
4403
4404 if(d_queryMade && !options::incrementalSolving()) {
4405 throw ModalException("Cannot make multiple queries unless "
4406 "incremental solving is enabled "
4407 "(try --incremental)");
4408 }
4409
4410 Expr e;
4411 if(!ex.isNull()) {
4412 // Substitute out any abstract values in ex.
4413 e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
4414 // Ensure expr is type-checked at this point.
4415 ensureBoolean(e);
4416 }
4417
4418 // check to see if a postsolve() is pending
4419 if(d_needPostsolve) {
4420 d_theoryEngine->postsolve();
4421 d_needPostsolve = false;
4422 }
4423
4424 // Push the context
4425 internalPush();
4426
4427 // Note that a query has been made
4428 d_queryMade = true;
4429
4430 // Add the formula
4431 if(!e.isNull()) {
4432 d_problemExtended = true;
4433 Expr ea = isQuery ? e.notExpr() : e;
4434 if(d_assertionList != NULL) {
4435 d_assertionList->push_back(ea);
4436 }
4437 d_private->addFormula(ea.getNode(), inUnsatCore);
4438 }
4439
4440 Result r(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
4441 r = isQuery ? check().asValidityResult() : check().asSatisfiabilityResult();
4442
4443 if ( ( options::solveRealAsInt() || options::solveIntAsBV() > 0 ) && r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
4444 r = Result(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
4445 }
4446
4447 d_needPostsolve = true;
4448
4449 // Dump the query if requested
4450 if(Dump.isOn("benchmark")) {
4451 // the expr already got dumped out if assertion-dumping is on
4452 if( isQuery ){
4453 Dump("benchmark") << QueryCommand(ex);
4454 }else{
4455 Dump("benchmark") << CheckSatCommand(ex);
4456 }
4457 }
4458
4459 // Pop the context
4460 internalPop();
4461
4462 // Remember the status
4463 d_status = r;
4464
4465 d_problemExtended = false;
4466
4467 Trace("smt") << "SmtEngine::" << (isQuery ? "query" : "checkSat") << "(" << e << ") => " << r << endl;
4468
4469 // Check that SAT results generate a model correctly.
4470 if(options::checkModels()) {
4471 if(r.asSatisfiabilityResult().isSat() == Result::SAT ||
4472 (r.isUnknown() && r.whyUnknown() == Result::INCOMPLETE) ){
4473 checkModel(/* hard failure iff */ ! r.isUnknown());
4474 }
4475 }
4476 // Check that UNSAT results generate a proof correctly.
4477 if(options::checkProofs()) {
4478 if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
4479 TimerStat::CodeTimer checkProofTimer(d_stats->d_checkProofTime);
4480 checkProof();
4481 }
4482 }
4483 // Check that UNSAT results generate an unsat core correctly.
4484 if(options::checkUnsatCores()) {
4485 if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
4486 TimerStat::CodeTimer checkUnsatCoreTimer(d_stats->d_checkUnsatCoreTime);
4487 checkUnsatCore();
4488 }
4489 }
4490
4491 return r;
4492 } catch (UnsafeInterruptException& e) {
4493 AlwaysAssert(d_private->getResourceManager()->out());
4494 Result::UnknownExplanation why = d_private->getResourceManager()->outOfResources() ?
4495 Result::RESOURCEOUT : Result::TIMEOUT;
4496 return Result(Result::SAT_UNKNOWN, why, d_filename);
4497 }
4498 }
4499
4500 Result SmtEngine::checkSynth(const Expr& e) throw(Exception) {
4501 SmtScope smts(this);
4502 Trace("smt") << "Check synth: " << e << std::endl;
4503 Trace("smt-synth") << "Check synthesis conjecture: " << e << std::endl;
4504 Expr e_check = e;
4505 Node conj = Node::fromExpr( e );
4506 if( conj.getKind()==kind::FORALL ){
4507 //possibly run quantifier elimination to make formula into single invocation
4508 if( conj[1].getKind()==kind::EXISTS ){
4509 Node conj_se = Node::fromExpr( expandDefinitions( conj[1][1].toExpr() ) );
4510
4511 Trace("smt-synth") << "Compute single invocation for " << conj_se << "..." << std::endl;
4512 quantifiers::SingleInvocationPartition sip;
4513 std::vector< Node > funcs;
4514 for( unsigned i=0; i<conj[0].getNumChildren(); i++ ){
4515 Node sf = conj[0][i].getAttribute(theory::SygusSynthFunAttribute());
4516 Assert( !sf.isNull() );
4517 funcs.push_back( sf );
4518 }
4519 sip.init( funcs, conj_se );
4520 Trace("smt-synth") << "...finished, got:" << std::endl;
4521 sip.debugPrint("smt-synth");
4522
4523 if( !sip.isPurelySingleInvocation() && sip.isNonGroundSingleInvocation() ){
4524 //We are in the case where our synthesis conjecture is exists f. forall xy. P( f( x ), x, y ), P does not contain f.
4525 //The following will run QE on (exists z x.) exists y. P( z, x, y ) to obtain Q( z, x ),
4526 // and then constructs exists f. forall x. Q( f( x ), x ), where Q does not contain f. We invoke synthesis solver on this result.
4527
4528 //create new smt engine to do quantifier elimination
4529 SmtEngine smt_qe( d_exprManager );
4530 smt_qe.setLogic(getLogicInfo());
4531 Trace("smt-synth") << "Property is non-ground single invocation, run QE to obtain single invocation." << std::endl;
4532 //partition variables
4533 std::vector< Node > qe_vars;
4534 std::vector< Node > nqe_vars;
4535 for( unsigned i=0; i<sip.d_all_vars.size(); i++ ){
4536 Node v = sip.d_all_vars[i];
4537 if( std::find( sip.d_si_vars.begin(), sip.d_si_vars.end(), v )==sip.d_si_vars.end() ){
4538 qe_vars.push_back( v );
4539 }else{
4540 nqe_vars.push_back( v );
4541 }
4542 }
4543 std::vector< Node > orig;
4544 std::vector< Node > subs;
4545 //skolemize non-qe variables
4546 for( unsigned i=0; i<nqe_vars.size(); i++ ){
4547 Node k = NodeManager::currentNM()->mkSkolem( "k", nqe_vars[i].getType(), "qe for non-ground single invocation" );
4548 orig.push_back( nqe_vars[i] );
4549 subs.push_back( k );
4550 Trace("smt-synth") << " subs : " << nqe_vars[i] << " -> " << k << std::endl;
4551 }
4552 for( std::map< Node, bool >::iterator it = sip.d_funcs.begin(); it != sip.d_funcs.end(); ++it ){
4553 orig.push_back( sip.d_func_inv[it->first] );
4554 Node k = NodeManager::currentNM()->mkSkolem( "k", sip.d_func_fo_var[it->first].getType(), "qe for function in non-ground single invocation" );
4555 subs.push_back( k );
4556 Trace("smt-synth") << " subs : " << sip.d_func_inv[it->first] << " -> " << k << std::endl;
4557 }
4558 Node conj_se_ngsi = sip.getFullSpecification();
4559 Node conj_se_ngsi_subs = conj_se_ngsi.substitute( orig.begin(), orig.end(), subs.begin(), subs.end() );
4560 Assert( !qe_vars.empty() );
4561 conj_se_ngsi_subs = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, qe_vars ), conj_se_ngsi_subs );
4562
4563 Trace("smt-synth") << "Run quantifier elimination on " << conj_se_ngsi_subs << std::endl;
4564 Expr qe_res = smt_qe.doQuantifierElimination( conj_se_ngsi_subs.toExpr(), true, false );
4565 Trace("smt-synth") << "Result : " << qe_res << std::endl;
4566
4567 //create single invocation conjecture
4568 Node qe_res_n = Node::fromExpr( qe_res );
4569 qe_res_n = qe_res_n.substitute( subs.begin(), subs.end(), orig.begin(), orig.end() );
4570 if( !nqe_vars.empty() ){
4571 qe_res_n = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, nqe_vars ), qe_res_n );
4572 }
4573 Assert( conj.getNumChildren()==3 );
4574 qe_res_n = NodeManager::currentNM()->mkNode( kind::FORALL, conj[0], qe_res_n, conj[2] );
4575 Trace("smt-synth") << "Converted conjecture after QE : " << qe_res_n << std::endl;
4576 e_check = qe_res_n.toExpr();
4577 }
4578 }
4579 }
4580
4581 return checkSatisfiability( e_check, true, false );
4582 }
4583
4584 Result SmtEngine::assertFormula(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
4585 Assert(ex.getExprManager() == d_exprManager);
4586 SmtScope smts(this);
4587 finalOptionsAreSet();
4588 doPendingPops();
4589
4590 Trace("smt") << "SmtEngine::assertFormula(" << ex << ")" << endl;
4591
4592 if (Dump.isOn("raw-benchmark")) {
4593 Dump("raw-benchmark") << AssertCommand(ex);
4594 }
4595
4596 // Substitute out any abstract values in ex
4597 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
4598
4599 ensureBoolean(e);
4600 if(d_assertionList != NULL) {
4601 d_assertionList->push_back(e);
4602 }
4603 d_private->addFormula(e.getNode(), inUnsatCore);
4604 return quickCheck().asValidityResult();
4605 }/* SmtEngine::assertFormula() */
4606
4607 Node SmtEngine::postprocess(TNode node, TypeNode expectedType) const {
4608 return node;
4609 }
4610
4611 Expr SmtEngine::simplify(const Expr& ex) throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
4612 Assert(ex.getExprManager() == d_exprManager);
4613 SmtScope smts(this);
4614 finalOptionsAreSet();
4615 doPendingPops();
4616 Trace("smt") << "SMT simplify(" << ex << ")" << endl;
4617
4618 if(Dump.isOn("benchmark")) {
4619 Dump("benchmark") << SimplifyCommand(ex);
4620 }
4621
4622 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
4623 if( options::typeChecking() ) {
4624 e.getType(true); // ensure expr is type-checked at this point
4625 }
4626
4627 // Make sure all preprocessing is done
4628 d_private->processAssertions();
4629 Node n = d_private->simplify(Node::fromExpr(e));
4630 n = postprocess(n, TypeNode::fromType(e.getType()));
4631 return n.toExpr();
4632 }
4633
4634 Expr SmtEngine::expandDefinitions(const Expr& ex) throw(TypeCheckingException, LogicException, UnsafeInterruptException) {
4635 d_private->spendResource(options::preprocessStep());
4636
4637 Assert(ex.getExprManager() == d_exprManager);
4638 SmtScope smts(this);
4639 finalOptionsAreSet();
4640 doPendingPops();
4641 Trace("smt") << "SMT expandDefinitions(" << ex << ")" << endl;
4642
4643 // Substitute out any abstract values in ex.
4644 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
4645 if(options::typeChecking()) {
4646 // Ensure expr is type-checked at this point.
4647 e.getType(true);
4648 }
4649 if(Dump.isOn("benchmark")) {
4650 Dump("benchmark") << ExpandDefinitionsCommand(e);
4651 }
4652 unordered_map<Node, Node, NodeHashFunction> cache;
4653 Node n = d_private->expandDefinitions(Node::fromExpr(e), cache, /* expandOnly = */ true);
4654 n = postprocess(n, TypeNode::fromType(e.getType()));
4655
4656 return n.toExpr();
4657 }
4658
4659 // TODO(#1108): Simplify the error reporting of this method.
4660 Expr SmtEngine::getValue(const Expr& ex) const throw(ModalException, TypeCheckingException, LogicException, UnsafeInterruptException) {
4661 Assert(ex.getExprManager() == d_exprManager);
4662 SmtScope smts(this);
4663
4664 Trace("smt") << "SMT getValue(" << ex << ")" << endl;
4665 if(Dump.isOn("benchmark")) {
4666 Dump("benchmark") << GetValueCommand(ex);
4667 }
4668
4669 if(!options::produceModels()) {
4670 const char* msg =
4671 "Cannot get value when produce-models options is off.";
4672 throw ModalException(msg);
4673 }
4674 if(d_status.isNull() ||
4675 d_status.asSatisfiabilityResult() == Result::UNSAT ||
4676 d_problemExtended) {
4677 const char* msg =
4678 "Cannot get value unless immediately preceded by SAT/INVALID or UNKNOWN response.";
4679 throw RecoverableModalException(msg);
4680 }
4681
4682 // Substitute out any abstract values in ex.
4683 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
4684
4685 // Ensure expr is type-checked at this point.
4686 e.getType(options::typeChecking());
4687
4688 // do not need to apply preprocessing substitutions (should be recorded
4689 // in model already)
4690
4691 Node n = Node::fromExpr(e);
4692 Trace("smt") << "--- getting value of " << n << endl;
4693 TypeNode expectedType = n.getType();
4694
4695 // Expand, then normalize
4696 unordered_map<Node, Node, NodeHashFunction> cache;
4697 n = d_private->expandDefinitions(n, cache);
4698 // There are two ways model values for terms are computed (for historical
4699 // reasons). One way is that used in check-model; the other is that
4700 // used by the Model classes. It's not clear to me exactly how these
4701 // two are different, but they need to be unified. This ugly hack here
4702 // is to fix bug 554 until we can revamp boolean-terms and models [MGD]
4703
4704 //AJR : necessary?
4705 if(!n.getType().isFunction()) {
4706 n = Rewriter::rewrite(n);
4707 }
4708
4709 Trace("smt") << "--- getting value of " << n << endl;
4710 TheoryModel* m = d_theoryEngine->getModel();
4711 Node resultNode;
4712 if(m != NULL) {
4713 resultNode = m->getValue(n);
4714 }
4715 Trace("smt") << "--- got value " << n << " = " << resultNode << endl;
4716 resultNode = postprocess(resultNode, expectedType);
4717 Trace("smt") << "--- model-post returned " << resultNode << endl;
4718 Trace("smt") << "--- model-post returned " << resultNode.getType() << endl;
4719 Trace("smt") << "--- model-post expected " << expectedType << endl;
4720
4721 // type-check the result we got
4722 Assert(resultNode.isNull() || resultNode.getType().isSubtypeOf(expectedType),
4723 "Run with -t smt for details.");
4724
4725 // ensure it's a constant
4726 Assert(resultNode.getKind() == kind::LAMBDA || resultNode.isConst());
4727
4728 if(options::abstractValues() && resultNode.getType().isArray()) {
4729 resultNode = d_private->mkAbstractValue(resultNode);
4730 Trace("smt") << "--- abstract value >> " << resultNode << endl;
4731 }
4732
4733 return resultNode.toExpr();
4734 }
4735
4736 bool SmtEngine::addToAssignment(const Expr& ex) {
4737 SmtScope smts(this);
4738 finalOptionsAreSet();
4739 doPendingPops();
4740 // Substitute out any abstract values in ex
4741 Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr();
4742 Type type = e.getType(options::typeChecking());
4743 // must be Boolean
4744 PrettyCheckArgument(
4745 type.isBoolean(), e,
4746 "expected Boolean-typed variable or function application "
4747 "in addToAssignment()" );
4748 Node n = e.getNode();
4749 // must be an APPLY of a zero-ary defined function, or a variable
4750 PrettyCheckArgument(
4751 ( ( n.getKind() == kind::APPLY &&
4752 ( d_definedFunctions->find(n.getOperator()) !=
4753 d_definedFunctions->end() ) &&
4754 n.getNumChildren() == 0 ) ||
4755 n.isVar() ), e,
4756 "expected variable or defined-function application "
4757 "in addToAssignment(),\ngot %s", e.toString().c_str() );
4758 if(!options::produceAssignments()) {
4759 return false;
4760 }
4761 if(d_assignments == NULL) {
4762 d_assignments = new(true) AssignmentSet(d_context);
4763 }
4764 d_assignments->insert(n);
4765
4766 return true;
4767 }
4768
4769 // TODO(#1108): Simplify the error reporting of this method.
4770 CVC4::SExpr SmtEngine::getAssignment() {
4771 Trace("smt") << "SMT getAssignment()" << endl;
4772 SmtScope smts(this);
4773 finalOptionsAreSet();
4774 if(Dump.isOn("benchmark")) {
4775 Dump("benchmark") << GetAssignmentCommand();
4776 }
4777 if(!options::produceAssignments()) {
4778 const char* msg =
4779 "Cannot get the current assignment when "
4780 "produce-assignments option is off.";
4781 throw ModalException(msg);
4782 }
4783 if(d_status.isNull() ||
4784 d_status.asSatisfiabilityResult() == Result::UNSAT ||
4785 d_problemExtended) {
4786 const char* msg =
4787 "Cannot get the current assignment unless immediately "
4788 "preceded by SAT/INVALID or UNKNOWN response.";
4789 throw RecoverableModalException(msg);
4790 }
4791
4792 if(d_assignments == NULL) {
4793 return SExpr(vector<SExpr>());
4794 }
4795
4796 vector<SExpr> sexprs;
4797 TypeNode boolType = d_nodeManager->booleanType();
4798 TheoryModel* m = d_theoryEngine->getModel();
4799 for(AssignmentSet::key_iterator i = d_assignments->key_begin(),
4800 iend = d_assignments->key_end();
4801 i != iend;
4802 ++i) {
4803 Assert((*i).getType() == boolType);
4804
4805 Trace("smt") << "--- getting value of " << *i << endl;
4806
4807 // Expand, then normalize
4808 unordered_map<Node, Node, NodeHashFunction> cache;
4809 Node n = d_private->expandDefinitions(*i, cache);
4810 n = Rewriter::rewrite(n);
4811
4812 Trace("smt") << "--- getting value of " << n << endl;
4813 Node resultNode;
4814 if(m != NULL) {
4815 resultNode = m->getValue(n);
4816 }
4817
4818 // type-check the result we got
4819 Assert(resultNode.isNull() || resultNode.getType() == boolType);
4820
4821 // ensure it's a constant
4822 Assert(resultNode.isConst());
4823
4824 vector<SExpr> v;
4825 if((*i).getKind() == kind::APPLY) {
4826 Assert((*i).getNumChildren() == 0);
4827 v.push_back(SExpr(SExpr::Keyword((*i).getOperator().toString())));
4828 } else {
4829 Assert((*i).isVar());
4830 v.push_back(SExpr(SExpr::Keyword((*i).toString())));
4831 }
4832 v.push_back(SExpr(SExpr::Keyword(resultNode.toString())));
4833 sexprs.push_back(SExpr(v));
4834 }
4835 return SExpr(sexprs);
4836 }
4837
4838 void SmtEngine::addToModelCommandAndDump(const Command& c, uint32_t flags, bool userVisible, const char* dumpTag) {
4839 Trace("smt") << "SMT addToModelCommandAndDump(" << c << ")" << endl;
4840 SmtScope smts(this);
4841 // If we aren't yet fully inited, the user might still turn on
4842 // produce-models. So let's keep any commands around just in
4843 // case. This is useful in two cases: (1) SMT-LIBv1 auto-declares
4844 // sort "U" in QF_UF before setLogic() is run and we still want to
4845 // support finding card(U) with --finite-model-find, and (2) to
4846 // decouple SmtEngine and ExprManager if the user does a few
4847 // ExprManager::mkSort() before SmtEngine::setOption("produce-models")
4848 // and expects to find their cardinalities in the model.
4849 if(/* userVisible && */
4850 (!d_fullyInited || options::produceModels()) &&
4851 (flags & ExprManager::VAR_FLAG_DEFINED) == 0) {
4852 doPendingPops();
4853 if(flags & ExprManager::VAR_FLAG_GLOBAL) {
4854 d_modelGlobalCommands.push_back(c.clone());
4855 } else {
4856 d_modelCommands->push_back(c.clone());
4857 }
4858 }
4859 if(Dump.isOn(dumpTag)) {
4860 if(d_fullyInited) {
4861 Dump(dumpTag) << c;
4862 } else {
4863 d_dumpCommands.push_back(c.clone());
4864 }
4865 }
4866 }
4867
4868 // TODO(#1108): Simplify the error reporting of this method.
4869 Model* SmtEngine::getModel() {
4870 Trace("smt") << "SMT getModel()" << endl;
4871 SmtScope smts(this);
4872
4873 finalOptionsAreSet();
4874
4875 if(Dump.isOn("benchmark")) {
4876 Dump("benchmark") << GetModelCommand();
4877 }
4878
4879 if(d_status.isNull() ||
4880 d_status.asSatisfiabilityResult() == Result::UNSAT ||
4881 d_problemExtended) {
4882 const char* msg =
4883 "Cannot get the current model unless immediately "
4884 "preceded by SAT/INVALID or UNKNOWN response.";
4885 throw RecoverableModalException(msg);
4886 }
4887 if(!options::produceModels()) {
4888 const char* msg =
4889 "Cannot get model when produce-models options is off.";
4890 throw ModalException(msg);
4891 }
4892 TheoryModel* m = d_theoryEngine->getModel();
4893 m->d_inputName = d_filename;
4894 return m;
4895 }
4896
4897 void SmtEngine::checkUnsatCore() {
4898 Assert(options::unsatCores(), "cannot check unsat core if unsat cores are turned off");
4899
4900 Notice() << "SmtEngine::checkUnsatCore(): generating unsat core" << endl;
4901 UnsatCore core = getUnsatCore();
4902
4903 SmtEngine coreChecker(d_exprManager);
4904 coreChecker.setLogic(getLogicInfo());
4905
4906 PROOF(
4907 std::vector<Command*>::const_iterator itg = d_defineCommands.begin();
4908 for (; itg != d_defineCommands.end(); ++itg) {
4909 (*itg)->invoke(&coreChecker);
4910 }
4911 );
4912
4913 Notice() << "SmtEngine::checkUnsatCore(): pushing core assertions (size == " << core.size() << ")" << endl;
4914 for(UnsatCore::iterator i = core.begin(); i != core.end(); ++i) {
4915 Notice() << "SmtEngine::checkUnsatCore(): pushing core member " << *i << endl;
4916 coreChecker.assertFormula(*i);
4917 }
4918 const bool checkUnsatCores = options::checkUnsatCores();
4919 Result r;
4920 try {
4921 options::checkUnsatCores.set(false);
4922 options::checkProofs.set(false);
4923 r = coreChecker.checkSat();
4924 } catch(...) {
4925 options::checkUnsatCores.set(checkUnsatCores);
4926 throw;
4927 }
4928 Notice() << "SmtEngine::checkUnsatCore(): result is " << r << endl;
4929 if(r.asSatisfiabilityResult().isUnknown()) {
4930 InternalError("SmtEngine::checkUnsatCore(): could not check core result unknown.");
4931 }
4932
4933 if(r.asSatisfiabilityResult().isSat()) {
4934 InternalError("SmtEngine::checkUnsatCore(): produced core was satisfiable.");
4935 }
4936 }
4937
4938 void SmtEngine::checkModel(bool hardFailure) {
4939 // --check-model implies --produce-assertions, which enables the
4940 // assertion list, so we should be ok.
4941 Assert(d_assertionList != NULL, "don't have an assertion list to check in SmtEngine::checkModel()");
4942
4943 TimerStat::CodeTimer checkModelTimer(d_stats->d_checkModelTime);
4944
4945 // Throughout, we use Notice() to give diagnostic output.
4946 //
4947 // If this function is running, the user gave --check-model (or equivalent),
4948 // and if Notice() is on, the user gave --verbose (or equivalent).
4949
4950 Notice() << "SmtEngine::checkModel(): generating model" << endl;
4951 TheoryModel* m = d_theoryEngine->getModel();
4952
4953 // Check individual theory assertions
4954 d_theoryEngine->checkTheoryAssertionsWithModel(hardFailure);
4955
4956 // Output the model
4957 Notice() << *m;
4958
4959 // We have a "fake context" for the substitution map (we don't need it
4960 // to be context-dependent)
4961 context::Context fakeContext;
4962 SubstitutionMap substitutions(&fakeContext, /* substituteUnderQuantifiers = */ false);
4963
4964 for(size_t k = 0; k < m->getNumCommands(); ++k) {
4965 const DeclareFunctionCommand* c = dynamic_cast<const DeclareFunctionCommand*>(m->getCommand(k));
4966 Notice() << "SmtEngine::checkModel(): model command " << k << " : " << m->getCommand(k) << endl;
4967 if(c == NULL) {
4968 // we don't care about DECLARE-DATATYPES, DECLARE-SORT, ...
4969 Notice() << "SmtEngine::checkModel(): skipping..." << endl;
4970 } else {
4971 // We have a DECLARE-FUN:
4972 //
4973 // We'll first do some checks, then add to our substitution map
4974 // the mapping: function symbol |-> value
4975
4976 Expr func = c->getFunction();
4977 Node val = m->getValue(func);
4978
4979 Notice() << "SmtEngine::checkModel(): adding substitution: " << func << " |-> " << val << endl;
4980
4981 // (1) if the value is a lambda, ensure the lambda doesn't contain the
4982 // function symbol (since then the definition is recursive)
4983 if (val.getKind() == kind::LAMBDA) {
4984 // first apply the model substitutions we have so far
4985 Debug("boolean-terms") << "applying subses to " << val[1] << endl;
4986 Node n = substitutions.apply(val[1]);
4987 Debug("boolean-terms") << "++ got " << n << endl;
4988 // now check if n contains func by doing a substitution
4989 // [func->func2] and checking equality of the Nodes.
4990 // (this just a way to check if func is in n.)
4991 SubstitutionMap subs(&fakeContext);
4992 Node func2 = NodeManager::currentNM()->mkSkolem("", TypeNode::fromType(func.getType()), "", NodeManager::SKOLEM_NO_NOTIFY);
4993 subs.addSubstitution(func, func2);
4994 if(subs.apply(n) != n) {
4995 Notice() << "SmtEngine::checkModel(): *** PROBLEM: MODEL VALUE DEFINED IN TERMS OF ITSELF ***" << endl;
4996 stringstream ss;
4997 ss << "SmtEngine::checkModel(): ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
4998 << "considering model value for " << func << endl
4999 << "body of lambda is: " << val << endl;
5000 if(n != val[1]) {
5001 ss << "body substitutes to: " << n << endl;
5002 }
5003 ss << "so " << func << " is defined in terms of itself." << endl
5004 << "Run with `--check-models -v' for additional diagnostics.";
5005 InternalError(ss.str());
5006 }
5007 }
5008
5009 // (2) check that the value is actually a value
5010 else if (!val.isConst()) {
5011 Notice() << "SmtEngine::checkModel(): *** PROBLEM: MODEL VALUE NOT A CONSTANT ***" << endl;
5012 stringstream ss;
5013 ss << "SmtEngine::checkModel(): ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
5014 << "model value for " << func << endl
5015 << " is " << val << endl
5016 << "and that is not a constant (.isConst() == false)." << endl
5017 << "Run with `--check-models -v' for additional diagnostics.";
5018 InternalError(ss.str());
5019 }
5020
5021 // (3) check that it's the correct (sub)type
5022 // This was intended to be a more general check, but for now we can't do that because
5023 // e.g. "1" is an INT, which isn't a subrange type [1..10] (etc.).
5024 else if(func.getType().isInteger() && !val.getType().isInteger()) {
5025 Notice() << "SmtEngine::checkModel(): *** PROBLEM: MODEL VALUE NOT CORRECT TYPE ***" << endl;
5026 stringstream ss;
5027 ss << "SmtEngine::checkModel(): ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
5028 << "model value for " << func << endl
5029 << " is " << val << endl
5030 << "value type is " << val.getType() << endl
5031 << "should be of type " << func.getType() << endl
5032 << "Run with `--check-models -v' for additional diagnostics.";
5033 InternalError(ss.str());
5034 }
5035
5036 // (4) checks complete, add the substitution
5037 Debug("boolean-terms") << "cm: adding subs " << func << " :=> " << val << endl;
5038 substitutions.addSubstitution(func, val);
5039 }
5040 }
5041
5042 // Now go through all our user assertions checking if they're satisfied.
5043 for(AssertionList::const_iterator i = d_assertionList->begin(); i != d_assertionList->end(); ++i) {
5044 Notice() << "SmtEngine::checkModel(): checking assertion " << *i << endl;
5045 Node n = Node::fromExpr(*i);
5046
5047 // Apply any define-funs from the problem.
5048 {
5049 unordered_map<Node, Node, NodeHashFunction> cache;
5050 n = d_private->expandDefinitions(n, cache);
5051 }
5052 Notice() << "SmtEngine::checkModel(): -- expands to " << n << endl;
5053
5054 // Apply our model value substitutions.
5055 Debug("boolean-terms") << "applying subses to " << n << endl;
5056 n = substitutions.apply(n);
5057 Debug("boolean-terms") << "++ got " << n << endl;
5058 Notice() << "SmtEngine::checkModel(): -- substitutes to " << n << endl;
5059
5060 if( n.getKind() != kind::REWRITE_RULE ){
5061 // In case it's a quantifier (or contains one), look up its value before
5062 // simplifying, or the quantifier might be irreparably altered.
5063 n = m->getValue(n);
5064 Notice() << "SmtEngine::checkModel(): -- get value : " << n << std::endl;
5065 } else {
5066 // Note this "skip" is done here, rather than above. This is
5067 // because (1) the quantifier could in principle simplify to false,
5068 // which should be reported, and (2) checking for the quantifier
5069 // above, before simplification, doesn't catch buried quantifiers
5070 // anyway (those not at the top-level).
5071 Notice() << "SmtEngine::checkModel(): -- skipping rewrite-rules assertion"
5072 << endl;
5073 continue;
5074 }
5075
5076 // Simplify the result.
5077 n = d_private->simplify(n);
5078 Notice() << "SmtEngine::checkModel(): -- simplifies to " << n << endl;
5079
5080 // Replace the already-known ITEs (this is important for ground ITEs under quantifiers).
5081 n = d_private->d_iteRemover.replace(n);
5082 Notice() << "SmtEngine::checkModel(): -- ite replacement gives " << n << endl;
5083
5084 // Apply our model value substitutions (again), as things may have been simplified.
5085 Debug("boolean-terms") << "applying subses to " << n << endl;
5086 n = substitutions.apply(n);
5087 Debug("boolean-terms") << "++ got " << n << endl;
5088 Notice() << "SmtEngine::checkModel(): -- re-substitutes to " << n << endl;
5089
5090 // As a last-ditch effort, ask model to simplify it.
5091 // Presently, this is only an issue for quantifiers, which can have a value
5092 // but don't show up in our substitution map above.
5093 n = m->getValue(n);
5094 Notice() << "SmtEngine::checkModel(): -- model-substitutes to " << n << endl;
5095
5096 if( d_logic.isQuantified() ){
5097 // AJR: since quantified formulas are not checkable, we assign them to true/false based on the satisfying assignment.
5098 // however, quantified formulas can be modified during preprocess, so they may not correspond to those in the satisfying assignment.
5099 // hence we use a relaxed version of check model here.
5100 // this is necessary until preprocessing passes explicitly record how they rewrite quantified formulas
5101 if( hardFailure && !n.isConst() && n.getKind() != kind::LAMBDA ){
5102 Notice() << "SmtEngine::checkModel(): -- relax check model wrt quantified formulas..." << endl;
5103 AlwaysAssert( quantifiers::QuantifiersRewriter::containsQuantifiers( n ) );
5104 Warning() << "Warning : SmtEngine::checkModel(): cannot check simplified assertion : " << n << endl;
5105 continue;
5106 }
5107 }else{
5108 AlwaysAssert(!hardFailure || n.isConst() || n.getKind() == kind::LAMBDA);
5109 }
5110 // The result should be == true.
5111 if(n != NodeManager::currentNM()->mkConst(true)) {
5112 Notice() << "SmtEngine::checkModel(): *** PROBLEM: EXPECTED `TRUE' ***"
5113 << endl;
5114 stringstream ss;
5115 ss << "SmtEngine::checkModel(): "
5116 << "ERRORS SATISFYING ASSERTIONS WITH MODEL:" << endl
5117 << "assertion: " << *i << endl
5118 << "simplifies to: " << n << endl
5119 << "expected `true'." << endl
5120 << "Run with `--check-models -v' for additional diagnostics.";
5121 if(hardFailure) {
5122 InternalError(ss.str());
5123 } else {
5124 Warning() << ss.str() << endl;
5125 }
5126 }
5127 }
5128 Notice() << "SmtEngine::checkModel(): all assertions checked out OK !" << endl;
5129 }
5130
5131 // TODO(#1108): Simplify the error reporting of this method.
5132 UnsatCore SmtEngine::getUnsatCore() {
5133 Trace("smt") << "SMT getUnsatCore()" << endl;
5134 SmtScope smts(this);
5135 finalOptionsAreSet();
5136 if(Dump.isOn("benchmark")) {
5137 Dump("benchmark") << GetUnsatCoreCommand();
5138 }
5139 #if IS_PROOFS_BUILD
5140 if(!options::unsatCores()) {
5141 throw ModalException("Cannot get an unsat core when produce-unsat-cores option is off.");
5142 }
5143 if(d_status.isNull() ||
5144 d_status.asSatisfiabilityResult() != Result::UNSAT ||
5145 d_problemExtended) {
5146 throw RecoverableModalException(
5147 "Cannot get an unsat core unless immediately preceded by UNSAT/VALID "
5148 "response.");
5149 }
5150
5151 d_proofManager->traceUnsatCore();// just to trigger core creation
5152 return UnsatCore(this, d_proofManager->extractUnsatCore());
5153 #else /* IS_PROOFS_BUILD */
5154 throw ModalException("This build of CVC4 doesn't have proof support (required for unsat cores).");
5155 #endif /* IS_PROOFS_BUILD */
5156 }
5157
5158 // TODO(#1108): Simplify the error reporting of this method.
5159 Proof* SmtEngine::getProof() {
5160 Trace("smt") << "SMT getProof()" << endl;
5161 SmtScope smts(this);
5162 finalOptionsAreSet();
5163 if(Dump.isOn("benchmark")) {
5164 Dump("benchmark") << GetProofCommand();
5165 }
5166 #if IS_PROOFS_BUILD
5167 if(!options::proof()) {
5168 throw ModalException("Cannot get a proof when produce-proofs option is off.");
5169 }
5170 if(d_status.isNull() ||
5171 d_status.asSatisfiabilityResult() != Result::UNSAT ||
5172 d_problemExtended) {
5173 throw RecoverableModalException(
5174 "Cannot get a proof unless immediately preceded by UNSAT/VALID "
5175 "response.");
5176 }
5177
5178 return ProofManager::getProof(this);
5179 #else /* IS_PROOFS_BUILD */
5180 throw ModalException("This build of CVC4 doesn't have proof support.");
5181 #endif /* IS_PROOFS_BUILD */
5182 }
5183
5184 void SmtEngine::printInstantiations( std::ostream& out ) {
5185 SmtScope smts(this);
5186 if( options::instFormatMode()==INST_FORMAT_MODE_SZS ){
5187 out << "% SZS output start Proof for " << d_filename.c_str() << std::endl;
5188 }
5189 if( d_theoryEngine ){
5190 d_theoryEngine->printInstantiations( out );
5191 }else{
5192 Assert( false );
5193 }
5194 if( options::instFormatMode()==INST_FORMAT_MODE_SZS ){
5195 out << "% SZS output end Proof for " << d_filename.c_str() << std::endl;
5196 }
5197 }
5198
5199 void SmtEngine::printSynthSolution( std::ostream& out ) {
5200 SmtScope smts(this);
5201 if( d_theoryEngine ){
5202 d_theoryEngine->printSynthSolution( out );
5203 }else{
5204 Assert( false );
5205 }
5206 }
5207
5208 Expr SmtEngine::doQuantifierElimination(const Expr& e, bool doFull,
5209 bool strict) throw(Exception) {
5210 SmtScope smts(this);
5211 if(!d_logic.isPure(THEORY_ARITH) && strict){
5212 Warning() << "Unexpected logic for quantifier elimination " << d_logic << endl;
5213 }
5214 Trace("smt-qe") << "Do quantifier elimination " << e << std::endl;
5215 Node n_e = Node::fromExpr( e );
5216 if( n_e.getKind()!=kind::EXISTS ){
5217 throw ModalException("Expecting an existentially quantified formula as argument to get-qe.");
5218 }
5219 //tag the quantified formula with the quant-elim attribute
5220 TypeNode t = NodeManager::currentNM()->booleanType();
5221 Node n_attr = NodeManager::currentNM()->mkSkolem("qe", t, "Auxiliary variable for qe attr.");
5222 std::vector< Node > node_values;
5223 d_theoryEngine->setUserAttribute( doFull ? "quant-elim" : "quant-elim-partial", n_attr, node_values, "");
5224 n_attr = NodeManager::currentNM()->mkNode(kind::INST_ATTRIBUTE, n_attr);
5225 n_attr = NodeManager::currentNM()->mkNode(kind::INST_PATTERN_LIST, n_attr);
5226 std::vector< Node > e_children;
5227 e_children.push_back( n_e[0] );
5228 e_children.push_back( n_e[1] );
5229 e_children.push_back( n_attr );
5230 Node nn_e = NodeManager::currentNM()->mkNode( kind::EXISTS, e_children );
5231 Trace("smt-qe-debug") << "Query for quantifier elimination : " << nn_e << std::endl;
5232 Assert( nn_e.getNumChildren()==3 );
5233 Result r = checkSatisfiability(nn_e.toExpr(), true, true);
5234 Trace("smt-qe") << "Query returned " << r << std::endl;
5235 if(r.asSatisfiabilityResult().isSat() != Result::UNSAT ) {
5236 if( r.asSatisfiabilityResult().isSat() != Result::SAT && doFull ){
5237 stringstream ss;
5238 ss << "While performing quantifier elimination, unexpected result : " << r << " for query.";
5239 InternalError(ss.str().c_str());
5240 }
5241 std::vector< Node > inst_qs;
5242 d_theoryEngine->getInstantiatedQuantifiedFormulas( inst_qs );
5243 Assert( inst_qs.size()<=1 );
5244 Node ret_n;
5245 if( inst_qs.size()==1 ){
5246 Node top_q = inst_qs[0];
5247 //Node top_q = Rewriter::rewrite( nn_e ).negate();
5248 Assert( top_q.getKind()==kind::FORALL );
5249 Trace("smt-qe") << "Get qe for " << top_q << std::endl;
5250 ret_n = d_theoryEngine->getInstantiatedConjunction( top_q );
5251 Trace("smt-qe") << "Returned : " << ret_n << std::endl;
5252 ret_n = Rewriter::rewrite( ret_n.negate() );
5253 }else{
5254 ret_n = NodeManager::currentNM()->mkConst(false);
5255 }
5256 return ret_n.toExpr();
5257 }else {
5258 return NodeManager::currentNM()->mkConst(true).toExpr();
5259 }
5260 }
5261
5262 void SmtEngine::getInstantiatedQuantifiedFormulas( std::vector< Expr >& qs ) {
5263 SmtScope smts(this);
5264 if( d_theoryEngine ){
5265 std::vector< Node > qs_n;
5266 d_theoryEngine->getInstantiatedQuantifiedFormulas( qs_n );
5267 for( unsigned i=0; i<qs_n.size(); i++ ){
5268 qs.push_back( qs_n[i].toExpr() );
5269 }
5270 }else{
5271 Assert( false );
5272 }
5273 }
5274
5275 void SmtEngine::getInstantiations( Expr q, std::vector< Expr >& insts ) {
5276 SmtScope smts(this);
5277 if( d_theoryEngine ){
5278 std::vector< Node > insts_n;
5279 d_theoryEngine->getInstantiations( Node::fromExpr( q ), insts_n );
5280 for( unsigned i=0; i<insts_n.size(); i++ ){
5281 insts.push_back( insts_n[i].toExpr() );
5282 }
5283 }else{
5284 Assert( false );
5285 }
5286 }
5287
5288 void SmtEngine::getInstantiationTermVectors( Expr q, std::vector< std::vector< Expr > >& tvecs ) {
5289 SmtScope smts(this);
5290 Assert(options::trackInstLemmas());
5291 if( d_theoryEngine ){
5292 std::vector< std::vector< Node > > tvecs_n;
5293 d_theoryEngine->getInstantiationTermVectors( Node::fromExpr( q ), tvecs_n );
5294 for( unsigned i=0; i<tvecs_n.size(); i++ ){
5295 std::vector< Expr > tvec;
5296 for( unsigned j=0; j<tvecs_n[i].size(); j++ ){
5297 tvec.push_back( tvecs_n[i][j].toExpr() );
5298 }
5299 tvecs.push_back( tvec );
5300 }
5301 }else{
5302 Assert( false );
5303 }
5304 }
5305
5306 vector<Expr> SmtEngine::getAssertions() {
5307 SmtScope smts(this);
5308 finalOptionsAreSet();
5309 doPendingPops();
5310 if(Dump.isOn("benchmark")) {
5311 Dump("benchmark") << GetAssertionsCommand();
5312 }
5313 Trace("smt") << "SMT getAssertions()" << endl;
5314 if(!options::produceAssertions()) {
5315 const char* msg =
5316 "Cannot query the current assertion list when not in produce-assertions mode.";
5317 throw ModalException(msg);
5318 }
5319 Assert(d_assertionList != NULL);
5320 // copy the result out
5321 return vector<Expr>(d_assertionList->begin(), d_assertionList->end());
5322 }
5323
5324 void SmtEngine::push() throw(ModalException, LogicException, UnsafeInterruptException) {
5325 SmtScope smts(this);
5326 finalOptionsAreSet();
5327 doPendingPops();
5328 Trace("smt") << "SMT push()" << endl;
5329 d_private->processAssertions();
5330 if(Dump.isOn("benchmark")) {
5331 Dump("benchmark") << PushCommand();
5332 }
5333 if(!options::incrementalSolving()) {
5334 throw ModalException("Cannot push when not solving incrementally (use --incremental)");
5335 }
5336
5337 // check to see if a postsolve() is pending
5338 if(d_needPostsolve) {
5339 d_theoryEngine->postsolve();
5340 d_needPostsolve = false;
5341 }
5342
5343 // The problem isn't really "extended" yet, but this disallows
5344 // get-model after a push, simplifying our lives somewhat and
5345 // staying symmtric with pop.
5346 d_problemExtended = true;
5347
5348 d_userLevels.push_back(d_userContext->getLevel());
5349 internalPush();
5350 Trace("userpushpop") << "SmtEngine: pushed to level "
5351 << d_userContext->getLevel() << endl;
5352 }
5353
5354 void SmtEngine::pop() {
5355 SmtScope smts(this);
5356 finalOptionsAreSet();
5357 Trace("smt") << "SMT pop()" << endl;
5358 if(Dump.isOn("benchmark")) {
5359 Dump("benchmark") << PopCommand();
5360 }
5361 if(!options::incrementalSolving()) {
5362 throw ModalException("Cannot pop when not solving incrementally (use --incremental)");
5363 }
5364 if(d_userLevels.size() == 0) {
5365 throw ModalException("Cannot pop beyond the first user frame");
5366 }
5367
5368 // check to see if a postsolve() is pending
5369 if(d_needPostsolve) {
5370 d_theoryEngine->postsolve();
5371 d_needPostsolve = false;
5372 }
5373
5374 // The problem isn't really "extended" yet, but this disallows
5375 // get-model after a pop, simplifying our lives somewhat. It might
5376 // not be strictly necessary to do so, since the pops occur lazily,
5377 // but also it would be weird to have a legally-executed (get-model)
5378 // that only returns a subset of the assignment (because the rest
5379 // is no longer in scope!).
5380 d_problemExtended = true;
5381
5382 AlwaysAssert(d_userContext->getLevel() > 0);
5383 AlwaysAssert(d_userLevels.back() < d_userContext->getLevel());
5384 while (d_userLevels.back() < d_userContext->getLevel()) {
5385 internalPop(true);
5386 }
5387 d_userLevels.pop_back();
5388
5389 // Clear out assertion queues etc., in case anything is still in there
5390 d_private->notifyPop();
5391
5392 Trace("userpushpop") << "SmtEngine: popped to level "
5393 << d_userContext->getLevel() << endl;
5394 // FIXME: should we reset d_status here?
5395 // SMT-LIBv2 spec seems to imply no, but it would make sense to..
5396 }
5397
5398 void SmtEngine::internalPush() {
5399 Assert(d_fullyInited);
5400 Trace("smt") << "SmtEngine::internalPush()" << endl;
5401 doPendingPops();
5402 if(options::incrementalSolving()) {
5403 d_private->processAssertions();
5404 TimerStat::CodeTimer pushPopTimer(d_stats->d_pushPopTime);
5405 d_userContext->push();
5406 // the d_context push is done inside of the SAT solver
5407 d_propEngine->push();
5408 }
5409 }
5410
5411 void SmtEngine::internalPop(bool immediate) {
5412 Assert(d_fullyInited);
5413 Trace("smt") << "SmtEngine::internalPop()" << endl;
5414 if(options::incrementalSolving()) {
5415 ++d_pendingPops;
5416 }
5417 if(immediate) {
5418 doPendingPops();
5419 }
5420 }
5421
5422 void SmtEngine::doPendingPops() {
5423 Assert(d_pendingPops == 0 || options::incrementalSolving());
5424 while(d_pendingPops > 0) {
5425 TimerStat::CodeTimer pushPopTimer(d_stats->d_pushPopTime);
5426 d_propEngine->pop();
5427 // the d_context pop is done inside of the SAT solver
5428 d_userContext->pop();
5429 --d_pendingPops;
5430 }
5431 }
5432
5433 void SmtEngine::reset() throw() {
5434 SmtScope smts(this);
5435 ExprManager *em = d_exprManager;
5436 Trace("smt") << "SMT reset()" << endl;
5437 if(Dump.isOn("benchmark")) {
5438 Dump("benchmark") << ResetCommand();
5439 }
5440 Options opts;
5441 opts.copyValues(d_originalOptions);
5442 this->~SmtEngine();
5443 NodeManager::fromExprManager(em)->getOptions().copyValues(opts);
5444 new(this) SmtEngine(em);
5445 }
5446
5447 void SmtEngine::resetAssertions() throw() {
5448 SmtScope smts(this);
5449
5450 Trace("smt") << "SMT resetAssertions()" << endl;
5451 if(Dump.isOn("benchmark")) {
5452 Dump("benchmark") << ResetAssertionsCommand();
5453 }
5454
5455 while(!d_userLevels.empty()) {
5456 pop();
5457 }
5458
5459 // Also remember the global push/pop around everything.
5460 Assert(d_userLevels.size() == 0 && d_userContext->getLevel() == 1);
5461 d_context->popto(0);
5462 d_userContext->popto(0);
5463 DeleteAndClearCommandVector(d_modelGlobalCommands);
5464 d_userContext->push();
5465 d_context->push();
5466 }
5467
5468 void SmtEngine::interrupt() throw(ModalException) {
5469 if(!d_fullyInited) {
5470 return;
5471 }
5472 d_propEngine->interrupt();
5473 d_theoryEngine->interrupt();
5474 }
5475
5476 void SmtEngine::setResourceLimit(unsigned long units, bool cumulative) {
5477 d_private->getResourceManager()->setResourceLimit(units, cumulative);
5478 }
5479 void SmtEngine::setTimeLimit(unsigned long milis, bool cumulative) {
5480 d_private->getResourceManager()->setTimeLimit(milis, cumulative);
5481 }
5482
5483 unsigned long SmtEngine::getResourceUsage() const {
5484 return d_private->getResourceManager()->getResourceUsage();
5485 }
5486
5487 unsigned long SmtEngine::getTimeUsage() const {
5488 return d_private->getResourceManager()->getTimeUsage();
5489 }
5490
5491 unsigned long SmtEngine::getResourceRemaining() const throw(ModalException) {
5492 return d_private->getResourceManager()->getResourceRemaining();
5493 }
5494
5495 unsigned long SmtEngine::getTimeRemaining() const throw(ModalException) {
5496 return d_private->getResourceManager()->getTimeRemaining();
5497 }
5498
5499 Statistics SmtEngine::getStatistics() const throw() {
5500 return Statistics(*d_statisticsRegistry);
5501 }
5502
5503 SExpr SmtEngine::getStatistic(std::string name) const throw() {
5504 return d_statisticsRegistry->getStatistic(name);
5505 }
5506
5507 void SmtEngine::safeFlushStatistics(int fd) const {
5508 d_statisticsRegistry->safeFlushInformation(fd);
5509 }
5510
5511 void SmtEngine::setUserAttribute(const std::string& attr, Expr expr, std::vector<Expr> expr_values, std::string str_value) {
5512 SmtScope smts(this);
5513 std::vector<Node> node_values;
5514 for( unsigned i=0; i<expr_values.size(); i++ ){
5515 node_values.push_back( expr_values[i].getNode() );
5516 }
5517 d_theoryEngine->setUserAttribute(attr, expr.getNode(), node_values, str_value);
5518 }
5519
5520 void SmtEngine::setPrintFuncInModel(Expr f, bool p) {
5521 Trace("setp-model") << "Set printInModel " << f << " to " << p << std::endl;
5522 for( unsigned i=0; i<d_modelGlobalCommands.size(); i++ ){
5523 Command * c = d_modelGlobalCommands[i];
5524 DeclareFunctionCommand* dfc = dynamic_cast<DeclareFunctionCommand*>(c);
5525 if(dfc != NULL) {
5526 if( dfc->getFunction()==f ){
5527 dfc->setPrintInModel( p );
5528 }
5529 }
5530 }
5531 for( unsigned i=0; i<d_modelCommands->size(); i++ ){
5532 Command * c = (*d_modelCommands)[i];
5533 DeclareFunctionCommand* dfc = dynamic_cast<DeclareFunctionCommand*>(c);
5534 if(dfc != NULL) {
5535 if( dfc->getFunction()==f ){
5536 dfc->setPrintInModel( p );
5537 }
5538 }
5539 }
5540 }
5541
5542
5543
5544 void SmtEngine::beforeSearch() throw(ModalException) {
5545 if(d_fullyInited) {
5546 throw ModalException(
5547 "SmtEngine::beforeSearch called after initialization.");
5548 }
5549 }
5550
5551
5552 void SmtEngine::setOption(const std::string& key, const CVC4::SExpr& value)
5553 throw(OptionException, ModalException) {
5554
5555 NodeManagerScope nms(d_nodeManager);
5556 Trace("smt") << "SMT setOption(" << key << ", " << value << ")" << endl;
5557
5558 if(Dump.isOn("benchmark")) {
5559 Dump("benchmark") << SetOptionCommand(key, value);
5560 }
5561
5562 if(key == "command-verbosity") {
5563 if(!value.isAtom()) {
5564 const vector<SExpr>& cs = value.getChildren();
5565 if(cs.size() == 2 &&
5566 (cs[0].isKeyword() || cs[0].isString()) &&
5567 cs[1].isInteger()) {
5568 string c = cs[0].getValue();
5569 const Integer& v = cs[1].getIntegerValue();
5570 if(v < 0 || v > 2) {
5571 throw OptionException("command-verbosity must be 0, 1, or 2");
5572 }
5573 d_commandVerbosity[c] = v;
5574 return;
5575 }
5576 }
5577 throw OptionException("command-verbosity value must be a tuple (command-name, integer)");
5578 }
5579
5580 if(!value.isAtom()) {
5581 throw OptionException("bad value for :" + key);
5582 }
5583
5584 string optionarg = value.getValue();
5585 Options& nodeManagerOptions = NodeManager::currentNM()->getOptions();
5586 nodeManagerOptions.setOption(key, optionarg);
5587 }
5588
5589 CVC4::SExpr SmtEngine::getOption(const std::string& key) const
5590 throw(OptionException) {
5591
5592 NodeManagerScope nms(d_nodeManager);
5593
5594 Trace("smt") << "SMT getOption(" << key << ")" << endl;
5595
5596 if(key.length() >= 18 &&
5597 key.compare(0, 18, "command-verbosity:") == 0) {
5598 map<string, Integer>::const_iterator i = d_commandVerbosity.find(key.c_str() + 18);
5599 if(i != d_commandVerbosity.end()) {
5600 return SExpr((*i).second);
5601 }
5602 i = d_commandVerbosity.find("*");
5603 if(i != d_commandVerbosity.end()) {
5604 return SExpr((*i).second);
5605 }
5606 return SExpr(Integer(2));
5607 }
5608
5609 if(Dump.isOn("benchmark")) {
5610 Dump("benchmark") << GetOptionCommand(key);
5611 }
5612
5613 if(key == "command-verbosity") {
5614 vector<SExpr> result;
5615 SExpr defaultVerbosity;
5616 for(map<string, Integer>::const_iterator i = d_commandVerbosity.begin();
5617 i != d_commandVerbosity.end();
5618 ++i) {
5619 vector<SExpr> v;
5620 v.push_back(SExpr((*i).first));
5621 v.push_back(SExpr((*i).second));
5622 if((*i).first == "*") {
5623 // put the default at the end of the SExpr
5624 defaultVerbosity = SExpr(v);
5625 } else {
5626 result.push_back(SExpr(v));
5627 }
5628 }
5629 // put the default at the end of the SExpr
5630 if(!defaultVerbosity.isAtom()) {
5631 result.push_back(defaultVerbosity);
5632 } else {
5633 // ensure the default is always listed
5634 vector<SExpr> v;
5635 v.push_back(SExpr("*"));
5636 v.push_back(SExpr(Integer(2)));
5637 result.push_back(SExpr(v));
5638 }
5639 return SExpr(result);
5640 }
5641
5642 Options& nodeManagerOptions = NodeManager::currentNM()->getOptions();
5643 return SExpr::parseAtom(nodeManagerOptions.getOption(key));
5644 }
5645
5646 void SmtEngine::setReplayStream(ExprStream* replayStream) {
5647 AlwaysAssert(!d_fullyInited,
5648 "Cannot set replay stream once fully initialized");
5649 d_replayStream = replayStream;
5650 }
5651
5652 }/* CVC4 namespace */