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,990 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ /*------------------------------------------------------------------------*/
6
+
7
+ // Failed literal probing uses its own propagation and assignment
8
+ // functions. It further provides on-the-fly generation of hyper binary
9
+ // resolvents but only probes on roots of the binary implication graph. The
10
+ // search for failed literals is limited, but untried roots are kept until
11
+ // the next time 'probe' is called. Left over probes from the last attempt
12
+ // and new probes are tried until the limit is hit or all are tried.
13
+
14
+ /*------------------------------------------------------------------------*/
15
+
16
+ bool Internal::inprobing () {
17
+ if (!opts.inprobing)
18
+ return false;
19
+ if (!preprocessing && !opts.inprocessing)
20
+ return false;
21
+ if (preprocessing)
22
+ assert (lim.preprocessing);
23
+ if (stats.inprobingphases && last.inprobe.reductions == stats.reductions)
24
+ return false;
25
+ return lim.inprobe <= stats.conflicts;
26
+ }
27
+
28
+ /*------------------------------------------------------------------------*/
29
+
30
+ inline int Internal::get_parent_reason_literal (int lit) {
31
+ const int idx = vidx (lit);
32
+ int res = parents[idx];
33
+ if (lit < 0)
34
+ res = -res;
35
+ return res;
36
+ }
37
+
38
+ inline void Internal::set_parent_reason_literal (int lit, int reason) {
39
+ const int idx = vidx (lit);
40
+ if (lit < 0)
41
+ reason = -reason;
42
+ parents[idx] = reason;
43
+ }
44
+
45
+ /*-----------------------------------------------------------------------*/
46
+
47
+ // for opts.probehbr=false we need to do a lot of extra work to remember the
48
+ // correct lrat_chains... This solution is also memory intensive I think
49
+ // all corresponding functions are guarded to only work with the right
50
+ // options so they can be called without checking for options
51
+ //
52
+ // call locally after failed_literal or backtracking
53
+ //
54
+ void Internal::clean_probehbr_lrat () {
55
+ if (!lrat || opts.probehbr)
56
+ return;
57
+ for (auto &field : probehbr_chains) {
58
+ for (auto &chain : field) {
59
+ chain.clear ();
60
+ }
61
+ }
62
+ }
63
+
64
+ // call globally before a probe round (or a lookahead round)
65
+ //
66
+ void Internal::init_probehbr_lrat () {
67
+ if (!lrat || opts.probehbr)
68
+ return;
69
+ const size_t size = 2 * (1 + (size_t) max_var);
70
+ probehbr_chains.resize (size);
71
+ for (size_t i = 0; i < size; i++) {
72
+ probehbr_chains[i].resize (size);
73
+ // commented because not needed... should be empty already
74
+ /*
75
+ for (size_t j = 0; j < size; j++) {
76
+ vector<int64_t> empty;
77
+ probehbr_chains[i][j] = empty;
78
+ }
79
+ */
80
+ }
81
+ }
82
+
83
+ // sets lrat_chain to the stored chain in probehbr_chains.
84
+ // this leads to conflict with unit reason uip
85
+ //
86
+ void Internal::get_probehbr_lrat (int lit, int uip) {
87
+ if (!lrat || opts.probehbr)
88
+ return;
89
+ assert (lit);
90
+ assert (lrat_chain.empty ());
91
+ assert (val (uip) < 0);
92
+ lrat_chain = probehbr_chains[vlit (lit)][vlit (uip)];
93
+ int64_t id = unit_id (-uip);
94
+ lrat_chain.push_back (id);
95
+ }
96
+
97
+ // sets the corresponding probehbr_chain to what is currently stored in
98
+ // lrat_chain. also clears lrat_chain.
99
+ //
100
+ void Internal::set_probehbr_lrat (int lit, int uip) {
101
+ if (!lrat || opts.probehbr)
102
+ return;
103
+ assert (lit);
104
+ assert (lrat_chain.size ());
105
+ assert (probehbr_chains[vlit (lit)][vlit (uip)].empty ());
106
+ probehbr_chains[vlit (lit)][vlit (uip)] = lrat_chain;
107
+ lrat_chain.clear ();
108
+ }
109
+
110
+ // compute lrat_chain for the part of the tree from lit to dom
111
+ // use mini_chain because it needs to be reversed
112
+ //
113
+ void Internal::probe_dominator_lrat (int dom, Clause *reason) {
114
+ if (!lrat || !dom)
115
+ return;
116
+ LOG (reason, "probe dominator LRAT for %d from", dom);
117
+ for (const auto lit : *reason) {
118
+ if (val (lit) >= 0)
119
+ continue;
120
+ const auto other = -lit;
121
+ if (other == dom)
122
+ continue;
123
+ Flags &f = flags (other);
124
+ if (f.seen)
125
+ continue;
126
+ f.seen = true;
127
+ analyzed.push_back (other);
128
+ Var u = var (other);
129
+ if (u.level) {
130
+ if (!u.reason) {
131
+ LOG ("this may be a problem %d", other);
132
+ continue;
133
+ }
134
+ probe_dominator_lrat (dom, u.reason);
135
+ continue;
136
+ }
137
+ int64_t id = unit_id (other);
138
+ lrat_chain.push_back (id);
139
+ }
140
+ lrat_chain.push_back (reason->id);
141
+ }
142
+
143
+ /*------------------------------------------------------------------------*/
144
+
145
+ // On-the-fly (dynamic) hyper binary resolution on decision level one can
146
+ // make use of the fact that the implication graph is actually a tree.
147
+
148
+ // Compute a dominator of two literals in the binary implication tree.
149
+
150
+ int Internal::probe_dominator (int a, int b) {
151
+ require_mode (PROBE);
152
+ int l = a, k = b;
153
+ Var *u = &var (l), *v = &var (k);
154
+ assert (val (l) > 0), assert (val (k) > 0);
155
+ assert (u->level == 1), assert (v->level == 1);
156
+ while (l != k) {
157
+ if (u->trail > v->trail)
158
+ swap (l, k), swap (u, v);
159
+ if (!get_parent_reason_literal (l))
160
+ return l;
161
+ int parent = get_parent_reason_literal (k);
162
+ assert (parent), assert (val (parent) > 0);
163
+ v = &var (k = parent);
164
+ assert (v->level == 1);
165
+ }
166
+ LOG ("dominator %d of %d and %d", l, a, b);
167
+ assert (val (l) > 0);
168
+ return l;
169
+ }
170
+
171
+ // The idea of dynamic on-the-fly hyper-binary resolution came up in the
172
+ // PrecoSAT solver, where it originally was used on all decision levels.
173
+
174
+ // It turned out, that most of the hyper-binary resolvents were generated
175
+ // during probing on decision level one anyhow. Thus this version is
176
+ // specialized to decision level one, where actually all long (non-binary)
177
+ // forcing clauses can be resolved to become binary. So if we find a clause
178
+ // which would force a new assignment at decision level one during probing
179
+ // we resolve it (the 'reason' argument) to obtain a hyper binary resolvent.
180
+ // It consists of the still unassigned literal (the new unit) and the
181
+ // negation of the unique closest dominator of the negation of all (false)
182
+ // literals in the clause (which has to exist on decision level one).
183
+
184
+ // There are two special cases which should be mentioned:
185
+ //
186
+ // (A) The reason is already a binary clause in a certain sense, since all
187
+ // its unwatched literals are root level fixed to false. In this
188
+ // situation it would be better to shrink the clause immediately instead
189
+ // of adding a new clause consisting only of the watched literals.
190
+ // However, this would happen during the next garbage collection anyhow.
191
+ //
192
+ // (B) The resolvent subsumes the original reason clause. This is
193
+ // equivalent to the property that the negated dominator is contained in
194
+ // the original reason. Again one could in principle shrink the clause.
195
+ //
196
+ // Note that (A) is actually subsumed by (B). The possible optimization to
197
+ // shrink the clause on-the-fly is difficult (need to update 'blit' and
198
+ // 'binary' of the other watch at least) and also not really that important.
199
+ // For (B) we simply add the new binary resolvent and mark the old subsumed
200
+ // clause as garbage instead. And since in the situation of (A) the
201
+ // shrinking will be performed at the next garbage collection anyhow, we
202
+ // do not change clauses in (A).
203
+
204
+ // The hyper binary resolvent clause is redundant unless it subsumes the
205
+ // original reason and that one is irredundant.
206
+
207
+ // If the option 'opts.probehbr' is 'false', we actually do not add the new
208
+ // hyper binary resolvent, but simply pretend we would have added it and
209
+ // still return the dominator as new reason / parent for the new unit.
210
+
211
+ // Finally note that adding clauses changes the watches of the propagated
212
+ // literal and thus we can not use standard iterators during probing but
213
+ // need to fall back to indices. One watch for the hyper binary resolvent
214
+ // clause is added at the end of the currently propagated watches, but its
215
+ // watch is a binary watch and will be skipped during propagating long
216
+ // clauses anyhow.
217
+
218
+ inline int Internal::hyper_binary_resolve (Clause *reason) {
219
+ require_mode (PROBE);
220
+ assert (level == 1);
221
+ assert (reason->size > 2);
222
+ const const_literal_iterator end = reason->end ();
223
+ const int *lits = reason->literals;
224
+ const_literal_iterator k;
225
+ #ifndef NDEBUG
226
+ // First literal unassigned, all others false.
227
+ assert (!val (lits[0]));
228
+ for (k = lits + 1; k != end; k++)
229
+ assert (val (*k) < 0);
230
+ assert (var (lits[1]).level == 1);
231
+ #endif
232
+ LOG (reason, "hyper binary resolving");
233
+ stats.hbrs++;
234
+ stats.hbrsizes += reason->size;
235
+ const int lit = lits[1];
236
+ int dom = -lit, non_root_level_literals = 0;
237
+ for (k = lits + 2; k != end; k++) {
238
+ const int other = -*k;
239
+ assert (val (other) > 0);
240
+ if (!var (other).level)
241
+ continue;
242
+ dom = probe_dominator (dom, other);
243
+ non_root_level_literals++;
244
+ }
245
+ probe_reason = reason;
246
+ if (non_root_level_literals && opts.probehbr) { // !(A)
247
+ bool contained = false;
248
+ for (k = lits + 1; !contained && k != end; k++)
249
+ contained = (*k == -dom);
250
+ const bool red = !contained || reason->redundant;
251
+ if (red)
252
+ stats.hbreds++;
253
+ LOG ("new %s hyper binary resolvent %d %d",
254
+ (red ? "redundant" : "irredundant"), -dom, lits[0]);
255
+ assert (clause.empty ());
256
+ clause.push_back (-dom);
257
+ clause.push_back (lits[0]);
258
+ probe_dominator_lrat (dom, reason);
259
+ if (lrat)
260
+ clear_analyzed_literals ();
261
+ Clause *c = new_hyper_binary_resolved_clause (red, 2);
262
+ probe_reason = c;
263
+ if (red)
264
+ c->hyper = true;
265
+ clause.clear ();
266
+ lrat_chain.clear ();
267
+ if (contained) {
268
+ stats.hbrsubs++;
269
+ LOG (reason, "subsumed original");
270
+ mark_garbage (reason);
271
+ }
272
+ } else if (non_root_level_literals && lrat) {
273
+ // still calculate LRAT and remember for later
274
+ assert (!opts.probehbr);
275
+ probe_dominator_lrat (dom, reason);
276
+ clear_analyzed_literals ();
277
+ set_probehbr_lrat (dom, lits[0]);
278
+ }
279
+ return dom;
280
+ }
281
+
282
+ /*------------------------------------------------------------------------*/
283
+
284
+ // The following functions 'probe_assign' and 'probe_propagate' are used for
285
+ // propagating during failed literal probing in simplification mode, as
286
+ // replacement of the generic propagation routine 'propagate' and
287
+ // 'search_assign'.
288
+
289
+ // The code is mostly copied from 'propagate.cpp' and specialized. We only
290
+ // comment on the differences. More explanations are in 'propagate.cpp'.
291
+
292
+ inline void Internal::probe_assign (int lit, int parent) {
293
+ require_mode (PROBE);
294
+ int idx = vidx (lit);
295
+ assert (!val (idx));
296
+ assert (!flags (idx).eliminated () || !parent);
297
+ assert (!parent || val (parent) > 0);
298
+ Var &v = var (idx);
299
+ v.level = level;
300
+ v.trail = (int) trail.size ();
301
+ assert ((int) num_assigned < max_var);
302
+ num_assigned++;
303
+ v.reason = level ? probe_reason : 0;
304
+ probe_reason = 0;
305
+ set_parent_reason_literal (lit, parent);
306
+ if (!level)
307
+ learn_unit_clause (lit);
308
+ else
309
+ assert (level == 1);
310
+ const signed char tmp = sign (lit);
311
+ set_val (idx, tmp);
312
+ assert (val (lit) > 0);
313
+ assert (val (-lit) < 0);
314
+ trail.push_back (lit);
315
+
316
+ // Do not save the current phase during inprocessing but remember the
317
+ // number of units on the trail of the last time this literal was
318
+ // assigned. This allows us to avoid some redundant failed literal
319
+ // probing attempts. Search for 'propfixed' in 'probe.cpp' for details.
320
+ //
321
+ if (level)
322
+ propfixed (lit) = stats.all.fixed;
323
+
324
+ if (parent)
325
+ LOG ("probe assign %d parent %d", lit, parent);
326
+ else if (level)
327
+ LOG ("probe assign %d probe", lit);
328
+ else
329
+ LOG ("probe assign %d negated failed literal UIP", lit);
330
+ }
331
+
332
+ void Internal::probe_assign_decision (int lit) {
333
+ require_mode (PROBE);
334
+ assert (!level);
335
+ assert (propagated == trail.size ());
336
+ level++;
337
+ control.push_back (Level (lit, trail.size ()));
338
+ probe_assign (lit, 0);
339
+ }
340
+
341
+ void Internal::probe_assign_unit (int lit) {
342
+ require_mode (PROBE);
343
+ assert (!level);
344
+ assert (active (lit));
345
+ probe_assign (lit, 0);
346
+ }
347
+
348
+ /*------------------------------------------------------------------------*/
349
+
350
+ // same as in propagate but inlined here
351
+ //
352
+ inline void Internal::probe_lrat_for_units (int lit) {
353
+ if (!lrat)
354
+ return;
355
+ if (level)
356
+ return; // not decision level 0
357
+ LOG ("building chain for units");
358
+ assert (lrat_chain.empty ());
359
+ assert (probe_reason);
360
+ for (auto &reason_lit : *probe_reason) {
361
+ if (lit == reason_lit)
362
+ continue;
363
+ assert (val (reason_lit));
364
+ if (!val (reason_lit))
365
+ continue;
366
+ const int signed_reason_lit = val (reason_lit) * reason_lit;
367
+ int64_t id = unit_id (signed_reason_lit);
368
+ lrat_chain.push_back (id);
369
+ }
370
+ lrat_chain.push_back (probe_reason->id);
371
+ }
372
+
373
+ /*------------------------------------------------------------------------*/
374
+
375
+ // This is essentially the same as 'propagate' except that we prioritize and
376
+ // always propagate binary clauses first (see our CPAIOR'13 paper on tree
377
+ // based look ahead), then immediately stop at a conflict and of course use
378
+ // 'probe_assign' instead of 'search_assign'. The binary propagation part
379
+ // is factored out too. If a new unit on decision level one is found we
380
+ // perform hyper binary resolution and thus actually build an implication
381
+ // tree instead of a DAG. Statistics counters are also different.
382
+
383
+ inline void Internal::probe_propagate2 () {
384
+ require_mode (PROBE);
385
+ int64_t &ticks = stats.ticks.probe;
386
+ while (propagated2 != trail.size ()) {
387
+ const int lit = -trail[propagated2++];
388
+ LOG ("probe propagating %d over binary clauses", -lit);
389
+ Watches &ws = watches (lit);
390
+ ticks += 1 + cache_lines (ws.size (), sizeof (const_watch_iterator *));
391
+ for (const auto &w : ws) {
392
+ if (!w.binary ())
393
+ continue;
394
+ const signed char b = val (w.blit);
395
+ if (b > 0)
396
+ continue;
397
+ ticks++;
398
+ if (b < 0)
399
+ conflict = w.clause; // but continue
400
+ else {
401
+ assert (lrat_chain.empty ());
402
+ assert (!probe_reason);
403
+ probe_reason = w.clause;
404
+ probe_lrat_for_units (w.blit);
405
+ probe_assign (w.blit, -lit);
406
+ lrat_chain.clear ();
407
+ }
408
+ }
409
+ }
410
+ }
411
+
412
+ bool Internal::probe_propagate () {
413
+ require_mode (PROBE);
414
+ assert (!unsat);
415
+ START (propagate);
416
+ int64_t before = propagated2 = propagated;
417
+ int64_t &ticks = stats.ticks.probe;
418
+ while (!conflict) {
419
+ if (propagated2 != trail.size ())
420
+ probe_propagate2 ();
421
+ else if (propagated != trail.size ()) {
422
+ const int lit = -trail[propagated++];
423
+ LOG ("probe propagating %d over large clauses", -lit);
424
+ Watches &ws = watches (lit);
425
+ ticks +=
426
+ 1 + cache_lines (ws.size (), sizeof (const_watch_iterator *));
427
+ size_t i = 0, j = 0;
428
+ while (i != ws.size ()) {
429
+ const Watch w = ws[j++] = ws[i++];
430
+ if (w.binary ())
431
+ continue;
432
+ const signed char b = val (w.blit);
433
+ if (b > 0)
434
+ continue;
435
+ ticks++;
436
+ if (w.clause->garbage)
437
+ continue;
438
+ const literal_iterator lits = w.clause->begin ();
439
+ const int other = lits[0] ^ lits[1] ^ lit;
440
+ // lits[0] = other, lits[1] = lit;
441
+ const signed char u = val (other);
442
+ if (u > 0)
443
+ ws[j - 1].blit = other;
444
+ else {
445
+ const int size = w.clause->size;
446
+ const const_literal_iterator end = lits + size;
447
+ const literal_iterator middle = lits + w.clause->pos;
448
+ literal_iterator k = middle;
449
+ int r = 0;
450
+ signed char v = -1;
451
+ while (k != end && (v = val (r = *k)) < 0)
452
+ k++;
453
+ if (v < 0) {
454
+ k = lits + 2;
455
+ assert (w.clause->pos <= size);
456
+ while (k != middle && (v = val (r = *k)) < 0)
457
+ k++;
458
+ }
459
+ w.clause->pos = k - lits;
460
+ assert (lits + 2 <= k), assert (k <= w.clause->end ());
461
+ if (v > 0)
462
+ ws[j - 1].blit = r;
463
+ else if (!v) {
464
+ ticks++;
465
+ LOG (w.clause, "unwatch %d in", r);
466
+ *k = lit;
467
+ lits[0] = other;
468
+ lits[1] = r;
469
+ watch_literal (r, lit, w.clause);
470
+ j--;
471
+ } else if (!u) {
472
+ ticks++;
473
+ if (level == 1) {
474
+ lits[0] = other, lits[1] = lit;
475
+ assert (lrat_chain.empty ());
476
+ assert (!probe_reason);
477
+ int dom = hyper_binary_resolve (w.clause);
478
+ probe_assign (other, dom);
479
+ } else {
480
+ ticks++;
481
+ assert (lrat_chain.empty ());
482
+ assert (!probe_reason);
483
+ probe_reason = w.clause;
484
+ probe_lrat_for_units (other);
485
+ probe_assign_unit (other);
486
+ lrat_chain.clear ();
487
+ }
488
+ probe_propagate2 ();
489
+ } else
490
+ conflict = w.clause;
491
+ }
492
+ }
493
+ if (j != i) {
494
+ while (i != ws.size ())
495
+ ws[j++] = ws[i++];
496
+ ws.resize (j);
497
+ }
498
+ } else
499
+ break;
500
+ }
501
+ int64_t delta = propagated2 - before;
502
+ stats.propagations.probe += delta;
503
+ if (conflict)
504
+ LOG (conflict, "conflict");
505
+ STOP (propagate);
506
+ return !conflict;
507
+ }
508
+
509
+ /*------------------------------------------------------------------------*/
510
+
511
+ // This a specialized instance of 'analyze'.
512
+
513
+ void Internal::failed_literal (int failed) {
514
+
515
+ LOG ("analyzing failed literal probe %d", failed);
516
+ stats.failed++;
517
+ stats.probefailed++;
518
+
519
+ assert (!unsat);
520
+ assert (conflict);
521
+ assert (level == 1);
522
+ assert (analyzed.empty ());
523
+ assert (lrat_chain.empty ());
524
+
525
+ START (analyze);
526
+
527
+ LOG (conflict, "analyzing failed literal conflict");
528
+
529
+ int uip = 0;
530
+ for (const auto &lit : *conflict) {
531
+ const int other = -lit;
532
+ if (!var (other).level) {
533
+ assert (val (other) > 0);
534
+ continue;
535
+ }
536
+ uip = uip ? probe_dominator (uip, other) : other;
537
+ }
538
+ probe_dominator_lrat (uip, conflict);
539
+ if (lrat)
540
+ clear_analyzed_literals ();
541
+
542
+ LOG ("found probing UIP %d", uip);
543
+ assert (uip);
544
+
545
+ vector<int> work;
546
+
547
+ int parent = uip;
548
+ while (parent != failed) {
549
+ const int next = get_parent_reason_literal (parent);
550
+ parent = next;
551
+ assert (parent);
552
+ work.push_back (parent);
553
+ }
554
+
555
+ backtrack ();
556
+ conflict = 0;
557
+
558
+ assert (!val (uip));
559
+ probe_assign_unit (-uip);
560
+ lrat_chain.clear ();
561
+
562
+ if (!probe_propagate ())
563
+ learn_empty_clause ();
564
+
565
+ size_t j = 0;
566
+ while (!unsat && j < work.size ()) {
567
+ // assert (!opts.probehbr); assertion fails ...
568
+ const int parent = work[j++];
569
+ const signed char tmp = val (parent);
570
+ if (tmp > 0) {
571
+ assert (!opts.probehbr); // ... assertion should hold here
572
+ get_probehbr_lrat (parent, uip);
573
+ LOG ("clashing failed parent %d", parent);
574
+ learn_empty_clause ();
575
+ } else if (tmp == 0) {
576
+ assert (!opts.probehbr); // ... and here
577
+ LOG ("found unassigned failed parent %d", parent);
578
+ get_probehbr_lrat (parent, uip); // this is computed during
579
+ probe_assign_unit (-parent); // propagation and can include
580
+ lrat_chain.clear (); // multiple chains where only one
581
+ if (!probe_propagate ())
582
+ learn_empty_clause (); // is needed!
583
+ }
584
+ uip = parent;
585
+ }
586
+ work.clear ();
587
+ erase_vector (work);
588
+
589
+ STOP (analyze);
590
+
591
+ assert (unsat || val (failed) < 0);
592
+ }
593
+
594
+ /*------------------------------------------------------------------------*/
595
+
596
+ bool Internal::is_binary_clause (Clause *c, int &a, int &b) {
597
+ assert (!level);
598
+ if (c->garbage)
599
+ return false;
600
+ int first = 0, second = 0;
601
+ for (const auto &lit : *c) {
602
+ const signed char tmp = val (lit);
603
+ if (tmp > 0)
604
+ return false;
605
+ if (tmp < 0)
606
+ continue;
607
+ if (second)
608
+ return false;
609
+ if (first)
610
+ second = lit;
611
+ else
612
+ first = lit;
613
+ }
614
+ if (!second)
615
+ return false;
616
+ a = first, b = second;
617
+ return true;
618
+ }
619
+
620
+ // We probe on literals first, which occur more often negated and thus we
621
+ // sort the 'probes' stack in such a way that literals which occur negated
622
+ // less frequently come first. Probes are taken from the back of the stack.
623
+
624
+ struct probe_negated_noccs_rank {
625
+ Internal *internal;
626
+ probe_negated_noccs_rank (Internal *i) : internal (i) {}
627
+ typedef size_t Type;
628
+ Type operator() (int a) const { return internal->noccs (-a); }
629
+ };
630
+
631
+ // Fill the 'probes' schedule.
632
+
633
+ void Internal::generate_probes () {
634
+
635
+ assert (probes.empty ());
636
+
637
+ int64_t &ticks = stats.ticks.probe;
638
+
639
+ // First determine all the literals which occur in binary clauses. It is
640
+ // way faster to go over the clauses once, instead of walking the watch
641
+ // lists for each literal.
642
+ //
643
+ init_noccs ();
644
+ ticks += 1 + cache_lines (clauses.size (), sizeof (Clause *));
645
+ for (const auto &c : clauses) {
646
+ int a, b;
647
+ ticks++;
648
+ if (!is_binary_clause (c, a, b))
649
+ continue;
650
+ noccs (a)++;
651
+ noccs (b)++;
652
+ }
653
+
654
+ for (auto idx : vars) {
655
+
656
+ // Then focus on roots of the binary implication graph, which are
657
+ // literals occurring negatively in a binary clause, but not positively.
658
+ // If neither 'idx' nor '-idx' is a root it makes less sense to probe
659
+ // this variable.
660
+
661
+ // This argument requires that equivalent literal substitution through
662
+ // 'decompose' is performed, because otherwise there might be 'cyclic
663
+ // roots' which are not tried, i.e., -1 2 0, 1 -2 0, 1 2 3 0, 1 2 -3 0.
664
+
665
+ ticks += 2;
666
+
667
+ const bool have_pos_bin_occs = noccs (idx) > 0;
668
+ const bool have_neg_bin_occs = noccs (-idx) > 0;
669
+
670
+ if (have_pos_bin_occs == have_neg_bin_occs)
671
+ continue;
672
+
673
+ int probe = have_neg_bin_occs ? idx : -idx;
674
+
675
+ // See the discussion where 'propfixed' is used below.
676
+ //
677
+ if (propfixed (probe) >= stats.all.fixed)
678
+ continue;
679
+
680
+ LOG ("scheduling probe %d negated occs %" PRId64 "", probe,
681
+ noccs (-probe));
682
+ probes.push_back (probe);
683
+ }
684
+
685
+ rsort (probes.begin (), probes.end (), probe_negated_noccs_rank (this));
686
+
687
+ reset_noccs ();
688
+ shrink_vector (probes);
689
+
690
+ PHASE ("probe-round", stats.probingrounds,
691
+ "scheduled %zd literals %.0f%%", probes.size (),
692
+ percent (probes.size (), 2u * max_var));
693
+ }
694
+
695
+ // Follow the ideas in 'generate_probes' but flush non root probes and
696
+ // reorder remaining probes.
697
+
698
+ void Internal::flush_probes () {
699
+
700
+ assert (!probes.empty ());
701
+ int64_t &ticks = stats.ticks.probe;
702
+
703
+ init_noccs ();
704
+ ticks += 1 + cache_lines (clauses.size (), sizeof (Clause *));
705
+ for (const auto &c : clauses) {
706
+ int a, b;
707
+ ticks++;
708
+ if (!is_binary_clause (c, a, b))
709
+ continue;
710
+ noccs (a)++;
711
+ noccs (b)++;
712
+ }
713
+
714
+ const auto eop = probes.end ();
715
+ auto j = probes.begin ();
716
+ for (auto i = j; i != eop; i++) {
717
+ int lit = *i;
718
+ if (!active (lit))
719
+ continue;
720
+ ticks += 2;
721
+ const bool have_pos_bin_occs = noccs (lit) > 0;
722
+ const bool have_neg_bin_occs = noccs (-lit) > 0;
723
+ if (have_pos_bin_occs == have_neg_bin_occs)
724
+ continue;
725
+ if (have_pos_bin_occs)
726
+ lit = -lit;
727
+ assert (!noccs (lit)), assert (noccs (-lit) > 0);
728
+ if (propfixed (lit) >= stats.all.fixed)
729
+ continue;
730
+ LOG ("keeping probe %d negated occs %" PRId64 "", lit, noccs (-lit));
731
+ *j++ = lit;
732
+ }
733
+ size_t remain = j - probes.begin ();
734
+ #ifndef QUIET
735
+ size_t flushed = probes.size () - remain;
736
+ #endif
737
+ probes.resize (remain);
738
+
739
+ rsort (probes.begin (), probes.end (), probe_negated_noccs_rank (this));
740
+
741
+ reset_noccs ();
742
+ shrink_vector (probes);
743
+
744
+ PHASE ("probe-round", stats.probingrounds,
745
+ "flushed %zd literals %.0f%% remaining %zd", flushed,
746
+ percent (flushed, remain + flushed), remain);
747
+ }
748
+
749
+ int Internal::next_probe () {
750
+
751
+ int generated = 0;
752
+
753
+ for (;;) {
754
+
755
+ if (probes.empty ()) {
756
+ if (generated++)
757
+ return 0;
758
+ generate_probes ();
759
+ }
760
+
761
+ while (!probes.empty ()) {
762
+
763
+ int probe = probes.back ();
764
+ probes.pop_back ();
765
+
766
+ // Eliminated or assigned.
767
+ //
768
+ if (!active (probe))
769
+ continue;
770
+
771
+ // There is now new unit since the last time we propagated this probe,
772
+ // thus we propagated it before without obtaining a conflict and
773
+ // nothing changed since then. Thus there is no need to propagate it
774
+ // again. This observation was independently made by Partik Simons
775
+ // et.al. in the context of implementing 'smodels' (see for instance
776
+ // Alg. 4 in his JAIR article from 2002) and it has also been
777
+ // contributed to the thesis work of Yacine Boufkhad.
778
+ //
779
+ if (propfixed (probe) >= stats.all.fixed)
780
+ continue;
781
+
782
+ return probe;
783
+ }
784
+ }
785
+ }
786
+
787
+ bool Internal::probe () {
788
+
789
+ if (!opts.probe)
790
+ return false;
791
+ if (unsat)
792
+ return false;
793
+ if (terminated_asynchronously ())
794
+ return false;
795
+
796
+ SET_EFFORT_LIMIT (limit, probe, true);
797
+
798
+ START_SIMPLIFIER (probe, PROBE);
799
+ stats.probingrounds++;
800
+
801
+ // Probing is limited in terms of non-probing propagations
802
+ // 'stats.propagations'. We allow a certain percentage 'opts.probeeffort'
803
+ // (say %5) of probing propagations in each probing with a lower bound of
804
+ // 'opts.probmineff'.
805
+ //
806
+
807
+ PHASE ("probe-round", stats.probingrounds,
808
+ "probing limit of %" PRId64 " propagations ", limit);
809
+
810
+ int old_failed = stats.failed;
811
+ #ifndef QUIET
812
+ int64_t old_probed = stats.probed;
813
+ #endif
814
+ int64_t old_hbrs = stats.hbrs;
815
+
816
+ if (!probes.empty ())
817
+ flush_probes ();
818
+
819
+ // We reset 'propfixed' since there was at least another conflict thus
820
+ // a new learned clause, which might produce new propagations (and hyper
821
+ // binary resolvents). During 'generate_probes' we keep the old value.
822
+ //
823
+ for (auto idx : vars)
824
+ propfixed (idx) = propfixed (-idx) = -1;
825
+
826
+ assert (unsat || propagated == trail.size ());
827
+ propagated = propagated2 = trail.size ();
828
+
829
+ int probe;
830
+ init_probehbr_lrat ();
831
+ while (!unsat && !terminated_asynchronously () &&
832
+ stats.ticks.probe < limit && (probe = next_probe ())) {
833
+ stats.probed++;
834
+ LOG ("probing %d", probe);
835
+ probe_assign_decision (probe);
836
+ if (probe_propagate ())
837
+ backtrack_without_updating_phases ();
838
+ else
839
+ failed_literal (probe);
840
+ clean_probehbr_lrat ();
841
+ }
842
+
843
+ if (unsat)
844
+ LOG ("probing derived empty clause");
845
+ else if (propagated < trail.size ()) {
846
+ LOG ("probing produced %zd units",
847
+ (size_t) (trail.size () - propagated));
848
+ if (!propagate ()) {
849
+ LOG ("propagating units after probing results in empty clause");
850
+ learn_empty_clause ();
851
+ } else
852
+ sort_watches ();
853
+ }
854
+
855
+ int failed = stats.failed - old_failed;
856
+ #ifndef QUIET
857
+ int64_t probed = stats.probed - old_probed;
858
+ #endif
859
+ int64_t hbrs = stats.hbrs - old_hbrs;
860
+
861
+ PHASE ("probe-round", stats.probingrounds,
862
+ "probed %" PRId64 " and found %d failed literals", probed, failed);
863
+
864
+ if (hbrs)
865
+ PHASE ("probe-round", stats.probingrounds,
866
+ "found %" PRId64 " hyper binary resolvents", hbrs);
867
+
868
+ STOP_SIMPLIFIER (probe, PROBE);
869
+
870
+ report ('p', !opts.reportall && !(unsat + failed + hbrs));
871
+
872
+ return !unsat && failed;
873
+ }
874
+
875
+ /*------------------------------------------------------------------------*/
876
+
877
+ // This schedules a number of inprocessing techniques.
878
+ // These range from very cheap and beneficial (decompose) to
879
+ // more expensive and sometimes less beneficial. We want to limit
880
+ // expensive techniques to some fraction of total time or search time.
881
+ // this is done using 'ticks'.
882
+ // Generally, there are options for each of the techniques to set the
883
+ // efficiency, i.e., the fraction of ticks they are allowed as budget.
884
+ // Whenever e.g. vivify is called, the budget is calculated from the
885
+ // search ticks that have passed since the last vivify round and this
886
+ // efficiency.
887
+ // We want to be able to run inprocessing frequently, without it dominating
888
+ // runtimes. This entire inprocessing scheme is scheduled after a certain
889
+ // amount of conflicts were found, the gap between two inprocessing rounds
890
+ // increasing by a constant number each time. In effect, the number of
891
+ // inprocessing rounds is allways the square root of the number of conflicts
892
+ // with some constant factor.
893
+ // This factor can also be with the option 'inprobeint'
894
+ // Some of the techniques are not run always, for different reasons.
895
+ // 'factor' or BVA depends on certain structures of the irredundant clauses
896
+ // and as such will only be run when new irredundant clauses are derived or
897
+ // it was not able to finish with the entire search space.
898
+ // 'sweeping' is especially usefull on certain classes of formulas, and uses
899
+ // a increasing or decreasing delay that depends on how usefull it was.
900
+ // In cases where it is less usefull, we obviously want to reset the budged,
901
+ // even if the routine was delayed.
902
+ // Additionally 'vivify', 'sweep' and 'factor' can also have a big initial
903
+ // overhead in setting up the datastructures. This has to be accounted for
904
+ // with the 'ticks', however, since inprocessing is done frequently, this
905
+ // overhead is too expensive to pay. So instead, we accumulate the budget
906
+ // of 'ticks' and delay the technique until it passes a certain threshhold,
907
+ // which depends on the the cost of initialization. Note that in the case of
908
+ // sweeping, we have two different delays, one which resets the budged, and
909
+ // one which passes it to the next round. In this case the former takes
910
+ // precendent, until we would run sweeping once, at which point the focus
911
+ // switches to the latter delay until the budget is big enough, such that
912
+ // sweeping can be run. Then we switch back to the other delay.
913
+
914
+ void CaDiCaL::Internal::inprobe (bool update_limits) {
915
+
916
+ if (unsat)
917
+ return;
918
+ if (level)
919
+ backtrack ();
920
+ if (!propagate ()) {
921
+ learn_empty_clause ();
922
+ return;
923
+ }
924
+
925
+ stats.inprobingphases++;
926
+ if (external_prop) {
927
+ assert (!level);
928
+ private_steps = true;
929
+ }
930
+ const int before = active ();
931
+ const int before_extended = stats.variables_extension;
932
+
933
+ // schedule of inprobing techniques.
934
+ //
935
+ {
936
+ mark_duplicated_binary_clauses_as_garbage ();
937
+ decompose ();
938
+ if (ternary ())
939
+ decompose (); // If we derived a binary clause
940
+ if (probe ())
941
+ decompose ();
942
+
943
+ if (extract_gates (preprocessing))
944
+ decompose ();
945
+ binary_clauses_backbone ();
946
+ mark_duplicated_binary_clauses_as_garbage ();
947
+ if (sweep ()) // full occurrence list
948
+ decompose (); // ... and (ELS) afterwards.
949
+ (void) vivify (); // resets watches
950
+ transred (); // builds big.
951
+ binary_clauses_backbone ();
952
+ factor (); // resets watches, partial occurrence list
953
+ }
954
+
955
+ if (external_prop) {
956
+ assert (!level);
957
+ private_steps = false;
958
+ }
959
+
960
+ if (!update_limits)
961
+ return;
962
+
963
+ const int after = active ();
964
+ const int after_extended = stats.variables_extension;
965
+ const int diff_extended = after_extended - before_extended;
966
+ assert (diff_extended >= 0);
967
+ const int removed = before - after + diff_extended;
968
+ assert (removed >= 0);
969
+
970
+ if (removed) {
971
+ stats.inprobesuccess++;
972
+ PHASE ("probe-phase", stats.inprobingphases,
973
+ "successfully removed %d active variables %.0f%%", removed,
974
+ percent (removed, before));
975
+ } else
976
+ PHASE ("probe-phase", stats.inprobingphases,
977
+ "could not remove any active variable");
978
+
979
+ const int64_t delta =
980
+ 25 * (int64_t) opts.inprobeint * log10 (stats.inprobingphases + 9);
981
+ lim.inprobe = stats.conflicts + delta;
982
+
983
+ PHASE ("probe-phase", stats.inprobingphases,
984
+ "new limit at %" PRId64 " conflicts after %" PRId64 " conflicts",
985
+ lim.inprobe, delta);
986
+
987
+ last.inprobe.reductions = stats.reductions;
988
+ }
989
+
990
+ } // namespace CaDiCaL