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,757 @@
1
+ #ifndef _congruenc_hpp_INCLUDED
2
+ #define _congruenc_hpp_INCLUDED
3
+
4
+ #include <algorithm>
5
+ #include <array>
6
+ #include <cassert>
7
+ #include <cstddef>
8
+ #include <cstdint>
9
+ #include <queue>
10
+ #include <string>
11
+ #include <sys/types.h>
12
+ #include <unordered_set>
13
+ #include <vector>
14
+
15
+ #include "clause.hpp"
16
+ #include "inttypes.hpp"
17
+ #include "util.hpp"
18
+ #include "watch.hpp"
19
+
20
+ namespace CaDiCaL {
21
+
22
+ typedef int64_t LRAT_ID;
23
+
24
+ // This implements the algorithm algorithm from SAT 2024.
25
+ //
26
+ // The idea is to:
27
+ // 0. handle binary clauses
28
+ // 1. detect gates and merge gates with same inputs ('lazy')
29
+ // 2. eagerly replace the equivalent literals and merge gates with same
30
+ // inputs
31
+ // 3. forward subsume
32
+ //
33
+ // In step 0 the normalization is fully lazy but we do not care about a
34
+ // normal form. Therefore we actually eagerly merge literals.
35
+ //
36
+ // In step 2 there is a subtility: we only replace with the equivalence
37
+ // chain as far as we propagated so far. This is the eager part. For LRAT we
38
+ // produce the equivalence up to the point we have propagated, no the full
39
+ // chain. This is important for merging literals. To merge literals we use
40
+ // union-find but we only compress paths when rewriting the literal, not
41
+ // before. The compression was not considered important in Kissat, but we do
42
+ // it aggressively as a mirror of the equivalences we have generated.
43
+ //
44
+ // We have two structures for merging:
45
+ // - the lazy ones contains alls merges, with functions like
46
+ // find_representative
47
+ //
48
+ // - the eager version that gets the merges one by one, with functions
49
+ // like find_eager_representatives
50
+ //
51
+ // The two structures are nicely separated and we only working on one of
52
+ // them except for:
53
+ //
54
+ // 1. When propagating one equivalence, we first important the
55
+ // equivalence from the lazy to the eager version, producing the full
56
+ // chain.
57
+ //
58
+ // 2. When merging the literals, we merge the literals given by the lazy
59
+ // structure, then we merge their representative in the eager version,
60
+ // updating only the lazy structure. We do not update the eager version.
61
+ //
62
+ // An important point: We cannot use internal->lrat_chain and
63
+ // internal->clause because in most places we can interrupt the
64
+ // transformation to learn a new clause representing an equivalence.
65
+ // However, we can only have 2 layers so we use this->lrat_chain and
66
+ // internal->lrat_chain when we really produce the proof.
67
+ struct Internal;
68
+
69
+ #define LD_MAX_ARITY 26
70
+ #define MAX_ARITY ((1 << LD_MAX_ARITY) - 1)
71
+
72
+ enum class Gate_Type : int8_t { And_Gate, XOr_Gate, ITE_Gate };
73
+
74
+ // Wrapper when we are looking for implication in if-then-else gates
75
+ struct lit_implication {
76
+ int first;
77
+ int second;
78
+ Clause *clause;
79
+ lit_implication (int f, int s, Clause *_id)
80
+ : first (f), second (s), clause (_id) {}
81
+ lit_implication (int f, int s) : first (f), second (s), clause (0) {}
82
+ lit_implication () : first (0), second (0), clause (nullptr) {}
83
+ void swap () { std::swap (first, second); }
84
+ };
85
+
86
+ // Wrapper when we are looking for equivalence for if-then-else-gate. They
87
+ // are produced by merging implication
88
+ struct lit_equivalence {
89
+ int first;
90
+ int second;
91
+ Clause *first_clause;
92
+ Clause *second_clause;
93
+ void check_invariant () const {
94
+ assert (second_clause);
95
+ assert (first_clause);
96
+ assert (std::find (begin (*first_clause), end (*first_clause), first) !=
97
+ end (*first_clause));
98
+ assert (std::find (begin (*second_clause), end (*second_clause),
99
+ second) != end (*second_clause));
100
+ assert (std::find (begin (*first_clause), end (*first_clause),
101
+ -second) != end (*first_clause));
102
+ assert (std::find (begin (*second_clause), end (*second_clause),
103
+ -first) != end (*second_clause));
104
+ }
105
+ lit_equivalence (int f, Clause *f_id, int s, Clause *s_id)
106
+ : first (f), second (s), first_clause (f_id), second_clause (s_id) {}
107
+ lit_equivalence (int f, int s)
108
+ : first (f), second (s), first_clause (nullptr),
109
+ second_clause (nullptr) {}
110
+ lit_equivalence ()
111
+ : first (0), second (0), first_clause (nullptr),
112
+ second_clause (nullptr) {}
113
+ lit_equivalence swap () {
114
+ std::swap (first, second);
115
+ std::swap (first_clause, second_clause);
116
+ return *this;
117
+ }
118
+ lit_equivalence negate_both () {
119
+ first = -first;
120
+ second = -second;
121
+ std::swap (first_clause, second_clause);
122
+ return *this;
123
+ }
124
+ };
125
+
126
+ typedef std::vector<lit_implication> lit_implications;
127
+ typedef std::vector<lit_equivalence> lit_equivalences;
128
+
129
+ std::string string_of_gate (Gate_Type t);
130
+
131
+ struct LitClausePair {
132
+ int current_lit; // current literal from the gate
133
+ Clause *clause;
134
+ LitClausePair (int lit, Clause *cl) : current_lit (lit), clause (cl) {}
135
+ LitClausePair () : current_lit (0), clause (nullptr) {}
136
+ };
137
+ struct LitIdPair {
138
+ int lit; // current literal from the gate
139
+ LRAT_ID id;
140
+ LitIdPair (int l, LRAT_ID i) : lit (l), id (i) {}
141
+ LitIdPair () : lit (0), id (0) {}
142
+ };
143
+
144
+ /*------------------------------------------------------------------------*/
145
+
146
+ // Sorting the scheduled clauses is way faster if we compute and save the
147
+ // clause size in the schedule to avoid pointer access to clauses during
148
+ // sorting. This slightly increases the schedule size though.
149
+
150
+ struct ClauseSize {
151
+ size_t size;
152
+ Clause *clause;
153
+ ClauseSize (int s, Clause *c) : size (s), clause (c) {}
154
+ ClauseSize (Clause *c) : size (c->size), clause (c) {}
155
+ ClauseSize () {}
156
+ };
157
+
158
+ struct smaller_clause_size_rank {
159
+ typedef size_t Type;
160
+ Type operator() (const ClauseSize &a) { return a.size; }
161
+ };
162
+
163
+ /*------------------------------------------------------------------------*/
164
+ // There are many special cases for ITE gates and we have to keep track of
165
+ // them as it is a gate property (rewriting might not make it obvious
166
+ // anymore).
167
+ // a = (a ? t : e) results in no -t and no +e gate (a --> a = t == (-a v -a
168
+ // v t) & (-a v a v -t)) a = (-a ? t : e) results in no +t and no -e gate a
169
+ // = (c ? a : e) results in no t gate (none of them) a = (c ? t : a) results
170
+ // in no e gate (none of them)
171
+ //
172
+ // We also use it for AND gates:
173
+ // a = (a & b)
174
+ // false = (a & b)
175
+ //
176
+ // The latter version can only happen when converting ITE gates to AND
177
+ // gates.
178
+ //
179
+ // They have a peculiarity: being special can fix itself. To avoid
180
+ // one more special case, we rewrite the LHS in that case too to make sure
181
+ // it remains special.
182
+ //
183
+ enum Special_Gate {
184
+ NORMAL = 0,
185
+ NO_PLUS_THEN = (1 << 0),
186
+ NO_NEG_THEN = (1 << 1),
187
+ NO_THEN = NO_PLUS_THEN + NO_NEG_THEN,
188
+ NO_PLUS_ELSE = (1 << 2),
189
+ NO_NEG_ELSE = (1 << 3),
190
+ DEGENERATED_AND = (1 << 4), // a = (a & b)
191
+ DEGENERATED_AND_LHS_FALSE = (1 << 5), // false = (a & b)
192
+ NO_ELSE = NO_PLUS_ELSE + NO_NEG_ELSE,
193
+ COND_LHS = NO_NEG_THEN + NO_PLUS_ELSE,
194
+ UCOND_LHS = NO_PLUS_THEN + NO_NEG_ELSE,
195
+ };
196
+
197
+ std::string special_gate_str (int8_t f);
198
+
199
+ inline bool ite_flags_no_then_clauses (int8_t flag) {
200
+ return (flag & NO_THEN) == NO_THEN;
201
+ }
202
+
203
+ inline bool ite_flags_no_else_clauses (int8_t flag) {
204
+ return (flag & NO_ELSE) == NO_ELSE;
205
+ }
206
+
207
+ inline bool ite_flags_neg_cond_lhs (int8_t flag) {
208
+ return (flag & UCOND_LHS) == UCOND_LHS;
209
+ }
210
+
211
+ inline bool ite_flags_cond_lhs (int8_t flag) {
212
+ return (flag & COND_LHS) == COND_LHS;
213
+ }
214
+
215
+ // std::optional is C++17 sadly
216
+ struct my_dummy_optional {
217
+ LitClausePair content;
218
+ my_dummy_optional () : content (0, 0) {}
219
+ bool operator() () const { return content.current_lit; }
220
+ my_dummy_optional operator= (LitClausePair p) {
221
+ content = p;
222
+ return *this;
223
+ }
224
+ void reset () { content = LitClausePair (0, 0); }
225
+ };
226
+
227
+ /*------------------------------------------------------------------------*/
228
+
229
+ // The core structure of this algorithm: the gate. It is composed of a
230
+ // left-hand side and an array of right-hand side.
231
+ //
232
+ // There are a few tags to help remembering the status of the gate (like
233
+ // deleted)
234
+ //
235
+ // To keep track of the proof we use two extra arrays:
236
+ // - `neg_lhs_ids' contains the long clause for AND gates. Otherwise, it is
237
+ // empty. TODO: change to std::option as it contains at most one element
238
+ // - `pos_lhs_ids' contains all the remaining gates.
239
+ //
240
+ // We keep the reasons with an index. This index depends on the gates:
241
+
242
+ // - AND-Gates and ITE-Gates: the index is the literal from the RHS
243
+ //
244
+ // - XOR-Gates: if you order the clauses by the order of the literals,
245
+ // each literal is either positive (bit '1') or negative (bit '0'). This
246
+ // gives a number that we can use.
247
+ //
248
+ // TODO Florian: I do not think that you have to changed anything, look at
249
+ // the 'Look at this first' in the CPP file.
250
+ //
251
+ // Important for the proofs: the LHS is not updated.
252
+ //
253
+ // TODO: we currently use a vector for the rhs, but we could also use FMA
254
+ // and inline the structure to avoid any indirection.
255
+ //
256
+ // One warning for degenerated gate: it is a monotone property on the
257
+ // defining clauses, but not on the LHS/RHS as the LHS is not rewritten:
258
+ // take 4 = AND 3 4 (degenerated with only the clause -4 3) with a rewriting
259
+ // 4 -> 1 (unchanged clause) and later 1 -> 3 (unchanged clause) but you do
260
+ // not know anymore from the gate that it is degenerated
261
+ struct Gate {
262
+ #ifdef LOGGING
263
+ uint64_t id;
264
+ #endif
265
+ int lhs;
266
+ Gate_Type tag;
267
+ bool garbage : 1;
268
+ bool indexed : 1;
269
+ bool marked : 1;
270
+ bool shrunken : 1;
271
+ vector<LitClausePair> pos_lhs_ids;
272
+ my_dummy_optional neg_lhs_ids;
273
+ int8_t degenerated_gate = Special_Gate::NORMAL;
274
+ vector<int> rhs;
275
+
276
+ size_t arity () const { return rhs.size (); }
277
+
278
+ bool operator== (Gate const &lhs) {
279
+ return tag == lhs.tag && rhs == lhs.rhs;
280
+ }
281
+ };
282
+
283
+ typedef vector<Gate *> GOccs;
284
+
285
+ struct GateEqualTo {
286
+ bool operator() (const Gate *const lhs, const Gate *const rhs) const {
287
+ return lhs->rhs == rhs->rhs && lhs->tag == rhs->tag;
288
+ }
289
+ };
290
+
291
+ struct CompactBinary {
292
+ Clause *clause;
293
+ LRAT_ID id;
294
+ int lit1, lit2;
295
+ CompactBinary (Clause *c, LRAT_ID i, int l1, int l2)
296
+ : clause (c), id (i), lit1 (l1), lit2 (l2) {}
297
+ CompactBinary () : clause (nullptr), id (0), lit1 (0), lit2 (0) {}
298
+ };
299
+
300
+ struct Hash {
301
+ Hash (std::array<uint64_t, 16> &ncs) : nonces (ncs) {}
302
+ const std::array<uint64_t, 16> &nonces;
303
+ inline size_t operator() (const Gate *const g) const;
304
+ };
305
+
306
+ struct Rewrite {
307
+ int src, dst;
308
+ LRAT_ID id1;
309
+ LRAT_ID id2;
310
+
311
+ Rewrite (int _src, int _dst, LRAT_ID _id1, LRAT_ID _id2)
312
+ : src (_src), dst (_dst), id1 (_id1), id2 (_id2) {}
313
+ Rewrite () : src (0), dst (0), id1 (0), id2 (0) {}
314
+ };
315
+
316
+ struct Closure {
317
+
318
+ Closure (Internal *i);
319
+ ~Closure () { delete dummy_search_gate; }
320
+ Gate *dummy_search_gate = nullptr;
321
+
322
+ Internal *const internal;
323
+ vector<Clause *> extra_clauses;
324
+ vector<CompactBinary> binaries;
325
+ std::vector<std::pair<size_t, size_t>> offsetsize;
326
+ bool full_watching = false;
327
+ std::array<uint64_t, 16> nonces;
328
+ typedef unordered_set<Gate *, Hash, GateEqualTo> GatesTable;
329
+
330
+ vector<bool> scheduled;
331
+ vector<signed char> marks;
332
+ vector<LitClausePair> mu1_ids, mu2_ids,
333
+ mu4_ids; // remember the ids and the literal. 2 and 4 are
334
+ // only used for lrat proofs, but we need 1 to
335
+ // promote binary clauses to irredundant
336
+
337
+ vector<int> lits; // result of definitions
338
+ vector<int> rhs; // stack for storing RHS
339
+ vector<int> unsimplified; // stack for storing unsimplified version (XOR,
340
+ // ITEs) for DRAT proof
341
+ vector<int> chain; // store clauses to be able to delete them properly
342
+ vector<int> clause; // storing partial clauses
343
+ vector<uint64_t>
344
+ glargecounts; // count for large clauses to complement internal->noccs
345
+ vector<uint64_t> gnew_largecounts; // count for large clauses to
346
+ // complement internal->noccs
347
+ GatesTable table;
348
+ std::array<lit_implications, 2> condbin;
349
+ std::array<lit_equivalences, 2> condeq;
350
+
351
+ std::vector<Clause *> new_unwatched_binary_clauses;
352
+ // LRAT proofs
353
+ vector<int> resolvent_analyzed;
354
+ mutable vector<LRAT_ID> lrat_chain; // storing LRAT chain
355
+
356
+ #ifdef LOGGING
357
+ uint64_t fresh_id;
358
+ #endif
359
+
360
+ uint64_t &new_largecounts (int lit);
361
+ uint64_t &largecounts (int lit);
362
+
363
+ void unmark_all ();
364
+ vector<int> representant; // union-find
365
+ vector<int> eager_representant; // union-find
366
+ vector<LRAT_ID> representant_id; // lrat version of union-find
367
+ vector<LRAT_ID> eager_representant_id; // lrat version of union-find
368
+ int &representative (int lit);
369
+ int representative (int lit) const;
370
+ LRAT_ID &representative_id (int lit);
371
+ LRAT_ID representative_id (int lit) const;
372
+ int &eager_representative (int lit);
373
+ int eager_representative (int lit) const;
374
+ LRAT_ID &eager_representative_id (int lit);
375
+ LRAT_ID eager_representative_id (int lit) const;
376
+ std::vector<char> lazy_propagated_idx;
377
+ char &lazy_propagated (int lit);
378
+
379
+ int find_lrat_representative_with_marks (int lit);
380
+ // representative in the union-find structure in the lazy equivalences
381
+ int find_representative (int lit);
382
+ // representative in the union-find structure in the lazy equivalences.
383
+ // only useful if you do not care about proofs like during forward
384
+ // subsumption.
385
+ int find_representative_and_compress_no_proofs (int lit);
386
+ int find_representative_already_compressed (int lit);
387
+ // find the representative and produce the binary clause representing the
388
+ // normalization from the literal to the result.
389
+ int find_representative_and_compress (int, bool update_eager = true);
390
+ // find the lazy representative for the `lit' and `-lit'
391
+ void find_representative_and_compress_both (int);
392
+ // find the eager representative
393
+ int find_eager_representative (int);
394
+
395
+ // compreses the path from lit to the representative with a new clause if
396
+ // needed. Save internal->lrat_chain to avoid any issue.
397
+ int find_eager_representative_and_compress (int);
398
+ // Import the path from the literal and its negation to the representative
399
+ // in the lazy graph to the eager part, producing the binary clauses.
400
+ void import_lazy_and_find_eager_representative_and_compress_both (
401
+ int); // generates clauses for -lit and lit
402
+
403
+ // returns the ID of the LRAT clause for the normalization from the
404
+ // literal lit to its argument, assuming that the representative was
405
+ // already compressed.
406
+ LRAT_ID find_representative_lrat (int lit);
407
+ // returns the ID of the LRAT clause for the eager normalization from the
408
+ // literal lit to its argument assuming that the representative was
409
+ // already compressed.
410
+ LRAT_ID find_eager_representative_lrat (int lit);
411
+
412
+ // Writes the LRAT chain required for the eager normalization to
413
+ // `lrat_chain`.
414
+ void produce_eager_representative_lrat (int lit);
415
+ // Writes the LRAT chain required for the lazy normalization to
416
+ // `lrat_chain`.
417
+ void produce_representative_lrat (int lit);
418
+
419
+ // learns a binary clause if not unit
420
+ Clause *maybe_add_binary_clause (int a, int b);
421
+ // add binary clause
422
+ Clause *add_binary_clause (int a, int b);
423
+ // add tmp clause
424
+ Clause *add_tmp_binary_clause (int a, int b);
425
+ // add clause taking core of tmp or full
426
+ Clause *learn_binary_tmp_or_full_clause (int a, int b);
427
+
428
+ // promotes a clause from redundant to irredundant. We do this for all
429
+ // clauses involved in gates to make sure that we produce correct result.
430
+ void promote_clause (Clause *);
431
+
432
+ // Merge functions. We actually need different several versions for LRAT
433
+ // in order to simplify the proof production.
434
+ //
435
+ // When merging binary clauses, we can simply produce the LRAT chain by
436
+ // (1) using the two binary clauses and (2) the reason clause from the
437
+ // literals to the representatives.
438
+ //
439
+ // The same approach does not work for merging gates because the
440
+ // representative might be also a representative of another literal
441
+ // (because of eager rewriting), requiring to resolve more than once on
442
+ // the same literal. An example of this are the two gates 4=-2&7 and
443
+ // 6=-2&1, the rewriting 7=1 and the equivalence 4=1. The simple road of
444
+ // merging 6 and 4 (requires resolving away 1) + adding the rewrite 4 to 1
445
+ // (requires adding 1) does not work.
446
+ //
447
+ // Therefore, we actually go for the more regular road and produce two
448
+ // equivalence: the merge from the LHS, followed by the actual equivalence
449
+ // (by combining it with the rewrite). In DRAT this is less important
450
+ // because the checker finds a chain and is less restricted than our LRAT
451
+ // chain.
452
+ bool merge_literals_equivalence (int lit, int other, Clause *c1,
453
+ Clause *c2);
454
+ bool merge_literals (Gate *g, Gate *h, int lit, int other,
455
+ const std::vector<LRAT_ID> & = {},
456
+ const std::vector<LRAT_ID> & = {});
457
+ bool merge_literals (int lit, int other,
458
+ const std::vector<LRAT_ID> & = {},
459
+ const std::vector<LRAT_ID> & = {});
460
+ // factoring out the merge w.r.t. both cases above
461
+ bool really_merge_literals (int lit, int other, int repr_lit,
462
+ int repr_other,
463
+ const std::vector<LRAT_ID> & = {},
464
+ const std::vector<LRAT_ID> & = {});
465
+
466
+ // proof production
467
+ vector<LitClausePair> lrat_chain_and_gate;
468
+ void push_lrat_id (const Clause *const c, int lit);
469
+ void push_lrat_unit (int lit);
470
+
471
+ // pushes the clause with the reasons to rewrite clause
472
+ // unless:
473
+ // - the rewriting is not necessary (resolvent_marked == 1)
474
+ // - it is overwritten by one of the arguments
475
+ void push_id_and_rewriting_lrat_unit (Clause *c, Rewrite rewrite1,
476
+ std::vector<LRAT_ID> &chain,
477
+ bool = true,
478
+ Rewrite rewrite2 = Rewrite (),
479
+ int execept_lhs = 0,
480
+ int except_lhs2 = 0);
481
+ void push_id_and_rewriting_lrat_full (Clause *c, Rewrite rewrite1,
482
+ std::vector<LRAT_ID> &chain,
483
+ bool = true,
484
+ Rewrite rewrite2 = Rewrite (),
485
+ int execept_lhs = 0,
486
+ int except_lhs2 = 0);
487
+ // TODO: does nothing except pushing on the stack, remove!
488
+ void push_id_on_chain (std::vector<LRAT_ID> &chain, Clause *c);
489
+ // TODO: does nothing except pushing on the stack, remove!
490
+ void push_id_on_chain (std::vector<LRAT_ID> &chain,
491
+ const std::vector<LitClausePair> &c);
492
+ void push_id_on_chain (std::vector<LRAT_ID> &chain,
493
+ const my_dummy_optional &c);
494
+ // TODO: does nothing except pushing on the stack, remove!
495
+ void push_id_on_chain (std::vector<LRAT_ID> &chain, Rewrite rewrite, int);
496
+ void update_and_gate_build_lrat_chain (
497
+ Gate *g, Gate *h, std::vector<LRAT_ID> &extra_reasons_lit,
498
+ std::vector<LRAT_ID> &extra_reasons_ulit, bool remove_units = true);
499
+ void update_and_gate_unit_build_lrat_chain (
500
+ Gate *g, int src, LRAT_ID id1, LRAT_ID id2, int dst,
501
+ std::vector<LRAT_ID> &extra_reasons_lit,
502
+ std::vector<LRAT_ID> &extra_reasons_ulit);
503
+ // occs
504
+ vector<GOccs> gtab;
505
+ GOccs &goccs (int lit);
506
+ void connect_goccs (Gate *g, int lit);
507
+ vector<Gate *> garbage;
508
+ void mark_garbage (Gate *);
509
+ // remove the gate from the table
510
+ bool remove_gate (Gate *);
511
+ bool remove_gate (GatesTable::iterator git);
512
+ void index_gate (Gate *);
513
+
514
+ // second counter for size, complements noccs
515
+ uint64_t &largecount (int lit);
516
+
517
+ // simplification
518
+ bool skip_and_gate (Gate *g);
519
+ bool skip_xor_gate (Gate *g);
520
+ void update_and_gate (Gate *g, GatesTable::iterator, int src, int dst,
521
+ LRAT_ID id1, LRAT_ID id2, int falsified = 0,
522
+ int clashing = 0);
523
+ void update_xor_gate (Gate *g, GatesTable::iterator);
524
+ void shrink_and_gate (Gate *g, int falsified = 0, int clashing = 0);
525
+ bool simplify_gate (Gate *g);
526
+ void simplify_and_gate (Gate *g);
527
+ void simplify_ite_gate (Gate *g);
528
+ Clause *simplify_xor_clause (int lhs, Clause *);
529
+ void simplify_xor_gate (Gate *g);
530
+ bool simplify_gates (int lit);
531
+ void simplify_and_sort_xor_lrat_clauses (const vector<LitClausePair> &,
532
+ vector<LitClausePair> &, int,
533
+ int except2 = 0, bool flip = 0);
534
+ void simplify_unit_xor_lrat_clauses (const vector<LitClausePair> &, int);
535
+
536
+ // rewriting
537
+ bool rewriting_lhs (Gate *g, int dst);
538
+ bool rewrite_gates (int dst, int src, LRAT_ID id1, LRAT_ID id2);
539
+ bool rewrite_gate (Gate *g, int dst, int src, LRAT_ID id1, LRAT_ID id2);
540
+ void rewrite_xor_gate (Gate *g, int dst, int src);
541
+ void rewrite_and_gate (Gate *g, int dst, int src, LRAT_ID id1,
542
+ LRAT_ID id2);
543
+ void rewrite_ite_gate (Gate *g, int dst, int src);
544
+
545
+ size_t units; // next trail position to propagate
546
+ bool propagate_unit (int lit);
547
+ bool propagate_units ();
548
+ size_t propagate_units_and_equivalences ();
549
+ bool propagate_equivalence (int lit);
550
+
551
+ // gates
552
+ void init_closure ();
553
+ void reset_closure ();
554
+ void reset_extraction ();
555
+ void reset_and_gate_extraction ();
556
+ void extract_and_gates (Closure &);
557
+ void extract_gates ();
558
+ void extract_and_gates_with_base_clause (Clause *c);
559
+ void init_and_gate_extraction ();
560
+ Gate *find_first_and_gate (Clause *base_clause, int lhs);
561
+ Gate *find_remaining_and_gate (Clause *base_clause, int lhs);
562
+ void extract_and_gates ();
563
+
564
+ Gate *find_and_lits (vector<int> &rhs, Gate *except = nullptr);
565
+ Gate *
566
+ find_gate_lits (vector<int> &rhs,
567
+ Gate_Type typ, // rhs unchanged but swapped back and forth
568
+ Gate *except = nullptr);
569
+ Gate *find_xor_lits (vector<int> &rhs);
570
+ // not const to normalize negations, also fixes the order of the LRAT
571
+ Gate *find_ite_gate (Gate *, bool &);
572
+ Gate *find_xor_gate (Gate *);
573
+
574
+ void reset_xor_gate_extraction ();
575
+ void init_xor_gate_extraction (std::vector<Clause *> &candidates);
576
+ LRAT_ID check_and_add_to_proof_chain (vector<int> &clause);
577
+ void add_xor_matching_proof_chain (Gate *g, int lhs1,
578
+ const vector<LitClausePair> &,
579
+ int lhs2, vector<LRAT_ID> &,
580
+ vector<LRAT_ID> &);
581
+ void add_xor_shrinking_proof_chain (Gate *g, int src);
582
+ void extract_xor_gates ();
583
+ void extract_xor_gates_with_base_clause (Clause *c);
584
+ Clause *find_large_xor_side_clause (std::vector<int> &lits);
585
+
586
+ void merge_condeq (int cond, lit_equivalences &condeq,
587
+ lit_equivalences &not_condeq);
588
+ void find_conditional_equivalences (int lit, lit_implications &condbin,
589
+ lit_equivalences &condeq);
590
+ void copy_conditional_equivalences (int lit, lit_implications &condbin);
591
+ void check_ite_implied (int lhs, int cond, int then_lit, int else_lit);
592
+ void check_ite_gate_implied (Gate *g);
593
+ void check_and_gate_implied (Gate *g);
594
+ void check_ite_lrat_reasons (Gate *g);
595
+ void check_contained_module_rewriting (Clause *c, int lit, bool,
596
+ int except);
597
+ void delete_proof_chain ();
598
+
599
+ // ite gate extraction
600
+ void extract_ite_gates_of_literal (int);
601
+ void extract_ite_gates_of_variable (int idx);
602
+ void extract_condeq_pairs (int lit, lit_implications &condbin,
603
+ lit_equivalences &condeq);
604
+ void init_ite_gate_extraction (std::vector<ClauseSize> &candidates);
605
+ lit_implications::const_iterator find_lit_implication_second_literal (
606
+ int lit, lit_implications::const_iterator begin,
607
+ lit_implications::const_iterator end);
608
+ void search_condeq (int lit, int pos_lit,
609
+ lit_implications::const_iterator pos_begin,
610
+ lit_implications::const_iterator pos_end, int neg_lit,
611
+ lit_implications::const_iterator neg_begin,
612
+ lit_implications::const_iterator neg_end,
613
+ lit_equivalences &condeq);
614
+ void reset_ite_gate_extraction ();
615
+ void extract_ite_gates ();
616
+
617
+ void forward_subsume_matching_clauses ();
618
+
619
+ void extract_congruence ();
620
+
621
+ void add_ite_matching_proof_chain (Gate *g, Gate *h, int lhs1, int lhs2,
622
+ std::vector<LRAT_ID> &reasons1,
623
+ std::vector<LRAT_ID> &reasons2);
624
+ void add_ite_turned_and_binary_clauses (Gate *g);
625
+ Gate *new_and_gate (Clause *, int);
626
+ Gate *new_ite_gate (int lhs, int cond, int then_lit, int else_lit,
627
+ std::vector<LitClausePair> &&clauses);
628
+ Gate *new_xor_gate (const vector<LitClausePair> &, int);
629
+ // check
630
+ void check_xor_gate_implied (Gate const *const);
631
+ void check_ternary (int a, int b, int c);
632
+ void check_binary_implied (int a, int b);
633
+ void check_implied ();
634
+
635
+ // learn units. You can delay units if you want to learn several at once
636
+ // before propagation. Otherwise, propagate! If you need propagation even
637
+ // if nothing is set, use the second parameter.
638
+ //
639
+ // The function can also learn the empty clause if the unit is already
640
+ // set. Do not add the unit in the chain!
641
+ bool learn_congruence_unit (int unit, bool = false, bool = false);
642
+ bool fully_propagate ();
643
+ void learn_congruence_unit_falsifies_lrat_chain (Gate *g, int src,
644
+ int dst, int clashing,
645
+ int falsified, int unit);
646
+ void learn_congruence_unit_when_lhs_set (Gate *g, int src, LRAT_ID id1,
647
+ LRAT_ID id2, int dst);
648
+
649
+ void find_units ();
650
+ void find_equivalences ();
651
+ void subsume_clause (Clause *subsuming, Clause *subsumed);
652
+ bool find_subsuming_clause (Clause *c);
653
+ void produce_rewritten_clause_lrat_and_clean (vector<LitClausePair> &,
654
+ int execept_lhs = 0,
655
+ bool = true, bool = false);
656
+ void produce_rewritten_clause_lrat_and_clean (my_dummy_optional &,
657
+ int execept_lhs = 0,
658
+ bool = true);
659
+
660
+ // rewrite the clause using eager rewriting and rew1 and rew2, except for
661
+ // 2 literals Usage:
662
+ // - the except are used to ignore LHS of gates that have not and should
663
+ // not be rewritten.
664
+ // - TODO: except_lhs2 should never be used actually
665
+ // - the Rewrite are for additional rewrite to allow for lazy rewrites
666
+ // to be taken into account without being added to the eager rewriting
667
+ // (yet)
668
+ Clause *produce_rewritten_clause_lrat (Clause *c, int execept_lhs = 0,
669
+ bool remove_units = true,
670
+ bool = false);
671
+ void produce_rewritten_clause_lrat (vector<LitClausePair> &,
672
+ int execept_lhs = 0, bool = true);
673
+ void compute_rewritten_clause_lrat_simple (Clause *c, int except);
674
+ // variant where we update the indices after removing the tautologies and
675
+ // remove the tautological clauses
676
+ void produce_rewritten_clause_lrat_and_clean (
677
+ std::vector<LitClausePair> &litIds, int except_lhs,
678
+ size_t &old_position1, size_t &old_position2,
679
+ bool remove_units = true);
680
+ // binary extraction and ternary strengthening
681
+ void extract_binaries ();
682
+ bool find_binary (int, int) const;
683
+
684
+ Clause *new_tmp_clause (std::vector<int> &clause);
685
+ Clause *maybe_promote_tmp_binary_clause (Clause *);
686
+ void check_not_tmp_binary_clause (Clause *c);
687
+ Clause *new_clause ();
688
+ //
689
+ void sort_literals_by_var (vector<int> &rhs);
690
+ void sort_literals_by_var_except (vector<int> &rhs, int, int except2 = 0);
691
+
692
+ // schedule
693
+ queue<int> schedule;
694
+ void schedule_literal (int lit);
695
+ void add_clause_to_chain (std::vector<int>, LRAT_ID);
696
+ // proof. If delete_id is non-zero, then delete the clause instead of
697
+ // learning it
698
+ LRAT_ID simplify_and_add_to_proof_chain (vector<int> &unsimplified,
699
+ LRAT_ID delete_id = 0);
700
+
701
+ // we define our own wrapper as cadical has otherwise a non-compatible
702
+ // marking system
703
+ signed char &marked (int lit);
704
+ void set_mu1_reason (int lit, Clause *c);
705
+ void set_mu2_reason (int lit, Clause *c);
706
+ void set_mu4_reason (int lit, Clause *c);
707
+ LitClausePair marked_mu1 (int lit);
708
+ LitClausePair marked_mu2 (int lit);
709
+ LitClausePair marked_mu4 (int lit);
710
+
711
+ // XOR
712
+ uint32_t number_from_xor_reason_reversed (const std::vector<int> &rhs);
713
+ uint32_t number_from_xor_reason (const std::vector<int> &rhs, int,
714
+ int except2 = 0, bool flip = 0);
715
+ void gate_sort_lrat_reasons (std::vector<LitClausePair> &, int,
716
+ int except2 = 0, bool flip = 0);
717
+ void gate_sort_lrat_reasons (LitClausePair &, int, int except2 = 0,
718
+ bool flip = 0);
719
+
720
+ bool rewrite_ite_gate_to_and (Gate *g, int dst, int src, size_t c,
721
+ size_t d,
722
+ int cond_lit_to_learn_if_degenerated);
723
+ void produce_ite_merge_then_else_reasons (
724
+ Gate *g, int dst, int src, std::vector<LRAT_ID> &reasons_implication,
725
+ std::vector<LRAT_ID> &reasons_back);
726
+ void produce_ite_merge_lhs_then_else_reasons (
727
+ Gate *g, std::vector<LRAT_ID> &reasons_implication,
728
+ std::vector<LRAT_ID> &reasons_back,
729
+ std::vector<LRAT_ID> &reasons_unit, bool, bool &);
730
+ void produce_ite_merge_rhs_cond (Gate *g, int, int);
731
+ void rewrite_ite_gate_update_lrat_reasons (Gate *g, int src, int dst);
732
+ void simplify_ite_gate_produce_unit_lrat (Gate *g, int lit, size_t idx1,
733
+ size_t idx2);
734
+ void merge_and_gate_lrat_produce_lrat (
735
+ Gate *g, Gate *h, std::vector<LRAT_ID> &reasons_lrat,
736
+ std::vector<LRAT_ID> &reasons_lrat_back, bool remove_units = true);
737
+ // first index is a binary clause after unit propagation and the second
738
+ // has length 3
739
+ bool simplify_ite_gate_to_and (Gate *g, size_t idx1, size_t idx2,
740
+ int removed);
741
+ void merge_ite_gate_same_then_else_lrat (
742
+ std::vector<LitClausePair> &clauses,
743
+ std::vector<LRAT_ID> &reasons_implication,
744
+ std::vector<LRAT_ID> &reasons_back);
745
+ void simplify_ite_gate_then_else_set (
746
+ Gate *g, std::vector<LRAT_ID> &reasons_implication,
747
+ std::vector<LRAT_ID> &reasons_back, size_t idx1, size_t idx2);
748
+
749
+ void simplify_ite_gate_condition_set (
750
+ Gate *g, std::vector<LRAT_ID> &reasons_lrat,
751
+ std::vector<LRAT_ID> &reasons_back_lrat, size_t idx1, size_t idx2);
752
+ bool normalize_ite_lits_gate (Gate *rhs);
753
+ };
754
+
755
+ } // namespace CaDiCaL
756
+
757
+ #endif