LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/prop - prop_engine.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 336 433 77.6 %
Date: 2026-03-03 11:42:59 Functions: 42 48 87.5 %
Branches: 186 332 56.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Implementation of the propositional engine of cvc5.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "prop/prop_engine.h"
      14                 :            : 
      15                 :            : #include <utility>
      16                 :            : 
      17                 :            : #include "base/check.h"
      18                 :            : #include "base/output.h"
      19                 :            : #include "expr/skolem_manager.h"
      20                 :            : #include "options/base_options.h"
      21                 :            : #include "options/decision_options.h"
      22                 :            : #include "options/main_options.h"
      23                 :            : #include "options/options.h"
      24                 :            : #include "options/proof_options.h"
      25                 :            : #include "options/prop_options.h"
      26                 :            : #include "options/smt_options.h"
      27                 :            : #include "proof/proof_node_algorithm.h"
      28                 :            : #include "prop/cnf_stream.h"
      29                 :            : #include "prop/proof_cnf_stream.h"
      30                 :            : #include "prop/prop_proof_manager.h"
      31                 :            : #include "prop/sat_solver.h"
      32                 :            : #include "prop/sat_solver_factory.h"
      33                 :            : #include "prop/theory_proxy.h"
      34                 :            : #include "smt/env.h"
      35                 :            : #include "theory/output_channel.h"
      36                 :            : #include "theory/theory_engine.h"
      37                 :            : #include "util/resource_manager.h"
      38                 :            : #include "util/result.h"
      39                 :            : 
      40                 :            : namespace cvc5::internal {
      41                 :            : namespace prop {
      42                 :            : 
      43                 :            : /** Keeps a boolean flag scoped */
      44                 :            : class ScopedBool {
      45                 :            : 
      46                 :            : private:
      47                 :            : 
      48                 :            :   bool d_original;
      49                 :            :   bool& d_reference;
      50                 :            : 
      51                 :            : public:
      52                 :            : 
      53                 :      49384 :   ScopedBool(bool& reference) :
      54                 :      49384 :     d_reference(reference) {
      55                 :      49384 :     d_original = reference;
      56                 :      49384 :   }
      57                 :            : 
      58                 :      49384 :   ~ScopedBool() {
      59                 :      49384 :     d_reference = d_original;
      60                 :      49384 :   }
      61                 :            : };
      62                 :            : 
      63                 :      50644 : PropEngine::PropEngine(Env& env, TheoryEngine* te)
      64                 :            :     : EnvObj(env),
      65                 :      50644 :       d_inCheckSat(false),
      66                 :      50644 :       d_theoryEngine(te),
      67                 :      50644 :       d_skdm(new SkolemDefManager(d_env.getContext(), d_env.getUserContext())),
      68                 :      50644 :       d_theoryProxy(nullptr),
      69                 :      50644 :       d_satSolver(nullptr),
      70                 :      50644 :       d_cnfStream(nullptr),
      71                 :      50644 :       d_theoryLemmaPg(d_env, d_env.getUserContext(), "PropEngine::ThLemmaPg"),
      72                 :      50644 :       d_ppm(nullptr),
      73                 :      50644 :       d_interrupted(false),
      74                 :      50644 :       d_assumptions(userContext()),
      75                 :      50644 :       d_localLemmas(userContext()),
      76                 :     151932 :       d_stats(statisticsRegistry())
      77                 :            : {
      78         [ +  - ]:      50644 :   Trace("prop") << "Constructing the PropEngine" << std::endl;
      79                 :      50644 :   context::UserContext* userContext = d_env.getUserContext();
      80                 :            : 
      81                 :            :   // CNF stream, SAT solver and theory proxy required pointers to each other,
      82                 :            :   // make the theory proxy first
      83                 :      50644 :   d_theoryProxy = new TheoryProxy(d_env, this, d_theoryEngine, d_skdm.get());
      84                 :            : 
      85                 :      50644 :   const auto factory = SatSolverFactory::getFactory(options().prop.satSolver);
      86                 :      50644 :   d_satSolver = factory(env, statisticsRegistry(), env.getResourceManager(),
      87                 :            :                         d_theoryProxy, "");
      88                 :            : 
      89                 :            :   // create CnfStream with new SAT solver
      90                 :     101288 :   d_cnfStream = new CnfStream(env,
      91                 :      50644 :                               d_satSolver,
      92                 :     101288 :                               d_theoryProxy,
      93                 :            :                               userContext,
      94                 :            :                               FormulaLitPolicy::TRACK,
      95         [ +  - ]:      50644 :                               "prop");
      96                 :            : 
      97                 :            :   // connect theory proxy
      98                 :      50644 :   d_theoryProxy->finishInit(d_satSolver, d_cnfStream);
      99                 :            :   // if proof producing at all
     100         [ +  + ]:      50644 :   if (options().smt.produceProofs)
     101                 :            :   {
     102                 :            :     PropPfManager* ppm =
     103                 :      19137 :         new PropPfManager(env, d_satSolver, *d_cnfStream, d_assumptions);
     104                 :      19137 :     d_ppm.reset(ppm);
     105                 :      19137 :     d_satSolver->attachProofManager(ppm);
     106                 :            :   }
     107                 :      50644 : }
     108                 :            : 
     109                 :      50644 : void PropEngine::finishInit()
     110                 :            : {
     111                 :            :   // Make sure that true/false are not free assumptions in the proof.
     112         [ +  + ]:      50644 :   if (d_ppm)
     113                 :            :   {
     114                 :      19137 :     NodeManager* nm = nodeManager();
     115                 :      38274 :     d_ppm->convertAndAssert(theory::InferenceId::INPUT,
     116                 :      38274 :                             nm->mkConst(true),
     117                 :            :                             false,
     118                 :            :                             false,
     119                 :            :                             true,
     120                 :            :                             nullptr);
     121                 :      38274 :     d_ppm->convertAndAssert(theory::InferenceId::INPUT,
     122                 :      38274 :                             nm->mkConst(false).notNode(),
     123                 :            :                             false,
     124                 :            :                             false,
     125                 :            :                             true,
     126                 :            :                             nullptr);
     127                 :            :   }
     128                 :      50644 : }
     129                 :            : 
     130                 :     100598 : PropEngine::~PropEngine() {
     131         [ +  - ]:      50299 :   Trace("prop") << "Destructing the PropEngine" << std::endl;
     132         [ +  - ]:      50299 :   delete d_cnfStream;
     133         [ +  - ]:      50299 :   delete d_satSolver;
     134         [ +  - ]:      50299 :   delete d_theoryProxy;
     135                 :     100598 : }
     136                 :            : 
     137                 :     459589 : TrustNode PropEngine::preprocess(TNode node,
     138                 :            :                                  std::vector<theory::SkolemLemma>& newLemmas)
     139                 :            : {
     140                 :     459589 :   return d_theoryProxy->preprocess(node, newLemmas);
     141                 :            : }
     142                 :            : 
     143                 :       1309 : TrustNode PropEngine::removeItes(TNode node,
     144                 :            :                                  std::vector<theory::SkolemLemma>& newLemmas)
     145                 :            : {
     146                 :       1309 :   return d_theoryProxy->removeItes(node, newLemmas);
     147                 :            : }
     148                 :            : 
     149                 :      52439 : void PropEngine::notifyTopLevelSubstitution(const Node& lhs,
     150                 :            :                                             const Node& rhs) const
     151                 :            : {
     152                 :      52439 :   d_theoryProxy->notifyTopLevelSubstitution(lhs, rhs);
     153         [ +  + ]:      52439 :   if (isOutputOn(OutputTag::SUBS))
     154                 :            :   {
     155                 :          2 :     Node eq = SkolemManager::getOriginalForm(lhs.eqNode(rhs));
     156                 :          2 :     output(OutputTag::SUBS) << "(substitution " << eq << ")" << std::endl;
     157                 :          2 :   }
     158 [ -  + ][ -  + ]:      52439 :   Assert(lhs.getType() == rhs.getType());
                 [ -  - ]
     159                 :      52439 : }
     160                 :            : 
     161                 :      64521 : void PropEngine::assertInputFormulas(
     162                 :            :     const std::vector<Node>& assertions,
     163                 :            :     std::unordered_map<size_t, Node>& skolemMap)
     164                 :            : {
     165 [ -  + ][ -  + ]:      64521 :   Assert(!d_inCheckSat) << "Sat solver in solve()!";
                 [ -  - ]
     166                 :            :   // now presolve with prop proof manager so proof logging is on. This must be
     167                 :            :   // done *before* the PropEngine checkSat call because when asserting formulas
     168                 :            :   // to the theory engine lemmas may already be generated.
     169         [ +  + ]:      64521 :   if (d_ppm != nullptr)
     170                 :            :   {
     171                 :      25836 :     d_ppm->presolve();
     172                 :            :   }
     173                 :      64521 :   d_theoryProxy->notifyInputFormulas(assertions, skolemMap);
     174                 :      64521 :   int64_t natomsPre = d_cnfStream->d_stats.d_numAtoms.get();
     175         [ +  + ]:     562668 :   for (const Node& node : assertions)
     176                 :            :   {
     177         [ +  - ]:     498163 :     Trace("prop") << "assertFormula(" << node << ")" << std::endl;
     178                 :     498179 :     assertInternal(theory::InferenceId::INPUT, node, false, false, true);
     179                 :            :   }
     180                 :      64505 :   int64_t natomsPost = d_cnfStream->d_stats.d_numAtoms.get();
     181 [ -  + ][ -  + ]:      64505 :   Assert(natomsPost >= natomsPre);
                 [ -  - ]
     182                 :      64505 :   d_stats.d_numInputAtoms += (natomsPost - natomsPre);
     183                 :      64505 : }
     184                 :            : 
     185                 :     896906 : void PropEngine::assertLemma(theory::InferenceId id,
     186                 :            :                              TrustNode tlemma,
     187                 :            :                              theory::LemmaProperty p)
     188                 :            : {
     189                 :     896906 :   bool removable = isLemmaPropertyRemovable(p);
     190                 :     896906 :   bool local = isLemmaPropertyLocal(p);
     191                 :     896906 :   bool inprocess = isLemmaPropertyInprocess(p);
     192                 :            : 
     193                 :            :   // call preprocessor
     194                 :     896906 :   std::vector<theory::SkolemLemma> ppLemmas;
     195                 :     896907 :   TrustNode tplemma = d_theoryProxy->preprocessLemma(tlemma, ppLemmas);
     196                 :            : 
     197                 :            :   // do final checks on the lemmas we are about to send
     198                 :     896905 :   if (d_env.isTheoryProofProducing()
     199 [ +  + ][ +  + ]:     896905 :       && options().proof.proofCheck == options::ProofCheckMode::EAGER)
                 [ +  + ]
     200                 :            :   {
     201 [ -  + ][ -  + ]:       2055 :     Assert(tplemma.getGenerator() != nullptr);
                 [ -  - ]
     202                 :            :     // ensure closed, make the proof node eagerly here to debug
     203                 :       2055 :     tplemma.debugCheckClosed(
     204                 :            :         options(), "te-proof-debug", "TheoryEngine::lemma");
     205         [ +  + ]:       2065 :     for (theory::SkolemLemma& lem : ppLemmas)
     206                 :            :     {
     207 [ -  + ][ -  + ]:         10 :       Assert(lem.d_lemma.getGenerator() != nullptr);
                 [ -  - ]
     208                 :         10 :       lem.d_lemma.debugCheckClosed(
     209                 :            :           options(), "te-proof-debug", "TheoryEngine::lemma_new");
     210                 :            :     }
     211                 :            :   }
     212                 :            : 
     213         [ -  + ]:     896905 :   if (TraceIsOn("te-lemma"))
     214                 :            :   {
     215                 :          0 :     Trace("te-lemma") << "Lemma, output: " << tplemma.getProven() << std::endl;
     216         [ -  - ]:          0 :     for (const theory::SkolemLemma& lem : ppLemmas)
     217                 :            :     {
     218                 :          0 :       Trace("te-lemma") << "Lemma, new lemma: " << lem.d_lemma.getProven()
     219                 :          0 :                         << " (skolem is " << lem.d_skolem << ")" << std::endl;
     220                 :            :     }
     221         [ -  - ]:          0 :     Trace("te-lemma") << "removable = " << removable << std::endl;
     222                 :            :   }
     223                 :            : 
     224                 :            :   // now, assert the lemmas
     225                 :     896905 :   assertLemmasInternal(id, tplemma, ppLemmas, removable, inprocess, local);
     226                 :     896906 : }
     227                 :            : 
     228                 :     931479 : void PropEngine::assertTrustedLemmaInternal(theory::InferenceId id,
     229                 :            :                                             TrustNode trn,
     230                 :            :                                             bool removable,
     231                 :            :                                             bool local)
     232                 :            : {
     233                 :     931479 :   Node node = trn.getNode();
     234         [ -  + ]:     931479 :   if (local)
     235                 :            :   {
     236                 :            :     // if local, filter here
     237         [ -  - ]:          0 :     if (d_localLemmas.find(node) != d_localLemmas.end())
     238                 :            :     {
     239                 :          0 :       return;
     240                 :            :     }
     241                 :          0 :     d_localLemmas.insert(node);
     242                 :            :   }
     243         [ +  - ]:     931479 :   Trace("prop::lemmas") << "assertLemma(" << node << ")" << std::endl;
     244         [ +  + ]:     931479 :   if (isOutputOn(OutputTag::LEMMAS))
     245                 :            :   {
     246                 :          1 :     output(OutputTag::LEMMAS) << "(lemma ";
     247                 :            :     // use original form of the lemma here
     248                 :          1 :     output(OutputTag::LEMMAS) << SkolemManager::getOriginalForm(node);
     249                 :          1 :     output(OutputTag::LEMMAS) << " :source " << id;
     250                 :          1 :     output(OutputTag::LEMMAS) << ")" << std::endl;
     251                 :            :   }
     252                 :     931479 :   bool negated = trn.getKind() == TrustNodeKind::CONFLICT;
     253                 :            :   // should have a proof generator if the theory engine is proof producing
     254 [ +  + ][ +  - ]:     931479 :   Assert(!d_env.isTheoryProofProducing() || trn.getGenerator() != nullptr);
         [ -  + ][ -  + ]
                 [ -  - ]
     255                 :            :   // if we are producing proofs for the SAT solver but not for theory engine,
     256                 :            :   // then we need to prevent the lemma of being added as an assumption (since
     257                 :            :   // the generator will be null). We use the default proof generator for lemmas.
     258         [ +  + ]:    1331102 :   if (d_env.isSatProofProducing() && !d_env.isTheoryProofProducing()
     259 [ +  + ][ +  + ]:    1331102 :       && !trn.getGenerator())
                 [ +  + ]
     260                 :            :   {
     261         [ +  + ]:         90 :     Node actualNode = negated ? node.notNode() : node;
     262                 :         90 :     d_theoryLemmaPg.addTrustedStep(actualNode, TrustId::THEORY_LEMMA, {}, {});
     263                 :         90 :     trn = TrustNode::mkReplaceGenTrustNode(trn, &d_theoryLemmaPg);
     264                 :         90 :   }
     265                 :     931479 :   assertInternal(id, node, negated, removable, false, trn.getGenerator());
     266         [ +  - ]:     931479 : }
     267                 :            : 
     268                 :    1429642 : void PropEngine::assertInternal(theory::InferenceId id,
     269                 :            :                                 TNode node,
     270                 :            :                                 bool negated,
     271                 :            :                                 bool removable,
     272                 :            :                                 bool input,
     273                 :            :                                 ProofGenerator* pg)
     274                 :            : {
     275                 :    1429642 :   bool addAssumption = false;
     276         [ +  + ]:    1429642 :   if (isProofEnabled())
     277                 :            :   {
     278                 :     831046 :     if (input
     279 [ +  + ][ +  + ]:     831046 :         && options().smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS)
                 [ +  + ]
     280                 :            :     {
     281                 :            :       // use the proof CNF stream to ensure the literal
     282                 :     116547 :       d_ppm->ensureLiteral(node);
     283                 :     116547 :       addAssumption = true;
     284                 :            :     }
     285                 :            :     else
     286                 :            :     {
     287                 :     714499 :       d_ppm->convertAndAssert(id, node, negated, removable, input, pg);
     288                 :            :     }
     289                 :            :   }
     290                 :     598596 :   else if (input
     291 [ +  + ][ -  + ]:     598596 :            && options().smt.unsatCoresMode
                 [ -  + ]
     292                 :            :                   == options::UnsatCoresMode::ASSUMPTIONS)
     293                 :            :   {
     294                 :          0 :     d_cnfStream->ensureLiteral(node);
     295                 :          0 :     addAssumption = true;
     296                 :            :   }
     297                 :            :   else
     298                 :            :   {
     299                 :     598612 :     d_cnfStream->convertAndAssert(node, removable, negated);
     300                 :            :   }
     301         [ +  + ]:    1429626 :   if (addAssumption)
     302                 :            :   {
     303         [ -  + ]:     116547 :     if (negated)
     304                 :            :     {
     305                 :          0 :       d_assumptions.push_back(node.notNode());
     306                 :            :     }
     307                 :            :     else
     308                 :            :     {
     309                 :     116547 :       d_assumptions.push_back(node);
     310                 :            :     }
     311                 :            :   }
     312                 :    1429626 : }
     313                 :            : 
     314                 :    1331618 : void PropEngine::assertLemmasInternal(
     315                 :            :     theory::InferenceId id,
     316                 :            :     TrustNode trn,
     317                 :            :     const std::vector<theory::SkolemLemma>& ppLemmas,
     318                 :            :     bool removable,
     319                 :            :     bool inprocess,
     320                 :            :     bool local)
     321                 :            : {
     322                 :            :   // notify skolem definitions first to ensure that the computation of
     323                 :            :   // when a literal contains a skolem is accurate in the calls below.
     324         [ +  - ]:    1331618 :   Trace("prop") << "Notify skolem definitions..." << std::endl;
     325         [ +  + ]:    1366192 :   for (const theory::SkolemLemma& lem : ppLemmas)
     326                 :            :   {
     327                 :      34574 :     d_theoryProxy->notifySkolemDefinition(lem.getProven(), lem.d_skolem);
     328                 :            :   }
     329                 :            :   // Assert to the SAT solver first
     330         [ +  - ]:    1331618 :   Trace("prop") << "Push to SAT..." << std::endl;
     331         [ +  + ]:    1331618 :   if (!trn.isNull())
     332                 :            :   {
     333                 :            :     // inprocess
     334                 :     896905 :     if (inprocess
     335 [ +  + ][ +  + ]:     896905 :         && options().theory.lemmaInprocess != options::LemmaInprocessMode::NONE)
                 [ +  + ]
     336                 :            :     {
     337                 :          3 :       trn = d_theoryProxy->inprocessLemma(trn);
     338                 :            :     }
     339                 :     896905 :     assertTrustedLemmaInternal(id, trn, removable, local);
     340                 :            :   }
     341         [ +  + ]:    1366192 :   for (const theory::SkolemLemma& lem : ppLemmas)
     342                 :            :   {
     343                 :      34574 :     assertTrustedLemmaInternal(theory::InferenceId::THEORY_PP_SKOLEM_LEM,
     344                 :      34574 :                                lem.d_lemma,
     345                 :            :                                removable,
     346                 :            :                                local);
     347                 :            :   }
     348                 :            :   // Note that this order is important for theories that send lemmas during
     349                 :            :   // preregistration, as it impacts the order in which lemmas are processed
     350                 :            :   // by default by the decision engine. In particular, sending to the SAT
     351                 :            :   // solver first means that lemmas sent during preregistration in response to
     352                 :            :   // the current lemma are processed after that lemma. This makes a difference
     353                 :            :   // e.g. for string reduction lemmas, where preregistration lemmas are
     354                 :            :   // introduced for skolems that appear in reductions. Moving the above
     355                 :            :   // block after the one below has mixed performance on SMT-LIB strings logics.
     356         [ +  - ]:    1331618 :   Trace("prop") << "Notify assertions..." << std::endl;
     357                 :            :   // also add to the decision engine, where notice we don't need proofs
     358         [ +  + ]:    1331618 :   if (!trn.isNull())
     359                 :            :   {
     360                 :            :     // notify the theory proxy of the lemma
     361                 :     896905 :     d_theoryProxy->notifyAssertion(trn.getProven(), TNode::null(), true, local);
     362                 :            :   }
     363         [ +  + ]:    1366192 :   for (const theory::SkolemLemma& lem : ppLemmas)
     364                 :            :   {
     365                 :      34574 :     d_theoryProxy->notifyAssertion(lem.getProven(), lem.d_skolem, true, local);
     366                 :            :   }
     367         [ +  - ]:    1331618 :   Trace("prop") << "Finish " << trn << std::endl;
     368                 :    1331618 : }
     369                 :            : 
     370                 :     266180 : void PropEngine::notifyExplainedPropagation(TrustNode texp)
     371                 :            : {
     372         [ +  + ]:     266180 :   if (d_ppm != nullptr)
     373                 :            :   {
     374                 :     154809 :     d_ppm->notifyExplainedPropagation(texp);
     375                 :            :   }
     376                 :     266180 : }
     377                 :            : 
     378                 :     167155 : void PropEngine::preferPhase(TNode n, bool phase)
     379                 :            : {
     380         [ +  - ]:     167155 :   Trace("prop") << "preferPhase(" << n << ", " << phase << ")" << std::endl;
     381                 :            : 
     382 [ -  + ][ -  + ]:     167155 :   Assert(n.getType().isBoolean());
                 [ -  - ]
     383                 :     167155 :   SatLiteral lit = d_cnfStream->getLiteral(n);
     384         [ +  + ]:     167155 :   d_satSolver->preferPhase(phase ? lit : ~lit);
     385                 :     167155 : }
     386                 :            : 
     387                 :     184082 : bool PropEngine::isDecision(Node lit) const {
     388 [ -  + ][ -  + ]:     184082 :   Assert(isSatLiteral(lit));
                 [ -  - ]
     389                 :     184082 :   return d_satSolver->isDecision(d_cnfStream->getLiteral(lit).getSatVariable());
     390                 :            : }
     391                 :            : 
     392                 :          0 : std::vector<Node> PropEngine::getPropDecisions() const
     393                 :            : {
     394                 :          0 :   std::vector<Node> decisions;
     395                 :          0 :   std::vector<SatLiteral> miniDecisions = d_satSolver->getDecisions();
     396         [ -  - ]:          0 :   for (SatLiteral d : miniDecisions)
     397                 :            :   {
     398                 :          0 :     decisions.push_back(d_cnfStream->getNode(d));
     399                 :            :   }
     400                 :          0 :   return decisions;
     401                 :          0 : }
     402                 :            : 
     403                 :          0 : std::vector<Node> PropEngine::getPropOrderHeap() const
     404                 :            : {
     405                 :          0 :   return d_satSolver->getOrderHeap();
     406                 :            : }
     407                 :            : 
     408                 :         16 : bool PropEngine::isFixed(TNode lit) const
     409                 :            : {
     410         [ +  - ]:         16 :   if (isSatLiteral(lit))
     411                 :            :   {
     412                 :         16 :     return d_satSolver->isFixed(d_cnfStream->getLiteral(lit).getSatVariable());
     413                 :            :   }
     414                 :          0 :   return false;
     415                 :            : }
     416                 :            : 
     417                 :          0 : void PropEngine::printSatisfyingAssignment(){
     418                 :            :   const CnfStream::NodeToLiteralMap& transCache =
     419                 :          0 :     d_cnfStream->getTranslationCache();
     420         [ -  - ]:          0 :   Trace("prop-value") << "Literal | Value | Expr" << std::endl
     421                 :          0 :                       << "----------------------------------------"
     422                 :          0 :                       << "-----------------" << std::endl;
     423                 :          0 :   for(CnfStream::NodeToLiteralMap::const_iterator i = transCache.begin(),
     424                 :          0 :       end = transCache.end();
     425         [ -  - ]:          0 :       i != end;
     426                 :          0 :       ++i) {
     427                 :          0 :     std::pair<Node, SatLiteral> curr = *i;
     428                 :          0 :     SatLiteral l = curr.second;
     429         [ -  - ]:          0 :     if(!l.isNegated()) {
     430                 :          0 :       Node n = curr.first;
     431                 :          0 :       SatValue value = d_satSolver->modelValue(l);
     432         [ -  - ]:          0 :       Trace("prop-value") << "'" << l << "' " << value << " " << n << std::endl;
     433                 :          0 :     }
     434                 :          0 :   }
     435                 :          0 : }
     436                 :       2016 : void PropEngine::outputIncompleteReason(UnknownExplanation uexp,
     437                 :            :                                         theory::IncompleteId iid)
     438                 :            : {
     439         [ +  + ]:       2016 :   if (isOutputOn(OutputTag::INCOMPLETE))
     440                 :            :   {
     441                 :          2 :     output(OutputTag::INCOMPLETE) << "(incomplete ";
     442                 :          2 :     output(OutputTag::INCOMPLETE) << uexp;
     443         [ +  - ]:          2 :     if (iid != theory::IncompleteId::UNKNOWN)
     444                 :            :     {
     445                 :          2 :       output(OutputTag::INCOMPLETE) << " " << iid;
     446                 :            :     }
     447                 :          2 :     output(OutputTag::INCOMPLETE) << ")" << std::endl;
     448                 :            :   }
     449                 :       2016 : }
     450                 :            : 
     451                 :      49384 : Result PropEngine::checkSat() {
     452 [ -  + ][ -  + ]:      49384 :   Assert(!d_inCheckSat) << "Sat solver in solve()!";
                 [ -  - ]
     453         [ +  - ]:      49384 :   Trace("prop") << "PropEngine::checkSat()" << std::endl;
     454                 :            : 
     455                 :            :   // Mark that we are in the checkSat
     456                 :      49384 :   ScopedBool scopedBool(d_inCheckSat);
     457                 :      49384 :   d_inCheckSat = true;
     458                 :            : 
     459         [ -  + ]:      49384 :   if (options().base.preprocessOnly)
     460                 :            :   {
     461                 :          0 :     outputIncompleteReason(UnknownExplanation::REQUIRES_FULL_CHECK);
     462                 :          0 :     return Result(Result::UNKNOWN, UnknownExplanation::REQUIRES_FULL_CHECK);
     463                 :            :   }
     464                 :            : 
     465                 :            :   // Note this currently ignores conflicts (a dangerous practice).
     466                 :      49384 :   d_theoryProxy->presolve();
     467                 :            : 
     468                 :            :   // add the assumptions
     469                 :      49384 :   std::vector<SatLiteral> assumptions;
     470         [ +  + ]:     177467 :   for (const Node& node : d_assumptions)
     471                 :            :   {
     472                 :     128083 :     assumptions.push_back(d_cnfStream->getLiteral(node));
     473                 :            :   }
     474                 :            : 
     475                 :            :   // now log preprocessing
     476         [ +  + ]:      49384 :   if (d_ppm != nullptr)
     477                 :            :   {
     478                 :      21095 :     d_ppm->logPreprocessing();
     479                 :            :   }
     480                 :            : 
     481                 :            :   // Reset the interrupted flag
     482                 :      49384 :   d_interrupted = false;
     483                 :            : 
     484                 :            :   // Check the problem
     485                 :            :   SatValue result;
     486         [ +  + ]:      49384 :   if (assumptions.empty())
     487                 :            :   {
     488                 :      40673 :     result = d_satSolver->solve();
     489                 :            :   }
     490                 :            :   else
     491                 :            :   {
     492                 :       8711 :     result = d_satSolver->solve(assumptions);
     493                 :            :   }
     494                 :            : 
     495                 :      49368 :   d_theoryProxy->postsolve(result);
     496                 :            : 
     497         [ +  + ]:      49368 :   if( result == SAT_VALUE_UNKNOWN ) {
     498                 :        236 :     ResourceManager* rm = resourceManager();
     499                 :        236 :     UnknownExplanation why = UnknownExplanation::INTERRUPTED;
     500         [ +  + ]:        236 :     if (rm->outOfTime())
     501                 :            :     {
     502                 :        234 :       why = UnknownExplanation::TIMEOUT;
     503                 :            :     }
     504         [ +  + ]:        236 :     if (rm->outOfResources())
     505                 :            :     {
     506                 :          2 :       why = UnknownExplanation::RESOURCEOUT;
     507                 :            :     }
     508                 :        236 :     outputIncompleteReason(why);
     509                 :        236 :     return Result(Result::UNKNOWN, why);
     510                 :            :   }
     511                 :            : 
     512                 :      49132 :   if( result == SAT_VALUE_TRUE && TraceIsOn("prop") ) {
     513                 :          0 :     printSatisfyingAssignment();
     514                 :            :   }
     515                 :            : 
     516         [ +  - ]:      49132 :   Trace("prop") << "PropEngine::checkSat() => " << result << std::endl;
     517         [ +  + ]:      49132 :   if (result == SAT_VALUE_TRUE)
     518                 :            :   {
     519         [ +  + ]:      23872 :     if (d_theoryProxy->isModelUnsound())
     520                 :            :     {
     521                 :       1765 :       outputIncompleteReason(UnknownExplanation::INCOMPLETE,
     522                 :       1765 :                              d_theoryProxy->getModelUnsoundId());
     523                 :       1765 :       return Result(Result::UNKNOWN, UnknownExplanation::INCOMPLETE);
     524                 :            :     }
     525                 :            :   }
     526         [ +  + ]:      25260 :   else if (d_theoryProxy->isRefutationUnsound())
     527                 :            :   {
     528                 :         15 :     outputIncompleteReason(UnknownExplanation::INCOMPLETE,
     529                 :         15 :                            d_theoryProxy->getRefutationUnsoundId());
     530                 :         15 :     return Result(Result::UNKNOWN, UnknownExplanation::INCOMPLETE);
     531                 :            :   }
     532                 :            : 
     533         [ +  + ]:      47352 :   if (d_ppm != nullptr)
     534                 :            :   {
     535                 :      20840 :     d_ppm->postsolve(result);
     536                 :            :   }
     537                 :            : 
     538         [ +  + ]:      47352 :   return Result(result == SAT_VALUE_TRUE ? Result::SAT : Result::UNSAT);
     539                 :      49400 : }
     540                 :            : 
     541                 :     107540 : Node PropEngine::getValue(TNode node) const
     542                 :            : {
     543 [ -  + ][ -  + ]:     107540 :   Assert(node.getType().isBoolean());
                 [ -  - ]
     544 [ -  + ][ -  + ]:     107540 :   Assert(d_cnfStream->hasLiteral(node));
                 [ -  - ]
     545                 :            : 
     546                 :     107540 :   SatLiteral lit = d_cnfStream->getLiteral(node);
     547                 :            : 
     548                 :     107540 :   SatValue v = d_satSolver->value(lit);
     549         [ +  + ]:     107540 :   if (v == SAT_VALUE_TRUE)
     550                 :            :   {
     551                 :     214056 :     return nodeManager()->mkConst(true);
     552                 :            :   }
     553         [ +  + ]:        512 :   else if (v == SAT_VALUE_FALSE)
     554                 :            :   {
     555                 :        924 :     return nodeManager()->mkConst(false);
     556                 :            :   }
     557                 :            :   else
     558                 :            :   {
     559 [ -  + ][ -  + ]:         50 :     Assert(v == SAT_VALUE_UNKNOWN);
                 [ -  - ]
     560                 :         50 :     return Node::null();
     561                 :            :   }
     562                 :            : }
     563                 :            : 
     564                 :   56737737 : bool PropEngine::isSatLiteral(TNode node) const
     565                 :            : {
     566                 :   56737737 :   return d_cnfStream->hasLiteral(node);
     567                 :            : }
     568                 :            : 
     569                 :   22502923 : bool PropEngine::hasValue(TNode node, bool& value) const
     570                 :            : {
     571 [ -  + ][ -  + ]:   22502923 :   Assert(node.getType().isBoolean());
                 [ -  - ]
     572                 :   22502923 :   Assert(d_cnfStream->hasLiteral(node)) << node;
     573                 :            : 
     574                 :   22502923 :   SatLiteral lit = d_cnfStream->getLiteral(node);
     575                 :            : 
     576                 :   22502923 :   SatValue v = d_satSolver->value(lit);
     577         [ +  + ]:   22502923 :   if (v == SAT_VALUE_TRUE)
     578                 :            :   {
     579                 :   13381351 :     value = true;
     580                 :   13381351 :     return true;
     581                 :            :   }
     582         [ +  + ]:    9121572 :   else if (v == SAT_VALUE_FALSE)
     583                 :            :   {
     584                 :     314179 :     value = false;
     585                 :     314179 :     return true;
     586                 :            :   }
     587                 :            :   else
     588                 :            :   {
     589 [ -  + ][ -  + ]:    8807393 :     Assert(v == SAT_VALUE_UNKNOWN);
                 [ -  - ]
     590                 :    8807393 :     return false;
     591                 :            :   }
     592                 :            : }
     593                 :            : 
     594                 :      34168 : void PropEngine::getBooleanVariables(std::vector<TNode>& outputVariables) const
     595                 :            : {
     596                 :      34168 :   d_cnfStream->getBooleanVariables(outputVariables);
     597                 :      34168 : }
     598                 :            : 
     599                 :     424005 : Node PropEngine::ensureLiteral(TNode n)
     600                 :            : {
     601                 :            :   // must preprocess
     602                 :     424005 :   Node preprocessed = getPreprocessedTerm(n);
     603         [ +  - ]:     848010 :   Trace("ensureLiteral") << "ensureLiteral preprocessed: " << preprocessed
     604                 :     424005 :                          << std::endl;
     605         [ +  + ]:     424005 :   if (isProofEnabled())
     606                 :            :   {
     607                 :     224704 :     d_ppm->ensureLiteral(preprocessed);
     608                 :            :   }
     609                 :            :   else
     610                 :            :   {
     611                 :     199301 :     d_cnfStream->ensureLiteral(preprocessed);
     612                 :            :   }
     613                 :     424005 :   return preprocessed;
     614                 :          0 : }
     615                 :            : 
     616                 :     434713 : Node PropEngine::getPreprocessedTerm(TNode n)
     617                 :            : {
     618                 :            :   // must preprocess
     619                 :     434713 :   std::vector<theory::SkolemLemma> newLemmas;
     620                 :     434713 :   TrustNode tpn = d_theoryProxy->preprocess(n, newLemmas);
     621                 :            :   // send lemmas corresponding to the skolems introduced by preprocessing n
     622                 :     434713 :   TrustNode trnNull;
     623                 :     434713 :   assertLemmasInternal(theory::InferenceId::THEORY_PP_SKOLEM_LEM,
     624                 :            :                        trnNull,
     625                 :            :                        newLemmas,
     626                 :            :                        false,
     627                 :            :                        false,
     628                 :            :                        false);
     629         [ +  + ]:     869426 :   return tpn.isNull() ? Node(n) : tpn.getNode();
     630                 :     434713 : }
     631                 :            : 
     632                 :       4481 : Node PropEngine::getPreprocessedTerm(TNode n,
     633                 :            :                                      std::vector<Node>& skAsserts,
     634                 :            :                                      std::vector<Node>& sks)
     635                 :            : {
     636                 :            :   // get the preprocessed form of the term
     637                 :       4481 :   Node pn = getPreprocessedTerm(n);
     638                 :            :   // initialize the set of skolems and assertions to process
     639                 :       4481 :   std::vector<Node> toProcessAsserts;
     640                 :       4481 :   std::vector<Node> toProcess;
     641                 :       4481 :   d_theoryProxy->getSkolems(pn, toProcessAsserts, toProcess);
     642                 :       4481 :   size_t index = 0;
     643                 :            :   // until fixed point is reached
     644         [ +  + ]:       8871 :   while (index < toProcess.size())
     645                 :            :   {
     646                 :       4390 :     Node ka = toProcessAsserts[index];
     647                 :       4390 :     Node k = toProcess[index];
     648                 :       4390 :     index++;
     649         [ +  + ]:       4390 :     if (std::find(sks.begin(), sks.end(), k) != sks.end())
     650                 :            :     {
     651                 :            :       // already added the skolem to the list
     652                 :       2308 :       continue;
     653                 :            :     }
     654                 :            :     // must preprocess lemmas as well
     655                 :       2082 :     Node kap = getPreprocessedTerm(ka);
     656                 :       2082 :     skAsserts.push_back(kap);
     657                 :       2082 :     sks.push_back(k);
     658                 :            :     // get the skolems in the preprocessed form of the lemma ka
     659                 :       2082 :     d_theoryProxy->getSkolems(kap, toProcessAsserts, toProcess);
     660 [ +  + ][ +  + ]:       6698 :   }
     661                 :            :   // return the preprocessed term
     662                 :       8962 :   return pn;
     663                 :       4481 : }
     664                 :            : 
     665                 :       8216 : void PropEngine::push()
     666                 :            : {
     667 [ -  + ][ -  + ]:       8216 :   Assert(!d_inCheckSat) << "Sat solver in solve()!";
                 [ -  - ]
     668                 :       8216 :   d_satSolver->push();
     669         [ +  - ]:       8216 :   Trace("prop") << "push()" << std::endl;
     670                 :       8216 : }
     671                 :            : 
     672                 :       8209 : void PropEngine::pop()
     673                 :            : {
     674 [ -  + ][ -  + ]:       8209 :   Assert(!d_inCheckSat) << "Sat solver in solve()!";
                 [ -  - ]
     675                 :       8209 :   d_satSolver->pop();
     676         [ +  - ]:       8209 :   Trace("prop") << "pop()" << std::endl;
     677                 :       8209 : }
     678                 :            : 
     679                 :      48551 : void PropEngine::resetTrail()
     680                 :            : {
     681                 :      48551 :   d_satSolver->resetTrail();
     682         [ +  - ]:      48551 :   Trace("prop") << "resetTrail()" << std::endl;
     683                 :      48551 : }
     684                 :            : 
     685                 :      49950 : uint32_t PropEngine::getAssertionLevel() const
     686                 :            : {
     687                 :      49950 :   return d_satSolver->getAssertionLevel();
     688                 :            : }
     689                 :            : 
     690                 :          0 : bool PropEngine::isRunning() const { return d_inCheckSat; }
     691                 :     123730 : void PropEngine::interrupt()
     692                 :            : {
     693         [ +  + ]:     123730 :   if (!d_inCheckSat)
     694                 :            :   {
     695                 :     122348 :     return;
     696                 :            :   }
     697                 :            : 
     698                 :       1382 :   d_interrupted = true;
     699                 :       1382 :   d_satSolver->interrupt();
     700         [ +  - ]:       1382 :   Trace("prop") << "interrupt()" << std::endl;
     701                 :            : }
     702                 :            : 
     703                 :       4994 : void PropEngine::spendResource(Resource r)
     704                 :            : {
     705                 :       4994 :   d_env.getResourceManager()->spendResource(r);
     706                 :       4994 : }
     707                 :            : 
     708                 :          0 : bool PropEngine::properExplanation(TNode node, TNode expl) const
     709                 :            : {
     710         [ -  - ]:          0 :   if (!d_cnfStream->hasLiteral(node))
     711                 :            :   {
     712         [ -  - ]:          0 :     Trace("properExplanation")
     713                 :          0 :         << "properExplanation(): Failing because node "
     714                 :          0 :         << "being explained doesn't have a SAT literal ?!" << std::endl
     715                 :          0 :         << "properExplanation(): The node is: " << node << std::endl;
     716                 :          0 :     return false;
     717                 :            :   }
     718                 :            : 
     719                 :          0 :   SatLiteral nodeLit = d_cnfStream->getLiteral(node);
     720                 :            : 
     721                 :          0 :   for (TNode::kinded_iterator i = expl.begin(Kind::AND),
     722                 :          0 :                               i_end = expl.end(Kind::AND);
     723         [ -  - ]:          0 :        i != i_end;
     724                 :          0 :        ++i)
     725                 :            :   {
     726         [ -  - ]:          0 :     if (!d_cnfStream->hasLiteral(*i))
     727                 :            :     {
     728         [ -  - ]:          0 :       Trace("properExplanation")
     729                 :          0 :           << "properExplanation(): Failing because one of explanation "
     730                 :          0 :           << "nodes doesn't have a SAT literal" << std::endl
     731                 :          0 :           << "properExplanation(): The explanation node is: " << *i
     732                 :          0 :           << std::endl;
     733                 :          0 :       return false;
     734                 :            :     }
     735                 :            : 
     736                 :          0 :     SatLiteral iLit = d_cnfStream->getLiteral(*i);
     737                 :            : 
     738         [ -  - ]:          0 :     if (iLit == nodeLit)
     739                 :            :     {
     740         [ -  - ]:          0 :       Trace("properExplanation")
     741                 :          0 :           << "properExplanation(): Failing because the node" << std::endl
     742                 :          0 :           << "properExplanation(): " << node << std::endl
     743                 :          0 :           << "properExplanation(): cannot be made to explain itself!"
     744                 :          0 :           << std::endl;
     745                 :          0 :       return false;
     746                 :            :     }
     747 [ -  - ][ -  - ]:          0 :   }
     748                 :            : 
     749                 :          0 :   return true;
     750                 :            : }
     751                 :            : 
     752                 :          7 : void PropEngine::checkProof(const context::CDList<Node>& assertions)
     753                 :            : {
     754         [ -  + ]:          7 :   if (!d_env.isSatProofProducing())
     755                 :            :   {
     756                 :          0 :     return;
     757                 :            :   }
     758                 :          7 :   return d_ppm->checkProof(assertions);
     759                 :            : }
     760                 :            : 
     761                 :       9443 : std::shared_ptr<ProofNode> PropEngine::getProof(bool connectCnf)
     762                 :            : {
     763         [ -  + ]:       9443 :   if (!d_env.isSatProofProducing())
     764                 :            :   {
     765                 :          0 :     return nullptr;
     766                 :            :   }
     767         [ +  - ]:      18886 :   Trace("sat-proof") << "PropEngine::getProof: getting proof with cnfStream's "
     768                 :          0 :                         "lazycdproof cxt lvl "
     769                 :       9443 :                      << userContext()->getLevel() << "\n";
     770                 :       9443 :   return d_ppm->getProof(connectCnf);
     771                 :            : }
     772                 :            : 
     773                 :          6 : std::vector<std::shared_ptr<ProofNode>> PropEngine::getProofLeaves(
     774                 :            :     modes::ProofComponent pc)
     775                 :            : {
     776                 :          6 :   return d_ppm->getProofLeaves(pc);
     777                 :            : }
     778                 :            : 
     779                 :    1853647 : bool PropEngine::isProofEnabled() const { return d_ppm != nullptr; }
     780                 :            : 
     781                 :       4401 : void PropEngine::getUnsatCore(std::vector<Node>& core)
     782                 :            : {
     783         [ +  + ]:       4401 :   if (options().smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS)
     784                 :            :   {
     785         [ +  - ]:       7772 :     Trace("unsat-core") << "PropEngine::getUnsatCore: via unsat assumptions"
     786                 :       3886 :                         << std::endl;
     787                 :       3886 :     std::vector<SatLiteral> unsat_assumptions;
     788                 :       3886 :     d_satSolver->getUnsatAssumptions(unsat_assumptions);
     789         [ +  + ]:      22799 :     for (const SatLiteral& lit : unsat_assumptions)
     790                 :            :     {
     791                 :      18913 :       core.push_back(d_cnfStream->getNode(lit));
     792                 :            :     }
     793                 :       3886 :   }
     794                 :            :   else
     795                 :            :   {
     796         [ +  - ]:        515 :     Trace("unsat-core") << "PropEngine::getUnsatCore: via proof" << std::endl;
     797                 :            :     // otherwise, it is just the free assumptions of the proof. Note that we
     798                 :            :     // need to connect the SAT proof to the CNF proof becuase we need the
     799                 :            :     // preprocessed input as leaves, not the clauses derived from them.
     800                 :        515 :     std::shared_ptr<ProofNode> pfn = getProof();
     801         [ +  - ]:        515 :     Trace("unsat-core") << "Proof is " << *pfn.get() << std::endl;
     802                 :        515 :     expr::getFreeAssumptions(pfn.get(), core);
     803         [ +  - ]:        515 :     Trace("unsat-core") << "Core is " << core << std::endl;
     804                 :        515 :   }
     805                 :       4401 : }
     806                 :            : 
     807                 :        458 : std::vector<Node> PropEngine::getUnsatCoreLemmas()
     808                 :            : {
     809 [ -  + ][ -  + ]:        458 :   Assert(d_env.isSatProofProducing());
                 [ -  - ]
     810                 :        458 :   std::vector<Node> lems = d_ppm->getUnsatCoreLemmas();
     811         [ -  + ]:        458 :   if (isOutputOn(OutputTag::UNSAT_CORE_LEMMAS))
     812                 :            :   {
     813                 :          0 :     output(OutputTag::UNSAT_CORE_LEMMAS)
     814                 :          0 :         << ";; unsat core lemmas start" << std::endl;
     815                 :          0 :     std::stringstream ss;
     816         [ -  - ]:          0 :     for (const Node& lem : lems)
     817                 :            :     {
     818                 :          0 :       output(OutputTag::UNSAT_CORE_LEMMAS) << "(unsat-core-lemma ";
     819                 :            :       output(OutputTag::UNSAT_CORE_LEMMAS)
     820                 :          0 :           << SkolemManager::getOriginalForm(lem);
     821                 :          0 :       uint64_t timestamp = 0;
     822                 :          0 :       theory::InferenceId id = d_ppm->getInferenceIdFor(lem, timestamp);
     823         [ -  - ]:          0 :       if (id != theory::InferenceId::NONE)
     824                 :            :       {
     825                 :          0 :         output(OutputTag::UNSAT_CORE_LEMMAS) << " :source " << id;
     826                 :            :       }
     827                 :          0 :       output(OutputTag::UNSAT_CORE_LEMMAS) << " :timestamp " << timestamp;
     828                 :          0 :       output(OutputTag::UNSAT_CORE_LEMMAS) << ")" << std::endl;
     829                 :            :       // for trace below
     830                 :          0 :       ss << id << ", " << timestamp << std::endl;
     831                 :            :     }
     832                 :          0 :     output(OutputTag::UNSAT_CORE_LEMMAS)
     833                 :          0 :         << ";; unsat core lemmas end" << std::endl;
     834                 :            :     // print in csv form for debugging
     835         [ -  - ]:          0 :     Trace("ocl-timestamp") << "TIMESTAMPS" << std::endl;
     836                 :          0 :     Trace("ocl-timestamp") << ss.str() << std::endl;
     837                 :          0 :   }
     838                 :        458 :   return lems;
     839                 :          0 : }
     840                 :            : 
     841                 :        648 : std::vector<Node> PropEngine::getLearnedZeroLevelLiterals(
     842                 :            :     modes::LearnedLitType ltype) const
     843                 :            : {
     844                 :        648 :   return d_theoryProxy->getLearnedZeroLevelLiterals(ltype);
     845                 :            : }
     846                 :            : 
     847                 :          7 : std::vector<Node> PropEngine::getLearnedZeroLevelLiteralsForRestart() const
     848                 :            : {
     849                 :          7 :   return d_theoryProxy->getLearnedZeroLevelLiteralsForRestart();
     850                 :            : }
     851                 :            : 
     852                 :          0 : modes::LearnedLitType PropEngine::getLiteralType(const Node& lit) const
     853                 :            : {
     854                 :          0 :   return d_theoryProxy->getLiteralType(lit);
     855                 :            : }
     856                 :            : 
     857                 :      50644 : PropEngine::Statistics::Statistics(StatisticsRegistry& sr)
     858                 :      50644 :     : d_numInputAtoms(sr.registerInt("prop::PropEngine::numInputAtoms"))
     859                 :            : {
     860                 :      50644 : }
     861                 :            : 
     862                 :            : }  // namespace prop
     863                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14