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 "options/base_options.h"
26 #include "options/expr_options.h"
27 #include "options/language.h"
28 #include "options/main_options.h"
29 #include "options/option_exception.h"
30 #include "options/options_public.h"
31 #include "options/parser_options.h"
32 #include "options/printer_options.h"
33 #include "options/proof_options.h"
34 #include "options/smt_options.h"
35 #include "options/theory_options.h"
36 #include "printer/printer.h"
37 #include "proof/unsat_core.h"
38 #include "prop/prop_engine.h"
39 #include "smt/abduction_solver.h"
40 #include "smt/abstract_values.h"
41 #include "smt/assertions.h"
42 #include "smt/check_models.h"
44 #include "smt/interpolation_solver.h"
45 #include "smt/listeners.h"
46 #include "smt/logic_exception.h"
47 #include "smt/model_blocker.h"
48 #include "smt/model_core_builder.h"
49 #include "smt/preprocessor.h"
50 #include "smt/proof_manager.h"
51 #include "smt/quant_elim_solver.h"
52 #include "smt/set_defaults.h"
53 #include "smt/smt_solver.h"
54 #include "smt/solver_engine_scope.h"
55 #include "smt/solver_engine_state.h"
56 #include "smt/solver_engine_stats.h"
57 #include "smt/sygus_solver.h"
58 #include "smt/unsat_core_manager.h"
59 #include "theory/quantifiers/instantiation_list.h"
60 #include "theory/quantifiers/quantifiers_attributes.h"
61 #include "theory/quantifiers_engine.h"
62 #include "theory/rewriter.h"
63 #include "theory/smt_engine_subsolver.h"
64 #include "theory/theory_engine.h"
65 #include "util/random.h"
66 #include "util/rational.h"
67 #include "util/resource_manager.h"
68 #include "util/sexpr.h"
69 #include "util/statistics_registry.h"
71 // required for hacks related to old proofs for unsat cores
72 #include "base/configuration.h"
73 #include "base/configuration_private.h"
76 using namespace cvc5::smt
;
77 using namespace cvc5::preprocessing
;
78 using namespace cvc5::prop
;
79 using namespace cvc5::context
;
80 using namespace cvc5::theory
;
84 SolverEngine::SolverEngine(NodeManager
* nm
, const Options
* optr
)
85 : d_env(new Env(nm
, optr
)),
86 d_state(new SolverEngineState(*d_env
.get(), *this)),
87 d_absValues(new AbstractValues(getNodeManager())),
88 d_asserts(new Assertions(*d_env
.get(), *d_absValues
.get())),
89 d_routListener(new ResourceOutListener(*this)),
91 d_checkModels(nullptr),
94 d_sygusSolver(nullptr),
95 d_abductSolver(nullptr),
96 d_interpolSolver(nullptr),
97 d_quantElimSolver(nullptr),
98 d_isInternalSubsolver(false),
102 // !!!!!!!!!!!!!!!!!!!!!! temporary hack: this makes the current SolverEngine
103 // we are constructing the current SolverEngine in scope for the lifetime of
104 // this SolverEngine, or until another SolverEngine is constructed (that
105 // SolverEngine is then in scope during its lifetime). This is mostly to
106 // ensure that options are always in scope, for e.g. printing expressions,
107 // which rely on knowing the output language. Notice that the SolverEngine may
108 // spawn new SolverEngine "subsolvers" internally. These are created, used,
109 // and deleted in a modular fashion while not interleaving calls to the master
110 // SolverEngine. Thus the hack here does not break this use case. On the other
111 // hand, this hack breaks use cases where multiple SolverEngine objects are
112 // created by the user.
113 d_scope
.reset(new SolverEngineScope(this));
114 // listen to resource out
115 getResourceManager()->registerListener(d_routListener
.get());
117 d_stats
.reset(new SolverEngineStatistics());
118 // make the SMT solver
119 d_smtSolver
.reset(new SmtSolver(*d_env
, *d_state
, *d_absValues
, *d_stats
));
120 // make the SyGuS solver
121 d_sygusSolver
.reset(new SygusSolver(*d_env
.get(), *d_smtSolver
));
122 // make the quantifier elimination solver
123 d_quantElimSolver
.reset(new QuantElimSolver(*d_env
.get(), *d_smtSolver
));
126 bool SolverEngine::isFullyInited() const { return d_state
->isFullyInited(); }
127 bool SolverEngine::isQueryMade() const { return d_state
->isQueryMade(); }
128 size_t SolverEngine::getNumUserLevels() const
130 return d_state
->getNumUserLevels();
132 SmtMode
SolverEngine::getSmtMode() const { return d_state
->getMode(); }
133 bool SolverEngine::isSmtModeSat() const
135 SmtMode mode
= getSmtMode();
136 return mode
== SmtMode::SAT
|| mode
== SmtMode::SAT_UNKNOWN
;
138 Result
SolverEngine::getStatusOfLastCommand() const
140 return d_state
->getStatus();
142 context::UserContext
* SolverEngine::getUserContext()
144 return d_env
->getUserContext();
146 context::Context
* SolverEngine::getContext() { return d_env
->getContext(); }
148 TheoryEngine
* SolverEngine::getTheoryEngine()
150 return d_smtSolver
->getTheoryEngine();
153 prop::PropEngine
* SolverEngine::getPropEngine()
155 return d_smtSolver
->getPropEngine();
158 void SolverEngine::finishInit()
160 if (d_state
->isFullyInited())
162 // already initialized, return
166 // Notice that finishInitInternal is called when options are finalized. If we
167 // are parsing smt2, this occurs at the moment we enter "Assert mode", page 52
168 // of SMT-LIB 2.6 standard.
171 const LogicInfo
& logic
= getLogicInfo();
172 if (!logic
.isLocked())
177 // set the random seed
178 Random::getRandom().setSeed(d_env
->getOptions().driver
.seed
);
180 // Call finish init on the set defaults module. This inializes the logic
181 // and the best default options based on our heuristics.
182 SetDefaults
sdefaults(*d_env
, d_isInternalSubsolver
);
183 sdefaults
.setDefaults(d_env
->d_logic
, getOptions());
185 if (d_env
->getOptions().smt
.produceProofs
)
187 // ensure bound variable uses canonical bound variables
188 getNodeManager()->getBoundVarManager()->enableKeepCacheValues();
189 // make the proof manager
190 d_pfManager
.reset(new PfManager(*d_env
.get()));
191 PreprocessProofGenerator
* pppg
= d_pfManager
->getPreprocessProofGenerator();
192 // start the unsat core manager
193 d_ucManager
.reset(new UnsatCoreManager());
194 // enable it in the assertions pipeline
195 d_asserts
->enableProofs(pppg
);
196 // enabled proofs in the preprocessor
197 d_smtSolver
->getPreprocessor()->enableProofs(pppg
);
200 Trace("smt-debug") << "SolverEngine::finishInit" << std::endl
;
201 d_smtSolver
->finishInit();
203 // now can construct the SMT-level model object
204 TheoryEngine
* te
= d_smtSolver
->getTheoryEngine();
205 Assert(te
!= nullptr);
206 TheoryModel
* tm
= te
->getModel();
209 // make the check models utility
210 d_checkModels
.reset(new CheckModels(*d_env
.get()));
213 // global push/pop around everything, to ensure proper destruction
214 // of context-dependent data structures
217 Trace("smt-debug") << "Set up assertions..." << std::endl
;
218 d_asserts
->finishInit();
221 if (d_env
->getOptions().smt
.produceAbducts
)
223 d_abductSolver
.reset(new AbductionSolver(*d_env
.get()));
225 if (d_env
->getOptions().smt
.produceInterpols
226 != options::ProduceInterpols::NONE
)
228 d_interpolSolver
.reset(new InterpolationSolver(*d_env
));
231 AlwaysAssert(getPropEngine()->getAssertionLevel() == 0)
232 << "The PropEngine has pushed but the SolverEngine "
233 "hasn't finished initializing!";
235 Assert(getLogicInfo().isLocked());
237 // store that we are finished initializing
238 d_state
->finishInit();
239 Trace("smt-debug") << "SolverEngine::finishInit done" << std::endl
;
242 void SolverEngine::shutdown()
246 d_smtSolver
->shutdown();
251 SolverEngine::~SolverEngine()
253 SolverEngineScope
smts(this);
259 // global push/pop around everything, to ensure proper destruction
260 // of context-dependent data structures
263 // destroy all passes before destroying things that they refer to
264 d_smtSolver
->getPreprocessor()->cleanup();
266 d_pfManager
.reset(nullptr);
267 d_ucManager
.reset(nullptr);
269 d_absValues
.reset(nullptr);
270 d_asserts
.reset(nullptr);
272 d_abductSolver
.reset(nullptr);
273 d_interpolSolver
.reset(nullptr);
274 d_quantElimSolver
.reset(nullptr);
275 d_sygusSolver
.reset(nullptr);
276 d_smtSolver
.reset(nullptr);
278 d_stats
.reset(nullptr);
279 d_routListener
.reset(nullptr);
281 d_state
.reset(nullptr);
282 // destroy the environment
283 d_env
.reset(nullptr);
287 d_env
->warning() << "cvc5 threw an exception during cleanup." << std::endl
<< e
<< std::endl
;
291 void SolverEngine::setLogic(const LogicInfo
& logic
)
293 SolverEngineScope
smts(this);
294 if (d_state
->isFullyInited())
296 throw ModalException(
297 "Cannot set logic in SolverEngine after the engine has "
298 "finished initializing.");
300 d_env
->d_logic
= logic
;
305 void SolverEngine::setLogic(const std::string
& s
)
307 SolverEngineScope
smts(this);
310 setLogic(LogicInfo(s
));
312 catch (IllegalArgumentException
& e
)
314 throw LogicException(e
.what());
318 void SolverEngine::setLogic(const char* logic
) { setLogic(string(logic
)); }
320 const LogicInfo
& SolverEngine::getLogicInfo() const
322 return d_env
->getLogicInfo();
325 LogicInfo
SolverEngine::getUserLogicInfo() const
327 // Lock the logic to make sure that this logic can be queried. We create a
328 // copy of the user logic here to keep this method const.
329 LogicInfo res
= d_userLogic
;
334 void SolverEngine::setLogicInternal()
336 Assert(!d_state
->isFullyInited())
337 << "setting logic in SolverEngine but the engine has already"
338 " finished initializing for this run";
339 d_env
->d_logic
.lock();
343 void SolverEngine::setInfo(const std::string
& key
, const std::string
& value
)
345 SolverEngineScope
smts(this);
347 Trace("smt") << "SMT setInfo(" << key
<< ", " << value
<< ")" << endl
;
349 if (key
== "filename")
351 d_env
->d_options
.driver
.filename
= value
;
352 d_env
->d_originalOptions
->driver
.filename
= value
;
353 d_env
->getStatisticsRegistry().registerValue
<std::string
>(
354 "driver::filename", value
);
356 else if (key
== "smt-lib-version"
357 && !getOptions().base
.inputLanguageWasSetByUser
)
359 if (value
!= "2" && value
!= "2.6")
361 d_env
->warning() << "SMT-LIB version " << value
362 << " unsupported, defaulting to language (and semantics of) "
365 getOptions().base
.inputLanguage
= Language::LANG_SMTLIB_V2_6
;
366 // also update the output language
367 if (!getOptions().base
.outputLanguageWasSetByUser
)
369 setOption("output-language", "smtlib2.6");
370 getOptions().base
.outputLanguageWasSetByUser
= false;
373 else if (key
== "status")
375 d_state
->notifyExpectedStatus(value
);
379 bool SolverEngine::isValidGetInfoFlag(const std::string
& key
) const
381 if (key
== "all-statistics" || key
== "error-behavior" || key
== "filename"
382 || key
== "name" || key
== "version" || key
== "authors"
383 || key
== "status" || key
== "time" || key
== "reason-unknown"
384 || key
== "assertion-stack-levels" || key
== "all-options")
391 std::string
SolverEngine::getInfo(const std::string
& key
) const
393 SolverEngineScope
smts(this);
395 Trace("smt") << "SMT getInfo(" << key
<< ")" << endl
;
396 if (key
== "all-statistics")
398 return toSExpr(d_env
->getStatisticsRegistry().begin(),
399 d_env
->getStatisticsRegistry().end());
401 if (key
== "error-behavior")
403 return "immediate-exit";
405 if (key
== "filename")
407 return d_env
->getOptions().driver
.filename
;
411 return toSExpr(Configuration::getName());
413 if (key
== "version")
415 return toSExpr(Configuration::getVersionString());
417 if (key
== "authors")
419 return toSExpr("the " + Configuration::getName() + " authors");
423 // sat | unsat | unknown
424 Result status
= d_state
->getStatus();
425 switch (status
.asSatisfiabilityResult().isSat())
427 case Result::SAT
: return "sat";
428 case Result::UNSAT
: return "unsat";
429 default: return "unknown";
434 return toSExpr(std::clock());
436 if (key
== "reason-unknown")
438 Result status
= d_state
->getStatus();
439 if (!status
.isNull() && status
.isUnknown())
441 std::stringstream ss
;
442 ss
<< status
.whyUnknown();
443 std::string s
= ss
.str();
444 transform(s
.begin(), s
.end(), s
.begin(), ::tolower
);
449 throw RecoverableModalException(
450 "Can't get-info :reason-unknown when the "
451 "last result wasn't unknown!");
454 if (key
== "assertion-stack-levels")
456 size_t ulevel
= d_state
->getNumUserLevels();
457 AlwaysAssert(ulevel
<= std::numeric_limits
<unsigned long int>::max());
458 return toSExpr(ulevel
);
460 Assert(key
== "all-options");
461 // get the options, like all-statistics
462 std::vector
<std::vector
<std::string
>> res
;
463 for (const auto& opt
: options::getNames())
466 std::vector
<std::string
>{opt
, options::get(getOptions(), opt
)});
471 void SolverEngine::debugCheckFormals(const std::vector
<Node
>& formals
,
474 for (std::vector
<Node
>::const_iterator i
= formals
.begin();
478 if ((*i
).getKind() != kind::BOUND_VARIABLE
)
481 ss
<< "All formal arguments to defined functions must be "
482 "BOUND_VARIABLEs, but in the\n"
483 << "definition of function " << func
<< ", formal\n"
485 << "has kind " << (*i
).getKind();
486 throw TypeCheckingExceptionPrivate(func
, ss
.str());
491 void SolverEngine::debugCheckFunctionBody(Node formula
,
492 const std::vector
<Node
>& formals
,
495 TypeNode formulaType
= formula
.getType(d_env
->getOptions().expr
.typeChecking
);
496 TypeNode funcType
= func
.getType();
497 // We distinguish here between definitions of constants and functions,
498 // because the type checking for them is subtly different. Perhaps we
499 // should instead have SolverEngine::defineFunction() and
500 // SolverEngine::defineConstant() for better clarity, although then that
501 // doesn't match the SMT-LIBv2 standard...
502 if (formals
.size() > 0)
504 TypeNode rangeType
= funcType
.getRangeType();
505 if (!formulaType
.isComparableTo(rangeType
))
508 ss
<< "Type of defined function does not match its declaration\n"
509 << "The function : " << func
<< "\n"
510 << "Declared type : " << rangeType
<< "\n"
511 << "The body : " << formula
<< "\n"
512 << "Body type : " << formulaType
;
513 throw TypeCheckingExceptionPrivate(func
, ss
.str());
518 if (!formulaType
.isComparableTo(funcType
))
521 ss
<< "Declared type of defined constant does not match its definition\n"
522 << "The constant : " << func
<< "\n"
523 << "Declared type : " << funcType
<< "\n"
524 << "The definition : " << formula
<< "\n"
525 << "Definition type: " << formulaType
;
526 throw TypeCheckingExceptionPrivate(func
, ss
.str());
531 void SolverEngine::defineFunction(Node func
,
532 const std::vector
<Node
>& formals
,
536 SolverEngineScope
smts(this);
538 d_state
->doPendingPops();
539 Trace("smt") << "SMT defineFunction(" << func
<< ")" << endl
;
540 debugCheckFormals(formals
, func
);
543 debugCheckFunctionBody(formula
, formals
, func
);
545 // Substitute out any abstract values in formula
546 Node def
= d_absValues
->substituteAbstractValues(formula
);
547 if (!formals
.empty())
549 NodeManager
* nm
= NodeManager::currentNM();
551 kind::LAMBDA
, nm
->mkNode(kind::BOUND_VAR_LIST
, formals
), def
);
553 // A define-fun is treated as a (higher-order) assertion. It is provided
554 // to the assertions object. It will be added as a top-level substitution
555 // within this class, possibly multiple times if global is true.
556 Node feq
= func
.eqNode(def
);
557 d_asserts
->addDefineFunDefinition(feq
, global
);
560 void SolverEngine::defineFunctionsRec(
561 const std::vector
<Node
>& funcs
,
562 const std::vector
<std::vector
<Node
>>& formals
,
563 const std::vector
<Node
>& formulas
,
566 SolverEngineScope
smts(this);
568 d_state
->doPendingPops();
569 Trace("smt") << "SMT defineFunctionsRec(...)" << endl
;
571 if (funcs
.size() != formals
.size() && funcs
.size() != formulas
.size())
574 ss
<< "Number of functions, formals, and function bodies passed to "
575 "defineFunctionsRec do not match:"
577 << " #functions : " << funcs
.size() << "\n"
578 << " #arg lists : " << formals
.size() << "\n"
579 << " #function bodies : " << formulas
.size() << "\n";
580 throw ModalException(ss
.str());
582 for (unsigned i
= 0, size
= funcs
.size(); i
< size
; i
++)
584 // check formal argument list
585 debugCheckFormals(formals
[i
], funcs
[i
]);
587 debugCheckFunctionBody(formulas
[i
], formals
[i
], funcs
[i
]);
590 NodeManager
* nm
= getNodeManager();
591 for (unsigned i
= 0, size
= funcs
.size(); i
< size
; i
++)
593 // we assert a quantified formula
595 // make the function application
596 if (formals
[i
].empty())
598 // it has no arguments
603 std::vector
<Node
> children
;
604 children
.push_back(funcs
[i
]);
605 children
.insert(children
.end(), formals
[i
].begin(), formals
[i
].end());
606 func_app
= nm
->mkNode(kind::APPLY_UF
, children
);
608 Node lem
= nm
->mkNode(kind::EQUAL
, func_app
, formulas
[i
]);
609 if (!formals
[i
].empty())
611 // set the attribute to denote this is a function definition
612 Node aexpr
= nm
->mkNode(kind::INST_ATTRIBUTE
, func_app
);
613 aexpr
= nm
->mkNode(kind::INST_PATTERN_LIST
, aexpr
);
615 func_app
.setAttribute(fda
, true);
616 // make the quantified formula
617 Node boundVars
= nm
->mkNode(kind::BOUND_VAR_LIST
, formals
[i
]);
618 lem
= nm
->mkNode(kind::FORALL
, boundVars
, lem
, aexpr
);
620 // Assert the quantified formula. Notice we don't call assertFormula
621 // directly, since we should call a private member method since we have
622 // already ensuring this SolverEngine is initialized above.
623 // add define recursive definition to the assertions
624 d_asserts
->addDefineFunDefinition(lem
, global
);
628 void SolverEngine::defineFunctionRec(Node func
,
629 const std::vector
<Node
>& formals
,
633 std::vector
<Node
> funcs
;
634 funcs
.push_back(func
);
635 std::vector
<std::vector
<Node
>> formals_multi
;
636 formals_multi
.push_back(formals
);
637 std::vector
<Node
> formulas
;
638 formulas
.push_back(formula
);
639 defineFunctionsRec(funcs
, formals_multi
, formulas
, global
);
642 Result
SolverEngine::quickCheck()
644 Assert(d_state
->isFullyInited());
645 Trace("smt") << "SMT quickCheck()" << endl
;
646 const std::string
& filename
= d_env
->getOptions().driver
.filename
;
648 Result::ENTAILMENT_UNKNOWN
, Result::REQUIRES_FULL_CHECK
, filename
);
651 TheoryModel
* SolverEngine::getAvailableModel(const char* c
) const
653 if (!d_env
->getOptions().theory
.assignFunctionValues
)
655 std::stringstream ss
;
656 ss
<< "Cannot " << c
<< " when --assign-function-values is false.";
657 throw RecoverableModalException(ss
.str().c_str());
660 if (d_state
->getMode() != SmtMode::SAT
661 && d_state
->getMode() != SmtMode::SAT_UNKNOWN
)
663 std::stringstream ss
;
665 << " unless immediately preceded by SAT/NOT_ENTAILED or UNKNOWN "
667 throw RecoverableModalException(ss
.str().c_str());
670 if (!d_env
->getOptions().smt
.produceModels
)
672 std::stringstream ss
;
673 ss
<< "Cannot " << c
<< " when produce-models options is off.";
674 throw ModalException(ss
.str().c_str());
677 TheoryEngine
* te
= d_smtSolver
->getTheoryEngine();
678 Assert(te
!= nullptr);
679 TheoryModel
* m
= te
->getBuiltModel();
683 std::stringstream ss
;
685 << " since model is not available. Perhaps the most recent call to "
686 "check-sat was interrupted?";
687 throw RecoverableModalException(ss
.str().c_str());
693 QuantifiersEngine
* SolverEngine::getAvailableQuantifiersEngine(
696 QuantifiersEngine
* qe
= d_smtSolver
->getQuantifiersEngine();
699 std::stringstream ss
;
700 ss
<< "Cannot " << c
<< " when quantifiers are not present.";
701 throw ModalException(ss
.str().c_str());
706 void SolverEngine::notifyPushPre()
708 d_smtSolver
->processAssertions(*d_asserts
);
711 void SolverEngine::notifyPushPost()
713 TimerStat::CodeTimer
pushPopTimer(d_stats
->d_pushPopTime
);
714 Assert(getPropEngine() != nullptr);
715 getPropEngine()->push();
718 void SolverEngine::notifyPopPre()
720 TimerStat::CodeTimer
pushPopTimer(d_stats
->d_pushPopTime
);
721 PropEngine
* pe
= getPropEngine();
722 Assert(pe
!= nullptr);
726 void SolverEngine::notifyPostSolvePre()
728 PropEngine
* pe
= getPropEngine();
729 Assert(pe
!= nullptr);
733 void SolverEngine::notifyPostSolvePost()
735 TheoryEngine
* te
= getTheoryEngine();
736 Assert(te
!= nullptr);
740 Result
SolverEngine::checkSat()
743 return checkSat(nullNode
);
746 Result
SolverEngine::checkSat(const Node
& assumption
)
748 std::vector
<Node
> assump
;
749 if (!assumption
.isNull())
751 assump
.push_back(assumption
);
753 return checkSatInternal(assump
, false);
756 Result
SolverEngine::checkSat(const std::vector
<Node
>& assumptions
)
758 return checkSatInternal(assumptions
, false);
761 Result
SolverEngine::checkEntailed(const Node
& node
)
763 return checkSatInternal(
764 node
.isNull() ? std::vector
<Node
>() : std::vector
<Node
>{node
},
766 .asEntailmentResult();
769 Result
SolverEngine::checkEntailed(const std::vector
<Node
>& nodes
)
771 return checkSatInternal(nodes
, true).asEntailmentResult();
774 Result
SolverEngine::checkSatInternal(const std::vector
<Node
>& assumptions
,
775 bool isEntailmentCheck
)
779 SolverEngineScope
smts(this);
782 Trace("smt") << "SolverEngine::"
783 << (isEntailmentCheck
? "checkEntailed" : "checkSat") << "("
784 << assumptions
<< ")" << endl
;
785 // check the satisfiability with the solver object
786 Result r
= d_smtSolver
->checkSatisfiability(
787 *d_asserts
.get(), assumptions
, isEntailmentCheck
);
789 Trace("smt") << "SolverEngine::"
790 << (isEntailmentCheck
? "query" : "checkSat") << "("
791 << assumptions
<< ") => " << r
<< endl
;
793 // Check that SAT results generate a model correctly.
794 if (d_env
->getOptions().smt
.checkModels
)
796 if (r
.asSatisfiabilityResult().isSat() == Result::SAT
)
801 // Check that UNSAT results generate a proof correctly.
802 if (d_env
->getOptions().smt
.checkProofs
)
804 if (r
.asSatisfiabilityResult().isSat() == Result::UNSAT
)
809 // Check that UNSAT results generate an unsat core correctly.
810 if (d_env
->getOptions().smt
.checkUnsatCores
)
812 if (r
.asSatisfiabilityResult().isSat() == Result::UNSAT
)
814 TimerStat::CodeTimer
checkUnsatCoreTimer(d_stats
->d_checkUnsatCoreTime
);
818 if (d_env
->getOptions().base
.statisticsEveryQuery
)
820 printStatisticsDiff();
824 catch (UnsafeInterruptException
& e
)
826 AlwaysAssert(getResourceManager()->out());
827 // Notice that we do not notify the state of this result. If we wanted to
828 // make the solver resume a working state after an interupt, then we would
829 // implement a different callback and use it here, e.g.
830 // d_state.notifyCheckSatInterupt.
831 Result::UnknownExplanation why
= getResourceManager()->outOfResources()
832 ? Result::RESOURCEOUT
835 if (d_env
->getOptions().base
.statisticsEveryQuery
)
837 printStatisticsDiff();
840 Result::SAT_UNKNOWN
, why
, d_env
->getOptions().driver
.filename
);
844 std::vector
<Node
> SolverEngine::getUnsatAssumptions(void)
846 Trace("smt") << "SMT getUnsatAssumptions()" << endl
;
847 SolverEngineScope
smts(this);
848 if (!d_env
->getOptions().smt
.unsatAssumptions
)
850 throw ModalException(
851 "Cannot get unsat assumptions when produce-unsat-assumptions option "
854 if (d_state
->getMode() != SmtMode::UNSAT
)
856 throw RecoverableModalException(
857 "Cannot get unsat assumptions unless immediately preceded by "
861 UnsatCore core
= getUnsatCoreInternal();
862 std::vector
<Node
> res
;
863 std::vector
<Node
>& assumps
= d_asserts
->getAssumptions();
864 for (const Node
& e
: assumps
)
866 if (std::find(core
.begin(), core
.end(), e
) != core
.end())
874 Result
SolverEngine::assertFormula(const Node
& formula
)
876 SolverEngineScope
smts(this);
878 d_state
->doPendingPops();
880 Trace("smt") << "SolverEngine::assertFormula(" << formula
<< ")" << endl
;
882 // Substitute out any abstract values in ex
883 Node n
= d_absValues
->substituteAbstractValues(formula
);
885 d_asserts
->assertFormula(n
);
886 return quickCheck().asEntailmentResult();
887 } /* SolverEngine::assertFormula() */
890 --------------------------------------------------------------------------
891 Handling SyGuS commands
892 --------------------------------------------------------------------------
895 void SolverEngine::declareSygusVar(Node var
)
897 SolverEngineScope
smts(this);
898 d_sygusSolver
->declareSygusVar(var
);
901 void SolverEngine::declareSynthFun(Node func
,
904 const std::vector
<Node
>& vars
)
906 SolverEngineScope
smts(this);
908 d_state
->doPendingPops();
909 d_sygusSolver
->declareSynthFun(func
, sygusType
, isInv
, vars
);
911 void SolverEngine::declareSynthFun(Node func
,
913 const std::vector
<Node
>& vars
)
915 // use a null sygus type
917 declareSynthFun(func
, sygusType
, isInv
, vars
);
920 void SolverEngine::assertSygusConstraint(Node n
, bool isAssume
)
922 SolverEngineScope
smts(this);
924 d_sygusSolver
->assertSygusConstraint(n
, isAssume
);
927 void SolverEngine::assertSygusInvConstraint(Node inv
,
932 SolverEngineScope
smts(this);
934 d_sygusSolver
->assertSygusInvConstraint(inv
, pre
, trans
, post
);
937 Result
SolverEngine::checkSynth(bool isNext
)
939 SolverEngineScope
smts(this);
941 if (isNext
&& d_state
->getMode() != SmtMode::SYNTH
)
943 throw RecoverableModalException(
944 "Cannot check-synth-next unless immediately preceded by a successful "
945 "call to check-synth(-next).");
947 Result r
= d_sygusSolver
->checkSynth(*d_asserts
, isNext
);
948 d_state
->notifyCheckSynthResult(r
);
953 --------------------------------------------------------------------------
954 End of Handling SyGuS commands
955 --------------------------------------------------------------------------
958 void SolverEngine::declarePool(const Node
& p
,
959 const std::vector
<Node
>& initValue
)
961 Assert(p
.isVar() && p
.getType().isSet());
963 QuantifiersEngine
* qe
= getAvailableQuantifiersEngine("declareTermPool");
964 qe
->declarePool(p
, initValue
);
967 Node
SolverEngine::simplify(const Node
& ex
)
969 SolverEngineScope
smts(this);
971 d_state
->doPendingPops();
972 // ensure we've processed assertions
973 d_smtSolver
->processAssertions(*d_asserts
);
974 return d_smtSolver
->getPreprocessor()->simplify(ex
);
977 Node
SolverEngine::expandDefinitions(const Node
& ex
)
979 getResourceManager()->spendResource(Resource::PreprocessStep
);
980 SolverEngineScope
smts(this);
982 d_state
->doPendingPops();
983 return d_smtSolver
->getPreprocessor()->expandDefinitions(ex
);
986 // TODO(#1108): Simplify the error reporting of this method.
987 Node
SolverEngine::getValue(const Node
& ex
) const
989 SolverEngineScope
smts(this);
991 Trace("smt") << "SMT getValue(" << ex
<< ")" << endl
;
992 TypeNode expectedType
= ex
.getType();
994 // Substitute out any abstract values in ex and expand
995 Node n
= d_smtSolver
->getPreprocessor()->expandDefinitions(ex
);
997 Trace("smt") << "--- getting value of " << n
<< endl
;
998 // There are two ways model values for terms are computed (for historical
999 // reasons). One way is that used in check-model; the other is that
1000 // used by the Model classes. It's not clear to me exactly how these
1001 // two are different, but they need to be unified. This ugly hack here
1002 // is to fix bug 554 until we can revamp boolean-terms and models [MGD]
1005 if (!n
.getType().isFunction())
1007 n
= d_env
->getRewriter()->rewrite(n
);
1010 Trace("smt") << "--- getting value of " << n
<< endl
;
1011 TheoryModel
* m
= getAvailableModel("get-value");
1012 Assert(m
!= nullptr);
1013 Node resultNode
= m
->getValue(n
);
1014 Trace("smt") << "--- got value " << n
<< " = " << resultNode
<< endl
;
1015 Trace("smt") << "--- type " << resultNode
.getType() << endl
;
1016 Trace("smt") << "--- expected type " << expectedType
<< endl
;
1018 // type-check the result we got
1019 // Notice that lambdas have function type, which does not respect the subtype
1020 // relation, so we ignore them here.
1021 Assert(resultNode
.isNull() || resultNode
.getKind() == kind::LAMBDA
1022 || resultNode
.getType().isSubtypeOf(expectedType
))
1023 << "Run with -t smt for details.";
1025 // Ensure it's a constant, or a lambda (for uninterpreted functions). This
1026 // assertion only holds for models that do not have approximate values.
1027 Assert(m
->hasApproximations() || resultNode
.getKind() == kind::LAMBDA
1028 || resultNode
.isConst());
1030 if (d_env
->getOptions().smt
.abstractValues
&& resultNode
.getType().isArray())
1032 resultNode
= d_absValues
->mkAbstractValue(resultNode
);
1033 Trace("smt") << "--- abstract value >> " << resultNode
<< endl
;
1039 std::vector
<Node
> SolverEngine::getValues(const std::vector
<Node
>& exprs
) const
1041 std::vector
<Node
> result
;
1042 for (const Node
& e
: exprs
)
1044 result
.push_back(getValue(e
));
1049 std::vector
<Node
> SolverEngine::getModelDomainElements(TypeNode tn
) const
1051 Assert(tn
.isSort());
1052 TheoryModel
* m
= getAvailableModel("getModelDomainElements");
1053 return m
->getDomainElements(tn
);
1056 bool SolverEngine::isModelCoreSymbol(Node n
)
1058 SolverEngineScope
smts(this);
1060 const Options
& opts
= d_env
->getOptions();
1061 if (opts
.smt
.modelCoresMode
== options::ModelCoresMode::NONE
)
1063 // if the model core mode is none, we are always a model core symbol
1066 TheoryModel
* tm
= getAvailableModel("isModelCoreSymbol");
1067 // compute the model core if not done so already
1068 if (!tm
->isUsingModelCore())
1070 // If we enabled model cores, we compute a model core for m based on our
1071 // (expanded) assertions using the model core builder utility. Notice that
1072 // we get the assertions using the getAssertionsInternal, which does not
1073 // impact whether we are in "sat" mode
1074 std::vector
<Node
> asserts
= getAssertionsInternal();
1075 d_smtSolver
->getPreprocessor()->expandDefinitions(asserts
);
1076 ModelCoreBuilder
mcb(*d_env
.get());
1077 mcb
.setModelCore(asserts
, tm
, opts
.smt
.modelCoresMode
);
1079 return tm
->isModelCoreSymbol(n
);
1082 std::string
SolverEngine::getModel(const std::vector
<TypeNode
>& declaredSorts
,
1083 const std::vector
<Node
>& declaredFuns
)
1085 SolverEngineScope
smts(this);
1086 // !!! Note that all methods called here should have a version at the API
1087 // level. This is to ensure that the information associated with a model is
1088 // completely accessible by the user. This is currently not rigorously
1089 // enforced. An alternative design would be to have this method implemented
1090 // at the API level, but this makes exceptions in the text interface less
1092 TheoryModel
* tm
= getAvailableModel("get model");
1093 // use the smt::Model model utility for printing
1094 const Options
& opts
= d_env
->getOptions();
1095 bool isKnownSat
= (d_state
->getMode() == SmtMode::SAT
);
1096 Model
m(isKnownSat
, opts
.driver
.filename
);
1097 // set the model declarations, which determines what is printed in the model
1098 for (const TypeNode
& tn
: declaredSorts
)
1100 m
.addDeclarationSort(tn
, getModelDomainElements(tn
));
1102 bool usingModelCores
=
1103 (opts
.smt
.modelCoresMode
!= options::ModelCoresMode::NONE
);
1104 for (const Node
& n
: declaredFuns
)
1106 if (usingModelCores
&& !tm
->isModelCoreSymbol(n
))
1108 // skip if not in model core
1111 Node value
= tm
->getValue(n
);
1112 m
.addDeclarationTerm(n
, value
);
1114 // for separation logic
1115 TypeNode locT
, dataT
;
1116 if (getSepHeapTypes(locT
, dataT
))
1118 std::pair
<Node
, Node
> sh
= getSepHeapAndNilExpr();
1119 m
.setHeapModel(sh
.first
, sh
.second
);
1122 std::stringstream ssm
;
1127 Result
SolverEngine::blockModel()
1129 Trace("smt") << "SMT blockModel()" << endl
;
1130 SolverEngineScope
smts(this);
1134 TheoryModel
* m
= getAvailableModel("block model");
1136 if (d_env
->getOptions().smt
.blockModelsMode
== options::BlockModelsMode::NONE
)
1138 std::stringstream ss
;
1139 ss
<< "Cannot block model when block-models is set to none.";
1140 throw RecoverableModalException(ss
.str().c_str());
1143 // get expanded assertions
1144 std::vector
<Node
> eassertsProc
= getExpandedAssertions();
1145 ModelBlocker
mb(*d_env
.get());
1146 Node eblocker
= mb
.getModelBlocker(
1147 eassertsProc
, m
, d_env
->getOptions().smt
.blockModelsMode
);
1148 Trace("smt") << "Block formula: " << eblocker
<< std::endl
;
1149 return assertFormula(eblocker
);
1152 Result
SolverEngine::blockModelValues(const std::vector
<Node
>& exprs
)
1154 Trace("smt") << "SMT blockModelValues()" << endl
;
1155 SolverEngineScope
smts(this);
1159 TheoryModel
* m
= getAvailableModel("block model values");
1161 // get expanded assertions
1162 std::vector
<Node
> eassertsProc
= getExpandedAssertions();
1163 // we always do block model values mode here
1164 ModelBlocker
mb(*d_env
.get());
1165 Node eblocker
= mb
.getModelBlocker(
1166 eassertsProc
, m
, options::BlockModelsMode::VALUES
, exprs
);
1167 return assertFormula(eblocker
);
1170 std::pair
<Node
, Node
> SolverEngine::getSepHeapAndNilExpr(void)
1172 if (!getLogicInfo().isTheoryEnabled(THEORY_SEP
))
1175 "Cannot obtain separation logic expressions if not using the "
1176 "separation logic theory.";
1177 throw RecoverableModalException(msg
);
1181 TheoryModel
* tm
= getAvailableModel("get separation logic heap and nil");
1182 if (!tm
->getHeapModel(heap
, nil
))
1185 "Failed to obtain heap/nil "
1186 "expressions from theory model.";
1187 throw RecoverableModalException(msg
);
1189 return std::make_pair(heap
, nil
);
1192 std::vector
<Node
> SolverEngine::getAssertionsInternal()
1194 Assert(d_state
->isFullyInited());
1195 const context::CDList
<Node
>& al
= d_asserts
->getAssertionList();
1196 std::vector
<Node
> res
;
1197 for (const Node
& n
: al
)
1199 res
.emplace_back(n
);
1204 const Options
& SolverEngine::options() const { return d_env
->getOptions(); }
1206 std::vector
<Node
> SolverEngine::getExpandedAssertions()
1208 std::vector
<Node
> easserts
= getAssertions();
1209 // must expand definitions
1210 d_smtSolver
->getPreprocessor()->expandDefinitions(easserts
);
1213 Env
& SolverEngine::getEnv() { return *d_env
.get(); }
1215 void SolverEngine::declareSepHeap(TypeNode locT
, TypeNode dataT
)
1217 if (!getLogicInfo().isTheoryEnabled(THEORY_SEP
))
1220 "Cannot declare heap if not using the separation logic theory.";
1221 throw RecoverableModalException(msg
);
1223 SolverEngineScope
smts(this);
1225 TheoryEngine
* te
= getTheoryEngine();
1226 te
->declareSepHeap(locT
, dataT
);
1229 bool SolverEngine::getSepHeapTypes(TypeNode
& locT
, TypeNode
& dataT
)
1231 SolverEngineScope
smts(this);
1233 TheoryEngine
* te
= getTheoryEngine();
1234 return te
->getSepHeapTypes(locT
, dataT
);
1237 Node
SolverEngine::getSepHeapExpr() { return getSepHeapAndNilExpr().first
; }
1239 Node
SolverEngine::getSepNilExpr() { return getSepHeapAndNilExpr().second
; }
1241 void SolverEngine::checkProof()
1243 Assert(d_env
->getOptions().smt
.produceProofs
);
1244 // internal check the proof
1245 PropEngine
* pe
= getPropEngine();
1246 Assert(pe
!= nullptr);
1247 if (d_env
->getOptions().proof
.proofCheck
== options::ProofCheckMode::EAGER
)
1249 pe
->checkProof(d_asserts
->getAssertionList());
1251 Assert(pe
->getProof() != nullptr);
1252 std::shared_ptr
<ProofNode
> pePfn
= pe
->getProof();
1253 if (d_env
->getOptions().smt
.checkProofs
)
1255 d_pfManager
->checkProof(pePfn
, *d_asserts
);
1259 StatisticsRegistry
& SolverEngine::getStatisticsRegistry()
1261 return d_env
->getStatisticsRegistry();
1264 UnsatCore
SolverEngine::getUnsatCoreInternal()
1266 if (!d_env
->getOptions().smt
.unsatCores
)
1268 throw ModalException(
1269 "Cannot get an unsat core when produce-unsat-cores or produce-proofs "
1272 if (d_state
->getMode() != SmtMode::UNSAT
)
1274 throw RecoverableModalException(
1275 "Cannot get an unsat core unless immediately preceded by "
1276 "UNSAT/ENTAILED response.");
1278 // generate with new proofs
1279 PropEngine
* pe
= getPropEngine();
1280 Assert(pe
!= nullptr);
1282 std::shared_ptr
<ProofNode
> pepf
;
1283 if (options().smt
.unsatCoresMode
== options::UnsatCoresMode::ASSUMPTIONS
)
1285 pepf
= pe
->getRefutation();
1289 pepf
= pe
->getProof();
1291 Assert(pepf
!= nullptr);
1292 std::shared_ptr
<ProofNode
> pfn
= d_pfManager
->getFinalProof(pepf
, *d_asserts
);
1293 std::vector
<Node
> core
;
1294 d_ucManager
->getUnsatCore(pfn
, *d_asserts
, core
);
1295 if (options().smt
.minimalUnsatCores
)
1297 core
= reduceUnsatCore(core
);
1299 return UnsatCore(core
);
1302 std::vector
<Node
> SolverEngine::reduceUnsatCore(const std::vector
<Node
>& core
)
1304 Assert(options().smt
.unsatCores
)
1305 << "cannot reduce unsat core if unsat cores are turned off";
1307 d_env
->verbose(1) << "SolverEngine::reduceUnsatCore(): reducing unsat core"
1309 std::unordered_set
<Node
> removed
;
1310 for (const Node
& skip
: core
)
1312 std::unique_ptr
<SolverEngine
> coreChecker
;
1313 initializeSubsolver(coreChecker
, *d_env
.get());
1314 coreChecker
->setLogic(getLogicInfo());
1315 coreChecker
->getOptions().smt
.checkUnsatCores
= false;
1316 // disable all proof options
1317 coreChecker
->getOptions().smt
.produceProofs
= false;
1318 coreChecker
->getOptions().smt
.checkProofs
= false;
1320 for (const Node
& ucAssertion
: core
)
1322 if (ucAssertion
!= skip
&& removed
.find(ucAssertion
) == removed
.end())
1324 Node assertionAfterExpansion
= expandDefinitions(ucAssertion
);
1325 coreChecker
->assertFormula(assertionAfterExpansion
);
1331 r
= coreChecker
->checkSat();
1338 if (r
.asSatisfiabilityResult().isSat() == Result::UNSAT
)
1340 removed
.insert(skip
);
1342 else if (r
.asSatisfiabilityResult().isUnknown())
1345 << "SolverEngine::reduceUnsatCore(): could not reduce unsat core "
1351 if (removed
.empty())
1357 std::vector
<Node
> newUcAssertions
;
1358 for (const Node
& n
: core
)
1360 if (removed
.find(n
) == removed
.end())
1362 newUcAssertions
.push_back(n
);
1366 return newUcAssertions
;
1370 void SolverEngine::checkUnsatCore()
1372 Assert(d_env
->getOptions().smt
.unsatCores
)
1373 << "cannot check unsat core if unsat cores are turned off";
1375 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): generating unsat core"
1377 UnsatCore core
= getUnsatCore();
1379 // initialize the core checker
1380 std::unique_ptr
<SolverEngine
> coreChecker
;
1381 initializeSubsolver(coreChecker
, *d_env
.get());
1382 coreChecker
->getOptions().smt
.checkUnsatCores
= false;
1383 // disable all proof options
1384 coreChecker
->getOptions().smt
.produceProofs
= false;
1385 coreChecker
->getOptions().smt
.checkProofs
= false;
1387 // set up separation logic heap if necessary
1388 TypeNode sepLocType
, sepDataType
;
1389 if (getSepHeapTypes(sepLocType
, sepDataType
))
1391 coreChecker
->declareSepHeap(sepLocType
, sepDataType
);
1394 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): pushing core assertions"
1396 theory::TrustSubstitutionMap
& tls
= d_env
->getTopLevelSubstitutions();
1397 for (UnsatCore::iterator i
= core
.begin(); i
!= core
.end(); ++i
)
1399 Node assertionAfterExpansion
= tls
.apply(*i
);
1400 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): pushing core member "
1401 << *i
<< ", expanded to " << assertionAfterExpansion
1403 coreChecker
->assertFormula(assertionAfterExpansion
);
1408 r
= coreChecker
->checkSat();
1414 d_env
->verbose(1) << "SolverEngine::checkUnsatCore(): result is " << r
1416 if (r
.asSatisfiabilityResult().isUnknown())
1418 d_env
->warning() << "SolverEngine::checkUnsatCore(): could not check core result "
1422 else if (r
.asSatisfiabilityResult().isSat())
1425 << "SolverEngine::checkUnsatCore(): produced core was satisfiable.";
1429 void SolverEngine::checkModel(bool hardFailure
)
1431 const context::CDList
<Node
>& al
= d_asserts
->getAssertionList();
1432 // --check-model implies --produce-assertions, which enables the
1433 // assertion list, so we should be ok.
1434 Assert(d_env
->getOptions().smt
.produceAssertions
)
1435 << "don't have an assertion list to check in SolverEngine::checkModel()";
1437 TimerStat::CodeTimer
checkModelTimer(d_stats
->d_checkModelTime
);
1439 d_env
->verbose(1) << "SolverEngine::checkModel(): generating model"
1441 TheoryModel
* m
= getAvailableModel("check model");
1442 Assert(m
!= nullptr);
1444 // check the model with the theory engine for debugging
1445 if (options().smt
.debugCheckModels
)
1447 TheoryEngine
* te
= getTheoryEngine();
1448 Assert(te
!= nullptr);
1449 te
->checkTheoryAssertionsWithModel(hardFailure
);
1452 // check the model with the check models utility
1453 Assert(d_checkModels
!= nullptr);
1454 d_checkModels
->checkModel(m
, al
, hardFailure
);
1457 UnsatCore
SolverEngine::getUnsatCore()
1459 Trace("smt") << "SMT getUnsatCore()" << std::endl
;
1460 SolverEngineScope
smts(this);
1462 return getUnsatCoreInternal();
1465 void SolverEngine::getRelevantInstantiationTermVectors(
1466 std::map
<Node
, InstantiationList
>& insts
, bool getDebugInfo
)
1468 Assert(d_state
->getMode() == SmtMode::UNSAT
);
1469 // generate with new proofs
1470 PropEngine
* pe
= getPropEngine();
1471 Assert(pe
!= nullptr);
1472 Assert(pe
->getProof() != nullptr);
1473 std::shared_ptr
<ProofNode
> pfn
=
1474 d_pfManager
->getFinalProof(pe
->getProof(), *d_asserts
);
1475 d_ucManager
->getRelevantInstantiations(pfn
, insts
, getDebugInfo
);
1478 std::string
SolverEngine::getProof()
1480 Trace("smt") << "SMT getProof()\n";
1481 SolverEngineScope
smts(this);
1483 if (!d_env
->getOptions().smt
.produceProofs
)
1485 throw ModalException("Cannot get a proof when proof option is off.");
1487 if (d_state
->getMode() != SmtMode::UNSAT
)
1489 throw RecoverableModalException(
1490 "Cannot get a proof unless immediately preceded by "
1491 "UNSAT/ENTAILED response.");
1493 // the prop engine has the proof of false
1494 PropEngine
* pe
= getPropEngine();
1495 Assert(pe
!= nullptr);
1496 Assert(pe
->getProof() != nullptr);
1497 Assert(d_pfManager
);
1498 std::ostringstream ss
;
1499 d_pfManager
->printProof(ss
, pe
->getProof(), *d_asserts
);
1503 void SolverEngine::printInstantiations(std::ostream
& out
)
1505 SolverEngineScope
smts(this);
1507 QuantifiersEngine
* qe
= getAvailableQuantifiersEngine("printInstantiations");
1509 // First, extract and print the skolemizations
1510 bool printed
= false;
1511 bool reqNames
= !d_env
->getOptions().printer
.printInstFull
;
1512 // only print when in list mode
1513 if (d_env
->getOptions().printer
.printInstMode
== options::PrintInstMode::LIST
)
1515 std::map
<Node
, std::vector
<Node
>> sks
;
1516 qe
->getSkolemTermVectors(sks
);
1517 for (const std::pair
<const Node
, std::vector
<Node
>>& s
: sks
)
1520 if (!qe
->getNameForQuant(s
.first
, name
, reqNames
))
1522 // did not have a name and we are only printing formulas with names
1525 SkolemList
slist(name
, s
.second
);
1531 // Second, extract and print the instantiations
1532 std::map
<Node
, InstantiationList
> rinsts
;
1533 if (d_env
->getOptions().smt
.produceProofs
1534 && (!d_env
->getOptions().smt
.unsatCores
1535 || d_env
->getOptions().smt
.unsatCoresMode
1536 == options::UnsatCoresMode::FULL_PROOF
)
1537 && getSmtMode() == SmtMode::UNSAT
)
1539 // minimize instantiations based on proof manager
1540 getRelevantInstantiationTermVectors(
1541 rinsts
, options().driver
.dumpInstantiationsDebug
);
1545 std::map
<Node
, std::vector
<std::vector
<Node
>>> insts
;
1546 getInstantiationTermVectors(insts
);
1547 for (const std::pair
<const Node
, std::vector
<std::vector
<Node
>>>& i
: insts
)
1549 // convert to instantiation list
1551 InstantiationList
& ilq
= rinsts
[q
];
1553 for (const std::vector
<Node
>& ii
: i
.second
)
1555 ilq
.d_inst
.push_back(InstantiationVec(ii
));
1559 for (std::pair
<const Node
, InstantiationList
>& i
: rinsts
)
1561 if (i
.second
.d_inst
.empty())
1563 // no instantiations, skip
1567 if (!qe
->getNameForQuant(i
.first
, name
, reqNames
))
1569 // did not have a name and we are only printing formulas with names
1573 if (d_env
->getOptions().printer
.printInstMode
1574 == options::PrintInstMode::NUM
)
1576 out
<< "(num-instantiations " << name
<< " " << i
.second
.d_inst
.size()
1577 << ")" << std::endl
;
1582 i
.second
.d_quant
= name
;
1583 Assert(d_env
->getOptions().printer
.printInstMode
1584 == options::PrintInstMode::LIST
);
1589 // if we did not print anything, we indicate this
1592 out
<< "none" << std::endl
;
1596 void SolverEngine::getInstantiationTermVectors(
1597 std::map
<Node
, std::vector
<std::vector
<Node
>>>& insts
)
1599 SolverEngineScope
smts(this);
1601 QuantifiersEngine
* qe
=
1602 getAvailableQuantifiersEngine("getInstantiationTermVectors");
1603 // get the list of all instantiations
1604 qe
->getInstantiationTermVectors(insts
);
1607 bool SolverEngine::getSynthSolutions(std::map
<Node
, Node
>& solMap
)
1609 SolverEngineScope
smts(this);
1611 return d_sygusSolver
->getSynthSolutions(solMap
);
1614 bool SolverEngine::getSubsolverSynthSolutions(std::map
<Node
, Node
>& solMap
)
1616 SolverEngineScope
smts(this);
1618 return d_sygusSolver
->getSubsolverSynthSolutions(solMap
);
1621 Node
SolverEngine::getQuantifierElimination(Node q
, bool doFull
, bool strict
)
1623 SolverEngineScope
smts(this);
1625 const LogicInfo
& logic
= getLogicInfo();
1626 if (!logic
.isPure(THEORY_ARITH
) && strict
)
1628 d_env
->warning() << "Unexpected logic for quantifier elimination " << logic
1631 return d_quantElimSolver
->getQuantifierElimination(
1632 *d_asserts
, q
, doFull
, d_isInternalSubsolver
);
1635 bool SolverEngine::getInterpol(const Node
& conj
,
1636 const TypeNode
& grammarType
,
1639 SolverEngineScope
smts(this);
1641 std::vector
<Node
> axioms
= getExpandedAssertions();
1643 d_interpolSolver
->getInterpol(axioms
, conj
, grammarType
, interpol
);
1644 // notify the state of whether the get-interpol call was successfuly, which
1645 // impacts the SMT mode.
1646 d_state
->notifyGetInterpol(success
);
1650 bool SolverEngine::getInterpol(const Node
& conj
, Node
& interpol
)
1652 TypeNode grammarType
;
1653 return getInterpol(conj
, grammarType
, interpol
);
1656 bool SolverEngine::getAbduct(const Node
& conj
,
1657 const TypeNode
& grammarType
,
1660 SolverEngineScope
smts(this);
1662 std::vector
<Node
> axioms
= getExpandedAssertions();
1663 bool success
= d_abductSolver
->getAbduct(axioms
, conj
, grammarType
, abd
);
1664 // notify the state of whether the get-abduct call was successful, which
1665 // impacts the SMT mode.
1666 d_state
->notifyGetAbduct(success
);
1670 bool SolverEngine::getAbductNext(Node
& abd
)
1672 SolverEngineScope
smts(this);
1674 if (d_state
->getMode() != SmtMode::ABDUCT
)
1676 throw RecoverableModalException(
1677 "Cannot get-abduct-next unless immediately preceded by a successful "
1678 "call to get-abduct(-next).");
1680 bool success
= d_abductSolver
->getAbductNext(abd
);
1681 // notify the state of whether the get-abduct-next call was successful
1682 d_state
->notifyGetAbduct(success
);
1686 void SolverEngine::getInstantiatedQuantifiedFormulas(std::vector
<Node
>& qs
)
1688 SolverEngineScope
smts(this);
1689 QuantifiersEngine
* qe
=
1690 getAvailableQuantifiersEngine("getInstantiatedQuantifiedFormulas");
1691 qe
->getInstantiatedQuantifiedFormulas(qs
);
1694 void SolverEngine::getInstantiationTermVectors(
1695 Node q
, std::vector
<std::vector
<Node
>>& tvecs
)
1697 SolverEngineScope
smts(this);
1698 QuantifiersEngine
* qe
=
1699 getAvailableQuantifiersEngine("getInstantiationTermVectors");
1700 qe
->getInstantiationTermVectors(q
, tvecs
);
1703 std::vector
<Node
> SolverEngine::getAssertions()
1705 SolverEngineScope
smts(this);
1707 d_state
->doPendingPops();
1708 Trace("smt") << "SMT getAssertions()" << endl
;
1709 if (!d_env
->getOptions().smt
.produceAssertions
)
1712 "Cannot query the current assertion list when not in "
1713 "produce-assertions mode.";
1714 throw ModalException(msg
);
1716 return getAssertionsInternal();
1719 void SolverEngine::getDifficultyMap(std::map
<Node
, Node
>& dmap
)
1721 Trace("smt") << "SMT getDifficultyMap()\n";
1722 SolverEngineScope
smts(this);
1724 if (!d_env
->getOptions().smt
.produceDifficulty
)
1726 throw ModalException(
1727 "Cannot get difficulty when difficulty option is off.");
1729 // the prop engine has the proof of false
1730 Assert(d_pfManager
);
1731 // get difficulty map from theory engine first
1732 TheoryEngine
* te
= getTheoryEngine();
1733 te
->getDifficultyMap(dmap
);
1734 // then ask proof manager to translate dmap in terms of the input
1735 d_pfManager
->translateDifficultyMap(dmap
, *d_asserts
);
1738 void SolverEngine::push()
1740 SolverEngineScope
smts(this);
1742 d_state
->doPendingPops();
1743 Trace("smt") << "SMT push()" << endl
;
1744 d_smtSolver
->processAssertions(*d_asserts
);
1745 d_state
->userPush();
1748 void SolverEngine::pop()
1750 SolverEngineScope
smts(this);
1752 Trace("smt") << "SMT pop()" << endl
;
1755 // Clear out assertion queues etc., in case anything is still in there
1756 d_asserts
->clearCurrent();
1757 // clear the learned literals from the preprocessor
1758 d_smtSolver
->getPreprocessor()->clearLearnedLiterals();
1760 Trace("userpushpop") << "SolverEngine: popped to level "
1761 << getUserContext()->getLevel() << endl
;
1762 // should we reset d_status here?
1763 // SMT-LIBv2 spec seems to imply no, but it would make sense to..
1766 void SolverEngine::resetAssertions()
1768 SolverEngineScope
smts(this);
1770 if (!d_state
->isFullyInited())
1772 // We're still in Start Mode, nothing asserted yet, do nothing.
1773 // (see solver execution modes in the SMT-LIB standard)
1774 Assert(getContext()->getLevel() == 0);
1775 Assert(getUserContext()->getLevel() == 0);
1779 Trace("smt") << "SMT resetAssertions()" << endl
;
1781 d_asserts
->clearCurrent();
1782 d_state
->notifyResetAssertions();
1783 // push the state to maintain global context around everything
1786 // reset SmtSolver, which will construct a new prop engine
1787 d_smtSolver
->resetAssertions();
1790 void SolverEngine::interrupt()
1792 if (!d_state
->isFullyInited())
1796 d_smtSolver
->interrupt();
1799 void SolverEngine::setResourceLimit(uint64_t units
, bool cumulative
)
1803 d_env
->d_options
.base
.cumulativeResourceLimit
= units
;
1807 d_env
->d_options
.base
.perCallResourceLimit
= units
;
1810 void SolverEngine::setTimeLimit(uint64_t millis
)
1812 d_env
->d_options
.base
.perCallMillisecondLimit
= millis
;
1815 unsigned long SolverEngine::getResourceUsage() const
1817 return getResourceManager()->getResourceUsage();
1820 unsigned long SolverEngine::getTimeUsage() const
1822 return getResourceManager()->getTimeUsage();
1825 unsigned long SolverEngine::getResourceRemaining() const
1827 return getResourceManager()->getResourceRemaining();
1830 NodeManager
* SolverEngine::getNodeManager() const
1832 return d_env
->getNodeManager();
1835 void SolverEngine::printStatisticsSafe(int fd
) const
1837 d_env
->getStatisticsRegistry().printSafe(fd
);
1840 void SolverEngine::printStatisticsDiff() const
1842 d_env
->getStatisticsRegistry().printDiff(*d_env
->getOptions().base
.err
);
1843 d_env
->getStatisticsRegistry().storeSnapshot();
1846 void SolverEngine::setOption(const std::string
& key
, const std::string
& value
)
1848 Trace("smt") << "SMT setOption(" << key
<< ", " << value
<< ")" << endl
;
1849 options::set(getOptions(), key
, value
);
1852 void SolverEngine::setIsInternalSubsolver() { d_isInternalSubsolver
= true; }
1854 bool SolverEngine::isInternalSubsolver() const { return d_isInternalSubsolver
; }
1856 std::string
SolverEngine::getOption(const std::string
& key
) const
1858 Trace("smt") << "SMT getOption(" << key
<< ")" << endl
;
1859 return options::get(getOptions(), key
);
1862 Options
& SolverEngine::getOptions() { return d_env
->d_options
; }
1864 const Options
& SolverEngine::getOptions() const { return d_env
->getOptions(); }
1866 ResourceManager
* SolverEngine::getResourceManager() const
1868 return d_env
->getResourceManager();
1871 const Printer
& SolverEngine::getPrinter() const { return d_env
->getPrinter(); }
1873 theory::Rewriter
* SolverEngine::getRewriter() { return d_env
->getRewriter(); }