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,545 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ /*------------------------------------------------------------------------*/
6
+
7
+ // Returns the positive number '1' ( > 0) if the given clause is root level
8
+ // satisfied or the negative number '-1' ( < 0) if it is not root level
9
+ // satisfied but contains a root level falsified literal. Otherwise, if it
10
+ // contains neither a satisfied nor falsified literal, then '0' is returned.
11
+
12
+ int Internal::clause_contains_fixed_literal (Clause *c) {
13
+ int satisfied = 0, falsified = 0;
14
+ for (const auto &lit : *c) {
15
+ const int tmp = fixed (lit);
16
+ if (tmp > 0) {
17
+ LOG (c, "root level satisfied literal %d in", lit);
18
+ satisfied++;
19
+ }
20
+ if (tmp < 0) {
21
+ LOG (c, "root level falsified literal %d in", lit);
22
+ falsified++;
23
+ }
24
+ }
25
+ if (satisfied)
26
+ return 1;
27
+ else if (falsified)
28
+ return -1;
29
+ else
30
+ return 0;
31
+ }
32
+
33
+ // Assume that the clause is not root level satisfied but contains a literal
34
+ // set to false (root level falsified literal), so it can be shrunken. The
35
+ // clause data is not actually reallocated at this point to avoid dealing
36
+ // with issues of special policies for watching binary clauses or whether a
37
+ // clause is extended or not. Only its size field is adjusted accordingly
38
+ // after flushing out root level falsified literals.
39
+
40
+ void Internal::remove_falsified_literals (Clause *c) {
41
+ const const_literal_iterator end = c->end ();
42
+ const_literal_iterator i;
43
+ int num_non_false = 0;
44
+ for (i = c->begin (); num_non_false < 2 && i != end; i++)
45
+ if (fixed (*i) >= 0)
46
+ num_non_false++;
47
+ if (num_non_false < 2)
48
+ return;
49
+ if (proof) {
50
+ // Flush changes the clause id, external forgettables need to be
51
+ // marked here (or the new id could be used instead of old one)
52
+ if (opts.check && is_external_forgettable (c->id))
53
+ mark_garbage_external_forgettable (c->id);
54
+ proof->flush_clause (c);
55
+ }
56
+ literal_iterator j = c->begin ();
57
+ for (i = j; i != end; i++) {
58
+ const int lit = *j++ = *i, tmp = fixed (lit);
59
+ assert (tmp <= 0);
60
+ if (tmp >= 0)
61
+ continue;
62
+ LOG ("flushing %d", lit);
63
+ j--;
64
+ }
65
+ stats.collected += shrink_clause (c, j - c->begin ());
66
+ }
67
+
68
+ // If there are new units (fixed variables) since the last garbage
69
+ // collection we go over all clauses, mark satisfied ones as garbage and
70
+ // flush falsified literals. Otherwise if no new units have been generated
71
+ // since the last garbage collection just skip this step.
72
+
73
+ void Internal::mark_satisfied_clauses_as_garbage () {
74
+
75
+ if (last.collect.fixed >= stats.all.fixed)
76
+ return;
77
+ last.collect.fixed = stats.all.fixed;
78
+
79
+ LOG ("marking satisfied clauses and removing falsified literals");
80
+
81
+ for (const auto &c : clauses) {
82
+ if (c->garbage)
83
+ continue;
84
+ const int tmp = clause_contains_fixed_literal (c);
85
+ if (tmp > 0)
86
+ mark_garbage (c);
87
+ else if (tmp < 0)
88
+ remove_falsified_literals (c);
89
+ }
90
+ }
91
+
92
+ /*------------------------------------------------------------------------*/
93
+
94
+ // Reason clauses can not be collected.
95
+ //
96
+ // We protect reasons before and release protection after garbage collection
97
+ // (actually within garbage collection).
98
+ //
99
+ // For 'reduce' we still need to make sure that all clauses which should not
100
+ // be removed are marked as such and thus we need to call it before marking
101
+ // clauses to be flushed.
102
+
103
+ void Internal::protect_reasons () {
104
+ LOG ("protecting reason clauses of all assigned variables on trail");
105
+ assert (!protected_reasons);
106
+ #ifdef LOGGING
107
+ size_t count = 0;
108
+ #endif
109
+ for (const auto &lit : trail) {
110
+ if (!active (lit))
111
+ continue;
112
+ assert (val (lit));
113
+ Var &v = var (lit);
114
+ assert (v.level > 0);
115
+ Clause *reason = v.reason;
116
+ if (!reason)
117
+ continue;
118
+ if (reason == external_reason)
119
+ continue;
120
+ LOG (reason, "protecting assigned %d reason %p", lit, (void *) reason);
121
+ assert (!reason->reason);
122
+ reason->reason = true;
123
+ #ifdef LOGGING
124
+ count++;
125
+ #endif
126
+ }
127
+ LOG ("protected %zd reason clauses referenced on trail", count);
128
+ protected_reasons = true;
129
+ }
130
+
131
+ /*------------------------------------------------------------------------*/
132
+
133
+ // After garbage collection we reset the 'reason' flag of the reasons
134
+ // of assigned literals on the trail.
135
+
136
+ void Internal::unprotect_reasons () {
137
+ LOG ("unprotecting reasons clauses of all assigned variables on trail");
138
+ assert (protected_reasons);
139
+ #ifdef LOGGING
140
+ size_t count = 0;
141
+ #endif
142
+ for (const auto &lit : trail) {
143
+ if (!active (lit))
144
+ continue;
145
+ assert (val (lit));
146
+ Var &v = var (lit);
147
+ assert (v.level > 0);
148
+ Clause *reason = v.reason;
149
+ if (!reason)
150
+ continue;
151
+ if (reason == external_reason)
152
+ continue;
153
+ LOG (reason, "unprotecting assigned %d reason %p", lit,
154
+ (void *) reason);
155
+ assert (reason->reason);
156
+ reason->reason = false;
157
+ #ifdef LOGGING
158
+ count++;
159
+ #endif
160
+ }
161
+ LOG ("unprotected %zd reason clauses referenced on trail", count);
162
+ protected_reasons = false;
163
+ }
164
+
165
+ /*------------------------------------------------------------------------*/
166
+
167
+ // Update occurrence lists before deleting garbage clauses in the context of
168
+ // preprocessing, e.g., during bounded variable elimination 'elim'. The
169
+ // result is the number of remaining clauses, which in this context means
170
+ // the number of non-garbage clauses.
171
+
172
+ size_t Internal::flush_occs (int lit) {
173
+ Occs &os = occs (lit);
174
+ const const_occs_iterator end = os.end ();
175
+ occs_iterator j = os.begin ();
176
+ const_occs_iterator i;
177
+ size_t res = 0;
178
+ Clause *c;
179
+ for (i = j; i != end; i++) {
180
+ c = *i;
181
+ if (c->collect ())
182
+ continue;
183
+ *j++ = c->moved ? c->copy : c;
184
+ // assert (!c->redundant); // -> not true in sweeping
185
+ res++;
186
+ }
187
+ os.resize (j - os.begin ());
188
+ shrink_occs (os);
189
+ return res;
190
+ }
191
+
192
+ // Update watch lists before deleting garbage clauses in the context of
193
+ // 'reduce' where we watch and no occurrence lists. We have to protect
194
+ // reason clauses not be collected and thus we have this additional check
195
+ // hidden in 'Clause.collect', which for the root level context of
196
+ // preprocessing is actually redundant.
197
+
198
+ inline void Internal::flush_watches (int lit, Watches &saved) {
199
+ assert (saved.empty ());
200
+ Watches &ws = watches (lit);
201
+ const const_watch_iterator end = ws.end ();
202
+ watch_iterator j = ws.begin ();
203
+ const_watch_iterator i;
204
+ for (i = j; i != end; i++) {
205
+ Watch w = *i;
206
+ Clause *c = w.clause;
207
+ if (c->collect ())
208
+ continue;
209
+ if (c->moved)
210
+ c = w.clause = c->copy;
211
+ w.size = c->size;
212
+ const int new_blit_pos = (c->literals[0] == lit);
213
+ LOG (c, "clause in flush_watch starting from %d", lit);
214
+ assert (c->literals[!new_blit_pos] == lit); /*FW1*/
215
+ w.blit = c->literals[new_blit_pos];
216
+ if (w.binary ())
217
+ *j++ = w;
218
+ else
219
+ saved.push_back (w);
220
+ }
221
+ ws.resize (j - ws.begin ());
222
+ for (const auto &w : saved)
223
+ ws.push_back (w);
224
+ saved.clear ();
225
+ shrink_vector (ws);
226
+ }
227
+
228
+ void Internal::flush_all_occs_and_watches () {
229
+ if (occurring ())
230
+ for (auto idx : vars)
231
+ flush_occs (idx), flush_occs (-idx);
232
+
233
+ if (watching ()) {
234
+ Watches tmp;
235
+ for (auto idx : vars)
236
+ flush_watches (idx, tmp), flush_watches (-idx, tmp);
237
+ }
238
+ }
239
+
240
+ /*------------------------------------------------------------------------*/
241
+
242
+ void Internal::update_reason_references () {
243
+ LOG ("update assigned reason references");
244
+ #ifdef LOGGING
245
+ size_t count = 0;
246
+ #endif
247
+ for (auto &lit : trail) {
248
+ if (!active (lit))
249
+ continue;
250
+ Var &v = var (lit);
251
+ Clause *c = v.reason;
252
+ if (!c)
253
+ continue;
254
+ if (c == external_reason)
255
+ continue;
256
+ LOG (c, "updating assigned %d reason", lit);
257
+ assert (c->reason);
258
+ assert (c->moved);
259
+ Clause *d = c->copy;
260
+ v.reason = d;
261
+ #ifdef LOGGING
262
+ count++;
263
+ #endif
264
+ }
265
+ LOG ("updated %zd assigned reason references", count);
266
+ }
267
+
268
+ /*------------------------------------------------------------------------*/
269
+
270
+ // This is a simple garbage collector which does not move clauses. It needs
271
+ // less space than the arena based clause allocator, but is not as cache
272
+ // efficient, since the copying garbage collector can put clauses together
273
+ // which are likely accessed after each other.
274
+
275
+ void Internal::delete_garbage_clauses () {
276
+
277
+ flush_all_occs_and_watches ();
278
+
279
+ LOG ("deleting garbage clauses");
280
+ #ifndef QUIET
281
+ int64_t collected_bytes = 0, collected_clauses = 0;
282
+ #endif
283
+ const auto end = clauses.end ();
284
+ auto j = clauses.begin (), i = j;
285
+ while (i != end) {
286
+ Clause *c = *j++ = *i++;
287
+ if (!c->collect ())
288
+ continue;
289
+ #ifndef QUIET
290
+ collected_bytes += c->bytes ();
291
+ collected_clauses++;
292
+ #endif
293
+ delete_clause (c);
294
+ j--;
295
+ }
296
+ clauses.resize (j - clauses.begin ());
297
+ shrink_vector (clauses);
298
+
299
+ PHASE ("collect", stats.collections,
300
+ "collected %" PRId64 " bytes of %" PRId64 " garbage clauses",
301
+ collected_bytes, collected_clauses);
302
+ }
303
+
304
+ /*------------------------------------------------------------------------*/
305
+
306
+ // This is the start of the copying garbage collector using the arena. At
307
+ // the core is the following function, which copies a clause to the 'to'
308
+ // space of the arena. Be careful if this clause is a reason of an
309
+ // assignment. In that case update the reason reference.
310
+ //
311
+ void Internal::copy_clause (Clause *c) {
312
+ LOG (c, "moving");
313
+ assert (!c->moved);
314
+ char *p = (char *) c;
315
+ char *q = arena.copy (p, c->bytes ());
316
+ c->copy = (Clause *) q;
317
+ c->moved = true;
318
+ LOG ("copied clause[%" PRId64 "] from %p to %p", c->id, (void *) c,
319
+ (void *) c->copy);
320
+ }
321
+
322
+ // This is the moving garbage collector.
323
+
324
+ void Internal::copy_non_garbage_clauses () {
325
+
326
+ size_t collected_clauses = 0, collected_bytes = 0;
327
+ size_t moved_clauses = 0, moved_bytes = 0;
328
+
329
+ // First determine 'moved_bytes' and 'collected_bytes'.
330
+ //
331
+ for (const auto &c : clauses)
332
+ if (!c->collect ())
333
+ moved_bytes += c->bytes (), moved_clauses++;
334
+ else
335
+ collected_bytes += c->bytes (), collected_clauses++;
336
+
337
+ PHASE ("collect", stats.collections,
338
+ "moving %zd bytes %.0f%% of %zd non garbage clauses", moved_bytes,
339
+ percent (moved_bytes, collected_bytes + moved_bytes),
340
+ moved_clauses);
341
+ (void) moved_clauses, (void) collected_clauses, (void) collected_bytes;
342
+ // Prepare 'to' space of size 'moved_bytes'.
343
+ //
344
+ arena.prepare (moved_bytes);
345
+
346
+ // Keep clauses in arena in the same order.
347
+ //
348
+ if (opts.arenacompact)
349
+ for (const auto &c : clauses)
350
+ if (!c->collect () && arena.contains (c))
351
+ copy_clause (c);
352
+
353
+ if (opts.arenatype == 1 || !watching ()) {
354
+
355
+ // Localize according to current clause order.
356
+
357
+ // If the option 'opts.arenatype == 1' is set, then this means the
358
+ // solver uses the original order of clauses. If there are no watches,
359
+ // we can not use the watched based copying policies below. This
360
+ // happens if garbage collection is triggered during bounded variable
361
+ // elimination.
362
+
363
+ // Copy clauses according to the order of calling 'copy_clause', which
364
+ // in essence just gives a compacting garbage collector, since their
365
+ // relative order is kept, and actually already gives the largest
366
+ // benefit due to better cache locality.
367
+
368
+ for (const auto &c : clauses)
369
+ if (!c->moved && !c->collect ())
370
+ copy_clause (c);
371
+
372
+ } else if (opts.arenatype == 2) {
373
+
374
+ // Localize according to (original) variable order.
375
+
376
+ // This is almost the version used by MiniSAT and descendants.
377
+ // Our version uses saved phases too.
378
+
379
+ for (int sign = -1; sign <= 1; sign += 2)
380
+ for (auto idx : vars)
381
+ for (const auto &w : watches (sign * likely_phase (idx)))
382
+ if (!w.clause->moved && !w.clause->collect ())
383
+ copy_clause (w.clause);
384
+
385
+ } else {
386
+
387
+ // Localize according to decision queue order.
388
+
389
+ // This is the default for search. It allocates clauses in the order of
390
+ // the decision queue and also uses saved phases. It seems faster than
391
+ // the MiniSAT version and thus we keep 'opts.arenatype == 3'.
392
+
393
+ assert (opts.arenatype == 3);
394
+
395
+ for (int sign = -1; sign <= 1; sign += 2)
396
+ for (int idx = queue.last; idx; idx = link (idx).prev)
397
+ for (const auto &w : watches (sign * likely_phase (idx)))
398
+ if (!w.clause->moved && !w.clause->collect ())
399
+ copy_clause (w.clause);
400
+ }
401
+
402
+ // Do not forget to move clauses which are not watched, which happened in
403
+ // a rare situation, and now is only left as defensive code.
404
+ //
405
+ for (const auto &c : clauses)
406
+ if (!c->collect () && !c->moved)
407
+ copy_clause (c);
408
+
409
+ flush_all_occs_and_watches ();
410
+ update_reason_references ();
411
+
412
+ // Replace and flush clause references in 'clauses'.
413
+ //
414
+ const auto end = clauses.end ();
415
+ auto j = clauses.begin (), i = j;
416
+ for (; i != end; i++) {
417
+ Clause *c = *i;
418
+ if (c->collect ())
419
+ delete_clause (c);
420
+ else
421
+ assert (c->moved), *j++ = c->copy, deallocate_clause (c);
422
+ }
423
+ clauses.resize (j - clauses.begin ());
424
+ if (clauses.size () < clauses.capacity () / 2)
425
+ shrink_vector (clauses);
426
+
427
+ if (opts.arenasort)
428
+ rsort (clauses.begin (), clauses.end (), pointer_rank ());
429
+
430
+ // Release 'from' space completely and then swap 'to' with 'from'.
431
+ //
432
+ arena.swap ();
433
+
434
+ PHASE ("collect", stats.collections,
435
+ "collected %zd bytes %.0f%% of %zd garbage clauses",
436
+ collected_bytes,
437
+ percent (collected_bytes, collected_bytes + moved_bytes),
438
+ collected_clauses);
439
+ }
440
+
441
+ /*------------------------------------------------------------------------*/
442
+
443
+ // Maintaining clause statistics is complex and error prone but necessary
444
+ // for proper scheduling of garbage collection, particularly during bounded
445
+ // variable elimination. With this function we can check whether these
446
+ // statistics are updated correctly.
447
+
448
+ void Internal::check_clause_stats () {
449
+ #ifndef NDEBUG
450
+ int64_t irredundant = 0, redundant = 0, total = 0, irrlits = 0;
451
+ for (const auto &c : clauses) {
452
+ if (c->garbage)
453
+ continue;
454
+ if (c->redundant)
455
+ redundant++;
456
+ else
457
+ irredundant++;
458
+ if (!c->redundant)
459
+ irrlits += c->size;
460
+ total++;
461
+ }
462
+ assert (stats.current.irredundant == irredundant);
463
+ assert (stats.current.redundant == redundant);
464
+ assert (stats.current.total == total);
465
+ assert (stats.irrlits == irrlits);
466
+ #endif
467
+ }
468
+
469
+ /*------------------------------------------------------------------------*/
470
+
471
+ // only delete binary clauses from watch list that are already mark as
472
+ // deleted.
473
+ void Internal::remove_garbage_binaries () {
474
+ if (unsat)
475
+ return;
476
+ START (collect);
477
+
478
+ if (!protected_reasons)
479
+ protect_reasons ();
480
+ int backtrack_level = level + 1;
481
+ Watches saved;
482
+ for (auto v : vars) {
483
+ for (auto lit : {-v, v}) {
484
+ assert (saved.empty ());
485
+ Watches &ws = watches (lit);
486
+ const const_watch_iterator end = ws.end ();
487
+ watch_iterator j = ws.begin ();
488
+ const_watch_iterator i;
489
+ for (i = j; i != end; i++) {
490
+ Watch w = *i;
491
+ *j++ = w;
492
+ Clause *c = w.clause;
493
+ COVER (!w.binary () && c->size == 2);
494
+ if (!w.binary ())
495
+ continue;
496
+ if (c->reason && c->garbage) {
497
+ COVER (true);
498
+ assert (c->size == 2);
499
+ backtrack_level =
500
+ min (backtrack_level, var (c->literals[0]).level);
501
+ LOG ("need to backtrack to before level %d", backtrack_level);
502
+ --j;
503
+ continue;
504
+ }
505
+ if (!c->collect ())
506
+ continue;
507
+ LOG (c, "removing from watch list");
508
+ --j;
509
+ }
510
+ ws.resize (j - ws.begin ());
511
+ shrink_vector (ws);
512
+ }
513
+ }
514
+ delete_garbage_clauses ();
515
+ unprotect_reasons ();
516
+ if (backtrack_level - 1 < level)
517
+ backtrack (backtrack_level - 1);
518
+ STOP (collect);
519
+ }
520
+
521
+ /*------------------------------------------------------------------------*/
522
+
523
+ bool Internal::arenaing () { return opts.arena && (stats.collections > 1); }
524
+
525
+ void Internal::garbage_collection () {
526
+ if (unsat)
527
+ return;
528
+ START (collect);
529
+ report ('G', 1);
530
+ stats.collections++;
531
+ mark_satisfied_clauses_as_garbage ();
532
+ if (!protected_reasons)
533
+ protect_reasons ();
534
+ if (arenaing ())
535
+ copy_non_garbage_clauses ();
536
+ else
537
+ delete_garbage_clauses ();
538
+ check_clause_stats ();
539
+ check_var_stats ();
540
+ unprotect_reasons ();
541
+ report ('C', 1);
542
+ STOP (collect);
543
+ }
544
+
545
+ } // namespace CaDiCaL