1 /********************* */
2 /*! \file cryptominisat.cpp
4 ** Top contributors (to current version):
5 ** Liana Hadarean, Mathias Preiner, Alex Ozdemir
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2021 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.\endverbatim
14 ** Implementation of the cryptominisat for cvc4 (bitvectors).
17 #ifdef CVC4_USE_CRYPTOMINISAT
19 #include "prop/cryptominisat.h"
21 #include "base/check.h"
23 #include <cryptominisat5/cryptominisat.h>
28 using CMSatVar
= unsigned;
33 CMSat::Lit
toInternalLit(SatLiteral lit
)
35 if (lit
== undefSatLiteral
)
37 return CMSat::lit_Undef
;
39 return CMSat::Lit(lit
.getSatVariable(), lit
.isNegated());
42 SatLiteral
toSatLiteral(CMSat::Lit lit
)
44 if (lit
== CMSat::lit_Undef
)
46 return undefSatLiteral
;
48 return SatLiteral(lit
.var(), lit
.sign());
51 SatValue
toSatLiteralValue(CMSat::lbool res
)
53 if (res
== CMSat::l_True
) return SAT_VALUE_TRUE
;
54 if (res
== CMSat::l_Undef
) return SAT_VALUE_UNKNOWN
;
55 Assert(res
== CMSat::l_False
);
56 return SAT_VALUE_FALSE
;
59 void toInternalClause(SatClause
& clause
,
60 std::vector
<CMSat::Lit
>& internal_clause
)
62 for (unsigned i
= 0; i
< clause
.size(); ++i
)
64 internal_clause
.push_back(toInternalLit(clause
[i
]));
66 Assert(clause
.size() == internal_clause
.size());
71 CryptoMinisatSolver::CryptoMinisatSolver(StatisticsRegistry
* registry
,
72 const std::string
& name
)
73 : d_solver(new CMSat::SATSolver()),
76 d_statistics(registry
, name
)
80 void CryptoMinisatSolver::init()
85 std::vector
<CMSat::Lit
> clause(1);
86 clause
[0] = CMSat::Lit(d_true
, false);
87 d_solver
->add_clause(clause
);
89 clause
[0] = CMSat::Lit(d_false
, true);
90 d_solver
->add_clause(clause
);
93 CryptoMinisatSolver::~CryptoMinisatSolver() {}
95 ClauseId
CryptoMinisatSolver::addXorClause(SatClause
& clause
,
99 Debug("sat::cryptominisat") << "Add xor clause " << clause
<<" = " << rhs
<< "\n";
102 Debug("sat::cryptominisat") << "Solver unsat: not adding clause.\n";
103 return ClauseIdError
;
106 ++(d_statistics
.d_xorClausesAdded
);
108 // ensure all sat literals have positive polarity by pushing
109 // the negation on the result
110 std::vector
<CMSatVar
> xor_clause
;
111 for (unsigned i
= 0; i
< clause
.size(); ++i
) {
112 xor_clause
.push_back(toInternalLit(clause
[i
]).var());
113 rhs
^= clause
[i
].isNegated();
115 bool res
= d_solver
->add_xor_clause(xor_clause
, rhs
);
117 return ClauseIdError
;
120 ClauseId
CryptoMinisatSolver::addClause(SatClause
& clause
, bool removable
){
121 Debug("sat::cryptominisat") << "Add clause " << clause
<<"\n";
124 Debug("sat::cryptominisat") << "Solver unsat: not adding clause.\n";
125 return ClauseIdError
;
128 ++(d_statistics
.d_clausesAdded
);
130 std::vector
<CMSat::Lit
> internal_clause
;
131 toInternalClause(clause
, internal_clause
);
132 bool nowOkay
= d_solver
->add_clause(internal_clause
);
135 freshId
= ClauseIdError
;
141 bool CryptoMinisatSolver::ok() const { return d_okay
; }
143 SatVariable
CryptoMinisatSolver::newVar(bool isTheoryAtom
, bool preRegister
, bool canErase
){
146 Assert(d_numVariables
== d_solver
->nVars());
147 return d_numVariables
- 1;
150 SatVariable
CryptoMinisatSolver::trueVar() {
154 SatVariable
CryptoMinisatSolver::falseVar() {
158 void CryptoMinisatSolver::markUnremovable(SatLiteral lit
) {
159 // cryptominisat supports dynamically adding back variables (?)
160 // so this is a no-op
164 void CryptoMinisatSolver::interrupt(){
165 d_solver
->interrupt_asap();
168 SatValue
CryptoMinisatSolver::solve(){
169 TimerStat::CodeTimer
codeTimer(d_statistics
.d_solveTime
);
170 ++d_statistics
.d_statCallsToSolve
;
171 return toSatLiteralValue(d_solver
->solve());
174 SatValue
CryptoMinisatSolver::solve(long unsigned int& resource
) {
175 // CMSat::SalverConf conf = d_solver->getConf();
176 Unreachable() << "Not sure how to set different limits for calls to solve in "
181 SatValue
CryptoMinisatSolver::solve(const std::vector
<SatLiteral
>& assumptions
)
183 TimerStat::CodeTimer
codeTimer(d_statistics
.d_solveTime
);
184 std::vector
<CMSat::Lit
> assumpts
;
185 for (const SatLiteral
& lit
: assumptions
)
187 assumpts
.push_back(toInternalLit(lit
));
189 ++d_statistics
.d_statCallsToSolve
;
190 return toSatLiteralValue(d_solver
->solve(&assumpts
));
193 void CryptoMinisatSolver::getUnsatAssumptions(
194 std::vector
<SatLiteral
>& assumptions
)
196 for (const CMSat::Lit
& lit
: d_solver
->get_conflict())
198 assumptions
.push_back(toSatLiteral(~lit
));
202 SatValue
CryptoMinisatSolver::value(SatLiteral l
){
203 const std::vector
<CMSat::lbool
> model
= d_solver
->get_model();
204 CMSatVar var
= l
.getSatVariable();
205 Assert(var
< model
.size());
206 CMSat::lbool value
= model
[var
];
207 return toSatLiteralValue(value
);
210 SatValue
CryptoMinisatSolver::modelValue(SatLiteral l
) { return value(l
); }
212 unsigned CryptoMinisatSolver::getAssertionLevel() const {
213 Unreachable() << "No interface to get assertion level in Cryptominisat";
217 // Satistics for CryptoMinisatSolver
219 CryptoMinisatSolver::Statistics::Statistics(StatisticsRegistry
* registry
,
220 const std::string
& prefix
) :
221 d_registry(registry
),
222 d_statCallsToSolve("theory::bv::"+prefix
+"::cryptominisat::calls_to_solve", 0),
223 d_xorClausesAdded("theory::bv::"+prefix
+"::cryptominisat::xor_clauses", 0),
224 d_clausesAdded("theory::bv::"+prefix
+"::cryptominisat::clauses", 0),
225 d_solveTime("theory::bv::"+prefix
+"::cryptominisat::solve_time"),
226 d_registerStats(!prefix
.empty())
228 if (!d_registerStats
)
231 d_registry
->registerStat(&d_statCallsToSolve
);
232 d_registry
->registerStat(&d_xorClausesAdded
);
233 d_registry
->registerStat(&d_clausesAdded
);
234 d_registry
->registerStat(&d_solveTime
);
237 CryptoMinisatSolver::Statistics::~Statistics() {
238 if (!d_registerStats
)
240 d_registry
->unregisterStat(&d_statCallsToSolve
);
241 d_registry
->unregisterStat(&d_xorClausesAdded
);
242 d_registry
->unregisterStat(&d_clausesAdded
);
243 d_registry
->unregisterStat(&d_solveTime
);