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