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,1034 @@
1
+ #include "internal.hpp"
2
+ #include "util.hpp"
3
+
4
+ #include <cstdint>
5
+
6
+ namespace CaDiCaL {
7
+
8
+ External::External (Internal *i)
9
+ : internal (i), max_var (0), vsize (0), extended (false),
10
+ concluded (false), terminator (0), learner (0), fixed_listener (0),
11
+ propagator (0), solution (0), vars (max_var) {
12
+ assert (internal);
13
+ assert (!internal->external);
14
+ internal->external = this;
15
+ }
16
+
17
+ External::~External () {
18
+ if (solution)
19
+ delete[] solution;
20
+ }
21
+
22
+ void External::enlarge (int new_max_var) {
23
+
24
+ assert (!extended);
25
+
26
+ size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) new_max_var;
27
+ while (new_vsize <= (size_t) new_max_var)
28
+ new_vsize *= 2;
29
+ LOG ("enlarge external size from %zd to new size %zd", vsize, new_vsize);
30
+ vsize = new_vsize;
31
+ }
32
+
33
+ void External::init (int new_max_var, bool extension) {
34
+ assert (!extended);
35
+ if (new_max_var <= max_var)
36
+ return;
37
+ int new_vars = new_max_var - max_var;
38
+ int old_internal_max_var = internal->max_var;
39
+ int new_internal_max_var = old_internal_max_var + new_vars;
40
+ internal->init_vars (new_internal_max_var);
41
+ if ((size_t) new_max_var >= vsize)
42
+ enlarge (new_max_var);
43
+ LOG ("initialized %d external variables", new_vars);
44
+ reserve_at_least (ext_units, 2 * new_max_var + 2);
45
+ reserve_at_least (e2i, new_max_var + 1);
46
+ reserve_at_least (ervars, new_max_var + 1);
47
+ reserve_at_least (ext_flags, new_max_var + 1);
48
+ reserve_at_least (internal->i2e, new_max_var + 1);
49
+ if (!max_var) {
50
+ assert (e2i.empty ());
51
+ e2i.push_back (0);
52
+ ext_units.push_back (0);
53
+ ext_units.push_back (0);
54
+ ext_flags.push_back (0);
55
+ ervars.push_back (0);
56
+ assert (internal->i2e.empty ());
57
+ internal->i2e.push_back (0);
58
+ } else {
59
+ assert (e2i.size () == (size_t) max_var + 1);
60
+ assert (internal->i2e.size () == (size_t) old_internal_max_var + 1);
61
+ }
62
+ unsigned iidx = old_internal_max_var + 1, eidx;
63
+ for (eidx = max_var + 1u; eidx <= (unsigned) new_max_var;
64
+ eidx++, iidx++) {
65
+ LOG ("mapping external %u to internal %u", eidx, iidx);
66
+ assert (e2i.size () == eidx);
67
+ e2i.push_back (iidx);
68
+ ext_units.push_back (0);
69
+ ext_units.push_back (0);
70
+ ext_flags.push_back (0);
71
+ ervars.push_back (0);
72
+ internal->i2e.push_back (eidx);
73
+ assert (internal->i2e[iidx] == (int) eidx);
74
+ assert (e2i[eidx] == (int) iidx);
75
+ }
76
+ if (extension)
77
+ internal->stats.variables_extension += new_vars;
78
+ else
79
+ internal->stats.variables_original += new_vars;
80
+ if (internal->opts.checkfrozen)
81
+ if (new_max_var >= (int64_t) moltentab.size ())
82
+ moltentab.resize (1 + (size_t) new_max_var, false);
83
+ assert (iidx == (size_t) new_internal_max_var + 1);
84
+ assert (eidx == (size_t) new_max_var + 1);
85
+ assert (ext_units.size () == (size_t) new_max_var * 2 + 2);
86
+ max_var = new_max_var;
87
+ }
88
+
89
+ /*------------------------------------------------------------------------*/
90
+
91
+ void External::reset_assumptions () {
92
+ assumptions.clear ();
93
+ internal->reset_assumptions ();
94
+ }
95
+
96
+ void External::reset_concluded () {
97
+ concluded = false;
98
+ internal->reset_concluded ();
99
+ }
100
+
101
+ void External::reset_constraint () {
102
+ constraint.clear ();
103
+ internal->reset_constraint ();
104
+ }
105
+
106
+ void External::reset_extended () {
107
+ if (!extended)
108
+ return;
109
+ LOG ("reset extended");
110
+ extended = false;
111
+ }
112
+
113
+ void External::reset_limits () { internal->reset_limits (); }
114
+
115
+ /*------------------------------------------------------------------------*/
116
+
117
+ // when extension is true, elit should be a fresh variable and
118
+ // we can set a flag that it is an extension variable.
119
+ // This is then used in the API contracts, that extension variables are
120
+ // never part of the input
121
+ int External::internalize (int elit, bool extension) {
122
+ int ilit;
123
+ if (elit) {
124
+ assert (elit != INT_MIN);
125
+ const int eidx = abs (elit);
126
+ if (extension && eidx <= max_var)
127
+ FATAL ("can not add a definition for an already used variable %d",
128
+ eidx);
129
+ if (eidx > max_var) {
130
+ init (eidx, extension);
131
+ }
132
+ if (extension) {
133
+ assert (ervars.size () > (size_t) eidx);
134
+ ervars[eidx] = true;
135
+ }
136
+ ilit = e2i[eidx];
137
+ if (elit < 0)
138
+ ilit = -ilit;
139
+ if (!ilit) {
140
+ assert (internal->max_var < INT_MAX);
141
+ ilit = internal->max_var + 1u;
142
+ internal->init_vars (ilit);
143
+ e2i[eidx] = ilit;
144
+ LOG ("mapping external %d to internal %d", eidx, ilit);
145
+ e2i[eidx] = ilit;
146
+ internal->i2e.push_back (eidx);
147
+ assert (internal->i2e[ilit] == eidx);
148
+ assert (e2i[eidx] == ilit);
149
+ if (elit < 0)
150
+ ilit = -ilit;
151
+ }
152
+ if (internal->opts.checkfrozen) {
153
+ assert (eidx < (int64_t) moltentab.size ());
154
+ if (moltentab[eidx])
155
+ FATAL ("can not reuse molten literal %d", eidx);
156
+ }
157
+ Flags &f = internal->flags (ilit);
158
+ if (f.status == Flags::UNUSED)
159
+ internal->mark_active (ilit);
160
+ else if (f.status != Flags::ACTIVE && f.status != Flags::FIXED)
161
+ internal->reactivate (ilit);
162
+ if (!marked (tainted, elit) && marked (witness, -elit)) {
163
+ assert (!internal->opts.checkfrozen);
164
+ LOG ("marking tainted %d", elit);
165
+ mark (tainted, elit);
166
+ }
167
+ } else
168
+ ilit = 0;
169
+ return ilit;
170
+ }
171
+
172
+ void External::add (int elit) {
173
+ assert (elit != INT_MIN);
174
+
175
+ if (elit)
176
+ REQUIRE (is_valid_input ((int) elit),
177
+ "extension variable '%d' defined by the solver internally "
178
+ "(all user variables have to be declared explicitly "
179
+ "if 'factor' is enabled)", // TODO only reason?
180
+ (int) abs(elit));
181
+ reset_extended ();
182
+
183
+ bool forgettable = false;
184
+
185
+ if (internal->opts.check &&
186
+ (internal->opts.checkwitness || internal->opts.checkfailed)) {
187
+
188
+ forgettable =
189
+ internal->from_propagator && internal->ext_clause_forgettable;
190
+
191
+ // Forgettable clauses (coming from the external propagator) are not
192
+ // saved into the external 'original' stack. They are stored separately
193
+ // in external 'forgettable_original', from where they are deleted when
194
+ // the corresponding clause is deleted (actually deleted, not just
195
+ // marked as garbage).
196
+ if (!forgettable)
197
+ original.push_back (elit);
198
+ }
199
+
200
+ const int ilit = internalize (elit);
201
+ assert (!elit == !ilit);
202
+
203
+ // The external literals of the new clause must be saved for later
204
+ // when the proof is printed during add_original_lit (0)
205
+ if (elit && (internal->proof || forgettable)) {
206
+ eclause.push_back (elit);
207
+ if (internal->lrat) {
208
+ // actually find unit of -elit (flips elit < 0)
209
+ unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
210
+ assert ((size_t) eidx < ext_units.size ());
211
+ const int64_t id = ext_units[eidx];
212
+ bool added = ext_flags[abs (elit)];
213
+ if (id && !added) {
214
+ ext_flags[abs (elit)] = true;
215
+ internal->lrat_chain.push_back (id);
216
+ }
217
+ }
218
+ }
219
+
220
+ if (!elit && internal->proof && internal->lrat) {
221
+ for (const auto &elit : eclause) {
222
+ ext_flags[abs (elit)] = false;
223
+ }
224
+ }
225
+
226
+ if (elit)
227
+ LOG ("adding external %d as internal %d", elit, ilit);
228
+ internal->add_original_lit (ilit);
229
+
230
+ // Clean-up saved external literals once proof line is printed
231
+ if (!elit && (internal->proof || forgettable))
232
+ eclause.clear ();
233
+ }
234
+
235
+ void External::assume (int elit) {
236
+ assert (elit);
237
+ reset_extended ();
238
+ if (internal->proof)
239
+ internal->proof->add_assumption (elit);
240
+ assumptions.push_back (elit);
241
+ const int ilit = internalize (elit);
242
+ assert (ilit);
243
+ LOG ("assuming external %d as internal %d", elit, ilit);
244
+ internal->assume (ilit);
245
+ }
246
+
247
+ bool External::flip (int elit) {
248
+ assert (elit);
249
+ assert (elit != INT_MIN);
250
+ assert (!propagator);
251
+
252
+ int eidx = abs (elit);
253
+ if (eidx > max_var)
254
+ return false;
255
+ if (marked (witness, elit))
256
+ return false;
257
+ int ilit = e2i[eidx];
258
+ if (!ilit)
259
+ return false;
260
+ bool res = internal->flip (ilit);
261
+ if (res && extended)
262
+ reset_extended ();
263
+ return res;
264
+ }
265
+
266
+ bool External::flippable (int elit) {
267
+ assert (elit);
268
+ assert (elit != INT_MIN);
269
+ assert (!propagator);
270
+
271
+ int eidx = abs (elit);
272
+ if (eidx > max_var)
273
+ return false;
274
+ if (marked (witness, elit))
275
+ return false;
276
+ int ilit = e2i[eidx];
277
+ if (!ilit)
278
+ return false;
279
+ return internal->flippable (ilit);
280
+ }
281
+
282
+ bool External::failed (int elit) {
283
+ assert (elit);
284
+ assert (elit != INT_MIN);
285
+ int eidx = abs (elit);
286
+ if (eidx > max_var)
287
+ return 0;
288
+ int ilit = e2i[eidx];
289
+ if (!ilit)
290
+ return 0;
291
+ if (elit < 0)
292
+ ilit = -ilit;
293
+ return internal->failed (ilit);
294
+ }
295
+
296
+ void External::constrain (int elit) {
297
+ if (constraint.size () && !constraint.back ()) {
298
+ LOG (constraint, "replacing previous constraint");
299
+ reset_constraint ();
300
+ }
301
+ assert (elit != INT_MIN);
302
+ reset_extended ();
303
+ const int ilit = internalize (elit);
304
+ assert (!elit == !ilit);
305
+ if (elit)
306
+ LOG ("adding external %d as internal %d to constraint", elit, ilit);
307
+ else if (!elit && internal->proof) {
308
+ internal->proof->add_constraint (constraint);
309
+ }
310
+ constraint.push_back (elit);
311
+ internal->constrain (ilit);
312
+ }
313
+
314
+ bool External::failed_constraint () {
315
+ return internal->failed_constraint ();
316
+ }
317
+
318
+ void External::phase (int elit) {
319
+ assert (elit);
320
+ assert (elit != INT_MIN);
321
+ const int ilit = internalize (elit);
322
+ internal->phase (ilit);
323
+ }
324
+
325
+ void External::unphase (int elit) {
326
+ assert (elit);
327
+ assert (elit != INT_MIN);
328
+ int eidx = abs (elit);
329
+ if (eidx > max_var) {
330
+ UNUSED:
331
+ LOG ("resetting forced phase of unused external %d ignored", elit);
332
+ return;
333
+ }
334
+ int ilit = e2i[eidx];
335
+ if (!ilit)
336
+ goto UNUSED;
337
+ if (elit < 0)
338
+ ilit = -ilit;
339
+ internal->unphase (ilit);
340
+ }
341
+
342
+ /*------------------------------------------------------------------------*/
343
+
344
+ // External propagation related functions
345
+ //
346
+ // Note that when an already assigned variable is added as observed, the
347
+ // solver will backtrack to undo this assignment.
348
+ //
349
+ void External::add_observed_var (int elit) {
350
+ assert (propagator); // REQ is in Solver::add_observed_var
351
+
352
+ assert (elit);
353
+ assert (elit != INT_MIN);
354
+ reset_extended (); // tainting!
355
+
356
+ int eidx = abs (elit);
357
+
358
+ REQUIRE (eidx > max_var ||
359
+ (!marked (witness, elit) && !marked (witness, -elit)),
360
+ "Only clean variables are allowed to be observed.");
361
+ // if (eidx <= max_var &&
362
+ // (marked (witness, elit) || marked (witness, -elit))) {
363
+ // LOG ("Error, only clean variables are allowed to become observed.");
364
+ // assert (false);
365
+
366
+ // // TODO: here needs to come the taint and restore of the newly
367
+ // // observed variable. Restore_clauses must be called before continue.
368
+ // // LOG ("marking tainted %d", elit);
369
+ // // mark (tainted, elit);
370
+ // // mark (tainted, -elit);
371
+ // // restore_clauses ...
372
+ // }
373
+
374
+ if (eidx >= (int64_t) is_observed.size ())
375
+ is_observed.resize (1 + (size_t) eidx, false);
376
+
377
+ if (is_observed[eidx])
378
+ return;
379
+
380
+ LOG ("marking %d as externally watched", eidx);
381
+
382
+ // Will do the necessary internalization
383
+ freeze (elit);
384
+ is_observed[eidx] = true;
385
+
386
+ int ilit = internalize (elit);
387
+ // internal add-observed-var backtracks to a lower decision level to
388
+ // unassign the variable in case it was already assigned previously (but
389
+ // not on the current level)
390
+ internal->add_observed_var (ilit);
391
+
392
+ if (propagator->is_lazy)
393
+ return;
394
+
395
+ // In case this variable was already assigned (e.g. via unit clause) and
396
+ // got compacted to map to another (not observed) variable, it can not be
397
+ // unnasigned so it must be notified explicitly now. (-> Can lead to
398
+ // repeated fixed assignment notifications, in case it was unobserved and
399
+ // observed again. But a repeated notification is less error-prone than
400
+ // never notifying an assignment.)
401
+ const int tmp = fixed (elit);
402
+ if (!tmp)
403
+ return;
404
+ int unit = tmp < 0 ? -elit : elit;
405
+
406
+ LOG ("notify propagator about fixed assignment upon observe for %d",
407
+ unit);
408
+
409
+ // internal add-observed-var had to backtrack to root-level already
410
+ assert (!internal->level);
411
+
412
+ std::vector<int> assigned = {unit};
413
+ propagator->notify_assignment (assigned);
414
+ }
415
+
416
+ void External::remove_observed_var (int elit) {
417
+ assert (propagator); // REQ is in Solver::remove_observed_var
418
+
419
+ int eidx = abs (elit);
420
+
421
+ if (eidx > max_var) // Ignore call if variable does not exist
422
+ return;
423
+
424
+ // Ignore call if variable is not observed
425
+ if ((size_t) eidx >= is_observed.size ())
426
+ return;
427
+ if (is_observed[eidx]) {
428
+ // Follow opposite order of add_observed_var, first remove internal
429
+ // is_observed
430
+ int ilit = e2i[eidx]; // internalize (elit);
431
+ internal->remove_observed_var (ilit);
432
+
433
+ is_observed[eidx] = false;
434
+ melt (elit);
435
+ LOG ("unmarking %d as externally watched", eidx);
436
+ }
437
+ }
438
+
439
+ void External::reset_observed_vars () {
440
+ // Shouldn't be called if there is no connected propagator
441
+ assert (propagator); // REQ is in Solver::reset_observed_vars
442
+ reset_extended ();
443
+
444
+ internal->notified = 0;
445
+ LOG ("reset notified counter to 0");
446
+
447
+ if (!is_observed.size ())
448
+ return;
449
+
450
+ for (auto elit : vars) {
451
+ int eidx = abs (elit);
452
+ assert (eidx <= max_var);
453
+ if ((size_t) eidx >= is_observed.size ())
454
+ break;
455
+ if (is_observed[eidx]) {
456
+ int ilit = internalize (elit);
457
+ internal->remove_observed_var (ilit);
458
+ LOG ("unmarking %d as externally watched", eidx);
459
+ is_observed[eidx] = false;
460
+ melt (elit);
461
+ }
462
+ }
463
+ }
464
+
465
+ bool External::observed (int elit) {
466
+ assert (elit);
467
+ assert (elit != INT_MIN);
468
+ int eidx = abs (elit);
469
+ if (eidx > max_var)
470
+ return false;
471
+ if (eidx >= (int) is_observed.size ())
472
+ return false;
473
+
474
+ return is_observed[eidx];
475
+ }
476
+
477
+ bool External::is_witness (int elit) {
478
+ assert (elit);
479
+ assert (elit != INT_MIN);
480
+ int eidx = abs (elit);
481
+ if (eidx > max_var)
482
+ return false;
483
+ return (marked (witness, elit) || marked (witness, -elit));
484
+ }
485
+
486
+ bool External::is_decision (int elit) {
487
+ assert (elit);
488
+ assert (elit != INT_MIN);
489
+ int eidx = abs (elit);
490
+ if (eidx > max_var)
491
+ return false;
492
+
493
+ int ilit = internalize (elit);
494
+ return internal->is_decision (ilit);
495
+ }
496
+
497
+ void External::force_backtrack (int new_level) {
498
+ assert (propagator); // REQ is is in Solver::force_backtrack
499
+
500
+ LOG ("force backtrack to level %d", new_level);
501
+ internal->force_backtrack (new_level);
502
+ }
503
+
504
+ /*------------------------------------------------------------------------*/
505
+
506
+ int External::propagate_assumptions () {
507
+ int res = internal->propagate_assumptions ();
508
+ if (res == 10 && !extended)
509
+ extend (); // Call solution reconstruction
510
+ check_solve_result (res);
511
+ reset_limits ();
512
+ return res;
513
+ }
514
+
515
+ void External::implied (std::vector<int> &trailed) {
516
+ std::vector<int> ilit_implicants;
517
+ internal->implied (ilit_implicants);
518
+
519
+ // Those implied literals must be filtered out that are witnesses
520
+ // on the reconstruction stack -> no inplace externalize is possible.
521
+ // (Internal does not see these marks, so no earlier filter is
522
+ // possible.)
523
+
524
+ trailed.clear ();
525
+
526
+ for (const auto &ilit : ilit_implicants) {
527
+ assert (ilit);
528
+ const int elit = internal->externalize (ilit);
529
+ const int eidx = abs (elit);
530
+ const bool is_extension_var = ervars[eidx];
531
+ if (!marked (tainted, elit) && !is_extension_var) {
532
+ trailed.push_back (elit);
533
+ }
534
+ }
535
+ }
536
+
537
+ void External::conclude_unknown () {
538
+ if (!internal->proof || concluded)
539
+ return;
540
+ concluded = true;
541
+
542
+ vector<int> trail;
543
+ implied (trail);
544
+ internal->proof->conclude_unknown (trail);
545
+ }
546
+
547
+ /*------------------------------------------------------------------------*/
548
+
549
+ // Internal checker if 'solve' claims the formula to be satisfiable.
550
+
551
+ void External::check_satisfiable () {
552
+ LOG ("checking satisfiable");
553
+ if (!extended)
554
+ extend ();
555
+ if (internal->opts.checkwitness)
556
+ check_assignment (&External::ival);
557
+ if (internal->opts.checkassumptions && !assumptions.empty ())
558
+ check_assumptions_satisfied ();
559
+ if (internal->opts.checkconstraint && !constraint.empty ())
560
+ check_constraint_satisfied ();
561
+ }
562
+
563
+ // Internal checker if 'solve' claims formula to be unsatisfiable.
564
+
565
+ void External::check_unsatisfiable () {
566
+ LOG ("checking unsatisfiable");
567
+ if (!internal->opts.checkfailed)
568
+ return;
569
+ if (!assumptions.empty () || !constraint.empty ())
570
+ check_failing ();
571
+ }
572
+
573
+ // Check result of 'solve' to be correct.
574
+
575
+ void External::check_solve_result (int res) {
576
+ if (!internal->opts.check)
577
+ return;
578
+ if (res == 10)
579
+ check_satisfiable ();
580
+ if (res == 20)
581
+ check_unsatisfiable ();
582
+ }
583
+
584
+ // Prepare checking that completely molten literals are not used as argument
585
+ // of 'add' or 'assume', which is invalid under freezing semantics. This
586
+ // case would be caught by our 'restore' implementation so is only needed
587
+ // for checking the deprecated 'freeze' semantics.
588
+
589
+ void External::update_molten_literals () {
590
+ if (!internal->opts.checkfrozen)
591
+ return;
592
+ assert ((size_t) max_var + 1 == moltentab.size ());
593
+ #ifdef LOGGING
594
+ int registered = 0, molten = 0;
595
+ #endif
596
+ for (auto lit : vars) {
597
+ if (moltentab[lit]) {
598
+ LOG ("skipping already molten literal %d", lit);
599
+ #ifdef LOGGING
600
+ molten++;
601
+ #endif
602
+ } else if (frozen (lit))
603
+ LOG ("skipping currently frozen literal %d", lit);
604
+ else {
605
+ LOG ("new molten literal %d", lit);
606
+ moltentab[lit] = true;
607
+ #ifdef LOGGING
608
+ registered++;
609
+ molten++;
610
+ #endif
611
+ }
612
+ }
613
+ LOG ("registered %d new molten literals", registered);
614
+ LOG ("reached in total %d molten literals", molten);
615
+ }
616
+
617
+ int External::solve (bool preprocess_only) {
618
+ reset_extended ();
619
+ update_molten_literals ();
620
+ int res = internal->solve (preprocess_only);
621
+ check_solve_result (res);
622
+ reset_limits ();
623
+ return res;
624
+ }
625
+
626
+ void External::terminate () { internal->terminate (); }
627
+
628
+ int External::lookahead () {
629
+ reset_extended ();
630
+ update_molten_literals ();
631
+ int ilit = internal->lookahead ();
632
+ const int elit =
633
+ (ilit && ilit != INT_MIN) ? internal->externalize (ilit) : 0;
634
+ LOG ("lookahead internal %d external %d", ilit, elit);
635
+ return elit;
636
+ }
637
+
638
+ CaDiCaL::CubesWithStatus External::generate_cubes (int depth,
639
+ int min_depth = 0) {
640
+ reset_extended ();
641
+ update_molten_literals ();
642
+ reset_limits ();
643
+ auto cubes = internal->generate_cubes (depth, min_depth);
644
+ auto externalize = [this] (int ilit) {
645
+ const int elit = ilit ? internal->externalize (ilit) : 0;
646
+ MSG ("lookahead internal %d external %d", ilit, elit);
647
+ return elit;
648
+ };
649
+ auto externalize_map = [this, externalize] (std::vector<int> cube) {
650
+ (void) this;
651
+ MSG ("Cube : ");
652
+ std::for_each (begin (cube), end (cube), externalize);
653
+ };
654
+ std::for_each (begin (cubes.cubes), end (cubes.cubes), externalize_map);
655
+
656
+ return cubes;
657
+ }
658
+
659
+ /*------------------------------------------------------------------------*/
660
+
661
+ void External::freeze (int elit) {
662
+ reset_extended ();
663
+ int ilit = internalize (elit);
664
+ unsigned eidx = vidx (elit);
665
+ if (eidx >= frozentab.size ())
666
+ frozentab.resize (eidx + 1, 0);
667
+ unsigned &ref = frozentab[eidx];
668
+ if (ref < UINT_MAX) {
669
+ ref++;
670
+ LOG ("external variable %d frozen once and now frozen %u times", eidx,
671
+ ref);
672
+ } else
673
+ LOG ("external variable %d frozen but remains frozen forever", eidx);
674
+ internal->freeze (ilit);
675
+ }
676
+
677
+ void External::melt (int elit) {
678
+ reset_extended ();
679
+ int ilit = internalize (elit);
680
+ unsigned eidx = vidx (elit);
681
+ assert (eidx < frozentab.size ());
682
+ unsigned &ref = frozentab[eidx];
683
+ assert (ref > 0);
684
+ if (ref < UINT_MAX) {
685
+ if (!--ref) {
686
+ if (observed (elit)) {
687
+ ref++;
688
+ LOG ("external variable %d is observed, can not be completely "
689
+ "molten",
690
+ eidx);
691
+ } else
692
+ LOG ("external variable %d melted once and now completely melted",
693
+ eidx);
694
+ } else
695
+ LOG ("external variable %d melted once but remains frozen %u times",
696
+ eidx, ref);
697
+ } else
698
+ LOG ("external variable %d melted but remains frozen forever", eidx);
699
+ internal->melt (ilit);
700
+ }
701
+
702
+ /*------------------------------------------------------------------------*/
703
+
704
+ void External::check_assignment (int (External::*a) (int) const) {
705
+
706
+ // First check all assigned and consistent.
707
+ //
708
+ for (auto idx : vars) {
709
+ if (!(this->*a) (idx))
710
+ FATAL ("unassigned variable: %d", idx);
711
+ int value_idx = (this->*a) (idx);
712
+ int value_neg_idx = (this->*a) (-idx);
713
+ if (value_idx == idx)
714
+ assert (value_neg_idx == idx);
715
+ else {
716
+ assert (value_idx == -idx);
717
+ assert (value_neg_idx == -idx);
718
+ }
719
+ if (value_idx != value_neg_idx)
720
+ FATAL ("inconsistently assigned literals %d and %d", idx, -idx);
721
+ }
722
+
723
+ // Then check that all (saved) original clauses are satisfied.
724
+ //
725
+ bool satisfied = false;
726
+ const auto end = original.end ();
727
+ auto start = original.begin (), i = start;
728
+ #ifndef QUIET
729
+ int64_t count = 0;
730
+ #endif
731
+ for (; i != end; i++) {
732
+ int lit = *i;
733
+ if (!lit) {
734
+ if (!satisfied) {
735
+ fatal_message_start ();
736
+ fputs ("unsatisfied clause:\n", stderr);
737
+ for (auto j = start; j != i; j++)
738
+ fprintf (stderr, "%d ", *j);
739
+ fputc ('0', stderr);
740
+ fatal_message_end ();
741
+ }
742
+ satisfied = false;
743
+ start = i + 1;
744
+ #ifndef QUIET
745
+ count++;
746
+ #endif
747
+ } else if (!satisfied && (this->*a) (lit) == lit)
748
+ satisfied = true;
749
+ }
750
+
751
+ bool presence_flag;
752
+ // Check those forgettable external clauses that are still present, but
753
+ // only if the external propagator is still connected (otherwise solution
754
+ // reconstruction is allowed to touch the previously observed variables so
755
+ // there is no guarantee that the final model will satisfy these clauses.)
756
+ for (const auto &forgettables : forgettable_original) {
757
+ if (!propagator)
758
+ break;
759
+ presence_flag = true;
760
+ satisfied = false;
761
+ #ifndef QUIET
762
+ count++;
763
+ #endif
764
+ std::vector<int> literals;
765
+ for (const auto lit : forgettables.second) {
766
+ if (presence_flag) {
767
+ // First integer is a Boolean flag, not a literal
768
+ if (!lit) {
769
+ // Deleted clauses can be ignored, they count as satisfied
770
+ satisfied = true;
771
+ break;
772
+ }
773
+ presence_flag = false;
774
+ continue;
775
+ }
776
+
777
+ if ((this->*a) (lit) == lit) {
778
+ satisfied = true;
779
+ break;
780
+ }
781
+ }
782
+
783
+ if (!satisfied) {
784
+ fatal_message_start ();
785
+ fputs ("unsatisfied external forgettable clause:\n", stderr);
786
+ for (size_t j = 1; j < forgettables.second.size (); j++)
787
+ fprintf (stderr, "%d ", forgettables.second[j]);
788
+ fputc ('0', stderr);
789
+ fatal_message_end ();
790
+ }
791
+ }
792
+ #ifndef QUIET
793
+ VERBOSE (1, "satisfying assignment checked on %" PRId64 " clauses",
794
+ count);
795
+ #endif
796
+ }
797
+
798
+ /*------------------------------------------------------------------------*/
799
+
800
+ void External::check_assumptions_satisfied () {
801
+ for (const auto &lit : assumptions) {
802
+ // Not 'signed char' !!!!
803
+ const int tmp = ival (lit);
804
+ if (tmp != lit)
805
+ FATAL ("assumption %d falsified", lit);
806
+ if (!tmp)
807
+ FATAL ("assumption %d unassigned", lit);
808
+ }
809
+ VERBOSE (1, "checked that %zd assumptions are satisfied",
810
+ assumptions.size ());
811
+ }
812
+
813
+ void External::check_constraint_satisfied () {
814
+ for (const auto lit : constraint) {
815
+ if (ival (lit) == lit) {
816
+ VERBOSE (1, "checked that constraint is satisfied");
817
+ return;
818
+ }
819
+ }
820
+ FATAL ("constraint not satisfied");
821
+ }
822
+
823
+ void External::check_failing () {
824
+ Solver *checker = new Solver ();
825
+ DeferDeletePtr<Solver> delete_checker (checker);
826
+ checker->prefix ("checker ");
827
+ #ifdef LOGGING
828
+ if (internal->opts.log)
829
+ checker->set ("log", true);
830
+ #endif
831
+ checker->set ("factorcheck", false);
832
+
833
+ for (const auto lit : assumptions) {
834
+ if (!failed (lit))
835
+ continue;
836
+ LOG ("checking failed literal %d in core", lit);
837
+ checker->add (lit);
838
+ checker->add (0);
839
+ }
840
+ if (failed_constraint ()) {
841
+ LOG (constraint, "checking failed constraint");
842
+ for (const auto lit : constraint)
843
+ checker->add (lit);
844
+ } else if (constraint.size ())
845
+ LOG (constraint, "constraint satisfied and ignored");
846
+
847
+ // Add original clauses as last step, failing () and failed_constraint ()
848
+ // might add more external clauses (due to lazy explanation)
849
+ for (const auto lit : original)
850
+ checker->add (lit);
851
+
852
+ // Add every forgettable external clauses
853
+ for (const auto &forgettables : forgettable_original) {
854
+ bool presence_flag = true;
855
+ for (const auto lit : forgettables.second) {
856
+ if (presence_flag) {
857
+ // First integer is a Boolean flag, not a literal, ignore it here
858
+ presence_flag = false;
859
+ continue;
860
+ }
861
+ checker->add (lit);
862
+ }
863
+ checker->add (0);
864
+ }
865
+
866
+ int res = checker->solve ();
867
+ if (res != 20)
868
+ FATAL ("failed assumptions do not form a core");
869
+ delete_checker.free ();
870
+ VERBOSE (1, "checked that %zd failing assumptions form a core",
871
+ assumptions.size ());
872
+ }
873
+
874
+ /*------------------------------------------------------------------------*/
875
+
876
+ // Traversal of unit clauses is implemented here.
877
+
878
+ // In principle we want to traverse the clauses of the simplified formula
879
+ // only, particularly eliminated variables should be completely removed.
880
+ // This poses the question what to do with unit clauses. Should they be
881
+ // considered part of the simplified formula or of the witness to construct
882
+ // solutions for the original formula? Ideally they should be considered
883
+ // to be part of the witness only, i.e., as they have been simplified away.
884
+
885
+ // Therefore we distinguish frozen and non-frozen units during clause
886
+ // traversal. Frozen units are treated as unit clauses while non-frozen
887
+ // units are treated as if they were already eliminated and put on the
888
+ // extension stack as witness clauses.
889
+
890
+ // Furthermore, eliminating units during 'compact' could be interpreted as
891
+ // variable elimination, i.e., just add the resolvents (remove falsified
892
+ // literals), then drop the clauses with the unit, and push the unit on the
893
+ // extension stack. This is of course only OK if the user did not freeze
894
+ // that variable (even implicitly during assumptions).
895
+
896
+ // Thanks go to Fahiem Bacchus for asking why there is a necessity to
897
+ // distinguish these two cases (frozen and non-frozen units). The answer is
898
+ // that it is not strictly necessary, and this distinction could be avoided
899
+ // by always treating units as remaining unit clauses, thus only using the
900
+ // first of the two following functions and dropping the 'if (!frozen (idx))
901
+ // continue;' check in it. This has however the down-side that those units
902
+ // are still in the simplified formula and only as units. I would not
903
+ // consider such a formula as really being 'simplified'. On the other hand
904
+ // if the user explicitly freezes a literal, then it should continue to be
905
+ // in the simplified formula during traversal. So also only using the
906
+ // second function is not ideal.
907
+
908
+ // There is however a catch where this solution breaks down (in the sense of
909
+ // producing less optimal results - that is keeping units in the formula
910
+ // which better would be witness clauses). The problem is with compact
911
+ // preprocessing which removes eliminated but also fixed internal variables.
912
+ // One internal unit (fixed) variable is kept and all the other external
913
+ // literals which became unit are mapped to that internal literal (negated
914
+ // or positively). Compact is called non-deterministically from the point
915
+ // of the user and thus there is no control on when this happens. If
916
+ // compact happens those external units are mapped to a single internal
917
+ // literal now and then all share the same 'frozen' counter. So if the
918
+ // user freezes one of them all in essence get frozen, which in turn then
919
+ // makes a difference in terms of traversing such a unit as unit clause or
920
+ // as unit witness.
921
+
922
+ bool External::traverse_all_frozen_units_as_clauses (ClauseIterator &it) {
923
+ if (internal->unsat)
924
+ return true;
925
+
926
+ vector<int> clause;
927
+
928
+ for (auto idx : vars) {
929
+ if (!frozen (idx))
930
+ continue;
931
+ const int tmp = fixed (idx);
932
+ if (!tmp)
933
+ continue;
934
+ int unit = tmp < 0 ? -idx : idx;
935
+ clause.push_back (unit);
936
+ if (!it.clause (clause))
937
+ return false;
938
+ clause.clear ();
939
+ }
940
+
941
+ return true;
942
+ }
943
+
944
+ bool External::traverse_all_non_frozen_units_as_witnesses (
945
+ WitnessIterator &it) {
946
+ if (internal->unsat)
947
+ return true;
948
+
949
+ vector<int> clause_and_witness;
950
+ for (auto idx : vars) {
951
+ if (frozen (idx))
952
+ continue;
953
+ const int tmp = fixed (idx);
954
+ if (!tmp)
955
+ continue;
956
+ int unit = tmp < 0 ? -idx : idx;
957
+ const int ilit = e2i[idx] * (tmp < 0 ? -1 : 1);
958
+ // heurstically add + max_var to the id to avoid reusing ids
959
+ const int64_t id = internal->lrat ? internal->unit_id (ilit) : 1;
960
+ assert (id);
961
+ clause_and_witness.push_back (unit);
962
+ if (!it.witness (clause_and_witness, clause_and_witness, id + max_var))
963
+ return false;
964
+ clause_and_witness.clear ();
965
+ }
966
+
967
+ return true;
968
+ }
969
+
970
+ /*------------------------------------------------------------------------*/
971
+
972
+ void External::copy_flags (External &other) const {
973
+ const vector<Flags> &this_ftab = internal->ftab;
974
+ vector<Flags> &other_ftab = other.internal->ftab;
975
+ const unsigned limit = min (max_var, other.max_var);
976
+ for (unsigned eidx = 1; eidx <= limit; eidx++) {
977
+ const int this_ilit = e2i[eidx];
978
+ if (!this_ilit)
979
+ continue;
980
+ const int other_ilit = other.e2i[eidx];
981
+ if (!other_ilit)
982
+ continue;
983
+ if (!internal->active (this_ilit))
984
+ continue;
985
+ if (!other.internal->active (other_ilit))
986
+ continue;
987
+ assert (this_ilit != INT_MIN);
988
+ assert (other_ilit != INT_MIN);
989
+ const Flags &this_flags = this_ftab[abs (this_ilit)];
990
+ Flags &other_flags = other_ftab[abs (other_ilit)];
991
+ this_flags.copy (other_flags);
992
+ }
993
+ }
994
+
995
+ /*------------------------------------------------------------------------*/
996
+
997
+ void External::export_learned_empty_clause () {
998
+ assert (learner);
999
+ if (learner->learning (0)) {
1000
+ LOG ("exporting learned empty clause");
1001
+ learner->learn (0);
1002
+ } else
1003
+ LOG ("not exporting learned empty clause");
1004
+ }
1005
+
1006
+ void External::export_learned_unit_clause (int ilit) {
1007
+ assert (learner);
1008
+ if (learner->learning (1)) {
1009
+ LOG ("exporting learned unit clause");
1010
+ const int elit = internal->externalize (ilit);
1011
+ assert (elit);
1012
+ learner->learn (elit);
1013
+ learner->learn (0);
1014
+ } else
1015
+ LOG ("not exporting learned unit clause");
1016
+ }
1017
+
1018
+ void External::export_learned_large_clause (const vector<int> &clause) {
1019
+ assert (learner);
1020
+ size_t size = clause.size ();
1021
+ assert (size <= (unsigned) INT_MAX);
1022
+ if (learner->learning ((int) size)) {
1023
+ LOG ("exporting learned clause of size %zu", size);
1024
+ for (auto ilit : clause) {
1025
+ const int elit = internal->externalize (ilit);
1026
+ assert (elit);
1027
+ learner->learn (elit);
1028
+ }
1029
+ learner->learn (0);
1030
+ } else
1031
+ LOG ("not exporting learned clause of size %zu", size);
1032
+ }
1033
+
1034
+ } // namespace CaDiCaL