Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
Solver.h
Go to the documentation of this file.
1/****************************************************************************************[Solver.h]
2Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
3Copyright (c) 2007-2010, Niklas Sorensson
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6associated documentation files (the "Software"), to deal in the Software without restriction,
7including without limitation the rights to use, copy, modify, merge, publish, distribute,
8sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all copies or
12substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
18OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19**************************************************************************************************/
20
21#pragma once
22
28
29
30namespace Minisat {
31namespace Internal {
32
33//=================================================================================================
34// Solver -- the main class:
35
36class Solver {
37public:
38
39 // Constructor/Destructor:
40 //
42 virtual ~Solver();
43
44 // Problem specification:
45 //
46 Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode.
47
48 bool addClause (const vec<Lit>& ps); // Add a clause to the solver.
49 bool addEmptyClause(); // Add the empty clause, making the solver contradictory.
50 bool addClause (Lit p); // Add a unit clause to the solver.
51 bool addClause (Lit p, Lit q); // Add a binary clause to the solver.
52 bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver.
53 bool addClause_( vec<Lit>& ps); // Add a clause to the solver without making superflous internal copy. Will
54 // change the passed vector 'ps'.
55
56
60
61 struct SolverStatus {
62 unsigned long long int restarts;
63 unsigned long long int conflicts;
64 unsigned long long int decisions;
65 unsigned long long int propagations;
66 unsigned long long int conflict_literals;
67 bool timeout;
69 };
70
71 // Solving:
72 //
73 bool simplify (); // Removes already satisfied clauses.
74 bool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
75 lbool solveLimited (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions (With resource constraints).
76 bool solve (); // Search without assumptions.
77 bool solve (double t, SolverStatus& st); // Search without assumptions and MAX time. //HEDTKE
78 bool solve (Lit p); // Search for a model that respects a single assumption.
79 bool solve (Lit p, Lit q); // Search for a model that respects two assumptions.
80 bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
81 bool okay () const; // FALSE means solver is in a conflicting state
82
83 void toDimacs (std::ostream &out, const vec<Lit>& assumps); // Write CNF to file in DIMACS-format.
84 void toDimacs (const char *file, const vec<Lit>& assumps);
85 void toDimacs (std::ostream &out, Clause& c, vec<Var>& map, Var& max);
86
87 // Convenience versions of 'toDimacs()':
88 void toDimacs (const char* file);
89 void toDimacs (const char* file, Lit p);
90 void toDimacs (const char* file, Lit p, Lit q);
91 void toDimacs (const char* file, Lit p, Lit q, Lit r);
92
93 // Variable mode:
94 //
95 void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
96 void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
97
98 // Read state:
99 //
100 lbool value (Var x) const; // The current value of a variable.
101 lbool value (Lit p) const; // The current value of a literal.
102 lbool modelValue (Var x) const; // The value of a variable in the last model. The last call to solve must have been satisfiable.
103 lbool modelValue (Lit p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable.
104 int nAssigns () const; // The current number of assigned literals.
105 int nClauses () const; // The current number of original clauses.
106 int nLearnts () const; // The current number of learnt clauses.
107 int nVars () const; // The current number of variables.
108 int nFreeVars () const;
109
110 // Resource contraints:
111 //
112 void setConfBudget(int64_t x);
113 void setPropBudget(int64_t x);
114 void budgetOff();
115 void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver.
116 void clearInterrupt(); // Clear interrupt indicator flag.
117
118 // Memory managment:
119 //
120 virtual void garbageCollect();
121 void checkGarbage(double gf);
122 void checkGarbage();
123
124 // Extra results: (read-only member variable)
125 //
126 vec<lbool> model; // If problem is satisfiable, this vector contains the model (if any).
127 vec<Lit> conflict; // If problem is unsatisfiable (possibly under assumptions),
128 // this vector represent the final conflict clause expressed in the assumptions.
129
130 // Mode of operation:
131 //
133 double var_decay;
138 int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, 2=deep).
139 int phase_saving; // Controls the level of phase saving (0=none, 1=limited, 2=full).
140 bool rnd_pol; // Use random polarities for branching heuristics.
141 bool rnd_init_act; // Initialize variable activities with a small random value.
142 double garbage_frac; // The fraction of wasted memory allowed before a garbage collection is triggered.
143
144 int restart_first; // The initial restart limit. (default 100)
145 double restart_inc; // The factor with which the restart limit is multiplied in each restart. (default 1.5)
146 double learntsize_factor; // The intitial limit for learnt clauses is a factor of the original clauses. (default 1 / 3)
147 double learntsize_inc; // The limit for learnt clauses is multiplied with this factor each restart. (default 1.1)
148
151
152 // Statistics: (read-only member variable)
153 //
156
157protected:
158
159 // Helper structures:
160 //
161 struct VarData { CRef reason; int level; };
162 static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; }
163
164 struct Watcher {
168 bool operator==(const Watcher& w) const { return cref == w.cref; }
169 bool operator!=(const Watcher& w) const { return cref != w.cref; }
170 };
171
173 {
176 bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; }
177 };
178
179 struct VarOrderLt {
181 bool operator () (Var x, Var y) const { return activity[x] > activity[y]; }
182 VarOrderLt(const vec<double>& act) : activity(act) { }
183 };
184
185 // Solver state:
186 //
187 bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!
188 vec<CRef> clauses; // List of problem clauses.
189 vec<CRef> learnts; // List of learnt clauses.
190 double cla_inc; // Amount to bump next clause with.
191 vec<double> activity; // A heuristic measurement of the activity of a variable.
192 double var_inc; // Amount to bump next variable with.
194 watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
195 vec<lbool> assigns; // The current assignments.
196 vec<char> polarity; // The preferred polarity of each variable.
197 vec<char> decision; // Declares if a variable is eligible for selection in the decision heuristic.
198 vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made.
199 vec<int> trail_lim; // Separator indices for different decision levels in 'trail'.
200 vec<VarData> vardata; // Stores reason and level for each variable.
201 int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
202 int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'.
203 int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'.
204 vec<Lit> assumptions; // Current set of assumptions provided to solve by the user.
205 Heap<VarOrderLt> order_heap; // A priority queue of variables ordered with respect to the variable activity.
206 double progress_estimate;// Set by 'search()'.
207 bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'.
208
210
211 // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
212 // used, exept 'seen' wich is used in several places.
213 //
218
222
223 // Resource contraints:
224 //
225 int64_t conflict_budget; // -1 means no budget.
226 int64_t propagation_budget; // -1 means no budget.
228
229 // Main internal methods:
230 //
231 void insertVarOrder (Var x); // Insert a variable in the decision order priority queue.
232 Lit pickBranchLit (); // Return the next decision variable.
233 void newDecisionLevel (); // Begins a new decision level.
234 void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined.
235 bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise.
236 CRef propagate (); // Perform unit propagation. Returns possibly conflicting clause.
237 void cancelUntil (int level); // Backtrack until a certain level.
238 void analyze (CRef confl, vec<Lit>& out_learnt, int& out_btlevel); // (bt = backtrack)
239 void analyzeFinal (Lit p, vec<Lit>& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION?
240 bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()')
241 lbool search (int nof_conflicts); // Search for a given number of conflicts.
242 lbool search (int nof_conflicts, double& time); // Search for a given number of conflicts with MAX time. //HEDTKE
243 lbool solve_ (); // Main solve method (assumptions given in 'assumptions').
244 lbool solve_ (double& t); // Main solve method (assumptions given in 'assumptions') with MAX time. //HEDTKE
245 void reduceDB (); // Reduce the set of learnt clauses.
246 void removeSatisfied (vec<CRef>& cs); // Shrink 'cs' to contain only non-satisfied clauses.
248
249 // Maintaining Variable/Clause activity:
250 //
251 void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead.
252 void varBumpActivity (Var v, double inc); // Increase a variable with the current 'bump' value.
253 void varBumpActivity (Var v); // Increase a variable with the current 'bump' value.
254 void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead.
255 void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value.
256
257 // Operations on clauses:
258 //
259 void attachClause (CRef cr); // Attach a clause to watcher lists.
260 void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists.
261 void removeClause (CRef cr); // Detach and free a clause.
262 bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state.
263 bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state.
264
266
267 // Misc:
268 //
269 int decisionLevel () const; // Gives the current decisionlevel.
270 uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels.
271 CRef reason (Var x) const;
272 int level (Var x) const;
273 double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
274 bool withinBudget () const;
275
276 // Static helpers:
277 //
278
279 // Returns a random float 0 <= x < 1. Seed must never be 0.
280 static inline double drand(double& seed) {
281 seed *= 1389796;
282 int q = (int)(seed / 2147483647);
283 seed -= (double)q * 2147483647;
284 return seed / 2147483647; }
285
286 // Returns a random integer 0 <= x < size. Seed must never be 0.
287 static inline int irand(double& seed, int size) {
288 return (int)(drand(seed) * size); }
289};
290
291
292//=================================================================================================
293// Implementation of inline methods:
294
295inline CRef Solver::reason(Var x) const { return vardata[x].reason; }
296inline int Solver::level (Var x) const { return vardata[x].level; }
297
299 if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); }
300
301inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); }
303inline void Solver::varBumpActivity(Var v, double inc) {
304 if ( (activity[v] += inc) > 1e100 ) {
305 // Rescale:
306 for (int i = 0; i < nVars(); i++)
307 activity[i] *= 1e-100;
308 var_inc *= 1e-100; }
309
310 // Update order_heap with respect to new activity:
311 if (order_heap.inHeap(v))
312 order_heap.decrease(v); }
313
316 if ( (c.activity() += (float)cla_inc) > 1e20f ) {
317 // Rescale:
318 for (int i = 0; i < learnts.size(); i++)
319 ca[learnts[i]].activity() *= 1e-20f;
320 cla_inc *= 1e-20; } }
321
322inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); }
323inline void Solver::checkGarbage(double gf){
324 if (ca.wasted() > ca.size() * gf)
325 garbageCollect(); }
326
327// NOTE: enqueue does not set the ok flag! (only public methods do)
328inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
329inline bool Solver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); }
330inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); }
331inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
332inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
333inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
334inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; }
336
337inline int Solver::decisionLevel () const { return trail_lim.size(); }
338inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); }
339inline lbool Solver::value (Var x) const { return assigns[x]; }
340inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); }
341inline lbool Solver::modelValue (Var x) const { return model[x]; }
342inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); }
343inline int Solver::nAssigns () const { return trail.size(); }
344inline int Solver::nClauses () const { return clauses.size(); }
345inline int Solver::nLearnts () const { return learnts.size(); }
346inline int Solver::nVars () const { return vardata.size(); }
347inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); }
348inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; }
349inline void Solver::setDecisionVar(Var v, bool b)
350{
351 if ( b && !decision[v]) dec_vars++;
352 else if (!b && decision[v]) dec_vars--;
353
354 decision[v] = b;
356}
359inline void Solver::interrupt(){ asynch_interrupt = true; }
366
367// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a
368// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or
369// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer.
370inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; }
371inline bool Solver::solve (double t, SolverStatus& st) {
372 budgetOff();
373 assumptions.clear();
375 st.restarts = starts;
376#if 0
379#endif
380 st.conflicts = conflicts;
381 st.decisions = decisions;
382 st.propagations = propagations;
383 st.conflict_literals = tot_literals;
384 st.timeout = (solver_value == l_Timeout);
385 if (st.timeout) {
386 st.answer = A_UNDEF;
387 } else if (solver_value == l_True) {
388 st.answer = A_TRUE;
389 } else {
390 st.answer = A_FALSE;
391 }
392 return (solver_value == l_True);
393} //HEDTKE
394
395inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; }
396inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; }
397inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; }
398inline bool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; }
400inline bool Solver::okay () const { return ok; }
401
402inline void Solver::toDimacs (const char* file){ vec<Lit> as; toDimacs(file, as); }
403inline void Solver::toDimacs (const char* file, Lit p){ vec<Lit> as; as.push(p); toDimacs(file, as); }
404inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec<Lit> as; as.push(p); as.push(q); toDimacs(file, as); }
405inline 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); }
406
407
408//=================================================================================================
409// Debug etc:
410
411
412//=================================================================================================
413} // namespace Internal
414} // namespace Minisat
#define l_Timeout
Definition SolverTypes.h:88
#define l_True
Definition SolverTypes.h:85
#define l_Undef
Definition SolverTypes.h:87
#define l_False
Definition SolverTypes.h:86
lbool search(int nof_conflicts, double &time)
bool addClause(const vec< Lit > &ps)
Definition Solver.h:329
ClauseAllocator ca
Definition Solver.h:209
void varBumpActivity(Var v, double inc)
Definition Solver.h:303
void insertVarOrder(Var x)
Definition Solver.h:298
void toDimacs(std::ostream &out, Clause &c, vec< Var > &map, Var &max)
void setConfBudget(int64_t x)
Definition Solver.h:357
int level(Var x) const
Definition Solver.h:296
bool satisfied(const Clause &c) const
vec< double > activity
Definition Solver.h:191
vec< Lit > analyze_stack
Definition Solver.h:215
bool withinBudget() const
Definition Solver.h:362
void analyze(CRef confl, vec< Lit > &out_learnt, int &out_btlevel)
void attachClause(CRef cr)
int nFreeVars() const
Definition Solver.h:347
void setDecisionVar(Var v, bool b)
Definition Solver.h:349
void toDimacs(const char *file, const vec< Lit > &assumps)
int decisionLevel() const
Definition Solver.h:337
CRef reason(Var x) const
Definition Solver.h:295
vec< Lit > analyze_toclear
Definition Solver.h:216
void relocAll(ClauseAllocator &to)
void toDimacs(std::ostream &out, const vec< Lit > &assumps)
Var newVar(bool polarity=true, bool dvar=true)
lbool modelValue(Var x) const
Definition Solver.h:341
static VarData mkVarData(CRef cr, int l)
Definition Solver.h:162
lbool value(Var x) const
Definition Solver.h:339
static double drand(double &seed)
Definition Solver.h:280
double progressEstimate() const
bool enqueue(Lit p, CRef from=CRef_Undef)
Definition Solver.h:328
bool locked(const Clause &c) const
Definition Solver.h:334
static int irand(double &seed, int size)
Definition Solver.h:287
OccLists< Lit, vec< Watcher >, WatcherDeleted > watches
Definition Solver.h:194
Heap< VarOrderLt > order_heap
Definition Solver.h:205
void setPropBudget(int64_t x)
Definition Solver.h:358
void claBumpActivity(Clause &c)
Definition Solver.h:315
void removeSatisfied(vec< CRef > &cs)
void cancelUntil(int level)
virtual void garbageCollect()
vec< VarData > vardata
Definition Solver.h:200
void removeClause(CRef cr)
void setPolarity(Var v, bool b)
Definition Solver.h:348
uint32_t abstractLevel(Var x) const
Definition Solver.h:338
lbool solveLimited(const vec< Lit > &assumps)
Definition Solver.h:399
vec< lbool > assigns
Definition Solver.h:195
void detachClause(CRef cr, bool strict=false)
void analyzeFinal(Lit p, vec< Lit > &out_conflict)
void uncheckedEnqueue(Lit p, CRef from=CRef_Undef)
lbool search(int nof_conflicts)
bool litRedundant(Lit p, uint32_t abstract_levels)
bool addClause_(vec< Lit > &ps)
lbool solve_(double &t)
int size(void) const
Definition Vec.h:63
void push(void)
Definition Vec.h:73
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
RegionAllocator< uint32_t >::Ref CRef
bool sign(Lit p)
Definition SolverTypes.h:60
const CRef CRef_Undef
unsigned long long int restarts
Definition Solver.h:62
unsigned long long int decisions
Definition Solver.h:64
unsigned long long int conflicts
Definition Solver.h:63
unsigned long long int propagations
Definition Solver.h:65
unsigned long long int conflict_literals
Definition Solver.h:66
bool operator()(Var x, Var y) const
Definition Solver.h:181
const vec< double > & activity
Definition Solver.h:180
VarOrderLt(const vec< double > &act)
Definition Solver.h:182
WatcherDeleted(const ClauseAllocator &_ca)
Definition Solver.h:175
bool operator()(const Watcher &w) const
Definition Solver.h:176
bool operator==(const Watcher &w) const
Definition Solver.h:168
bool operator!=(const Watcher &w) const
Definition Solver.h:169