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,649 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
inline unsigned Checker::l2u (int lit) {
|
|
8
|
+
assert (lit);
|
|
9
|
+
assert (lit != INT_MIN);
|
|
10
|
+
unsigned res = 2 * (abs (lit) - 1);
|
|
11
|
+
if (lit < 0)
|
|
12
|
+
res++;
|
|
13
|
+
return res;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
inline signed char Checker::val (int lit) {
|
|
17
|
+
assert (lit);
|
|
18
|
+
assert (lit != INT_MIN);
|
|
19
|
+
assert (abs (lit) < size_vars);
|
|
20
|
+
assert (vals[lit] == -vals[-lit]);
|
|
21
|
+
return vals[lit];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
signed char &Checker::mark (int lit) {
|
|
25
|
+
const unsigned u = l2u (lit);
|
|
26
|
+
assert (u < marks.size ());
|
|
27
|
+
return marks[u];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
inline CheckerWatcher &Checker::watcher (int lit) {
|
|
31
|
+
const unsigned u = l2u (lit);
|
|
32
|
+
assert (u < watchers.size ());
|
|
33
|
+
return watchers[u];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/*------------------------------------------------------------------------*/
|
|
37
|
+
|
|
38
|
+
CheckerClause *Checker::new_clause () {
|
|
39
|
+
const size_t size = simplified.size ();
|
|
40
|
+
assert (size > 1), assert (size <= UINT_MAX);
|
|
41
|
+
const size_t bytes = sizeof (CheckerClause) + (size - 2) * sizeof (int);
|
|
42
|
+
CheckerClause *res = (CheckerClause *) new char[bytes];
|
|
43
|
+
DeferDeleteArray<char> delete_res ((char *) res);
|
|
44
|
+
res->next = 0;
|
|
45
|
+
res->hash = last_hash;
|
|
46
|
+
res->size = size;
|
|
47
|
+
int *literals = res->literals, *p = literals;
|
|
48
|
+
for (const auto &lit : simplified)
|
|
49
|
+
*p++ = lit;
|
|
50
|
+
num_clauses++;
|
|
51
|
+
|
|
52
|
+
// First two literals are used as watches and should not be false.
|
|
53
|
+
//
|
|
54
|
+
for (unsigned i = 0; i < 2; i++) {
|
|
55
|
+
int lit = literals[i];
|
|
56
|
+
if (!val (lit))
|
|
57
|
+
continue;
|
|
58
|
+
for (unsigned j = i + 1; j < size; j++) {
|
|
59
|
+
int other = literals[j];
|
|
60
|
+
if (val (other))
|
|
61
|
+
continue;
|
|
62
|
+
swap (literals[i], literals[j]);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
assert (!val (literals[0]));
|
|
67
|
+
assert (!val (literals[1]));
|
|
68
|
+
watcher (literals[0]).push_back (CheckerWatch (literals[1], res));
|
|
69
|
+
watcher (literals[1]).push_back (CheckerWatch (literals[0], res));
|
|
70
|
+
|
|
71
|
+
delete_res.release ();
|
|
72
|
+
return res;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void Checker::delete_clause (CheckerClause *c) {
|
|
76
|
+
if (c->size) {
|
|
77
|
+
assert (c->size > 1);
|
|
78
|
+
assert (num_clauses);
|
|
79
|
+
num_clauses--;
|
|
80
|
+
} else {
|
|
81
|
+
assert (num_garbage);
|
|
82
|
+
num_garbage--;
|
|
83
|
+
}
|
|
84
|
+
delete[] (char *) c;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void Checker::enlarge_clauses () {
|
|
88
|
+
assert (num_clauses == size_clauses);
|
|
89
|
+
const uint64_t new_size_clauses = size_clauses ? 2 * size_clauses : 1;
|
|
90
|
+
LOG ("CHECKER enlarging clauses of checker from %" PRIu64 " to %" PRIu64,
|
|
91
|
+
(uint64_t) size_clauses, (uint64_t) new_size_clauses);
|
|
92
|
+
CheckerClause **new_clauses;
|
|
93
|
+
new_clauses = new CheckerClause *[new_size_clauses];
|
|
94
|
+
clear_n (new_clauses, new_size_clauses);
|
|
95
|
+
for (uint64_t i = 0; i < size_clauses; i++) {
|
|
96
|
+
for (CheckerClause *c = clauses[i], *next; c; c = next) {
|
|
97
|
+
next = c->next;
|
|
98
|
+
const uint64_t h = reduce_hash (c->hash, new_size_clauses);
|
|
99
|
+
c->next = new_clauses[h];
|
|
100
|
+
new_clauses[h] = c;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
delete[] clauses;
|
|
104
|
+
clauses = new_clauses;
|
|
105
|
+
size_clauses = new_size_clauses;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
bool Checker::clause_satisfied (CheckerClause *c) {
|
|
109
|
+
for (unsigned i = 0; i < c->size; i++)
|
|
110
|
+
if (val (c->literals[i]) > 0)
|
|
111
|
+
return true;
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// The main reason why we have an explicit garbage collection phase is that
|
|
116
|
+
// removing clauses from watcher lists eagerly might lead to an accumulated
|
|
117
|
+
// quadratic algorithm. Thus we delay removing garbage clauses from watcher
|
|
118
|
+
// lists until garbage collection (even though we remove garbage clauses on
|
|
119
|
+
// the fly during propagation too). We also remove satisfied clauses.
|
|
120
|
+
//
|
|
121
|
+
void Checker::collect_garbage_clauses () {
|
|
122
|
+
|
|
123
|
+
stats.collections++;
|
|
124
|
+
|
|
125
|
+
for (size_t i = 0; i < size_clauses; i++) {
|
|
126
|
+
CheckerClause **p = clauses + i, *c;
|
|
127
|
+
while ((c = *p)) {
|
|
128
|
+
if (clause_satisfied (c)) {
|
|
129
|
+
c->size = 0; // mark as garbage
|
|
130
|
+
*p = c->next;
|
|
131
|
+
c->next = garbage;
|
|
132
|
+
garbage = c;
|
|
133
|
+
num_garbage++;
|
|
134
|
+
assert (num_clauses);
|
|
135
|
+
num_clauses--;
|
|
136
|
+
} else
|
|
137
|
+
p = &c->next;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
LOG ("CHECKER collecting %" PRIu64 " garbage clauses %.0f%%", num_garbage,
|
|
142
|
+
percent (num_garbage, num_clauses));
|
|
143
|
+
|
|
144
|
+
for (int lit = -size_vars + 1; lit < size_vars; lit++) {
|
|
145
|
+
if (!lit)
|
|
146
|
+
continue;
|
|
147
|
+
CheckerWatcher &ws = watcher (lit);
|
|
148
|
+
const auto end = ws.end ();
|
|
149
|
+
auto j = ws.begin (), i = j;
|
|
150
|
+
for (; i != end; i++) {
|
|
151
|
+
CheckerWatch &w = *i;
|
|
152
|
+
if (w.clause->size)
|
|
153
|
+
*j++ = w;
|
|
154
|
+
}
|
|
155
|
+
if (j == ws.end ())
|
|
156
|
+
continue;
|
|
157
|
+
if (j == ws.begin ())
|
|
158
|
+
erase_vector (ws);
|
|
159
|
+
else
|
|
160
|
+
ws.resize (j - ws.begin ());
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
for (CheckerClause *c = garbage, *next; c; c = next)
|
|
164
|
+
next = c->next, delete_clause (c);
|
|
165
|
+
|
|
166
|
+
assert (!num_garbage);
|
|
167
|
+
garbage = 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/*------------------------------------------------------------------------*/
|
|
171
|
+
|
|
172
|
+
Checker::Checker (Internal *i)
|
|
173
|
+
: internal (i), size_vars (0), vals (0), inconsistent (false),
|
|
174
|
+
num_clauses (0), num_garbage (0), size_clauses (0), clauses (0),
|
|
175
|
+
garbage (0), next_to_propagate (0), last_hash (0) {
|
|
176
|
+
|
|
177
|
+
// Initialize random number table for hash function.
|
|
178
|
+
//
|
|
179
|
+
Random random (42);
|
|
180
|
+
for (unsigned n = 0; n < num_nonces; n++) {
|
|
181
|
+
uint64_t nonce = random.next ();
|
|
182
|
+
if (!(nonce & 1))
|
|
183
|
+
nonce++;
|
|
184
|
+
assert (nonce), assert (nonce & 1);
|
|
185
|
+
nonces[n] = nonce;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
memset (&stats, 0, sizeof (stats)); // Initialize statistics.
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
void Checker::connect_internal (Internal *i) {
|
|
192
|
+
internal = i;
|
|
193
|
+
LOG ("CHECKER connected to internal");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
Checker::~Checker () {
|
|
197
|
+
LOG ("CHECKER delete");
|
|
198
|
+
vals -= size_vars;
|
|
199
|
+
delete[] vals;
|
|
200
|
+
for (size_t i = 0; i < size_clauses; i++)
|
|
201
|
+
for (CheckerClause *c = clauses[i], *next; c; c = next)
|
|
202
|
+
next = c->next, delete_clause (c);
|
|
203
|
+
for (CheckerClause *c = garbage, *next; c; c = next)
|
|
204
|
+
next = c->next, delete_clause (c);
|
|
205
|
+
delete[] clauses;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/*------------------------------------------------------------------------*/
|
|
209
|
+
|
|
210
|
+
// The simplicity for accessing 'vals' and 'watchers' directly through a
|
|
211
|
+
// signed integer literal, comes with the price of slightly more complex
|
|
212
|
+
// code in deleting and enlarging the checker data structures.
|
|
213
|
+
|
|
214
|
+
void Checker::enlarge_vars (int64_t idx) {
|
|
215
|
+
|
|
216
|
+
assert (0 < idx), assert (idx <= INT_MAX);
|
|
217
|
+
|
|
218
|
+
int64_t new_size_vars = size_vars ? 2 * size_vars : 2;
|
|
219
|
+
while (idx >= new_size_vars)
|
|
220
|
+
new_size_vars *= 2;
|
|
221
|
+
LOG ("CHECKER enlarging variables of checker from %" PRId64 " to %" PRId64
|
|
222
|
+
"",
|
|
223
|
+
size_vars, new_size_vars);
|
|
224
|
+
|
|
225
|
+
signed char *new_vals;
|
|
226
|
+
new_vals = new signed char[2 * new_size_vars];
|
|
227
|
+
clear_n (new_vals, 2 * new_size_vars);
|
|
228
|
+
new_vals += new_size_vars;
|
|
229
|
+
if (size_vars) // To make sanitizer happy (without '-O').
|
|
230
|
+
memcpy ((void *) (new_vals - size_vars), (void *) (vals - size_vars),
|
|
231
|
+
2 * size_vars);
|
|
232
|
+
vals -= size_vars;
|
|
233
|
+
delete[] vals;
|
|
234
|
+
vals = new_vals;
|
|
235
|
+
size_vars = new_size_vars;
|
|
236
|
+
|
|
237
|
+
watchers.resize (2 * new_size_vars);
|
|
238
|
+
marks.resize (2 * new_size_vars);
|
|
239
|
+
|
|
240
|
+
assert (idx < new_size_vars);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
inline void Checker::import_literal (int lit) {
|
|
244
|
+
assert (lit);
|
|
245
|
+
assert (lit != INT_MIN);
|
|
246
|
+
int idx = abs (lit);
|
|
247
|
+
if (idx >= size_vars)
|
|
248
|
+
enlarge_vars (idx);
|
|
249
|
+
simplified.push_back (lit);
|
|
250
|
+
unsimplified.push_back (lit);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
void Checker::import_clause (const vector<int> &c) {
|
|
254
|
+
for (const auto &lit : c)
|
|
255
|
+
import_literal (lit);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
struct lit_smaller {
|
|
259
|
+
bool operator() (int a, int b) const {
|
|
260
|
+
int c = abs (a), d = abs (b);
|
|
261
|
+
if (c < d)
|
|
262
|
+
return true;
|
|
263
|
+
if (c > d)
|
|
264
|
+
return false;
|
|
265
|
+
return a < b;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
bool Checker::tautological () {
|
|
270
|
+
sort (simplified.begin (), simplified.end (), lit_smaller ());
|
|
271
|
+
const auto end = simplified.end ();
|
|
272
|
+
auto j = simplified.begin ();
|
|
273
|
+
int prev = 0;
|
|
274
|
+
for (auto i = j; i != end; i++) {
|
|
275
|
+
int lit = *i;
|
|
276
|
+
if (lit == prev)
|
|
277
|
+
continue; // duplicated literal
|
|
278
|
+
if (lit == -prev)
|
|
279
|
+
return true; // tautological clause
|
|
280
|
+
const signed char tmp = val (lit);
|
|
281
|
+
if (tmp > 0)
|
|
282
|
+
return true; // satisfied literal and clause
|
|
283
|
+
*j++ = prev = lit;
|
|
284
|
+
}
|
|
285
|
+
simplified.resize (j - simplified.begin ());
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/*------------------------------------------------------------------------*/
|
|
290
|
+
|
|
291
|
+
uint64_t Checker::reduce_hash (uint64_t hash, uint64_t size) {
|
|
292
|
+
assert (size > 0);
|
|
293
|
+
unsigned shift = 32;
|
|
294
|
+
uint64_t res = hash;
|
|
295
|
+
while ((((uint64_t) 1) << shift) > size) {
|
|
296
|
+
res ^= res >> shift;
|
|
297
|
+
shift >>= 1;
|
|
298
|
+
}
|
|
299
|
+
res &= size - 1;
|
|
300
|
+
assert (res < size);
|
|
301
|
+
return res;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
uint64_t Checker::compute_hash () {
|
|
305
|
+
unsigned j = last_id % num_nonces;
|
|
306
|
+
uint64_t tmp = nonces[j] * last_id;
|
|
307
|
+
return last_hash = tmp;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
CheckerClause **Checker::find () {
|
|
311
|
+
stats.searches++;
|
|
312
|
+
CheckerClause **res, *c;
|
|
313
|
+
const uint64_t hash = compute_hash ();
|
|
314
|
+
const unsigned size = simplified.size ();
|
|
315
|
+
const uint64_t h = reduce_hash (hash, size_clauses);
|
|
316
|
+
for (const auto &lit : simplified)
|
|
317
|
+
mark (lit) = true;
|
|
318
|
+
for (res = clauses + h; (c = *res); res = &c->next) {
|
|
319
|
+
if (c->hash == hash && c->size == size) {
|
|
320
|
+
bool found = true;
|
|
321
|
+
const int *literals = c->literals;
|
|
322
|
+
for (unsigned i = 0; found && i != size; i++)
|
|
323
|
+
found = mark (literals[i]);
|
|
324
|
+
if (found)
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
stats.collisions++;
|
|
328
|
+
}
|
|
329
|
+
for (const auto &lit : simplified)
|
|
330
|
+
mark (lit) = false;
|
|
331
|
+
return res;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
void Checker::insert () {
|
|
335
|
+
stats.insertions++;
|
|
336
|
+
if (num_clauses == size_clauses)
|
|
337
|
+
enlarge_clauses ();
|
|
338
|
+
const uint64_t h = reduce_hash (compute_hash (), size_clauses);
|
|
339
|
+
CheckerClause *c = new_clause ();
|
|
340
|
+
c->next = clauses[h];
|
|
341
|
+
clauses[h] = c;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/*------------------------------------------------------------------------*/
|
|
345
|
+
|
|
346
|
+
inline void Checker::assign (int lit) {
|
|
347
|
+
assert (!val (lit));
|
|
348
|
+
vals[lit] = 1;
|
|
349
|
+
vals[-lit] = -1;
|
|
350
|
+
trail.push_back (lit);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
inline void Checker::assume (int lit) {
|
|
354
|
+
signed char tmp = val (lit);
|
|
355
|
+
if (tmp > 0)
|
|
356
|
+
return;
|
|
357
|
+
assert (!tmp);
|
|
358
|
+
stats.assumptions++;
|
|
359
|
+
assign (lit);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
void Checker::backtrack (unsigned previously_propagated) {
|
|
363
|
+
|
|
364
|
+
assert (previously_propagated <= trail.size ());
|
|
365
|
+
|
|
366
|
+
while (trail.size () > previously_propagated) {
|
|
367
|
+
int lit = trail.back ();
|
|
368
|
+
assert (val (lit) > 0);
|
|
369
|
+
assert (val (-lit) < 0);
|
|
370
|
+
vals[lit] = vals[-lit] = 0;
|
|
371
|
+
trail.pop_back ();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
trail.resize (previously_propagated);
|
|
375
|
+
next_to_propagate = previously_propagated;
|
|
376
|
+
assert (trail.size () == next_to_propagate);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/*------------------------------------------------------------------------*/
|
|
380
|
+
|
|
381
|
+
// This is a standard propagation routine without using blocking literals
|
|
382
|
+
// nor without saving the last replacement position.
|
|
383
|
+
|
|
384
|
+
bool Checker::propagate () {
|
|
385
|
+
bool res = true;
|
|
386
|
+
while (res && next_to_propagate < trail.size ()) {
|
|
387
|
+
int lit = trail[next_to_propagate++];
|
|
388
|
+
stats.propagations++;
|
|
389
|
+
assert (val (lit) > 0);
|
|
390
|
+
assert (abs (lit) < size_vars);
|
|
391
|
+
CheckerWatcher &ws = watcher (-lit);
|
|
392
|
+
const auto end = ws.end ();
|
|
393
|
+
auto j = ws.begin (), i = j;
|
|
394
|
+
for (; res && i != end; i++) {
|
|
395
|
+
CheckerWatch &w = *j++ = *i;
|
|
396
|
+
const int blit = w.blit;
|
|
397
|
+
assert (blit != -lit);
|
|
398
|
+
const signed char blit_val = val (blit);
|
|
399
|
+
if (blit_val > 0)
|
|
400
|
+
continue;
|
|
401
|
+
const unsigned size = w.size;
|
|
402
|
+
if (size == 2) { // not precise since
|
|
403
|
+
if (blit_val < 0)
|
|
404
|
+
res = false; // clause might be garbage
|
|
405
|
+
else
|
|
406
|
+
assign (w.blit); // but still sound
|
|
407
|
+
} else {
|
|
408
|
+
assert (size > 2);
|
|
409
|
+
CheckerClause *c = w.clause;
|
|
410
|
+
if (!c->size) {
|
|
411
|
+
j--;
|
|
412
|
+
continue;
|
|
413
|
+
} // skip garbage clauses
|
|
414
|
+
assert (size == c->size);
|
|
415
|
+
int *lits = c->literals;
|
|
416
|
+
int other = lits[0] ^ lits[1] ^ (-lit);
|
|
417
|
+
assert (other != -lit);
|
|
418
|
+
signed char other_val = val (other);
|
|
419
|
+
if (other_val > 0) {
|
|
420
|
+
j[-1].blit = other;
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
lits[0] = other, lits[1] = -lit;
|
|
424
|
+
unsigned k;
|
|
425
|
+
int replacement = 0;
|
|
426
|
+
signed char replacement_val = -1;
|
|
427
|
+
for (k = 2; k < size; k++)
|
|
428
|
+
if ((replacement_val = val (replacement = lits[k])) >= 0)
|
|
429
|
+
break;
|
|
430
|
+
if (replacement_val >= 0) {
|
|
431
|
+
watcher (replacement).push_back (CheckerWatch (-lit, c));
|
|
432
|
+
swap (lits[1], lits[k]);
|
|
433
|
+
j--;
|
|
434
|
+
} else if (!other_val)
|
|
435
|
+
assign (other);
|
|
436
|
+
else
|
|
437
|
+
res = false;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
while (i != end)
|
|
441
|
+
*j++ = *i++;
|
|
442
|
+
ws.resize (j - ws.begin ());
|
|
443
|
+
}
|
|
444
|
+
return res;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
bool Checker::check () {
|
|
448
|
+
stats.checks++;
|
|
449
|
+
if (inconsistent)
|
|
450
|
+
return true;
|
|
451
|
+
unsigned previously_propagated = next_to_propagate;
|
|
452
|
+
for (const auto &lit : simplified)
|
|
453
|
+
assume (-lit);
|
|
454
|
+
bool res = !propagate ();
|
|
455
|
+
backtrack (previously_propagated);
|
|
456
|
+
return res;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
bool Checker::check_blocked () {
|
|
460
|
+
for (const auto &lit : unsimplified) {
|
|
461
|
+
mark (-lit) = true;
|
|
462
|
+
}
|
|
463
|
+
vector<int> not_blocked;
|
|
464
|
+
for (size_t i = 0; i < size_clauses; i++) {
|
|
465
|
+
for (CheckerClause *c = clauses[i], *next; c; c = next) {
|
|
466
|
+
next = c->next;
|
|
467
|
+
unsigned count = 0;
|
|
468
|
+
int first;
|
|
469
|
+
for (int *i = c->literals; i < c->literals + c->size; i++) {
|
|
470
|
+
const int lit = *i;
|
|
471
|
+
if (val (lit) > 0) {
|
|
472
|
+
LOG (c->literals, c->size, "satisfied clause");
|
|
473
|
+
count = 2;
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
if (mark (lit)) {
|
|
477
|
+
count++;
|
|
478
|
+
LOG (c->literals, c->size, "clause");
|
|
479
|
+
first = lit;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
if (count == 1)
|
|
483
|
+
not_blocked.push_back (first);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
for (const auto &lit : not_blocked) {
|
|
487
|
+
mark (lit) = false;
|
|
488
|
+
}
|
|
489
|
+
bool blocked = false;
|
|
490
|
+
for (const auto &lit : unsimplified) {
|
|
491
|
+
if (mark (-lit))
|
|
492
|
+
blocked = true;
|
|
493
|
+
mark (-lit) = false;
|
|
494
|
+
}
|
|
495
|
+
return blocked;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/*------------------------------------------------------------------------*/
|
|
499
|
+
|
|
500
|
+
void Checker::add_clause (const char *type) {
|
|
501
|
+
#ifndef LOGGING
|
|
502
|
+
(void) type;
|
|
503
|
+
#endif
|
|
504
|
+
|
|
505
|
+
// If there are enough garbage clauses collect them first.
|
|
506
|
+
if (num_garbage > 0.5 * max ((size_t) size_clauses, (size_t) size_vars))
|
|
507
|
+
collect_garbage_clauses ();
|
|
508
|
+
|
|
509
|
+
int unit = 0;
|
|
510
|
+
for (const auto &lit : simplified) {
|
|
511
|
+
const signed char tmp = val (lit);
|
|
512
|
+
if (tmp < 0)
|
|
513
|
+
continue;
|
|
514
|
+
assert (!tmp);
|
|
515
|
+
if (unit) {
|
|
516
|
+
unit = INT_MIN;
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
unit = lit;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (simplified.empty ()) {
|
|
523
|
+
LOG ("CHECKER added empty %s clause", type);
|
|
524
|
+
inconsistent = true;
|
|
525
|
+
}
|
|
526
|
+
if (!unit) {
|
|
527
|
+
LOG ("CHECKER added and checked falsified %s clause", type);
|
|
528
|
+
inconsistent = true;
|
|
529
|
+
} else if (unit != INT_MIN) {
|
|
530
|
+
LOG ("CHECKER added and checked %s unit clause %d", type, unit);
|
|
531
|
+
assign (unit);
|
|
532
|
+
stats.units++;
|
|
533
|
+
if (!propagate ()) {
|
|
534
|
+
LOG ("CHECKER inconsistent after propagating %s unit", type);
|
|
535
|
+
inconsistent = true;
|
|
536
|
+
}
|
|
537
|
+
} else
|
|
538
|
+
insert ();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
void Checker::add_original_clause (int64_t id, bool, const vector<int> &c,
|
|
542
|
+
bool) {
|
|
543
|
+
if (inconsistent)
|
|
544
|
+
return;
|
|
545
|
+
START (checking);
|
|
546
|
+
LOG (c, "CHECKER addition of original clause");
|
|
547
|
+
stats.added++;
|
|
548
|
+
stats.original++;
|
|
549
|
+
import_clause (c);
|
|
550
|
+
last_id = id;
|
|
551
|
+
if (tautological ())
|
|
552
|
+
LOG ("CHECKER ignoring satisfied original clause");
|
|
553
|
+
else
|
|
554
|
+
add_clause ("original");
|
|
555
|
+
simplified.clear ();
|
|
556
|
+
unsimplified.clear ();
|
|
557
|
+
STOP (checking);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
void Checker::add_derived_clause (int64_t id, bool, int,
|
|
561
|
+
const vector<int> &c,
|
|
562
|
+
const vector<int64_t> &) {
|
|
563
|
+
if (inconsistent)
|
|
564
|
+
return;
|
|
565
|
+
START (checking);
|
|
566
|
+
LOG (c, "CHECKER addition of derived clause");
|
|
567
|
+
stats.added++;
|
|
568
|
+
stats.derived++;
|
|
569
|
+
import_clause (c);
|
|
570
|
+
last_id = id;
|
|
571
|
+
if (tautological ())
|
|
572
|
+
LOG ("CHECKER ignoring satisfied derived clause");
|
|
573
|
+
else if (!check () && !check_blocked ()) { // needed for ER proof support
|
|
574
|
+
fatal_message_start ();
|
|
575
|
+
fputs ("failed to check derived clause:\n", stderr);
|
|
576
|
+
for (const auto &lit : unsimplified)
|
|
577
|
+
fprintf (stderr, "%d ", lit);
|
|
578
|
+
fputc ('0', stderr);
|
|
579
|
+
fatal_message_end ();
|
|
580
|
+
} else
|
|
581
|
+
add_clause ("derived");
|
|
582
|
+
simplified.clear ();
|
|
583
|
+
unsimplified.clear ();
|
|
584
|
+
STOP (checking);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/*------------------------------------------------------------------------*/
|
|
588
|
+
|
|
589
|
+
void Checker::delete_clause (int64_t id, bool, const vector<int> &c) {
|
|
590
|
+
if (inconsistent)
|
|
591
|
+
return;
|
|
592
|
+
START (checking);
|
|
593
|
+
LOG (c, "CHECKER checking deletion of clause");
|
|
594
|
+
stats.deleted++;
|
|
595
|
+
simplified.clear (); // Can be non-empty if clause allocation fails.
|
|
596
|
+
unsimplified.clear (); // Can be non-empty if clause allocation fails.
|
|
597
|
+
import_clause (c);
|
|
598
|
+
last_id = id;
|
|
599
|
+
if (!tautological ()) {
|
|
600
|
+
CheckerClause **p = find (), *d = *p;
|
|
601
|
+
if (d) {
|
|
602
|
+
assert (d->size > 1);
|
|
603
|
+
// Remove from hash table, mark as garbage, connect to garbage list.
|
|
604
|
+
num_garbage++;
|
|
605
|
+
assert (num_clauses);
|
|
606
|
+
num_clauses--;
|
|
607
|
+
*p = d->next;
|
|
608
|
+
d->next = garbage;
|
|
609
|
+
garbage = d;
|
|
610
|
+
d->size = 0;
|
|
611
|
+
} else {
|
|
612
|
+
fatal_message_start ();
|
|
613
|
+
fputs ("deleted clause not in proof:\n", stderr);
|
|
614
|
+
for (const auto &lit : unsimplified)
|
|
615
|
+
fprintf (stderr, "%d ", lit);
|
|
616
|
+
fputc ('0', stderr);
|
|
617
|
+
fatal_message_end ();
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
simplified.clear ();
|
|
621
|
+
unsimplified.clear ();
|
|
622
|
+
STOP (checking);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
void Checker::add_assumption_clause (int64_t id, const vector<int> &c,
|
|
626
|
+
const vector<int64_t> &chain) {
|
|
627
|
+
add_derived_clause (id, true, 0, c, chain);
|
|
628
|
+
delete_clause (id, true, c);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/*------------------------------------------------------------------------*/
|
|
632
|
+
|
|
633
|
+
void Checker::dump () {
|
|
634
|
+
int max_var = 0;
|
|
635
|
+
for (uint64_t i = 0; i < size_clauses; i++)
|
|
636
|
+
for (CheckerClause *c = clauses[i]; c; c = c->next)
|
|
637
|
+
for (unsigned i = 0; i < c->size; i++)
|
|
638
|
+
if (abs (c->literals[i]) > max_var)
|
|
639
|
+
max_var = abs (c->literals[i]);
|
|
640
|
+
printf ("p cnf %d %" PRIu64 "\n", max_var, num_clauses);
|
|
641
|
+
for (uint64_t i = 0; i < size_clauses; i++)
|
|
642
|
+
for (CheckerClause *c = clauses[i]; c; c = c->next) {
|
|
643
|
+
for (unsigned i = 0; i < c->size; i++)
|
|
644
|
+
printf ("%d ", c->literals[i]);
|
|
645
|
+
printf ("0\n");
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
} // namespace CaDiCaL
|