abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Solver.cpp
Go to the documentation of this file.
1 /***************************************************************************************[Solver.cc]
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 #include <math.h>
22 
23 #include "Sort.h"
24 #include "Solver.h"
25 
26 using namespace Minisat;
27 
28 //=================================================================================================
29 // Options:
30 
31 
32 static const char* _cat = "CORE";
33 
34 static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false));
35 static DoubleOption opt_clause_decay (_cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false));
36 static DoubleOption opt_random_var_freq (_cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true));
37 static DoubleOption opt_random_seed (_cat, "rnd-seed", "Used by the random variable selection", 91648253, DoubleRange(0, false, HUGE_VAL, false));
38 static IntOption opt_ccmin_mode (_cat, "ccmin-mode", "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2));
39 static IntOption opt_phase_saving (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2));
40 static BoolOption opt_rnd_init_act (_cat, "rnd-init", "Randomize the initial activity", false);
41 static BoolOption opt_luby_restart (_cat, "luby", "Use the Luby restart sequence", true);
42 static IntOption opt_restart_first (_cat, "rfirst", "The base restart interval", 100, IntRange(1, INT32_MAX));
43 static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interval increase factor", 2, DoubleRange(1, false, HUGE_VAL, false));
44 static DoubleOption opt_garbage_frac (_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false));
45 
46 
47 //=================================================================================================
48 // Constructor/Destructor:
49 
50 
52 
53  // Parameters (user settable):
54  //
55  verbosity (0)
56  , var_decay (opt_var_decay)
57  , clause_decay (opt_clause_decay)
58  , random_var_freq (opt_random_var_freq)
59  , random_seed (opt_random_seed)
60  , luby_restart (opt_luby_restart)
61  , ccmin_mode (opt_ccmin_mode)
62  , phase_saving (opt_phase_saving)
63  , rnd_pol (false)
64  , rnd_init_act (opt_rnd_init_act)
65  , garbage_frac (opt_garbage_frac)
66  , restart_first (opt_restart_first)
67  , restart_inc (opt_restart_inc)
68 
69  // Parameters (the rest):
70  //
71  , learntsize_factor((double)1/(double)3), learntsize_inc(1.1)
72 
73  // Parameters (experimental):
74  //
75  , learntsize_adjust_start_confl (100)
76  , learntsize_adjust_inc (1.5)
77 
78  // Statistics: (formerly in 'SolverStats')
79  //
80  , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
81  , dec_vars(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
82 
83  , ok (true)
84  , cla_inc (1)
85  , var_inc (1)
86  , watches (WatcherDeleted(ca))
87  , qhead (0)
88  , simpDB_assigns (-1)
89  , simpDB_props (0)
90  , order_heap (VarOrderLt(activity))
91  , progress_estimate (0)
92  , remove_satisfied (true)
93 
94  // Resource constraints:
95  //
96  , conflict_budget (-1)
97  , propagation_budget (-1)
98  , asynch_interrupt (false)
99 {}
100 
101 
103 {
104 }
105 
106 
107 //=================================================================================================
108 // Minor methods:
109 
110 
111 // Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be
112 // used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
113 //
114 Var Solver::newVar(bool sign, bool dvar)
115 {
116  int v = nVars();
117  watches .init(mkLit(v, false));
118  watches .init(mkLit(v, true ));
119  assigns .push(l_Undef);
120  vardata .push(mkVarData(CRef_Undef, 0));
121  //activity .push(0);
122  activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0);
123  seen .push(0);
124  polarity .push(sign);
125  decision .push();
126  trail .capacity(v+1);
127  setDecisionVar(v, dvar);
128  return v;
129 }
130 
131 
133 {
134  assert(decisionLevel() == 0);
135  if (!ok) return false;
136 
137  // Check if clause is satisfied and remove false/duplicate literals:
138  sort(ps);
139  Lit p; int i, j;
140  for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
141  if (value(ps[i]) == l_True || ps[i] == ~p)
142  return true;
143  else if (value(ps[i]) != l_False && ps[i] != p)
144  ps[j++] = p = ps[i];
145  ps.shrink(i - j);
146 
147  if (ps.size() == 0)
148  return ok = false;
149  else if (ps.size() == 1){
150  uncheckedEnqueue(ps[0]);
151  return ok = (propagate() == CRef_Undef);
152  }else{
153  CRef cr = ca.alloc(ps, false);
154  clauses.push(cr);
155  attachClause(cr);
156  }
157 
158  return true;
159 }
160 
161 
163  const Clause& c = ca[cr];
164  assert(c.size() > 1);
165  watches[~c[0]].push(Watcher(cr, c[1]));
166  watches[~c[1]].push(Watcher(cr, c[0]));
167  if (c.learnt()) learnts_literals += c.size();
168  else clauses_literals += c.size(); }
169 
170 
171 void Solver::detachClause(CRef cr, bool strict) {
172  const Clause& c = ca[cr];
173  assert(c.size() > 1);
174 
175  if (strict){
176  remove(watches[~c[0]], Watcher(cr, c[1]));
177  remove(watches[~c[1]], Watcher(cr, c[0]));
178  }else{
179  // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
180  watches.smudge(~c[0]);
181  watches.smudge(~c[1]);
182  }
183 
184  if (c.learnt()) learnts_literals -= c.size();
185  else clauses_literals -= c.size(); }
186 
187 
189  Clause& c = ca[cr];
190  detachClause(cr);
191  // Don't leave pointers to free'd memory!
192  if (locked(c)) vardata[var(c[0])].reason = CRef_Undef;
193  c.mark(1);
194  ca._free(cr);
195 }
196 
197 
198 bool Solver::satisfied(const Clause& c) const {
199  for (int i = 0; i < c.size(); i++)
200  if (value(c[i]) == l_True)
201  return true;
202  return false; }
203 
204 
205 // Revert to the state at given level (keeping all assignment at 'level' but not beyond).
206 //
207 void Solver::cancelUntil(int level) {
208  if (decisionLevel() > level){
209  for (int c = trail.size()-1; c >= trail_lim[level]; c--){
210  Var x = var(trail[c]);
211  assigns [x] = l_Undef;
212  if (phase_saving > 1 || (phase_saving == 1) && c > trail_lim.last())
213  polarity[x] = sign(trail[c]);
214  insertVarOrder(x); }
215  qhead = trail_lim[level];
216  trail.shrink(trail.size() - trail_lim[level]);
218  } }
219 
220 
221 //=================================================================================================
222 // Major methods:
223 
224 
226 {
227  Var next = var_Undef;
228 
229  // Random decision:
230  if (drand(random_seed) < random_var_freq && !order_heap.empty()){
231  next = order_heap[irand(random_seed,order_heap.size())];
232  if (value(next) == l_Undef && decision[next])
233  rnd_decisions++; }
234 
235  // Activity based decision:
236  while (next == var_Undef || value(next) != l_Undef || !decision[next])
237  if (order_heap.empty()){
238  next = var_Undef;
239  break;
240  }else
241  next = order_heap.removeMin();
242 
243  return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]);
244 }
245 
246 
247 /*_________________________________________________________________________________________________
248 |
249 | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
250 |
251 | Description:
252 | Analyze conflict and produce a reason clause.
253 |
254 | Pre-conditions:
255 | * 'out_learnt' is assumed to be cleared.
256 | * Current decision level must be greater than root level.
257 |
258 | Post-conditions:
259 | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
260 | * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
261 | rest of literals. There may be others from the same level though.
262 |
263 |________________________________________________________________________________________________@*/
264 void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
265 {
266  int pathC = 0;
267  Lit p = lit_Undef;
268 
269  // Generate conflict clause:
270  //
271  out_learnt.push(); // (leave room for the asserting literal)
272  int index = trail.size() - 1;
273 
274  do{
275  assert(confl != CRef_Undef); // (otherwise should be UIP)
276  Clause& c = ca[confl];
277 
278  if (c.learnt())
279  claBumpActivity(c);
280 
281  for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
282  Lit q = c[j];
283 
284  if (!seen[var(q)] && level(var(q)) > 0){
285  varBumpActivity(var(q));
286  seen[var(q)] = 1;
287  if (level(var(q)) >= decisionLevel())
288  pathC++;
289  else
290  out_learnt.push(q);
291  }
292  }
293 
294  // Select next clause to look at:
295  while (!seen[var(trail[index--])]);
296  p = trail[index+1];
297  confl = reason(var(p));
298  seen[var(p)] = 0;
299  pathC--;
300 
301  }while (pathC > 0);
302  out_learnt[0] = ~p;
303 
304  // Simplify conflict clause:
305  //
306  int i, j;
307  out_learnt.copyTo(analyze_toclear);
308  if (ccmin_mode == 2){
309  uint32_t abstract_level = 0;
310  for (i = 1; i < out_learnt.size(); i++)
311  abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
312 
313  for (i = j = 1; i < out_learnt.size(); i++)
314  if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level))
315  out_learnt[j++] = out_learnt[i];
316 
317  }else if (ccmin_mode == 1){
318  for (i = j = 1; i < out_learnt.size(); i++){
319  Var x = var(out_learnt[i]);
320 
321  if (reason(x) == CRef_Undef)
322  out_learnt[j++] = out_learnt[i];
323  else{
324  Clause& c = ca[reason(var(out_learnt[i]))];
325  for (int k = 1; k < c.size(); k++)
326  if (!seen[var(c[k])] && level(var(c[k])) > 0){
327  out_learnt[j++] = out_learnt[i];
328  break; }
329  }
330  }
331  }else
332  i = j = out_learnt.size();
333 
334  max_literals += out_learnt.size();
335  out_learnt.shrink(i - j);
336  tot_literals += out_learnt.size();
337 
338  // Find correct backtrack level:
339  //
340  if (out_learnt.size() == 1)
341  out_btlevel = 0;
342  else{
343  int max_i = 1;
344  // Find the first literal assigned at the next-highest level:
345  for (int i = 2; i < out_learnt.size(); i++)
346  if (level(var(out_learnt[i])) > level(var(out_learnt[max_i])))
347  max_i = i;
348  // Swap-in this literal at index 1:
349  Lit p = out_learnt[max_i];
350  out_learnt[max_i] = out_learnt[1];
351  out_learnt[1] = p;
352  out_btlevel = level(var(p));
353  }
354 
355  for (j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared)
356 }
357 
358 
359 // Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
360 // visiting literals at levels that cannot be removed later.
361 bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
362 {
363  analyze_stack.clear(); analyze_stack.push(p);
364  int top = analyze_toclear.size();
365  while (analyze_stack.size() > 0){
367  Clause& c = ca[reason(var(analyze_stack.last()))]; analyze_stack.pop();
368 
369  for (int i = 1; i < c.size(); i++){
370  Lit p = c[i];
371  if (!seen[var(p)] && level(var(p)) > 0){
372  if (reason(var(p)) != CRef_Undef && (abstractLevel(var(p)) & abstract_levels) != 0){
373  seen[var(p)] = 1;
374  analyze_stack.push(p);
375  analyze_toclear.push(p);
376  }else{
377  for (int j = top; j < analyze_toclear.size(); j++)
378  seen[var(analyze_toclear[j])] = 0;
379  analyze_toclear.shrink(analyze_toclear.size() - top);
380  return false;
381  }
382  }
383  }
384  }
385 
386  return true;
387 }
388 
389 
390 /*_________________________________________________________________________________________________
391 |
392 | analyzeFinal : (p : Lit) -> [void]
393 |
394 | Description:
395 | Specialized analysis procedure to express the final conflict in terms of assumptions.
396 | Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
397 | stores the result in 'out_conflict'.
398 |________________________________________________________________________________________________@*/
399 void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
400 {
401  out_conflict.clear();
402  out_conflict.push(p);
403 
404  if (decisionLevel() == 0)
405  return;
406 
407  seen[var(p)] = 1;
408 
409  for (int i = trail.size()-1; i >= trail_lim[0]; i--){
410  Var x = var(trail[i]);
411  if (seen[x]){
412  if (reason(x) == CRef_Undef){
413  assert(level(x) > 0);
414  out_conflict.push(~trail[i]);
415  }else{
416  Clause& c = ca[reason(x)];
417  for (int j = 1; j < c.size(); j++)
418  if (level(var(c[j])) > 0)
419  seen[var(c[j])] = 1;
420  }
421  seen[x] = 0;
422  }
423  }
424 
425  seen[var(p)] = 0;
426 }
427 
428 
430 {
431  assert(value(p) == l_Undef);
432  assigns[var(p)] = lbool(!sign(p));
433  vardata[var(p)] = mkVarData(from, decisionLevel());
434  trail.push_(p);
435 }
436 
437 
438 /*_________________________________________________________________________________________________
439 |
440 | propagate : [void] -> [Clause*]
441 |
442 | Description:
443 | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
444 | otherwise CRef_Undef.
445 |
446 | Post-conditions:
447 | * the propagation queue is empty, even if there was a conflict.
448 |________________________________________________________________________________________________@*/
450 {
451  CRef confl = CRef_Undef;
452  int num_props = 0;
453  watches.cleanAll();
454 
455  while (qhead < trail.size()){
456  Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
457  vec<Watcher>& ws = watches[p];
458  Watcher *i, *j, *end;
459  num_props++;
460 
461  for (i = j = (Watcher*)ws, end = i + ws.size(); i != end;){
462  // Try to avoid inspecting the clause:
463  Lit blocker = i->blocker;
464  if (value(blocker) == l_True){
465  *j++ = *i++; continue; }
466 
467  // Make sure the false literal is data[1]:
468  CRef cr = i->cref;
469  Clause& c = ca[cr];
470  Lit false_lit = ~p;
471  if (c[0] == false_lit)
472  c[0] = c[1], c[1] = false_lit;
473  assert(c[1] == false_lit);
474  i++;
475 
476  // If 0th watch is true, then clause is already satisfied.
477  Lit first = c[0];
478  Watcher w = Watcher(cr, first);
479  if (first != blocker && value(first) == l_True){
480  *j++ = w; continue; }
481 
482  // Look for new watch:
483  for (int k = 2; k < c.size(); k++)
484  if (value(c[k]) != l_False){
485  c[1] = c[k]; c[k] = false_lit;
486  watches[~c[1]].push(w);
487  goto NextClause; }
488 
489  // Did not find watch -- clause is unit under assignment:
490  *j++ = w;
491  if (value(first) == l_False){
492  confl = cr;
493  qhead = trail.size();
494  // Copy the remaining watches:
495  while (i < end)
496  *j++ = *i++;
497  }else
498  uncheckedEnqueue(first, cr);
499 
500  NextClause:;
501  }
502  ws.shrink(i - j);
503  }
504  propagations += num_props;
505  simpDB_props -= num_props;
506 
507  return confl;
508 }
509 
510 
511 /*_________________________________________________________________________________________________
512 |
513 | reduceDB : () -> [void]
514 |
515 | Description:
516 | Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
517 | clauses are clauses that are reason to some assignment. Binary clauses are never removed.
518 |________________________________________________________________________________________________@*/
519 struct reduceDB_lt {
521  reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
522  bool operator () (CRef x, CRef y) {
523  return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
524 };
526 {
527  int i, j;
528  double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity
529 
531  // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
532  // and clauses with activity smaller than 'extra_lim':
533  for (i = j = 0; i < learnts.size(); i++){
534  Clause& c = ca[learnts[i]];
535  if (c.size() > 2 && !locked(c) && (i < learnts.size() / 2 || c.activity() < extra_lim))
536  removeClause(learnts[i]);
537  else
538  learnts[j++] = learnts[i];
539  }
540  learnts.shrink(i - j);
541  checkGarbage();
542 }
543 
544 
546 {
547  int i, j;
548  for (i = j = 0; i < cs.size(); i++){
549  Clause& c = ca[cs[i]];
550  if (satisfied(c))
551  removeClause(cs[i]);
552  else
553  cs[j++] = cs[i];
554  }
555  cs.shrink(i - j);
556 }
557 
558 
560 {
561  vec<Var> vs;
562  for (Var v = 0; v < nVars(); v++)
563  if (decision[v] && value(v) == l_Undef)
564  vs.push(v);
565  order_heap.build(vs);
566 }
567 
568 
569 /*_________________________________________________________________________________________________
570 |
571 | simplify : [void] -> [bool]
572 |
573 | Description:
574 | Simplify the clause database according to the current top-level assigment. Currently, the only
575 | thing done here is the removal of satisfied clauses, but more things can be put here.
576 |________________________________________________________________________________________________@*/
578 {
579  assert(decisionLevel() == 0);
580 
581  if (!ok || propagate() != CRef_Undef)
582  return ok = false;
583 
584  if (nAssigns() == simpDB_assigns || (simpDB_props > 0))
585  return true;
586 
587  // Remove satisfied clauses:
589  if (remove_satisfied) // Can be turned off.
591  checkGarbage();
593 
595  simpDB_props = clauses_literals + learnts_literals; // (shouldn't depend on stats really, but it will do for now)
596 
597  return true;
598 }
599 
600 
601 /*_________________________________________________________________________________________________
602 |
603 | search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool]
604 |
605 | Description:
606 | Search for a model the specified number of conflicts.
607 | NOTE! Use negative value for 'nof_conflicts' indicate infinity.
608 |
609 | Output:
610 | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
611 | all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
612 | if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
613 |________________________________________________________________________________________________@*/
614 lbool Solver::search(int nof_conflicts)
615 {
616  assert(ok);
617  int backtrack_level;
618  int conflictC = 0;
619  vec<Lit> learnt_clause;
620  starts++;
621 
622  for (;;){
623  CRef confl = propagate();
624  if (confl != CRef_Undef){
625  // CONFLICT
626  conflicts++; conflictC++;
627  if (decisionLevel() == 0) return l_False;
628 
629  learnt_clause.clear();
630  analyze(confl, learnt_clause, backtrack_level);
631  cancelUntil(backtrack_level);
632 
633  if (learnt_clause.size() == 1){
634  uncheckedEnqueue(learnt_clause[0]);
635  }else{
636  CRef cr = ca.alloc(learnt_clause, true);
637  learnts.push(cr);
638  attachClause(cr);
639  claBumpActivity(ca[cr]);
640  uncheckedEnqueue(learnt_clause[0], cr);
641  }
642 
645 
646  if (--learntsize_adjust_cnt == 0){
650 
651  if (verbosity >= 1)
652  printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
653  (int)conflicts,
654  (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals,
655  (int)max_learnts, nLearnts(), ((double)((int64_t)learnts_literals))/nLearnts(), progressEstimate()*100);
656  }
657 
658  }else{
659  // NO CONFLICT
660  if (nof_conflicts >= 0 && conflictC >= nof_conflicts || !withinBudget()){
661  // Reached bound on number of conflicts:
663  cancelUntil(0);
664  return l_Undef; }
665 
666  // Simplify the set of problem clauses:
667  if (decisionLevel() == 0 && !simplify())
668  return l_False;
669 
670  if (learnts.size()-nAssigns() >= max_learnts)
671  // Reduce the set of learnt clauses:
672  reduceDB();
673 
674  Lit next = lit_Undef;
675  while (decisionLevel() < assumptions.size()){
676  // Perform user provided assumption:
678  if (value(p) == l_True){
679  // Dummy decision level:
681  }else if (value(p) == l_False){
682  analyzeFinal(~p, conflict);
683  return l_False;
684  }else{
685  next = p;
686  break;
687  }
688  }
689 
690  if (next == lit_Undef){
691  // New variable decision:
692  decisions++;
693  next = pickBranchLit();
694 
695  if (next == lit_Undef)
696  // Model found:
697  return l_True;
698  }
699 
700  // Increase decision level and enqueue 'next'
702  uncheckedEnqueue(next);
703  }
704  }
705 }
706 
707 
709 {
710  double progress = 0;
711  double F = 1.0 / nVars();
712 
713  for (int i = 0; i <= decisionLevel(); i++){
714  int beg = i == 0 ? 0 : trail_lim[i - 1];
715  int end = i == decisionLevel() ? trail.size() : trail_lim[i];
716  progress += pow(F, i) * (end - beg);
717  }
718 
719  return progress / nVars();
720 }
721 
722 /*
723  Finite subsequences of the Luby-sequence:
724 
725  0: 1
726  1: 1 1 2
727  2: 1 1 2 1 1 2 4
728  3: 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8
729  ...
730 
731 
732  */
733 
734 static double luby(double y, int x){
735 
736  // Find the finite subsequence that contains index 'x', and the
737  // size of that subsequence:
738  int size, seq;
739  for (size = 1, seq = 0; size < x+1; seq++, size = 2*size+1);
740 
741  while (size-1 != x){
742  size = (size-1)>>1;
743  seq--;
744  x = x % size;
745  }
746 
747  return pow(y, seq);
748 }
749 
750 // NOTE: assumptions passed in member-variable 'assumptions'.
752 {
753  model.clear();
754  conflict.clear();
755  if (!ok) return l_False;
756 
757  solves++;
758 
762  lbool status = l_Undef;
763 
764  if (verbosity >= 1){
765  printf("============================[ Search Statistics ]==============================\n");
766  printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n");
767  printf("| | Vars Clauses Literals | Limit Clauses Lit/Cl | |\n");
768  printf("===============================================================================\n");
769  }
770 
771  // Search:
772  int curr_restarts = 0;
773  while (status == l_Undef){
774  double rest_base = luby_restart ? luby(restart_inc, curr_restarts) : pow(restart_inc, curr_restarts);
775  status = search(rest_base * restart_first);
776  if (!withinBudget()) break;
777  curr_restarts++;
778  }
779 
780  if (verbosity >= 1)
781  printf("===============================================================================\n");
782 
783 
784  if (status == l_True){
785  // Extend & copy model:
786  model.growTo(nVars());
787  for (int i = 0; i < nVars(); i++) model[i] = value(i);
788  }else if (status == l_False && conflict.size() == 0)
789  ok = false;
790 
791  cancelUntil(0);
792  return status;
793 }
794 
795 //=================================================================================================
796 // Writing CNF to DIMACS:
797 //
798 // FIXME: this needs to be rewritten completely.
799 
800 static Var mapVar(Var x, vec<Var>& map, Var& max)
801 {
802  if (map.size() <= x || map[x] == -1){
803  map.growTo(x+1, -1);
804  map[x] = max++;
805  }
806  return map[x];
807 }
808 
809 
810 void Solver::toDimacs(FILE* f, Clause& c, vec<Var>& map, Var& max)
811 {
812  if (satisfied(c)) return;
813 
814  for (int i = 0; i < c.size(); i++)
815  if (value(c[i]) != l_False)
816  fprintf(f, "%s%d ", sign(c[i]) ? "-" : "", mapVar(var(c[i]), map, max)+1);
817  fprintf(f, "0\n");
818 }
819 
820 
821 void Solver::toDimacs(const char *file, const vec<Lit>& assumps)
822 {
823  FILE* f = fopen(file, "wr");
824  if (f == NULL)
825  fprintf(stderr, "could not open file %s\n", file), exit(1);
826  toDimacs(f, assumps);
827  fclose(f);
828 }
829 
830 
831 void Solver::toDimacs(FILE* f, const vec<Lit>& assumps)
832 {
833  // Handle case when solver is in contradictory state:
834  if (!ok){
835  fprintf(f, "p cnf 1 2\n1 0\n-1 0\n");
836  return; }
837 
838  vec<Var> map; Var max = 0;
839 
840  // Cannot use removeClauses here because it is not safe
841  // to deallocate them at this point. Could be improved.
842  int i, cnt = 0;
843  for (i = 0; i < clauses.size(); i++)
844  if (!satisfied(ca[clauses[i]]))
845  cnt++;
846 
847  for (i = 0; i < clauses.size(); i++)
848  if (!satisfied(ca[clauses[i]])){
849  Clause& c = ca[clauses[i]];
850  for (int j = 0; j < c.size(); j++)
851  if (value(c[j]) != l_False)
852  mapVar(var(c[j]), map, max);
853  }
854 
855  // Assumptions are added as unit clauses:
856  cnt += assumptions.size();
857 
858  fprintf(f, "p cnf %d %d\n", max, cnt);
859 
860  for (i = 0; i < assumptions.size(); i++){
862  fprintf(f, "%s%d 0\n", sign(assumptions[i]) ? "-" : "", mapVar(var(assumptions[i]), map, max)+1);
863  }
864 
865  for (i = 0; i < clauses.size(); i++)
866  toDimacs(f, ca[clauses[i]], map, max);
867 
868  if (verbosity > 0)
869  printf("Wrote %d clauses with %d variables.\n", cnt, max);
870 }
871 
872 
873 //=================================================================================================
874 // Garbage Collection methods:
875 
877 {
878  // All watchers:
879  //
880  // for (int i = 0; i < watches.size(); i++)
881  watches.cleanAll();
882  for (int v = 0; v < nVars(); v++)
883  for (int s = 0; s < 2; s++){
884  Lit p = mkLit(v, s);
885  // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
886  vec<Watcher>& ws = watches[p];
887  for (int j = 0; j < ws.size(); j++)
888  ca.reloc(ws[j].cref, to);
889  }
890 
891  // All reasons:
892  //
893  int i;
894  for (i = 0; i < trail.size(); i++){
895  Var v = var(trail[i]);
896 
897  if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
898  ca.reloc(vardata[v].reason, to);
899  }
900 
901  // All learnt:
902  //
903  for (i = 0; i < learnts.size(); i++)
904  ca.reloc(learnts[i], to);
905 
906  // All original:
907  //
908  for (i = 0; i < clauses.size(); i++)
909  ca.reloc(clauses[i], to);
910 }
911 
912 
914 {
915  // Initialize the next region to a size corresponding to the estimated utilization degree. This
916  // is not precise but should avoid some unnecessary reallocations for the new region:
917  ClauseAllocator to(ca.size() - ca.wasted());
918 
919  relocAll(to);
920  if (verbosity >= 2)
921  printf("| Garbage collection: %12d bytes => %12d bytes |\n",
923  to.moveTo(ca);
924 }
uint32_t size() const
Definition: Alloc.h:56
RegionAllocator< uint32_t >::Ref CRef
Definition: SolverTypes.h:120
#define INT32_MAX
Definition: pstdint.h:415
uint32_t wasted() const
Definition: Alloc.h:57
double learntsize_inc
Definition: Solver.h:131
VOID_HACK exit()
bool locked(const Clause &c) const
Definition: Solver.h:316
void reduceDB()
Definition: Solver.cpp:525
ClauseAllocator ca
Definition: Solver.h:193
int learntsize_adjust_cnt
Definition: Solver.h:205
bool luby_restart
Definition: Solver.h:121
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:57
char lbool
Definition: satVec.h:133
bool simplify()
Definition: Solver.cpp:577
CRef reason(Var x) const
Definition: Solver.h:277
int level(Var x) const
Definition: Solver.h:278
static DoubleOption opt_clause_decay(_cat,"cla-decay","The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false))
void relocAll(ClauseAllocator &to)
Definition: Solver.cpp:876
static Llb_Mgr_t * p
Definition: llb3Image.c:950
static DoubleOption opt_random_seed(_cat,"rnd-seed","Used by the random variable selection", 91648253, DoubleRange(0, false, HUGE_VAL, false))
int restart_first
Definition: Solver.h:128
#define l_Undef
Definition: SolverTypes.h:86
double learntsize_adjust_inc
Definition: Solver.h:134
bool withinBudget() const
Definition: Solver.h:344
int var(Lit p)
Definition: SolverTypes.h:62
double max_learnts
Definition: Solver.h:203
static IntOption opt_phase_saving(_cat,"phase-saving","Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2))
void claDecayActivity()
Definition: Solver.h:296
double learntsize_factor
Definition: Solver.h:130
void claBumpActivity(Clause &c)
Definition: Solver.h:297
int ccmin_mode
Definition: Solver.h:122
void map()
vec< Lit > conflict
Definition: Solver.h:111
vec< char > polarity
Definition: Solver.h:180
double cla_inc
Definition: Solver.h:174
#define l_True
Definition: SolverTypes.h:84
void newDecisionLevel()
Definition: Solver.h:317
CRef alloc(const Lits &ps, bool learnt=false)
Definition: SolverTypes.h:209
int learntsize_adjust_start_confl
Definition: Solver.h:133
bool sign(Lit p)
Definition: SolverTypes.h:61
uint64_t starts
Definition: Solver.h:138
#define HUGE_VAL
Definition: util_old.h:295
#define false
Definition: place_base.h:29
static BoolOption opt_rnd_init_act(_cat,"rnd-init","Randomize the initial activity", false)
void attachClause(CRef cr)
Definition: Solver.cpp:162
Lit mkLit(Var var, bool sign)
Definition: SolverTypes.h:58
unsigned learnt
Definition: SolverTypes.h:126
lbool search(int nof_conflicts)
Definition: Solver.cpp:614
void setDecisionVar(Var v, bool b)
Definition: Solver.h:331
vec< Lit > analyze_stack
Definition: Solver.h:199
void cancelUntil(int level)
Definition: Solver.cpp:207
void insertVarOrder(Var x)
Definition: Solver.h:280
void copyTo(vec< T > &copy) const
Definition: Vec.h:90
void detachClause(CRef cr, bool strict=false)
Definition: Solver.cpp:171
void removeSatisfied(vec< CRef > &cs)
Definition: Solver.cpp:545
uint64_t dec_vars
Definition: Solver.h:139
void push(void)
Definition: Vec.h:73
vec< int > trail_lim
Definition: Solver.h:183
static Var mapVar(Var x, vec< Var > &map, Var &max)
Definition: Solver.cpp:800
int nVars() const
Definition: Solver.h:328
int size(void) const
Definition: Vec.h:63
float & activity()
Definition: SolverTypes.h:181
bool litRedundant(Lit p, uint32_t abstract_levels)
Definition: Solver.cpp:361
Lit pickBranchLit()
Definition: Solver.cpp:225
uint64_t learnts_literals
Definition: Solver.h:139
const CRef CRef_Undef
Definition: SolverTypes.h:193
int decisionLevel() const
Definition: Solver.h:319
uint64_t decisions
Definition: Solver.h:138
static DoubleOption opt_restart_inc(_cat,"rinc","Restart interval increase factor", 2, DoubleRange(1, false, HUGE_VAL, false))
vec< Lit > assumptions
Definition: Solver.h:188
void checkGarbage()
Definition: Solver.h:304
vec< char > seen
Definition: Solver.h:198
double random_var_freq
Definition: Solver.h:119
vec< CRef > clauses
Definition: Solver.h:172
static IntOption opt_restart_first(_cat,"rfirst","The base restart interval", 100, IntRange(1, INT32_MAX))
void rebuildOrderHeap()
Definition: Solver.cpp:559
double progress_estimate
Definition: Solver.h:190
void shrink(int nelems)
Definition: Vec.h:64
static double max
Definition: cuddSubsetHB.c:134
int nAssigns() const
Definition: Solver.h:325
static int size
Definition: cuddSign.c:86
bool addClause_(vec< Lit > &ps)
Definition: Solver.cpp:132
vec< VarData > vardata
Definition: Solver.h:184
uint64_t clauses_literals
Definition: Solver.h:139
void clear(bool dealloc=false)
Definition: Vec.h:121
int phase_saving
Definition: Solver.h:123
bool rnd_init_act
Definition: Solver.h:125
ClauseAllocator & ca
Definition: Solver.cpp:520
int nClauses() const
Definition: Solver.h:326
reduceDB_lt(ClauseAllocator &ca_)
Definition: Solver.cpp:521
void reloc(CRef &cr, ClauseAllocator &to)
Definition: SolverTypes.h:234
static DoubleOption opt_garbage_frac(_cat,"gc-frac","The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false))
void removeClause(CRef cr)
Definition: Solver.cpp:188
vec< Lit > analyze_toclear
Definition: Solver.h:200
void toDimacs(FILE *f, const vec< Lit > &assumps)
Definition: Solver.cpp:831
vec< lbool > model
Definition: Solver.h:110
static double drand(double &seed)
Definition: Solver.h:262
uint64_t propagations
Definition: Solver.h:138
vec< double > activity
Definition: Solver.h:175
OccLists< Lit, vec< Watcher >, WatcherDeleted > watches
Definition: Solver.h:178
static DoubleOption opt_var_decay(_cat,"var-decay","The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false))
lbool value(Var x) const
Definition: Solver.h:321
lbool solve_()
Definition: Solver.cpp:751
void varDecayActivity()
Definition: Solver.h:283
int simpDB_assigns
Definition: Solver.h:186
static const char * _cat
Definition: Solver.cpp:32
virtual void garbageCollect()
Definition: Solver.cpp:913
static BoolOption opt_luby_restart(_cat,"luby","Use the Luby restart sequence", true)
vec< CRef > learnts
Definition: Solver.h:173
static int irand(double &seed, int size)
Definition: Solver.h:269
static IntOption opt_ccmin_mode(_cat,"ccmin-mode","Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2))
uint64_t solves
Definition: Solver.h:138
static double luby(double y, int x)
Definition: Solver.cpp:734
#define l_False
Definition: SolverTypes.h:85
int Var
Definition: SolverTypes.h:42
double restart_inc
Definition: Solver.h:129
Var newVar(bool polarity=true, bool dvar=true)
Definition: Solver.cpp:114
virtual ~Solver()
Definition: Solver.cpp:102
void analyzeFinal(Lit p, vec< Lit > &out_conflict)
Definition: Solver.cpp:399
void uncheckedEnqueue(Lit p, CRef from=CRef_Undef)
Definition: Solver.cpp:429
const Lit lit_Undef
Definition: SolverTypes.h:72
uint32_t abstractLevel(Var x) const
Definition: Solver.h:320
void analyze(CRef confl, vec< Lit > &out_learnt, int &out_btlevel)
Definition: Solver.cpp:264
vec< Lit > trail
Definition: Solver.h:182
uint64_t max_literals
Definition: Solver.h:139
#define assert(ex)
Definition: util_old.h:213
#define var_Undef
Definition: SolverTypes.h:43
vec< char > decision
Definition: Solver.h:181
int nLearnts() const
Definition: Solver.h:327
#define true
Definition: place_base.h:28
bool satisfied(const Clause &c) const
Definition: Solver.cpp:198
void growTo(int size)
Definition: Vec.h:113
void _free(CRef cid)
Definition: SolverTypes.h:228
double progressEstimate() const
Definition: Solver.cpp:708
int64_t simpDB_props
Definition: Solver.h:187
CRef propagate()
Definition: Solver.cpp:449
static DoubleOption opt_random_var_freq(_cat,"rnd-freq","The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true))
void varBumpActivity(Var v, double inc)
Definition: Solver.h:285
Heap< VarOrderLt > order_heap
Definition: Solver.h:189
vec< lbool > assigns
Definition: Solver.h:179
static VarData mkVarData(CRef cr, int l)
Definition: Solver.h:146
uint64_t rnd_decisions
Definition: Solver.h:138
double random_seed
Definition: Solver.h:120
uint64_t conflicts
Definition: Solver.h:138
const T & last(void) const
Definition: Vec.h:82
uint64_t tot_literals
Definition: Solver.h:139
bool remove_satisfied
Definition: Solver.h:191
double learntsize_adjust_confl
Definition: Solver.h:204
bool rnd_pol
Definition: Solver.h:124