LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/prop/minisat - minisat.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 154 200 77.0 %
Date: 2026-04-11 10:14:16 Functions: 31 39 79.5 %
Branches: 51 100 51.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                 :            :  * SAT Solver.
      11                 :            :  *
      12                 :            :  * Implementation of the minisat interface for cvc5.
      13                 :            :  */
      14                 :            : 
      15                 :            : #include "prop/minisat/minisat.h"
      16                 :            : 
      17                 :            : #include "options/base_options.h"
      18                 :            : #include "options/decision_options.h"
      19                 :            : #include "options/proof_options.h"
      20                 :            : #include "options/prop_options.h"
      21                 :            : #include "options/smt_options.h"
      22                 :            : #include "proof/clause_id.h"
      23                 :            : #include "prop/minisat/simp/SimpSolver.h"
      24                 :            : #include "util/statistics_stats.h"
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : namespace prop {
      28                 :            : 
      29                 :            : //// DPllMinisatSatSolver
      30                 :            : 
      31                 :      51568 : MinisatSatSolver::MinisatSatSolver(Env& env, StatisticsRegistry& registry)
      32                 :            :     : EnvObj(env),
      33                 :      51568 :       d_minisat(nullptr),
      34                 :     103136 :       d_context(context()),
      35                 :      51568 :       d_assumptions(),
      36                 :     103136 :       d_statistics(registry)
      37                 :            : {
      38                 :      51568 : }
      39                 :            : 
      40                 :     102446 : MinisatSatSolver::~MinisatSatSolver()
      41                 :            : {
      42                 :      51223 :   d_statistics.deinit();
      43         [ +  - ]:      51223 :   delete d_minisat;
      44                 :     102446 : }
      45                 :            : 
      46                 :          0 : SatVariable MinisatSatSolver::toSatVariable(Minisat::Var var)
      47                 :            : {
      48         [ -  - ]:          0 :   if (var == var_Undef)
      49                 :            :   {
      50                 :          0 :     return undefSatVariable;
      51                 :            :   }
      52                 :          0 :   return SatVariable(var);
      53                 :            : }
      54                 :            : 
      55                 :   95435231 : Minisat::Lit MinisatSatSolver::toMinisatLit(SatLiteral lit)
      56                 :            : {
      57         [ +  + ]:   95435231 :   if (lit == undefSatLiteral)
      58                 :            :   {
      59                 :    4140388 :     return Minisat::lit_Undef;
      60                 :            :   }
      61                 :   91294843 :   return Minisat::mkLit(lit.getSatVariable(), lit.isNegated());
      62                 :            : }
      63                 :            : 
      64                 :  121730297 : SatLiteral MinisatSatSolver::toSatLiteral(Minisat::Lit lit)
      65                 :            : {
      66         [ -  + ]:  121730297 :   if (lit == Minisat::lit_Undef)
      67                 :            :   {
      68                 :          0 :     return undefSatLiteral;
      69                 :            :   }
      70                 :            : 
      71                 :  121730297 :   return SatLiteral(SatVariable(Minisat::var(lit)), Minisat::sign(lit));
      72                 :            : }
      73                 :            : 
      74                 :   50541749 : SatValue MinisatSatSolver::toSatLiteralValue(Minisat::lbool res)
      75                 :            : {
      76         [ +  + ]:   50541749 :   if (res == (Minisat::lbool((uint8_t)0))) return SAT_VALUE_TRUE;
      77         [ +  + ]:   27748702 :   if (res == (Minisat::lbool((uint8_t)2))) return SAT_VALUE_UNKNOWN;
      78 [ -  + ][ -  + ]:    7324508 :   Assert(res == (Minisat::lbool((uint8_t)1)));
                 [ -  - ]
      79                 :    7324508 :   return SAT_VALUE_FALSE;
      80                 :            : }
      81                 :            : 
      82                 :          0 : Minisat::lbool MinisatSatSolver::toMinisatlbool(SatValue val)
      83                 :            : {
      84         [ -  - ]:          0 :   if (val == SAT_VALUE_TRUE) return Minisat::lbool((uint8_t)0);
      85         [ -  - ]:          0 :   if (val == SAT_VALUE_UNKNOWN) return Minisat::lbool((uint8_t)2);
      86                 :          0 :   Assert(val == SAT_VALUE_FALSE);
      87                 :          0 :   return Minisat::lbool((uint8_t)1);
      88                 :            : }
      89                 :            : 
      90                 :            : /*bool MinisatSatSolver::tobool(SatValue val)
      91                 :            : {
      92                 :            :   if(val == SAT_VALUE_TRUE) return true;
      93                 :            :   Assert(val == SAT_VALUE_FALSE);
      94                 :            :   return false;
      95                 :            :   }*/
      96                 :            : 
      97                 :   17444423 : void MinisatSatSolver::toMinisatClause(
      98                 :            :     const SatClause& clause, Minisat::vec<Minisat::Lit>& minisat_clause)
      99                 :            : {
     100         [ +  + ]:   52699121 :   for (const SatLiteral i : clause)
     101                 :            :   {
     102                 :   35254698 :     minisat_clause.push(toMinisatLit(i));
     103                 :            :   }
     104 [ -  + ][ -  + ]:   17444423 :   Assert(clause.size() == static_cast<unsigned>(minisat_clause.size()));
                 [ -  - ]
     105                 :   17444423 : }
     106                 :            : 
     107                 :     904297 : void MinisatSatSolver::toSatClause(const Minisat::Clause& clause,
     108                 :            :                                    SatClause& sat_clause)
     109                 :            : {
     110         [ +  + ]:   39553516 :   for (int i = 0; i < clause.size(); ++i)
     111                 :            :   {
     112                 :   38649219 :     sat_clause.push_back(toSatLiteral(clause[i]));
     113                 :            :   }
     114 [ -  + ][ -  + ]:     904297 :   Assert((unsigned)clause.size() == sat_clause.size());
                 [ -  - ]
     115                 :     904297 : }
     116                 :            : 
     117                 :      51568 : void MinisatSatSolver::initialize(TheoryProxy* theoryProxy)
     118                 :            : {
     119         [ +  + ]:      51568 :   if (options().decision.decisionMode != options::DecisionMode::INTERNAL)
     120                 :            :   {
     121                 :      41243 :     verbose(1) << "minisat: Incremental solving is forced on (to avoid "
     122                 :            :                   "variable elimination)"
     123                 :      41243 :                << " unless using internal decision strategy." << std::endl;
     124                 :            :   }
     125                 :            : 
     126                 :            :   // Create the solver
     127                 :      51568 :   d_minisat =
     128                 :            :       new Minisat::SimpSolver(d_env,
     129                 :            :                               theoryProxy,
     130                 :      51568 :                               context(),
     131                 :      51568 :                               options().base.incrementalSolving
     132 [ +  + ][ +  + ]:      51568 :                                   || options().decision.decisionMode
     133                 :      51568 :                                          != options::DecisionMode::INTERNAL);
     134                 :            : 
     135                 :      51568 :   d_statistics.init(d_minisat);
     136                 :      51568 :   initialize();
     137                 :      51568 : }
     138                 :            : 
     139                 :      51568 : void MinisatSatSolver::initialize() {}
     140                 :            : 
     141                 :      19900 : void MinisatSatSolver::attachProofManager(PropPfManager* ppm)
     142                 :            : {
     143                 :      19900 :   d_minisat->attachProofManager(ppm);
     144                 :      19900 : }
     145                 :            : 
     146                 :            : // Like initialize() above, but called just before each search when in
     147                 :            : // incremental mode
     148                 :      50291 : void MinisatSatSolver::setupOptions()
     149                 :            : {
     150                 :            :   // Copy options from cvc5 options structure into minisat, as appropriate
     151                 :            : 
     152                 :            :   // Set up the verbosity
     153         [ +  + ]:      50291 :   d_minisat->verbosity = (options().base.verbosity > 0) ? 1 : -1;
     154                 :            : 
     155                 :            :   // Set up the random decision parameters
     156                 :      50291 :   d_minisat->random_var_freq = options().prop.satRandomFreq;
     157                 :            :   // If 0, we use whatever we like (here, the Minisat default seed)
     158         [ +  + ]:      50291 :   if (options().prop.satRandomSeed != 0)
     159                 :            :   {
     160                 :          2 :     d_minisat->random_seed = double(options().prop.satRandomSeed);
     161                 :            :   }
     162                 :            : 
     163                 :            :   // Give access to all possible options in the sat solver
     164                 :      50291 :   d_minisat->var_decay = options().prop.satVarDecay;
     165                 :      50291 :   d_minisat->clause_decay = options().prop.satClauseDecay;
     166                 :      50291 :   d_minisat->restart_first = options().prop.satRestartFirst;
     167                 :      50291 :   d_minisat->restart_inc = options().prop.satRestartInc;
     168                 :      50291 : }
     169                 :            : 
     170                 :    5943405 : ClauseId MinisatSatSolver::addClause(const SatClause& clause, bool removable)
     171                 :            : {
     172                 :    5943405 :   Minisat::vec<Minisat::Lit> minisat_clause;
     173                 :    5943405 :   toMinisatClause(clause, minisat_clause);
     174                 :    5943405 :   ClauseId clause_id = ClauseIdError;
     175                 :            :   // FIXME: This relies on the invariant that when ok() is false
     176                 :            :   // the SAT solver does not add the clause (which is what Minisat currently
     177                 :            :   // does)
     178         [ +  + ]:    5943405 :   if (!ok())
     179                 :            :   {
     180                 :       7060 :     return ClauseIdUndef;
     181                 :            :   }
     182                 :    5936345 :   d_minisat->addClause(minisat_clause, removable, clause_id);
     183                 :            :   // FIXME: to be deleted when we kill old proof code for unsat cores
     184 [ +  + ][ +  - ]:    5936345 :   Assert(!options().smt.produceUnsatCores || options().smt.produceProofs
         [ -  + ][ -  - ]
         [ -  + ][ -  + ]
                 [ -  - ]
     185                 :            :          || clause_id != ClauseIdError);
     186                 :    5936345 :   return clause_id;
     187                 :    5943405 : }
     188                 :            : 
     189                 :    2152826 : SatVariable MinisatSatSolver::newVar(bool isTheoryAtom, bool canErase)
     190                 :            : {
     191                 :    2152826 :   return d_minisat->newVar(true, true, isTheoryAtom, canErase);
     192                 :            : }
     193                 :            : 
     194                 :          0 : SatValue MinisatSatSolver::solve(unsigned long& resource)
     195                 :            : {
     196         [ -  - ]:          0 :   Trace("limit") << "SatSolver::solve(): have limit of " << resource
     197                 :          0 :                  << " conflicts" << std::endl;
     198                 :          0 :   setupOptions();
     199         [ -  - ]:          0 :   if (resource == 0)
     200                 :            :   {
     201                 :          0 :     d_minisat->budgetOff();
     202                 :            :   }
     203                 :            :   else
     204                 :            :   {
     205                 :          0 :     d_minisat->setConfBudget(resource);
     206                 :            :   }
     207                 :          0 :   Minisat::vec<Minisat::Lit> empty;
     208                 :          0 :   unsigned long conflictsBefore =
     209                 :          0 :       d_minisat->conflicts + d_minisat->resources_consumed;
     210                 :          0 :   SatValue result = toSatLiteralValue(d_minisat->solveLimited(empty));
     211                 :          0 :   d_minisat->clearInterrupt();
     212                 :          0 :   resource =
     213                 :          0 :       d_minisat->conflicts + d_minisat->resources_consumed - conflictsBefore;
     214         [ -  - ]:          0 :   Trace("limit") << "SatSolver::solve(): it took " << resource << " conflicts"
     215                 :          0 :                  << std::endl;
     216                 :          0 :   return result;
     217                 :          0 : }
     218                 :            : 
     219                 :      41338 : SatValue MinisatSatSolver::solve()
     220                 :            : {
     221                 :      41338 :   setupOptions();
     222                 :      41338 :   d_minisat->budgetOff();
     223                 :      41338 :   SatValue result = toSatLiteralValue(d_minisat->solve());
     224                 :      41322 :   d_minisat->clearInterrupt();
     225                 :      41322 :   return result;
     226                 :            : }
     227                 :            : 
     228                 :       8953 : SatValue MinisatSatSolver::solve(const std::vector<SatLiteral>& assumptions)
     229                 :            : {
     230                 :       8953 :   setupOptions();
     231                 :       8953 :   d_minisat->budgetOff();
     232                 :            : 
     233                 :       8953 :   d_assumptions.clear();
     234                 :       8953 :   Minisat::vec<Minisat::Lit> assumps;
     235                 :            : 
     236         [ +  + ]:     137904 :   for (const SatLiteral& lit : assumptions)
     237                 :            :   {
     238                 :     128951 :     Minisat::Lit mlit = toMinisatLit(lit);
     239                 :     128951 :     assumps.push(mlit);
     240                 :     128951 :     d_assumptions.emplace(lit);
     241                 :            :   }
     242                 :            : 
     243                 :       8953 :   SatValue result = toSatLiteralValue(d_minisat->solve(assumps));
     244                 :       8953 :   d_minisat->clearInterrupt();
     245                 :       8953 :   return result;
     246                 :       8953 : }
     247                 :            : 
     248                 :       3895 : void MinisatSatSolver::getUnsatAssumptions(
     249                 :            :     std::vector<SatLiteral>& unsat_assumptions)
     250                 :            : {
     251         [ +  + ]:      22812 :   for (size_t i = 0, size = d_minisat->d_conflict.size(); i < size; ++i)
     252                 :            :   {
     253                 :      18917 :     Minisat::Lit mlit = d_minisat->d_conflict[i];
     254                 :      18917 :     SatLiteral lit = ~toSatLiteral(mlit);
     255         [ +  - ]:      18917 :     if (d_assumptions.find(lit) != d_assumptions.end())
     256                 :            :     {
     257                 :      18917 :       unsat_assumptions.push_back(lit);
     258                 :            :     }
     259                 :            :   }
     260                 :       3895 : }
     261                 :            : 
     262                 :    5943405 : bool MinisatSatSolver::ok() const { return d_minisat->okay(); }
     263                 :            : 
     264                 :       6121 : void MinisatSatSolver::interrupt() { d_minisat->interrupt(); }
     265                 :            : 
     266                 :   50491474 : SatValue MinisatSatSolver::value(SatLiteral l)
     267                 :            : {
     268                 :   50491474 :   return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
     269                 :            : }
     270                 :            : 
     271                 :          0 : SatValue MinisatSatSolver::modelValue(SatLiteral l)
     272                 :            : {
     273                 :          0 :   return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
     274                 :            : }
     275                 :            : 
     276                 :     168122 : void MinisatSatSolver::preferPhase(SatLiteral lit)
     277                 :            : {
     278 [ -  + ][ -  + ]:     168122 :   Assert(!d_minisat->rnd_pol);
                 [ -  - ]
     279         [ +  - ]:     336244 :   Trace("minisat") << "preferPhase(" << lit << ")"
     280                 :     168122 :                    << " " << lit.getSatVariable() << " " << lit.isNegated()
     281                 :     168122 :                    << std::endl;
     282                 :     168122 :   SatVariable v = lit.getSatVariable();
     283                 :     168122 :   d_minisat->freezePolarity(v, lit.isNegated());
     284                 :     168122 : }
     285                 :            : 
     286                 :     193453 : bool MinisatSatSolver::isDecision(SatVariable decn) const
     287                 :            : {
     288                 :     193453 :   return d_minisat->isDecision(decn);
     289                 :            : }
     290                 :            : 
     291                 :         16 : bool MinisatSatSolver::isFixed(SatVariable var) const
     292                 :            : {
     293         [ +  + ]:         32 :   return d_minisat->intro_level(var) == 0 && d_minisat->user_level(var) == 0
     294 [ +  - ][ +  + ]:         32 :          && d_minisat->level(var) == 0;
     295                 :            : }
     296                 :            : 
     297                 :          0 : std::vector<SatLiteral> MinisatSatSolver::getDecisions() const
     298                 :            : {
     299                 :          0 :   std::vector<SatLiteral> decisions;
     300                 :            :   const Minisat::vec<Minisat::Lit>& miniDecisions =
     301                 :          0 :       d_minisat->getMiniSatAssignmentTrail();
     302         [ -  - ]:          0 :   for (size_t i = 0, ndec = miniDecisions.size(); i < ndec; ++i)
     303                 :            :   {
     304                 :          0 :     auto satLit = toSatLiteral(miniDecisions[i]);
     305         [ -  - ]:          0 :     if (isDecision(satLit.getSatVariable()))
     306                 :            :     {
     307                 :          0 :       decisions.push_back(satLit);
     308                 :            :     }
     309                 :            :   }
     310                 :          0 :   return decisions;
     311                 :          0 : }
     312                 :            : 
     313                 :          0 : std::vector<Node> MinisatSatSolver::getOrderHeap() const
     314                 :            : {
     315                 :          0 :   return d_minisat->getMiniSatOrderHeap();
     316                 :            : }
     317                 :            : 
     318                 :       9413 : std::shared_ptr<ProofNode> MinisatSatSolver::getProof()
     319                 :            : {
     320 [ -  + ][ -  + ]:       9413 :   Assert(d_env.isSatProofProducing());
                 [ -  - ]
     321                 :       9413 :   return d_minisat->getProof();
     322                 :            : }
     323                 :            : 
     324                 :            : /** Incremental interface */
     325                 :            : 
     326                 :      50874 : uint32_t MinisatSatSolver::getAssertionLevel() const
     327                 :            : {
     328                 :      50874 :   return d_minisat->getAssertionLevel();
     329                 :            : }
     330                 :            : 
     331                 :       8192 : void MinisatSatSolver::push() { d_minisat->push(); }
     332                 :            : 
     333                 :       8185 : void MinisatSatSolver::pop() { d_minisat->pop(); }
     334                 :            : 
     335                 :      49450 : void MinisatSatSolver::resetTrail() { d_minisat->resetTrail(); }
     336                 :            : 
     337                 :            : /// Statistics for MinisatSatSolver
     338                 :            : 
     339                 :      51568 : MinisatSatSolver::Statistics::Statistics(StatisticsRegistry& registry)
     340                 :      51568 :     : d_statStarts(registry.registerReference<int64_t>("sat::starts")),
     341                 :      51568 :       d_statDecisions(registry.registerReference<int64_t>("sat::decisions")),
     342                 :      51568 :       d_statRndDecisions(
     343                 :            :           registry.registerReference<int64_t>("sat::rnd_decisions")),
     344                 :      51568 :       d_statPropagations(
     345                 :            :           registry.registerReference<int64_t>("sat::propagations")),
     346                 :      51568 :       d_statConflicts(registry.registerReference<int64_t>("sat::conflicts")),
     347                 :      51568 :       d_statClausesLiterals(
     348                 :            :           registry.registerReference<int64_t>("sat::clauses_literals")),
     349                 :      51568 :       d_statLearntsLiterals(
     350                 :            :           registry.registerReference<int64_t>("sat::learnts_literals")),
     351                 :      51568 :       d_statMaxLiterals(
     352                 :            :           registry.registerReference<int64_t>("sat::max_literals")),
     353                 :      51568 :       d_statTotLiterals(
     354                 :            :           registry.registerReference<int64_t>("sat::tot_literals"))
     355                 :            : {
     356                 :      51568 : }
     357                 :            : 
     358                 :      51568 : void MinisatSatSolver::Statistics::init(Minisat::SimpSolver* minisat)
     359                 :            : {
     360                 :      51568 :   d_statStarts.set(minisat->starts);
     361                 :      51568 :   d_statDecisions.set(minisat->decisions);
     362                 :      51568 :   d_statRndDecisions.set(minisat->rnd_decisions);
     363                 :      51568 :   d_statPropagations.set(minisat->propagations);
     364                 :      51568 :   d_statConflicts.set(minisat->conflicts);
     365                 :      51568 :   d_statClausesLiterals.set(minisat->clauses_literals);
     366                 :      51568 :   d_statLearntsLiterals.set(minisat->learnts_literals);
     367                 :      51568 :   d_statMaxLiterals.set(minisat->max_literals);
     368                 :      51568 :   d_statTotLiterals.set(minisat->tot_literals);
     369                 :      51568 : }
     370                 :      51223 : void MinisatSatSolver::Statistics::deinit()
     371                 :            : {
     372                 :      51223 :   d_statStarts.reset();
     373                 :      51223 :   d_statDecisions.reset();
     374                 :      51223 :   d_statRndDecisions.reset();
     375                 :      51223 :   d_statPropagations.reset();
     376                 :      51223 :   d_statConflicts.reset();
     377                 :      51223 :   d_statClausesLiterals.reset();
     378                 :      51223 :   d_statLearntsLiterals.reset();
     379                 :      51223 :   d_statMaxLiterals.reset();
     380                 :      51223 :   d_statTotLiterals.reset();
     381                 :      51223 : }
     382                 :            : 
     383                 :            : }  // namespace prop
     384                 :            : }  // namespace cvc5::internal
     385                 :            : 
     386                 :            : namespace cvc5::internal {
     387                 :            : template <>
     388                 :          0 : prop::SatLiteral toSatLiteral<cvc5::internal::Minisat::Solver>(
     389                 :            :     Minisat::Solver::TLit lit)
     390                 :            : {
     391                 :          0 :   return prop::MinisatSatSolver::toSatLiteral(lit);
     392                 :            : }
     393                 :            : 
     394                 :            : template <>
     395                 :          0 : void toSatClause<cvc5::internal::Minisat::Solver>(
     396                 :            :     const cvc5::internal::Minisat::Solver::TClause& minisat_cl,
     397                 :            :     prop::SatClause& sat_cl)
     398                 :            : {
     399                 :          0 :   prop::MinisatSatSolver::toSatClause(minisat_cl, sat_cl);
     400                 :          0 : }
     401                 :            : 
     402                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14