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.
- checksums.yaml +7 -0
- data/LICENSE.txt +26 -0
- data/README.md +101 -0
- data/ext/cadical/cadical/LICENSE +28 -0
- data/ext/cadical/cadical/README.md +65 -0
- data/ext/cadical/cadical/VERSION +1 -0
- data/ext/cadical/cadical/src/analyze.cpp +1360 -0
- data/ext/cadical/cadical/src/arena.cpp +30 -0
- data/ext/cadical/cadical/src/arena.hpp +105 -0
- data/ext/cadical/cadical/src/assume.cpp +616 -0
- data/ext/cadical/cadical/src/averages.cpp +34 -0
- data/ext/cadical/cadical/src/averages.hpp +37 -0
- data/ext/cadical/cadical/src/backbone.cpp +631 -0
- data/ext/cadical/cadical/src/backtrack.cpp +177 -0
- data/ext/cadical/cadical/src/backward.cpp +231 -0
- data/ext/cadical/cadical/src/bins.cpp +22 -0
- data/ext/cadical/cadical/src/bins.hpp +22 -0
- data/ext/cadical/cadical/src/block.cpp +824 -0
- data/ext/cadical/cadical/src/block.hpp +37 -0
- data/ext/cadical/cadical/src/cadical.cpp +1026 -0
- data/ext/cadical/cadical/src/cadical.hpp +1419 -0
- data/ext/cadical/cadical/src/ccadical.cpp +208 -0
- data/ext/cadical/cadical/src/ccadical.h +74 -0
- data/ext/cadical/cadical/src/checker.cpp +649 -0
- data/ext/cadical/cadical/src/checker.hpp +173 -0
- data/ext/cadical/cadical/src/clause.cpp +689 -0
- data/ext/cadical/cadical/src/clause.hpp +190 -0
- data/ext/cadical/cadical/src/collect.cpp +545 -0
- data/ext/cadical/cadical/src/compact.cpp +550 -0
- data/ext/cadical/cadical/src/condition.cpp +940 -0
- data/ext/cadical/cadical/src/config.cpp +101 -0
- data/ext/cadical/cadical/src/config.hpp +20 -0
- data/ext/cadical/cadical/src/congruence.cpp +7880 -0
- data/ext/cadical/cadical/src/congruence.hpp +757 -0
- data/ext/cadical/cadical/src/constrain.cpp +64 -0
- data/ext/cadical/cadical/src/contract.cpp +27 -0
- data/ext/cadical/cadical/src/contract.hpp +139 -0
- data/ext/cadical/cadical/src/cover.cpp +704 -0
- data/ext/cadical/cadical/src/cover.hpp +34 -0
- data/ext/cadical/cadical/src/decide.cpp +347 -0
- data/ext/cadical/cadical/src/decompose.cpp +738 -0
- data/ext/cadical/cadical/src/decompose.hpp +23 -0
- data/ext/cadical/cadical/src/deduplicate.cpp +275 -0
- data/ext/cadical/cadical/src/definition.cpp +283 -0
- data/ext/cadical/cadical/src/delay.hpp +38 -0
- data/ext/cadical/cadical/src/drattracer.cpp +153 -0
- data/ext/cadical/cadical/src/drattracer.hpp +55 -0
- data/ext/cadical/cadical/src/elim.cpp +1171 -0
- data/ext/cadical/cadical/src/elim.hpp +53 -0
- data/ext/cadical/cadical/src/elimfast.cpp +570 -0
- data/ext/cadical/cadical/src/ema.cpp +95 -0
- data/ext/cadical/cadical/src/ema.hpp +68 -0
- data/ext/cadical/cadical/src/extend.cpp +289 -0
- data/ext/cadical/cadical/src/external.cpp +1034 -0
- data/ext/cadical/cadical/src/external.hpp +487 -0
- data/ext/cadical/cadical/src/external_propagate.cpp +1316 -0
- data/ext/cadical/cadical/src/factor.cpp +1011 -0
- data/ext/cadical/cadical/src/factor.hpp +54 -0
- data/ext/cadical/cadical/src/file.cpp +506 -0
- data/ext/cadical/cadical/src/file.hpp +210 -0
- data/ext/cadical/cadical/src/flags.cpp +135 -0
- data/ext/cadical/cadical/src/flags.hpp +93 -0
- data/ext/cadical/cadical/src/flip.cpp +269 -0
- data/ext/cadical/cadical/src/format.cpp +89 -0
- data/ext/cadical/cadical/src/format.hpp +36 -0
- data/ext/cadical/cadical/src/frattracer.cpp +277 -0
- data/ext/cadical/cadical/src/frattracer.hpp +67 -0
- data/ext/cadical/cadical/src/gates.cpp +766 -0
- data/ext/cadical/cadical/src/heap.hpp +212 -0
- data/ext/cadical/cadical/src/idruptracer.cpp +566 -0
- data/ext/cadical/cadical/src/idruptracer.hpp +112 -0
- data/ext/cadical/cadical/src/instantiate.cpp +365 -0
- data/ext/cadical/cadical/src/instantiate.hpp +45 -0
- data/ext/cadical/cadical/src/internal.cpp +1265 -0
- data/ext/cadical/cadical/src/internal.hpp +1941 -0
- data/ext/cadical/cadical/src/inttypes.hpp +34 -0
- data/ext/cadical/cadical/src/ipasir.cpp +47 -0
- data/ext/cadical/cadical/src/ipasir.h +37 -0
- data/ext/cadical/cadical/src/kitten.c +2599 -0
- data/ext/cadical/cadical/src/kitten.h +97 -0
- data/ext/cadical/cadical/src/level.hpp +33 -0
- data/ext/cadical/cadical/src/lidruptracer.cpp +657 -0
- data/ext/cadical/cadical/src/lidruptracer.hpp +122 -0
- data/ext/cadical/cadical/src/limit.cpp +146 -0
- data/ext/cadical/cadical/src/limit.hpp +168 -0
- data/ext/cadical/cadical/src/logging.cpp +214 -0
- data/ext/cadical/cadical/src/logging.hpp +98 -0
- data/ext/cadical/cadical/src/lookahead.cpp +520 -0
- data/ext/cadical/cadical/src/lratchecker.cpp +833 -0
- data/ext/cadical/cadical/src/lratchecker.hpp +168 -0
- data/ext/cadical/cadical/src/lrattracer.cpp +200 -0
- data/ext/cadical/cadical/src/lrattracer.hpp +61 -0
- data/ext/cadical/cadical/src/lucky.cpp +506 -0
- data/ext/cadical/cadical/src/message.cpp +218 -0
- data/ext/cadical/cadical/src/message.hpp +65 -0
- data/ext/cadical/cadical/src/minimize.cpp +224 -0
- data/ext/cadical/cadical/src/mobical.cpp +5588 -0
- data/ext/cadical/cadical/src/occs.cpp +52 -0
- data/ext/cadical/cadical/src/occs.hpp +36 -0
- data/ext/cadical/cadical/src/options.cpp +359 -0
- data/ext/cadical/cadical/src/options.hpp +442 -0
- data/ext/cadical/cadical/src/parse.cpp +471 -0
- data/ext/cadical/cadical/src/parse.hpp +75 -0
- data/ext/cadical/cadical/src/phases.cpp +56 -0
- data/ext/cadical/cadical/src/phases.hpp +19 -0
- data/ext/cadical/cadical/src/probe.cpp +990 -0
- data/ext/cadical/cadical/src/profile.cpp +107 -0
- data/ext/cadical/cadical/src/profile.hpp +283 -0
- data/ext/cadical/cadical/src/proof.cpp +691 -0
- data/ext/cadical/cadical/src/proof.hpp +125 -0
- data/ext/cadical/cadical/src/propagate.cpp +584 -0
- data/ext/cadical/cadical/src/queue.cpp +90 -0
- data/ext/cadical/cadical/src/queue.hpp +74 -0
- data/ext/cadical/cadical/src/radix.hpp +180 -0
- data/ext/cadical/cadical/src/random.cpp +207 -0
- data/ext/cadical/cadical/src/random.h +44 -0
- data/ext/cadical/cadical/src/random.hpp +98 -0
- data/ext/cadical/cadical/src/range.hpp +125 -0
- data/ext/cadical/cadical/src/reap.cpp +127 -0
- data/ext/cadical/cadical/src/reap.hpp +28 -0
- data/ext/cadical/cadical/src/reduce.cpp +278 -0
- data/ext/cadical/cadical/src/reluctant.hpp +82 -0
- data/ext/cadical/cadical/src/rephase.cpp +402 -0
- data/ext/cadical/cadical/src/report.cpp +313 -0
- data/ext/cadical/cadical/src/resources.cpp +160 -0
- data/ext/cadical/cadical/src/resources.hpp +16 -0
- data/ext/cadical/cadical/src/restart.cpp +178 -0
- data/ext/cadical/cadical/src/restore.cpp +267 -0
- data/ext/cadical/cadical/src/score.cpp +51 -0
- data/ext/cadical/cadical/src/score.hpp +16 -0
- data/ext/cadical/cadical/src/shrink.cpp +507 -0
- data/ext/cadical/cadical/src/signal.cpp +136 -0
- data/ext/cadical/cadical/src/signal.hpp +33 -0
- data/ext/cadical/cadical/src/solution.cpp +50 -0
- data/ext/cadical/cadical/src/solver.cpp +1871 -0
- data/ext/cadical/cadical/src/stable.cpp +31 -0
- data/ext/cadical/cadical/src/stack.h +110 -0
- data/ext/cadical/cadical/src/stats.cpp +920 -0
- data/ext/cadical/cadical/src/stats.hpp +418 -0
- data/ext/cadical/cadical/src/subsume.cpp +645 -0
- data/ext/cadical/cadical/src/sweep.cpp +1960 -0
- data/ext/cadical/cadical/src/sweep.hpp +61 -0
- data/ext/cadical/cadical/src/terminal.cpp +38 -0
- data/ext/cadical/cadical/src/terminal.hpp +96 -0
- data/ext/cadical/cadical/src/ternary.cpp +450 -0
- data/ext/cadical/cadical/src/testing.hpp +24 -0
- data/ext/cadical/cadical/src/tier.cpp +189 -0
- data/ext/cadical/cadical/src/tracer.hpp +186 -0
- data/ext/cadical/cadical/src/transred.cpp +253 -0
- data/ext/cadical/cadical/src/unstable.cpp +29 -0
- data/ext/cadical/cadical/src/util.cpp +129 -0
- data/ext/cadical/cadical/src/util.hpp +181 -0
- data/ext/cadical/cadical/src/var.cpp +39 -0
- data/ext/cadical/cadical/src/var.hpp +22 -0
- data/ext/cadical/cadical/src/veripbtracer.cpp +427 -0
- data/ext/cadical/cadical/src/veripbtracer.hpp +106 -0
- data/ext/cadical/cadical/src/version.cpp +107 -0
- data/ext/cadical/cadical/src/version.hpp +13 -0
- data/ext/cadical/cadical/src/vivify.cpp +1893 -0
- data/ext/cadical/cadical/src/vivify.hpp +50 -0
- data/ext/cadical/cadical/src/walk.cpp +1088 -0
- data/ext/cadical/cadical/src/walk.hpp +91 -0
- data/ext/cadical/cadical/src/walk_full_occs.cpp +966 -0
- data/ext/cadical/cadical/src/warmup.cpp +403 -0
- data/ext/cadical/cadical/src/watch.cpp +126 -0
- data/ext/cadical/cadical/src/watch.hpp +77 -0
- data/ext/cadical/cadical_ext.c +778 -0
- data/ext/cadical/extconf.rb +26 -0
- data/lib/cadical/version.rb +3 -0
- data/lib/cadical.rb +12 -0
- metadata +218 -0
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
// As in our original SATeLite published at SAT'05 we are trying to find
|
|
8
|
+
// gates in order to restrict the number of resolutions that need to be
|
|
9
|
+
// tried. If there is such a gate, we only need to consider resolvents
|
|
10
|
+
// among gate and one non-gate clauses. Resolvents between definitions will
|
|
11
|
+
// be tautological anyhow and resolvents among non-gates can actually be
|
|
12
|
+
// shown to be redundant too.
|
|
13
|
+
|
|
14
|
+
/*------------------------------------------------------------------------*/
|
|
15
|
+
|
|
16
|
+
// The next function returns a non-zero if the clause 'c', which is assumed
|
|
17
|
+
// to contain the literal 'first', after removing falsified literals is a
|
|
18
|
+
// binary clause. Then the actual second literal is returned.
|
|
19
|
+
|
|
20
|
+
int Internal::second_literal_in_binary_clause (Eliminator &eliminator,
|
|
21
|
+
Clause *c, int first) {
|
|
22
|
+
assert (!c->garbage);
|
|
23
|
+
int second = 0;
|
|
24
|
+
for (const auto &lit : *c) {
|
|
25
|
+
if (lit == first)
|
|
26
|
+
continue;
|
|
27
|
+
const signed char tmp = val (lit);
|
|
28
|
+
if (tmp < 0)
|
|
29
|
+
continue;
|
|
30
|
+
if (tmp > 0) {
|
|
31
|
+
mark_garbage (c);
|
|
32
|
+
elim_update_removed_clause (eliminator, c);
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
if (second) {
|
|
36
|
+
second = INT_MIN;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
second = lit;
|
|
40
|
+
}
|
|
41
|
+
if (!second)
|
|
42
|
+
return 0;
|
|
43
|
+
if (second == INT_MIN)
|
|
44
|
+
return 0;
|
|
45
|
+
assert (active (second));
|
|
46
|
+
#ifdef LOGGING
|
|
47
|
+
if (c->size == 2)
|
|
48
|
+
LOG (c, "found binary");
|
|
49
|
+
else
|
|
50
|
+
LOG (c, "found actual binary %d %d", first, second);
|
|
51
|
+
#endif
|
|
52
|
+
return second;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/*------------------------------------------------------------------------*/
|
|
56
|
+
|
|
57
|
+
// need a copy from above that does not care about garbage
|
|
58
|
+
|
|
59
|
+
int Internal::second_literal_in_binary_clause_lrat (Clause *c, int first) {
|
|
60
|
+
if (c->garbage)
|
|
61
|
+
return 0;
|
|
62
|
+
int second = 0;
|
|
63
|
+
for (const auto &lit : *c) {
|
|
64
|
+
if (lit == first)
|
|
65
|
+
continue;
|
|
66
|
+
const signed char tmp = val (lit);
|
|
67
|
+
if (tmp < 0)
|
|
68
|
+
continue;
|
|
69
|
+
if (tmp > 0)
|
|
70
|
+
return 0;
|
|
71
|
+
if (!tmp) {
|
|
72
|
+
if (second) {
|
|
73
|
+
second = INT_MIN;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
second = lit;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!second)
|
|
80
|
+
return 0;
|
|
81
|
+
if (second == INT_MIN)
|
|
82
|
+
return 0;
|
|
83
|
+
return second;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// I needed to find the second clause for hyper unary resolution to build
|
|
87
|
+
// LRAT this is not efficient but I could not find a better way then just
|
|
88
|
+
// finding the corresponding clause in all possible clauses
|
|
89
|
+
//
|
|
90
|
+
Clause *Internal::find_binary_clause (int first, int second) {
|
|
91
|
+
int best = first;
|
|
92
|
+
int other = second;
|
|
93
|
+
if (occs (first).size () > occs (second).size ()) {
|
|
94
|
+
best = second;
|
|
95
|
+
other = first;
|
|
96
|
+
}
|
|
97
|
+
for (auto c : occs (best))
|
|
98
|
+
if (second_literal_in_binary_clause_lrat (c, best) == other)
|
|
99
|
+
return c;
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/*------------------------------------------------------------------------*/
|
|
104
|
+
|
|
105
|
+
// Mark all other literals in binary clauses with 'first'. During this
|
|
106
|
+
// marking we might also detect hyper unary resolvents producing a unit.
|
|
107
|
+
// If such a unit is found we propagate it and return immediately.
|
|
108
|
+
|
|
109
|
+
void Internal::mark_binary_literals (Eliminator &eliminator, int first) {
|
|
110
|
+
|
|
111
|
+
if (unsat)
|
|
112
|
+
return;
|
|
113
|
+
if (val (first))
|
|
114
|
+
return;
|
|
115
|
+
if (!eliminator.gates.empty ())
|
|
116
|
+
return;
|
|
117
|
+
|
|
118
|
+
assert (!marked (first));
|
|
119
|
+
assert (eliminator.marked.empty ());
|
|
120
|
+
|
|
121
|
+
const Occs &os = occs (first);
|
|
122
|
+
for (const auto &c : os) {
|
|
123
|
+
if (c->garbage)
|
|
124
|
+
continue;
|
|
125
|
+
const int second =
|
|
126
|
+
second_literal_in_binary_clause (eliminator, c, first);
|
|
127
|
+
if (!second)
|
|
128
|
+
continue;
|
|
129
|
+
const int tmp = marked (second);
|
|
130
|
+
if (tmp < 0) {
|
|
131
|
+
// had a bug where units could occur multiple times here
|
|
132
|
+
// solved with flags
|
|
133
|
+
LOG ("found binary resolved unit %d", first);
|
|
134
|
+
if (lrat) {
|
|
135
|
+
Clause *d = find_binary_clause (first, -second);
|
|
136
|
+
assert (d);
|
|
137
|
+
for (auto &lit : *d) {
|
|
138
|
+
if (lit == first || lit == -second)
|
|
139
|
+
continue;
|
|
140
|
+
assert (val (lit) < 0);
|
|
141
|
+
Flags &f = flags (lit);
|
|
142
|
+
if (f.seen)
|
|
143
|
+
continue;
|
|
144
|
+
analyzed.push_back (lit);
|
|
145
|
+
f.seen = true;
|
|
146
|
+
int64_t id = unit_id (-lit);
|
|
147
|
+
lrat_chain.push_back (id);
|
|
148
|
+
// LOG ("gates added id %" PRId64, id);
|
|
149
|
+
}
|
|
150
|
+
for (auto &lit : *c) {
|
|
151
|
+
if (lit == first || lit == second)
|
|
152
|
+
continue;
|
|
153
|
+
assert (val (lit) < 0);
|
|
154
|
+
Flags &f = flags (lit);
|
|
155
|
+
if (f.seen)
|
|
156
|
+
continue;
|
|
157
|
+
analyzed.push_back (lit);
|
|
158
|
+
f.seen = true;
|
|
159
|
+
int64_t id = unit_id (-lit);
|
|
160
|
+
lrat_chain.push_back (id);
|
|
161
|
+
// LOG ("gates added id %" PRId64, id);
|
|
162
|
+
}
|
|
163
|
+
lrat_chain.push_back (c->id);
|
|
164
|
+
lrat_chain.push_back (d->id);
|
|
165
|
+
// LOG ("gates added id %" PRId64, c->id);
|
|
166
|
+
// LOG ("gates added id %" PRId64, d->id);
|
|
167
|
+
clear_analyzed_literals ();
|
|
168
|
+
}
|
|
169
|
+
assign_unit (first);
|
|
170
|
+
elim_propagate (eliminator, first);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (tmp > 0) {
|
|
174
|
+
LOG (c, "duplicated actual binary clause");
|
|
175
|
+
elim_update_removed_clause (eliminator, c);
|
|
176
|
+
mark_garbage (c);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
eliminator.marked.push_back (second);
|
|
180
|
+
mark (second);
|
|
181
|
+
LOG ("marked second literal %d in binary clause %d %d", second, first,
|
|
182
|
+
second);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Unmark all literals saved on the 'marked' stack.
|
|
187
|
+
|
|
188
|
+
void Internal::unmark_binary_literals (Eliminator &eliminator) {
|
|
189
|
+
LOG ("unmarking %zd literals", eliminator.marked.size ());
|
|
190
|
+
for (const auto &lit : eliminator.marked)
|
|
191
|
+
unmark (lit);
|
|
192
|
+
eliminator.marked.clear ();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/*------------------------------------------------------------------------*/
|
|
196
|
+
|
|
197
|
+
// Find equivalence for 'pivot'. Requires that all other literals in binary
|
|
198
|
+
// clauses with 'pivot' are marked (through 'mark_binary_literals');
|
|
199
|
+
|
|
200
|
+
void Internal::find_equivalence (Eliminator &eliminator, int pivot) {
|
|
201
|
+
|
|
202
|
+
if (!opts.elimequivs)
|
|
203
|
+
return;
|
|
204
|
+
|
|
205
|
+
assert (opts.elimsubst);
|
|
206
|
+
|
|
207
|
+
if (unsat)
|
|
208
|
+
return;
|
|
209
|
+
if (val (pivot))
|
|
210
|
+
return;
|
|
211
|
+
if (!eliminator.gates.empty ())
|
|
212
|
+
return;
|
|
213
|
+
|
|
214
|
+
mark_binary_literals (eliminator, pivot);
|
|
215
|
+
if (unsat || val (pivot))
|
|
216
|
+
goto DONE;
|
|
217
|
+
|
|
218
|
+
for (const auto &c : occs (-pivot)) {
|
|
219
|
+
|
|
220
|
+
if (c->garbage)
|
|
221
|
+
continue;
|
|
222
|
+
|
|
223
|
+
const int second =
|
|
224
|
+
second_literal_in_binary_clause (eliminator, c, -pivot);
|
|
225
|
+
if (!second)
|
|
226
|
+
continue;
|
|
227
|
+
const int tmp = marked (second);
|
|
228
|
+
if (tmp > 0) {
|
|
229
|
+
LOG ("found binary resolved unit %d", second);
|
|
230
|
+
// did not find a bug where units could occur multiple times here
|
|
231
|
+
// still solved potential issues with flags
|
|
232
|
+
if (lrat) {
|
|
233
|
+
Clause *d = find_binary_clause (pivot, second);
|
|
234
|
+
assert (d);
|
|
235
|
+
for (auto &lit : *d) {
|
|
236
|
+
if (lit == pivot || lit == second)
|
|
237
|
+
continue;
|
|
238
|
+
assert (val (lit) < 0);
|
|
239
|
+
Flags &f = flags (lit);
|
|
240
|
+
if (f.seen)
|
|
241
|
+
continue;
|
|
242
|
+
analyzed.push_back (lit);
|
|
243
|
+
f.seen = true;
|
|
244
|
+
int64_t id = unit_id (-lit);
|
|
245
|
+
lrat_chain.push_back (id);
|
|
246
|
+
// LOG ("gates added id %" PRId64, id);
|
|
247
|
+
}
|
|
248
|
+
for (auto &lit : *c) {
|
|
249
|
+
if (lit == -pivot || lit == second)
|
|
250
|
+
continue;
|
|
251
|
+
assert (val (lit) < 0);
|
|
252
|
+
Flags &f = flags (lit);
|
|
253
|
+
if (f.seen)
|
|
254
|
+
continue;
|
|
255
|
+
analyzed.push_back (lit);
|
|
256
|
+
f.seen = true;
|
|
257
|
+
int64_t id = unit_id (-lit);
|
|
258
|
+
lrat_chain.push_back (id);
|
|
259
|
+
// LOG ("gates added id %" PRId64, id);
|
|
260
|
+
}
|
|
261
|
+
lrat_chain.push_back (c->id);
|
|
262
|
+
lrat_chain.push_back (d->id);
|
|
263
|
+
clear_analyzed_literals ();
|
|
264
|
+
// LOG ("gates added id %" PRId64, c->id);
|
|
265
|
+
// LOG ("gates added id %" PRId64, d->id);
|
|
266
|
+
}
|
|
267
|
+
assign_unit (second);
|
|
268
|
+
elim_propagate (eliminator, second);
|
|
269
|
+
if (val (pivot))
|
|
270
|
+
break;
|
|
271
|
+
if (unsat)
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
if (tmp >= 0)
|
|
275
|
+
continue;
|
|
276
|
+
|
|
277
|
+
LOG ("found equivalence %d = %d", pivot, -second);
|
|
278
|
+
stats.elimequivs++;
|
|
279
|
+
stats.elimgates++;
|
|
280
|
+
|
|
281
|
+
LOG (c, "first gate clause");
|
|
282
|
+
assert (!c->gate);
|
|
283
|
+
c->gate = true;
|
|
284
|
+
eliminator.gates.push_back (c);
|
|
285
|
+
|
|
286
|
+
Clause *d = 0;
|
|
287
|
+
const Occs &ps = occs (pivot);
|
|
288
|
+
for (const auto &e : ps) {
|
|
289
|
+
if (e->garbage)
|
|
290
|
+
continue;
|
|
291
|
+
const int other =
|
|
292
|
+
second_literal_in_binary_clause (eliminator, e, pivot);
|
|
293
|
+
if (other == -second) {
|
|
294
|
+
d = e;
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
assert (d);
|
|
299
|
+
|
|
300
|
+
LOG (d, "second gate clause");
|
|
301
|
+
assert (!d->gate);
|
|
302
|
+
d->gate = true;
|
|
303
|
+
eliminator.gates.push_back (d);
|
|
304
|
+
eliminator.gatetype = EQUI;
|
|
305
|
+
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
DONE:
|
|
310
|
+
unmark_binary_literals (eliminator);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/*------------------------------------------------------------------------*/
|
|
314
|
+
|
|
315
|
+
// Find and gates for 'pivot' with a long clause, in which the pivot occurs
|
|
316
|
+
// positively. Requires that all other literals in binary clauses with
|
|
317
|
+
// 'pivot' are marked (through 'mark_binary_literals');
|
|
318
|
+
|
|
319
|
+
void Internal::find_and_gate (Eliminator &eliminator, int pivot) {
|
|
320
|
+
|
|
321
|
+
if (!opts.elimands)
|
|
322
|
+
return;
|
|
323
|
+
|
|
324
|
+
assert (opts.elimsubst);
|
|
325
|
+
|
|
326
|
+
if (unsat)
|
|
327
|
+
return;
|
|
328
|
+
if (val (pivot))
|
|
329
|
+
return;
|
|
330
|
+
if (!eliminator.gates.empty ())
|
|
331
|
+
return;
|
|
332
|
+
|
|
333
|
+
mark_binary_literals (eliminator, pivot);
|
|
334
|
+
if (unsat || val (pivot))
|
|
335
|
+
goto DONE;
|
|
336
|
+
|
|
337
|
+
for (const auto &c : occs (-pivot)) {
|
|
338
|
+
|
|
339
|
+
if (c->garbage)
|
|
340
|
+
continue;
|
|
341
|
+
if (c->size < 3)
|
|
342
|
+
continue;
|
|
343
|
+
|
|
344
|
+
bool all_literals_marked = true;
|
|
345
|
+
unsigned arity = 0;
|
|
346
|
+
int satisfied = 0;
|
|
347
|
+
|
|
348
|
+
for (const auto &lit : *c) {
|
|
349
|
+
if (lit == -pivot)
|
|
350
|
+
continue;
|
|
351
|
+
assert (lit != pivot);
|
|
352
|
+
signed char tmp = val (lit);
|
|
353
|
+
if (tmp < 0)
|
|
354
|
+
continue;
|
|
355
|
+
if (tmp > 0) {
|
|
356
|
+
satisfied = lit;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
tmp = marked (lit);
|
|
360
|
+
if (tmp < 0) {
|
|
361
|
+
arity++;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
all_literals_marked = false;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!all_literals_marked)
|
|
369
|
+
continue;
|
|
370
|
+
|
|
371
|
+
if (satisfied) {
|
|
372
|
+
LOG (c, "satisfied by %d candidate base clause", satisfied);
|
|
373
|
+
mark_garbage (c);
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
#ifdef LOGGING
|
|
378
|
+
if (opts.log) {
|
|
379
|
+
Logger::print_log_prefix (this);
|
|
380
|
+
tout.magenta ();
|
|
381
|
+
printf ("found arity %u AND gate %d = ", arity, -pivot);
|
|
382
|
+
bool first = true;
|
|
383
|
+
for (const auto &lit : *c) {
|
|
384
|
+
if (lit == -pivot)
|
|
385
|
+
continue;
|
|
386
|
+
assert (lit != pivot);
|
|
387
|
+
if (!first)
|
|
388
|
+
fputs (" & ", stdout);
|
|
389
|
+
printf ("%d", -lit);
|
|
390
|
+
first = false;
|
|
391
|
+
}
|
|
392
|
+
fputc ('\n', stdout);
|
|
393
|
+
tout.normal ();
|
|
394
|
+
fflush (stdout);
|
|
395
|
+
}
|
|
396
|
+
#endif
|
|
397
|
+
stats.elimands++;
|
|
398
|
+
stats.elimgates++;
|
|
399
|
+
eliminator.gatetype = AND;
|
|
400
|
+
|
|
401
|
+
(void) arity;
|
|
402
|
+
assert (!c->gate);
|
|
403
|
+
c->gate = true;
|
|
404
|
+
eliminator.gates.push_back (c);
|
|
405
|
+
for (const auto &lit : *c) {
|
|
406
|
+
if (lit == -pivot)
|
|
407
|
+
continue;
|
|
408
|
+
assert (lit != pivot);
|
|
409
|
+
signed char tmp = val (lit);
|
|
410
|
+
if (tmp < 0)
|
|
411
|
+
continue;
|
|
412
|
+
assert (!tmp);
|
|
413
|
+
assert (marked (lit) < 0);
|
|
414
|
+
marks[vidx (lit)] *= 2;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
unsigned count = 0;
|
|
418
|
+
for (const auto &d : occs (pivot)) {
|
|
419
|
+
if (d->garbage)
|
|
420
|
+
continue;
|
|
421
|
+
const int other =
|
|
422
|
+
second_literal_in_binary_clause (eliminator, d, pivot);
|
|
423
|
+
if (!other)
|
|
424
|
+
continue;
|
|
425
|
+
const int tmp = marked (other);
|
|
426
|
+
if (tmp != 2)
|
|
427
|
+
continue;
|
|
428
|
+
LOG (d, "AND gate binary side clause");
|
|
429
|
+
assert (!d->gate);
|
|
430
|
+
d->gate = true;
|
|
431
|
+
eliminator.gates.push_back (d);
|
|
432
|
+
count++;
|
|
433
|
+
}
|
|
434
|
+
assert (count >= arity);
|
|
435
|
+
(void) count;
|
|
436
|
+
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
DONE:
|
|
441
|
+
unmark_binary_literals (eliminator);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/*------------------------------------------------------------------------*/
|
|
445
|
+
|
|
446
|
+
// Find and extract ternary clauses.
|
|
447
|
+
|
|
448
|
+
bool Internal::get_ternary_clause (Clause *d, int &a, int &b, int &c) {
|
|
449
|
+
if (d->garbage)
|
|
450
|
+
return false;
|
|
451
|
+
if (d->size < 3)
|
|
452
|
+
return false;
|
|
453
|
+
int found = 0;
|
|
454
|
+
a = b = c = 0;
|
|
455
|
+
for (const auto &lit : *d) {
|
|
456
|
+
if (val (lit))
|
|
457
|
+
continue;
|
|
458
|
+
if (++found == 1)
|
|
459
|
+
a = lit;
|
|
460
|
+
else if (found == 2)
|
|
461
|
+
b = lit;
|
|
462
|
+
else if (found == 3)
|
|
463
|
+
c = lit;
|
|
464
|
+
else
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
return found == 3;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// This function checks whether 'd' exists as ternary clause.
|
|
471
|
+
|
|
472
|
+
bool Internal::match_ternary_clause (Clause *d, int a, int b, int c) {
|
|
473
|
+
if (d->garbage)
|
|
474
|
+
return false;
|
|
475
|
+
int found = 0;
|
|
476
|
+
for (const auto &lit : *d) {
|
|
477
|
+
if (val (lit))
|
|
478
|
+
continue;
|
|
479
|
+
if (a != lit && b != lit && c != lit)
|
|
480
|
+
return false;
|
|
481
|
+
found++;
|
|
482
|
+
}
|
|
483
|
+
return found == 3;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
Clause *Internal::find_ternary_clause (int a, int b, int c) {
|
|
487
|
+
if (occs (b).size () > occs (c).size ())
|
|
488
|
+
swap (b, c);
|
|
489
|
+
if (occs (a).size () > occs (b).size ())
|
|
490
|
+
swap (a, b);
|
|
491
|
+
for (auto d : occs (a))
|
|
492
|
+
if (match_ternary_clause (d, a, b, c))
|
|
493
|
+
return d;
|
|
494
|
+
return 0;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/*------------------------------------------------------------------------*/
|
|
498
|
+
|
|
499
|
+
// Find if-then-else gate.
|
|
500
|
+
|
|
501
|
+
void Internal::find_if_then_else (Eliminator &eliminator, int pivot) {
|
|
502
|
+
|
|
503
|
+
if (!opts.elimites)
|
|
504
|
+
return;
|
|
505
|
+
|
|
506
|
+
assert (opts.elimsubst);
|
|
507
|
+
|
|
508
|
+
if (unsat)
|
|
509
|
+
return;
|
|
510
|
+
if (val (pivot))
|
|
511
|
+
return;
|
|
512
|
+
if (!eliminator.gates.empty ())
|
|
513
|
+
return;
|
|
514
|
+
|
|
515
|
+
const Occs &os = occs (pivot);
|
|
516
|
+
const auto end = os.end ();
|
|
517
|
+
for (auto i = os.begin (); i != end; i++) {
|
|
518
|
+
Clause *di = *i;
|
|
519
|
+
int ai, bi, ci;
|
|
520
|
+
if (!get_ternary_clause (di, ai, bi, ci))
|
|
521
|
+
continue;
|
|
522
|
+
if (bi == pivot)
|
|
523
|
+
swap (ai, bi);
|
|
524
|
+
if (ci == pivot)
|
|
525
|
+
swap (ai, ci);
|
|
526
|
+
assert (ai == pivot);
|
|
527
|
+
for (auto j = i + 1; j != end; j++) {
|
|
528
|
+
Clause *dj = *j;
|
|
529
|
+
int aj, bj, cj;
|
|
530
|
+
if (!get_ternary_clause (dj, aj, bj, cj))
|
|
531
|
+
continue;
|
|
532
|
+
if (bj == pivot)
|
|
533
|
+
swap (aj, bj);
|
|
534
|
+
if (cj == pivot)
|
|
535
|
+
swap (aj, cj);
|
|
536
|
+
assert (aj == pivot);
|
|
537
|
+
if (abs (bi) == abs (cj))
|
|
538
|
+
swap (bj, cj);
|
|
539
|
+
if (abs (ci) == abs (cj))
|
|
540
|
+
continue;
|
|
541
|
+
if (bi != -bj)
|
|
542
|
+
continue;
|
|
543
|
+
Clause *d1 = find_ternary_clause (-pivot, bi, -ci);
|
|
544
|
+
if (!d1)
|
|
545
|
+
continue;
|
|
546
|
+
Clause *d2 = find_ternary_clause (-pivot, bj, -cj);
|
|
547
|
+
if (!d2)
|
|
548
|
+
continue;
|
|
549
|
+
LOG (di, "1st if-then-else");
|
|
550
|
+
LOG (dj, "2nd if-then-else");
|
|
551
|
+
LOG (d1, "3rd if-then-else");
|
|
552
|
+
LOG (d2, "4th if-then-else");
|
|
553
|
+
LOG ("found ITE gate %d == (%d ? %d : %d)", pivot, -bi, -ci, -cj);
|
|
554
|
+
assert (!di->gate);
|
|
555
|
+
assert (!dj->gate);
|
|
556
|
+
assert (!d1->gate);
|
|
557
|
+
assert (!d2->gate);
|
|
558
|
+
di->gate = true;
|
|
559
|
+
dj->gate = true;
|
|
560
|
+
d1->gate = true;
|
|
561
|
+
d2->gate = true;
|
|
562
|
+
eliminator.gates.push_back (di);
|
|
563
|
+
eliminator.gates.push_back (dj);
|
|
564
|
+
eliminator.gates.push_back (d1);
|
|
565
|
+
eliminator.gates.push_back (d2);
|
|
566
|
+
stats.elimgates++;
|
|
567
|
+
stats.elimites++;
|
|
568
|
+
eliminator.gatetype = ITE;
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/*------------------------------------------------------------------------*/
|
|
575
|
+
|
|
576
|
+
// Find and extract clause.
|
|
577
|
+
|
|
578
|
+
bool Internal::get_clause (Clause *c, vector<int> &l) {
|
|
579
|
+
if (c->garbage)
|
|
580
|
+
return false;
|
|
581
|
+
l.clear ();
|
|
582
|
+
for (const auto &lit : *c) {
|
|
583
|
+
if (val (lit) < 0)
|
|
584
|
+
continue;
|
|
585
|
+
if (val (lit) > 0) {
|
|
586
|
+
l.clear ();
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
l.push_back (lit);
|
|
590
|
+
}
|
|
591
|
+
return true;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Check whether 'c' contains only the literals in 'l'.
|
|
595
|
+
|
|
596
|
+
bool Internal::is_clause (Clause *c, const vector<int> &lits) {
|
|
597
|
+
if (c->garbage)
|
|
598
|
+
return false;
|
|
599
|
+
int size = lits.size ();
|
|
600
|
+
if (c->size < size)
|
|
601
|
+
return false;
|
|
602
|
+
int found = 0;
|
|
603
|
+
for (const auto &lit : *c) {
|
|
604
|
+
if (val (lit) < 0)
|
|
605
|
+
continue;
|
|
606
|
+
if (val (lit) > 0)
|
|
607
|
+
return false;
|
|
608
|
+
const auto it = find (lits.begin (), lits.end (), lit);
|
|
609
|
+
if (it == lits.end ())
|
|
610
|
+
return false;
|
|
611
|
+
if (++found > size)
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
return found == size;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
Clause *Internal::find_clause (const vector<int> &lits) {
|
|
618
|
+
int best = 0;
|
|
619
|
+
size_t len = 0;
|
|
620
|
+
for (const auto &lit : lits) {
|
|
621
|
+
size_t l = occs (lit).size ();
|
|
622
|
+
if (best && l >= len)
|
|
623
|
+
continue;
|
|
624
|
+
len = l, best = lit;
|
|
625
|
+
}
|
|
626
|
+
for (auto c : occs (best))
|
|
627
|
+
if (is_clause (c, lits))
|
|
628
|
+
return c;
|
|
629
|
+
return 0;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
void Internal::find_xor_gate (Eliminator &eliminator, int pivot) {
|
|
633
|
+
|
|
634
|
+
if (!opts.elimxors)
|
|
635
|
+
return;
|
|
636
|
+
|
|
637
|
+
assert (opts.elimsubst);
|
|
638
|
+
|
|
639
|
+
if (unsat)
|
|
640
|
+
return;
|
|
641
|
+
if (val (pivot))
|
|
642
|
+
return;
|
|
643
|
+
if (!eliminator.gates.empty ())
|
|
644
|
+
return;
|
|
645
|
+
|
|
646
|
+
vector<int> lits;
|
|
647
|
+
|
|
648
|
+
for (auto d : occs (pivot)) {
|
|
649
|
+
|
|
650
|
+
if (!get_clause (d, lits))
|
|
651
|
+
continue;
|
|
652
|
+
|
|
653
|
+
const int size = lits.size (); // clause size
|
|
654
|
+
const int arity = size - 1; // arity of XOR
|
|
655
|
+
|
|
656
|
+
if (size < 3)
|
|
657
|
+
continue;
|
|
658
|
+
if (arity > opts.elimxorlim)
|
|
659
|
+
continue;
|
|
660
|
+
|
|
661
|
+
assert (eliminator.gates.empty ());
|
|
662
|
+
|
|
663
|
+
unsigned needed = (1u << arity) - 1; // additional clauses
|
|
664
|
+
unsigned signs = 0; // literals to negate
|
|
665
|
+
|
|
666
|
+
do {
|
|
667
|
+
const unsigned prev = signs;
|
|
668
|
+
while (parity (++signs))
|
|
669
|
+
;
|
|
670
|
+
for (int j = 0; j < size; j++) {
|
|
671
|
+
const unsigned bit = 1u << j;
|
|
672
|
+
int lit = lits[j];
|
|
673
|
+
if ((prev & bit) != (signs & bit))
|
|
674
|
+
lits[j] = lit = -lit;
|
|
675
|
+
}
|
|
676
|
+
Clause *e = find_clause (lits);
|
|
677
|
+
if (!e)
|
|
678
|
+
break;
|
|
679
|
+
eliminator.gates.push_back (e);
|
|
680
|
+
} while (--needed);
|
|
681
|
+
|
|
682
|
+
if (needed) {
|
|
683
|
+
eliminator.gates.clear ();
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
eliminator.gates.push_back (d);
|
|
688
|
+
assert (eliminator.gates.size () == (1u << arity));
|
|
689
|
+
|
|
690
|
+
#ifdef LOGGING
|
|
691
|
+
if (opts.log) {
|
|
692
|
+
Logger::print_log_prefix (this);
|
|
693
|
+
tout.magenta ();
|
|
694
|
+
printf ("found arity %u XOR gate %d = ", arity, -pivot);
|
|
695
|
+
bool first = true;
|
|
696
|
+
for (const auto &lit : *d) {
|
|
697
|
+
if (lit == pivot)
|
|
698
|
+
continue;
|
|
699
|
+
assert (lit != -pivot);
|
|
700
|
+
if (!first)
|
|
701
|
+
fputs (" ^ ", stdout);
|
|
702
|
+
printf ("%d", lit);
|
|
703
|
+
first = false;
|
|
704
|
+
}
|
|
705
|
+
fputc ('\n', stdout);
|
|
706
|
+
tout.normal ();
|
|
707
|
+
fflush (stdout);
|
|
708
|
+
}
|
|
709
|
+
#endif
|
|
710
|
+
stats.elimgates++;
|
|
711
|
+
stats.elimxors++;
|
|
712
|
+
const auto end = eliminator.gates.end ();
|
|
713
|
+
auto j = eliminator.gates.begin ();
|
|
714
|
+
for (auto i = j; i != end; i++) {
|
|
715
|
+
Clause *e = *i;
|
|
716
|
+
if (e->gate)
|
|
717
|
+
continue;
|
|
718
|
+
e->gate = true;
|
|
719
|
+
LOG (e, "contributing");
|
|
720
|
+
*j++ = e;
|
|
721
|
+
}
|
|
722
|
+
eliminator.gates.resize (j - eliminator.gates.begin ());
|
|
723
|
+
eliminator.gatetype = XOR;
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/*------------------------------------------------------------------------*/
|
|
729
|
+
|
|
730
|
+
// Find a gate for 'pivot'. If such a gate is found, the gate clauses are
|
|
731
|
+
// marked and pushed on the stack of gates. Further hyper unary resolution
|
|
732
|
+
// might detect units, which are propagated. This might assign the pivot or
|
|
733
|
+
// even produce the empty clause.
|
|
734
|
+
|
|
735
|
+
void Internal::find_gate_clauses (Eliminator &eliminator, int pivot) {
|
|
736
|
+
if (!opts.elimsubst)
|
|
737
|
+
return;
|
|
738
|
+
|
|
739
|
+
if (unsat)
|
|
740
|
+
return;
|
|
741
|
+
if (val (pivot))
|
|
742
|
+
return;
|
|
743
|
+
|
|
744
|
+
assert (eliminator.gates.empty ());
|
|
745
|
+
|
|
746
|
+
find_equivalence (eliminator, pivot);
|
|
747
|
+
find_and_gate (eliminator, pivot);
|
|
748
|
+
find_and_gate (eliminator, -pivot);
|
|
749
|
+
find_if_then_else (eliminator, pivot);
|
|
750
|
+
find_xor_gate (eliminator, pivot);
|
|
751
|
+
find_definition (eliminator, pivot);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
void Internal::unmark_gate_clauses (Eliminator &eliminator) {
|
|
755
|
+
LOG ("unmarking %zd gate clauses", eliminator.gates.size ());
|
|
756
|
+
for (const auto &c : eliminator.gates) {
|
|
757
|
+
assert (c->gate);
|
|
758
|
+
c->gate = false;
|
|
759
|
+
}
|
|
760
|
+
eliminator.gates.clear ();
|
|
761
|
+
eliminator.definition_unit = 0;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/*------------------------------------------------------------------------*/
|
|
765
|
+
|
|
766
|
+
} // namespace CaDiCaL
|