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,403 @@
1
+ #include "cadical.hpp"
2
+ #include "internal.hpp"
3
+
4
+ namespace CaDiCaL {
5
+
6
+ // The idea of warmup is to reuse the strength of CDCL, namely
7
+ // propagating, before calling random walk that is not good at
8
+ // propagating long chains. Therefore, we propagate (ignoring all conflicts)
9
+ // discovered along the way.
10
+ // The asignmend is the same as the normal assignment however, it updates
11
+ // the target phases so that local search can pick them up later
12
+
13
+ // specific warmup version with saving of the target.
14
+ inline void Internal::warmup_assign (int lit, Clause *reason) {
15
+
16
+ assert (level); // no need to learn unit clauses here
17
+ require_mode (SEARCH);
18
+
19
+ const int idx = vidx (lit);
20
+ assert (reason != external_reason);
21
+ assert (!vals[idx]);
22
+ assert (!flags (idx).eliminated () || reason == decision_reason);
23
+ assert (!searching_lucky_phases);
24
+ assert (lrat_chain.empty ());
25
+ Var &v = var (idx);
26
+ int lit_level;
27
+ assert (
28
+ !(reason == external_reason &&
29
+ ((size_t) level <= assumptions.size () + (!!constraint.size ()))));
30
+ assert (reason);
31
+ assert (level || reason == decision_reason);
32
+ // we purely assign in order here
33
+ lit_level = level;
34
+
35
+ v.level = lit_level;
36
+ v.trail = trail.size ();
37
+ v.reason = reason;
38
+ assert ((int) num_assigned < max_var);
39
+ assert (num_assigned == trail.size ());
40
+ num_assigned++;
41
+ const signed char tmp = sign (lit);
42
+ phases.saved[idx] = tmp;
43
+ set_val (idx, tmp);
44
+ assert (val (lit) > 0);
45
+ assert (val (-lit) < 0);
46
+
47
+ trail.push_back (lit);
48
+ #ifdef LOGGING
49
+ if (!lit_level)
50
+ LOG ("root-level unit assign %d @ 0", lit);
51
+ else
52
+ LOG (reason, "search assign %d @ %d", lit, lit_level);
53
+ #endif
54
+
55
+ assert (watching ());
56
+ const Watches &ws = watches (-lit);
57
+ if (!ws.empty ()) {
58
+ const Watch &w = ws[0];
59
+ __builtin_prefetch (&w, 0, 1);
60
+ }
61
+ }
62
+
63
+ void Internal::warmup_propagate_beyond_conflict () {
64
+
65
+ assert (!unsat);
66
+
67
+ START (propagate);
68
+ assert (!ignore);
69
+
70
+ int64_t before = propagated;
71
+
72
+ while (propagated != trail.size ()) {
73
+
74
+ const int lit = -trail[propagated++];
75
+ LOG ("propagating %d", -lit);
76
+ Watches &ws = watches (lit);
77
+
78
+ const const_watch_iterator eow = ws.end ();
79
+ watch_iterator j = ws.begin ();
80
+ const_watch_iterator i = j;
81
+
82
+ while (i != eow) {
83
+
84
+ const Watch w = *j++ = *i++;
85
+ const signed char b = val (w.blit);
86
+
87
+ if (b > 0)
88
+ continue; // blocking literal satisfied
89
+
90
+ if (w.binary ()) {
91
+
92
+ // In principle we can ignore garbage binary clauses too, but that
93
+ // would require to dereference the clause pointer all the time with
94
+ //
95
+ // if (w.clause->garbage) { j--; continue; } // (*)
96
+ //
97
+ // This is too costly. It is however necessary to produce correct
98
+ // proof traces if binary clauses are traced to be deleted ('d ...'
99
+ // line) immediately as soon they are marked as garbage. Actually
100
+ // finding instances where this happens is pretty difficult (six
101
+ // parallel fuzzing jobs in parallel took an hour), but it does
102
+ // occur. Our strategy to avoid generating incorrect proofs now is
103
+ // to delay tracing the deletion of binary clauses marked as garbage
104
+ // until they are really deleted from memory. For large clauses
105
+ // this is not necessary since we have to access the clause anyhow.
106
+ //
107
+ // Thanks go to Mathias Fleury, who wanted me to explain why the
108
+ // line '(*)' above was in the code. Removing it actually really
109
+ // improved running times and thus I tried to find concrete
110
+ // instances where this happens (which I found), and then
111
+ // implemented the described fix.
112
+
113
+ // Binary clauses are treated separately since they do not require
114
+ // to access the clause at all (only during conflict analysis, and
115
+ // there also only to simplify the code).
116
+
117
+ if (b < 0)
118
+ // ignoring conflict
119
+ ++stats.warmup.conflicts;
120
+ else {
121
+ warmup_assign (w.blit, w.clause);
122
+ }
123
+
124
+ } else {
125
+ assert (w.clause->size > 2);
126
+
127
+ // The cache line with the clause data is forced to be loaded here
128
+ // and thus this first memory access below is the real hot-spot of
129
+ // the solver. Note, that this check is positive very rarely and
130
+ // thus branch prediction should be almost perfect here.
131
+
132
+ if (w.clause->garbage) {
133
+ j--;
134
+ continue;
135
+ }
136
+ literal_iterator lits = w.clause->begin ();
137
+ const int other = lits[0] ^ lits[1] ^ lit;
138
+ const signed char u = val (other);
139
+ if (u > 0)
140
+ j[-1].blit = other;
141
+ else {
142
+ const int size = w.clause->size;
143
+ const const_literal_iterator end = lits + size;
144
+ const literal_iterator middle = lits + w.clause->pos;
145
+ literal_iterator k = middle;
146
+ signed char v = -1;
147
+ int r = 0;
148
+ while (k != end && (v = val (r = *k)) < 0)
149
+ k++;
150
+ if (v < 0) {
151
+ k = lits + 2;
152
+ assert (w.clause->pos <= size);
153
+ while (k != middle && (v = val (r = *k)) < 0)
154
+ k++;
155
+ }
156
+
157
+ w.clause->pos = k - lits; // always save position
158
+
159
+ assert (lits + 2 <= k), assert (k <= w.clause->end ());
160
+
161
+ if (v > 0) {
162
+
163
+ // Replacement satisfied, so just replace 'blit'.
164
+
165
+ j[-1].blit = r;
166
+
167
+ } else if (!v) {
168
+
169
+ // Found new unassigned replacement literal to be watched.
170
+
171
+ LOG (w.clause, "unwatch %d in", lit);
172
+
173
+ lits[0] = other;
174
+ lits[1] = r;
175
+ *k = lit;
176
+
177
+ watch_literal (r, lit, w.clause);
178
+
179
+ j--; // Drop this watch from the watch list of 'lit'.
180
+
181
+ } else if (!u) {
182
+
183
+ assert (v < 0);
184
+
185
+ // The other watch is unassigned ('!u') and all other literals
186
+ // assigned to false (still 'v < 0'), thus we found a unit.
187
+ //
188
+ build_chain_for_units (other, w.clause, 0);
189
+ warmup_assign (other, w.clause);
190
+ } else {
191
+ assert (u < 0);
192
+ assert (v < 0);
193
+
194
+ // ignoring conflict
195
+ ++stats.warmup.conflicts;
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ if (j != i) {
202
+ ws.resize (j - ws.begin ());
203
+ }
204
+ }
205
+
206
+ assert (propagated == trail.size ());
207
+
208
+ stats.warmup.propagated += (trail.size () - before);
209
+ STOP (propagate);
210
+ }
211
+
212
+ int Internal::warmup_decide () {
213
+ assert (!satisfied ());
214
+ START (decide);
215
+ int res = 0;
216
+ if ((size_t) level < assumptions.size ()) {
217
+ const int lit = assumptions[level];
218
+ assert (assumed (lit));
219
+ const signed char tmp = val (lit);
220
+ if (tmp < 0) {
221
+ LOG ("assumption %d falsified", lit);
222
+ res = 20;
223
+ } else if (tmp > 0) {
224
+ LOG ("assumption %d already satisfied", lit);
225
+ new_trail_level (0);
226
+ LOG ("added pseudo decision level");
227
+ } else {
228
+ LOG ("deciding assumption %d", lit);
229
+ search_assume_decision (lit);
230
+ }
231
+ } else if ((size_t) level == assumptions.size () && constraint.size ()) {
232
+
233
+ int satisfied_lit = 0; // The literal satisfying the constrain.
234
+ int unassigned_lit = 0; // Highest score unassigned literal.
235
+ int previous_lit = 0; // Move satisfied literals to the front.
236
+
237
+ const size_t size_constraint = constraint.size ();
238
+
239
+ #ifndef NDEBUG
240
+ unsigned sum = 0;
241
+ for (auto lit : constraint)
242
+ sum += lit;
243
+ #endif
244
+ for (size_t i = 0; i != size_constraint; i++) {
245
+
246
+ // Get literal and move 'constraint[i] = constraint[i-1]'.
247
+
248
+ int lit = constraint[i];
249
+ constraint[i] = previous_lit;
250
+ previous_lit = lit;
251
+
252
+ const signed char tmp = val (lit);
253
+ if (tmp < 0) {
254
+ LOG ("constraint literal %d falsified", lit);
255
+ continue;
256
+ }
257
+
258
+ if (tmp > 0) {
259
+ LOG ("constraint literal %d satisfied", lit);
260
+ satisfied_lit = lit;
261
+ break;
262
+ }
263
+
264
+ assert (!tmp);
265
+ LOG ("constraint literal %d unassigned", lit);
266
+
267
+ if (!unassigned_lit || better_decision (lit, unassigned_lit))
268
+ unassigned_lit = lit;
269
+ }
270
+
271
+ if (satisfied_lit) {
272
+
273
+ constraint[0] = satisfied_lit; // Move satisfied to the front.
274
+
275
+ LOG ("literal %d satisfies constraint and "
276
+ "is implied by assumptions",
277
+ satisfied_lit);
278
+
279
+ new_trail_level (0);
280
+ LOG ("added pseudo decision level for constraint");
281
+ notify_decision ();
282
+
283
+ } else {
284
+
285
+ // Just move all the literals back. If we found an unsatisfied
286
+ // literal then it will be satisfied (most likely) at the next
287
+ // decision and moved then to the first position.
288
+
289
+ if (size_constraint) {
290
+
291
+ for (size_t i = 0; i + 1 != size_constraint; i++)
292
+ constraint[i] = constraint[i + 1];
293
+
294
+ constraint[size_constraint - 1] = previous_lit;
295
+ }
296
+
297
+ if (unassigned_lit) {
298
+
299
+ LOG ("deciding %d to satisfy constraint", unassigned_lit);
300
+ search_assume_decision (unassigned_lit);
301
+
302
+ } else {
303
+
304
+ LOG ("failing constraint");
305
+ unsat_constraint = true;
306
+ res = 20;
307
+ }
308
+ }
309
+
310
+ #ifndef NDEBUG
311
+ for (auto lit : constraint)
312
+ sum -= lit;
313
+ assert (!sum); // Checksum of literal should not change!
314
+ #endif
315
+
316
+ } else {
317
+ const bool target = (stable || opts.target == 2);
318
+ stats.warmup.decision++;
319
+ int idx = next_decision_variable ();
320
+ if (flags (idx).eliminated ())
321
+ ++stats.warmup.dummydecision;
322
+ int decision = decide_phase (idx, target);
323
+ new_trail_level (decision);
324
+ warmup_assign (decision, decision_reason);
325
+ }
326
+ if (res)
327
+ marked_failed = false;
328
+ STOP (decide);
329
+ return res;
330
+ }
331
+
332
+ int Internal::warmup () {
333
+ assert (!unsat);
334
+ assert (!level);
335
+ if (!opts.warmup)
336
+ return 0;
337
+ require_mode (WALK);
338
+ START (warmup);
339
+ ++stats.warmup.count;
340
+ int res = 0;
341
+
342
+ #ifndef QUIET
343
+ const int64_t warmup_propagated = stats.warmup.propagated;
344
+ const int64_t decision = stats.warmup.decision;
345
+ const int64_t dummydecision = stats.warmup.dummydecision;
346
+ #endif
347
+ // first propagate assumptions in case we find a conflict. One subtle
348
+ // thing, if we find a conflict in the assumption, then we actually do
349
+ // need the notifications. Otherwise, we there should be no notification
350
+ // at all (not even the `backtrack ()` at the end). Also, we cannot not
351
+ // ignore conflicts at all, meaning that we cannot use our special
352
+ // propagation function, even if it could counts ticks.
353
+ const size_t assms_contraint_level =
354
+ assumptions.size () + !constraint.empty ();
355
+ while (!res && (size_t) level < assms_contraint_level &&
356
+ num_assigned < (size_t) max_var) {
357
+ assert (num_assigned < (size_t) max_var);
358
+ res = warmup_decide ();
359
+ if (!propagate ()) {
360
+ res = 20;
361
+ marked_failed = false;
362
+ break;
363
+ }
364
+ }
365
+ const bool no_backtrack_notification = (level == 0);
366
+
367
+ // now we do not need any notification and can simply propagate
368
+ assert (res || propagated == trail.size ());
369
+ assert (!private_steps);
370
+ private_steps = true;
371
+
372
+ LOG ("propagating beyond conflicts to warm-up walk");
373
+ while (!res && num_assigned < (size_t) max_var) {
374
+ assert (propagated == trail.size ());
375
+ res = warmup_decide ();
376
+ warmup_propagate_beyond_conflict ();
377
+ LOG (lrat_chain, "during warmup with lrat chain:");
378
+ }
379
+ assert (res || num_assigned == (size_t) max_var);
380
+ #ifndef QUIET
381
+ // constrains with empty levels break this
382
+ // assert (res || stats.warmup.propagated - warmup_propagated ==
383
+ // (int64_t)num_assigned);
384
+ VERBOSE (3,
385
+ "warming-up needed %" PRIu64 " propagations including %" PRIu64
386
+ " decisions (with %" PRIu64 " dummy ones)",
387
+ stats.warmup.propagated - warmup_propagated,
388
+ stats.warmup.decision - decision,
389
+ stats.warmup.dummydecision - dummydecision);
390
+ #endif
391
+
392
+ // now we backtrack, notifying only if there was something to
393
+ // notify.
394
+ private_steps = no_backtrack_notification;
395
+ if (!res)
396
+ backtrack_without_updating_phases ();
397
+ private_steps = false;
398
+ STOP (warmup);
399
+ require_mode (WALK);
400
+ return res;
401
+ }
402
+
403
+ } // namespace CaDiCaL
@@ -0,0 +1,126 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ void Internal::init_watches () {
6
+ assert (wtab.empty ());
7
+ if (wtab.size () < 2 * vsize)
8
+ wtab.resize (2 * vsize, Watches ());
9
+ LOG ("initialized watcher tables");
10
+ }
11
+
12
+ void Internal::clear_watches () {
13
+ for (auto lit : lits)
14
+ watches (lit).clear ();
15
+ }
16
+
17
+ void Internal::reset_watches () {
18
+ assert (!wtab.empty ());
19
+ erase_vector (wtab);
20
+ LOG ("reset watcher tables");
21
+ }
22
+
23
+ // This can be quite costly since lots of memory is accessed in a rather
24
+ // random fashion, and thus we optionally profile it.
25
+
26
+ void Internal::connect_watches (bool irredundant_only) {
27
+ START (connect);
28
+ assert (watching ());
29
+
30
+ LOG ("watching all %sclauses", irredundant_only ? "irredundant " : "");
31
+
32
+ // First connect binary clauses.
33
+ //
34
+ for (const auto &c : clauses) {
35
+ if (irredundant_only && c->redundant)
36
+ continue;
37
+ if (c->garbage || c->size > 2)
38
+ continue;
39
+ watch_clause (c);
40
+ }
41
+
42
+ // Then connect non-binary clauses.
43
+ //
44
+ for (const auto &c : clauses) {
45
+ if (irredundant_only && c->redundant)
46
+ continue;
47
+ if (c->garbage || c->size == 2)
48
+ continue;
49
+ watch_clause (c);
50
+ if (!level) {
51
+ const int lit0 = c->literals[0];
52
+ const int lit1 = c->literals[1];
53
+ const signed char tmp0 = val (lit0);
54
+ const signed char tmp1 = val (lit1);
55
+ if (tmp0 > 0)
56
+ continue;
57
+ if (tmp1 > 0)
58
+ continue;
59
+ if (tmp0 < 0) {
60
+ const size_t pos0 = var (lit0).trail;
61
+ if (pos0 < propagated) {
62
+ propagated = pos0;
63
+ LOG ("literal %d resets propagated to %zd", lit0, pos0);
64
+ }
65
+ }
66
+ if (tmp1 < 0) {
67
+ const size_t pos1 = var (lit1).trail;
68
+ if (pos1 < propagated) {
69
+ propagated = pos1;
70
+ LOG ("literal %d resets propagated to %zd", lit1, pos1);
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ STOP (connect);
77
+ }
78
+
79
+ // This can be quite costly since lots of memory is accessed in a rather
80
+ // random fashion, and thus we optionally profile it.
81
+
82
+ void Internal::connect_binary_watches () {
83
+ START (connect);
84
+ assert (watching ());
85
+
86
+ LOG ("watching binary clauses");
87
+
88
+ // First connect binary clauses.
89
+ //
90
+ for (const auto &c : clauses) {
91
+ if (c->garbage || c->size > 2)
92
+ continue;
93
+ watch_clause (c);
94
+ }
95
+
96
+ STOP (connect);
97
+ }
98
+
99
+ void Internal::sort_watches () {
100
+ assert (watching ());
101
+ LOG ("sorting watches");
102
+ Watches saved;
103
+ for (auto lit : lits) {
104
+ Watches &ws = watches (lit);
105
+
106
+ const const_watch_iterator end = ws.end ();
107
+ watch_iterator j = ws.begin ();
108
+ const_watch_iterator i;
109
+
110
+ assert (saved.empty ());
111
+
112
+ for (i = j; i != end; i++) {
113
+ const Watch w = *i;
114
+ if (w.binary ())
115
+ *j++ = w;
116
+ else
117
+ saved.push_back (w);
118
+ }
119
+
120
+ std::copy (saved.cbegin (), saved.cend (), j);
121
+
122
+ saved.clear ();
123
+ }
124
+ }
125
+
126
+ } // namespace CaDiCaL
@@ -0,0 +1,77 @@
1
+ #ifndef _watch_hpp_INCLUDED
2
+ #define _watch_hpp_INCLUDED
3
+
4
+ #include <cassert>
5
+ #include <vector>
6
+
7
+ #include "clause.hpp"
8
+
9
+ namespace CaDiCaL {
10
+
11
+ // Watch lists for CDCL search. The blocking literal (see also comments
12
+ // related to 'propagate') is a must and thus combining that with a 64 bit
13
+ // pointer will give a 16 byte (8 byte aligned) structure anyhow, which
14
+ // means the additional 4 bytes for the size come for free. As alternative
15
+ // one could use a 32-bit reference instead of the pointer which would
16
+ // however limit the number of clauses to '2^32 - 1'. One would also need
17
+ // to use at least one more bit (either taken away from the variable space
18
+ // or the clauses) to denote whether the watch is binary.
19
+
20
+ // in fashion of Intel Sat 10.4230/LIPIcs.SAT.2022.8 we try to
21
+ // guarantee the following invariant:
22
+ // For both watches:
23
+ // if the watched literal is negatively assigned
24
+ // either it will be propagated in the future
25
+ // or the corresponding blocking literal is positively assigned
26
+ // and its level is smaller than the level of the watched literal
27
+ //
28
+
29
+ struct Clause;
30
+
31
+ struct Watch {
32
+
33
+ Clause *clause;
34
+ int blit;
35
+ int size;
36
+
37
+ Watch (int b, Clause *c) : clause (c), blit (b), size (c->size) {}
38
+ Watch (bool, int b, Clause *c) : clause (c), blit (b), size (2) {
39
+ assert (c->size == 2);
40
+ }
41
+ Watch () {}
42
+
43
+ bool binary () const { return size == 2; }
44
+ };
45
+
46
+ typedef vector<Watch> Watches; // of one literal
47
+
48
+ typedef Watches::iterator watch_iterator;
49
+ typedef Watches::const_iterator const_watch_iterator;
50
+
51
+ inline void remove_watch (Watches &ws, Clause *clause) {
52
+ const auto end = ws.end ();
53
+ auto i = ws.begin ();
54
+ for (auto j = i; j != end; j++) {
55
+ const Watch &w = *i++ = *j;
56
+ if (w.clause == clause)
57
+ i--;
58
+ }
59
+ assert (i + 1 == end);
60
+ ws.resize (i - ws.begin ());
61
+ }
62
+
63
+ // search for the clause and updates the size marked in the watch lists
64
+ inline void update_watch_size (Watches &ws, int blit, Clause *conflict) {
65
+ bool found = false;
66
+ const int size = conflict->size;
67
+ for (Watch &w : ws) {
68
+ if (w.clause == conflict)
69
+ w.size = size, w.blit = blit, found = true;
70
+ assert (w.clause->garbage || w.size == 2 || w.clause->size != 2);
71
+ }
72
+ assert (found), (void) found;
73
+ }
74
+
75
+ } // namespace CaDiCaL
76
+
77
+ #endif