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
@@ -1,88 +0,0 @@
1
- ##
2
- ## Makefile for Standard, Profile, Debug, Release, and Release-static versions of MiniSat
3
- ##
4
- ## eg: "make rs" for a statically linked release version.
5
- ## "make d" for a debug version (no optimizations).
6
- ## "make" for the standard version (optimized, but with debug information and assertions active)
7
-
8
- CSRCS = $(wildcard *.C)
9
- CHDRS = $(wildcard *.h)
10
- COBJS = $(addsuffix .o, $(basename $(CSRCS)))
11
-
12
- PCOBJS = $(addsuffix p, $(COBJS))
13
- DCOBJS = $(addsuffix d, $(COBJS))
14
- RCOBJS = $(addsuffix r, $(COBJS))
15
-
16
- EXEC = minisat
17
-
18
- CXX = g++
19
- CFLAGS = -Wall -ffloat-store
20
- COPTIMIZE = -O3
21
-
22
-
23
- .PHONY : s p d r build clean depend
24
-
25
- s: WAY=standard
26
- p: WAY=profile
27
- d: WAY=debug
28
- r: WAY=release
29
- rs: WAY=release static
30
-
31
- s: CFLAGS+=$(COPTIMIZE) -ggdb -D DEBUG
32
- p: CFLAGS+=$(COPTIMIZE) -pg -ggdb -D DEBUG
33
- d: CFLAGS+=-O0 -ggdb -D DEBUG
34
- r: CFLAGS+=$(COPTIMIZE) -D NDEBUG
35
- rs: CFLAGS+=$(COPTIMIZE) -D NDEBUG
36
-
37
- s: build $(EXEC)
38
- p: build $(EXEC)_profile
39
- d: build $(EXEC)_debug
40
- r: build $(EXEC)_release
41
- rs: build $(EXEC)_static
42
-
43
- build:
44
- @echo Building $(EXEC) "("$(WAY)")"
45
-
46
- clean:
47
- @rm -f $(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static \
48
- $(COBJS) $(PCOBJS) $(DCOBJS) $(RCOBJS) depend.mak
49
-
50
- ## Build rule
51
- %.o %.op %.od %.or: %.C
52
- @echo Compiling: $<
53
- @$(CXX) $(CFLAGS) -c -o $@ $<
54
-
55
- ## Linking rules (standard/profile/debug/release)
56
- $(EXEC): $(COBJS)
57
- @echo Linking $(EXEC)
58
- @$(CXX) $(COBJS) -lz -ggdb -Wall -o $@
59
-
60
- $(EXEC)_profile: $(PCOBJS)
61
- @echo Linking $@
62
- @$(CXX) $(PCOBJS) -lz -ggdb -Wall -pg -o $@
63
-
64
- $(EXEC)_debug: $(DCOBJS)
65
- @echo Linking $@
66
- @$(CXX) $(DCOBJS) -lz -ggdb -Wall -o $@
67
-
68
- $(EXEC)_release: $(RCOBJS)
69
- @echo Linking $@
70
- @$(CXX) $(RCOBJS) -lz -Wall -o $@
71
-
72
- $(EXEC)_static: $(RCOBJS)
73
- @echo Linking $@
74
- @$(CXX) --static $(RCOBJS) -lz -Wall -o $@
75
-
76
-
77
- ## Make dependencies
78
- depend: depend.mak
79
- depend.mak: $(CSRCS) $(CHDRS)
80
- @echo Making dependencies ...
81
- @$(CXX) -MM $(CSRCS) > depend.mak
82
- @cp depend.mak /tmp/depend.mak.tmp
83
- @sed "s/o:/op:/" /tmp/depend.mak.tmp >> depend.mak
84
- @sed "s/o:/od:/" /tmp/depend.mak.tmp >> depend.mak
85
- @sed "s/o:/or:/" /tmp/depend.mak.tmp >> depend.mak
86
- @rm /tmp/depend.mak.tmp
87
-
88
- include depend.mak
@@ -1,30 +0,0 @@
1
- MiniSat v1.14 / MiniSat-p v1.14
2
- ========================================
3
-
4
- This version is a cleaned up version of the MiniSat solver entering
5
- the SAT 2005 competition. Some of the most low-level optimization has
6
- been removed for the sake of clarity, resulting in a 5-10% performance
7
- degradation. The guard on "too-many-calls" in 'simplifyDB()' has also
8
- been improved. If uttermost performance is needed, use the competition
9
- version, also available at the MiniSat page
10
- (www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/).
11
-
12
- Several things has changed inside MiniSat since the first version,
13
- documented in the paper "An Extensible SAT Solver". The most important
14
- is the lack of support for non-clausal constraints in this
15
- version. Please use MiniSat v1.12b if you need this. Other changes are
16
- special treatment of binary clauses for efficiency (messes up the code
17
- a bit, but gives quite a speedup), improved variable order (still
18
- VSIDS based, but works MUCH better than in previous MiniSat
19
- versions!), conflict clause minimization (by Niklas S�rensson), and a
20
- better Main module (for those of you who use MiniSat as a stand-alone
21
- solver).
22
-
23
- The MiniSat-p version also supports proof logging, sacrificing the
24
- binary clauses trick for clarity (some 10-20% slower). For
25
- scalability, we decided to keep the proof only on disk. This frees up
26
- memory for the working set of conflict clauses, and allows for
27
- bigger-than-memory proofs to be produced (which can happen, even if
28
- you garbage collect the proof).
29
-
30
- For information about upcomming changes, please review the TODO file.
@@ -1,781 +0,0 @@
1
- /****************************************************************************************[Solver.C]
2
- MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5
- associated documentation files (the "Software"), to deal in the Software without restriction,
6
- including without limitation the rights to use, copy, modify, merge, publish, distribute,
7
- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8
- furnished to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all copies or
11
- substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14
- NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16
- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17
- OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
- **************************************************************************************************/
19
-
20
- #include "Solver.h"
21
- #include "Sort.h"
22
- #include <cmath>
23
-
24
-
25
- //=================================================================================================
26
- // Helper functions:
27
-
28
-
29
- bool removeWatch(vec<GClause>& ws, GClause elem) // Pre-condition: 'elem' must exists in 'ws' OR 'ws' must be empty.
30
- {
31
- if (ws.size() == 0) return false; // (skip lists that are already cleared)
32
- int j = 0;
33
- for (; ws[j] != elem ; j++) assert(j < ws.size());
34
- for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
35
- ws.pop();
36
- return true;
37
- }
38
-
39
-
40
- //=================================================================================================
41
- // Operations on clauses:
42
-
43
-
44
- /*_________________________________________________________________________________________________
45
- |
46
- | newClause : (ps : const vec<Lit>&) (learnt : bool) -> [void]
47
- |
48
- | Description:
49
- | Allocate and add a new clause to the SAT solvers clause database. If a conflict is detected,
50
- | the 'ok' flag is cleared and the solver is in an unusable state (must be disposed).
51
- |
52
- | Input:
53
- | ps - The new clause as a vector of literals.
54
- | learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the
55
- | asserting literal. An appropriate 'enqueue()' operation will be performed on this
56
- | literal. One of the watches will always be on this literal, the other will be set to
57
- | the literal with the highest decision level.
58
- |
59
- | Effect:
60
- | Activity heuristics are updated.
61
- |________________________________________________________________________________________________@*/
62
- void Solver::newClause(const vec<Lit>& ps_, bool learnt)
63
- {
64
- if (!ok) return;
65
-
66
- vec<Lit> qs;
67
- if (!learnt){
68
- assert(decisionLevel() == 0);
69
- ps_.copyTo(qs); // Make a copy of the input vector.
70
-
71
- // Remove duplicates:
72
- sortUnique(qs);
73
-
74
- // Check if clause is satisfied:
75
- for (int i = 0; i < qs.size()-1; i++){
76
- if (qs[i] == ~qs[i+1])
77
- return; }
78
- for (int i = 0; i < qs.size(); i++){
79
- if (value(qs[i]) == l_True)
80
- return; }
81
-
82
- // Remove false literals:
83
- int i, j;
84
- for (i = j = 0; i < qs.size(); i++)
85
- if (value(qs[i]) != l_False)
86
- qs[j++] = qs[i];
87
- qs.shrink(i - j);
88
- }
89
- const vec<Lit>& ps = learnt ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals.
90
-
91
- if (ps.size() == 0){
92
- ok = false;
93
-
94
- }else if (ps.size() == 1){
95
- // NOTE: If enqueue takes place at root level, the assignment will be lost in incremental use (it doesn't seem to hurt much though).
96
- if (!enqueue(ps[0]))
97
- ok = false;
98
-
99
- }else if (ps.size() == 2){
100
- // Create special binary clause watch:
101
- watches[index(~ps[0])].push(GClause_new(ps[1]));
102
- watches[index(~ps[1])].push(GClause_new(ps[0]));
103
-
104
- if (learnt){
105
- check(enqueue(ps[0], GClause_new(~ps[1])));
106
- stats.learnts_literals += ps.size();
107
- }else
108
- stats.clauses_literals += ps.size();
109
- n_bin_clauses++;
110
-
111
- }else{
112
- // Allocate clause:
113
- Clause* c = Clause_new(learnt, ps);
114
-
115
- if (learnt){
116
- // Put the second watch on the literal with highest decision level:
117
- int max_i = 1;
118
- int max = level[var(ps[1])];
119
- for (int i = 2; i < ps.size(); i++)
120
- if (level[var(ps[i])] > max)
121
- max = level[var(ps[i])],
122
- max_i = i;
123
- (*c)[1] = ps[max_i];
124
- (*c)[max_i] = ps[1];
125
-
126
- // Bump, enqueue, store clause:
127
- claBumpActivity(c); // (newly learnt clauses should be considered active)
128
- check(enqueue((*c)[0], GClause_new(c)));
129
- learnts.push(c);
130
- stats.learnts_literals += c->size();
131
- }else{
132
- // Store clause:
133
- clauses.push(c);
134
- stats.clauses_literals += c->size();
135
- }
136
- // Watch clause:
137
- watches[index(~(*c)[0])].push(GClause_new(c));
138
- watches[index(~(*c)[1])].push(GClause_new(c));
139
- }
140
- }
141
-
142
-
143
- // Disposes a clauses and removes it from watcher lists. NOTE! Low-level; does NOT change the 'clauses' and 'learnts' vector.
144
- //
145
- void Solver::remove(Clause* c, bool just_dealloc)
146
- {
147
- if (!just_dealloc){
148
- if (c->size() == 2)
149
- removeWatch(watches[index(~(*c)[0])], GClause_new((*c)[1])),
150
- removeWatch(watches[index(~(*c)[1])], GClause_new((*c)[0]));
151
- else
152
- removeWatch(watches[index(~(*c)[0])], GClause_new(c)),
153
- removeWatch(watches[index(~(*c)[1])], GClause_new(c));
154
- }
155
-
156
- if (c->learnt()) stats.learnts_literals -= c->size();
157
- else stats.clauses_literals -= c->size();
158
-
159
- xfree(c);
160
- }
161
-
162
-
163
- // Can assume everything has been propagated! (esp. the first two literals are != l_False, unless
164
- // the clause is binary and satisfied, in which case the first literal is true)
165
- // Returns True if clause is satisfied (will be removed), False otherwise.
166
- //
167
- bool Solver::simplify(Clause* c) const
168
- {
169
- assert(decisionLevel() == 0);
170
- for (int i = 0; i < c->size(); i++){
171
- if (value((*c)[i]) == l_True)
172
- return true;
173
- }
174
- return false;
175
- }
176
-
177
-
178
- //=================================================================================================
179
- // Minor methods:
180
-
181
-
182
- // Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be
183
- // used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
184
- //
185
- Var Solver::newVar() {
186
- int index;
187
- index = nVars();
188
- watches .push(); // (list for positive literal)
189
- watches .push(); // (list for negative literal)
190
- reason .push(GClause_NULL);
191
- assigns .push(toInt(l_Undef));
192
- level .push(-1);
193
- activity .push(0);
194
- order .newVar();
195
- analyze_seen.push(0);
196
- return index; }
197
-
198
-
199
- // Returns FALSE if immediate conflict.
200
- bool Solver::assume(Lit p) {
201
- trail_lim.push(trail.size());
202
- return enqueue(p); }
203
-
204
-
205
- // Revert to the state at given level.
206
- void Solver::cancelUntil(int level) {
207
- if (decisionLevel() > level){
208
- for (int c = trail.size()-1; c >= trail_lim[level]; c--){
209
- Var x = var(trail[c]);
210
- assigns[x] = toInt(l_Undef);
211
- reason [x] = GClause_NULL;
212
- order.undo(x); }
213
- trail.shrink(trail.size() - trail_lim[level]);
214
- trail_lim.shrink(trail_lim.size() - level);
215
- qhead = trail.size(); } }
216
-
217
-
218
- //=================================================================================================
219
- // Major methods:
220
-
221
-
222
- /*_________________________________________________________________________________________________
223
- |
224
- | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
225
- |
226
- | Description:
227
- | Analyze conflict and produce a reason clause.
228
- |
229
- | Pre-conditions:
230
- | * 'out_learnt' is assumed to be cleared.
231
- | * Current decision level must be greater than root level.
232
- |
233
- | Post-conditions:
234
- | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
235
- |
236
- | Effect:
237
- | Will undo part of the trail, upto but not beyond the assumption of the current decision level.
238
- |________________________________________________________________________________________________@*/
239
- void Solver::analyze(Clause* _confl, vec<Lit>& out_learnt, int& out_btlevel)
240
- {
241
- GClause confl = GClause_new(_confl);
242
- vec<char>& seen = analyze_seen;
243
- int pathC = 0;
244
- Lit p = lit_Undef;
245
-
246
- // Generate conflict clause:
247
- //
248
- out_learnt.push(); // (leave room for the asserting literal)
249
- out_btlevel = 0;
250
- int index = trail.size()-1;
251
- do{
252
- assert(confl != GClause_NULL); // (otherwise should be UIP)
253
-
254
- Clause& c = confl.isLit() ? ((*analyze_tmpbin)[1] = confl.lit(), *analyze_tmpbin)
255
- : *confl.clause();
256
- if (c.learnt())
257
- claBumpActivity(&c);
258
-
259
- for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
260
- Lit q = c[j];
261
- if (!seen[var(q)] && level[var(q)] > 0){
262
- varBumpActivity(q);
263
- seen[var(q)] = 1;
264
- if (level[var(q)] == decisionLevel())
265
- pathC++;
266
- else{
267
- out_learnt.push(q);
268
- out_btlevel = max(out_btlevel, level[var(q)]);
269
- }
270
- }
271
- }
272
-
273
- // Select next clause to look at:
274
- while (!seen[var(trail[index--])]);
275
- p = trail[index+1];
276
- confl = reason[var(p)];
277
- seen[var(p)] = 0;
278
- pathC--;
279
-
280
- }while (pathC > 0);
281
- out_learnt[0] = ~p;
282
-
283
- int i, j;
284
- if (expensive_ccmin){
285
- // Simplify conflict clause (a lot):
286
- //
287
- uint min_level = 0;
288
- for (i = 1; i < out_learnt.size(); i++)
289
- min_level |= 1 << (level[var(out_learnt[i])] & 31); // (maintain an abstraction of levels involved in conflict)
290
-
291
- out_learnt.copyTo(analyze_toclear);
292
- for (i = j = 1; i < out_learnt.size(); i++)
293
- if (reason[var(out_learnt[i])] == GClause_NULL || !analyze_removable(out_learnt[i], min_level))
294
- out_learnt[j++] = out_learnt[i];
295
- }else{
296
- // Simplify conflict clause (a little):
297
- //
298
- out_learnt.copyTo(analyze_toclear);
299
- for (i = j = 1; i < out_learnt.size(); i++){
300
- GClause r = reason[var(out_learnt[i])];
301
- if (r == GClause_NULL)
302
- out_learnt[j++] = out_learnt[i];
303
- else if (r.isLit()){
304
- Lit q = r.lit();
305
- if (!seen[var(q)] && level[var(q)] != 0)
306
- out_learnt[j++] = out_learnt[i];
307
- }else{
308
- Clause& c = *r.clause();
309
- for (int k = 1; k < c.size(); k++)
310
- if (!seen[var(c[k])] && level[var(c[k])] != 0){
311
- out_learnt[j++] = out_learnt[i];
312
- break; }
313
- }
314
- }
315
- }
316
-
317
- stats.max_literals += out_learnt.size();
318
- out_learnt.shrink(i - j);
319
- stats.tot_literals += out_learnt.size();
320
-
321
- for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared)
322
- }
323
-
324
-
325
- // Check if 'p' can be removed. 'min_level' is used to abort early if visiting literals at a level that cannot be removed.
326
- //
327
- bool Solver::analyze_removable(Lit p, uint min_level)
328
- {
329
- assert(reason[var(p)] != GClause_NULL);
330
- analyze_stack.clear(); analyze_stack.push(p);
331
- int top = analyze_toclear.size();
332
- while (analyze_stack.size() > 0){
333
- assert(reason[var(analyze_stack.last())] != GClause_NULL);
334
- GClause r = reason[var(analyze_stack.last())]; analyze_stack.pop();
335
- Clause& c = r.isLit() ? ((*analyze_tmpbin)[1] = r.lit(), *analyze_tmpbin)
336
- : *r.clause();
337
- for (int i = 1; i < c.size(); i++){
338
- Lit p = c[i];
339
- if (!analyze_seen[var(p)] && level[var(p)] != 0){
340
- if (reason[var(p)] != GClause_NULL && ((1 << (level[var(p)] & 31)) & min_level) != 0){
341
- analyze_seen[var(p)] = 1;
342
- analyze_stack.push(p);
343
- analyze_toclear.push(p);
344
- }else{
345
- for (int j = top; j < analyze_toclear.size(); j++)
346
- analyze_seen[var(analyze_toclear[j])] = 0;
347
- analyze_toclear.shrink(analyze_toclear.size() - top);
348
- return false;
349
- }
350
- }
351
- }
352
- }
353
-
354
- return true;
355
- }
356
-
357
-
358
- /*_________________________________________________________________________________________________
359
- |
360
- | analyzeFinal : (confl : Clause*) (skip_first : bool) -> [void]
361
- |
362
- | Description:
363
- | Specialized analysis procedure to express the final conflict in terms of assumptions.
364
- | 'root_level' is allowed to point beyond end of trace (useful if called after conflict while
365
- | making assumptions). If 'skip_first' is TRUE, the first literal of 'confl' is ignored (needed
366
- | if conflict arose before search even started).
367
- |________________________________________________________________________________________________@*/
368
- void Solver::analyzeFinal(Clause* confl, bool skip_first)
369
- {
370
- // -- NOTE! This code is relatively untested. Please report bugs!
371
- conflict.clear();
372
- if (root_level == 0) return;
373
-
374
- vec<char>& seen = analyze_seen;
375
- for (int i = skip_first ? 1 : 0; i < confl->size(); i++){
376
- Var x = var((*confl)[i]);
377
- if (level[x] > 0)
378
- seen[x] = 1;
379
- }
380
-
381
- int start = (root_level >= trail_lim.size()) ? trail.size()-1 : trail_lim[root_level];
382
- for (int i = start; i >= trail_lim[0]; i--){
383
- Var x = var(trail[i]);
384
- if (seen[x]){
385
- GClause r = reason[x];
386
- if (r == GClause_NULL){
387
- assert(level[x] > 0);
388
- conflict.push(~trail[i]);
389
- }else{
390
- if (r.isLit()){
391
- Lit p = r.lit();
392
- if (level[var(p)] > 0)
393
- seen[var(p)] = 1;
394
- }else{
395
- Clause& c = *r.clause();
396
- for (int j = 1; j < c.size(); j++)
397
- if (level[var(c[j])] > 0)
398
- seen[var(c[j])] = 1;
399
- }
400
- }
401
- seen[x] = 0;
402
- }
403
- }
404
- }
405
-
406
-
407
- /*_________________________________________________________________________________________________
408
- |
409
- | enqueue : (p : Lit) (from : Clause*) -> [bool]
410
- |
411
- | Description:
412
- | Puts a new fact on the propagation queue as well as immediately updating the variable's value.
413
- | Should a conflict arise, FALSE is returned.
414
- |
415
- | Input:
416
- | p - The fact to enqueue
417
- | from - [Optional] Fact propagated from this (currently) unit clause. Stored in 'reason[]'.
418
- | Default value is NULL (no reason).
419
- |
420
- | Output:
421
- | TRUE if fact was enqueued without conflict, FALSE otherwise.
422
- |________________________________________________________________________________________________@*/
423
- bool Solver::enqueue(Lit p, GClause from)
424
- {
425
- if (value(p) != l_Undef)
426
- return value(p) != l_False;
427
- else{
428
- assigns[var(p)] = toInt(lbool(!sign(p)));
429
- level [var(p)] = decisionLevel();
430
- reason [var(p)] = from;
431
- trail.push(p);
432
- return true;
433
- }
434
- }
435
-
436
-
437
- /*_________________________________________________________________________________________________
438
- |
439
- | propagate : [void] -> [Clause*]
440
- |
441
- | Description:
442
- | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
443
- | otherwise NULL.
444
- |
445
- | Post-conditions:
446
- | * the propagation queue is empty, even if there was a conflict.
447
- |________________________________________________________________________________________________@*/
448
- Clause* Solver::propagate()
449
- {
450
- Clause* confl = NULL;
451
- while (qhead < trail.size()){
452
- stats.propagations++;
453
- simpDB_props--;
454
-
455
- Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
456
- vec<GClause>& ws = watches[index(p)];
457
- GClause* i,* j, *end;
458
-
459
- for (i = j = (GClause*)ws, end = i + ws.size(); i != end;){
460
- if (i->isLit()){
461
- if (!enqueue(i->lit(), GClause_new(p))){
462
- if (decisionLevel() == 0)
463
- ok = false;
464
- confl = propagate_tmpbin;
465
- (*confl)[1] = ~p;
466
- (*confl)[0] = i->lit();
467
-
468
- qhead = trail.size();
469
- // Copy the remaining watches:
470
- while (i < end)
471
- *j++ = *i++;
472
- }else
473
- *j++ = *i++;
474
- }else{
475
- Clause& c = *i->clause(); i++;
476
- assert(c.size() > 2);
477
- // Make sure the false literal is data[1]:
478
- Lit false_lit = ~p;
479
- if (c[0] == false_lit)
480
- c[0] = c[1], c[1] = false_lit;
481
-
482
- assert(c[1] == false_lit);
483
-
484
- // If 0th watch is true, then clause is already satisfied.
485
- Lit first = c[0];
486
- lbool val = value(first);
487
- if (val == l_True){
488
- *j++ = GClause_new(&c);
489
- }else{
490
- // Look for new watch:
491
- for (int k = 2; k < c.size(); k++)
492
- if (value(c[k]) != l_False){
493
- c[1] = c[k]; c[k] = false_lit;
494
- watches[index(~c[1])].push(GClause_new(&c));
495
- goto FoundWatch; }
496
-
497
- // Did not find watch -- clause is unit under assignment:
498
- *j++ = GClause_new(&c);
499
- if (!enqueue(first, GClause_new(&c))){
500
- if (decisionLevel() == 0)
501
- ok = false;
502
- confl = &c;
503
- qhead = trail.size();
504
- // Copy the remaining watches:
505
- while (i < end)
506
- *j++ = *i++;
507
- }
508
- FoundWatch:;
509
- }
510
- }
511
- }
512
- ws.shrink(i - j);
513
- }
514
-
515
- return confl;
516
- }
517
-
518
-
519
- /*_________________________________________________________________________________________________
520
- |
521
- | reduceDB : () -> [void]
522
- |
523
- | Description:
524
- | Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
525
- | clauses are clauses that are reason to some assignment. Binary clauses are never removed.
526
- |________________________________________________________________________________________________@*/
527
- struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } };
528
- void Solver::reduceDB()
529
- {
530
- int i, j;
531
- double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity
532
-
533
- sort(learnts, reduceDB_lt());
534
- for (i = j = 0; i < learnts.size() / 2; i++){
535
- if (learnts[i]->size() > 2 && !locked(learnts[i]))
536
- remove(learnts[i]);
537
- else
538
- learnts[j++] = learnts[i];
539
- }
540
- for (; i < learnts.size(); i++){
541
- if (learnts[i]->size() > 2 && !locked(learnts[i]) && learnts[i]->activity() < extra_lim)
542
- remove(learnts[i]);
543
- else
544
- learnts[j++] = learnts[i];
545
- }
546
- learnts.shrink(i - j);
547
- }
548
-
549
-
550
- /*_________________________________________________________________________________________________
551
- |
552
- | simplifyDB : [void] -> [bool]
553
- |
554
- | Description:
555
- | Simplify the clause database according to the current top-level assigment. Currently, the only
556
- | thing done here is the removal of satisfied clauses, but more things can be put here.
557
- |________________________________________________________________________________________________@*/
558
- void Solver::simplifyDB()
559
- {
560
- if (!ok) return; // GUARD (public method)
561
- assert(decisionLevel() == 0);
562
-
563
- if (propagate() != NULL){
564
- ok = false;
565
- return; }
566
-
567
- if (nAssigns() == simpDB_assigns || simpDB_props > 0) // (nothing has changed or preformed a simplification too recently)
568
- return;
569
-
570
- // Clear watcher lists:
571
- for (int i = simpDB_assigns; i < nAssigns(); i++){
572
- Lit p = trail[i];
573
- vec<GClause>& ws = watches[index(~p)];
574
- for (int j = 0; j < ws.size(); j++)
575
- if (ws[j].isLit())
576
- if (removeWatch(watches[index(~ws[j].lit())], GClause_new(p))) // (remove binary GClause from "other" watcher list)
577
- n_bin_clauses--;
578
- watches[index( p)].clear(true);
579
- watches[index(~p)].clear(true);
580
- }
581
-
582
- // Remove satisfied clauses:
583
- for (int type = 0; type < 2; type++){
584
- vec<Clause*>& cs = type ? learnts : clauses;
585
- int j = 0;
586
- for (int i = 0; i < cs.size(); i++){
587
- if (!locked(cs[i]) && simplify(cs[i])) // (the test for 'locked()' is currently superfluous, but without it the reason-graph is not correctly maintained for decision level 0)
588
- remove(cs[i]);
589
- else
590
- cs[j++] = cs[i];
591
- }
592
- cs.shrink(cs.size()-j);
593
- }
594
-
595
- simpDB_assigns = nAssigns();
596
- simpDB_props = stats.clauses_literals + stats.learnts_literals; // (shouldn't depend on 'stats' really, but it will do for now)
597
- }
598
-
599
-
600
- /*_________________________________________________________________________________________________
601
- |
602
- | search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool]
603
- |
604
- | Description:
605
- | Search for a model the specified number of conflicts, keeping the number of learnt clauses
606
- | below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to
607
- | 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, int nof_learnts, const SearchParams& params)
615
- {
616
- if (!ok) return l_False; // GUARD (public method)
617
- assert(root_level == decisionLevel());
618
-
619
- stats.starts++;
620
- int conflictC = 0;
621
- var_decay = 1 / params.var_decay;
622
- cla_decay = 1 / params.clause_decay;
623
- model.clear();
624
-
625
- for (;;){
626
- Clause* confl = propagate();
627
- if (confl != NULL){
628
- // CONFLICT
629
-
630
- stats.conflicts++; conflictC++;
631
- vec<Lit> learnt_clause;
632
- int backtrack_level;
633
- if (decisionLevel() == root_level){
634
- // Contradiction found:
635
- analyzeFinal(confl);
636
- return l_False; }
637
- analyze(confl, learnt_clause, backtrack_level);
638
- cancelUntil(max(backtrack_level, root_level));
639
- newClause(learnt_clause, true);
640
- if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0; // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions)
641
- varDecayActivity();
642
- claDecayActivity();
643
-
644
- }else{
645
- // NO CONFLICT
646
-
647
- if (nof_conflicts >= 0 && conflictC >= nof_conflicts){
648
- // Reached bound on number of conflicts:
649
- progress_estimate = progressEstimate();
650
- cancelUntil(root_level);
651
- return l_Undef; }
652
-
653
- if (decisionLevel() == 0)
654
- // Simplify the set of problem clauses:
655
- simplifyDB(), assert(ok);
656
-
657
- if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts)
658
- // Reduce the set of learnt clauses:
659
- reduceDB();
660
-
661
- // New variable decision:
662
- stats.decisions++;
663
- Var next = order.select(params.random_var_freq);
664
-
665
- if (next == var_Undef){
666
- // Model found:
667
- model.growTo(nVars());
668
- for (int i = 0; i < nVars(); i++) model[i] = value(i);
669
- cancelUntil(root_level);
670
- return l_True;
671
- }
672
-
673
- check(assume(~Lit(next)));
674
- }
675
- }
676
- }
677
-
678
-
679
- // Return search-space coverage. Not extremely reliable.
680
- //
681
- double Solver::progressEstimate()
682
- {
683
- double progress = 0;
684
- double F = 1.0 / nVars();
685
- for (int i = 0; i < nVars(); i++)
686
- if (value(i) != l_Undef)
687
- progress += pow(F, level[i]);
688
- return progress / nVars();
689
- }
690
-
691
-
692
- // Divide all variable activities by 1e100.
693
- //
694
- void Solver::varRescaleActivity()
695
- {
696
- for (int i = 0; i < nVars(); i++)
697
- activity[i] *= 1e-100;
698
- var_inc *= 1e-100;
699
- }
700
-
701
-
702
- // Divide all constraint activities by 1e100.
703
- //
704
- void Solver::claRescaleActivity()
705
- {
706
- for (int i = 0; i < learnts.size(); i++)
707
- learnts[i]->activity() *= 1e-20;
708
- cla_inc *= 1e-20;
709
- }
710
-
711
-
712
- /*_________________________________________________________________________________________________
713
- |
714
- | solve : (assumps : const vec<Lit>&) -> [bool]
715
- |
716
- | Description:
717
- | Top-level solve. If using assumptions (non-empty 'assumps' vector), you must call
718
- | 'simplifyDB()' first to see that no top-level conflict is present (which would put the solver
719
- | in an undefined state).
720
- |________________________________________________________________________________________________@*/
721
- bool Solver::solve(const vec<Lit>& assumps)
722
- {
723
- simplifyDB();
724
- if (!ok) return false;
725
-
726
- SearchParams params(default_params);
727
- double nof_conflicts = 100;
728
- double nof_learnts = nClauses() / 3;
729
- lbool status = l_Undef;
730
-
731
- // Perform assumptions:
732
- root_level = assumps.size();
733
- for (int i = 0; i < assumps.size(); i++){
734
- Lit p = assumps[i];
735
- assert(var(p) < nVars());
736
- if (!assume(p)){
737
- GClause r = reason[var(p)];
738
- if (r != GClause_NULL){
739
- Clause* confl;
740
- if (r.isLit()){
741
- confl = propagate_tmpbin;
742
- (*confl)[1] = ~p;
743
- (*confl)[0] = r.lit();
744
- }else
745
- confl = r.clause();
746
- analyzeFinal(confl, true);
747
- conflict.push(~p);
748
- }else
749
- conflict.clear(),
750
- conflict.push(~p);
751
- cancelUntil(0);
752
- return false; }
753
- Clause* confl = propagate();
754
- if (confl != NULL){
755
- analyzeFinal(confl), assert(conflict.size() > 0);
756
- cancelUntil(0);
757
- return false; }
758
- }
759
- assert(root_level == decisionLevel());
760
-
761
- // Search:
762
- if (verbosity >= 1){
763
- reportf("==================================[MINISAT]===================================\n");
764
- reportf("| Conflicts | ORIGINAL | LEARNT | Progress |\n");
765
- reportf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n");
766
- reportf("==============================================================================\n");
767
- }
768
-
769
- while (status == l_Undef){
770
- if (verbosity >= 1)
771
- reportf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (int)stats.learnts_literals, (double)stats.learnts_literals/nLearnts(), progress_estimate*100);
772
- status = search((int)nof_conflicts, (int)nof_learnts, params);
773
- nof_conflicts *= 1.5;
774
- nof_learnts *= 1.1;
775
- }
776
- if (verbosity >= 1)
777
- reportf("==============================================================================\n");
778
-
779
- cancelUntil(0);
780
- return status == l_True;
781
- }