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: 148 188 78.7 %
Date: 2024-12-21 13:21:27 Functions: 29 37 78.4 %
Branches: 51 98 52.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Gereon Kremer, Liana Hadarean, Dejan Jovanovic
       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                 :            :  * SAT Solver.
      14                 :            :  *
      15                 :            :  * Implementation of the minisat interface for cvc5.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "prop/minisat/minisat.h"
      19                 :            : 
      20                 :            : #include "options/base_options.h"
      21                 :            : #include "options/decision_options.h"
      22                 :            : #include "options/proof_options.h"
      23                 :            : #include "options/prop_options.h"
      24                 :            : #include "options/smt_options.h"
      25                 :            : #include "proof/clause_id.h"
      26                 :            : #include "prop/minisat/simp/SimpSolver.h"
      27                 :            : #include "util/statistics_stats.h"
      28                 :            : 
      29                 :            : namespace cvc5::internal {
      30                 :            : namespace prop {
      31                 :            : 
      32                 :            : //// DPllMinisatSatSolver
      33                 :            : 
      34                 :      50572 : MinisatSatSolver::MinisatSatSolver(Env& env, StatisticsRegistry& registry)
      35                 :            :     : EnvObj(env),
      36                 :            :       d_minisat(NULL),
      37                 :            :       d_context(NULL),
      38                 :            :       d_assumptions(),
      39                 :      50572 :       d_statistics(registry)
      40                 :      50572 : {}
      41                 :            : 
      42                 :     100632 : MinisatSatSolver::~MinisatSatSolver()
      43                 :            : {
      44                 :      50316 :   d_statistics.deinit();
      45         [ +  - ]:      50316 :   delete d_minisat;
      46                 :     100632 : }
      47                 :            : 
      48                 :          0 : SatVariable MinisatSatSolver::toSatVariable(Minisat::Var var) {
      49         [ -  - ]:          0 :   if (var == var_Undef) {
      50                 :          0 :     return undefSatVariable;
      51                 :            :   }
      52                 :          0 :   return SatVariable(var);
      53                 :            : }
      54                 :            : 
      55                 :  114794000 : Minisat::Lit MinisatSatSolver::toMinisatLit(SatLiteral lit) {
      56         [ +  + ]:  114794000 :   if (lit == undefSatLiteral) {
      57                 :    3546980 :     return Minisat::lit_Undef;
      58                 :            :   }
      59                 :  111247000 :   return Minisat::mkLit(lit.getSatVariable(), lit.isNegated());
      60                 :            : }
      61                 :            : 
      62                 :  174932000 : SatLiteral MinisatSatSolver::toSatLiteral(Minisat::Lit lit) {
      63         [ -  + ]:  174932000 :   if (lit == Minisat::lit_Undef) {
      64                 :          0 :     return undefSatLiteral;
      65                 :            :   }
      66                 :            : 
      67                 :  174932000 :   return SatLiteral(SatVariable(Minisat::var(lit)),
      68                 :  349863000 :                     Minisat::sign(lit));
      69                 :            : }
      70                 :            : 
      71                 :   67066900 : SatValue MinisatSatSolver::toSatLiteralValue(Minisat::lbool res) {
      72         [ +  + ]:   67066900 :   if(res == (Minisat::lbool((uint8_t)0))) return SAT_VALUE_TRUE;
      73         [ +  + ]:   36700100 :   if(res == (Minisat::lbool((uint8_t)2))) return SAT_VALUE_UNKNOWN;
      74 [ -  + ][ -  + ]:    6836380 :   Assert(res == (Minisat::lbool((uint8_t)1)));
                 [ -  - ]
      75                 :    6836380 :   return SAT_VALUE_FALSE;
      76                 :            : }
      77                 :            : 
      78                 :          0 : Minisat::lbool MinisatSatSolver::toMinisatlbool(SatValue val)
      79                 :            : {
      80         [ -  - ]:          0 :   if(val == SAT_VALUE_TRUE) return Minisat::lbool((uint8_t)0);
      81         [ -  - ]:          0 :   if(val == SAT_VALUE_UNKNOWN) return Minisat::lbool((uint8_t)2);
      82                 :          0 :   Assert(val == SAT_VALUE_FALSE);
      83                 :          0 :   return Minisat::lbool((uint8_t)1);
      84                 :            : }
      85                 :            : 
      86                 :            : /*bool MinisatSatSolver::tobool(SatValue val)
      87                 :            : {
      88                 :            :   if(val == SAT_VALUE_TRUE) return true;
      89                 :            :   Assert(val == SAT_VALUE_FALSE);
      90                 :            :   return false;
      91                 :            :   }*/
      92                 :            : 
      93                 :   22420900 : void MinisatSatSolver::toMinisatClause(SatClause& clause,
      94                 :            :                                            Minisat::vec<Minisat::Lit>& minisat_clause) {
      95         [ +  + ]:   55717900 :   for (unsigned i = 0; i < clause.size(); ++i) {
      96                 :   33297000 :     minisat_clause.push(toMinisatLit(clause[i]));
      97                 :            :   }
      98 [ -  + ][ -  + ]:   22420900 :   Assert(clause.size() == (unsigned)minisat_clause.size());
                 [ -  - ]
      99                 :   22420900 : }
     100                 :            : 
     101                 :     984543 : void MinisatSatSolver::toSatClause(const Minisat::Clause& clause,
     102                 :            :                                        SatClause& sat_clause) {
     103         [ +  + ]:   39970500 :   for (int i = 0; i < clause.size(); ++i) {
     104                 :   38986000 :     sat_clause.push_back(toSatLiteral(clause[i]));
     105                 :            :   }
     106 [ -  + ][ -  + ]:     984543 :   Assert((unsigned)clause.size() == sat_clause.size());
                 [ -  - ]
     107                 :     984543 : }
     108                 :            : 
     109                 :      50572 : void MinisatSatSolver::initialize(context::Context* context,
     110                 :            :                                   TheoryProxy* theoryProxy,
     111                 :            :                                   context::UserContext* userContext,
     112                 :            :                                   PropPfManager* ppm)
     113                 :            : {
     114                 :      50572 :   d_context = context;
     115                 :            : 
     116         [ +  + ]:      50572 :   if (options().decision.decisionMode != options::DecisionMode::INTERNAL)
     117                 :            :   {
     118                 :      40211 :     verbose(1) << "minisat: Incremental solving is forced on (to avoid "
     119                 :            :                   "variable elimination)"
     120                 :      40211 :                << " unless using internal decision strategy." << std::endl;
     121                 :            :   }
     122                 :            : 
     123                 :            :   // Create the solver
     124                 :      50572 :   d_minisat =
     125                 :            :       new Minisat::SimpSolver(d_env,
     126                 :            :                               theoryProxy,
     127                 :            :                               d_context,
     128                 :            :                               userContext,
     129                 :            :                               ppm,
     130                 :      50572 :                               options().base.incrementalSolving
     131 [ +  + ][ +  + ]:      50572 :                                   || options().decision.decisionMode
     132                 :      50572 :                                          != options::DecisionMode::INTERNAL);
     133                 :            : 
     134                 :      50572 :   d_statistics.init(d_minisat);
     135                 :            : 
     136                 :            :   // Since the prop engine asserts "true" to the CNF stream regardless of what
     137                 :            :   // is in the input (see PropEngine::finishInit), if a real "true" assertion is
     138                 :            :   // made to the SAT solver via the Proof CNF stream, that would be ignored,
     139                 :            :   // since there is already "true" in the CNF stream. Thus the SAT proof would
     140                 :            :   // not have True as an assumption, which can lead to issues when building its
     141                 :            :   // proof. To prevent this problem, we track it directly here.
     142                 :      50572 :   SatProofManager* spfm = d_minisat->getProofManager();
     143         [ +  + ]:      50572 :   if (spfm)
     144                 :            :   {
     145                 :      10881 :     NodeManager* nm = nodeManager();
     146                 :      21762 :     spfm->registerSatAssumptions({nm->mkConst(true)});
     147                 :            :   }
     148                 :      50572 : }
     149                 :            : 
     150                 :            : // Like initialize() above, but called just before each search when in
     151                 :            : // incremental mode
     152                 :      49986 : void MinisatSatSolver::setupOptions() {
     153                 :            :   // Copy options from cvc5 options structure into minisat, as appropriate
     154                 :            : 
     155                 :            :   // Set up the verbosity
     156         [ +  + ]:      49986 :   d_minisat->verbosity = (options().base.verbosity > 0) ? 1 : -1;
     157                 :            : 
     158                 :            :   // Set up the random decision parameters
     159                 :      49986 :   d_minisat->random_var_freq = options().prop.satRandomFreq;
     160                 :            :   // If 0, we use whatever we like (here, the Minisat default seed)
     161         [ +  + ]:      49986 :   if (options().prop.satRandomSeed != 0)
     162                 :            :   {
     163                 :          2 :     d_minisat->random_seed = double(options().prop.satRandomSeed);
     164                 :            :   }
     165                 :            : 
     166                 :            :   // Give access to all possible options in the sat solver
     167                 :      49986 :   d_minisat->var_decay = options().prop.satVarDecay;
     168                 :      49986 :   d_minisat->clause_decay = options().prop.satClauseDecay;
     169                 :      49986 :   d_minisat->restart_first = options().prop.satRestartFirst;
     170                 :      49986 :   d_minisat->restart_inc = options().prop.satRestartInc;
     171                 :      49986 : }
     172                 :            : 
     173                 :    6258670 : ClauseId MinisatSatSolver::addClause(SatClause& clause, bool removable)
     174                 :            : {
     175                 :   12517300 :   Minisat::vec<Minisat::Lit> minisat_clause;
     176                 :    6258670 :   toMinisatClause(clause, minisat_clause);
     177                 :    6258670 :   ClauseId clause_id = ClauseIdError;
     178                 :            :   // FIXME: This relies on the invariant that when ok() is false
     179                 :            :   // the SAT solver does not add the clause (which is what Minisat currently does)
     180         [ +  + ]:    6258670 :   if (!ok()) {
     181                 :       8574 :     return ClauseIdUndef;
     182                 :            :   }
     183                 :    6250100 :   d_minisat->addClause(minisat_clause, removable, clause_id);
     184                 :            :   // FIXME: to be deleted when we kill old proof code for unsat cores
     185 [ +  + ][ -  + ]:    6250100 :   Assert(!options().smt.produceUnsatCores || options().smt.produceProofs
         [ -  - ][ -  + ]
                 [ -  - ]
     186                 :            :          || clause_id != ClauseIdError);
     187                 :    6250100 :   return clause_id;
     188                 :            : }
     189                 :            : 
     190                 :    2230920 : SatVariable MinisatSatSolver::newVar(bool isTheoryAtom, bool canErase)
     191                 :            : {
     192                 :    2230920 :   return d_minisat->newVar(true, true, isTheoryAtom, canErase);
     193                 :            : }
     194                 :            : 
     195                 :          0 : SatValue MinisatSatSolver::solve(unsigned long& resource) {
     196         [ -  - ]:          0 :   Trace("limit") << "SatSolver::solve(): have limit of " << resource << " conflicts" << std::endl;
     197                 :          0 :   setupOptions();
     198         [ -  - ]:          0 :   if(resource == 0) {
     199                 :          0 :     d_minisat->budgetOff();
     200                 :            :   } else {
     201                 :          0 :     d_minisat->setConfBudget(resource);
     202                 :            :   }
     203                 :          0 :   Minisat::vec<Minisat::Lit> empty;
     204                 :          0 :   unsigned long conflictsBefore = d_minisat->conflicts + d_minisat->resources_consumed;
     205                 :          0 :   SatValue result = toSatLiteralValue(d_minisat->solveLimited(empty));
     206                 :          0 :   d_minisat->clearInterrupt();
     207                 :          0 :   resource = d_minisat->conflicts + d_minisat->resources_consumed - conflictsBefore;
     208         [ -  - ]:          0 :   Trace("limit") << "SatSolver::solve(): it took " << resource << " conflicts" << std::endl;
     209                 :          0 :   return result;
     210                 :            : }
     211                 :            : 
     212                 :      40996 : SatValue MinisatSatSolver::solve() {
     213                 :      40996 :   setupOptions();
     214                 :      40996 :   d_minisat->budgetOff();
     215                 :      40996 :   SatValue result = toSatLiteralValue(d_minisat->solve());
     216                 :      40983 :   d_minisat->clearInterrupt();
     217                 :      40983 :   return result;
     218                 :            : }
     219                 :            : 
     220                 :       8990 : SatValue MinisatSatSolver::solve(const std::vector<SatLiteral>& assumptions)
     221                 :            : {
     222                 :       8990 :   setupOptions();
     223                 :       8990 :   d_minisat->budgetOff();
     224                 :            : 
     225                 :       8990 :   d_assumptions.clear();
     226                 :       8990 :   Minisat::vec<Minisat::Lit> assumps;
     227                 :            : 
     228         [ +  + ]:     157968 :   for (const SatLiteral& lit : assumptions)
     229                 :            :   {
     230                 :     148978 :     Minisat::Lit mlit = toMinisatLit(lit);
     231                 :     148978 :     assumps.push(mlit);
     232                 :     148978 :     d_assumptions.emplace(lit);
     233                 :            :   }
     234                 :            : 
     235                 :       8990 :   SatValue result = toSatLiteralValue(d_minisat->solve(assumps));
     236                 :       8990 :   d_minisat->clearInterrupt();
     237                 :      17980 :   return result;
     238                 :            : }
     239                 :            : 
     240                 :       4242 : void MinisatSatSolver::getUnsatAssumptions(
     241                 :            :     std::vector<SatLiteral>& unsat_assumptions)
     242                 :            : {
     243         [ +  + ]:      24295 :   for (size_t i = 0, size = d_minisat->d_conflict.size(); i < size; ++i)
     244                 :            :   {
     245                 :      20053 :     Minisat::Lit mlit = d_minisat->d_conflict[i];
     246                 :      20053 :     SatLiteral lit = ~toSatLiteral(mlit);
     247         [ +  - ]:      20053 :     if (d_assumptions.find(lit) != d_assumptions.end())
     248                 :            :     {
     249                 :      20053 :       unsat_assumptions.push_back(lit);
     250                 :            :     }
     251                 :            :   }
     252                 :       4242 : }
     253                 :            : 
     254                 :    6258670 : bool MinisatSatSolver::ok() const {
     255                 :    6258670 :   return d_minisat->okay();
     256                 :            : }
     257                 :            : 
     258                 :      20152 : void MinisatSatSolver::interrupt() {
     259                 :      20152 :   d_minisat->interrupt();
     260                 :      20152 : }
     261                 :            : 
     262                 :   67016900 : SatValue MinisatSatSolver::value(SatLiteral l) {
     263                 :   67016900 :   return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
     264                 :            : }
     265                 :            : 
     266                 :          0 : SatValue MinisatSatSolver::modelValue(SatLiteral l){
     267                 :          0 :   return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
     268                 :            : }
     269                 :            : 
     270                 :     167894 : void MinisatSatSolver::preferPhase(SatLiteral lit)
     271                 :            : {
     272 [ -  + ][ -  + ]:     167894 :   Assert(!d_minisat->rnd_pol);
                 [ -  - ]
     273         [ +  - ]:     335788 :   Trace("minisat") << "preferPhase(" << lit << ")"
     274                 :     167894 :                    << " " << lit.getSatVariable() << " " << lit.isNegated()
     275                 :     167894 :                    << std::endl;
     276                 :     167894 :   SatVariable v = lit.getSatVariable();
     277                 :     167894 :   d_minisat->freezePolarity(v, lit.isNegated());
     278                 :     167894 : }
     279                 :            : 
     280                 :     193757 : bool MinisatSatSolver::isDecision(SatVariable decn) const {
     281                 :     193757 :   return d_minisat->isDecision( decn );
     282                 :            : }
     283                 :            : 
     284                 :         16 : bool MinisatSatSolver::isFixed(SatVariable var) const
     285                 :            : {
     286         [ +  + ]:         32 :   return d_minisat->intro_level(var) == 0 && d_minisat->user_level(var) == 0
     287 [ +  - ][ +  + ]:         32 :          && d_minisat->level(var) == 0;
     288                 :            : }
     289                 :            : 
     290                 :          0 : std::vector<SatLiteral> MinisatSatSolver::getDecisions() const
     291                 :            : {
     292                 :          0 :   std::vector<SatLiteral> decisions;
     293                 :            :   const Minisat::vec<Minisat::Lit>& miniDecisions =
     294                 :          0 :       d_minisat->getMiniSatAssignmentTrail();
     295         [ -  - ]:          0 :   for (size_t i = 0, ndec = miniDecisions.size(); i < ndec; ++i)
     296                 :            :   {
     297                 :          0 :     auto satLit = toSatLiteral(miniDecisions[i]);
     298         [ -  - ]:          0 :     if (isDecision(satLit.getSatVariable()))
     299                 :            :     {
     300                 :          0 :       decisions.push_back(satLit);
     301                 :            :     }
     302                 :            :   }
     303                 :          0 :   return decisions;
     304                 :            : }
     305                 :            : 
     306                 :          0 : std::vector<Node> MinisatSatSolver::getOrderHeap() const
     307                 :            : {
     308                 :          0 :   return d_minisat->getMiniSatOrderHeap();
     309                 :            : }
     310                 :            : 
     311                 :       9830 : std::shared_ptr<ProofNode> MinisatSatSolver::getProof()
     312                 :            : {
     313 [ -  + ][ -  + ]:       9830 :   Assert(d_env.isSatProofProducing());
                 [ -  - ]
     314                 :       9830 :   return d_minisat->getProof();
     315                 :            : }
     316                 :            : 
     317                 :            : /** Incremental interface */
     318                 :            : 
     319                 :      49968 : uint32_t MinisatSatSolver::getAssertionLevel() const
     320                 :            : {
     321                 :      49968 :   return d_minisat->getAssertionLevel();
     322                 :            : }
     323                 :            : 
     324                 :       9025 : void MinisatSatSolver::push() {
     325                 :       9025 :   d_minisat->push();
     326                 :       9025 : }
     327                 :            : 
     328                 :       9020 : void MinisatSatSolver::pop() {
     329                 :       9020 :   d_minisat->pop();
     330                 :       9020 : }
     331                 :            : 
     332                 :      49204 : void MinisatSatSolver::resetTrail() { d_minisat->resetTrail(); }
     333                 :            : 
     334                 :            : /// Statistics for MinisatSatSolver
     335                 :            : 
     336                 :      50572 : MinisatSatSolver::Statistics::Statistics(StatisticsRegistry& registry)
     337                 :            :     : d_statStarts(registry.registerReference<int64_t>("sat::starts")),
     338                 :            :       d_statDecisions(registry.registerReference<int64_t>("sat::decisions")),
     339                 :            :       d_statRndDecisions(
     340                 :            :           registry.registerReference<int64_t>("sat::rnd_decisions")),
     341                 :            :       d_statPropagations(
     342                 :            :           registry.registerReference<int64_t>("sat::propagations")),
     343                 :            :       d_statConflicts(registry.registerReference<int64_t>("sat::conflicts")),
     344                 :            :       d_statClausesLiterals(
     345                 :            :           registry.registerReference<int64_t>("sat::clauses_literals")),
     346                 :            :       d_statLearntsLiterals(
     347                 :            :           registry.registerReference<int64_t>("sat::learnts_literals")),
     348                 :            :       d_statMaxLiterals(
     349                 :            :           registry.registerReference<int64_t>("sat::max_literals")),
     350                 :            :       d_statTotLiterals(
     351                 :      50572 :           registry.registerReference<int64_t>("sat::tot_literals"))
     352                 :            : {
     353                 :      50572 : }
     354                 :            : 
     355                 :      50572 : void MinisatSatSolver::Statistics::init(Minisat::SimpSolver* minisat){
     356                 :      50572 :   d_statStarts.set(minisat->starts);
     357                 :      50572 :   d_statDecisions.set(minisat->decisions);
     358                 :      50572 :   d_statRndDecisions.set(minisat->rnd_decisions);
     359                 :      50572 :   d_statPropagations.set(minisat->propagations);
     360                 :      50572 :   d_statConflicts.set(minisat->conflicts);
     361                 :      50572 :   d_statClausesLiterals.set(minisat->clauses_literals);
     362                 :      50572 :   d_statLearntsLiterals.set(minisat->learnts_literals);
     363                 :      50572 :   d_statMaxLiterals.set(minisat->max_literals);
     364                 :      50572 :   d_statTotLiterals.set(minisat->tot_literals);
     365                 :      50572 : }
     366                 :      50316 : void MinisatSatSolver::Statistics::deinit()
     367                 :            : {
     368                 :      50316 :   d_statStarts.reset();
     369                 :      50316 :   d_statDecisions.reset();
     370                 :      50316 :   d_statRndDecisions.reset();
     371                 :      50316 :   d_statPropagations.reset();
     372                 :      50316 :   d_statConflicts.reset();
     373                 :      50316 :   d_statClausesLiterals.reset();
     374                 :      50316 :   d_statLearntsLiterals.reset();
     375                 :      50316 :   d_statMaxLiterals.reset();
     376                 :      50316 :   d_statTotLiterals.reset();
     377                 :      50316 : }
     378                 :            : 
     379                 :            : }  // namespace prop
     380                 :            : }  // namespace cvc5::internal
     381                 :            : 
     382                 :            : namespace cvc5::internal {
     383                 :            : template <>
     384                 :          0 : prop::SatLiteral toSatLiteral<cvc5::internal::Minisat::Solver>(Minisat::Solver::TLit lit)
     385                 :            : {
     386                 :          0 :   return prop::MinisatSatSolver::toSatLiteral(lit);
     387                 :            : }
     388                 :            : 
     389                 :            : template <>
     390                 :          0 : void toSatClause<cvc5::internal::Minisat::Solver>(
     391                 :            :     const cvc5::internal::Minisat::Solver::TClause& minisat_cl, prop::SatClause& sat_cl)
     392                 :            : {
     393                 :          0 :   prop::MinisatSatSolver::toSatClause(minisat_cl, sat_cl);
     394                 :          0 : }
     395                 :            : 
     396                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14