1 |
|
/****************************************************************************************[Solver.h] |
2 |
|
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson |
3 |
|
Copyright (c) 2007-2010, Niklas Sorensson |
4 |
|
|
5 |
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and |
6 |
|
associated documentation files (the "Software"), to deal in the Software without restriction, |
7 |
|
including without limitation the rights to use, copy, modify, merge, publish, distribute, |
8 |
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
9 |
|
furnished to do so, subject to the following conditions: |
10 |
|
|
11 |
|
The above copyright notice and this permission notice shall be included in all copies or |
12 |
|
substantial portions of the Software. |
13 |
|
|
14 |
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT |
15 |
|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
16 |
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
17 |
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT |
18 |
|
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
19 |
|
**************************************************************************************************/ |
20 |
|
|
21 |
|
#ifndef Minisat_Solver_h |
22 |
|
#define Minisat_Solver_h |
23 |
|
|
24 |
|
#include <iosfwd> |
25 |
|
|
26 |
|
#include "base/check.h" |
27 |
|
#include "base/output.h" |
28 |
|
#include "context/context.h" |
29 |
|
#include "cvc5_private.h" |
30 |
|
#include "proof/clause_id.h" |
31 |
|
#include "proof/proof_node_manager.h" |
32 |
|
#include "prop/minisat/core/SolverTypes.h" |
33 |
|
#include "prop/minisat/mtl/Alg.h" |
34 |
|
#include "prop/minisat/mtl/Heap.h" |
35 |
|
#include "prop/minisat/mtl/Vec.h" |
36 |
|
#include "prop/minisat/utils/Options.h" |
37 |
|
#include "prop/sat_proof_manager.h" |
38 |
|
#include "theory/theory.h" |
39 |
|
#include "util/resource_manager.h" |
40 |
|
|
41 |
|
namespace cvc5 { |
42 |
|
|
43 |
|
namespace prop { |
44 |
|
class PropEngine; |
45 |
|
class TheoryProxy; |
46 |
|
} // namespace prop |
47 |
|
} // namespace cvc5 |
48 |
|
|
49 |
|
namespace cvc5 { |
50 |
|
namespace Minisat { |
51 |
|
|
52 |
|
//================================================================================================= |
53 |
|
// Solver -- the main class: |
54 |
|
|
55 |
|
class Solver { |
56 |
|
/** The only two cvc5 entry points to the private solver data */ |
57 |
|
friend class cvc5::prop::PropEngine; |
58 |
|
friend class cvc5::prop::TheoryProxy; |
59 |
|
friend class cvc5::prop::SatProofManager; |
60 |
|
|
61 |
|
public: |
62 |
|
static CRef TCRef_Undef; |
63 |
|
static CRef TCRef_Lazy; |
64 |
|
|
65 |
|
typedef Var TVar; |
66 |
|
typedef Lit TLit; |
67 |
|
typedef Clause TClause; |
68 |
|
typedef CRef TCRef; |
69 |
|
typedef vec<Lit> TLitVec; |
70 |
|
|
71 |
|
protected: |
72 |
|
/** The pointer to the proxy that provides interfaces to the SMT engine */ |
73 |
|
cvc5::prop::TheoryProxy* d_proxy; |
74 |
|
|
75 |
|
/** The context from the SMT solver */ |
76 |
|
cvc5::context::Context* d_context; |
77 |
|
|
78 |
|
/** The current assertion level (user) */ |
79 |
|
int assertionLevel; |
80 |
|
|
81 |
|
/** Variable representing true */ |
82 |
|
Var varTrue; |
83 |
|
|
84 |
|
/** Variable representing false */ |
85 |
|
Var varFalse; |
86 |
|
|
87 |
|
/** The resolution proof manager */ |
88 |
|
std::unique_ptr<cvc5::prop::SatProofManager> d_pfManager; |
89 |
|
|
90 |
|
public: |
91 |
|
/** Returns the current user assertion level */ |
92 |
18939 |
int getAssertionLevel() const { return assertionLevel; } |
93 |
|
|
94 |
|
protected: |
95 |
|
/** Do we allow incremental solving */ |
96 |
|
bool d_enable_incremental; |
97 |
|
|
98 |
|
/** Literals propagated by lemmas */ |
99 |
|
vec<vec<Lit> > lemmas; |
100 |
|
|
101 |
|
/** Is the lemma removable */ |
102 |
|
vec<bool> lemmas_removable; |
103 |
|
|
104 |
|
/** Do a another check if FULL_EFFORT was the last one */ |
105 |
|
bool recheck; |
106 |
|
|
107 |
|
/** Shrink 'cs' to contain only clauses below given level */ |
108 |
|
void removeClausesAboveLevel(vec<CRef>& cs, int level); |
109 |
|
|
110 |
|
/** True if we are currently solving. */ |
111 |
|
bool minisat_busy; |
112 |
|
|
113 |
|
// Information about registration of variables |
114 |
|
struct VarIntroInfo |
115 |
|
{ |
116 |
|
Var d_var; |
117 |
|
int d_level; |
118 |
601881 |
VarIntroInfo(Var var, int level) : d_var(var), d_level(level) {} |
119 |
|
}; |
120 |
|
|
121 |
|
/** Variables to re-register with theory solvers on backtracks */ |
122 |
|
vec<VarIntroInfo> variables_to_register; |
123 |
|
|
124 |
|
/** Keep only newSize variables */ |
125 |
|
void resizeVars(int newSize); |
126 |
|
|
127 |
|
public: |
128 |
|
|
129 |
|
// Constructor/Destructor: |
130 |
|
// |
131 |
|
Solver(cvc5::prop::TheoryProxy* proxy, |
132 |
|
cvc5::context::Context* context, |
133 |
|
cvc5::context::UserContext* userContext, |
134 |
|
ProofNodeManager* pnm, |
135 |
|
bool enableIncremental = false); |
136 |
|
virtual ~Solver(); |
137 |
|
|
138 |
|
// Problem specification: |
139 |
|
// |
140 |
|
Var newVar(bool polarity = true, |
141 |
|
bool dvar = true, |
142 |
|
bool isTheoryAtom = false, |
143 |
|
bool preRegister = false, |
144 |
|
bool canErase = true); // Add a new variable with parameters |
145 |
|
// specifying variable mode. |
146 |
9994 |
Var trueVar() const { return varTrue; } |
147 |
9994 |
Var falseVar() const { return varFalse; } |
148 |
|
|
149 |
|
/** Retrive the SAT proof manager */ |
150 |
|
cvc5::prop::SatProofManager* getProofManager(); |
151 |
|
|
152 |
|
/** Retrive the refutation proof */ |
153 |
|
std::shared_ptr<ProofNode> getProof(); |
154 |
|
|
155 |
|
/** Is proof enabled? */ |
156 |
|
bool isProofEnabled() const; |
157 |
|
|
158 |
|
/** |
159 |
|
* Checks whether we need a proof. |
160 |
|
* |
161 |
|
* SAT proofs are not required for assumption-based unsat cores. |
162 |
|
*/ |
163 |
|
bool needProof() const; |
164 |
|
|
165 |
|
// Less than for literals in a lemma |
166 |
|
struct lemma_lt |
167 |
|
{ |
168 |
|
Solver& d_solver; |
169 |
1701963 |
lemma_lt(Solver& solver) : d_solver(solver) {} |
170 |
19590834 |
bool operator()(Lit x, Lit y) |
171 |
|
{ |
172 |
19590834 |
lbool x_value = d_solver.value(x); |
173 |
19590834 |
lbool y_value = d_solver.value(y); |
174 |
|
// Two unassigned literals are sorted arbitrarily |
175 |
19590834 |
if (x_value == l_Undef && y_value == l_Undef) |
176 |
|
{ |
177 |
10504344 |
return x < y; |
178 |
|
} |
179 |
|
// Unassigned literals are put to front |
180 |
9086490 |
if (x_value == l_Undef) return true; |
181 |
8478862 |
if (y_value == l_Undef) return false; |
182 |
|
// Literals of the same value are sorted by decreasing levels |
183 |
8334588 |
if (x_value == y_value) |
184 |
|
{ |
185 |
8085627 |
return d_solver.trail_index(var(x)) > d_solver.trail_index(var(y)); |
186 |
|
} |
187 |
|
else |
188 |
|
{ |
189 |
|
// True literals go up front |
190 |
248961 |
if (x_value == l_True) |
191 |
|
{ |
192 |
39682 |
return true; |
193 |
|
} |
194 |
|
else |
195 |
|
{ |
196 |
209279 |
return false; |
197 |
|
} |
198 |
|
} |
199 |
|
} |
200 |
|
}; |
201 |
|
|
202 |
|
// cvc5 context push/pop |
203 |
|
void push(); |
204 |
|
void pop(); |
205 |
|
|
206 |
|
/* |
207 |
|
* Reset the decisions in the DPLL(T) SAT solver at the current assertion |
208 |
|
* level. |
209 |
|
*/ |
210 |
|
void resetTrail(); |
211 |
|
// addClause returns the ClauseId corresponding to the clause added in the |
212 |
|
// reference parameter id. |
213 |
|
bool addClause(const vec<Lit>& ps, |
214 |
|
bool removable, |
215 |
|
ClauseId& id); // Add a clause to the solver. |
216 |
|
bool addEmptyClause( |
217 |
|
bool removable); // Add the empty clause, making the solver contradictory. |
218 |
|
bool addClause(Lit p, |
219 |
|
bool removable, |
220 |
|
ClauseId& id); // Add a unit clause to the solver. |
221 |
|
bool addClause(Lit p, |
222 |
|
Lit q, |
223 |
|
bool removable, |
224 |
|
ClauseId& id); // Add a binary clause to the solver. |
225 |
|
bool addClause(Lit p, |
226 |
|
Lit q, |
227 |
|
Lit r, |
228 |
|
bool removable, |
229 |
|
ClauseId& id); // Add a ternary clause to the solver. |
230 |
|
bool addClause_( |
231 |
|
vec<Lit>& ps, |
232 |
|
bool removable, |
233 |
|
ClauseId& id); // Add a clause to the solver without making superflous |
234 |
|
// internal copy. Will change the passed vector 'ps'. |
235 |
|
|
236 |
|
// Solving: |
237 |
|
// |
238 |
|
bool simplify(); // Removes already satisfied clauses. |
239 |
|
lbool solve(const vec<Lit>& assumps); // Search for a model that respects a |
240 |
|
// given set of assumptions. |
241 |
|
lbool solveLimited( |
242 |
|
const vec<Lit>& assumps); // Search for a model that respects a given set |
243 |
|
// of assumptions (With resource constraints). |
244 |
|
lbool solve(); // Search without assumptions. |
245 |
|
lbool solve(Lit p); // Search for a model that respects a single assumption. |
246 |
|
lbool solve(Lit p, |
247 |
|
Lit q); // Search for a model that respects two assumptions. |
248 |
|
lbool solve(Lit p, |
249 |
|
Lit q, |
250 |
|
Lit r); // Search for a model that respects three assumptions. |
251 |
|
bool okay() const; // FALSE means solver is in a conflicting state |
252 |
|
|
253 |
|
void toDimacs(); |
254 |
|
void toDimacs(FILE* f, |
255 |
|
const vec<Lit>& assumps); // Write CNF to file in DIMACS-format. |
256 |
|
void toDimacs(const char* file, const vec<Lit>& assumps); |
257 |
|
void toDimacs(FILE* f, Clause& c, vec<Var>& map, Var& max); |
258 |
|
|
259 |
|
// Convenience versions of 'toDimacs()': |
260 |
|
void toDimacs(const char* file); |
261 |
|
void toDimacs(const char* file, Lit p); |
262 |
|
void toDimacs(const char* file, Lit p, Lit q); |
263 |
|
void toDimacs(const char* file, Lit p, Lit q, Lit r); |
264 |
|
|
265 |
|
// Variable mode: |
266 |
|
// |
267 |
|
void setPolarity( |
268 |
|
Var v, bool b); // Declare which polarity the decision heuristic should |
269 |
|
// use for a variable. Requires mode 'polarity_user'. |
270 |
|
void freezePolarity( |
271 |
|
Var v, |
272 |
|
bool b); // Declare which polarity the decision heuristic MUST ALWAYS use |
273 |
|
// for a variable. Requires mode 'polarity_user'. |
274 |
|
void setDecisionVar(Var v, |
275 |
|
bool b); // Declare if a variable should be eligible for |
276 |
|
// selection in the decision heuristic. |
277 |
|
|
278 |
|
// Read state: |
279 |
|
// |
280 |
|
lbool value(Var x) const; // The current value of a variable. |
281 |
|
lbool value(Lit p) const; // The current value of a literal. |
282 |
|
lbool modelValue( |
283 |
|
Var x) const; // The value of a variable in the last model. The last call |
284 |
|
// to solve must have been satisfiable. |
285 |
|
lbool modelValue( |
286 |
|
Lit p) const; // The value of a literal in the last model. The last call |
287 |
|
// to solve must have been satisfiable. |
288 |
|
int nAssigns() const; // The current number of assigned literals. |
289 |
|
int nClauses() const; // The current number of original clauses. |
290 |
|
int nLearnts() const; // The current number of learnt clauses. |
291 |
|
int nVars() const; // The current number of variables. |
292 |
|
int nFreeVars() const; |
293 |
|
bool isDecision(Var x) const; // is the given var a decision? |
294 |
|
|
295 |
|
// Debugging SMT explanations |
296 |
|
// |
297 |
|
bool properExplanation(Lit l, Lit expl) |
298 |
|
const; // returns true if expl can be used to explain l---i.e., both |
299 |
|
// assigned and trail_index(expl) < trail_index(l) |
300 |
|
|
301 |
|
// Resource contraints: |
302 |
|
// |
303 |
|
void setConfBudget(int64_t x); |
304 |
|
void setPropBudget(int64_t x); |
305 |
|
void budgetOff(); |
306 |
|
void interrupt(); // Trigger a (potentially asynchronous) interruption of the |
307 |
|
// solver. |
308 |
|
void clearInterrupt(); // Clear interrupt indicator flag. |
309 |
|
|
310 |
|
// Memory managment: |
311 |
|
// |
312 |
|
virtual void garbageCollect(); |
313 |
|
void checkGarbage(double gf); |
314 |
|
void checkGarbage(); |
315 |
|
|
316 |
|
// Extra results: (read-only member variable) |
317 |
|
// |
318 |
|
vec<lbool> model; // If problem is satisfiable, this vector contains the model |
319 |
|
// (if any). |
320 |
|
vec<Lit> d_conflict; // If problem is unsatisfiable (possibly under |
321 |
|
// assumptions), this vector represent the final |
322 |
|
// conflict clause expressed in the assumptions. |
323 |
|
|
324 |
|
// Mode of operation: |
325 |
|
// |
326 |
|
int verbosity; |
327 |
|
double var_decay; |
328 |
|
double clause_decay; |
329 |
|
double random_var_freq; |
330 |
|
double random_seed; |
331 |
|
bool luby_restart; |
332 |
|
int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, |
333 |
|
// 2=deep). |
334 |
|
int phase_saving; // Controls the level of phase saving (0=none, 1=limited, |
335 |
|
// 2=full). |
336 |
|
bool rnd_pol; // Use random polarities for branching heuristics. |
337 |
|
bool |
338 |
|
rnd_init_act; // Initialize variable activities with a small random value. |
339 |
|
double garbage_frac; // The fraction of wasted memory allowed before a garbage |
340 |
|
// collection is triggered. |
341 |
|
|
342 |
|
int restart_first; // The initial restart limit. (default 100) |
343 |
|
double restart_inc; // The factor with which the restart limit is multiplied |
344 |
|
// in each restart. (default 1.5) |
345 |
|
double |
346 |
|
learntsize_factor; // The intitial limit for learnt clauses is a factor of |
347 |
|
// the original clauses. (default 1 / 3) |
348 |
|
double learntsize_inc; // The limit for learnt clauses is multiplied with this |
349 |
|
// factor each restart. (default 1.1) |
350 |
|
|
351 |
|
int learntsize_adjust_start_confl; |
352 |
|
double learntsize_adjust_inc; |
353 |
|
|
354 |
|
// Statistics: (read-only member variable) |
355 |
|
// |
356 |
|
int64_t solves, starts, decisions, rnd_decisions, propagations, conflicts, |
357 |
|
resources_consumed; |
358 |
|
int64_t dec_vars, clauses_literals, learnts_literals, max_literals, |
359 |
|
tot_literals; |
360 |
|
|
361 |
|
protected: |
362 |
|
|
363 |
|
// Helper structures: |
364 |
|
// |
365 |
|
struct VarData { |
366 |
|
// Reason for the literal being in the trail |
367 |
|
CRef d_reason; |
368 |
|
// Sat level when the literal was added to the trail |
369 |
|
int d_level; |
370 |
|
// User level when the literal was added to the trail |
371 |
|
int d_user_level; |
372 |
|
// User level at which this literal was introduced |
373 |
|
int d_intro_level; |
374 |
|
// The index in the trail |
375 |
|
int d_trail_index; |
376 |
|
|
377 |
117728485 |
VarData(CRef reason, |
378 |
|
int level, |
379 |
|
int user_level, |
380 |
|
int intro_level, |
381 |
|
int trail_index) |
382 |
117728485 |
: d_reason(reason), |
383 |
|
d_level(level), |
384 |
|
d_user_level(user_level), |
385 |
|
d_intro_level(intro_level), |
386 |
117728485 |
d_trail_index(trail_index) |
387 |
117728485 |
{} |
388 |
|
}; |
389 |
|
|
390 |
|
struct Watcher { |
391 |
|
CRef cref; |
392 |
|
Lit blocker; |
393 |
305509007 |
Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {} |
394 |
|
bool operator==(const Watcher& w) const { return cref == w.cref; } |
395 |
4996771 |
bool operator!=(const Watcher& w) const { return cref != w.cref; } |
396 |
|
}; |
397 |
|
|
398 |
|
struct WatcherDeleted |
399 |
|
{ |
400 |
|
const ClauseAllocator& ca; |
401 |
9994 |
WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {} |
402 |
14377452 |
bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; } |
403 |
|
}; |
404 |
|
|
405 |
|
struct VarOrderLt { |
406 |
|
const vec<double>& activity; |
407 |
143219081 |
bool operator () (Var x, Var y) const { return activity[x] > activity[y]; } |
408 |
9994 |
VarOrderLt(const vec<double>& act) : activity(act) { } |
409 |
|
}; |
410 |
|
|
411 |
|
// Solver state: |
412 |
|
// |
413 |
|
bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! |
414 |
|
vec<CRef> clauses_persistent; // List of problem clauses. |
415 |
|
vec<CRef> clauses_removable; // List of learnt clauses. |
416 |
|
double cla_inc; // Amount to bump next clause with. |
417 |
|
vec<double> activity; // A heuristic measurement of the activity of a variable. |
418 |
|
double var_inc; // Amount to bump next variable with. |
419 |
|
OccLists<Lit, vec<Watcher>, WatcherDeleted> |
420 |
|
watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). |
421 |
|
vec<lbool> assigns; // The current assignments. |
422 |
|
vec<int> assigns_lim; // The size by levels of the current assignment |
423 |
|
vec<char> polarity; // The preferred polarity of each variable (bit 0) and whether it's locked (bit 1). |
424 |
|
vec<char> decision; // Declares if a variable is eligible for selection in the decision heuristic. |
425 |
|
vec<int> flipped; // Which trail_lim decisions have been flipped in this context. |
426 |
|
vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made. |
427 |
|
vec<int> trail_lim; // Separator indices for different decision levels in 'trail'. |
428 |
|
vec<bool> trail_ok; // Stack of "whether we're in conflict" flags. |
429 |
|
vec<VarData> vardata; // Stores reason and level for each variable. |
430 |
|
int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). |
431 |
|
int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'. |
432 |
|
int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'. |
433 |
|
vec<Lit> assumptions; // Current set of assumptions provided to solve by the user. |
434 |
|
Heap<VarOrderLt> order_heap; // A priority queue of variables ordered with respect to the variable activity. |
435 |
|
double progress_estimate; // Set by 'search()'. |
436 |
|
bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'. |
437 |
|
|
438 |
|
ClauseAllocator ca; |
439 |
|
|
440 |
|
// cvc5 Stuff |
441 |
|
/** |
442 |
|
* A vector determining whether each variable represents a theory atom. |
443 |
|
* More generally, this value is true for any literal that the theory proxy |
444 |
|
* should be notified about when asserted. |
445 |
|
*/ |
446 |
|
vec<bool> theory; |
447 |
|
|
448 |
|
enum TheoryCheckType { |
449 |
|
// Quick check, but don't perform theory reasoning |
450 |
|
CHECK_WITHOUT_THEORY, |
451 |
|
// Check and perform theory reasoning |
452 |
|
CHECK_WITH_THEORY, |
453 |
|
// The SAT abstraction of the problem is satisfiable, perform a full theory check |
454 |
|
CHECK_FINAL, |
455 |
|
// Perform a full theory check even if not done with everything |
456 |
|
CHECK_FINAL_FAKE |
457 |
|
}; |
458 |
|
|
459 |
|
// Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is |
460 |
|
// used, exept 'seen' wich is used in several places. |
461 |
|
// |
462 |
|
vec<char> seen; |
463 |
|
vec<Lit> analyze_stack; |
464 |
|
vec<Lit> analyze_toclear; |
465 |
|
vec<Lit> add_tmp; |
466 |
|
|
467 |
|
double max_learnts; |
468 |
|
double learntsize_adjust_confl; |
469 |
|
int learntsize_adjust_cnt; |
470 |
|
|
471 |
|
// Resource contraints: |
472 |
|
// |
473 |
|
int64_t conflict_budget; // -1 means no budget. |
474 |
|
int64_t propagation_budget; // -1 means no budget. |
475 |
|
bool asynch_interrupt; |
476 |
|
|
477 |
|
// Main internal methods: |
478 |
|
// |
479 |
|
void insertVarOrder (Var x); // Insert a variable in the decision order priority queue. |
480 |
|
Lit pickBranchLit (); // Return the next decision variable. |
481 |
|
void newDecisionLevel (); // Begins a new decision level. |
482 |
|
void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined. |
483 |
|
bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise. |
484 |
|
bool theoryConflict; // Was the last conflict a theory conflict |
485 |
|
CRef propagate (TheoryCheckType type); // Perform Boolean and Theory. Returns possibly conflicting clause. |
486 |
|
CRef propagateBool (); // Perform Boolean propagation. Returns possibly conflicting clause. |
487 |
|
void propagateTheory (); // Perform Theory propagation. |
488 |
|
void theoryCheck( |
489 |
|
cvc5::theory::Theory::Effort |
490 |
|
effort); // Perform a theory satisfiability check. Adds lemmas. |
491 |
|
CRef updateLemmas (); // Add the lemmas, backtraking if necessary and return a conflict if there is one |
492 |
|
void cancelUntil (int level); // Backtrack until a certain level. |
493 |
|
int analyze (CRef confl, vec<Lit>& out_learnt, int& out_btlevel); // (bt = backtrack) |
494 |
|
void analyzeFinal (Lit p, vec<Lit>& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION? |
495 |
|
bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()') - true if p is redundant |
496 |
|
lbool search (int nof_conflicts); // Search for a given number of conflicts. |
497 |
|
lbool solve_ (); // Main solve method (assumptions given in 'assumptions'). |
498 |
|
void reduceDB (); // Reduce the set of learnt clauses. |
499 |
|
void removeSatisfied (vec<CRef>& cs); // Shrink 'cs' to contain only non-satisfied clauses. |
500 |
|
void rebuildOrderHeap (); |
501 |
|
|
502 |
|
// Maintaining Variable/Clause activity: |
503 |
|
// |
504 |
|
void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead. |
505 |
|
void varBumpActivity (Var v, double inc); // Increase a variable with the current 'bump' value. |
506 |
|
void varBumpActivity (Var v); // Increase a variable with the current 'bump' value. |
507 |
|
void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead. |
508 |
|
void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value. |
509 |
|
|
510 |
|
// Operations on clauses: |
511 |
|
// |
512 |
|
void attachClause (CRef cr); // Attach a clause to watcher lists. |
513 |
|
void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists. |
514 |
|
void removeClause (CRef cr); // Detach and free a clause. |
515 |
|
bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state. |
516 |
|
bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state. |
517 |
|
|
518 |
|
void relocAll (ClauseAllocator& to); |
519 |
|
|
520 |
|
// Misc: |
521 |
|
// |
522 |
|
int decisionLevel () const; // Gives the current decisionlevel. |
523 |
|
uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels. |
524 |
|
CRef reason (Var x); // Get the reason of the variable (non const as it might create the explanation on the fly) |
525 |
|
bool hasReasonClause (Var x) const; // Does the variable have a reason |
526 |
|
bool isPropagated (Var x) const; // Does the variable have a propagated variables |
527 |
|
bool isPropagatedBy (Var x, const Clause& c) const; // Is the value of the variable propagated by the clause Clause C |
528 |
|
|
529 |
|
int trail_index (Var x) const; // Index in the trail |
530 |
|
double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ... |
531 |
|
public: |
532 |
|
int level (Var x) const; |
533 |
|
int user_level (Var x) const; // User level at which this variable was asserted |
534 |
|
int intro_level (Var x) const; // User level at which this variable was created |
535 |
|
bool withinBudget (uint64_t amount) const; |
536 |
|
bool withinBudget(Resource r) const; |
537 |
|
|
538 |
|
protected: |
539 |
|
// Static helpers: |
540 |
|
// |
541 |
|
|
542 |
|
// Returns a random float 0 <= x < 1. Seed must never be 0. |
543 |
1420540 |
static inline double drand(double& seed) { |
544 |
1420540 |
seed *= 1389796; |
545 |
1420540 |
int q = (int)(seed / 2147483647); |
546 |
1420540 |
seed -= (double)q * 2147483647; |
547 |
1420540 |
return seed / 2147483647; } |
548 |
|
|
549 |
|
// Returns a random integer 0 <= x < size. Seed must never be 0. |
550 |
|
static inline int irand(double& seed, int size) { |
551 |
|
return (int)(drand(seed) * size); } |
552 |
|
|
553 |
|
}; |
554 |
|
|
555 |
|
|
556 |
|
|
557 |
|
//================================================================================================= |
558 |
|
// Implementation of inline methods: |
559 |
|
|
560 |
179950 |
inline bool Solver::hasReasonClause(Var x) const |
561 |
|
{ |
562 |
179950 |
return vardata[x].d_reason != CRef_Undef && vardata[x].d_reason != CRef_Lazy; |
563 |
|
} |
564 |
|
|
565 |
|
inline bool Solver::isPropagated(Var x) const |
566 |
|
{ |
567 |
|
return vardata[x].d_reason != CRef_Undef; |
568 |
|
} |
569 |
|
|
570 |
203307 |
inline bool Solver::isPropagatedBy(Var x, const Clause& c) const |
571 |
|
{ |
572 |
303853 |
return vardata[x].d_reason != CRef_Undef && vardata[x].d_reason != CRef_Lazy |
573 |
294120 |
&& ca.lea(vardata[var(c[0])].d_reason) == &c; |
574 |
|
} |
575 |
|
|
576 |
176887 |
inline bool Solver::isDecision(Var x) const |
577 |
|
{ |
578 |
353774 |
Debug("minisat") << "var " << x << " is a decision iff " |
579 |
353774 |
<< (vardata[x].d_reason == CRef_Undef) << " && " << level(x) |
580 |
176887 |
<< " > 0" << std::endl; |
581 |
176887 |
return vardata[x].d_reason == CRef_Undef && level(x) > 0; |
582 |
|
} |
583 |
|
|
584 |
653706538 |
inline int Solver::level(Var x) const |
585 |
|
{ |
586 |
653706538 |
Assert(x < vardata.size()); |
587 |
653706538 |
return vardata[x].d_level; |
588 |
|
} |
589 |
|
|
590 |
3810766 |
inline int Solver::user_level(Var x) const |
591 |
|
{ |
592 |
3810766 |
Assert(x < vardata.size()); |
593 |
3810766 |
return vardata[x].d_user_level; |
594 |
|
} |
595 |
|
|
596 |
129045857 |
inline int Solver::intro_level(Var x) const |
597 |
|
{ |
598 |
129045857 |
Assert(x < vardata.size()); |
599 |
129045857 |
return vardata[x].d_intro_level; |
600 |
|
} |
601 |
|
|
602 |
16920024 |
inline int Solver::trail_index(Var x) const |
603 |
|
{ |
604 |
16920024 |
Assert(x < vardata.size()); |
605 |
16920024 |
return vardata[x].d_trail_index; |
606 |
|
} |
607 |
|
|
608 |
117371687 |
inline void Solver::insertVarOrder(Var x) { |
609 |
117371687 |
Assert(x < vardata.size()); |
610 |
117371687 |
if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); |
611 |
117371687 |
} |
612 |
|
|
613 |
295242 |
inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); } |
614 |
60167643 |
inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); } |
615 |
60167643 |
inline void Solver::varBumpActivity(Var v, double inc) { |
616 |
60167643 |
if ( (activity[v] += inc) > 1e100 ) { |
617 |
|
// Rescale: |
618 |
45358 |
for (int i = 0; i < nVars(); i++) |
619 |
45333 |
activity[i] *= 1e-100; |
620 |
25 |
var_inc *= 1e-100; } |
621 |
|
|
622 |
|
// Update order_heap with respect to new activity: |
623 |
60167643 |
if (order_heap.inHeap(v)) |
624 |
46488375 |
order_heap.decrease(v); } |
625 |
|
|
626 |
295242 |
inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); } |
627 |
2215554 |
inline void Solver::claBumpActivity (Clause& c) { |
628 |
2215554 |
if ( (c.activity() += cla_inc) > 1e20 ) { |
629 |
|
// Rescale: |
630 |
41321 |
for (int i = 0; i < clauses_removable.size(); i++) |
631 |
41320 |
ca[clauses_removable[i]].activity() *= 1e-20; |
632 |
1 |
cla_inc *= 1e-20; } } |
633 |
|
|
634 |
22879 |
inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); } |
635 |
125333 |
inline void Solver::checkGarbage(double gf){ |
636 |
125333 |
if (ca.wasted() > ca.size() * gf) |
637 |
2818 |
garbageCollect(); } |
638 |
|
|
639 |
|
// NOTE: enqueue does not set the ok flag! (only public methods do) |
640 |
9053 |
inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); } |
641 |
72449 |
inline bool Solver::addClause (const vec<Lit>& ps, bool removable, ClauseId& id) |
642 |
72449 |
{ ps.copyTo(add_tmp); return addClause_(add_tmp, removable, id); } |
643 |
|
inline bool Solver::addEmptyClause (bool removable) { add_tmp.clear(); ClauseId tmp; return addClause_(add_tmp, removable, tmp); } |
644 |
|
inline bool Solver::addClause (Lit p, bool removable, ClauseId& id) |
645 |
|
{ add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, id); } |
646 |
|
inline bool Solver::addClause (Lit p, Lit q, bool removable, ClauseId& id) |
647 |
|
{ add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, id); } |
648 |
|
inline bool Solver::addClause (Lit p, Lit q, Lit r, bool removable, ClauseId& id) |
649 |
|
{ add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, id); } |
650 |
1303576 |
inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && isPropagatedBy(var(c[0]), c); } |
651 |
2961044 |
inline void Solver::newDecisionLevel() |
652 |
|
{ |
653 |
2961044 |
trail_lim.push(trail.size()); |
654 |
2961044 |
flipped.push(false); |
655 |
2961044 |
d_context->push(); |
656 |
2961044 |
} |
657 |
|
|
658 |
188381907 |
inline int Solver::decisionLevel () const { return trail_lim.size(); } |
659 |
77801851 |
inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); } |
660 |
9444722 |
inline lbool Solver::value(Var x) const |
661 |
|
{ |
662 |
9444722 |
Assert(x < nVars()); |
663 |
9444722 |
return assigns[x]; |
664 |
|
} |
665 |
2347165177 |
inline lbool Solver::value(Lit p) const |
666 |
|
{ |
667 |
2347165177 |
Assert(var(p) < nVars()); |
668 |
2347165177 |
return assigns[var(p)] ^ sign(p); |
669 |
|
} |
670 |
|
inline lbool Solver::modelValue (Var x) const { return model[x]; } |
671 |
50416 |
inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); } |
672 |
3069447 |
inline int Solver::nAssigns () const { return trail.size(); } |
673 |
13646 |
inline int Solver::nClauses () const { return clauses_persistent.size(); } |
674 |
|
inline int Solver::nLearnts () const { return clauses_removable.size(); } |
675 |
2484983885 |
inline int Solver::nVars () const { return vardata.size(); } |
676 |
|
inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); } |
677 |
|
inline bool Solver::properExplanation(Lit l, Lit expl) const { return value(l) == l_True && value(expl) == l_True && trail_index(var(expl)) < trail_index(var(l)); } |
678 |
|
inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; } |
679 |
69431 |
inline void Solver::freezePolarity(Var v, bool b) { polarity[v] = int(b) | 0x2; } |
680 |
1311040 |
inline void Solver::setDecisionVar(Var v, bool b) |
681 |
|
{ |
682 |
1311040 |
if ( b && !decision[v] ) dec_vars++; |
683 |
39023 |
else if (!b && decision[v] ) dec_vars--; |
684 |
|
|
685 |
1311040 |
decision[v] = b; |
686 |
1311040 |
insertVarOrder(v); |
687 |
1311040 |
} |
688 |
|
|
689 |
|
inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; } |
690 |
|
inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; } |
691 |
|
inline void Solver::interrupt(){ asynch_interrupt = true; } |
692 |
15232 |
inline void Solver::clearInterrupt(){ asynch_interrupt = false; } |
693 |
30496 |
inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; } |
694 |
|
|
695 |
|
inline lbool Solver::solve () { budgetOff(); assumptions.clear(); return solve_(); } |
696 |
|
inline lbool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(); } |
697 |
|
inline lbool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(); } |
698 |
|
inline lbool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(); } |
699 |
|
inline lbool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_(); } |
700 |
|
inline lbool Solver::solveLimited (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); } |
701 |
3706059 |
inline bool Solver::okay () const { return ok; } |
702 |
|
|
703 |
|
inline void Solver::toDimacs () { vec<Lit> as; toDimacs(stdout, as); } |
704 |
|
inline void Solver::toDimacs (const char* file){ vec<Lit> as; toDimacs(file, as); } |
705 |
|
inline void Solver::toDimacs (const char* file, Lit p){ vec<Lit> as; as.push(p); toDimacs(file, as); } |
706 |
|
inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec<Lit> as; as.push(p); as.push(q); toDimacs(file, as); } |
707 |
|
inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec<Lit> as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); } |
708 |
|
|
709 |
|
|
710 |
|
|
711 |
|
//================================================================================================= |
712 |
|
// Debug etc: |
713 |
|
|
714 |
|
|
715 |
|
//================================================================================================= |
716 |
|
} // namespace Minisat |
717 |
|
} // namespace cvc5 |
718 |
|
|
719 |
|
#endif |