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,766 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ /*------------------------------------------------------------------------*/
6
+
7
+ // As in our original SATeLite published at SAT'05 we are trying to find
8
+ // gates in order to restrict the number of resolutions that need to be
9
+ // tried. If there is such a gate, we only need to consider resolvents
10
+ // among gate and one non-gate clauses. Resolvents between definitions will
11
+ // be tautological anyhow and resolvents among non-gates can actually be
12
+ // shown to be redundant too.
13
+
14
+ /*------------------------------------------------------------------------*/
15
+
16
+ // The next function returns a non-zero if the clause 'c', which is assumed
17
+ // to contain the literal 'first', after removing falsified literals is a
18
+ // binary clause. Then the actual second literal is returned.
19
+
20
+ int Internal::second_literal_in_binary_clause (Eliminator &eliminator,
21
+ Clause *c, int first) {
22
+ assert (!c->garbage);
23
+ int second = 0;
24
+ for (const auto &lit : *c) {
25
+ if (lit == first)
26
+ continue;
27
+ const signed char tmp = val (lit);
28
+ if (tmp < 0)
29
+ continue;
30
+ if (tmp > 0) {
31
+ mark_garbage (c);
32
+ elim_update_removed_clause (eliminator, c);
33
+ return 0;
34
+ }
35
+ if (second) {
36
+ second = INT_MIN;
37
+ break;
38
+ }
39
+ second = lit;
40
+ }
41
+ if (!second)
42
+ return 0;
43
+ if (second == INT_MIN)
44
+ return 0;
45
+ assert (active (second));
46
+ #ifdef LOGGING
47
+ if (c->size == 2)
48
+ LOG (c, "found binary");
49
+ else
50
+ LOG (c, "found actual binary %d %d", first, second);
51
+ #endif
52
+ return second;
53
+ }
54
+
55
+ /*------------------------------------------------------------------------*/
56
+
57
+ // need a copy from above that does not care about garbage
58
+
59
+ int Internal::second_literal_in_binary_clause_lrat (Clause *c, int first) {
60
+ if (c->garbage)
61
+ return 0;
62
+ int second = 0;
63
+ for (const auto &lit : *c) {
64
+ if (lit == first)
65
+ continue;
66
+ const signed char tmp = val (lit);
67
+ if (tmp < 0)
68
+ continue;
69
+ if (tmp > 0)
70
+ return 0;
71
+ if (!tmp) {
72
+ if (second) {
73
+ second = INT_MIN;
74
+ break;
75
+ }
76
+ second = lit;
77
+ }
78
+ }
79
+ if (!second)
80
+ return 0;
81
+ if (second == INT_MIN)
82
+ return 0;
83
+ return second;
84
+ }
85
+
86
+ // I needed to find the second clause for hyper unary resolution to build
87
+ // LRAT this is not efficient but I could not find a better way then just
88
+ // finding the corresponding clause in all possible clauses
89
+ //
90
+ Clause *Internal::find_binary_clause (int first, int second) {
91
+ int best = first;
92
+ int other = second;
93
+ if (occs (first).size () > occs (second).size ()) {
94
+ best = second;
95
+ other = first;
96
+ }
97
+ for (auto c : occs (best))
98
+ if (second_literal_in_binary_clause_lrat (c, best) == other)
99
+ return c;
100
+ return 0;
101
+ }
102
+
103
+ /*------------------------------------------------------------------------*/
104
+
105
+ // Mark all other literals in binary clauses with 'first'. During this
106
+ // marking we might also detect hyper unary resolvents producing a unit.
107
+ // If such a unit is found we propagate it and return immediately.
108
+
109
+ void Internal::mark_binary_literals (Eliminator &eliminator, int first) {
110
+
111
+ if (unsat)
112
+ return;
113
+ if (val (first))
114
+ return;
115
+ if (!eliminator.gates.empty ())
116
+ return;
117
+
118
+ assert (!marked (first));
119
+ assert (eliminator.marked.empty ());
120
+
121
+ const Occs &os = occs (first);
122
+ for (const auto &c : os) {
123
+ if (c->garbage)
124
+ continue;
125
+ const int second =
126
+ second_literal_in_binary_clause (eliminator, c, first);
127
+ if (!second)
128
+ continue;
129
+ const int tmp = marked (second);
130
+ if (tmp < 0) {
131
+ // had a bug where units could occur multiple times here
132
+ // solved with flags
133
+ LOG ("found binary resolved unit %d", first);
134
+ if (lrat) {
135
+ Clause *d = find_binary_clause (first, -second);
136
+ assert (d);
137
+ for (auto &lit : *d) {
138
+ if (lit == first || lit == -second)
139
+ continue;
140
+ assert (val (lit) < 0);
141
+ Flags &f = flags (lit);
142
+ if (f.seen)
143
+ continue;
144
+ analyzed.push_back (lit);
145
+ f.seen = true;
146
+ int64_t id = unit_id (-lit);
147
+ lrat_chain.push_back (id);
148
+ // LOG ("gates added id %" PRId64, id);
149
+ }
150
+ for (auto &lit : *c) {
151
+ if (lit == first || lit == second)
152
+ continue;
153
+ assert (val (lit) < 0);
154
+ Flags &f = flags (lit);
155
+ if (f.seen)
156
+ continue;
157
+ analyzed.push_back (lit);
158
+ f.seen = true;
159
+ int64_t id = unit_id (-lit);
160
+ lrat_chain.push_back (id);
161
+ // LOG ("gates added id %" PRId64, id);
162
+ }
163
+ lrat_chain.push_back (c->id);
164
+ lrat_chain.push_back (d->id);
165
+ // LOG ("gates added id %" PRId64, c->id);
166
+ // LOG ("gates added id %" PRId64, d->id);
167
+ clear_analyzed_literals ();
168
+ }
169
+ assign_unit (first);
170
+ elim_propagate (eliminator, first);
171
+ return;
172
+ }
173
+ if (tmp > 0) {
174
+ LOG (c, "duplicated actual binary clause");
175
+ elim_update_removed_clause (eliminator, c);
176
+ mark_garbage (c);
177
+ continue;
178
+ }
179
+ eliminator.marked.push_back (second);
180
+ mark (second);
181
+ LOG ("marked second literal %d in binary clause %d %d", second, first,
182
+ second);
183
+ }
184
+ }
185
+
186
+ // Unmark all literals saved on the 'marked' stack.
187
+
188
+ void Internal::unmark_binary_literals (Eliminator &eliminator) {
189
+ LOG ("unmarking %zd literals", eliminator.marked.size ());
190
+ for (const auto &lit : eliminator.marked)
191
+ unmark (lit);
192
+ eliminator.marked.clear ();
193
+ }
194
+
195
+ /*------------------------------------------------------------------------*/
196
+
197
+ // Find equivalence for 'pivot'. Requires that all other literals in binary
198
+ // clauses with 'pivot' are marked (through 'mark_binary_literals');
199
+
200
+ void Internal::find_equivalence (Eliminator &eliminator, int pivot) {
201
+
202
+ if (!opts.elimequivs)
203
+ return;
204
+
205
+ assert (opts.elimsubst);
206
+
207
+ if (unsat)
208
+ return;
209
+ if (val (pivot))
210
+ return;
211
+ if (!eliminator.gates.empty ())
212
+ return;
213
+
214
+ mark_binary_literals (eliminator, pivot);
215
+ if (unsat || val (pivot))
216
+ goto DONE;
217
+
218
+ for (const auto &c : occs (-pivot)) {
219
+
220
+ if (c->garbage)
221
+ continue;
222
+
223
+ const int second =
224
+ second_literal_in_binary_clause (eliminator, c, -pivot);
225
+ if (!second)
226
+ continue;
227
+ const int tmp = marked (second);
228
+ if (tmp > 0) {
229
+ LOG ("found binary resolved unit %d", second);
230
+ // did not find a bug where units could occur multiple times here
231
+ // still solved potential issues with flags
232
+ if (lrat) {
233
+ Clause *d = find_binary_clause (pivot, second);
234
+ assert (d);
235
+ for (auto &lit : *d) {
236
+ if (lit == pivot || lit == second)
237
+ continue;
238
+ assert (val (lit) < 0);
239
+ Flags &f = flags (lit);
240
+ if (f.seen)
241
+ continue;
242
+ analyzed.push_back (lit);
243
+ f.seen = true;
244
+ int64_t id = unit_id (-lit);
245
+ lrat_chain.push_back (id);
246
+ // LOG ("gates added id %" PRId64, id);
247
+ }
248
+ for (auto &lit : *c) {
249
+ if (lit == -pivot || lit == second)
250
+ continue;
251
+ assert (val (lit) < 0);
252
+ Flags &f = flags (lit);
253
+ if (f.seen)
254
+ continue;
255
+ analyzed.push_back (lit);
256
+ f.seen = true;
257
+ int64_t id = unit_id (-lit);
258
+ lrat_chain.push_back (id);
259
+ // LOG ("gates added id %" PRId64, id);
260
+ }
261
+ lrat_chain.push_back (c->id);
262
+ lrat_chain.push_back (d->id);
263
+ clear_analyzed_literals ();
264
+ // LOG ("gates added id %" PRId64, c->id);
265
+ // LOG ("gates added id %" PRId64, d->id);
266
+ }
267
+ assign_unit (second);
268
+ elim_propagate (eliminator, second);
269
+ if (val (pivot))
270
+ break;
271
+ if (unsat)
272
+ break;
273
+ }
274
+ if (tmp >= 0)
275
+ continue;
276
+
277
+ LOG ("found equivalence %d = %d", pivot, -second);
278
+ stats.elimequivs++;
279
+ stats.elimgates++;
280
+
281
+ LOG (c, "first gate clause");
282
+ assert (!c->gate);
283
+ c->gate = true;
284
+ eliminator.gates.push_back (c);
285
+
286
+ Clause *d = 0;
287
+ const Occs &ps = occs (pivot);
288
+ for (const auto &e : ps) {
289
+ if (e->garbage)
290
+ continue;
291
+ const int other =
292
+ second_literal_in_binary_clause (eliminator, e, pivot);
293
+ if (other == -second) {
294
+ d = e;
295
+ break;
296
+ }
297
+ }
298
+ assert (d);
299
+
300
+ LOG (d, "second gate clause");
301
+ assert (!d->gate);
302
+ d->gate = true;
303
+ eliminator.gates.push_back (d);
304
+ eliminator.gatetype = EQUI;
305
+
306
+ break;
307
+ }
308
+
309
+ DONE:
310
+ unmark_binary_literals (eliminator);
311
+ }
312
+
313
+ /*------------------------------------------------------------------------*/
314
+
315
+ // Find and gates for 'pivot' with a long clause, in which the pivot occurs
316
+ // positively. Requires that all other literals in binary clauses with
317
+ // 'pivot' are marked (through 'mark_binary_literals');
318
+
319
+ void Internal::find_and_gate (Eliminator &eliminator, int pivot) {
320
+
321
+ if (!opts.elimands)
322
+ return;
323
+
324
+ assert (opts.elimsubst);
325
+
326
+ if (unsat)
327
+ return;
328
+ if (val (pivot))
329
+ return;
330
+ if (!eliminator.gates.empty ())
331
+ return;
332
+
333
+ mark_binary_literals (eliminator, pivot);
334
+ if (unsat || val (pivot))
335
+ goto DONE;
336
+
337
+ for (const auto &c : occs (-pivot)) {
338
+
339
+ if (c->garbage)
340
+ continue;
341
+ if (c->size < 3)
342
+ continue;
343
+
344
+ bool all_literals_marked = true;
345
+ unsigned arity = 0;
346
+ int satisfied = 0;
347
+
348
+ for (const auto &lit : *c) {
349
+ if (lit == -pivot)
350
+ continue;
351
+ assert (lit != pivot);
352
+ signed char tmp = val (lit);
353
+ if (tmp < 0)
354
+ continue;
355
+ if (tmp > 0) {
356
+ satisfied = lit;
357
+ break;
358
+ }
359
+ tmp = marked (lit);
360
+ if (tmp < 0) {
361
+ arity++;
362
+ continue;
363
+ }
364
+ all_literals_marked = false;
365
+ break;
366
+ }
367
+
368
+ if (!all_literals_marked)
369
+ continue;
370
+
371
+ if (satisfied) {
372
+ LOG (c, "satisfied by %d candidate base clause", satisfied);
373
+ mark_garbage (c);
374
+ continue;
375
+ }
376
+
377
+ #ifdef LOGGING
378
+ if (opts.log) {
379
+ Logger::print_log_prefix (this);
380
+ tout.magenta ();
381
+ printf ("found arity %u AND gate %d = ", arity, -pivot);
382
+ bool first = true;
383
+ for (const auto &lit : *c) {
384
+ if (lit == -pivot)
385
+ continue;
386
+ assert (lit != pivot);
387
+ if (!first)
388
+ fputs (" & ", stdout);
389
+ printf ("%d", -lit);
390
+ first = false;
391
+ }
392
+ fputc ('\n', stdout);
393
+ tout.normal ();
394
+ fflush (stdout);
395
+ }
396
+ #endif
397
+ stats.elimands++;
398
+ stats.elimgates++;
399
+ eliminator.gatetype = AND;
400
+
401
+ (void) arity;
402
+ assert (!c->gate);
403
+ c->gate = true;
404
+ eliminator.gates.push_back (c);
405
+ for (const auto &lit : *c) {
406
+ if (lit == -pivot)
407
+ continue;
408
+ assert (lit != pivot);
409
+ signed char tmp = val (lit);
410
+ if (tmp < 0)
411
+ continue;
412
+ assert (!tmp);
413
+ assert (marked (lit) < 0);
414
+ marks[vidx (lit)] *= 2;
415
+ }
416
+
417
+ unsigned count = 0;
418
+ for (const auto &d : occs (pivot)) {
419
+ if (d->garbage)
420
+ continue;
421
+ const int other =
422
+ second_literal_in_binary_clause (eliminator, d, pivot);
423
+ if (!other)
424
+ continue;
425
+ const int tmp = marked (other);
426
+ if (tmp != 2)
427
+ continue;
428
+ LOG (d, "AND gate binary side clause");
429
+ assert (!d->gate);
430
+ d->gate = true;
431
+ eliminator.gates.push_back (d);
432
+ count++;
433
+ }
434
+ assert (count >= arity);
435
+ (void) count;
436
+
437
+ break;
438
+ }
439
+
440
+ DONE:
441
+ unmark_binary_literals (eliminator);
442
+ }
443
+
444
+ /*------------------------------------------------------------------------*/
445
+
446
+ // Find and extract ternary clauses.
447
+
448
+ bool Internal::get_ternary_clause (Clause *d, int &a, int &b, int &c) {
449
+ if (d->garbage)
450
+ return false;
451
+ if (d->size < 3)
452
+ return false;
453
+ int found = 0;
454
+ a = b = c = 0;
455
+ for (const auto &lit : *d) {
456
+ if (val (lit))
457
+ continue;
458
+ if (++found == 1)
459
+ a = lit;
460
+ else if (found == 2)
461
+ b = lit;
462
+ else if (found == 3)
463
+ c = lit;
464
+ else
465
+ return false;
466
+ }
467
+ return found == 3;
468
+ }
469
+
470
+ // This function checks whether 'd' exists as ternary clause.
471
+
472
+ bool Internal::match_ternary_clause (Clause *d, int a, int b, int c) {
473
+ if (d->garbage)
474
+ return false;
475
+ int found = 0;
476
+ for (const auto &lit : *d) {
477
+ if (val (lit))
478
+ continue;
479
+ if (a != lit && b != lit && c != lit)
480
+ return false;
481
+ found++;
482
+ }
483
+ return found == 3;
484
+ }
485
+
486
+ Clause *Internal::find_ternary_clause (int a, int b, int c) {
487
+ if (occs (b).size () > occs (c).size ())
488
+ swap (b, c);
489
+ if (occs (a).size () > occs (b).size ())
490
+ swap (a, b);
491
+ for (auto d : occs (a))
492
+ if (match_ternary_clause (d, a, b, c))
493
+ return d;
494
+ return 0;
495
+ }
496
+
497
+ /*------------------------------------------------------------------------*/
498
+
499
+ // Find if-then-else gate.
500
+
501
+ void Internal::find_if_then_else (Eliminator &eliminator, int pivot) {
502
+
503
+ if (!opts.elimites)
504
+ return;
505
+
506
+ assert (opts.elimsubst);
507
+
508
+ if (unsat)
509
+ return;
510
+ if (val (pivot))
511
+ return;
512
+ if (!eliminator.gates.empty ())
513
+ return;
514
+
515
+ const Occs &os = occs (pivot);
516
+ const auto end = os.end ();
517
+ for (auto i = os.begin (); i != end; i++) {
518
+ Clause *di = *i;
519
+ int ai, bi, ci;
520
+ if (!get_ternary_clause (di, ai, bi, ci))
521
+ continue;
522
+ if (bi == pivot)
523
+ swap (ai, bi);
524
+ if (ci == pivot)
525
+ swap (ai, ci);
526
+ assert (ai == pivot);
527
+ for (auto j = i + 1; j != end; j++) {
528
+ Clause *dj = *j;
529
+ int aj, bj, cj;
530
+ if (!get_ternary_clause (dj, aj, bj, cj))
531
+ continue;
532
+ if (bj == pivot)
533
+ swap (aj, bj);
534
+ if (cj == pivot)
535
+ swap (aj, cj);
536
+ assert (aj == pivot);
537
+ if (abs (bi) == abs (cj))
538
+ swap (bj, cj);
539
+ if (abs (ci) == abs (cj))
540
+ continue;
541
+ if (bi != -bj)
542
+ continue;
543
+ Clause *d1 = find_ternary_clause (-pivot, bi, -ci);
544
+ if (!d1)
545
+ continue;
546
+ Clause *d2 = find_ternary_clause (-pivot, bj, -cj);
547
+ if (!d2)
548
+ continue;
549
+ LOG (di, "1st if-then-else");
550
+ LOG (dj, "2nd if-then-else");
551
+ LOG (d1, "3rd if-then-else");
552
+ LOG (d2, "4th if-then-else");
553
+ LOG ("found ITE gate %d == (%d ? %d : %d)", pivot, -bi, -ci, -cj);
554
+ assert (!di->gate);
555
+ assert (!dj->gate);
556
+ assert (!d1->gate);
557
+ assert (!d2->gate);
558
+ di->gate = true;
559
+ dj->gate = true;
560
+ d1->gate = true;
561
+ d2->gate = true;
562
+ eliminator.gates.push_back (di);
563
+ eliminator.gates.push_back (dj);
564
+ eliminator.gates.push_back (d1);
565
+ eliminator.gates.push_back (d2);
566
+ stats.elimgates++;
567
+ stats.elimites++;
568
+ eliminator.gatetype = ITE;
569
+ return;
570
+ }
571
+ }
572
+ }
573
+
574
+ /*------------------------------------------------------------------------*/
575
+
576
+ // Find and extract clause.
577
+
578
+ bool Internal::get_clause (Clause *c, vector<int> &l) {
579
+ if (c->garbage)
580
+ return false;
581
+ l.clear ();
582
+ for (const auto &lit : *c) {
583
+ if (val (lit) < 0)
584
+ continue;
585
+ if (val (lit) > 0) {
586
+ l.clear ();
587
+ return false;
588
+ }
589
+ l.push_back (lit);
590
+ }
591
+ return true;
592
+ }
593
+
594
+ // Check whether 'c' contains only the literals in 'l'.
595
+
596
+ bool Internal::is_clause (Clause *c, const vector<int> &lits) {
597
+ if (c->garbage)
598
+ return false;
599
+ int size = lits.size ();
600
+ if (c->size < size)
601
+ return false;
602
+ int found = 0;
603
+ for (const auto &lit : *c) {
604
+ if (val (lit) < 0)
605
+ continue;
606
+ if (val (lit) > 0)
607
+ return false;
608
+ const auto it = find (lits.begin (), lits.end (), lit);
609
+ if (it == lits.end ())
610
+ return false;
611
+ if (++found > size)
612
+ return false;
613
+ }
614
+ return found == size;
615
+ }
616
+
617
+ Clause *Internal::find_clause (const vector<int> &lits) {
618
+ int best = 0;
619
+ size_t len = 0;
620
+ for (const auto &lit : lits) {
621
+ size_t l = occs (lit).size ();
622
+ if (best && l >= len)
623
+ continue;
624
+ len = l, best = lit;
625
+ }
626
+ for (auto c : occs (best))
627
+ if (is_clause (c, lits))
628
+ return c;
629
+ return 0;
630
+ }
631
+
632
+ void Internal::find_xor_gate (Eliminator &eliminator, int pivot) {
633
+
634
+ if (!opts.elimxors)
635
+ return;
636
+
637
+ assert (opts.elimsubst);
638
+
639
+ if (unsat)
640
+ return;
641
+ if (val (pivot))
642
+ return;
643
+ if (!eliminator.gates.empty ())
644
+ return;
645
+
646
+ vector<int> lits;
647
+
648
+ for (auto d : occs (pivot)) {
649
+
650
+ if (!get_clause (d, lits))
651
+ continue;
652
+
653
+ const int size = lits.size (); // clause size
654
+ const int arity = size - 1; // arity of XOR
655
+
656
+ if (size < 3)
657
+ continue;
658
+ if (arity > opts.elimxorlim)
659
+ continue;
660
+
661
+ assert (eliminator.gates.empty ());
662
+
663
+ unsigned needed = (1u << arity) - 1; // additional clauses
664
+ unsigned signs = 0; // literals to negate
665
+
666
+ do {
667
+ const unsigned prev = signs;
668
+ while (parity (++signs))
669
+ ;
670
+ for (int j = 0; j < size; j++) {
671
+ const unsigned bit = 1u << j;
672
+ int lit = lits[j];
673
+ if ((prev & bit) != (signs & bit))
674
+ lits[j] = lit = -lit;
675
+ }
676
+ Clause *e = find_clause (lits);
677
+ if (!e)
678
+ break;
679
+ eliminator.gates.push_back (e);
680
+ } while (--needed);
681
+
682
+ if (needed) {
683
+ eliminator.gates.clear ();
684
+ continue;
685
+ }
686
+
687
+ eliminator.gates.push_back (d);
688
+ assert (eliminator.gates.size () == (1u << arity));
689
+
690
+ #ifdef LOGGING
691
+ if (opts.log) {
692
+ Logger::print_log_prefix (this);
693
+ tout.magenta ();
694
+ printf ("found arity %u XOR gate %d = ", arity, -pivot);
695
+ bool first = true;
696
+ for (const auto &lit : *d) {
697
+ if (lit == pivot)
698
+ continue;
699
+ assert (lit != -pivot);
700
+ if (!first)
701
+ fputs (" ^ ", stdout);
702
+ printf ("%d", lit);
703
+ first = false;
704
+ }
705
+ fputc ('\n', stdout);
706
+ tout.normal ();
707
+ fflush (stdout);
708
+ }
709
+ #endif
710
+ stats.elimgates++;
711
+ stats.elimxors++;
712
+ const auto end = eliminator.gates.end ();
713
+ auto j = eliminator.gates.begin ();
714
+ for (auto i = j; i != end; i++) {
715
+ Clause *e = *i;
716
+ if (e->gate)
717
+ continue;
718
+ e->gate = true;
719
+ LOG (e, "contributing");
720
+ *j++ = e;
721
+ }
722
+ eliminator.gates.resize (j - eliminator.gates.begin ());
723
+ eliminator.gatetype = XOR;
724
+ break;
725
+ }
726
+ }
727
+
728
+ /*------------------------------------------------------------------------*/
729
+
730
+ // Find a gate for 'pivot'. If such a gate is found, the gate clauses are
731
+ // marked and pushed on the stack of gates. Further hyper unary resolution
732
+ // might detect units, which are propagated. This might assign the pivot or
733
+ // even produce the empty clause.
734
+
735
+ void Internal::find_gate_clauses (Eliminator &eliminator, int pivot) {
736
+ if (!opts.elimsubst)
737
+ return;
738
+
739
+ if (unsat)
740
+ return;
741
+ if (val (pivot))
742
+ return;
743
+
744
+ assert (eliminator.gates.empty ());
745
+
746
+ find_equivalence (eliminator, pivot);
747
+ find_and_gate (eliminator, pivot);
748
+ find_and_gate (eliminator, -pivot);
749
+ find_if_then_else (eliminator, pivot);
750
+ find_xor_gate (eliminator, pivot);
751
+ find_definition (eliminator, pivot);
752
+ }
753
+
754
+ void Internal::unmark_gate_clauses (Eliminator &eliminator) {
755
+ LOG ("unmarking %zd gate clauses", eliminator.gates.size ());
756
+ for (const auto &c : eliminator.gates) {
757
+ assert (c->gate);
758
+ c->gate = false;
759
+ }
760
+ eliminator.gates.clear ();
761
+ eliminator.definition_unit = 0;
762
+ }
763
+
764
+ /*------------------------------------------------------------------------*/
765
+
766
+ } // namespace CaDiCaL