cadical 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +26 -0
  3. data/README.md +101 -0
  4. data/ext/cadical/cadical/LICENSE +28 -0
  5. data/ext/cadical/cadical/README.md +65 -0
  6. data/ext/cadical/cadical/VERSION +1 -0
  7. data/ext/cadical/cadical/src/analyze.cpp +1360 -0
  8. data/ext/cadical/cadical/src/arena.cpp +30 -0
  9. data/ext/cadical/cadical/src/arena.hpp +105 -0
  10. data/ext/cadical/cadical/src/assume.cpp +616 -0
  11. data/ext/cadical/cadical/src/averages.cpp +34 -0
  12. data/ext/cadical/cadical/src/averages.hpp +37 -0
  13. data/ext/cadical/cadical/src/backbone.cpp +631 -0
  14. data/ext/cadical/cadical/src/backtrack.cpp +177 -0
  15. data/ext/cadical/cadical/src/backward.cpp +231 -0
  16. data/ext/cadical/cadical/src/bins.cpp +22 -0
  17. data/ext/cadical/cadical/src/bins.hpp +22 -0
  18. data/ext/cadical/cadical/src/block.cpp +824 -0
  19. data/ext/cadical/cadical/src/block.hpp +37 -0
  20. data/ext/cadical/cadical/src/cadical.cpp +1026 -0
  21. data/ext/cadical/cadical/src/cadical.hpp +1419 -0
  22. data/ext/cadical/cadical/src/ccadical.cpp +208 -0
  23. data/ext/cadical/cadical/src/ccadical.h +74 -0
  24. data/ext/cadical/cadical/src/checker.cpp +649 -0
  25. data/ext/cadical/cadical/src/checker.hpp +173 -0
  26. data/ext/cadical/cadical/src/clause.cpp +689 -0
  27. data/ext/cadical/cadical/src/clause.hpp +190 -0
  28. data/ext/cadical/cadical/src/collect.cpp +545 -0
  29. data/ext/cadical/cadical/src/compact.cpp +550 -0
  30. data/ext/cadical/cadical/src/condition.cpp +940 -0
  31. data/ext/cadical/cadical/src/config.cpp +101 -0
  32. data/ext/cadical/cadical/src/config.hpp +20 -0
  33. data/ext/cadical/cadical/src/congruence.cpp +7880 -0
  34. data/ext/cadical/cadical/src/congruence.hpp +757 -0
  35. data/ext/cadical/cadical/src/constrain.cpp +64 -0
  36. data/ext/cadical/cadical/src/contract.cpp +27 -0
  37. data/ext/cadical/cadical/src/contract.hpp +139 -0
  38. data/ext/cadical/cadical/src/cover.cpp +704 -0
  39. data/ext/cadical/cadical/src/cover.hpp +34 -0
  40. data/ext/cadical/cadical/src/decide.cpp +347 -0
  41. data/ext/cadical/cadical/src/decompose.cpp +738 -0
  42. data/ext/cadical/cadical/src/decompose.hpp +23 -0
  43. data/ext/cadical/cadical/src/deduplicate.cpp +275 -0
  44. data/ext/cadical/cadical/src/definition.cpp +283 -0
  45. data/ext/cadical/cadical/src/delay.hpp +38 -0
  46. data/ext/cadical/cadical/src/drattracer.cpp +153 -0
  47. data/ext/cadical/cadical/src/drattracer.hpp +55 -0
  48. data/ext/cadical/cadical/src/elim.cpp +1171 -0
  49. data/ext/cadical/cadical/src/elim.hpp +53 -0
  50. data/ext/cadical/cadical/src/elimfast.cpp +570 -0
  51. data/ext/cadical/cadical/src/ema.cpp +95 -0
  52. data/ext/cadical/cadical/src/ema.hpp +68 -0
  53. data/ext/cadical/cadical/src/extend.cpp +289 -0
  54. data/ext/cadical/cadical/src/external.cpp +1034 -0
  55. data/ext/cadical/cadical/src/external.hpp +487 -0
  56. data/ext/cadical/cadical/src/external_propagate.cpp +1316 -0
  57. data/ext/cadical/cadical/src/factor.cpp +1011 -0
  58. data/ext/cadical/cadical/src/factor.hpp +54 -0
  59. data/ext/cadical/cadical/src/file.cpp +506 -0
  60. data/ext/cadical/cadical/src/file.hpp +210 -0
  61. data/ext/cadical/cadical/src/flags.cpp +135 -0
  62. data/ext/cadical/cadical/src/flags.hpp +93 -0
  63. data/ext/cadical/cadical/src/flip.cpp +269 -0
  64. data/ext/cadical/cadical/src/format.cpp +89 -0
  65. data/ext/cadical/cadical/src/format.hpp +36 -0
  66. data/ext/cadical/cadical/src/frattracer.cpp +277 -0
  67. data/ext/cadical/cadical/src/frattracer.hpp +67 -0
  68. data/ext/cadical/cadical/src/gates.cpp +766 -0
  69. data/ext/cadical/cadical/src/heap.hpp +212 -0
  70. data/ext/cadical/cadical/src/idruptracer.cpp +566 -0
  71. data/ext/cadical/cadical/src/idruptracer.hpp +112 -0
  72. data/ext/cadical/cadical/src/instantiate.cpp +365 -0
  73. data/ext/cadical/cadical/src/instantiate.hpp +45 -0
  74. data/ext/cadical/cadical/src/internal.cpp +1265 -0
  75. data/ext/cadical/cadical/src/internal.hpp +1941 -0
  76. data/ext/cadical/cadical/src/inttypes.hpp +34 -0
  77. data/ext/cadical/cadical/src/ipasir.cpp +47 -0
  78. data/ext/cadical/cadical/src/ipasir.h +37 -0
  79. data/ext/cadical/cadical/src/kitten.c +2599 -0
  80. data/ext/cadical/cadical/src/kitten.h +97 -0
  81. data/ext/cadical/cadical/src/level.hpp +33 -0
  82. data/ext/cadical/cadical/src/lidruptracer.cpp +657 -0
  83. data/ext/cadical/cadical/src/lidruptracer.hpp +122 -0
  84. data/ext/cadical/cadical/src/limit.cpp +146 -0
  85. data/ext/cadical/cadical/src/limit.hpp +168 -0
  86. data/ext/cadical/cadical/src/logging.cpp +214 -0
  87. data/ext/cadical/cadical/src/logging.hpp +98 -0
  88. data/ext/cadical/cadical/src/lookahead.cpp +520 -0
  89. data/ext/cadical/cadical/src/lratchecker.cpp +833 -0
  90. data/ext/cadical/cadical/src/lratchecker.hpp +168 -0
  91. data/ext/cadical/cadical/src/lrattracer.cpp +200 -0
  92. data/ext/cadical/cadical/src/lrattracer.hpp +61 -0
  93. data/ext/cadical/cadical/src/lucky.cpp +506 -0
  94. data/ext/cadical/cadical/src/message.cpp +218 -0
  95. data/ext/cadical/cadical/src/message.hpp +65 -0
  96. data/ext/cadical/cadical/src/minimize.cpp +224 -0
  97. data/ext/cadical/cadical/src/mobical.cpp +5588 -0
  98. data/ext/cadical/cadical/src/occs.cpp +52 -0
  99. data/ext/cadical/cadical/src/occs.hpp +36 -0
  100. data/ext/cadical/cadical/src/options.cpp +359 -0
  101. data/ext/cadical/cadical/src/options.hpp +442 -0
  102. data/ext/cadical/cadical/src/parse.cpp +471 -0
  103. data/ext/cadical/cadical/src/parse.hpp +75 -0
  104. data/ext/cadical/cadical/src/phases.cpp +56 -0
  105. data/ext/cadical/cadical/src/phases.hpp +19 -0
  106. data/ext/cadical/cadical/src/probe.cpp +990 -0
  107. data/ext/cadical/cadical/src/profile.cpp +107 -0
  108. data/ext/cadical/cadical/src/profile.hpp +283 -0
  109. data/ext/cadical/cadical/src/proof.cpp +691 -0
  110. data/ext/cadical/cadical/src/proof.hpp +125 -0
  111. data/ext/cadical/cadical/src/propagate.cpp +584 -0
  112. data/ext/cadical/cadical/src/queue.cpp +90 -0
  113. data/ext/cadical/cadical/src/queue.hpp +74 -0
  114. data/ext/cadical/cadical/src/radix.hpp +180 -0
  115. data/ext/cadical/cadical/src/random.cpp +207 -0
  116. data/ext/cadical/cadical/src/random.h +44 -0
  117. data/ext/cadical/cadical/src/random.hpp +98 -0
  118. data/ext/cadical/cadical/src/range.hpp +125 -0
  119. data/ext/cadical/cadical/src/reap.cpp +127 -0
  120. data/ext/cadical/cadical/src/reap.hpp +28 -0
  121. data/ext/cadical/cadical/src/reduce.cpp +278 -0
  122. data/ext/cadical/cadical/src/reluctant.hpp +82 -0
  123. data/ext/cadical/cadical/src/rephase.cpp +402 -0
  124. data/ext/cadical/cadical/src/report.cpp +313 -0
  125. data/ext/cadical/cadical/src/resources.cpp +160 -0
  126. data/ext/cadical/cadical/src/resources.hpp +16 -0
  127. data/ext/cadical/cadical/src/restart.cpp +178 -0
  128. data/ext/cadical/cadical/src/restore.cpp +267 -0
  129. data/ext/cadical/cadical/src/score.cpp +51 -0
  130. data/ext/cadical/cadical/src/score.hpp +16 -0
  131. data/ext/cadical/cadical/src/shrink.cpp +507 -0
  132. data/ext/cadical/cadical/src/signal.cpp +136 -0
  133. data/ext/cadical/cadical/src/signal.hpp +33 -0
  134. data/ext/cadical/cadical/src/solution.cpp +50 -0
  135. data/ext/cadical/cadical/src/solver.cpp +1871 -0
  136. data/ext/cadical/cadical/src/stable.cpp +31 -0
  137. data/ext/cadical/cadical/src/stack.h +110 -0
  138. data/ext/cadical/cadical/src/stats.cpp +920 -0
  139. data/ext/cadical/cadical/src/stats.hpp +418 -0
  140. data/ext/cadical/cadical/src/subsume.cpp +645 -0
  141. data/ext/cadical/cadical/src/sweep.cpp +1960 -0
  142. data/ext/cadical/cadical/src/sweep.hpp +61 -0
  143. data/ext/cadical/cadical/src/terminal.cpp +38 -0
  144. data/ext/cadical/cadical/src/terminal.hpp +96 -0
  145. data/ext/cadical/cadical/src/ternary.cpp +450 -0
  146. data/ext/cadical/cadical/src/testing.hpp +24 -0
  147. data/ext/cadical/cadical/src/tier.cpp +189 -0
  148. data/ext/cadical/cadical/src/tracer.hpp +186 -0
  149. data/ext/cadical/cadical/src/transred.cpp +253 -0
  150. data/ext/cadical/cadical/src/unstable.cpp +29 -0
  151. data/ext/cadical/cadical/src/util.cpp +129 -0
  152. data/ext/cadical/cadical/src/util.hpp +181 -0
  153. data/ext/cadical/cadical/src/var.cpp +39 -0
  154. data/ext/cadical/cadical/src/var.hpp +22 -0
  155. data/ext/cadical/cadical/src/veripbtracer.cpp +427 -0
  156. data/ext/cadical/cadical/src/veripbtracer.hpp +106 -0
  157. data/ext/cadical/cadical/src/version.cpp +107 -0
  158. data/ext/cadical/cadical/src/version.hpp +13 -0
  159. data/ext/cadical/cadical/src/vivify.cpp +1893 -0
  160. data/ext/cadical/cadical/src/vivify.hpp +50 -0
  161. data/ext/cadical/cadical/src/walk.cpp +1088 -0
  162. data/ext/cadical/cadical/src/walk.hpp +91 -0
  163. data/ext/cadical/cadical/src/walk_full_occs.cpp +966 -0
  164. data/ext/cadical/cadical/src/warmup.cpp +403 -0
  165. data/ext/cadical/cadical/src/watch.cpp +126 -0
  166. data/ext/cadical/cadical/src/watch.hpp +77 -0
  167. data/ext/cadical/cadical_ext.c +778 -0
  168. data/ext/cadical/extconf.rb +26 -0
  169. data/lib/cadical/version.rb +3 -0
  170. data/lib/cadical.rb +12 -0
  171. metadata +218 -0
@@ -0,0 +1,53 @@
1
+ #ifndef _elim_hpp_INCLUDED
2
+ #define _elim_hpp_INCLUDED
3
+
4
+ #include "heap.hpp" // Alphabetically after 'elim.hpp'.
5
+
6
+ namespace CaDiCaL {
7
+
8
+ struct Internal;
9
+
10
+ struct elim_more {
11
+ Internal *internal;
12
+ elim_more (Internal *i) : internal (i) {}
13
+ bool operator() (unsigned a, unsigned b);
14
+ };
15
+
16
+ typedef heap<elim_more> ElimSchedule;
17
+
18
+ struct proof_clause {
19
+ int64_t id;
20
+ vector<int> literals;
21
+ // for lrat
22
+ unsigned cid; // kitten id
23
+ bool learned;
24
+ vector<int64_t> chain;
25
+ };
26
+
27
+ enum GateType { NO = 0, EQUI = 1, AND = 2, ITE = 3, XOR = 4, DEF = 5 };
28
+
29
+ struct Eliminator {
30
+
31
+ Internal *internal;
32
+ ElimSchedule schedule;
33
+
34
+ Eliminator (Internal *i)
35
+ : internal (i), schedule (elim_more (i)), definition_unit (0),
36
+ gatetype (NO) {}
37
+ ~Eliminator ();
38
+
39
+ queue<Clause *> backward;
40
+
41
+ Clause *dequeue ();
42
+ void enqueue (Clause *);
43
+
44
+ vector<Clause *> gates;
45
+ unsigned definition_unit;
46
+ vector<proof_clause> proof_clauses;
47
+ vector<int> marked;
48
+ GateType gatetype;
49
+ };
50
+
51
+ } // namespace CaDiCaL
52
+
53
+ #endif
@@ -0,0 +1,570 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ /*------------------------------------------------------------------------*/
6
+
7
+ // Implements a variant of elimination with a much lower limit to be run as
8
+ // preprocessing. See elim for comments
9
+
10
+ /*------------------------------------------------------------------------*/
11
+
12
+ // Flush garbage clause, check fast elimination limits and return number of
13
+ // remaining occurrences (or 'fastelimbound + 1' if some limit was hit).
14
+
15
+ int64_t Internal::flush_elimfast_occs (int lit) {
16
+ const int64_t occslim = opts.fastelimocclim;
17
+ const int64_t clslim = opts.fastelimclslim;
18
+ const int64_t failed = occslim + 1;
19
+ Occs &os = occs (lit);
20
+ const const_occs_iterator end = os.end ();
21
+ occs_iterator j = os.begin (), i = j;
22
+ int64_t res = 0;
23
+ while (i != end) {
24
+ Clause *c = *i++;
25
+ if (c->collect ())
26
+ continue;
27
+ *j++ = c;
28
+ if (c->size > clslim) {
29
+ res = failed;
30
+ break;
31
+ }
32
+ if (++res > occslim) {
33
+ assert (opts.fastelimbound < 0 || res == failed);
34
+ break;
35
+ }
36
+ }
37
+ if (i != j) {
38
+ while (i != end)
39
+ *j++ = *i++;
40
+ os.resize (j - os.begin ());
41
+ shrink_occs (os);
42
+ }
43
+ return res;
44
+ }
45
+
46
+ /*------------------------------------------------------------------------*/
47
+
48
+ // Check whether the number of non-tautological resolvents on 'pivot' is
49
+ // smaller or equal to the number of clauses with 'pivot' or '-pivot'. This
50
+ // is the main criteria of bounded variable elimination. As a side effect
51
+ // it flushes garbage clauses with that variable, sorts its occurrence lists
52
+ // (smallest clauses first) and also negates pivot if it has more positive
53
+ // than negative occurrences.
54
+
55
+ bool Internal::elimfast_resolvents_are_bounded (Eliminator &eliminator,
56
+ int pivot) {
57
+ assert (eliminator.gates.empty ());
58
+ assert (!eliminator.definition_unit);
59
+
60
+ stats.elimtried++;
61
+
62
+ assert (!unsat);
63
+ assert (active (pivot));
64
+
65
+ const Occs &ps = occs (pivot);
66
+ const Occs &ns = occs (-pivot);
67
+
68
+ int64_t pos = ps.size ();
69
+ int64_t neg = ns.size ();
70
+
71
+ int64_t bound = opts.fastelimbound;
72
+
73
+ if (!pos || !neg)
74
+ return bound >= 0;
75
+
76
+ const int64_t sum = pos + neg;
77
+ const int64_t product = pos * neg;
78
+ if (bound > sum)
79
+ bound = sum;
80
+
81
+ LOG ("checking number resolvents on %d bounded by "
82
+ "%" PRId64 " = %" PRId64 " + %" PRId64 " + %d",
83
+ pivot, bound, pos, neg, opts.fastelimbound);
84
+
85
+ if (product <= bound) {
86
+ LOG ("fast elimination occurrence limits sufficiently small enough");
87
+ return true;
88
+ }
89
+
90
+ // Try all resolutions between a positive occurrence (outer loop) of
91
+ // 'pivot' and a negative occurrence of 'pivot' (inner loop) as long the
92
+ // bound on non-tautological resolvents is not hit and the size of the
93
+ // generated resolvents does not exceed the resolvent clause size limit.
94
+
95
+ int64_t resolvents = 0; // Non-tautological resolvents.
96
+
97
+ for (const auto &c : ps) {
98
+ assert (!c->redundant);
99
+ if (c->garbage)
100
+ continue;
101
+ for (const auto &d : ns) {
102
+ assert (!d->redundant);
103
+ if (d->garbage)
104
+ continue;
105
+ if (resolve_clauses (eliminator, c, pivot, d, true)) {
106
+ resolvents++;
107
+ int size = clause.size ();
108
+ clause.clear ();
109
+ LOG ("now at least %" PRId64
110
+ " non-tautological resolvents on pivot %d",
111
+ resolvents, pivot);
112
+ if (size > opts.fastelimclslim) {
113
+ LOG ("resolvent size %d too big after %" PRId64
114
+ " resolvents on %d",
115
+ size, resolvents, pivot);
116
+ return false;
117
+ }
118
+ if (resolvents > bound) {
119
+ LOG ("too many non-tautological resolvents on %d", pivot);
120
+ return false;
121
+ }
122
+ } else if (unsat)
123
+ return false;
124
+ else if (val (pivot))
125
+ return false;
126
+ }
127
+ }
128
+
129
+ LOG ("need %" PRId64 " <= %" PRId64 " non-tautological resolvents",
130
+ resolvents, bound);
131
+
132
+ return true;
133
+ }
134
+ /*------------------------------------------------------------------------*/
135
+
136
+ /*------------------------------------------------------------------------*/
137
+ // Add all resolvents on 'pivot' and connect them.
138
+
139
+ inline void Internal::elimfast_add_resolvents (Eliminator &eliminator,
140
+ int pivot) {
141
+
142
+ assert (eliminator.gates.empty ());
143
+ assert (!eliminator.definition_unit);
144
+
145
+ LOG ("adding all resolvents on %d", pivot);
146
+
147
+ assert (!val (pivot));
148
+ assert (!flags (pivot).eliminated ());
149
+
150
+ const Occs &ps = occs (pivot);
151
+ const Occs &ns = occs (-pivot);
152
+ #ifdef LOGGING
153
+ int64_t resolvents = 0;
154
+ #endif
155
+ for (auto &c : ps) {
156
+ if (unsat)
157
+ break;
158
+ if (c->garbage)
159
+ continue;
160
+ for (auto &d : ns) {
161
+ if (unsat)
162
+ break;
163
+ if (d->garbage)
164
+ continue;
165
+ if (!resolve_clauses (eliminator, c, pivot, d, false))
166
+ continue;
167
+ assert (!lrat || !lrat_chain.empty ());
168
+ Clause *r = new_resolved_irredundant_clause ();
169
+ elim_update_added_clause (eliminator, r);
170
+ eliminator.enqueue (r);
171
+ lrat_chain.clear ();
172
+ clause.clear ();
173
+ #ifdef LOGGING
174
+ resolvents++;
175
+ #endif
176
+ }
177
+ }
178
+
179
+ LOG ("added %" PRId64 " resolvents to eliminate %d", resolvents, pivot);
180
+ }
181
+
182
+ /*------------------------------------------------------------------------*/
183
+
184
+ // Try to eliminate 'pivot' by bounded variable elimination.
185
+ void Internal::try_to_fasteliminate_variable (Eliminator &eliminator,
186
+ int pivot,
187
+ bool &deleted_binary_clause) {
188
+
189
+ if (!active (pivot))
190
+ return;
191
+ assert (!frozen (pivot));
192
+
193
+ // First flush garbage clauses and check limits.
194
+
195
+ const int64_t occ_bound = opts.fastelimocclim;
196
+ int64_t bound = opts.fastelimbound;
197
+
198
+ int64_t pos = flush_elimfast_occs (pivot);
199
+ int64_t neg = flush_elimfast_occs (-pivot);
200
+ if (neg && pos > occ_bound) {
201
+ LOG ("too many occurrences thus not eliminated %d", pivot);
202
+ assert (!eliminator.schedule.contains (abs (pivot)));
203
+ return;
204
+ }
205
+
206
+ if (pos && neg > occ_bound) {
207
+ LOG ("too many occurrences thus not eliminated %d", -pivot);
208
+ assert (!eliminator.schedule.contains (abs (pivot)));
209
+ return;
210
+ }
211
+
212
+ const int64_t product = pos * neg;
213
+ const int64_t sum = pos + neg;
214
+ if (bound > sum)
215
+ bound = sum;
216
+
217
+ if (pos > neg) {
218
+ pivot = -pivot;
219
+ swap (pos, neg);
220
+ }
221
+
222
+ LOG ("pivot %d occurs positively %" PRId64
223
+ " times and negatively %" PRId64 " times",
224
+ pivot, pos, neg);
225
+
226
+ assert (!eliminator.schedule.contains (abs (pivot)));
227
+ assert (pos <= neg);
228
+
229
+ LOG ("trying to eliminate %d", pivot);
230
+ assert (!flags (pivot).eliminated ());
231
+
232
+ // Sort occurrence lists, such that shorter clauses come first.
233
+ Occs &ps = occs (pivot);
234
+ stable_sort (ps.begin (), ps.end (), clause_smaller_size ());
235
+ Occs &ns = occs (-pivot);
236
+ stable_sort (ns.begin (), ns.end (), clause_smaller_size ());
237
+
238
+ if (!unsat && !val (pivot)) {
239
+ if (product <= bound ||
240
+ elimfast_resolvents_are_bounded (eliminator, pivot)) {
241
+ LOG ("number of resolvents on %d are bounded", pivot);
242
+ elimfast_add_resolvents (eliminator, pivot);
243
+ if (!unsat)
244
+ mark_eliminated_clauses_as_garbage (eliminator, pivot,
245
+ deleted_binary_clause);
246
+ if (active (pivot))
247
+ mark_eliminated (pivot);
248
+ } else {
249
+ LOG ("too many resolvents on %d so not eliminated", pivot);
250
+ }
251
+ }
252
+
253
+ unmark_gate_clauses (eliminator);
254
+ elim_backward_clauses (eliminator);
255
+ }
256
+
257
+ /*------------------------------------------------------------------------*/
258
+
259
+ // This function performs one round of bounded variable elimination and
260
+ // returns the number of eliminated variables. The additional result
261
+ // 'completed' is true if this elimination round ran to completion (all
262
+ // variables have been tried). Otherwise it was asynchronously terminated
263
+ // or the resolution limit was hit.
264
+
265
+ int Internal::elimfast_round (bool &completed,
266
+ bool &deleted_binary_clause) {
267
+
268
+ assert (opts.fastelim);
269
+ assert (!unsat);
270
+
271
+ START_SIMPLIFIER (fastelim, ELIM);
272
+
273
+ stats.elimfastrounds++;
274
+
275
+ assert (!level);
276
+
277
+ int64_t resolution_limit;
278
+
279
+ if (opts.elimlimited) {
280
+ int64_t delta = stats.propagations.search;
281
+ delta *= 1e-3 * opts.elimeffort;
282
+ if (delta < opts.elimmineff)
283
+ delta = opts.elimmineff;
284
+ if (delta > opts.elimmaxeff)
285
+ delta = opts.elimmaxeff;
286
+
287
+ PHASE ("fastelim-round", stats.elimfastrounds,
288
+ "limit of %" PRId64 " resolutions", delta);
289
+
290
+ resolution_limit = stats.elimres + delta;
291
+ } else {
292
+ PHASE ("fastelim-round", stats.elimfastrounds, "resolutions unlimited");
293
+ resolution_limit = LONG_MAX;
294
+ }
295
+
296
+ init_noccs ();
297
+
298
+ // First compute the number of occurrences of each literal and at the same
299
+ // time mark satisfied clauses and update 'elim' flags of variables in
300
+ // clauses with root level assigned literals (both false and true).
301
+ //
302
+ for (const auto &c : clauses) {
303
+ if (c->garbage || c->redundant)
304
+ continue;
305
+ bool satisfied = false, falsified = false;
306
+ for (const auto &lit : *c) {
307
+ const signed char tmp = val (lit);
308
+ if (tmp > 0)
309
+ satisfied = true;
310
+ else if (tmp < 0)
311
+ falsified = true;
312
+ else
313
+ assert (active (lit));
314
+ }
315
+ if (satisfied)
316
+ mark_garbage (c); // forces more precise counts
317
+ else {
318
+ for (const auto &lit : *c) {
319
+ if (!active (lit))
320
+ continue;
321
+ if (falsified)
322
+ mark_elim (lit); // simulate unit propagation
323
+ noccs (lit)++;
324
+ }
325
+ }
326
+ }
327
+
328
+ init_occs ();
329
+
330
+ Eliminator eliminator (this);
331
+ ElimSchedule &schedule = eliminator.schedule;
332
+ assert (schedule.empty ());
333
+
334
+ // Now find elimination candidates which occurred in clauses removed since
335
+ // the last time we ran bounded variable elimination, which in turned
336
+ // triggered their 'elim' bit to be set.
337
+ //
338
+ for (auto idx : vars) {
339
+ if (!active (idx))
340
+ continue;
341
+ if (frozen (idx))
342
+ continue;
343
+ if (!flags (idx).elim)
344
+ continue;
345
+ LOG ("scheduling %d for elimination initially", idx);
346
+ schedule.push_back (idx);
347
+ }
348
+
349
+ schedule.shrink ();
350
+
351
+ #ifndef QUIET
352
+ int64_t scheduled = schedule.size ();
353
+ #endif
354
+
355
+ PHASE ("fastelim-round", stats.elimfastrounds,
356
+ "scheduled %" PRId64 " variables %.0f%% for elimination",
357
+ scheduled, percent (scheduled, active ()));
358
+
359
+ // Connect irredundant clauses.
360
+ //
361
+ for (const auto &c : clauses)
362
+ if (!c->garbage && !c->redundant)
363
+ for (const auto &lit : *c)
364
+ if (active (lit))
365
+ occs (lit).push_back (c);
366
+
367
+ #ifndef QUIET
368
+ const int64_t old_resolutions = stats.elimres;
369
+ #endif
370
+ const int old_eliminated = stats.all.eliminated;
371
+ const int old_fixed = stats.all.fixed;
372
+
373
+ // Limit on garbage literals during variable elimination. If the limit is
374
+ // hit a garbage collection is performed.
375
+ //
376
+ const int64_t garbage_limit = (2 * stats.irrlits / 3) + (1 << 20);
377
+
378
+ // Main loops tries to eliminate variables according to the schedule. The
379
+ // schedule is updated dynamically and variables are potentially
380
+ // rescheduled to be tried again if they occur in a removed clause.
381
+ //
382
+ #ifndef QUIET
383
+ int64_t tried = 0;
384
+ #endif
385
+ while (!unsat && !terminated_asynchronously () &&
386
+ stats.elimres <= resolution_limit && !schedule.empty ()) {
387
+ int idx = schedule.front ();
388
+ schedule.pop_front ();
389
+ flags (idx).elim = false;
390
+ try_to_fasteliminate_variable (eliminator, idx, deleted_binary_clause);
391
+ #ifndef QUIET
392
+ tried++;
393
+ #endif
394
+ if (stats.garbage.literals <= garbage_limit)
395
+ continue;
396
+ mark_redundant_clauses_with_eliminated_variables_as_garbage ();
397
+ garbage_collection ();
398
+ }
399
+
400
+ // If the schedule is empty all variables have been tried (even
401
+ // rescheduled ones). Otherwise asynchronous termination happened or we
402
+ // ran into the resolution limit (or derived unsatisfiability).
403
+ //
404
+ completed = !schedule.size ();
405
+
406
+ PHASE ("fastelim-round", stats.elimfastrounds,
407
+ "tried to eliminate %" PRId64 " variables %.0f%% (%zd remain)",
408
+ tried, percent (tried, scheduled), schedule.size ());
409
+
410
+ schedule.erase ();
411
+
412
+ reset_occs ();
413
+ reset_noccs ();
414
+
415
+ // Mark all redundant clauses with eliminated variables as garbage.
416
+ //
417
+ if (!unsat)
418
+ mark_redundant_clauses_with_eliminated_variables_as_garbage ();
419
+
420
+ int eliminated = stats.all.eliminated - old_eliminated;
421
+ stats.all.fasteliminated += eliminated;
422
+ #ifndef QUIET
423
+ int64_t resolutions = stats.elimres - old_resolutions;
424
+ PHASE ("fastelim-round", stats.elimfastrounds,
425
+ "eliminated %d variables %.0f%% in %" PRId64 " resolutions",
426
+ eliminated, percent (eliminated, scheduled), resolutions);
427
+ #endif
428
+
429
+ const int units = stats.all.fixed - old_fixed;
430
+ report ('e', !opts.reportall && !(eliminated + units));
431
+ STOP_SIMPLIFIER (fastelim, ELIM);
432
+
433
+ return eliminated; // non-zero if successful
434
+ }
435
+
436
+ /*------------------------------------------------------------------------*/
437
+
438
+ void Internal::elimfast () {
439
+
440
+ if (unsat)
441
+ return;
442
+ if (level)
443
+ backtrack ();
444
+ if (!propagate ()) {
445
+ learn_empty_clause ();
446
+ return;
447
+ }
448
+
449
+ stats.elimfastphases++;
450
+ PHASE ("fastelim-phase", stats.elimfastphases,
451
+ "starting at most %d elimination rounds", opts.fastelimrounds);
452
+
453
+ if (external_prop) {
454
+ assert (!level);
455
+ private_steps = true;
456
+ }
457
+
458
+ #ifndef QUIET
459
+ int old_active_variables = active ();
460
+ int old_eliminated = stats.all.eliminated;
461
+ #endif
462
+
463
+ reset_watches (); // saves lots of memory
464
+
465
+ // Alternate one round of bounded variable elimination ('elim_round') and
466
+ // subsumption ('subsume_round'), blocked ('block') and covered clause
467
+ // elimination ('cover') until nothing changes, or the round limit is hit.
468
+ // The loop also aborts early if no variable could be eliminated, the
469
+ // empty clause is resolved, it is asynchronously terminated or a
470
+ // resolution limit is hit.
471
+
472
+ // This variable determines whether the whole loop of this bounded
473
+ // variable elimination phase ('elim') ran until completion. This
474
+ // potentially triggers an incremental increase of the elimination bound.
475
+ //
476
+ bool phase_complete = false, deleted_binary_clause = false;
477
+
478
+ int round = 1;
479
+ #ifndef QUIET
480
+ int eliminated = 0;
481
+ #endif
482
+
483
+ bool round_complete = false;
484
+ while (!unsat && !phase_complete && !terminated_asynchronously ()) {
485
+ #ifndef QUIET
486
+ int eliminated =
487
+ #endif
488
+ elimfast_round (round_complete, deleted_binary_clause);
489
+
490
+ if (!round_complete) {
491
+ PHASE ("fastelim-phase", stats.elimphases,
492
+ "last round %d incomplete %s", round,
493
+ eliminated ? "but successful" : "and unsuccessful");
494
+ assert (!phase_complete);
495
+ break;
496
+ }
497
+
498
+ if (round++ >= opts.fastelimrounds) {
499
+ PHASE ("fastelim-phase", stats.elimphases, "round limit %d hit (%s)",
500
+ round - 1,
501
+ eliminated ? "though last round successful"
502
+ : "last round unsuccessful anyhow");
503
+ assert (!phase_complete);
504
+ break;
505
+ }
506
+
507
+ // Prioritize 'subsumption' over blocked and covered clause elimination.
508
+
509
+ if (subsume_round ())
510
+ continue;
511
+
512
+ // Was not able to generate new variable elimination candidates after
513
+ // variable elimination round, neither through subsumption, nor blocked,
514
+ // nor covered clause elimination.
515
+ //
516
+ PHASE ("fastelim-phase", stats.elimphases,
517
+ "no new variable elimination candidates");
518
+
519
+ assert (round_complete);
520
+ phase_complete = true;
521
+ }
522
+
523
+ for (auto idx : vars) {
524
+ if (active (idx))
525
+ flags (idx).elim = true;
526
+ }
527
+
528
+ if (phase_complete) {
529
+ stats.elimcompleted++;
530
+ PHASE ("fastelim-phase", stats.elimphases,
531
+ "fully completed elimination %" PRId64
532
+ " at elimination bound %" PRId64 "",
533
+ stats.elimcompleted, lim.elimbound);
534
+ } else {
535
+ PHASE ("fastelim-phase", stats.elimphases,
536
+ "incomplete elimination %" PRId64
537
+ " at elimination bound %" PRId64 "",
538
+ stats.elimcompleted + 1, lim.elimbound);
539
+ }
540
+
541
+ if (deleted_binary_clause)
542
+ delete_garbage_clauses ();
543
+ init_watches ();
544
+ connect_watches ();
545
+
546
+ if (unsat)
547
+ LOG ("elimination derived empty clause");
548
+ else if (propagated < trail.size ()) {
549
+ LOG ("elimination produced %zd units",
550
+ (size_t) (trail.size () - propagated));
551
+ if (!propagate ()) {
552
+ LOG ("propagating units after elimination results in empty clause");
553
+ learn_empty_clause ();
554
+ }
555
+ }
556
+
557
+ #ifndef QUIET
558
+ eliminated = stats.all.eliminated - old_eliminated;
559
+ PHASE ("fastelim-phase", stats.elimphases,
560
+ "eliminated %d variables %.2f%%", eliminated,
561
+ percent (eliminated, old_active_variables));
562
+ #endif
563
+
564
+ if (external_prop) {
565
+ assert (!level);
566
+ private_steps = false;
567
+ }
568
+ }
569
+
570
+ } // namespace CaDiCaL