Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Andrew Reynolds, Aina Niemetz, Gereon Kremer 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2025 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 : : * **************************************************************************** 12 : : * 13 : : * The solver for SMT queries in an SolverEngine. 14 : : */ 15 : : 16 : : #include "smt/smt_solver.h" 17 : : 18 : : #include "options/base_options.h" 19 : : #include "options/main_options.h" 20 : : #include "options/smt_options.h" 21 : : #include "preprocessing/assertion_pipeline.h" 22 : : #include "prop/prop_engine.h" 23 : : #include "smt/assertions.h" 24 : : #include "smt/env.h" 25 : : #include "smt/logic_exception.h" 26 : : #include "smt/preprocessor.h" 27 : : #include "smt/proof_manager.h" 28 : : #include "smt/solver_engine_stats.h" 29 : : #include "theory/logic_info.h" 30 : : #include "theory/theory_engine.h" 31 : : #include "theory/theory_traits.h" 32 : : 33 : : using namespace std; 34 : : 35 : : namespace cvc5::internal { 36 : : namespace smt { 37 : : 38 : 71513 : SmtSolver::SmtSolver(Env& env, SolverEngineStatistics& stats) 39 : : : EnvObj(env), 40 : : d_pp(env, stats), 41 : : d_asserts(env), 42 : : d_stats(stats), 43 : : d_theoryEngine(nullptr), 44 : : d_propEngine(nullptr), 45 : 143026 : d_ppAssertions(userContext()), 46 : 71513 : d_ppSkolemMap(userContext()) 47 : : { 48 : 71513 : } 49 : : 50 : 133902 : SmtSolver::~SmtSolver() {} 51 : : 52 : 50758 : void SmtSolver::finishInit() 53 : : { 54 : : // We have mutual dependency here, so we add the prop engine to the theory 55 : : // engine later (it is non-essential there) 56 : 50758 : d_theoryEngine.reset(new TheoryEngine(d_env)); 57 : : 58 : : // Add the theories 59 [ + + ]: 761370 : for (theory::TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; 60 : 710612 : ++id) 61 : : { 62 : 710612 : theory::TheoryConstructor::addTheory(d_theoryEngine.get(), id); 63 : : } 64 : : // Add the proof checkers for each theory 65 : 50758 : ProofNodeManager* pnm = d_env.getProofNodeManager(); 66 [ + + ]: 50758 : if (pnm) 67 : : { 68 : : // reset the rule checkers 69 : 19932 : pnm->getChecker()->reset(); 70 : : // add rule checkers from the theory engine 71 : 19932 : d_theoryEngine->initializeProofChecker(pnm->getChecker()); 72 : : } 73 [ + - ]: 50758 : Trace("smt-debug") << "Making prop engine..." << std::endl; 74 : : /* force destruction of referenced PropEngine to enforce that statistics 75 : : * are unregistered by the obsolete PropEngine object before registered 76 : : * again by the new PropEngine object */ 77 : 50758 : d_propEngine.reset(nullptr); 78 : 50758 : d_propEngine.reset(new prop::PropEngine(d_env, d_theoryEngine.get())); 79 : : 80 [ + - ]: 50758 : Trace("smt-debug") << "Setting up theory engine..." << std::endl; 81 : 50758 : d_theoryEngine->setPropEngine(getPropEngine()); 82 [ + - ]: 50758 : Trace("smt-debug") << "Finishing init for theory engine..." << std::endl; 83 : 50758 : d_theoryEngine->finishInit(); 84 : 50758 : d_propEngine->finishInit(); 85 : 50758 : finishInitPreprocessor(); 86 : : 87 [ - + ]: 50758 : if (options().proof.proofLog) 88 : : { 89 : 0 : smt::PfManager* pm = d_env.getProofManager(); 90 [ - - ]: 0 : if (pm != nullptr) 91 : : { 92 : : // Logs proofs on the base output stream of the solver 93 : 0 : pm->startProofLogging(options().base.out, d_asserts); 94 : : } 95 : : } 96 : 50758 : } 97 : : 98 : 597 : void SmtSolver::resetAssertions() 99 : : { 100 : : /* Create new PropEngine. 101 : : * First force destruction of referenced PropEngine to enforce that 102 : : * statistics are unregistered by the obsolete PropEngine object before 103 : : * registered again by the new PropEngine object */ 104 : 597 : d_propEngine.reset(nullptr); 105 : 597 : d_propEngine.reset(new prop::PropEngine(d_env, d_theoryEngine.get())); 106 : 597 : d_theoryEngine->setPropEngine(getPropEngine()); 107 : : // Notice that we do not reset TheoryEngine, nor does it require calling 108 : : // finishInit again. In particular, TheoryEngine::finishInit does not 109 : : // depend on knowing the associated PropEngine. 110 : 597 : d_propEngine->finishInit(); 111 : : // must reset the preprocessor as well 112 : 597 : finishInitPreprocessor(); 113 : 597 : } 114 : : 115 : 693658 : void SmtSolver::interrupt() 116 : : { 117 [ + - ]: 693658 : if (d_propEngine != nullptr) 118 : : { 119 : 693658 : d_propEngine->interrupt(); 120 : : } 121 [ + - ]: 693658 : if (d_theoryEngine != nullptr) 122 : : { 123 : 693658 : d_theoryEngine->interrupt(); 124 : : } 125 : 693658 : } 126 : : 127 : 50757 : Result SmtSolver::checkSatInternal() 128 : : { 129 : : // call the prop engine to check sat 130 : 50757 : return d_propEngine->checkSat(); 131 : : } 132 : : 133 : 67576 : void SmtSolver::preprocess(preprocessing::AssertionPipeline& ap) 134 : : { 135 : 135152 : TimerStat::CodeTimer paTimer(d_stats.d_processAssertionsTime); 136 : 67576 : d_env.getResourceManager()->spendResource(Resource::PreprocessStep); 137 : : 138 : : // process the assertions with the preprocessor 139 : 67576 : d_pp.process(ap); 140 : : 141 : : // end: INVARIANT to maintain: no reordering of assertions or 142 : : // introducing new ones 143 : 67552 : } 144 : : 145 : 67552 : void SmtSolver::assertToInternal(preprocessing::AssertionPipeline& ap) 146 : : { 147 : : // carry information about soundness to the theory engine we are sending to 148 [ + + ]: 67552 : if (ap.isRefutationUnsound()) 149 : : { 150 : 44 : d_theoryEngine->setRefutationUnsound(theory::IncompleteId::PREPROCESSING); 151 : : } 152 [ - + ]: 67552 : if (ap.isModelUnsound()) 153 : : { 154 : 0 : d_theoryEngine->setModelUnsound(theory::IncompleteId::PREPROCESSING); 155 : : } 156 : : // get the assertions 157 : 67552 : const std::vector<Node>& assertions = ap.ref(); 158 : 67552 : preprocessing::IteSkolemMap& ism = ap.getIteSkolemMap(); 159 : : // assert to prop engine, which will convert to CNF 160 : 67552 : d_env.verbose(2) << "converting to CNF..." << endl; 161 : 67552 : d_propEngine->assertInputFormulas(assertions, ism); 162 : : 163 : : // It is important to distinguish the input assertions from the skolem 164 : : // definitions, as the decision justification heuristic treates the latter 165 : : // specially. Note that we don't pass the preprocess learned literals 166 : : // d_pp.getLearnedLiterals() here, since they may not exactly correspond 167 : : // to the actual preprocessed learned literals, as the input may have 168 : : // undergone further preprocessing. 169 : : // if we can deep restart, we always remember the preprocessed formulas, 170 : : // which are the basis for the next check-sat. 171 [ + + ]: 67536 : if (trackPreprocessedAssertions()) 172 : : { 173 : : // incompatible with global negation 174 [ - + ][ - + ]: 29584 : Assert(!options().quantifiers.globalNegate); [ - - ] 175 : 29584 : theory::SubstitutionMap& sm = d_env.getTopLevelSubstitutions().get(); 176 : 29584 : size_t startIndex = d_ppAssertions.size(); 177 : : // remember the assertions and Skolem mapping 178 [ + + ]: 394533 : for (const Node& a : assertions) 179 : : { 180 : 364949 : d_ppAssertions.push_back(a); 181 : : } 182 [ + + ]: 48778 : for (const std::pair<const size_t, Node>& k : ism) 183 : : { 184 : : // optimization: skip skolems that were eliminated in preprocessing 185 [ + + ]: 19194 : if (sm.hasSubstitution(k.second)) 186 : : { 187 : 2 : continue; 188 : : } 189 : 19192 : size_t newIndex = k.first + startIndex; 190 : 19192 : d_ppSkolemMap[newIndex] = k.second; 191 : : } 192 : : } 193 : 67536 : } 194 : : 195 : 602 : const context::CDList<Node>& SmtSolver::getPreprocessedAssertions() const 196 : : { 197 : 602 : return d_ppAssertions; 198 : : } 199 : : 200 : 588 : const context::CDHashMap<size_t, Node>& SmtSolver::getPreprocessedSkolemMap() 201 : : const 202 : : { 203 : 588 : return d_ppSkolemMap; 204 : : } 205 : : 206 : 67536 : bool SmtSolver::trackPreprocessedAssertions() const 207 : : { 208 : 67536 : return options().smt.deepRestartMode != options::DeepRestartMode::NONE 209 [ + + ][ + + ]: 67536 : || options().smt.produceProofs; 210 : : } 211 : : 212 : 26192 : TheoryEngine* SmtSolver::getTheoryEngine() { return d_theoryEngine.get(); } 213 : : 214 : 127630 : prop::PropEngine* SmtSolver::getPropEngine() { return d_propEngine.get(); } 215 : : 216 : 4378 : theory::QuantifiersEngine* SmtSolver::getQuantifiersEngine() 217 : : { 218 [ - + ][ - + ]: 4378 : Assert(d_theoryEngine != nullptr); [ - - ] 219 : 4378 : return d_theoryEngine->getQuantifiersEngine(); 220 : : } 221 : : 222 : 143093 : Preprocessor* SmtSolver::getPreprocessor() { return &d_pp; } 223 : : 224 : 435822 : Assertions& SmtSolver::getAssertions() { return d_asserts; } 225 : : 226 : 9046 : void SmtSolver::pushPropContext() 227 : : { 228 : 18092 : TimerStat::CodeTimer pushPopTimer(d_stats.d_pushPopTime); 229 [ - + ][ - + ]: 9046 : Assert(d_propEngine != nullptr); [ - - ] 230 : 9046 : d_propEngine->push(); 231 : 9046 : } 232 : : 233 : 9041 : void SmtSolver::popPropContext() 234 : : { 235 : 18082 : TimerStat::CodeTimer pushPopTimer(d_stats.d_pushPopTime); 236 [ - + ][ - + ]: 9041 : Assert(d_propEngine != nullptr); [ - - ] 237 : 9041 : d_propEngine->pop(); 238 : 9041 : } 239 : : 240 : 49920 : void SmtSolver::resetTrail() 241 : : { 242 [ - + ][ - + ]: 49920 : Assert(d_propEngine != nullptr); [ - - ] 243 : 49920 : d_propEngine->resetTrail(); 244 : 49920 : } 245 : : 246 : 51355 : void SmtSolver::finishInitPreprocessor() 247 : : { 248 : : // determine if we are assigning a preprocess proof generator here 249 : 51355 : smt::PfManager* pm = d_env.getProofManager(); 250 : 51355 : smt::PreprocessProofGenerator* pppg = nullptr; 251 [ + + ]: 51355 : if (pm != nullptr) 252 : : { 253 : 20149 : pppg = pm->getPreprocessProofGenerator(); 254 : : } 255 : 51355 : d_pp.finishInit(d_theoryEngine.get(), d_propEngine.get(), pppg); 256 : 51355 : } 257 : : 258 : : } // namespace smt 259 : : } // namespace cvc5::internal