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