1 /******************************************************************************
2 * Top contributors (to current version):
3 * Andrew Reynolds, Morgan Deters, Abdalrhman Mohamed
5 * This file is part of the cvc5 project.
7 * Copyright (c) 2009-2021 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.
11 * ****************************************************************************
13 * The main entry point into the cvc5 library's SMT interface.
16 #include "smt/solver_engine.h"
18 #include "base/check.h"
19 #include "base/exception.h"
20 #include "base/modal_exception.h"
21 #include "base/output.h"
22 #include "decision/decision_engine.h"
23 #include "expr/bound_var_manager.h"
24 #include "expr/node.h"
25 #include "expr/node_algorithm.h"
26 #include "options/base_options.h"
27 #include "options/expr_options.h"
28 #include "options/language.h"
29 #include "options/main_options.h"
30 #include "options/option_exception.h"
31 #include "options/options_public.h"
32 #include "options/parser_options.h"
33 #include "options/printer_options.h"
34 #include "options/proof_options.h"
35 #include "options/smt_options.h"
36 #include "options/theory_options.h"
37 #include "printer/printer.h"
38 #include "proof/unsat_core.h"
39 #include "prop/prop_engine.h"
40 #include "smt/abduction_solver.h"
41 #include "smt/abstract_values.h"
42 #include "smt/assertions.h"
43 #include "smt/check_models.h"
45 #include "smt/interpolation_solver.h"
46 #include "smt/listeners.h"
47 #include "smt/logic_exception.h"
48 #include "smt/model_blocker.h"
49 #include "smt/model_core_builder.h"
50 #include "smt/preprocessor.h"
51 #include "smt/proof_manager.h"
52 #include "smt/quant_elim_solver.h"
53 #include "smt/set_defaults.h"
54 #include "smt/smt_solver.h"
55 #include "smt/solver_engine_scope.h"
56 #include "smt/solver_engine_state.h"
57 #include "smt/solver_engine_stats.h"
58 #include "smt/sygus_solver.h"
59 #include "smt/unsat_core_manager.h"
60 #include "theory/quantifiers/instantiation_list.h"
61 #include "theory/quantifiers/quantifiers_attributes.h"
62 #include "theory/quantifiers_engine.h"
63 #include "theory/rewriter.h"
64 #include "theory/smt_engine_subsolver.h"
65 #include "theory/theory_engine.h"
66 #include "util/random.h"
67 #include "util/rational.h"
68 #include "util/resource_manager.h"
69 #include "util/sexpr.h"
70 #include "util/statistics_registry.h"
72 // required for hacks related to old proofs for unsat cores
73 #include "base/configuration.h"
74 #include "base/configuration_private.h"
77 using namespace cvc5::smt
;
78 using namespace cvc5::preprocessing
;
79 using namespace cvc5::prop
;
80 using namespace cvc5::context
;
81 using namespace cvc5::theory
;
85 SolverEngine::SolverEngine(NodeManager
* nm
, const Options
* optr
)
86 : d_env(new Env(nm
, optr
)),
87 d_state(new SolverEngineState(*d_env
.get(), *this)),
88 d_absValues(new AbstractValues(getNodeManager())),
89 d_asserts(new Assertions(*d_env
.get(), *d_absValues
.get())),
90 d_routListener(new ResourceOutListener(*this)),
92 d_checkModels(nullptr),
95 d_sygusSolver(nullptr),
96 d_abductSolver(nullptr),
97 d_interpolSolver(nullptr),
98 d_quantElimSolver(nullptr),
99 d_isInternalSubsolver(false),
103 // !!!!!!!!!!!!!!!!!!!!!! temporary hack: this makes the current SolverEngine
104 // we are constructing the current SolverEngine in scope for the lifetime of
105 // this SolverEngine, or until another SolverEngine is constructed (that
106 // SolverEngine is then in scope during its lifetime). This is mostly to
107 // ensure that options are always in scope, for e.g. printing expressions,
108 // which rely on knowing the output language. Notice that the SolverEngine may
109 // spawn new SolverEngine "subsolvers" internally. These are created, used,
110 // and deleted in a modular fashion while not interleaving calls to the master
111 // SolverEngine. Thus the hack here does not break this use case. On the other
112 // hand, this hack breaks use cases where multiple SolverEngine objects are
113 // created by the user.
114 d_scope
.reset(new SolverEngineScope(this));
115 // listen to resource out
116 getResourceManager()->registerListener(d_routListener
.get());
118 d_stats
.reset(new SolverEngineStatistics());
119 // make the SMT solver
120 d_smtSolver
.reset(new SmtSolver(*d_env
, *d_state
, *d_absValues
, *d_stats
));
121 // make the SyGuS solver
122 d_sygusSolver
.reset(new SygusSolver(*d_env
.get(), *d_smtSolver
));
123 // make the quantifier elimination solver
124 d_quantElimSolver
.reset(new QuantElimSolver(*d_env
.get(), *d_smtSolver
));
127 bool SolverEngine::isFullyInited() const { return d_state
->isFullyInited(); }
128 bool SolverEngine::isQueryMade() const { return d_state
->isQueryMade(); }
129 size_t SolverEngine::getNumUserLevels() const
131 return d_state
->getNumUserLevels();
133 SmtMode
SolverEngine::getSmtMode() const { return d_state
->getMode(); }
134 bool SolverEngine::isSmtModeSat() const
136 SmtMode mode
= getSmtMode();
137 return mode
== SmtMode::SAT
|| mode
== SmtMode::SAT_UNKNOWN
;
139 Result
SolverEngine::getStatusOfLastCommand() const
141 return d_state
->getStatus();
143 context::UserContext
* SolverEngine::getUserContext()
145 return d_env
->getUserContext();
147 context::Context
* SolverEngine::getContext() { return d_env
->getContext(); }
149 TheoryEngine
* SolverEngine::getTheoryEngine()
151 return d_smtSolver
->getTheoryEngine();
154 prop::PropEngine
* SolverEngine::getPropEngine()
156 return d_smtSolver
->getPropEngine();
159 void SolverEngine::finishInit()
161 if (d_state
->isFullyInited())
163 // already initialized, return
167 // Notice that finishInitInternal is called when options are finalized. If we
168 // are parsing smt2, this occurs at the moment we enter "Assert mode", page 52
169 // of SMT-LIB 2.6 standard.
172 const LogicInfo
& logic
= getLogicInfo();
173 if (!logic
.isLocked())
178 // set the random seed
179 Random::getRandom().setSeed(d_env
->getOptions().driver
.seed
);
181 // Call finish init on the set defaults module. This inializes the logic
182 // and the best default options based on our heuristics.
183 SetDefaults
sdefaults(*d_env
, d_isInternalSubsolver
);
184 sdefaults
.setDefaults(d_env
->d_logic
, getOptions());
186 if (d_env
->getOptions().smt
.produceProofs
)
188 // ensure bound variable uses canonical bound variables
189 getNodeManager()->getBoundVarManager()->enableKeepCacheValues();
190 // make the proof manager
191 d_pfManager
.reset(new PfManager(*d_env
.get()));
192 PreprocessProofGenerator
* pppg
= d_pfManager
->getPreprocessProofGenerator();
193 // start the unsat core manager
194 d_ucManager
.reset(new UnsatCoreManager());
195 // enable it in the assertions pipeline
196 d_asserts
->enableProofs(pppg
);
197 // enabled proofs in the preprocessor
198 d_smtSolver
->getPreprocessor()->enableProofs(pppg
);
201 Trace("smt-debug") << "SolverEngine::finishInit" << std::endl
;
202 d_smtSolver
->finishInit();
204 // now can construct the SMT-level model object
205 TheoryEngine
* te
= d_smtSolver
->getTheoryEngine();
206 Assert(te
!= nullptr);
207 TheoryModel
* tm
= te
->getModel();
210 // make the check models utility
211 d_checkModels
.reset(new CheckModels(*d_env
.get()));
214 // global push/pop around everything, to ensure proper destruction
215 // of context-dependent data structures
219 if (d_env
->getOptions().smt
.produceAbducts
)
221 d_abductSolver
.reset(new AbductionSolver(*d_env
.get()));
223 if (d_env
->getOptions().smt
.produceInterpols
224 != options::ProduceInterpols::NONE
)
226 d_interpolSolver
.reset(new InterpolationSolver(*d_env
));
229 AlwaysAssert(getPropEngine()->getAssertionLevel() == 0)
230 << "The PropEngine has pushed but the SolverEngine "
231 "hasn't finished initializing!";
233 Assert(getLogicInfo().isLocked());
235 // store that we are finished initializing
236 d_state
->finishInit();
237 Trace("smt-debug") << "SolverEngine::finishInit done" << std::endl
;
240 void SolverEngine::shutdown()
246 SolverEngine::~SolverEngine()
248 SolverEngineScope
smts(this);
254 // global push/pop around everything, to ensure proper destruction
255 // of context-dependent data structures
258 // destroy all passes before destroying things that they refer to
259 d_smtSolver
->getPreprocessor()->cleanup();
261 d_pfManager
.reset(nullptr);
262 d_ucManager
.reset(nullptr);
264 d_absValues
.reset(nullptr);
265 d_asserts
.reset(nullptr);
267 d_abductSolver
.reset(nullptr);
268 d_interpolSolver
.reset(nullptr);
269 d_quantElimSolver
.reset(nullptr);
270 d_sygusSolver
.reset(nullptr);
271 d_smtSolver
.reset(nullptr);
273 d_stats
.reset(nullptr);
274 d_routListener
.reset(nullptr);
276 d_state
.reset(nullptr);
277 // destroy the environment
278 d_env
.reset(nullptr);
282 d_env
->warning() << "cvc5 threw an exception during cleanup." << std::endl
<< e
<< std::endl
;
286 void SolverEngine::setLogic(const LogicInfo
& logic
)
288 SolverEngineScope
smts(this);
289 if (d_state
->isFullyInited())
291 throw ModalException(
292 "Cannot set logic in SolverEngine after the engine has "
293 "finished initializing.");
295 d_env
->d_logic
= logic
;
300 void SolverEngine::setLogic(const std::string
& s
)
302 SolverEngineScope
smts(this);
305 setLogic(LogicInfo(s
));
307 catch (IllegalArgumentException
& e
)
309 throw LogicException(e
.what());
313 void SolverEngine::setLogic(const char* logic
) { setLogic(string(logic
)); }
315 const LogicInfo
& SolverEngine::getLogicInfo() const
317 return d_env
->getLogicInfo();
320 LogicInfo
SolverEngine::getUserLogicInfo() const
322 // Lock the logic to make sure that this logic can be queried. We create a
323 // copy of the user logic here to keep this method const.
324 LogicInfo res
= d_userLogic
;
329 void SolverEngine::setLogicInternal()
331 Assert(!d_state
->isFullyInited())
332 << "setting logic in SolverEngine but the engine has already"
333 " finished initializing for this run";
334 d_env
->d_logic
.lock();
338 void SolverEngine::setInfo(const std::string
& key
, const std::string
& value
)
340 SolverEngineScope
smts(this);
342 Trace("smt") << "SMT setInfo(" << key
<< ", " << value
<< ")" << endl
;
344 if (key
== "filename")
346 d_env
->d_options
.driver
.filename
= value
;
347 d_env
->d_originalOptions
->driver
.filename
= value
;
348 d_env
->getStatisticsRegistry().registerValue
<std::string
>(
349 "driver::filename", value
);
351 else if (key
== "smt-lib-version"
352 && !getOptions().base
.inputLanguageWasSetByUser
)
354 if (value
!= "2" && value
!= "2.6")
356 d_env
->warning() << "SMT-LIB version " << value
357 << " unsupported, defaulting to language (and semantics of) "
360 getOptions().base
.inputLanguage
= Language::LANG_SMTLIB_V2_6
;
361 // also update the output language
362 if (!getOptions().base
.outputLanguageWasSetByUser
)
364 setOption("output-language", "smtlib2.6");
365 getOptions().base
.outputLanguageWasSetByUser
= false;
368 else if (key
== "status")
370 d_state
->notifyExpectedStatus(value
);
374 bool SolverEngine::isValidGetInfoFlag(const std::string
& key
) const
376 if (key
== "all-statistics" || key
== "error-behavior" || key
== "filename"
377 || key
== "name" || key
== "version" || key
== "authors"
378 || key
== "status" || key
== "time" || key
== "reason-unknown"
379 || key
== "assertion-stack-levels" || key
== "all-options")
386 std::string
SolverEngine::getInfo(const std::string
& key
) const
388 SolverEngineScope
smts(this);
390 Trace("smt") << "SMT getInfo(" << key
<< ")" << endl
;
391 if (key
== "all-statistics")
393 return toSExpr(d_env
->getStatisticsRegistry().begin(),
394 d_env
->getStatisticsRegistry().end());
396 if (key
== "error-behavior")
398 return "immediate-exit";
400 if (key
== "filename")
402 return d_env
->getOptions().driver
.filename
;
406 return toSExpr(Configuration::getName());
408 if (key
== "version")
410 return toSExpr(Configuration::getVersionString());
412 if (key
== "authors")
414 return toSExpr("the " + Configuration::getName() + " authors");
418 // sat | unsat | unknown
419 Result status
= d_state
->getStatus();
420 switch (status
.getStatus())
422 case Result::SAT
: return "sat";
423 case Result::UNSAT
: return "unsat";
424 default: return "unknown";
429 return toSExpr(std::clock());
431 if (key
== "reason-unknown")
433 Result status
= d_state
->getStatus();
434 if (!status
.isNull() && status
.isUnknown())
436 std::stringstream ss
;
437 ss
<< status
.getUnknownExplanation();
438 std::string s
= ss
.str();
439 transform(s
.begin(), s
.end(), s
.begin(), ::tolower
);
444 throw RecoverableModalException(
445 "Can't get-info :reason-unknown when the "
446 "last result wasn't unknown!");
449 if (key
== "assertion-stack-levels")
451 size_t ulevel
= d_state
->getNumUserLevels();
452 AlwaysAssert(ulevel
<= std::numeric_limits
<unsigned long int>::max());
453 return toSExpr(ulevel
);
455 Assert(key
== "all-options");
456 // get the options, like all-statistics
457 std::vector
<std::vector
<std::string
>> res
;
458 for (const auto& opt
: options::getNames())
461 std::vector
<std::string
>{opt
, options::get(getOptions(), opt
)});
466 void SolverEngine::debugCheckFormals(const std::vector
<Node
>& formals
,
469 for (std::vector
<Node
>::const_iterator i
= formals
.begin();
473 if ((*i
).getKind() != kind::BOUND_VARIABLE
)
476 ss
<< "All formal arguments to defined functions must be "
477 "BOUND_VARIABLEs, but in the\n"
478 << "definition of function " << func
<< ", formal\n"
480 << "has kind " << (*i
).getKind();
481 throw TypeCheckingExceptionPrivate(func
, ss
.str());
486 void SolverEngine::debugCheckFunctionBody(Node formula
,
487 const std::vector
<Node
>& formals
,
490 TypeNode formulaType
= formula
.getType(d_env
->getOptions().expr
.typeChecking
);
491 TypeNode funcType
= func
.getType();
492 // We distinguish here between definitions of constants and functions,
493 // because the type checking for them is subtly different. Perhaps we
494 // should instead have SolverEngine::defineFunction() and
495 // SolverEngine::defineConstant() for better clarity, although then that
496 // doesn't match the SMT-LIBv2 standard...
497 if (formals
.size() > 0)
499 TypeNode rangeType
= funcType
.getRangeType();
500 if (!formulaType
.isComparableTo(rangeType
))
503 ss
<< "Type of defined function does not match its declaration\n"
504 << "The function : " << func
<< "\n"
505 << "Declared type : " << rangeType
<< "\n"
506 << "The body : " << formula
<< "\n"
507 << "Body type : " << formulaType
;
508 throw TypeCheckingExceptionPrivate(func
, ss
.str());
513 if (!formulaType
.isComparableTo(funcType
))
516 ss
<< "Declared type of defined constant does not match its definition\n"
517 << "The constant : " << func
<< "\n"
518 << "Declared type : " << funcType
<< "\n"
519 << "The definition : " << formula
<< "\n"
520 << "Definition type: " << formulaType
;
521 throw TypeCheckingExceptionPrivate(func
, ss
.str());
526 void SolverEngine::defineFunction(Node func
,
527 const std::vector
<Node
>& formals
,
531 SolverEngineScope
smts(this);
533 d_state
->doPendingPops();
534 Trace("smt") << "SMT defineFunction(" << func
<< ")" << endl
;
535 debugCheckFormals(formals
, func
);
538 debugCheckFunctionBody(formula
, formals
, func
);
540 // Substitute out any abstract values in formula
541 Node def
= d_absValues
->substituteAbstractValues(formula
);
542 if (!formals
.empty())
544 NodeManager
* nm
= NodeManager::currentNM();
546 kind::LAMBDA
, nm
->mkNode(kind::BOUND_VAR_LIST
, formals
), def
);
548 // A define-fun is treated as a (higher-order) assertion. It is provided
549 // to the assertions object. It will be added as a top-level substitution
550 // within this class, possibly multiple times if global is true.
551 Node feq
= func
.eqNode(def
);
552 d_asserts
->addDefineFunDefinition(feq
, global
);
555 void SolverEngine::defineFunctionsRec(
556 const std::vector
<Node
>& funcs
,
557 const std::vector
<std::vector
<Node
>>& formals
,
558 const std::vector
<Node
>& formulas
,
561 SolverEngineScope
smts(this);
563 d_state
->doPendingPops();
564 Trace("smt") << "SMT defineFunctionsRec(...)" << endl
;
566 if (funcs
.size() != formals
.size() && funcs
.size() != formulas
.size())
569 ss
<< "Number of functions, formals, and function bodies passed to "
570 "defineFunctionsRec do not match:"
572 << " #functions : " << funcs
.size() << "\n"
573 << " #arg lists : " << formals
.size() << "\n"
574 << " #function bodies : " << formulas
.size() << "\n";
575 throw ModalException(ss
.str());
577 for (unsigned i
= 0, size
= funcs
.size(); i
< size
; i
++)
579 // check formal argument list
580 debugCheckFormals(formals
[i
], funcs
[i
]);
582 debugCheckFunctionBody(formulas
[i
], formals
[i
], funcs
[i
]);
585 NodeManager
* nm
= getNodeManager();
586 for (unsigned i
= 0, size
= funcs
.size(); i
< size
; i
++)
588 // we assert a quantified formula
590 // make the function application
591 if (formals
[i
].empty())
593 // it has no arguments
598 std::vector
<Node
> children
;
599 children
.push_back(funcs
[i
]);
600 children
.insert(children
.end(), formals
[i
].begin(), formals
[i
].end());
601 func_app
= nm
->mkNode(kind::APPLY_UF
, children
);
603 Node lem
= nm
->mkNode(kind::EQUAL
, func_app
, formulas
[i
]);
604 if (!formals
[i
].empty())
606 // set the attribute to denote this is a function definition
607 Node aexpr
= nm
->mkNode(kind::INST_ATTRIBUTE
, func_app
);
608 aexpr
= nm
->mkNode(kind::INST_PATTERN_LIST
, aexpr
);
610 func_app
.setAttribute(fda
, true);
611 // make the quantified formula
612 Node boundVars
= nm
->mkNode(kind::BOUND_VAR_LIST
, formals
[i
]);
613 lem
= nm
->mkNode(kind::FORALL
, boundVars
, lem
, aexpr
);
615 // Assert the quantified formula. Notice we don't call assertFormula
616 // directly, since we should call a private member method since we have
617 // already ensuring this SolverEngine is initialized above.
618 // add define recursive definition to the assertions
619 d_asserts
->addDefineFunDefinition(lem
, global
);
623 void SolverEngine::defineFunctionRec(Node func
,
624 const std::vector
<Node
>& formals
,
628 std::vector
<Node
> funcs
;
629 funcs
.push_back(func
);
630 std::vector
<std::vector
<Node
>> formals_multi
;
631 formals_multi
.push_back(formals
);
632 std::vector
<Node
> formulas
;
633 formulas
.push_back(formula
);
634 defineFunctionsRec(funcs
, formals_multi
, formulas
, global
);
637 TheoryModel
* SolverEngine::getAvailableModel(const char* c
) const
639 if (!d_env
->getOptions().theory
.assignFunctionValues
)
641 std::stringstream ss
;
642 ss
<< "Cannot " << c
<< " when --assign-function-values is false.";
643 throw RecoverableModalException(ss
.str().c_str());
646 if (d_state
->getMode() != SmtMode::SAT
647 && d_state
->getMode() != SmtMode::SAT_UNKNOWN
)
649 std::stringstream ss
;
651 << " unless immediately preceded by SAT/NOT_ENTAILED or UNKNOWN "
653 throw RecoverableModalException(ss
.str().c_str());
656 if (!d_env
->getOptions().smt
.produceModels
)
658 std::stringstream ss
;
659 ss
<< "Cannot " << c
<< " when produce-models options is off.";
660 throw ModalException(ss
.str().c_str());
663 TheoryEngine
* te
= d_smtSolver
->getTheoryEngine();
664 Assert(te
!= nullptr);
665 TheoryModel
* m
= te
->getBuiltModel();
669 std::stringstream ss
;
671 << " since model is not available. Perhaps the most recent call to "
672 "check-sat was interrupted?";
673 throw RecoverableModalException(ss
.str().c_str());
679 QuantifiersEngine
* SolverEngine::getAvailableQuantifiersEngine(
682 QuantifiersEngine
* qe
= d_smtSolver
->getQuantifiersEngine();
685 std::stringstream ss
;
686 ss
<< "Cannot " << c
<< " when quantifiers are not present.";
687 throw ModalException(ss
.str().c_str());
692 void SolverEngine::notifyPushPre()
694 d_smtSolver
->processAssertions(*d_asserts
);
697 void SolverEngine::notifyPushPost()
699 TimerStat::CodeTimer
pushPopTimer(d_stats
->d_pushPopTime
);
700 Assert(getPropEngine() != nullptr);
701 getPropEngine()->push();
704 void SolverEngine::notifyPopPre()
706 TimerStat::CodeTimer
pushPopTimer(d_stats
->d_pushPopTime
);
707 PropEngine
* pe
= getPropEngine();
708 Assert(pe
!= nullptr);
712 void SolverEngine::notifyPostSolvePre()
714 PropEngine
* pe
= getPropEngine();
715 Assert(pe
!= nullptr);
719 void SolverEngine::notifyPostSolvePost()
721 TheoryEngine
* te
= getTheoryEngine();
722 Assert(te
!= nullptr);
726 Result
SolverEngine::checkSat()
729 return checkSat(nullNode
);
732 Result
SolverEngine::checkSat(const Node
& assumption
)
734 ensureWellFormedTerm(assumption
, "checkSat");
735 std::vector
<Node
> assump
;
736 if (!assumption
.isNull())
738 assump
.push_back(assumption
);
740 return checkSatInternal(assump
);
743 Result
SolverEngine::checkSat(const std::vector
<Node
>& assumptions
)
745 ensureWellFormedTerms(assumptions
, "checkSat");
746 return checkSatInternal(assumptions
);
749 Result
SolverEngine::checkSatInternal(const std::vector
<Node
>& assumptions
)
753 SolverEngineScope
smts(this);
756 Trace("smt") << "SolverEngine::checkSat(" << assumptions
<< ")" << endl
;
757 // check the satisfiability with the solver object
758 r
= d_smtSolver
->checkSatisfiability(*d_asserts
.get(), assumptions
);
760 Trace("smt") << "SolverEngine::checkSat(" << assumptions
<< ") => " << r
763 // Check that SAT results generate a model correctly.
764 if (d_env
->getOptions().smt
.checkModels
)
766 if (r
.getStatus() == Result::SAT
)
771 // Check that UNSAT results generate a proof correctly.
772 if (d_env
->getOptions().smt
.checkProofs
)
774 if (r
.getStatus() == Result::UNSAT
)
779 // Check that UNSAT results generate an unsat core correctly.
780 if (d_env
->getOptions().smt
.checkUnsatCores
)
782 if (r
.getStatus() == Result::UNSAT
)
784 TimerStat::CodeTimer
checkUnsatCoreTimer(d_stats
->d_checkUnsatCoreTime
);
789 if (d_env
->getOptions().base
.statisticsEveryQuery
)
791 printStatisticsDiff();
796 std::vector
<Node
> SolverEngine::getUnsatAssumptions(void)
798 Trace("smt") << "SMT getUnsatAssumptions()" << endl
;
799 SolverEngineScope
smts(this);
800 if (!d_env
->getOptions().smt
.unsatAssumptions
)
802 throw ModalException(
803 "Cannot get unsat assumptions when produce-unsat-assumptions option "
806 if (d_state
->getMode() != SmtMode::UNSAT
)
808 throw RecoverableModalException(
809 "Cannot get unsat assumptions unless immediately preceded by "
813 UnsatCore core
= getUnsatCoreInternal();
814 std::vector
<Node
> res
;
815 std::vector
<Node
>& assumps
= d_asserts
->getAssumptions();
816 for (const Node
& e
: assumps
)
818 if (std::find(core
.begin(), core
.end(), e
) != core
.end())
826 void SolverEngine::assertFormula(const Node
& formula
)
828 SolverEngineScope
smts(this);
830 d_state
->doPendingPops();
831 ensureWellFormedTerm(formula
, "assertFormula");
832 assertFormulaInternal(formula
);
835 void SolverEngine::assertFormulaInternal(const Node
& formula
)
837 // as an optimization we do not check whether formula is well-formed here, and
838 // defer this check for certain cases within the assertions module.
839 Trace("smt") << "SolverEngine::assertFormula(" << formula
<< ")" << endl
;
841 // Substitute out any abstract values in ex
842 Node n
= d_absValues
->substituteAbstractValues(formula
);
844 d_asserts
->assertFormula(n
);
848 --------------------------------------------------------------------------
849 Handling SyGuS commands
850 --------------------------------------------------------------------------
853 void SolverEngine::declareSygusVar(Node var
)
855 SolverEngineScope
smts(this);
856 d_sygusSolver
->declareSygusVar(var
);
859 void SolverEngine::declareSynthFun(Node func
,
862 const std::vector
<Node
>& vars
)
864 SolverEngineScope
smts(this);
866 d_state
->doPendingPops();
867 d_sygusSolver
->declareSynthFun(func
, sygusType
, isInv
, vars
);
869 void SolverEngine::declareSynthFun(Node func
,
871 const std::vector
<Node
>& vars
)
873 // use a null sygus type
875 declareSynthFun(func
, sygusType
, isInv
, vars
);
878 void SolverEngine::assertSygusConstraint(Node n
, bool isAssume
)
880 SolverEngineScope
smts(this);
882 d_sygusSolver
->assertSygusConstraint(n
, isAssume
);
885 void SolverEngine::assertSygusInvConstraint(Node inv
,
890 SolverEngineScope
smts(this);
892 d_sygusSolver
->assertSygusInvConstraint(inv
, pre
, trans
, post
);
895 Result
SolverEngine::checkSynth(bool isNext
)
897 SolverEngineScope
smts(this);
899 if (isNext
&& d_state
->getMode() != SmtMode::SYNTH
)
901 throw RecoverableModalException(
902 "Cannot check-synth-next unless immediately preceded by a successful "
903 "call to check-synth(-next).");
905 Result r
= d_sygusSolver
->checkSynth(*d_asserts
, isNext
);
906 d_state
->notifyCheckSynthResult(r
);
911 --------------------------------------------------------------------------
912 End of Handling SyGuS commands
913 --------------------------------------------------------------------------
916 void SolverEngine::declarePool(const Node
& p
,
917 const std::vector
<Node
>& initValue
)
919 Assert(p
.isVar() && p
.getType().isSet());
921 QuantifiersEngine
* qe
= getAvailableQuantifiersEngine("declareTermPool");
922 qe
->declarePool(p
, initValue
);
925 Node
SolverEngine::simplify(const Node
& ex
)
927 SolverEngineScope
smts(this);
929 d_state
->doPendingPops();
930 // ensure we've processed assertions
931 d_smtSolver
->processAssertions(*d_asserts
);
932 return d_smtSolver
->getPreprocessor()->simplify(ex
);
935 Node
SolverEngine::expandDefinitions(const Node
& ex
)
937 getResourceManager()->spendResource(Resource::PreprocessStep
);
938 SolverEngineScope
smts(this);
940 d_state
->doPendingPops();
941 return d_smtSolver
->getPreprocessor()->expandDefinitions(ex
);
944 // TODO(#1108): Simplify the error reporting of this method.
945 Node
SolverEngine::getValue(const Node
& ex
) const
947 SolverEngineScope
smts(this);
949 ensureWellFormedTerm(ex
, "get value");
950 Trace("smt") << "SMT getValue(" << ex
<< ")" << endl
;
951 TypeNode expectedType
= ex
.getType();
953 // Substitute out any abstract values in ex and expand
954 Node n
= d_smtSolver
->getPreprocessor()->expandDefinitions(ex
);
956 Trace("smt") << "--- getting value of " << n
<< endl
;
957 // There are two ways model values for terms are computed (for historical
958 // reasons). One way is that used in check-model; the other is that
959 // used by the Model classes. It's not clear to me exactly how these
960 // two are different, but they need to be unified. This ugly hack here
961 // is to fix bug 554 until we can revamp boolean-terms and models [MGD]
964 if (!n
.getType().isFunction())
966 n
= d_env
->getRewriter()->rewrite(n
);
969 Trace("smt") << "--- getting value of " << n
<< endl
;
970 TheoryModel
* m
= getAvailableModel("get-value");
971 Assert(m
!= nullptr);
972 Node resultNode
= m
->getValue(n
);
973 Trace("smt") << "--- got value " << n
<< " = " << resultNode
<< endl
;
974 Trace("smt") << "--- type " << resultNode
.getType() << endl
;
975 Trace("smt") << "--- expected type " << expectedType
<< endl
;
977 // type-check the result we got
978 // Notice that lambdas have function type, which does not respect the subtype
979 // relation, so we ignore them here.
980 Assert(resultNode
.isNull() || resultNode
.getKind() == kind::LAMBDA
981 || resultNode
.getType().isSubtypeOf(expectedType
))
982 << "Run with -t smt for details.";
984 // Ensure it's a value (constant or const-ish like real algebraic
985 // numbers), or a lambda (for uninterpreted functions). This assertion only
986 // holds for models that do not have approximate values.
987 if (!m
->isValue(resultNode
))
989 d_env
->warning() << "Could not evaluate " << resultNode
990 << " in getValue." << std::endl
;
993 if (d_env
->getOptions().smt
.abstractValues
&& resultNode
.getType().isArray())
995 resultNode
= d_absValues
->mkAbstractValue(resultNode
);
996 Trace("smt") << "--- abstract value >> " << resultNode
<< endl
;
1002 std::vector
<Node
> SolverEngine::getValues(const std::vector
<Node
>& exprs
) const
1004 std::vector
<Node
> result
;
1005 for (const Node
& e
: exprs
)
1007 result
.push_back(getValue(e
));
1012 std::vector
<Node
> SolverEngine::getModelDomainElements(TypeNode tn
) const
1014 Assert(tn
.isSort());
1015 TheoryModel
* m
= getAvailableModel("getModelDomainElements");
1016 return m
->getDomainElements(tn
);
1019 bool SolverEngine::isModelCoreSymbol(Node n
)
1021 SolverEngineScope
smts(this);
1023 const Options
& opts
= d_env
->getOptions();
1024 if (opts
.smt
.modelCoresMode
== options::ModelCoresMode::NONE
)
1026 // if the model core mode is none, we are always a model core symbol
1029 TheoryModel
* tm
= getAvailableModel("isModelCoreSymbol");
1030 // compute the model core if not done so already
1031 if (!tm
->isUsingModelCore())
1033 // If we enabled model cores, we compute a model core for m based on our
1034 // (expanded) assertions using the model core builder utility. Notice that
1035 // we get the assertions using the getAssertionsInternal, which does not
1036 // impact whether we are in "sat" mode
1037 std::vector
<Node
> asserts
= getAssertionsInternal();
1038 d_smtSolver
->getPreprocessor()->expandDefinitions(asserts
);
1039 ModelCoreBuilder
mcb(*d_env
.get());
1040 mcb
.setModelCore(asserts
, tm
, opts
.smt
.modelCoresMode
);
1042 return tm
->isModelCoreSymbol(n
);
1045 std::string
SolverEngine::getModel(const std::vector
<TypeNode
>& declaredSorts
,
1046 const std::vector
<Node
>& declaredFuns
)
1048 SolverEngineScope
smts(this);
1049 // !!! Note that all methods called here should have a version at the API
1050 // level. This is to ensure that the information associated with a model is
1051 // completely accessible by the user. This is currently not rigorously
1052 // enforced. An alternative design would be to have this method implemented
1053 // at the API level, but this makes exceptions in the text interface less
1055 TheoryModel
* tm
= getAvailableModel("get model");
1056 // use the smt::Model model utility for printing
1057 const Options
& opts
= d_env
->getOptions();
1058 bool isKnownSat
= (d_state
->getMode() == SmtMode::SAT
);
1059 Model
m(isKnownSat
, opts
.driver
.filename
);
1060 // set the model declarations, which determines what is printed in the model
1061 for (const TypeNode
& tn
: declaredSorts
)
1063 m
.addDeclarationSort(tn
, getModelDomainElements(tn
));
1065 bool usingModelCores
=
1066 (opts
.smt
.modelCoresMode
!= options::ModelCoresMode::NONE
);
1067 for (const Node
& n
: declaredFuns
)
1069 if (usingModelCores
&& !tm
->isModelCoreSymbol(n
))
1071 // skip if not in model core
1074 Node value
= tm
->getValue(n
);
1075 m
.addDeclarationTerm(n
, value
);
1077 // for separation logic
1078 TypeNode locT
, dataT
;
1079 if (getSepHeapTypes(locT
, dataT
))
1081 std::pair
<Node
, Node
> sh
= getSepHeapAndNilExpr();
1082 m
.setHeapModel(sh
.first
, sh
.second
);
1085 std::stringstream ssm
;
1090 void SolverEngine::blockModel()
1092 Trace("smt") << "SMT blockModel()" << endl
;
1093 SolverEngineScope
smts(this);
1097 TheoryModel
* m
= getAvailableModel("block model");
1099 if (d_env
->getOptions().smt
.blockModelsMode
== options::BlockModelsMode::NONE
)
1101 std::stringstream ss
;
1102 ss
<< "Cannot block model when block-models is set to none.";
1103 throw RecoverableModalException(ss
.str().c_str());
1106 // get expanded assertions
1107 std::vector
<Node
> eassertsProc
= getExpandedAssertions();
1108 ModelBlocker
mb(*d_env
.get());
1109 Node eblocker
= mb
.getModelBlocker(
1110 eassertsProc
, m
, d_env
->getOptions().smt
.blockModelsMode
);
1111 Trace("smt") << "Block formula: " << eblocker
<< std::endl
;
1112 assertFormulaInternal(eblocker
);
1115 void SolverEngine::blockModelValues(const std::vector
<Node
>& exprs
)
1117 Trace("smt") << "SMT blockModelValues()" << endl
;
1118 SolverEngineScope
smts(this);
1122 for (const Node
& e
: exprs
)
1124 ensureWellFormedTerm(e
, "block model values");
1127 TheoryModel
* m
= getAvailableModel("block model values");
1129 // get expanded assertions
1130 std::vector
<Node
> eassertsProc
= getExpandedAssertions();
1131 // we always do block model values mode here
1132 ModelBlocker
mb(*d_env
.get());
1133 Node eblocker
= mb
.getModelBlocker(
1134 eassertsProc
, m
, options::BlockModelsMode::VALUES
, exprs
);
1135 assertFormulaInternal(eblocker
);
1138 std::pair
<Node
, Node
> SolverEngine::getSepHeapAndNilExpr(void)
1140 if (!getLogicInfo().isTheoryEnabled(THEORY_SEP
))
1143 "Cannot obtain separation logic expressions if not using the "
1144 "separation logic theory.";
1145 throw RecoverableModalException(msg
);
1149 TheoryModel
* tm
= getAvailableModel("get separation logic heap and nil");
1150 if (!tm
->getHeapModel(heap
, nil
))
1153 "Failed to obtain heap/nil "
1154 "expressions from theory model.";
1155 throw RecoverableModalException(msg
);
1157 return std::make_pair(heap
, nil
);
1160 std::vector
<Node
> SolverEngine::getAssertionsInternal()
1162 Assert(d_state
->isFullyInited());
1163 const context::CDList
<Node
>& al
= d_asserts
->getAssertionList();
1164 std::vector
<Node
> res
;
1165 for (const Node
& n
: al
)
1167 res
.emplace_back(n
);
1172 const Options
& SolverEngine::options() const { return d_env
->getOptions(); }
1174 void SolverEngine::ensureWellFormedTerm(const Node
& n
,
1175 const std::string
& src
) const
1177 if (Configuration::isAssertionBuild())
1179 bool wasShadow
= false;
1180 if (expr::hasFreeOrShadowedVar(n
, wasShadow
))
1182 std::string
varType(wasShadow
? "shadowed" : "free");
1183 std::stringstream se
;
1184 se
<< "Cannot process term with " << varType
<< " variable in " << src
1186 throw ModalException(se
.str().c_str());
1191 void SolverEngine::ensureWellFormedTerms(const std::vector
<Node
>& ns
,
1192 const std::string
& src
) const
1194 if (Configuration::isAssertionBuild())
1196 for (const Node
& n
: ns
)
1198 ensureWellFormedTerm(n
, src
);
1203 std::vector
<Node
> SolverEngine::getExpandedAssertions()
1205 std::vector
<Node
> easserts
= getAssertions();
1206 // must expand definitions
1207 d_smtSolver
->getPreprocessor()->expandDefinitions(easserts
);
1210 Env
& SolverEngine::getEnv() { return *d_env
.get(); }
1212 void SolverEngine::declareSepHeap(TypeNode locT
, TypeNode dataT
)
1214 if (!getLogicInfo().isTheoryEnabled(THEORY_SEP
))
1217 "Cannot declare heap if not using the separation logic theory.";
1218 throw RecoverableModalException(msg
);
1220 SolverEngineScope
smts(this);
1222 // check whether incremental is enabled, where separation logic is not
1224 if (d_env
->getOptions().base
.incrementalSolving
)
1226 throw RecoverableModalException(
1227 "Separation logic not supported in incremental mode");
1229 TheoryEngine
* te
= getTheoryEngine();
1230 te
->declareSepHeap(locT
, dataT
);
1233 bool SolverEngine::getSepHeapTypes(TypeNode
& locT
, TypeNode
& dataT
)
1235 SolverEngineScope
smts(this);
1237 TheoryEngine
* te
= getTheoryEngine();
1238 return te
->getSepHeapTypes(locT
, dataT
);
1241 Node
SolverEngine::getSepHeapExpr() { return getSepHeapAndNilExpr().first
; }
1243 Node
SolverEngine::getSepNilExpr() { return getSepHeapAndNilExpr().second
; }
1245 std::vector
<Node
> SolverEngine::getLearnedLiterals()
1247 Trace("smt") << "SMT getLearnedLiterals()" << std::endl
;
1248 SolverEngineScope
smts(this);
1249 // note that the default mode for learned literals is via the prop engine,
1250 // although other modes could use the preprocessor
1251 PropEngine
* pe
= getPropEngine();
1252 Assert(pe
!= nullptr);
1253 return pe
->getLearnedZeroLevelLiterals();
1256 void SolverEngine::checkProof()
1258 Assert(d_env
->getOptions().smt
.produceProofs
);
1259 // internal check the proof
1260 PropEngine
* pe
= getPropEngine();
1261 Assert(pe
!= nullptr);
1262 if (d_env
->getOptions().proof
.proofCheck
== options::ProofCheckMode::EAGER
)
1264 pe
->checkProof(d_asserts
->getAssertionList());
1266 Assert(pe
->getProof() != nullptr);
1267 std::shared_ptr
<ProofNode
> pePfn
= pe
->getProof();
1268 if (d_env
->getOptions().smt
.checkProofs
)
1270 d_pfManager
->checkProof(pePfn
, *d_asserts
);
1274 StatisticsRegistry
& SolverEngine::getStatisticsRegistry()
1276 return d_env
->getStatisticsRegistry();
1279 UnsatCore
SolverEngine::getUnsatCoreInternal()
1281 if (!d_env
->getOptions().smt
.unsatCores
)
1283 throw ModalException(
1284 "Cannot get an unsat core when produce-unsat-cores or produce-proofs "
1287 if (d_state
->getMode() != SmtMode::UNSAT
)
1289 throw RecoverableModalException(
1290 "Cannot get an unsat core unless immediately preceded by "
1291 "UNSAT/ENTAILED response.");
1293 // generate with new proofs
1294 PropEngine
* pe
= getPropEngine();
1295 Assert(pe
!= nullptr);
1297 std::shared_ptr
<ProofNode
> pepf
;
1298 if (options().smt
.unsatCoresMode
== options::UnsatCoresMode::ASSUMPTIONS
)
1300 pepf
= pe
->getRefutation();
1304 pepf
= pe
->getProof();
1306 Assert(pepf
!= nullptr);
1307 std::shared_ptr
<ProofNode
> pfn
= d_pfManager
->getFinalProof(pepf
, *d_asserts
);
1308 std::vector
<Node
> core
;
1309 d_ucManager
->getUnsatCore(pfn
, *d_asserts
, core
);
1310 if (options().smt
.minimalUnsatCores
)
1312 core
= reduceUnsatCore(core
);
1314 return UnsatCore(core
);
1317 std::vector
<Node
> SolverEngine::reduceUnsatCore(const std::vector
<Node
>& core
)
1319 Assert(options().smt
.unsatCores
)
1320 << "cannot reduce unsat core if unsat cores are turned off";
1322 d_env
->verbose(1) << "SolverEngine::reduceUnsatCore(): reducing unsat core"
1324 std::unordered_set
<Node
> removed
;
1325 for (const Node
& skip
: core
)
1327 std::unique_ptr
<SolverEngine
> coreChecker
;
1328 initializeSubsolver(coreChecker
, *d_env
.get());
1329 coreChecker
->setLogic(getLogicInfo());
1330 coreChecker
->getOptions().smt
.checkUnsatCores
= false;
1331 // disable all proof options
1332 coreChecker
->getOptions().smt
.produceProofs
= false;
1333 coreChecker
->getOptions().smt
.checkProofs
= false;
1335 for (const Node
& ucAssertion
: core
)
1337 if (ucAssertion
!= skip
&& removed
.find(ucAssertion
) == removed
.end())
1339 Node assertionAfterExpansion
= expandDefinitions(ucAssertion
);
1340 coreChecker
->assertFormula(assertionAfterExpansion
);
1346 r
= coreChecker
->checkSat();
1353 if (r
.getStatus() == Result::UNSAT
)
1355 removed
.insert(skip
);
1357 else if (r
.isUnknown())
1360 << "SolverEngine::reduceUnsatCore(): could not reduce unsat core "
1366 if (removed
.empty())
1372 std::vector
<Node
> newUcAssertions
;
1373 for (const Node
& n
: core
)
1375 if (removed
.find(n
) == removed
.end())
1377 newUcAssertions
.push_back(n
);
1381 return newUcAssertions
;
1385 void SolverEngine::checkUnsatCore()
1387 Assert(d_env
->getOptions().smt
.unsatCores
)
1388 << "cannot check unsat core if unsat cores are turned off";
1390 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): generating unsat core"
1392 UnsatCore core
= getUnsatCore();
1394 // initialize the core checker
1395 std::unique_ptr
<SolverEngine
> coreChecker
;
1396 initializeSubsolver(coreChecker
, *d_env
.get());
1397 coreChecker
->getOptions().smt
.checkUnsatCores
= false;
1398 // disable all proof options
1399 coreChecker
->getOptions().smt
.produceProofs
= false;
1400 coreChecker
->getOptions().smt
.checkProofs
= false;
1402 // set up separation logic heap if necessary
1403 TypeNode sepLocType
, sepDataType
;
1404 if (getSepHeapTypes(sepLocType
, sepDataType
))
1406 coreChecker
->declareSepHeap(sepLocType
, sepDataType
);
1409 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): pushing core assertions"
1411 theory::TrustSubstitutionMap
& tls
= d_env
->getTopLevelSubstitutions();
1412 for (UnsatCore::iterator i
= core
.begin(); i
!= core
.end(); ++i
)
1414 Node assertionAfterExpansion
= tls
.apply(*i
);
1415 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): pushing core member "
1416 << *i
<< ", expanded to " << assertionAfterExpansion
1418 coreChecker
->assertFormula(assertionAfterExpansion
);
1423 r
= coreChecker
->checkSat();
1429 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): result is " << r
1433 d_env
->warning() << "SolverEngine::checkUnsatCore(): could not check core result "
1437 else if (r
.getStatus() == Result::SAT
)
1440 << "SolverEngine::checkUnsatCore(): produced core was satisfiable.";
1444 void SolverEngine::checkModel(bool hardFailure
)
1446 const context::CDList
<Node
>& al
= d_asserts
->getAssertionList();
1447 // we always enable the assertion list, so it is able to be checked
1449 TimerStat::CodeTimer
checkModelTimer(d_stats
->d_checkModelTime
);
1451 d_env
->verbose(1) << "SolverEngine::checkModel(): generating model"
1453 TheoryModel
* m
= getAvailableModel("check model");
1454 Assert(m
!= nullptr);
1456 // check the model with the theory engine for debugging
1457 if (options().smt
.debugCheckModels
)
1459 TheoryEngine
* te
= getTheoryEngine();
1460 Assert(te
!= nullptr);
1461 te
->checkTheoryAssertionsWithModel(hardFailure
);
1464 // check the model with the check models utility
1465 Assert(d_checkModels
!= nullptr);
1466 d_checkModels
->checkModel(m
, al
, hardFailure
);
1469 UnsatCore
SolverEngine::getUnsatCore()
1471 Trace("smt") << "SMT getUnsatCore()" << std::endl
;
1472 SolverEngineScope
smts(this);
1474 return getUnsatCoreInternal();
1477 void SolverEngine::getRelevantInstantiationTermVectors(
1478 std::map
<Node
, InstantiationList
>& insts
, bool getDebugInfo
)
1480 Assert(d_state
->getMode() == SmtMode::UNSAT
);
1481 // generate with new proofs
1482 PropEngine
* pe
= getPropEngine();
1483 Assert(pe
!= nullptr);
1484 Assert(pe
->getProof() != nullptr);
1485 std::shared_ptr
<ProofNode
> pfn
=
1486 d_pfManager
->getFinalProof(pe
->getProof(), *d_asserts
);
1487 d_ucManager
->getRelevantInstantiations(pfn
, insts
, getDebugInfo
);
1490 std::string
SolverEngine::getProof()
1492 Trace("smt") << "SMT getProof()\n";
1493 SolverEngineScope
smts(this);
1495 if (!d_env
->getOptions().smt
.produceProofs
)
1497 throw ModalException("Cannot get a proof when proof option is off.");
1499 if (d_state
->getMode() != SmtMode::UNSAT
)
1501 throw RecoverableModalException(
1502 "Cannot get a proof unless immediately preceded by "
1503 "UNSAT/ENTAILED response.");
1505 // the prop engine has the proof of false
1506 PropEngine
* pe
= getPropEngine();
1507 Assert(pe
!= nullptr);
1508 Assert(pe
->getProof() != nullptr);
1509 Assert(d_pfManager
);
1510 std::ostringstream ss
;
1511 d_pfManager
->printProof(ss
, pe
->getProof(), *d_asserts
);
1515 void SolverEngine::printInstantiations(std::ostream
& out
)
1517 SolverEngineScope
smts(this);
1519 QuantifiersEngine
* qe
= getAvailableQuantifiersEngine("printInstantiations");
1521 // First, extract and print the skolemizations
1522 bool printed
= false;
1523 bool reqNames
= !d_env
->getOptions().printer
.printInstFull
;
1524 // only print when in list mode
1525 if (d_env
->getOptions().printer
.printInstMode
== options::PrintInstMode::LIST
)
1527 std::map
<Node
, std::vector
<Node
>> sks
;
1528 qe
->getSkolemTermVectors(sks
);
1529 for (const std::pair
<const Node
, std::vector
<Node
>>& s
: sks
)
1532 if (!qe
->getNameForQuant(s
.first
, name
, reqNames
))
1534 // did not have a name and we are only printing formulas with names
1537 SkolemList
slist(name
, s
.second
);
1543 // Second, extract and print the instantiations
1544 std::map
<Node
, InstantiationList
> rinsts
;
1545 if ((d_env
->getOptions().smt
.produceProofs
1546 && d_env
->getOptions().smt
.proofMode
== options::ProofMode::FULL
)
1547 && getSmtMode() == SmtMode::UNSAT
)
1549 // minimize instantiations based on proof manager
1550 getRelevantInstantiationTermVectors(
1551 rinsts
, options().driver
.dumpInstantiationsDebug
);
1555 std::map
<Node
, std::vector
<std::vector
<Node
>>> insts
;
1556 getInstantiationTermVectors(insts
);
1557 for (const std::pair
<const Node
, std::vector
<std::vector
<Node
>>>& i
: insts
)
1559 // convert to instantiation list
1561 InstantiationList
& ilq
= rinsts
[q
];
1563 for (const std::vector
<Node
>& ii
: i
.second
)
1565 ilq
.d_inst
.push_back(InstantiationVec(ii
));
1569 for (std::pair
<const Node
, InstantiationList
>& i
: rinsts
)
1571 if (i
.second
.d_inst
.empty())
1573 // no instantiations, skip
1577 if (!qe
->getNameForQuant(i
.first
, name
, reqNames
))
1579 // did not have a name and we are only printing formulas with names
1583 if (d_env
->getOptions().printer
.printInstMode
1584 == options::PrintInstMode::NUM
)
1586 out
<< "(num-instantiations " << name
<< " " << i
.second
.d_inst
.size()
1587 << ")" << std::endl
;
1592 i
.second
.d_quant
= name
;
1593 Assert(d_env
->getOptions().printer
.printInstMode
1594 == options::PrintInstMode::LIST
);
1599 // if we did not print anything, we indicate this
1602 out
<< "none" << std::endl
;
1606 void SolverEngine::getInstantiationTermVectors(
1607 std::map
<Node
, std::vector
<std::vector
<Node
>>>& insts
)
1609 SolverEngineScope
smts(this);
1611 QuantifiersEngine
* qe
=
1612 getAvailableQuantifiersEngine("getInstantiationTermVectors");
1613 // get the list of all instantiations
1614 qe
->getInstantiationTermVectors(insts
);
1617 bool SolverEngine::getSynthSolutions(std::map
<Node
, Node
>& solMap
)
1619 SolverEngineScope
smts(this);
1621 return d_sygusSolver
->getSynthSolutions(solMap
);
1624 bool SolverEngine::getSubsolverSynthSolutions(std::map
<Node
, Node
>& solMap
)
1626 SolverEngineScope
smts(this);
1628 return d_sygusSolver
->getSubsolverSynthSolutions(solMap
);
1631 Node
SolverEngine::getQuantifierElimination(Node q
, bool doFull
)
1633 SolverEngineScope
smts(this);
1635 return d_quantElimSolver
->getQuantifierElimination(
1636 *d_asserts
, q
, doFull
, d_isInternalSubsolver
);
1639 Node
SolverEngine::getInterpolant(const Node
& conj
, const TypeNode
& grammarType
)
1641 SolverEngineScope
smts(this);
1643 std::vector
<Node
> axioms
= getExpandedAssertions();
1646 d_interpolSolver
->getInterpolant(axioms
, conj
, grammarType
, interpol
);
1647 // notify the state of whether the get-interpol call was successfuly, which
1648 // impacts the SMT mode.
1649 d_state
->notifyGetInterpol(success
);
1650 Assert(success
== !interpol
.isNull());
1654 Node
SolverEngine::getInterpolantNext()
1656 SolverEngineScope
smts(this);
1658 if (d_state
->getMode() != SmtMode::INTERPOL
)
1660 throw RecoverableModalException(
1661 "Cannot get-interpol-next unless immediately preceded by a successful "
1662 "call to get-interpol(-next).");
1665 bool success
= d_interpolSolver
->getInterpolantNext(interpol
);
1666 // notify the state of whether the get-interpolant-next call was successful
1667 d_state
->notifyGetInterpol(success
);
1668 Assert(success
== !interpol
.isNull());
1672 Node
SolverEngine::getAbduct(const Node
& conj
, const TypeNode
& grammarType
)
1674 SolverEngineScope
smts(this);
1676 std::vector
<Node
> axioms
= getExpandedAssertions();
1678 bool success
= d_abductSolver
->getAbduct(axioms
, conj
, grammarType
, abd
);
1679 // notify the state of whether the get-abduct call was successful, which
1680 // impacts the SMT mode.
1681 d_state
->notifyGetAbduct(success
);
1682 Assert(success
== !abd
.isNull());
1686 Node
SolverEngine::getAbductNext()
1688 SolverEngineScope
smts(this);
1690 if (d_state
->getMode() != SmtMode::ABDUCT
)
1692 throw RecoverableModalException(
1693 "Cannot get-abduct-next unless immediately preceded by a successful "
1694 "call to get-abduct(-next).");
1697 bool success
= d_abductSolver
->getAbductNext(abd
);
1698 // notify the state of whether the get-abduct-next call was successful
1699 d_state
->notifyGetAbduct(success
);
1700 Assert(success
== !abd
.isNull());
1704 void SolverEngine::getInstantiatedQuantifiedFormulas(std::vector
<Node
>& qs
)
1706 SolverEngineScope
smts(this);
1707 QuantifiersEngine
* qe
=
1708 getAvailableQuantifiersEngine("getInstantiatedQuantifiedFormulas");
1709 qe
->getInstantiatedQuantifiedFormulas(qs
);
1712 void SolverEngine::getInstantiationTermVectors(
1713 Node q
, std::vector
<std::vector
<Node
>>& tvecs
)
1715 SolverEngineScope
smts(this);
1716 QuantifiersEngine
* qe
=
1717 getAvailableQuantifiersEngine("getInstantiationTermVectors");
1718 qe
->getInstantiationTermVectors(q
, tvecs
);
1721 std::vector
<Node
> SolverEngine::getAssertions()
1723 SolverEngineScope
smts(this);
1725 d_state
->doPendingPops();
1726 Trace("smt") << "SMT getAssertions()" << endl
;
1727 // note we always enable assertions, so it is available here
1728 return getAssertionsInternal();
1731 void SolverEngine::getDifficultyMap(std::map
<Node
, Node
>& dmap
)
1733 Trace("smt") << "SMT getDifficultyMap()\n";
1734 SolverEngineScope
smts(this);
1736 if (!d_env
->getOptions().smt
.produceDifficulty
)
1738 throw ModalException(
1739 "Cannot get difficulty when difficulty option is off.");
1741 // the prop engine has the proof of false
1742 Assert(d_pfManager
);
1743 // get difficulty map from theory engine first
1744 TheoryEngine
* te
= getTheoryEngine();
1745 te
->getDifficultyMap(dmap
);
1746 // then ask proof manager to translate dmap in terms of the input
1747 d_pfManager
->translateDifficultyMap(dmap
, *d_asserts
);
1750 void SolverEngine::push()
1752 SolverEngineScope
smts(this);
1754 d_state
->doPendingPops();
1755 Trace("smt") << "SMT push()" << endl
;
1756 d_smtSolver
->processAssertions(*d_asserts
);
1757 d_state
->userPush();
1760 void SolverEngine::pop()
1762 SolverEngineScope
smts(this);
1764 Trace("smt") << "SMT pop()" << endl
;
1767 // Clear out assertion queues etc., in case anything is still in there
1768 d_asserts
->clearCurrent();
1769 // clear the learned literals from the preprocessor
1770 d_smtSolver
->getPreprocessor()->clearLearnedLiterals();
1772 Trace("userpushpop") << "SolverEngine: popped to level "
1773 << getUserContext()->getLevel() << endl
;
1774 // should we reset d_status here?
1775 // SMT-LIBv2 spec seems to imply no, but it would make sense to..
1778 void SolverEngine::resetAssertions()
1780 SolverEngineScope
smts(this);
1782 if (!d_state
->isFullyInited())
1784 // We're still in Start Mode, nothing asserted yet, do nothing.
1785 // (see solver execution modes in the SMT-LIB standard)
1786 Assert(getContext()->getLevel() == 0);
1787 Assert(getUserContext()->getLevel() == 0);
1791 Trace("smt") << "SMT resetAssertions()" << endl
;
1793 d_asserts
->clearCurrent();
1794 d_state
->notifyResetAssertions();
1795 // push the state to maintain global context around everything
1798 // reset SmtSolver, which will construct a new prop engine
1799 d_smtSolver
->resetAssertions();
1802 void SolverEngine::interrupt()
1804 if (!d_state
->isFullyInited())
1808 d_smtSolver
->interrupt();
1811 void SolverEngine::setResourceLimit(uint64_t units
, bool cumulative
)
1815 d_env
->d_options
.base
.cumulativeResourceLimit
= units
;
1819 d_env
->d_options
.base
.perCallResourceLimit
= units
;
1822 void SolverEngine::setTimeLimit(uint64_t millis
)
1824 d_env
->d_options
.base
.perCallMillisecondLimit
= millis
;
1827 unsigned long SolverEngine::getResourceUsage() const
1829 return getResourceManager()->getResourceUsage();
1832 unsigned long SolverEngine::getTimeUsage() const
1834 return getResourceManager()->getTimeUsage();
1837 unsigned long SolverEngine::getResourceRemaining() const
1839 return getResourceManager()->getResourceRemaining();
1842 NodeManager
* SolverEngine::getNodeManager() const
1844 return d_env
->getNodeManager();
1847 void SolverEngine::printStatisticsSafe(int fd
) const
1849 d_env
->getStatisticsRegistry().printSafe(fd
);
1852 void SolverEngine::printStatisticsDiff() const
1854 d_env
->getStatisticsRegistry().printDiff(*d_env
->getOptions().base
.err
);
1855 d_env
->getStatisticsRegistry().storeSnapshot();
1858 void SolverEngine::setOption(const std::string
& key
, const std::string
& value
)
1860 Trace("smt") << "SMT setOption(" << key
<< ", " << value
<< ")" << endl
;
1861 options::set(getOptions(), key
, value
);
1864 void SolverEngine::setIsInternalSubsolver() { d_isInternalSubsolver
= true; }
1866 bool SolverEngine::isInternalSubsolver() const { return d_isInternalSubsolver
; }
1868 std::string
SolverEngine::getOption(const std::string
& key
) const
1870 Trace("smt") << "SMT getOption(" << key
<< ")" << endl
;
1871 return options::get(getOptions(), key
);
1874 Options
& SolverEngine::getOptions() { return d_env
->d_options
; }
1876 const Options
& SolverEngine::getOptions() const { return d_env
->getOptions(); }
1878 ResourceManager
* SolverEngine::getResourceManager() const
1880 return d_env
->getResourceManager();
1883 const Printer
& SolverEngine::getPrinter() const { return d_env
->getPrinter(); }
1885 theory::Rewriter
* SolverEngine::getRewriter() { return d_env
->getRewriter(); }