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