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,211 @@
1
+ /*****************************************************************************************[Main.cc]
2
+ Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
3
+ Copyright (c) 2007, 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 <errno.h>
22
+
23
+ #include <signal.h>
24
+ #include <zlib.h>
25
+ #include <sys/resource.h>
26
+
27
+ #include "utils/System.h"
28
+ #include "utils/ParseUtils.h"
29
+ #include "utils/Options.h"
30
+ #include "core/Dimacs.h"
31
+ #include "simp/SimpSolver.h"
32
+
33
+ using namespace Minisat;
34
+
35
+ //=================================================================================================
36
+
37
+
38
+ void printStats(Solver& solver)
39
+ {
40
+ double cpu_time = cpuTime();
41
+ double mem_used = memUsedPeak();
42
+ printf("restarts : %"PRIu64"\n", solver.starts);
43
+ printf("conflicts : %-12"PRIu64" (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time);
44
+ printf("decisions : %-12"PRIu64" (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time);
45
+ printf("propagations : %-12"PRIu64" (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time);
46
+ printf("conflict literals : %-12"PRIu64" (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals);
47
+ if (mem_used != 0) printf("Memory used : %.2f MB\n", mem_used);
48
+ printf("CPU time : %g s\n", cpu_time);
49
+ }
50
+
51
+
52
+ static Solver* solver;
53
+ // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case
54
+ // for this feature of the Solver as it may take longer than an immediate call to '_exit()'.
55
+ static void SIGINT_interrupt(int signum) { solver->interrupt(); }
56
+
57
+ // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls
58
+ // destructors and may cause deadlocks if a malloc/free function happens to be running (these
59
+ // functions are guarded by locks for multithreaded use).
60
+ static void SIGINT_exit(int signum) {
61
+ printf("\n"); printf("*** INTERRUPTED ***\n");
62
+ if (solver->verbosity > 0){
63
+ printStats(*solver);
64
+ printf("\n"); printf("*** INTERRUPTED ***\n"); }
65
+ _exit(1); }
66
+
67
+
68
+ //=================================================================================================
69
+ // Main:
70
+
71
+ int main(int argc, char** argv)
72
+ {
73
+ try {
74
+ setUsageHelp("USAGE: %s [options] <input-file> <result-output-file>\n\n where input may be either in plain or gzipped DIMACS.\n");
75
+ // printf("This is MiniSat 2.0 beta\n");
76
+
77
+ #if defined(__linux__)
78
+ fpu_control_t oldcw, newcw;
79
+ _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
80
+ printf("WARNING: for repeatability, setting FPU to use double precision\n");
81
+ #endif
82
+ // Extra options:
83
+ //
84
+ IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2));
85
+ BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true);
86
+ StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file.");
87
+ IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX));
88
+ IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX));
89
+
90
+ parseOptions(argc, argv, true);
91
+
92
+ SimpSolver S;
93
+ double initial_time = cpuTime();
94
+
95
+ if (!pre) S.eliminate(true);
96
+
97
+ S.verbosity = verb;
98
+
99
+ solver = &S;
100
+ // Use signal handlers that forcibly quit until the solver will be able to respond to
101
+ // interrupts:
102
+ signal(SIGINT, SIGINT_exit);
103
+ signal(SIGXCPU,SIGINT_exit);
104
+
105
+ // Set limit on CPU-time:
106
+ if (cpu_lim != INT32_MAX){
107
+ rlimit rl;
108
+ getrlimit(RLIMIT_CPU, &rl);
109
+ if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){
110
+ rl.rlim_cur = cpu_lim;
111
+ if (setrlimit(RLIMIT_CPU, &rl) == -1)
112
+ printf("WARNING! Could not set resource limit: CPU-time.\n");
113
+ } }
114
+
115
+ // Set limit on virtual memory:
116
+ if (mem_lim != INT32_MAX){
117
+ rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024;
118
+ rlimit rl;
119
+ getrlimit(RLIMIT_AS, &rl);
120
+ if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){
121
+ rl.rlim_cur = new_mem_lim;
122
+ if (setrlimit(RLIMIT_AS, &rl) == -1)
123
+ printf("WARNING! Could not set resource limit: Virtual memory.\n");
124
+ } }
125
+
126
+ if (argc == 1)
127
+ printf("Reading from standard input... Use '--help' for help.\n");
128
+
129
+ gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
130
+ if (in == NULL)
131
+ printf("ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
132
+
133
+ if (S.verbosity > 0){
134
+ printf("============================[ Problem Statistics ]=============================\n");
135
+ printf("| |\n"); }
136
+
137
+ parse_DIMACS(in, S);
138
+ gzclose(in);
139
+ FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL;
140
+
141
+ if (S.verbosity > 0){
142
+ printf("| Number of variables: %12d |\n", S.nVars());
143
+ printf("| Number of clauses: %12d |\n", S.nClauses()); }
144
+
145
+ double parsed_time = cpuTime();
146
+ if (S.verbosity > 0)
147
+ printf("| Parse time: %12.2f s |\n", parsed_time - initial_time);
148
+
149
+ // Change to signal-handlers that will only notify the solver and allow it to terminate
150
+ // voluntarily:
151
+ signal(SIGINT, SIGINT_interrupt);
152
+ signal(SIGXCPU,SIGINT_interrupt);
153
+
154
+ S.eliminate(true);
155
+ double simplified_time = cpuTime();
156
+ if (S.verbosity > 0){
157
+ printf("| Simplification time: %12.2f s |\n", simplified_time - parsed_time);
158
+ printf("| |\n"); }
159
+
160
+ if (!S.okay()){
161
+ if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
162
+ if (S.verbosity > 0){
163
+ printf("===============================================================================\n");
164
+ printf("Solved by simplification\n");
165
+ printStats(S);
166
+ printf("\n"); }
167
+ printf("UNSATISFIABLE\n");
168
+ exit(20);
169
+ }
170
+
171
+ if (dimacs){
172
+ if (S.verbosity > 0)
173
+ printf("==============================[ Writing DIMACS ]===============================\n");
174
+ S.toDimacs((const char*)dimacs);
175
+ if (S.verbosity > 0)
176
+ printStats(S);
177
+ exit(0);
178
+ }
179
+
180
+ vec<Lit> dummy;
181
+ lbool ret = S.solveLimited(dummy);
182
+
183
+ if (S.verbosity > 0){
184
+ printStats(S);
185
+ printf("\n"); }
186
+ printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n");
187
+ if (res != NULL){
188
+ if (ret == l_True){
189
+ fprintf(res, "SAT\n");
190
+ for (int i = 0; i < S.nVars(); i++)
191
+ if (S.model[i] != l_Undef)
192
+ fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
193
+ fprintf(res, " 0\n");
194
+ }else if (ret == l_False)
195
+ fprintf(res, "UNSAT\n");
196
+ else
197
+ fprintf(res, "INDET\n");
198
+ fclose(res);
199
+ }
200
+
201
+ #ifdef NDEBUG
202
+ exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver')
203
+ #else
204
+ return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
205
+ #endif
206
+ } catch (OutOfMemoryException&){
207
+ printf("===============================================================================\n");
208
+ printf("INDETERMINATE\n");
209
+ exit(0);
210
+ }
211
+ }
@@ -0,0 +1,717 @@
1
+ /***********************************************************************************[SimpSolver.cc]
2
+ Copyright (c) 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 "mtl/Sort.h"
22
+ #include "simp/SimpSolver.h"
23
+ #include "utils/System.h"
24
+
25
+ using namespace Minisat;
26
+
27
+ //=================================================================================================
28
+ // Options:
29
+
30
+
31
+ static const char* _cat = "SIMP";
32
+
33
+ static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false);
34
+ static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false);
35
+ static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true);
36
+ static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0);
37
+ static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX));
38
+ static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX));
39
+ static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false));
40
+
41
+
42
+ //=================================================================================================
43
+ // Constructor/Destructor:
44
+
45
+
46
+ SimpSolver::SimpSolver() :
47
+ grow (opt_grow)
48
+ , clause_lim (opt_clause_lim)
49
+ , subsumption_lim (opt_subsumption_lim)
50
+ , simp_garbage_frac (opt_simp_garbage_frac)
51
+ , use_asymm (opt_use_asymm)
52
+ , use_rcheck (opt_use_rcheck)
53
+ , use_elim (opt_use_elim)
54
+ , merges (0)
55
+ , asymm_lits (0)
56
+ , eliminated_vars (0)
57
+ , elimorder (1)
58
+ , use_simplification (true)
59
+ , occurs (ClauseDeleted(ca))
60
+ , elim_heap (ElimLt(n_occ))
61
+ , bwdsub_assigns (0)
62
+ , n_touched (0)
63
+ {
64
+ vec<Lit> dummy(1,lit_Undef);
65
+ ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
66
+ bwdsub_tmpunit = ca.alloc(dummy);
67
+ remove_satisfied = false;
68
+ }
69
+
70
+
71
+ SimpSolver::~SimpSolver()
72
+ {
73
+ }
74
+
75
+
76
+ Var SimpSolver::newVar(bool sign, bool dvar) {
77
+ Var v = Solver::newVar(sign, dvar);
78
+
79
+ frozen .push((char)false);
80
+ eliminated.push((char)false);
81
+
82
+ if (use_simplification){
83
+ n_occ .push(0);
84
+ n_occ .push(0);
85
+ occurs .init(v);
86
+ touched .push(0);
87
+ elim_heap .insert(v);
88
+ }
89
+ return v; }
90
+
91
+
92
+
93
+ lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
94
+ {
95
+ vec<Var> extra_frozen;
96
+ lbool result = l_True;
97
+
98
+ do_simp &= use_simplification;
99
+
100
+ if (do_simp){
101
+ // Assumptions must be temporarily frozen to run variable elimination:
102
+ for (int i = 0; i < assumptions.size(); i++){
103
+ Var v = var(assumptions[i]);
104
+
105
+ // If an assumption has been eliminated, remember it.
106
+ assert(!isEliminated(v));
107
+
108
+ if (!frozen[v]){
109
+ // Freeze and store.
110
+ setFrozen(v, true);
111
+ extra_frozen.push(v);
112
+ } }
113
+
114
+ result = lbool(eliminate(turn_off_simp));
115
+ }
116
+
117
+ if (result == l_True)
118
+ result = Solver::solve_();
119
+ else if (verbosity >= 1)
120
+ printf("===============================================================================\n");
121
+
122
+ if (result == l_True)
123
+ extendModel();
124
+
125
+ if (do_simp)
126
+ // Unfreeze the assumptions that were frozen:
127
+ for (int i = 0; i < extra_frozen.size(); i++)
128
+ setFrozen(extra_frozen[i], false);
129
+
130
+ return result;
131
+ }
132
+
133
+
134
+
135
+ bool SimpSolver::addClause_(vec<Lit>& ps)
136
+ {
137
+ #ifndef NDEBUG
138
+ for (int i = 0; i < ps.size(); i++)
139
+ assert(!isEliminated(var(ps[i])));
140
+ #endif
141
+
142
+ int nclauses = clauses.size();
143
+
144
+ if (use_rcheck && implied(ps))
145
+ return true;
146
+
147
+ if (!Solver::addClause_(ps))
148
+ return false;
149
+
150
+ if (use_simplification && clauses.size() == nclauses + 1){
151
+ CRef cr = clauses.last();
152
+ const Clause& c = ca[cr];
153
+
154
+ // NOTE: the clause is added to the queue immediately and then
155
+ // again during 'gatherTouchedClauses()'. If nothing happens
156
+ // in between, it will only be checked once. Otherwise, it may
157
+ // be checked twice unnecessarily. This is an unfortunate
158
+ // consequence of how backward subsumption is used to mimic
159
+ // forward subsumption.
160
+ subsumption_queue.insert(cr);
161
+ for (int i = 0; i < c.size(); i++){
162
+ occurs[var(c[i])].push(cr);
163
+ n_occ[toInt(c[i])]++;
164
+ touched[var(c[i])] = 1;
165
+ n_touched++;
166
+ if (elim_heap.inHeap(var(c[i])))
167
+ elim_heap.increase(var(c[i]));
168
+ }
169
+ }
170
+
171
+ return true;
172
+ }
173
+
174
+
175
+ void SimpSolver::removeClause(CRef cr)
176
+ {
177
+ const Clause& c = ca[cr];
178
+
179
+ if (use_simplification)
180
+ for (int i = 0; i < c.size(); i++){
181
+ n_occ[toInt(c[i])]--;
182
+ updateElimHeap(var(c[i]));
183
+ occurs.smudge(var(c[i]));
184
+ }
185
+
186
+ Solver::removeClause(cr);
187
+ }
188
+
189
+
190
+ bool SimpSolver::strengthenClause(CRef cr, Lit l)
191
+ {
192
+ Clause& c = ca[cr];
193
+ assert(decisionLevel() == 0);
194
+ assert(use_simplification);
195
+
196
+ // FIX: this is too inefficient but would be nice to have (properly implemented)
197
+ // if (!find(subsumption_queue, &c))
198
+ subsumption_queue.insert(cr);
199
+
200
+ if (c.size() == 2){
201
+ removeClause(cr);
202
+ c.strengthen(l);
203
+ }else{
204
+ detachClause(cr, true);
205
+ c.strengthen(l);
206
+ attachClause(cr);
207
+ remove(occurs[var(l)], cr);
208
+ n_occ[toInt(l)]--;
209
+ updateElimHeap(var(l));
210
+ }
211
+
212
+ return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true;
213
+ }
214
+
215
+
216
+ // Returns FALSE if clause is always satisfied ('out_clause' should not be used).
217
+ bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
218
+ {
219
+ merges++;
220
+ out_clause.clear();
221
+
222
+ bool ps_smallest = _ps.size() < _qs.size();
223
+ const Clause& ps = ps_smallest ? _qs : _ps;
224
+ const Clause& qs = ps_smallest ? _ps : _qs;
225
+
226
+ for (int i = 0; i < qs.size(); i++){
227
+ if (var(qs[i]) != v){
228
+ for (int j = 0; j < ps.size(); j++)
229
+ if (var(ps[j]) == var(qs[i]))
230
+ if (ps[j] == ~qs[i])
231
+ return false;
232
+ else
233
+ goto next;
234
+ out_clause.push(qs[i]);
235
+ }
236
+ next:;
237
+ }
238
+
239
+ for (int i = 0; i < ps.size(); i++)
240
+ if (var(ps[i]) != v)
241
+ out_clause.push(ps[i]);
242
+
243
+ return true;
244
+ }
245
+
246
+
247
+ // Returns FALSE if clause is always satisfied.
248
+ bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size)
249
+ {
250
+ merges++;
251
+
252
+ bool ps_smallest = _ps.size() < _qs.size();
253
+ const Clause& ps = ps_smallest ? _qs : _ps;
254
+ const Clause& qs = ps_smallest ? _ps : _qs;
255
+ const Lit* __ps = (const Lit*)ps;
256
+ const Lit* __qs = (const Lit*)qs;
257
+
258
+ size = ps.size()-1;
259
+
260
+ for (int i = 0; i < qs.size(); i++){
261
+ if (var(__qs[i]) != v){
262
+ for (int j = 0; j < ps.size(); j++)
263
+ if (var(__ps[j]) == var(__qs[i]))
264
+ if (__ps[j] == ~__qs[i])
265
+ return false;
266
+ else
267
+ goto next;
268
+ size++;
269
+ }
270
+ next:;
271
+ }
272
+
273
+ return true;
274
+ }
275
+
276
+
277
+ void SimpSolver::gatherTouchedClauses()
278
+ {
279
+ if (n_touched == 0) return;
280
+
281
+ int i,j;
282
+ for (i = j = 0; i < subsumption_queue.size(); i++)
283
+ if (ca[subsumption_queue[i]].mark() == 0)
284
+ ca[subsumption_queue[i]].mark(2);
285
+
286
+ for (i = 0; i < touched.size(); i++)
287
+ if (touched[i]){
288
+ const vec<CRef>& cs = occurs.lookup(i);
289
+ for (j = 0; j < cs.size(); j++)
290
+ if (ca[cs[j]].mark() == 0){
291
+ subsumption_queue.insert(cs[j]);
292
+ ca[cs[j]].mark(2);
293
+ }
294
+ touched[i] = 0;
295
+ }
296
+
297
+ for (i = 0; i < subsumption_queue.size(); i++)
298
+ if (ca[subsumption_queue[i]].mark() == 2)
299
+ ca[subsumption_queue[i]].mark(0);
300
+
301
+ n_touched = 0;
302
+ }
303
+
304
+
305
+ bool SimpSolver::implied(const vec<Lit>& c)
306
+ {
307
+ assert(decisionLevel() == 0);
308
+
309
+ trail_lim.push(trail.size());
310
+ for (int i = 0; i < c.size(); i++)
311
+ if (value(c[i]) == l_True){
312
+ cancelUntil(0);
313
+ return false;
314
+ }else if (value(c[i]) != l_False){
315
+ assert(value(c[i]) == l_Undef);
316
+ uncheckedEnqueue(~c[i]);
317
+ }
318
+
319
+ bool result = propagate() != CRef_Undef;
320
+ cancelUntil(0);
321
+ return result;
322
+ }
323
+
324
+
325
+ // Backward subsumption + backward subsumption resolution
326
+ bool SimpSolver::backwardSubsumptionCheck(bool verbose)
327
+ {
328
+ int cnt = 0;
329
+ int subsumed = 0;
330
+ int deleted_literals = 0;
331
+ assert(decisionLevel() == 0);
332
+
333
+ while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){
334
+
335
+ // Empty subsumption queue and return immediately on user-interrupt:
336
+ if (asynch_interrupt){
337
+ subsumption_queue.clear();
338
+ bwdsub_assigns = trail.size();
339
+ break; }
340
+
341
+ // Check top-level assignments by creating a dummy clause and placing it in the queue:
342
+ if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){
343
+ Lit l = trail[bwdsub_assigns++];
344
+ ca[bwdsub_tmpunit][0] = l;
345
+ ca[bwdsub_tmpunit].calcAbstraction();
346
+ subsumption_queue.insert(bwdsub_tmpunit); }
347
+
348
+ CRef cr = subsumption_queue.peek(); subsumption_queue.pop();
349
+ Clause& c = ca[cr];
350
+
351
+ if (c.mark()) continue;
352
+
353
+ if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
354
+ printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals);
355
+
356
+ assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point.
357
+
358
+ // Find best variable to scan:
359
+ Var best = var(c[0]);
360
+ for (int i = 1; i < c.size(); i++)
361
+ if (occurs[var(c[i])].size() < occurs[best].size())
362
+ best = var(c[i]);
363
+
364
+ // Search all candidates:
365
+ vec<CRef>& _cs = occurs.lookup(best);
366
+ CRef* cs = (CRef*)_cs;
367
+
368
+ for (int j = 0; j < _cs.size(); j++)
369
+ if (c.mark())
370
+ break;
371
+ else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){
372
+ Lit l = c.subsumes(ca[cs[j]]);
373
+
374
+ if (l == lit_Undef)
375
+ subsumed++, removeClause(cs[j]);
376
+ else if (l != lit_Error){
377
+ deleted_literals++;
378
+
379
+ if (!strengthenClause(cs[j], ~l))
380
+ return false;
381
+
382
+ // Did current candidate get deleted from cs? Then check candidate at index j again:
383
+ if (var(l) == best)
384
+ j--;
385
+ }
386
+ }
387
+ }
388
+
389
+ return true;
390
+ }
391
+
392
+
393
+ bool SimpSolver::asymm(Var v, CRef cr)
394
+ {
395
+ Clause& c = ca[cr];
396
+ assert(decisionLevel() == 0);
397
+
398
+ if (c.mark() || satisfied(c)) return true;
399
+
400
+ trail_lim.push(trail.size());
401
+ Lit l = lit_Undef;
402
+ for (int i = 0; i < c.size(); i++)
403
+ if (var(c[i]) != v && value(c[i]) != l_False)
404
+ uncheckedEnqueue(~c[i]);
405
+ else
406
+ l = c[i];
407
+
408
+ if (propagate() != CRef_Undef){
409
+ cancelUntil(0);
410
+ asymm_lits++;
411
+ if (!strengthenClause(cr, l))
412
+ return false;
413
+ }else
414
+ cancelUntil(0);
415
+
416
+ return true;
417
+ }
418
+
419
+
420
+ bool SimpSolver::asymmVar(Var v)
421
+ {
422
+ assert(use_simplification);
423
+
424
+ const vec<CRef>& cls = occurs.lookup(v);
425
+
426
+ if (value(v) != l_Undef || cls.size() == 0)
427
+ return true;
428
+
429
+ for (int i = 0; i < cls.size(); i++)
430
+ if (!asymm(v, cls[i]))
431
+ return false;
432
+
433
+ return backwardSubsumptionCheck();
434
+ }
435
+
436
+
437
+ static void mkElimClause(vec<uint32_t>& elimclauses, Lit x)
438
+ {
439
+ elimclauses.push(toInt(x));
440
+ elimclauses.push(1);
441
+ }
442
+
443
+
444
+ static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& c)
445
+ {
446
+ int first = elimclauses.size();
447
+ int v_pos = -1;
448
+
449
+ // Copy clause to elimclauses-vector. Remember position where the
450
+ // variable 'v' occurs:
451
+ for (int i = 0; i < c.size(); i++){
452
+ elimclauses.push(toInt(c[i]));
453
+ if (var(c[i]) == v)
454
+ v_pos = i + first;
455
+ }
456
+ assert(v_pos != -1);
457
+
458
+ // Swap the first literal with the 'v' literal, so that the literal
459
+ // containing 'v' will occur first in the clause:
460
+ uint32_t tmp = elimclauses[v_pos];
461
+ elimclauses[v_pos] = elimclauses[first];
462
+ elimclauses[first] = tmp;
463
+
464
+ // Store the length of the clause last:
465
+ elimclauses.push(c.size());
466
+ }
467
+
468
+
469
+
470
+ bool SimpSolver::eliminateVar(Var v)
471
+ {
472
+ assert(!frozen[v]);
473
+ assert(!isEliminated(v));
474
+ assert(value(v) == l_Undef);
475
+
476
+ // Split the occurrences into positive and negative:
477
+ //
478
+ const vec<CRef>& cls = occurs.lookup(v);
479
+ vec<CRef> pos, neg;
480
+ for (int i = 0; i < cls.size(); i++)
481
+ (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
482
+
483
+ // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
484
+ // clause must exceed the limit on the maximal clause size (if it is set):
485
+ //
486
+ int cnt = 0;
487
+ int clause_size = 0;
488
+
489
+ for (int i = 0; i < pos.size(); i++)
490
+ for (int j = 0; j < neg.size(); j++)
491
+ if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
492
+ (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
493
+ return true;
494
+
495
+ // Delete and store old clauses:
496
+ eliminated[v] = true;
497
+ setDecisionVar(v, false);
498
+ eliminated_vars++;
499
+
500
+ if (pos.size() > neg.size()){
501
+ for (int i = 0; i < neg.size(); i++)
502
+ mkElimClause(elimclauses, v, ca[neg[i]]);
503
+ mkElimClause(elimclauses, mkLit(v));
504
+ }else{
505
+ for (int i = 0; i < pos.size(); i++)
506
+ mkElimClause(elimclauses, v, ca[pos[i]]);
507
+ mkElimClause(elimclauses, ~mkLit(v));
508
+ }
509
+
510
+ for (int i = 0; i < cls.size(); i++)
511
+ removeClause(cls[i]);
512
+
513
+ // Produce clauses in cross product:
514
+ vec<Lit>& resolvent = add_tmp;
515
+ for (int i = 0; i < pos.size(); i++)
516
+ for (int j = 0; j < neg.size(); j++)
517
+ if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent))
518
+ return false;
519
+
520
+ // Free occurs list for this variable:
521
+ occurs[v].clear(true);
522
+
523
+ // Free watchers lists for this variable, if possible:
524
+ if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
525
+ if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
526
+
527
+ return backwardSubsumptionCheck();
528
+ }
529
+
530
+
531
+ bool SimpSolver::substitute(Var v, Lit x)
532
+ {
533
+ assert(!frozen[v]);
534
+ assert(!isEliminated(v));
535
+ assert(value(v) == l_Undef);
536
+
537
+ if (!ok) return false;
538
+
539
+ eliminated[v] = true;
540
+ setDecisionVar(v, false);
541
+ const vec<CRef>& cls = occurs.lookup(v);
542
+
543
+ vec<Lit>& subst_clause = add_tmp;
544
+ for (int i = 0; i < cls.size(); i++){
545
+ Clause& c = ca[cls[i]];
546
+
547
+ subst_clause.clear();
548
+ for (int j = 0; j < c.size(); j++){
549
+ Lit p = c[j];
550
+ subst_clause.push(var(p) == v ? x ^ sign(p) : p);
551
+ }
552
+
553
+ removeClause(cls[i]);
554
+
555
+ if (!addClause_(subst_clause))
556
+ return ok = false;
557
+ }
558
+
559
+ return true;
560
+ }
561
+
562
+
563
+ void SimpSolver::extendModel()
564
+ {
565
+ int i, j;
566
+ Lit x;
567
+
568
+ for (i = elimclauses.size()-1; i > 0; i -= j){
569
+ for (j = elimclauses[i--]; j > 1; j--, i--)
570
+ if (modelValue(toLit(elimclauses[i])) != l_False)
571
+ goto next;
572
+
573
+ x = toLit(elimclauses[i]);
574
+ model[var(x)] = lbool(!sign(x));
575
+ next:;
576
+ }
577
+ }
578
+
579
+
580
+ bool SimpSolver::eliminate(bool turn_off_elim)
581
+ {
582
+ if (!simplify())
583
+ return false;
584
+ else if (!use_simplification)
585
+ return true;
586
+
587
+ // Main simplification loop:
588
+ //
589
+ while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){
590
+
591
+ gatherTouchedClauses();
592
+ // printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
593
+ if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
594
+ !backwardSubsumptionCheck(true)){
595
+ ok = false; goto cleanup; }
596
+
597
+ // Empty elim_heap and return immediately on user-interrupt:
598
+ if (asynch_interrupt){
599
+ assert(bwdsub_assigns == trail.size());
600
+ assert(subsumption_queue.size() == 0);
601
+ assert(n_touched == 0);
602
+ elim_heap.clear();
603
+ goto cleanup; }
604
+
605
+ // printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
606
+ for (int cnt = 0; !elim_heap.empty(); cnt++){
607
+ Var elim = elim_heap.removeMin();
608
+
609
+ if (asynch_interrupt) break;
610
+
611
+ if (isEliminated(elim) || value(elim) != l_Undef) continue;
612
+
613
+ if (verbosity >= 2 && cnt % 100 == 0)
614
+ printf("elimination left: %10d\r", elim_heap.size());
615
+
616
+ if (use_asymm){
617
+ // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again:
618
+ bool was_frozen = frozen[elim];
619
+ frozen[elim] = true;
620
+ if (!asymmVar(elim)){
621
+ ok = false; goto cleanup; }
622
+ frozen[elim] = was_frozen; }
623
+
624
+ // At this point, the variable may have been set by assymetric branching, so check it
625
+ // again. Also, don't eliminate frozen variables:
626
+ if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){
627
+ ok = false; goto cleanup; }
628
+
629
+ checkGarbage(simp_garbage_frac);
630
+ }
631
+
632
+ assert(subsumption_queue.size() == 0);
633
+ }
634
+ cleanup:
635
+
636
+ // If no more simplification is needed, free all simplification-related data structures:
637
+ if (turn_off_elim){
638
+ touched .clear(true);
639
+ occurs .clear(true);
640
+ n_occ .clear(true);
641
+ elim_heap.clear(true);
642
+ subsumption_queue.clear(true);
643
+
644
+ use_simplification = false;
645
+ remove_satisfied = true;
646
+ ca.extra_clause_field = false;
647
+
648
+ // Force full cleanup (this is safe and desirable since it only happens once):
649
+ rebuildOrderHeap();
650
+ garbageCollect();
651
+ }else{
652
+ // Cheaper cleanup:
653
+ cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow?
654
+ checkGarbage();
655
+ }
656
+
657
+ if (verbosity >= 1 && elimclauses.size() > 0)
658
+ printf("| Eliminated clauses: %10.2f Mb |\n",
659
+ double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
660
+
661
+ return ok;
662
+ }
663
+
664
+
665
+ void SimpSolver::cleanUpClauses()
666
+ {
667
+ occurs.cleanAll();
668
+ int i,j;
669
+ for (i = j = 0; i < clauses.size(); i++)
670
+ if (ca[clauses[i]].mark() == 0)
671
+ clauses[j++] = clauses[i];
672
+ clauses.shrink(i - j);
673
+ }
674
+
675
+
676
+ //=================================================================================================
677
+ // Garbage Collection methods:
678
+
679
+
680
+ void SimpSolver::relocAll(ClauseAllocator& to)
681
+ {
682
+ if (!use_simplification) return;
683
+
684
+ // All occurs lists:
685
+ //
686
+ for (int i = 0; i < nVars(); i++){
687
+ vec<CRef>& cs = occurs[i];
688
+ for (int j = 0; j < cs.size(); j++)
689
+ ca.reloc(cs[j], to);
690
+ }
691
+
692
+ // Subsumption queue:
693
+ //
694
+ for (int i = 0; i < subsumption_queue.size(); i++)
695
+ ca.reloc(subsumption_queue[i], to);
696
+
697
+ // Temporary clause:
698
+ //
699
+ ca.reloc(bwdsub_tmpunit, to);
700
+ }
701
+
702
+
703
+ void SimpSolver::garbageCollect()
704
+ {
705
+ // Initialize the next region to a size corresponding to the estimated utilization degree. This
706
+ // is not precise but should avoid some unnecessary reallocations for the new region:
707
+ ClauseAllocator to(ca.size() - ca.wasted());
708
+
709
+ cleanUpClauses();
710
+ to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
711
+ relocAll(to);
712
+ Solver::relocAll(to);
713
+ if (verbosity >= 2)
714
+ printf("| Garbage collection: %12d bytes => %12d bytes |\n",
715
+ ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
716
+ to.moveTo(ca);
717
+ }