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: 318 401 79.3 %
Date: 2025-01-06 12:36:47 Functions: 42 48 87.5 %
Branches: 176 314 56.1 %

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

Generated by: LCOV version 1.14