ruby-minisat 1.14.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -21
  3. data/Gemfile +4 -0
  4. data/LICENSE +3 -2
  5. data/README.md +42 -0
  6. data/Rakefile +1 -48
  7. data/examples/shikaku.rb +2 -2
  8. data/ext/minisat/extconf.rb +19 -4
  9. data/ext/minisat/minisat-wrap.cpp +11 -5
  10. data/ext/minisat/minisat.c +17 -3
  11. data/ext/minisat/minisat.h +1 -1
  12. data/minisat/minisat-2.2.0.tar.gz +0 -0
  13. data/minisat/{MiniSat_v1.14 → minisat}/LICENSE +2 -1
  14. data/minisat/minisat/README +24 -0
  15. data/minisat/minisat/core/Dimacs.h +89 -0
  16. data/minisat/minisat/core/Main.cc +192 -0
  17. data/minisat/minisat/core/Solver.cc +923 -0
  18. data/minisat/minisat/core/Solver.h +373 -0
  19. data/minisat/minisat/core/SolverTypes.h +407 -0
  20. data/minisat/minisat/mtl/Alg.h +84 -0
  21. data/minisat/minisat/mtl/Alloc.h +131 -0
  22. data/minisat/minisat/mtl/Heap.h +148 -0
  23. data/minisat/minisat/mtl/IntTypes.h +42 -0
  24. data/minisat/minisat/mtl/Map.h +193 -0
  25. data/minisat/minisat/mtl/Queue.h +69 -0
  26. data/minisat/{MiniSat_v1.14 → minisat/mtl}/Sort.h +14 -47
  27. data/minisat/minisat/mtl/Vec.h +130 -0
  28. data/minisat/minisat/mtl/XAlloc.h +45 -0
  29. data/minisat/minisat/mtl/config.mk +6 -0
  30. data/minisat/minisat/mtl/template.mk +107 -0
  31. data/minisat/minisat/simp/Main.cc +211 -0
  32. data/minisat/minisat/simp/SimpSolver.cc +717 -0
  33. data/minisat/minisat/simp/SimpSolver.h +197 -0
  34. data/minisat/minisat/utils/Options.cc +91 -0
  35. data/minisat/minisat/utils/Options.h +386 -0
  36. data/minisat/minisat/utils/ParseUtils.h +122 -0
  37. data/minisat/minisat/utils/System.cc +95 -0
  38. data/minisat/minisat/utils/System.h +60 -0
  39. data/ruby-minisat.gemspec +21 -0
  40. metadata +94 -75
  41. data/README.rdoc +0 -56
  42. data/minisat/MiniSat_v1.14.2006-Aug-29.src.zip +0 -0
  43. data/minisat/MiniSat_v1.14/Global.h +0 -274
  44. data/minisat/MiniSat_v1.14/Heap.h +0 -100
  45. data/minisat/MiniSat_v1.14/Main.C +0 -244
  46. data/minisat/MiniSat_v1.14/Makefile +0 -88
  47. data/minisat/MiniSat_v1.14/README +0 -30
  48. data/minisat/MiniSat_v1.14/Solver.C +0 -781
  49. data/minisat/MiniSat_v1.14/Solver.h +0 -206
  50. data/minisat/MiniSat_v1.14/Solver.o +0 -0
  51. data/minisat/MiniSat_v1.14/SolverTypes.h +0 -130
  52. data/minisat/MiniSat_v1.14/TODO +0 -73
  53. data/minisat/MiniSat_v1.14/VarOrder.h +0 -96
@@ -0,0 +1,923 @@
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 "mtl/Sort.h"
24
+ #include "core/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
+
51
+ Solver::Solver() :
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
+
102
+ Solver::~Solver()
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
+
132
+ bool Solver::addClause_(vec<Lit>& ps)
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
+
162
+ void Solver::attachClause(CRef cr) {
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
+
188
+ void Solver::removeClause(CRef cr) {
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]);
217
+ trail_lim.shrink(trail_lim.size() - level);
218
+ } }
219
+
220
+
221
+ //=================================================================================================
222
+ // Major methods:
223
+
224
+
225
+ Lit Solver::pickBranchLit()
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 (int 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){
366
+ assert(reason(var(analyze_stack.last())) != CRef_Undef);
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
+
429
+ void Solver::uncheckedEnqueue(Lit p, CRef from)
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
+ |________________________________________________________________________________________________@*/
449
+ CRef Solver::propagate()
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 {
520
+ ClauseAllocator& ca;
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
+ };
525
+ void Solver::reduceDB()
526
+ {
527
+ int i, j;
528
+ double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity
529
+
530
+ sort(learnts, reduceDB_lt(ca));
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
+
545
+ void Solver::removeSatisfied(vec<CRef>& cs)
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
+
559
+ void Solver::rebuildOrderHeap()
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
+ |________________________________________________________________________________________________@*/
577
+ bool Solver::simplify()
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:
588
+ removeSatisfied(learnts);
589
+ if (remove_satisfied) // Can be turned off.
590
+ removeSatisfied(clauses);
591
+ checkGarbage();
592
+ rebuildOrderHeap();
593
+
594
+ simpDB_assigns = nAssigns();
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
+
643
+ varDecayActivity();
644
+ claDecayActivity();
645
+
646
+ if (--learntsize_adjust_cnt == 0){
647
+ learntsize_adjust_confl *= learntsize_adjust_inc;
648
+ learntsize_adjust_cnt = (int)learntsize_adjust_confl;
649
+ max_learnts *= learntsize_inc;
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)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:
662
+ progress_estimate = progressEstimate();
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:
677
+ Lit p = assumptions[decisionLevel()];
678
+ if (value(p) == l_True){
679
+ // Dummy decision level:
680
+ newDecisionLevel();
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'
701
+ newDecisionLevel();
702
+ uncheckedEnqueue(next);
703
+ }
704
+ }
705
+ }
706
+
707
+
708
+ double Solver::progressEstimate() const
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'.
751
+ lbool Solver::solve_()
752
+ {
753
+ model.clear();
754
+ conflict.clear();
755
+ if (!ok) return l_False;
756
+
757
+ solves++;
758
+
759
+ max_learnts = nClauses() * learntsize_factor;
760
+ learntsize_adjust_confl = learntsize_adjust_start_confl;
761
+ learntsize_adjust_cnt = (int)learntsize_adjust_confl;
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 cnt = 0;
843
+ for (int i = 0; i < clauses.size(); i++)
844
+ if (!satisfied(ca[clauses[i]]))
845
+ cnt++;
846
+
847
+ for (int 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 (int i = 0; i < assumptions.size(); i++){
861
+ assert(value(assumptions[i]) != l_False);
862
+ fprintf(f, "%s%d 0\n", sign(assumptions[i]) ? "-" : "", mapVar(var(assumptions[i]), map, max)+1);
863
+ }
864
+
865
+ for (int 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
+
876
+ void Solver::relocAll(ClauseAllocator& to)
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
+ for (int i = 0; i < trail.size(); i++){
894
+ Var v = var(trail[i]);
895
+
896
+ if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
897
+ ca.reloc(vardata[v].reason, to);
898
+ }
899
+
900
+ // All learnt:
901
+ //
902
+ for (int i = 0; i < learnts.size(); i++)
903
+ ca.reloc(learnts[i], to);
904
+
905
+ // All original:
906
+ //
907
+ for (int i = 0; i < clauses.size(); i++)
908
+ ca.reloc(clauses[i], to);
909
+ }
910
+
911
+
912
+ void Solver::garbageCollect()
913
+ {
914
+ // Initialize the next region to a size corresponding to the estimated utilization degree. This
915
+ // is not precise but should avoid some unnecessary reallocations for the new region:
916
+ ClauseAllocator to(ca.size() - ca.wasted());
917
+
918
+ relocAll(to);
919
+ if (verbosity >= 2)
920
+ printf("| Garbage collection: %12d bytes => %12d bytes |\n",
921
+ ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
922
+ to.moveTo(ca);
923
+ }