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,1265 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ /*------------------------------------------------------------------------*/
6
+ static Clause external_reason_clause;
7
+
8
+ Internal::Internal ()
9
+ : mode (SEARCH), unsat (false), iterating (false),
10
+ localsearching (false), lookingahead (false), preprocessing (false),
11
+ protected_reasons (false), force_saved_phase (false),
12
+ searching_lucky_phases (false), stable (false), reported (false),
13
+ external_prop (false), did_external_prop (false),
14
+ external_prop_is_lazy (true), forced_backt_allowed (false),
15
+
16
+ private_steps (false), rephased (0), vsize (0), max_var (0),
17
+ clause_id (0), original_id (0), reserved_ids (0), conflict_id (0),
18
+ saved_decisions (0), concluded (false), lrat (false), frat (false),
19
+ level (0), vals (0), score_inc (1.0), scores (this), conflict (0),
20
+ ignore (0), external_reason (&external_reason_clause),
21
+ newest_clause (0), force_no_backtrack (false),
22
+ from_propagator (false), ext_clause_forgettable (false),
23
+ changed_val (0), notified (0), probe_reason (0), propagated (0),
24
+ propagated2 (0), propergated (0), best_assigned (0),
25
+ target_assigned (0), no_conflict_until (0), unsat_constraint (false),
26
+ marked_failed (true), sweep_incomplete (false),
27
+ randomized_deciding (false), citten (0), num_assigned (0), proof (0),
28
+ opts (this),
29
+ #ifndef QUIET
30
+ profiles (this), force_phase_messages (false),
31
+ #endif
32
+ arena (this), prefix ("c "), internal (this), external (0),
33
+ termination_forced (false), vars (this->max_var),
34
+ lits (this->max_var) {
35
+ control.push_back (Level (0, 0));
36
+
37
+ // The 'dummy_binary' is used in 'try_to_subsume_clause' to fake a real
38
+ // clause (which then can be used to subsume or strengthen the given
39
+ // clause in one routine for both binary and non binary clauses) and
40
+ // in walk (which is only used as a placeholder in the watch lists
41
+ // when logging is off, since the clause is not accessed). This
42
+ // fake binary clause is always kept non-redundant (and not-moved etc.)
43
+ // due to the following 'memset'. Only literals will be changed.
44
+
45
+ // In a previous version we used local automatic allocated 'Clause' on the
46
+ // stack, which became incompatible with several compilers (see the
47
+ // discussion on flexible array member in 'Clause.cpp').
48
+
49
+ size_t bytes = Clause::bytes (2);
50
+ dummy_binary = (Clause *) new char[bytes];
51
+ memset (dummy_binary, 0, bytes);
52
+ dummy_binary->size = 2;
53
+
54
+ /*with C++17: static_*/ assert (max_used == (1 << USED_SIZE) - 1);
55
+ }
56
+
57
+ Internal::~Internal () {
58
+ // If a memory exception ocurred a profile might still be active.
59
+ #ifndef QUIET
60
+ #define PROFILE(NAME, LEVEL) \
61
+ if (PROFILE_ACTIVE (NAME)) \
62
+ STOP (NAME);
63
+ PROFILES
64
+ #undef PROFILE
65
+ #endif
66
+ delete[] (char *) dummy_binary;
67
+ for (const auto &c : clauses)
68
+ delete_clause (c);
69
+ if (proof)
70
+ delete proof;
71
+ for (auto &tracer : tracers)
72
+ delete tracer;
73
+ for (auto &filetracer : file_tracers)
74
+ delete filetracer;
75
+ for (auto &stattracer : stat_tracers)
76
+ delete stattracer;
77
+ if (vals) {
78
+ vals -= vsize;
79
+ delete[] vals;
80
+ }
81
+ }
82
+
83
+ /*------------------------------------------------------------------------*/
84
+
85
+ // Values in 'vals' can be accessed in the range '[-max_var,max_var]' that
86
+ // is directly by a literal. This is crucial for performance. By shifting
87
+ // the start of 'vals' appropriately, we achieve that negative offsets from
88
+ // the start of 'vals' can be used. We also need to set both values at
89
+ // 'lit' and '-lit' during assignments. In MiniSAT integer literals are
90
+ // encoded, using the least significant bit as negation. This avoids taking
91
+ // the 'abs ()' (as in our solution) and thus also avoids a branch in the
92
+ // hot-spot of the solver (clause traversal in propagation). That solution
93
+ // requires another (branch less) negation of the values though and
94
+ // debugging is harder since literals occur only encoded in clauses.
95
+ // The main draw-back of our solution is that we have to shift the memory
96
+ // and access it through negative indices, which looks less clean (but still
97
+ // as far I can tell is properly defined C / C++). You might get a warning
98
+ // by static analyzers though. Clang with '--analyze' thought that this
99
+ // idiom would generate a memory leak thus we use the following dummy.
100
+
101
+ static signed char *ignore_clang_analyze_memory_leak_warning;
102
+
103
+ void Internal::enlarge_vals (size_t new_vsize) {
104
+ signed char *new_vals;
105
+ const size_t bytes = 2u * new_vsize;
106
+ new_vals = new signed char[bytes]; // g++-4.8 does not like ... { 0 };
107
+ memset (new_vals, 0, bytes);
108
+ ignore_clang_analyze_memory_leak_warning = new_vals;
109
+ new_vals += new_vsize;
110
+
111
+ if (vals) {
112
+ memcpy (new_vals - max_var, vals - max_var, 2u * max_var + 1u);
113
+ vals -= vsize;
114
+ delete[] vals;
115
+ } else
116
+ assert (!vsize);
117
+ vals = new_vals;
118
+ }
119
+
120
+ /*------------------------------------------------------------------------*/
121
+
122
+ void Internal::enlarge (int new_max_var) {
123
+ // New variables can be created that can invoke enlarge anytime (via calls
124
+ // during ipasir-up call-backs), thus assuming (!level) is not correct
125
+ size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) new_max_var;
126
+ while (new_vsize <= (size_t) new_max_var)
127
+ new_vsize *= 2;
128
+ LOG ("enlarge internal size from %zd to new size %zd", vsize, new_vsize);
129
+ // Ordered in the size of allocated memory (larger block first).
130
+ if (lrat || frat)
131
+ enlarge_zero (unit_clauses_idx, 2 * new_vsize);
132
+ enlarge_only (wtab, 2 * new_vsize);
133
+ enlarge_only (vtab, new_vsize);
134
+ enlarge_zero (parents, new_vsize);
135
+ enlarge_only (links, new_vsize);
136
+ enlarge_zero (btab, new_vsize);
137
+ enlarge_zero (gtab, new_vsize);
138
+ enlarge_zero (stab, new_vsize);
139
+ enlarge_init (ptab, 2 * new_vsize, -1);
140
+ enlarge_only (ftab, new_vsize);
141
+ enlarge_vals (new_vsize);
142
+ vsize = new_vsize;
143
+ if (external)
144
+ enlarge_zero (relevanttab, new_vsize);
145
+ const signed char val = opts.phase ? 1 : -1;
146
+ enlarge_init (phases.saved, new_vsize, val);
147
+ enlarge_zero (phases.forced, new_vsize);
148
+ enlarge_zero (phases.target, new_vsize);
149
+ enlarge_zero (phases.best, new_vsize);
150
+ enlarge_zero (phases.prev, new_vsize);
151
+ enlarge_zero (marks, new_vsize);
152
+ }
153
+
154
+ void Internal::init_vars (int new_max_var) {
155
+ if (new_max_var <= max_var)
156
+ return;
157
+ // New variables can be created that can invoke enlarge anytime (via calls
158
+ // during ipasir-up call-backs), thus assuming (!level) is not correct
159
+ LOG ("initializing %d internal variables from %d to %d",
160
+ new_max_var - max_var, max_var + 1, new_max_var);
161
+ if ((size_t) new_max_var >= vsize)
162
+ enlarge (new_max_var);
163
+ #ifndef NDEBUG
164
+ for (int64_t i = -new_max_var; i < -max_var; i++)
165
+ assert (!vals[i]);
166
+ for (unsigned i = max_var + 1; i <= (unsigned) new_max_var; i++)
167
+ assert (!vals[i]), assert (!btab[i]), assert (!gtab[i]);
168
+ for (uint64_t i = 2 * ((uint64_t) max_var + 1);
169
+ i <= 2 * (uint64_t) new_max_var + 1; i++)
170
+ assert (ptab[i] == -1);
171
+ #endif
172
+ assert (!btab[0]);
173
+ int old_max_var = max_var;
174
+ max_var = new_max_var;
175
+ init_queue (old_max_var, new_max_var);
176
+ init_scores (old_max_var, new_max_var);
177
+ int initialized = new_max_var - old_max_var;
178
+ stats.vars += initialized;
179
+ stats.unused += initialized;
180
+ stats.inactive += initialized;
181
+ LOG ("finished initializing %d internal variables", initialized);
182
+ }
183
+
184
+ void Internal::add_original_lit (int lit) {
185
+ assert (abs (lit) <= max_var);
186
+ if (lit) {
187
+ original.push_back (lit);
188
+ } else {
189
+ const int64_t id =
190
+ original_id < reserved_ids ? ++original_id : ++clause_id;
191
+ if (proof) {
192
+ // Use the external form of the clause for printing in proof
193
+ // Externalize(internalized literal) != external literal
194
+ assert (!original.size () || !external->eclause.empty ());
195
+ proof->add_external_original_clause (id, false, external->eclause);
196
+ }
197
+ if (internal->opts.check &&
198
+ (internal->opts.checkwitness || internal->opts.checkfailed)) {
199
+ bool forgettable = from_propagator && ext_clause_forgettable;
200
+ if (forgettable && opts.check) {
201
+ assert (!original.size () || !external->eclause.empty ());
202
+
203
+ // First integer is the presence-flag (even if the clause is empty)
204
+ external->forgettable_original[id] = {1};
205
+
206
+ for (auto const &elit : external->eclause)
207
+ external->forgettable_original[id].push_back (elit);
208
+
209
+ LOG (external->eclause,
210
+ "clause added to external forgettable map:");
211
+ }
212
+ }
213
+
214
+ add_new_original_clause (id);
215
+ original.clear ();
216
+ }
217
+ }
218
+
219
+ void Internal::finish_added_clause_with_id (int64_t id, bool restore) {
220
+ if (proof) {
221
+ // Use the external form of the clause for printing in proof
222
+ // Externalize(internalized literal) != external literal
223
+ assert (!original.size () || !external->eclause.empty ());
224
+ proof->add_external_original_clause (id, false, external->eclause,
225
+ restore);
226
+ }
227
+ add_new_original_clause (id);
228
+ original.clear ();
229
+ }
230
+
231
+ /*------------------------------------------------------------------------*/
232
+
233
+ void Internal::reserve_ids (int number) {
234
+ // return;
235
+ LOG ("reserving %d ids", number);
236
+ assert (number >= 0);
237
+ assert (!clause_id && !reserved_ids && !original_id);
238
+ clause_id = reserved_ids = number;
239
+ if (proof)
240
+ proof->begin_proof (reserved_ids);
241
+ }
242
+
243
+ /*------------------------------------------------------------------------*/
244
+
245
+ #ifdef PROFILE_MODE
246
+
247
+ // Separating these makes it easier to profile stable and unstable search.
248
+
249
+ bool Internal::propagate_wrapper () {
250
+ if (stable)
251
+ return propagate_stable ();
252
+ else
253
+ return propagate_unstable ();
254
+ }
255
+
256
+ void Internal::analyze_wrapper () {
257
+ if (stable)
258
+ analyze_stable ();
259
+ else
260
+ analyze_unstable ();
261
+ }
262
+
263
+ int Internal::decide_wrapper () {
264
+ if (stable)
265
+ return decide_stable ();
266
+ else
267
+ return decide_unstable ();
268
+ }
269
+
270
+ #endif
271
+
272
+ /*------------------------------------------------------------------------*/
273
+
274
+ // This is the main CDCL loop with interleaved inprocessing.
275
+
276
+ int Internal::cdcl_loop_with_inprocessing () {
277
+
278
+ int res = 0;
279
+
280
+ START (search);
281
+
282
+ if (stable) {
283
+ START (stable);
284
+ report ('[');
285
+ } else {
286
+ START (unstable);
287
+ report ('{');
288
+ }
289
+
290
+ while (!res) {
291
+ if (unsat)
292
+ res = 20;
293
+ else if (unsat_constraint)
294
+ res = 20;
295
+ else if (!propagate_wrapper ())
296
+ analyze_wrapper (); // propagate and analyze
297
+ else if (iterating)
298
+ iterate (); // report learned unit
299
+ else if (!external_propagate () || unsat) { // external propagation
300
+ if (unsat)
301
+ continue;
302
+ else
303
+ analyze ();
304
+ } else if (satisfied ()) { // found model
305
+ if (!external_check_solution () || unsat) {
306
+ if (unsat)
307
+ continue;
308
+ else
309
+ analyze ();
310
+ } else if (satisfied ())
311
+ res = 10;
312
+ } else if (search_limits_hit ())
313
+ break; // decision or conflict limit
314
+ else if (terminated_asynchronously ()) // externally terminated
315
+ break;
316
+ else if (restarting ())
317
+ restart (); // restart by backtracking
318
+ else if (rephasing ())
319
+ rephase (); // reset variable phases
320
+ else if (reducing ())
321
+ reduce (); // collect useless clauses
322
+ else if (inprobing ())
323
+ inprobe (); // schedule of inprocessing
324
+ else if (ineliminating ())
325
+ elim (); // variable elimination
326
+ else if (compacting ())
327
+ compact (); // collect variables
328
+ else if (conditioning ())
329
+ condition (); // globally blocked clauses
330
+ else
331
+ res = decide (); // next decision
332
+ }
333
+
334
+ if (stable) {
335
+ STOP (stable);
336
+ report (']');
337
+ } else {
338
+ STOP (unstable);
339
+ report ('}');
340
+ }
341
+
342
+ STOP (search);
343
+
344
+ return res;
345
+ }
346
+
347
+ int Internal::propagate_assumptions () {
348
+ if (proof)
349
+ proof->solve_query ();
350
+ if (opts.ilb) {
351
+ sort_and_reuse_assumptions ();
352
+ assert (opts.ilb == 2 || (size_t) level <= assumptions.size ());
353
+ stats.ilbtriggers++;
354
+ stats.ilbsuccess += (level > 0);
355
+ stats.levelsreused += level;
356
+ if (level) {
357
+ assert (control.size () > 1);
358
+ stats.literalsreused += num_assigned - control[1].trail;
359
+ }
360
+ }
361
+ init_search_limits ();
362
+ init_report_limits ();
363
+
364
+ int res = already_solved (); // root-level propagation is done here
365
+
366
+ int last_assumption_level = assumptions.size ();
367
+ if (constraint.size ())
368
+ last_assumption_level++;
369
+
370
+ if (!res) {
371
+ restore_clauses ();
372
+ while (!res) {
373
+ if (unsat)
374
+ res = 20;
375
+ else if (unsat_constraint)
376
+ res = 20;
377
+ else if (!propagate ()) {
378
+ // let analyze run to get failed assumptions
379
+ analyze ();
380
+ } else if (!external_propagate () || unsat) { // external propagation
381
+ if (unsat)
382
+ continue;
383
+ else
384
+ analyze ();
385
+ } else if (satisfied ()) { // found model
386
+ if (!external_check_solution () || unsat) {
387
+ if (unsat)
388
+ continue;
389
+ else
390
+ analyze ();
391
+ } else if (satisfied ())
392
+ res = 10;
393
+ } else if (search_limits_hit ())
394
+ break; // decision or conflict limit
395
+ else if (terminated_asynchronously ()) // externally terminated
396
+ break;
397
+ else {
398
+ if (level >= last_assumption_level)
399
+ break;
400
+ res = decide ();
401
+ }
402
+ }
403
+ }
404
+
405
+ if (unsat || unsat_constraint)
406
+ res = 20;
407
+
408
+ if (!res && satisfied ())
409
+ res = 10;
410
+
411
+ finalize (res);
412
+ reset_solving ();
413
+ report_solving (res);
414
+
415
+ return res;
416
+ }
417
+
418
+ void Internal::implied (std::vector<int> &entrailed) {
419
+ int last_assumption_level = assumptions.size ();
420
+ if (constraint.size ())
421
+ last_assumption_level++;
422
+
423
+ size_t trail_limit = trail.size ();
424
+ if (level > last_assumption_level)
425
+ trail_limit = control[last_assumption_level + 1].trail;
426
+
427
+ for (size_t i = 0; i < trail_limit; i++)
428
+ entrailed.push_back (trail[i]);
429
+ }
430
+
431
+ /*------------------------------------------------------------------------*/
432
+
433
+ // Most of the limits are only initialized in the first 'solve' call and
434
+ // increased as in a stand-alone non-incremental SAT call except for those
435
+ // explicitly marked as being reset below.
436
+
437
+ void Internal::init_report_limits () {
438
+ reported = false;
439
+ lim.report = 0;
440
+ lim.recompute_tier = 5000;
441
+ }
442
+
443
+ void Internal::init_preprocessing_limits () {
444
+
445
+ const bool incremental = lim.initialized;
446
+ if (incremental)
447
+ LOG ("reinitializing preprocessing limits incrementally");
448
+ else
449
+ LOG ("initializing preprocessing limits and increments");
450
+
451
+ const char *mode = 0;
452
+
453
+ /*----------------------------------------------------------------------*/
454
+
455
+ if (incremental)
456
+ mode = "keeping";
457
+ else {
458
+ last.elim.marked = -1;
459
+ lim.elim = stats.conflicts + scale (opts.elimint);
460
+ mode = "initial";
461
+ }
462
+ (void) mode;
463
+ LOG ("%s elim limit %" PRId64 " after %" PRId64 " conflicts", mode,
464
+ lim.elim, lim.elim - stats.conflicts);
465
+
466
+ // Initialize and reset elimination bounds in any case.
467
+
468
+ lim.elimbound = opts.elimboundmin;
469
+ LOG ("elimination bound %" PRId64 "", lim.elimbound);
470
+
471
+ /*----------------------------------------------------------------------*/
472
+
473
+ if (!incremental) {
474
+
475
+ last.ternary.marked = -1; // TODO this should not be necessary...
476
+
477
+ lim.compact = stats.conflicts + opts.compactint;
478
+ LOG ("initial compact limit %" PRId64 " increment %" PRId64 "",
479
+ lim.compact, lim.compact - stats.conflicts);
480
+ }
481
+
482
+ /*----------------------------------------------------------------------*/
483
+
484
+ if (incremental)
485
+ mode = "keeping";
486
+ else {
487
+ double delta = log10 (stats.added.irredundant + 10);
488
+ delta = delta * delta;
489
+ lim.inprobe = stats.conflicts + opts.inprobeint * delta;
490
+ mode = "initial";
491
+ }
492
+ (void) mode;
493
+ LOG ("%s probe limit %" PRId64 " after %" PRId64 " conflicts", mode,
494
+ lim.inprobe, lim.inprobe - stats.conflicts);
495
+
496
+ /*----------------------------------------------------------------------*/
497
+
498
+ if (incremental)
499
+ mode = "keeping";
500
+ else {
501
+ lim.condition = stats.conflicts + opts.conditionint;
502
+ mode = "initial";
503
+ }
504
+ LOG ("%s condition limit %" PRId64 " increment %" PRId64, mode,
505
+ lim.condition, lim.condition - stats.conflicts);
506
+
507
+ /*----------------------------------------------------------------------*/
508
+
509
+ // Initial preprocessing rounds.
510
+
511
+ if (inc.preprocessing <= 0) {
512
+ lim.preprocessing = 0;
513
+ LOG ("no preprocessing");
514
+ } else {
515
+ lim.preprocessing = inc.preprocessing;
516
+ LOG ("limiting to %" PRId64 " preprocessing rounds", lim.preprocessing);
517
+ }
518
+ }
519
+
520
+ void Internal::init_search_limits () {
521
+
522
+ const bool incremental = lim.initialized;
523
+ if (incremental)
524
+ LOG ("reinitializing search limits incrementally");
525
+ else
526
+ LOG ("initializing search limits and increments");
527
+
528
+ const char *mode = 0;
529
+
530
+ /*----------------------------------------------------------------------*/
531
+
532
+ if (incremental)
533
+ mode = "keeping";
534
+ else {
535
+ last.reduce.conflicts = -1;
536
+ lim.reduce = stats.conflicts + opts.reduceinit;
537
+ mode = "initial";
538
+ }
539
+ (void) mode;
540
+ LOG ("%s reduce limit %" PRId64 " after %" PRId64 " conflicts", mode,
541
+ lim.reduce, lim.reduce - stats.conflicts);
542
+
543
+ /*----------------------------------------------------------------------*/
544
+
545
+ if (incremental)
546
+ mode = "keeping";
547
+ else {
548
+ lim.flush = opts.flushint;
549
+ inc.flush = opts.flushint;
550
+ mode = "initial";
551
+ }
552
+ (void) mode;
553
+ LOG ("%s flush limit %" PRId64 " interval %" PRId64 "", mode, lim.flush,
554
+ inc.flush);
555
+
556
+ /*----------------------------------------------------------------------*/
557
+
558
+ // Initialize or reset 'rephase' limits in any case.
559
+
560
+ lim.rephase = stats.conflicts + opts.rephaseint;
561
+ lim.rephased[0] = lim.rephased[1] = 0;
562
+ last.stabilize.rephased = 0;
563
+ LOG ("new rephase limit %" PRId64 " after %" PRId64 " conflicts",
564
+ lim.rephase, lim.rephase - stats.conflicts);
565
+
566
+ /*----------------------------------------------------------------------*/
567
+
568
+ // Initialize or reset 'restart' limits in any case.
569
+
570
+ lim.restart = stats.conflicts + opts.restartint;
571
+ LOG ("new restart limit %" PRId64 " increment %" PRId64 "", lim.restart,
572
+ lim.restart - stats.conflicts);
573
+
574
+ /*----------------------------------------------------------------------*/
575
+
576
+ if (!incremental) {
577
+ stable = opts.stabilize && opts.stabilizeonly;
578
+ if (stable)
579
+ LOG ("starting in always forced stable phase");
580
+ else
581
+ LOG ("starting in default non-stable phase");
582
+ init_averages ();
583
+ } else if (opts.stabilize && opts.stabilizeonly) {
584
+ LOG ("keeping always forced stable phase");
585
+ assert (stable);
586
+ } else if (stable) {
587
+ LOG ("switching back to default non-stable phase");
588
+ stable = false;
589
+ swap_averages ();
590
+ } else
591
+ LOG ("keeping non-stable phase");
592
+
593
+ inc.stabilize = 0;
594
+ last.stabilize.conflicts = stats.conflicts;
595
+ lim.stabilize = stats.conflicts + opts.stabilizeinit;
596
+ last.stabilize.ticks = stats.ticks.search[0];
597
+ stats.stabphases = 0;
598
+ LOG ("new ticks-based stabilize limit %" PRId64 " after %d conflicts",
599
+ lim.stabilize, (int) opts.stabilizeinit);
600
+
601
+ if (opts.stabilize && opts.reluctant && opts.reluctantint) {
602
+ LOG ("new restart reluctant doubling sequence period %d",
603
+ opts.reluctant);
604
+ reluctant.enable (opts.reluctantint, opts.reluctantmax);
605
+ } else
606
+ reluctant.disable ();
607
+
608
+ /*----------------------------------------------------------------------*/
609
+
610
+ // Conflict and decision limits.
611
+
612
+ if (inc.conflicts < 0) {
613
+ lim.conflicts = -1;
614
+ LOG ("no limit on conflicts");
615
+ } else {
616
+ lim.conflicts = stats.conflicts + inc.conflicts;
617
+ LOG ("conflict limit after %" PRId64 " conflicts at %" PRId64
618
+ " conflicts",
619
+ inc.conflicts, lim.conflicts);
620
+ }
621
+
622
+ if (inc.decisions < 0) {
623
+ lim.decisions = -1;
624
+ LOG ("no limit on decisions");
625
+ } else {
626
+ lim.decisions = stats.decisions + inc.decisions;
627
+ LOG ("decision limit after %" PRId64 " decisions at %" PRId64
628
+ " decisions",
629
+ inc.decisions, lim.decisions);
630
+ }
631
+
632
+ if (inc.ticks < 0) {
633
+ lim.ticks = -1;
634
+ LOG ("no limit on ticks");
635
+ } else {
636
+ lim.ticks = stats.ticks.search[0] + stats.ticks.search[1] + inc.ticks;
637
+ LOG ("ticks limit after %" PRId64 " ticks at %" PRId64 " ticks",
638
+ inc.ticks, lim.ticks);
639
+ }
640
+
641
+ /*----------------------------------------------------------------------*/
642
+
643
+ // Initial preprocessing rounds.
644
+
645
+ if (inc.localsearch <= 0) {
646
+ lim.localsearch = 0;
647
+ LOG ("no local search");
648
+ } else {
649
+ lim.localsearch = inc.localsearch;
650
+ LOG ("limiting to %" PRId64 " local search rounds", lim.localsearch);
651
+ }
652
+
653
+ /*----------------------------------------------------------------------*/
654
+ // tier 1 and tier 2 limits
655
+ if (incremental && opts.recomputetier) {
656
+ for (auto m : {true, false})
657
+ for (auto &u : stats.used[m])
658
+ u = 0;
659
+ stats.bump_used = {0, 0};
660
+ for (auto u : {true, false}) {
661
+ tier1[u] = max (tier1[u], opts.tier1minglue ? opts.tier1minglue : 2);
662
+ tier2[u] = max (tier2[u], opts.tier2minglue ? opts.tier2minglue : 6);
663
+ }
664
+ stats.tierecomputed = 0;
665
+ }
666
+
667
+ /*----------------------------------------------------------------------*/
668
+ // clause decaying
669
+ if (incremental)
670
+ last.incremental_decay.last_id = 0;
671
+ else {
672
+ lim.incremental_decay = opts.incdecayint;
673
+ }
674
+
675
+ /*----------------------------------------------------------------------*/
676
+
677
+ if (incremental)
678
+ mode = "keeping";
679
+ else {
680
+ lim.random_decision = stats.conflicts + opts.randecinit;
681
+ mode = "initial";
682
+ }
683
+ (void) mode;
684
+ LOG ("%s randomize decision limit %" PRId64 " after %" PRId64
685
+ " conflicts",
686
+ mode, lim.random_decision, lim.random_decision - stats.conflicts);
687
+
688
+ /*----------------------------------------------------------------------*/
689
+
690
+ lim.initialized = true;
691
+ }
692
+
693
+ /*------------------------------------------------------------------------*/
694
+
695
+ bool Internal::preprocess_round (int round) {
696
+ (void) round;
697
+ if (unsat)
698
+ return false;
699
+ if (!max_var)
700
+ return false;
701
+ START (preprocess);
702
+ struct {
703
+ int64_t vars, clauses;
704
+ } before, after;
705
+ before.vars = active ();
706
+ before.clauses = stats.current.irredundant;
707
+ stats.preprocessings++;
708
+ assert (!preprocessing);
709
+ preprocessing = true;
710
+ PHASE ("preprocessing", stats.preprocessings,
711
+ "starting round %d with %" PRId64 " variables and %" PRId64
712
+ " clauses",
713
+ round, before.vars, before.clauses);
714
+ int old_elimbound = lim.elimbound;
715
+ if (opts.inprobing)
716
+ inprobe (false);
717
+ if (opts.elim)
718
+ elim (false);
719
+ if (opts.condition)
720
+ condition (false);
721
+
722
+ after.vars = active ();
723
+ after.clauses = stats.current.irredundant;
724
+ assert (preprocessing);
725
+ preprocessing = false;
726
+ PHASE ("preprocessing", stats.preprocessings,
727
+ "finished round %d with %" PRId64 " variables and %" PRId64
728
+ " clauses",
729
+ round, after.vars, after.clauses);
730
+ STOP (preprocess);
731
+ report ('P');
732
+ if (unsat)
733
+ return false;
734
+ if (after.vars < before.vars)
735
+ return true;
736
+ if (old_elimbound < lim.elimbound)
737
+ return true;
738
+ return false;
739
+ }
740
+
741
+ // for now counts as one of the preprocessing rounds TODO: change this?
742
+ void Internal::preprocess_quickly (bool always) {
743
+ if (unsat)
744
+ return;
745
+ if (!max_var)
746
+ return;
747
+ if (!opts.preprocesslight)
748
+ return;
749
+ if (!always && stats.searches > 1)
750
+ return;
751
+ START (preprocess);
752
+ #ifndef QUIET
753
+ struct {
754
+ int64_t vars, clauses;
755
+ } before, after;
756
+ before.vars = active ();
757
+ before.clauses = stats.current.irredundant;
758
+ #endif
759
+ // stats.preprocessings++;
760
+ assert (!preprocessing);
761
+ preprocessing = true;
762
+ report ('(');
763
+ PHASE ("preprocessing", stats.preprocessings,
764
+ "starting with %" PRId64 " variables and %" PRId64 " clauses",
765
+ before.vars, before.clauses);
766
+
767
+ if (extract_gates (true))
768
+ decompose ();
769
+ binary_clauses_backbone ();
770
+
771
+ if (sweep ())
772
+ decompose ();
773
+
774
+ if (opts.factor)
775
+ factor ();
776
+
777
+ if (opts.fastelim)
778
+ elimfast ();
779
+ // if (opts.condition)
780
+ // condition (false);
781
+ #ifndef QUIET
782
+ after.vars = active ();
783
+ after.clauses = stats.current.irredundant;
784
+ #endif
785
+ assert (preprocessing);
786
+ preprocessing = false;
787
+ PHASE ("preprocessing", stats.preprocessings,
788
+ "finished with %" PRId64 " variables and %" PRId64 " clauses",
789
+ after.vars, after.clauses);
790
+ STOP (preprocess);
791
+ report ('P');
792
+ }
793
+
794
+ int Internal::preprocess (bool always) {
795
+ int res = 0;
796
+ if (!level && !unsat && opts.luckyearly)
797
+ res = lucky_phases ();
798
+ if (res)
799
+ return res;
800
+
801
+ if (opts.deduplicateallinit && !stats.deduplicatedinitrounds)
802
+ deduplicate_all_clauses ();
803
+
804
+ preprocess_quickly (always);
805
+ for (int i = 0; i < lim.preprocessing; i++)
806
+ if (!preprocess_round (i))
807
+ break;
808
+ report (')');
809
+ if (unsat)
810
+ return 20;
811
+ return 0;
812
+ }
813
+
814
+ /*------------------------------------------------------------------------*/
815
+
816
+ int Internal::try_to_satisfy_formula_by_saved_phases () {
817
+ LOG ("satisfying formula by saved phases");
818
+ assert (!level);
819
+ assert (!force_saved_phase);
820
+ assert (propagated == trail.size ());
821
+ force_saved_phase = true;
822
+ if (external_prop) {
823
+ assert (!level);
824
+ LOG ("external notifications are turned off during preprocessing.");
825
+ private_steps = true;
826
+ }
827
+ int res = 0;
828
+ while (!res) {
829
+ if (satisfied ()) {
830
+ LOG ("formula indeed satisfied by saved phases");
831
+ res = 10;
832
+ } else if (decide ()) {
833
+ LOG ("inconsistent assumptions with redundant clauses and phases");
834
+ res = 20;
835
+ } else if (!propagate ()) {
836
+ LOG ("saved phases do not satisfy redundant clauses");
837
+ assert (level > 0);
838
+ backtrack ();
839
+ conflict = 0; // ignore conflict
840
+ assert (!res);
841
+ break;
842
+ }
843
+ }
844
+ assert (force_saved_phase);
845
+ force_saved_phase = false;
846
+ if (external_prop) {
847
+ private_steps = false;
848
+ LOG ("external notifications are turned back on.");
849
+ if (!level)
850
+ notify_assignments (); // In case fixed assignments were found.
851
+ else {
852
+ renotify_trail_after_local_search ();
853
+ }
854
+ }
855
+ return res;
856
+ }
857
+
858
+ /*------------------------------------------------------------------------*/
859
+
860
+ void Internal::produce_failed_assumptions () {
861
+ LOG ("producing failed assumptions");
862
+ assert (!level);
863
+ assert (!assumptions.empty ());
864
+ while (!unsat) {
865
+ assert (!satisfied ());
866
+ notify_assignments ();
867
+ if (decide ())
868
+ break;
869
+ while (!unsat && !propagate ())
870
+ analyze ();
871
+ }
872
+ notify_assignments ();
873
+ if (unsat)
874
+ LOG ("formula is actually unsatisfiable unconditionally");
875
+ else
876
+ LOG ("assumptions indeed failing");
877
+ }
878
+
879
+ /*------------------------------------------------------------------------*/
880
+
881
+ int Internal::local_search_round (int round) {
882
+
883
+ assert (round > 0);
884
+
885
+ if (unsat)
886
+ return false;
887
+ if (!max_var)
888
+ return false;
889
+
890
+ START_OUTER_WALK ();
891
+ assert (!localsearching);
892
+ localsearching = true;
893
+
894
+ // Determine propagation limit quadratically scaled with rounds.
895
+ //
896
+ int64_t limit = opts.walkmineff;
897
+ limit *= round;
898
+ if (LONG_MAX / round > limit)
899
+ limit *= round;
900
+ else
901
+ limit = LONG_MAX;
902
+
903
+ int res;
904
+ if (opts.walkfullocc)
905
+ res = walk_full_occs_round (limit, true);
906
+ else
907
+ res = walk_round (limit, true);
908
+
909
+ assert (localsearching);
910
+ localsearching = false;
911
+ STOP_OUTER_WALK ();
912
+
913
+ report ('L');
914
+
915
+ return res;
916
+ }
917
+
918
+ int Internal::local_search () {
919
+
920
+ if (unsat)
921
+ return 0;
922
+ if (!max_var)
923
+ return 0;
924
+ if (!opts.walk)
925
+ return 0;
926
+ if (constraint.size ())
927
+ return 0;
928
+
929
+ int res = 0;
930
+
931
+ for (int i = 1; !res && i <= lim.localsearch; i++)
932
+ res = local_search_round (i);
933
+
934
+ if (res == 10) {
935
+ LOG ("local search determined formula to be satisfiable");
936
+ assert (!stats.walk.minimum);
937
+ res = try_to_satisfy_formula_by_saved_phases ();
938
+ } else if (res == 20) {
939
+ LOG ("local search determined assumptions to be inconsistent");
940
+ assert (!assumptions.empty ());
941
+ produce_failed_assumptions ();
942
+ }
943
+
944
+ return res;
945
+ }
946
+
947
+ /*------------------------------------------------------------------------*/
948
+
949
+ // if preprocess_only is false and opts.ilb is true we do not preprocess
950
+ // such that we do not have to backtrack to level 0.
951
+ //
952
+ int Internal::solve (bool preprocess_only) {
953
+ assert (clause.empty ());
954
+ stats.searches++;
955
+ START (solve);
956
+ if (proof)
957
+ proof->solve_query ();
958
+ if (opts.ilb) {
959
+ sort_and_reuse_assumptions ();
960
+ assert (opts.ilb || (size_t) level <= assumptions.size ());
961
+ stats.ilbtriggers++;
962
+ stats.ilbsuccess += (level > 0);
963
+ stats.levelsreused += level;
964
+ if (level) {
965
+ assert (control.size () > 1);
966
+ stats.literalsreused += num_assigned - control[1].trail;
967
+ }
968
+ if (external->propagator)
969
+ renotify_trail_after_ilb ();
970
+ }
971
+ if (preprocess_only)
972
+ LOG ("internal solving in preprocessing only mode");
973
+ else
974
+ LOG ("internal solving in full mode");
975
+ init_report_limits ();
976
+ int res = already_solved ();
977
+ if (!res && preprocess_only && level)
978
+ backtrack ();
979
+ if (!res)
980
+ res = restore_clauses ();
981
+ if (!res || (res == 10 && external_prop)) {
982
+ init_preprocessing_limits ();
983
+ if (!preprocess_only)
984
+ init_search_limits ();
985
+ }
986
+ if (!preprocess_only) {
987
+ if (!res && !level)
988
+ res = local_search ();
989
+ }
990
+ if (!res && !level)
991
+ res = preprocess (preprocess_only);
992
+ if (!preprocess_only) {
993
+ if (!res && !level && opts.luckylate)
994
+ res = lucky_phases ();
995
+ if (!res && !level)
996
+ res = local_search ();
997
+ if (!res)
998
+ decay_clauses_upon_incremental_clauses ();
999
+ if (!res || (res == 10 && external_prop)) {
1000
+ if (res == 10 && external_prop && level)
1001
+ backtrack ();
1002
+ res = cdcl_loop_with_inprocessing ();
1003
+ }
1004
+ }
1005
+ finalize (res);
1006
+ reset_solving ();
1007
+ report_solving (res);
1008
+ STOP (solve);
1009
+ return res;
1010
+ }
1011
+
1012
+ int Internal::already_solved () {
1013
+ int res = 0;
1014
+ if (unsat || unsat_constraint) {
1015
+ LOG ("already inconsistent");
1016
+ res = 20;
1017
+ } else {
1018
+ if (level && !opts.ilb)
1019
+ backtrack ();
1020
+ if (!level && !propagate ()) {
1021
+ LOG ("root level propagation produces conflict");
1022
+ learn_empty_clause ();
1023
+ res = 20;
1024
+ }
1025
+ if (max_var == 0 && res == 0)
1026
+ res = 10;
1027
+ }
1028
+ return res;
1029
+ }
1030
+ void Internal::report_solving (int res) {
1031
+ if (res == 10)
1032
+ report ('1');
1033
+ else if (res == 20)
1034
+ report ('0');
1035
+ else
1036
+ report ('?');
1037
+ }
1038
+
1039
+ void Internal::reset_solving () {
1040
+ if (termination_forced) {
1041
+
1042
+ // TODO this leads potentially to a data race if the external
1043
+ // user is calling 'terminate' twice within one 'solve' call.
1044
+ // A proper solution would be to guard / protect setting the
1045
+ // 'termination_forced' flag and only allow it during solving and
1046
+ // ignore it otherwise thus also the second time it is called during a
1047
+ // 'solve' call. We could move resetting it also the start of
1048
+ // 'solve'.
1049
+ //
1050
+ termination_forced = false;
1051
+
1052
+ LOG ("reset forced termination");
1053
+ }
1054
+ }
1055
+
1056
+ int Internal::restore_clauses () {
1057
+ int res = 0;
1058
+ if (opts.restoreall <= 1 && external->tainted.empty ()) {
1059
+ LOG ("no tainted literals and nothing to restore");
1060
+ report ('*');
1061
+ } else {
1062
+ report ('+');
1063
+ // remove_garbage_binaries ();
1064
+ external->restore_clauses ();
1065
+ internal->report ('r');
1066
+ if (!unsat && !level && !propagate ()) {
1067
+ LOG ("root level propagation after restore produces conflict");
1068
+ learn_empty_clause ();
1069
+ res = 20;
1070
+ }
1071
+ }
1072
+ return res;
1073
+ }
1074
+
1075
+ int Internal::lookahead () {
1076
+ assert (clause.empty ());
1077
+ START (lookahead);
1078
+ assert (!lookingahead);
1079
+ lookingahead = true;
1080
+ if (external_prop) {
1081
+ if (level) {
1082
+ // Combining lookahead with external propagator is limited
1083
+ // Note that lookahead_probing (); would also force backtrack anyway
1084
+ backtrack ();
1085
+ }
1086
+ LOG ("external notifications are turned off during preprocessing.");
1087
+ private_steps = true;
1088
+ }
1089
+ int tmp = already_solved ();
1090
+ if (!tmp)
1091
+ tmp = restore_clauses ();
1092
+ int res = 0;
1093
+ if (!tmp)
1094
+ res = lookahead_probing ();
1095
+ if (res == INT_MIN)
1096
+ res = 0;
1097
+ reset_solving ();
1098
+ report_solving (tmp);
1099
+ assert (lookingahead);
1100
+ lookingahead = false;
1101
+ STOP (lookahead);
1102
+ if (external_prop) {
1103
+ private_steps = false;
1104
+ LOG ("external notifications are turned back on.");
1105
+ notify_assignments (); // In case fixed assignments were found.
1106
+ }
1107
+ return res;
1108
+ }
1109
+
1110
+ /*------------------------------------------------------------------------*/
1111
+
1112
+ void Internal::finalize (int res) {
1113
+ if (!proof)
1114
+ return;
1115
+ LOG ("finalizing");
1116
+ // finalize external units
1117
+ if (frat) {
1118
+ for (const auto &evar : external->vars) {
1119
+ assert (evar > 0);
1120
+ const auto eidx = 2 * evar;
1121
+ int sign = 1;
1122
+ int64_t id = external->ext_units[eidx];
1123
+ if (!id) {
1124
+ sign = -1;
1125
+ id = external->ext_units[eidx + 1];
1126
+ }
1127
+ if (id) {
1128
+ proof->finalize_external_unit (id, evar * sign);
1129
+ }
1130
+ }
1131
+ // finalize internal units
1132
+ for (const auto &lit : lits) {
1133
+ const auto elit = externalize (lit);
1134
+ if (elit) {
1135
+ const unsigned eidx = (elit < 0) + 2u * (unsigned) abs (elit);
1136
+ const int64_t id = external->ext_units[eidx];
1137
+ if (id) {
1138
+ assert (unit_clauses (vlit (lit)) == id);
1139
+ continue;
1140
+ }
1141
+ }
1142
+ const int64_t id = unit_clauses (vlit (lit));
1143
+ if (!id)
1144
+ continue;
1145
+ proof->finalize_unit (id, lit);
1146
+ }
1147
+ // See the discussion in 'propagate' on why garbage binary clauses stick
1148
+ // around.
1149
+ for (const auto &c : clauses)
1150
+ if (!c->garbage || (c->size == 2 && !c->flushed))
1151
+ proof->finalize_clause (c);
1152
+
1153
+ // finalize conflict and proof
1154
+ if (conflict_id) {
1155
+ proof->finalize_clause (conflict_id, {});
1156
+ }
1157
+ }
1158
+ proof->report_status (res, conflict_id);
1159
+ if (res == 10)
1160
+ external->conclude_sat ();
1161
+ else if (res == 20)
1162
+ conclude_unsat ();
1163
+ else if (!res)
1164
+ external->conclude_unknown ();
1165
+ }
1166
+
1167
+ /*------------------------------------------------------------------------*/
1168
+
1169
+ void Internal::print_statistics () {
1170
+ stats.print (this);
1171
+ for (auto &st : stat_tracers)
1172
+ st->print_stats ();
1173
+ }
1174
+
1175
+ /*------------------------------------------------------------------------*/
1176
+
1177
+ // Only useful for debugging purposes.
1178
+
1179
+ void Internal::dump (Clause *c) {
1180
+ for (const auto &lit : *c)
1181
+ printf ("%d ", lit);
1182
+ printf ("0\n");
1183
+ }
1184
+
1185
+ void Internal::dump () {
1186
+ int64_t m = assumptions.size ();
1187
+ for (auto idx : vars)
1188
+ if (fixed (idx))
1189
+ m++;
1190
+ for (const auto &c : clauses)
1191
+ if (!c->garbage)
1192
+ m++;
1193
+ printf ("p cnf %d %" PRId64 "\n", max_var, m);
1194
+ for (auto idx : vars) {
1195
+ const int tmp = fixed (idx);
1196
+ if (tmp)
1197
+ printf ("%d 0\n", tmp < 0 ? -idx : idx);
1198
+ }
1199
+ for (const auto &c : clauses)
1200
+ if (!c->garbage)
1201
+ dump (c);
1202
+ for (const auto &lit : assumptions)
1203
+ printf ("%d 0\n", lit);
1204
+ fflush (stdout);
1205
+ }
1206
+
1207
+ /*------------------------------------------------------------------------*/
1208
+
1209
+ bool Internal::traverse_constraint (ClauseIterator &it) {
1210
+ if (constraint.empty () && !unsat_constraint)
1211
+ return true;
1212
+
1213
+ vector<int> eclause;
1214
+ if (unsat)
1215
+ return it.clause (eclause);
1216
+
1217
+ LOG (constraint, "traversing constraint");
1218
+ bool satisfied = false;
1219
+ for (auto ilit : constraint) {
1220
+ const int tmp = fixed (ilit);
1221
+ if (tmp > 0) {
1222
+ satisfied = true;
1223
+ break;
1224
+ }
1225
+ if (tmp < 0)
1226
+ continue;
1227
+ const int elit = externalize (ilit);
1228
+ eclause.push_back (elit);
1229
+ }
1230
+ if (!satisfied && !it.clause (eclause))
1231
+ return false;
1232
+
1233
+ return true;
1234
+ }
1235
+ /*------------------------------------------------------------------------*/
1236
+
1237
+ bool Internal::traverse_clauses (ClauseIterator &it) {
1238
+ vector<int> eclause;
1239
+ if (unsat)
1240
+ return it.clause (eclause);
1241
+ for (const auto &c : clauses) {
1242
+ if (c->garbage)
1243
+ continue;
1244
+ if (c->redundant)
1245
+ continue;
1246
+ bool satisfied = false;
1247
+ for (const auto &ilit : *c) {
1248
+ const int tmp = fixed (ilit);
1249
+ if (tmp > 0) {
1250
+ satisfied = true;
1251
+ break;
1252
+ }
1253
+ if (tmp < 0)
1254
+ continue;
1255
+ const int elit = externalize (ilit);
1256
+ eclause.push_back (elit);
1257
+ }
1258
+ if (!satisfied && !it.clause (eclause))
1259
+ return false;
1260
+ eclause.clear ();
1261
+ }
1262
+ return true;
1263
+ }
1264
+
1265
+ } // namespace CaDiCaL