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,545 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
// Returns the positive number '1' ( > 0) if the given clause is root level
|
|
8
|
+
// satisfied or the negative number '-1' ( < 0) if it is not root level
|
|
9
|
+
// satisfied but contains a root level falsified literal. Otherwise, if it
|
|
10
|
+
// contains neither a satisfied nor falsified literal, then '0' is returned.
|
|
11
|
+
|
|
12
|
+
int Internal::clause_contains_fixed_literal (Clause *c) {
|
|
13
|
+
int satisfied = 0, falsified = 0;
|
|
14
|
+
for (const auto &lit : *c) {
|
|
15
|
+
const int tmp = fixed (lit);
|
|
16
|
+
if (tmp > 0) {
|
|
17
|
+
LOG (c, "root level satisfied literal %d in", lit);
|
|
18
|
+
satisfied++;
|
|
19
|
+
}
|
|
20
|
+
if (tmp < 0) {
|
|
21
|
+
LOG (c, "root level falsified literal %d in", lit);
|
|
22
|
+
falsified++;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (satisfied)
|
|
26
|
+
return 1;
|
|
27
|
+
else if (falsified)
|
|
28
|
+
return -1;
|
|
29
|
+
else
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Assume that the clause is not root level satisfied but contains a literal
|
|
34
|
+
// set to false (root level falsified literal), so it can be shrunken. The
|
|
35
|
+
// clause data is not actually reallocated at this point to avoid dealing
|
|
36
|
+
// with issues of special policies for watching binary clauses or whether a
|
|
37
|
+
// clause is extended or not. Only its size field is adjusted accordingly
|
|
38
|
+
// after flushing out root level falsified literals.
|
|
39
|
+
|
|
40
|
+
void Internal::remove_falsified_literals (Clause *c) {
|
|
41
|
+
const const_literal_iterator end = c->end ();
|
|
42
|
+
const_literal_iterator i;
|
|
43
|
+
int num_non_false = 0;
|
|
44
|
+
for (i = c->begin (); num_non_false < 2 && i != end; i++)
|
|
45
|
+
if (fixed (*i) >= 0)
|
|
46
|
+
num_non_false++;
|
|
47
|
+
if (num_non_false < 2)
|
|
48
|
+
return;
|
|
49
|
+
if (proof) {
|
|
50
|
+
// Flush changes the clause id, external forgettables need to be
|
|
51
|
+
// marked here (or the new id could be used instead of old one)
|
|
52
|
+
if (opts.check && is_external_forgettable (c->id))
|
|
53
|
+
mark_garbage_external_forgettable (c->id);
|
|
54
|
+
proof->flush_clause (c);
|
|
55
|
+
}
|
|
56
|
+
literal_iterator j = c->begin ();
|
|
57
|
+
for (i = j; i != end; i++) {
|
|
58
|
+
const int lit = *j++ = *i, tmp = fixed (lit);
|
|
59
|
+
assert (tmp <= 0);
|
|
60
|
+
if (tmp >= 0)
|
|
61
|
+
continue;
|
|
62
|
+
LOG ("flushing %d", lit);
|
|
63
|
+
j--;
|
|
64
|
+
}
|
|
65
|
+
stats.collected += shrink_clause (c, j - c->begin ());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// If there are new units (fixed variables) since the last garbage
|
|
69
|
+
// collection we go over all clauses, mark satisfied ones as garbage and
|
|
70
|
+
// flush falsified literals. Otherwise if no new units have been generated
|
|
71
|
+
// since the last garbage collection just skip this step.
|
|
72
|
+
|
|
73
|
+
void Internal::mark_satisfied_clauses_as_garbage () {
|
|
74
|
+
|
|
75
|
+
if (last.collect.fixed >= stats.all.fixed)
|
|
76
|
+
return;
|
|
77
|
+
last.collect.fixed = stats.all.fixed;
|
|
78
|
+
|
|
79
|
+
LOG ("marking satisfied clauses and removing falsified literals");
|
|
80
|
+
|
|
81
|
+
for (const auto &c : clauses) {
|
|
82
|
+
if (c->garbage)
|
|
83
|
+
continue;
|
|
84
|
+
const int tmp = clause_contains_fixed_literal (c);
|
|
85
|
+
if (tmp > 0)
|
|
86
|
+
mark_garbage (c);
|
|
87
|
+
else if (tmp < 0)
|
|
88
|
+
remove_falsified_literals (c);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/*------------------------------------------------------------------------*/
|
|
93
|
+
|
|
94
|
+
// Reason clauses can not be collected.
|
|
95
|
+
//
|
|
96
|
+
// We protect reasons before and release protection after garbage collection
|
|
97
|
+
// (actually within garbage collection).
|
|
98
|
+
//
|
|
99
|
+
// For 'reduce' we still need to make sure that all clauses which should not
|
|
100
|
+
// be removed are marked as such and thus we need to call it before marking
|
|
101
|
+
// clauses to be flushed.
|
|
102
|
+
|
|
103
|
+
void Internal::protect_reasons () {
|
|
104
|
+
LOG ("protecting reason clauses of all assigned variables on trail");
|
|
105
|
+
assert (!protected_reasons);
|
|
106
|
+
#ifdef LOGGING
|
|
107
|
+
size_t count = 0;
|
|
108
|
+
#endif
|
|
109
|
+
for (const auto &lit : trail) {
|
|
110
|
+
if (!active (lit))
|
|
111
|
+
continue;
|
|
112
|
+
assert (val (lit));
|
|
113
|
+
Var &v = var (lit);
|
|
114
|
+
assert (v.level > 0);
|
|
115
|
+
Clause *reason = v.reason;
|
|
116
|
+
if (!reason)
|
|
117
|
+
continue;
|
|
118
|
+
if (reason == external_reason)
|
|
119
|
+
continue;
|
|
120
|
+
LOG (reason, "protecting assigned %d reason %p", lit, (void *) reason);
|
|
121
|
+
assert (!reason->reason);
|
|
122
|
+
reason->reason = true;
|
|
123
|
+
#ifdef LOGGING
|
|
124
|
+
count++;
|
|
125
|
+
#endif
|
|
126
|
+
}
|
|
127
|
+
LOG ("protected %zd reason clauses referenced on trail", count);
|
|
128
|
+
protected_reasons = true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*------------------------------------------------------------------------*/
|
|
132
|
+
|
|
133
|
+
// After garbage collection we reset the 'reason' flag of the reasons
|
|
134
|
+
// of assigned literals on the trail.
|
|
135
|
+
|
|
136
|
+
void Internal::unprotect_reasons () {
|
|
137
|
+
LOG ("unprotecting reasons clauses of all assigned variables on trail");
|
|
138
|
+
assert (protected_reasons);
|
|
139
|
+
#ifdef LOGGING
|
|
140
|
+
size_t count = 0;
|
|
141
|
+
#endif
|
|
142
|
+
for (const auto &lit : trail) {
|
|
143
|
+
if (!active (lit))
|
|
144
|
+
continue;
|
|
145
|
+
assert (val (lit));
|
|
146
|
+
Var &v = var (lit);
|
|
147
|
+
assert (v.level > 0);
|
|
148
|
+
Clause *reason = v.reason;
|
|
149
|
+
if (!reason)
|
|
150
|
+
continue;
|
|
151
|
+
if (reason == external_reason)
|
|
152
|
+
continue;
|
|
153
|
+
LOG (reason, "unprotecting assigned %d reason %p", lit,
|
|
154
|
+
(void *) reason);
|
|
155
|
+
assert (reason->reason);
|
|
156
|
+
reason->reason = false;
|
|
157
|
+
#ifdef LOGGING
|
|
158
|
+
count++;
|
|
159
|
+
#endif
|
|
160
|
+
}
|
|
161
|
+
LOG ("unprotected %zd reason clauses referenced on trail", count);
|
|
162
|
+
protected_reasons = false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/*------------------------------------------------------------------------*/
|
|
166
|
+
|
|
167
|
+
// Update occurrence lists before deleting garbage clauses in the context of
|
|
168
|
+
// preprocessing, e.g., during bounded variable elimination 'elim'. The
|
|
169
|
+
// result is the number of remaining clauses, which in this context means
|
|
170
|
+
// the number of non-garbage clauses.
|
|
171
|
+
|
|
172
|
+
size_t Internal::flush_occs (int lit) {
|
|
173
|
+
Occs &os = occs (lit);
|
|
174
|
+
const const_occs_iterator end = os.end ();
|
|
175
|
+
occs_iterator j = os.begin ();
|
|
176
|
+
const_occs_iterator i;
|
|
177
|
+
size_t res = 0;
|
|
178
|
+
Clause *c;
|
|
179
|
+
for (i = j; i != end; i++) {
|
|
180
|
+
c = *i;
|
|
181
|
+
if (c->collect ())
|
|
182
|
+
continue;
|
|
183
|
+
*j++ = c->moved ? c->copy : c;
|
|
184
|
+
// assert (!c->redundant); // -> not true in sweeping
|
|
185
|
+
res++;
|
|
186
|
+
}
|
|
187
|
+
os.resize (j - os.begin ());
|
|
188
|
+
shrink_occs (os);
|
|
189
|
+
return res;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Update watch lists before deleting garbage clauses in the context of
|
|
193
|
+
// 'reduce' where we watch and no occurrence lists. We have to protect
|
|
194
|
+
// reason clauses not be collected and thus we have this additional check
|
|
195
|
+
// hidden in 'Clause.collect', which for the root level context of
|
|
196
|
+
// preprocessing is actually redundant.
|
|
197
|
+
|
|
198
|
+
inline void Internal::flush_watches (int lit, Watches &saved) {
|
|
199
|
+
assert (saved.empty ());
|
|
200
|
+
Watches &ws = watches (lit);
|
|
201
|
+
const const_watch_iterator end = ws.end ();
|
|
202
|
+
watch_iterator j = ws.begin ();
|
|
203
|
+
const_watch_iterator i;
|
|
204
|
+
for (i = j; i != end; i++) {
|
|
205
|
+
Watch w = *i;
|
|
206
|
+
Clause *c = w.clause;
|
|
207
|
+
if (c->collect ())
|
|
208
|
+
continue;
|
|
209
|
+
if (c->moved)
|
|
210
|
+
c = w.clause = c->copy;
|
|
211
|
+
w.size = c->size;
|
|
212
|
+
const int new_blit_pos = (c->literals[0] == lit);
|
|
213
|
+
LOG (c, "clause in flush_watch starting from %d", lit);
|
|
214
|
+
assert (c->literals[!new_blit_pos] == lit); /*FW1*/
|
|
215
|
+
w.blit = c->literals[new_blit_pos];
|
|
216
|
+
if (w.binary ())
|
|
217
|
+
*j++ = w;
|
|
218
|
+
else
|
|
219
|
+
saved.push_back (w);
|
|
220
|
+
}
|
|
221
|
+
ws.resize (j - ws.begin ());
|
|
222
|
+
for (const auto &w : saved)
|
|
223
|
+
ws.push_back (w);
|
|
224
|
+
saved.clear ();
|
|
225
|
+
shrink_vector (ws);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
void Internal::flush_all_occs_and_watches () {
|
|
229
|
+
if (occurring ())
|
|
230
|
+
for (auto idx : vars)
|
|
231
|
+
flush_occs (idx), flush_occs (-idx);
|
|
232
|
+
|
|
233
|
+
if (watching ()) {
|
|
234
|
+
Watches tmp;
|
|
235
|
+
for (auto idx : vars)
|
|
236
|
+
flush_watches (idx, tmp), flush_watches (-idx, tmp);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/*------------------------------------------------------------------------*/
|
|
241
|
+
|
|
242
|
+
void Internal::update_reason_references () {
|
|
243
|
+
LOG ("update assigned reason references");
|
|
244
|
+
#ifdef LOGGING
|
|
245
|
+
size_t count = 0;
|
|
246
|
+
#endif
|
|
247
|
+
for (auto &lit : trail) {
|
|
248
|
+
if (!active (lit))
|
|
249
|
+
continue;
|
|
250
|
+
Var &v = var (lit);
|
|
251
|
+
Clause *c = v.reason;
|
|
252
|
+
if (!c)
|
|
253
|
+
continue;
|
|
254
|
+
if (c == external_reason)
|
|
255
|
+
continue;
|
|
256
|
+
LOG (c, "updating assigned %d reason", lit);
|
|
257
|
+
assert (c->reason);
|
|
258
|
+
assert (c->moved);
|
|
259
|
+
Clause *d = c->copy;
|
|
260
|
+
v.reason = d;
|
|
261
|
+
#ifdef LOGGING
|
|
262
|
+
count++;
|
|
263
|
+
#endif
|
|
264
|
+
}
|
|
265
|
+
LOG ("updated %zd assigned reason references", count);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/*------------------------------------------------------------------------*/
|
|
269
|
+
|
|
270
|
+
// This is a simple garbage collector which does not move clauses. It needs
|
|
271
|
+
// less space than the arena based clause allocator, but is not as cache
|
|
272
|
+
// efficient, since the copying garbage collector can put clauses together
|
|
273
|
+
// which are likely accessed after each other.
|
|
274
|
+
|
|
275
|
+
void Internal::delete_garbage_clauses () {
|
|
276
|
+
|
|
277
|
+
flush_all_occs_and_watches ();
|
|
278
|
+
|
|
279
|
+
LOG ("deleting garbage clauses");
|
|
280
|
+
#ifndef QUIET
|
|
281
|
+
int64_t collected_bytes = 0, collected_clauses = 0;
|
|
282
|
+
#endif
|
|
283
|
+
const auto end = clauses.end ();
|
|
284
|
+
auto j = clauses.begin (), i = j;
|
|
285
|
+
while (i != end) {
|
|
286
|
+
Clause *c = *j++ = *i++;
|
|
287
|
+
if (!c->collect ())
|
|
288
|
+
continue;
|
|
289
|
+
#ifndef QUIET
|
|
290
|
+
collected_bytes += c->bytes ();
|
|
291
|
+
collected_clauses++;
|
|
292
|
+
#endif
|
|
293
|
+
delete_clause (c);
|
|
294
|
+
j--;
|
|
295
|
+
}
|
|
296
|
+
clauses.resize (j - clauses.begin ());
|
|
297
|
+
shrink_vector (clauses);
|
|
298
|
+
|
|
299
|
+
PHASE ("collect", stats.collections,
|
|
300
|
+
"collected %" PRId64 " bytes of %" PRId64 " garbage clauses",
|
|
301
|
+
collected_bytes, collected_clauses);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/*------------------------------------------------------------------------*/
|
|
305
|
+
|
|
306
|
+
// This is the start of the copying garbage collector using the arena. At
|
|
307
|
+
// the core is the following function, which copies a clause to the 'to'
|
|
308
|
+
// space of the arena. Be careful if this clause is a reason of an
|
|
309
|
+
// assignment. In that case update the reason reference.
|
|
310
|
+
//
|
|
311
|
+
void Internal::copy_clause (Clause *c) {
|
|
312
|
+
LOG (c, "moving");
|
|
313
|
+
assert (!c->moved);
|
|
314
|
+
char *p = (char *) c;
|
|
315
|
+
char *q = arena.copy (p, c->bytes ());
|
|
316
|
+
c->copy = (Clause *) q;
|
|
317
|
+
c->moved = true;
|
|
318
|
+
LOG ("copied clause[%" PRId64 "] from %p to %p", c->id, (void *) c,
|
|
319
|
+
(void *) c->copy);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// This is the moving garbage collector.
|
|
323
|
+
|
|
324
|
+
void Internal::copy_non_garbage_clauses () {
|
|
325
|
+
|
|
326
|
+
size_t collected_clauses = 0, collected_bytes = 0;
|
|
327
|
+
size_t moved_clauses = 0, moved_bytes = 0;
|
|
328
|
+
|
|
329
|
+
// First determine 'moved_bytes' and 'collected_bytes'.
|
|
330
|
+
//
|
|
331
|
+
for (const auto &c : clauses)
|
|
332
|
+
if (!c->collect ())
|
|
333
|
+
moved_bytes += c->bytes (), moved_clauses++;
|
|
334
|
+
else
|
|
335
|
+
collected_bytes += c->bytes (), collected_clauses++;
|
|
336
|
+
|
|
337
|
+
PHASE ("collect", stats.collections,
|
|
338
|
+
"moving %zd bytes %.0f%% of %zd non garbage clauses", moved_bytes,
|
|
339
|
+
percent (moved_bytes, collected_bytes + moved_bytes),
|
|
340
|
+
moved_clauses);
|
|
341
|
+
(void) moved_clauses, (void) collected_clauses, (void) collected_bytes;
|
|
342
|
+
// Prepare 'to' space of size 'moved_bytes'.
|
|
343
|
+
//
|
|
344
|
+
arena.prepare (moved_bytes);
|
|
345
|
+
|
|
346
|
+
// Keep clauses in arena in the same order.
|
|
347
|
+
//
|
|
348
|
+
if (opts.arenacompact)
|
|
349
|
+
for (const auto &c : clauses)
|
|
350
|
+
if (!c->collect () && arena.contains (c))
|
|
351
|
+
copy_clause (c);
|
|
352
|
+
|
|
353
|
+
if (opts.arenatype == 1 || !watching ()) {
|
|
354
|
+
|
|
355
|
+
// Localize according to current clause order.
|
|
356
|
+
|
|
357
|
+
// If the option 'opts.arenatype == 1' is set, then this means the
|
|
358
|
+
// solver uses the original order of clauses. If there are no watches,
|
|
359
|
+
// we can not use the watched based copying policies below. This
|
|
360
|
+
// happens if garbage collection is triggered during bounded variable
|
|
361
|
+
// elimination.
|
|
362
|
+
|
|
363
|
+
// Copy clauses according to the order of calling 'copy_clause', which
|
|
364
|
+
// in essence just gives a compacting garbage collector, since their
|
|
365
|
+
// relative order is kept, and actually already gives the largest
|
|
366
|
+
// benefit due to better cache locality.
|
|
367
|
+
|
|
368
|
+
for (const auto &c : clauses)
|
|
369
|
+
if (!c->moved && !c->collect ())
|
|
370
|
+
copy_clause (c);
|
|
371
|
+
|
|
372
|
+
} else if (opts.arenatype == 2) {
|
|
373
|
+
|
|
374
|
+
// Localize according to (original) variable order.
|
|
375
|
+
|
|
376
|
+
// This is almost the version used by MiniSAT and descendants.
|
|
377
|
+
// Our version uses saved phases too.
|
|
378
|
+
|
|
379
|
+
for (int sign = -1; sign <= 1; sign += 2)
|
|
380
|
+
for (auto idx : vars)
|
|
381
|
+
for (const auto &w : watches (sign * likely_phase (idx)))
|
|
382
|
+
if (!w.clause->moved && !w.clause->collect ())
|
|
383
|
+
copy_clause (w.clause);
|
|
384
|
+
|
|
385
|
+
} else {
|
|
386
|
+
|
|
387
|
+
// Localize according to decision queue order.
|
|
388
|
+
|
|
389
|
+
// This is the default for search. It allocates clauses in the order of
|
|
390
|
+
// the decision queue and also uses saved phases. It seems faster than
|
|
391
|
+
// the MiniSAT version and thus we keep 'opts.arenatype == 3'.
|
|
392
|
+
|
|
393
|
+
assert (opts.arenatype == 3);
|
|
394
|
+
|
|
395
|
+
for (int sign = -1; sign <= 1; sign += 2)
|
|
396
|
+
for (int idx = queue.last; idx; idx = link (idx).prev)
|
|
397
|
+
for (const auto &w : watches (sign * likely_phase (idx)))
|
|
398
|
+
if (!w.clause->moved && !w.clause->collect ())
|
|
399
|
+
copy_clause (w.clause);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Do not forget to move clauses which are not watched, which happened in
|
|
403
|
+
// a rare situation, and now is only left as defensive code.
|
|
404
|
+
//
|
|
405
|
+
for (const auto &c : clauses)
|
|
406
|
+
if (!c->collect () && !c->moved)
|
|
407
|
+
copy_clause (c);
|
|
408
|
+
|
|
409
|
+
flush_all_occs_and_watches ();
|
|
410
|
+
update_reason_references ();
|
|
411
|
+
|
|
412
|
+
// Replace and flush clause references in 'clauses'.
|
|
413
|
+
//
|
|
414
|
+
const auto end = clauses.end ();
|
|
415
|
+
auto j = clauses.begin (), i = j;
|
|
416
|
+
for (; i != end; i++) {
|
|
417
|
+
Clause *c = *i;
|
|
418
|
+
if (c->collect ())
|
|
419
|
+
delete_clause (c);
|
|
420
|
+
else
|
|
421
|
+
assert (c->moved), *j++ = c->copy, deallocate_clause (c);
|
|
422
|
+
}
|
|
423
|
+
clauses.resize (j - clauses.begin ());
|
|
424
|
+
if (clauses.size () < clauses.capacity () / 2)
|
|
425
|
+
shrink_vector (clauses);
|
|
426
|
+
|
|
427
|
+
if (opts.arenasort)
|
|
428
|
+
rsort (clauses.begin (), clauses.end (), pointer_rank ());
|
|
429
|
+
|
|
430
|
+
// Release 'from' space completely and then swap 'to' with 'from'.
|
|
431
|
+
//
|
|
432
|
+
arena.swap ();
|
|
433
|
+
|
|
434
|
+
PHASE ("collect", stats.collections,
|
|
435
|
+
"collected %zd bytes %.0f%% of %zd garbage clauses",
|
|
436
|
+
collected_bytes,
|
|
437
|
+
percent (collected_bytes, collected_bytes + moved_bytes),
|
|
438
|
+
collected_clauses);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/*------------------------------------------------------------------------*/
|
|
442
|
+
|
|
443
|
+
// Maintaining clause statistics is complex and error prone but necessary
|
|
444
|
+
// for proper scheduling of garbage collection, particularly during bounded
|
|
445
|
+
// variable elimination. With this function we can check whether these
|
|
446
|
+
// statistics are updated correctly.
|
|
447
|
+
|
|
448
|
+
void Internal::check_clause_stats () {
|
|
449
|
+
#ifndef NDEBUG
|
|
450
|
+
int64_t irredundant = 0, redundant = 0, total = 0, irrlits = 0;
|
|
451
|
+
for (const auto &c : clauses) {
|
|
452
|
+
if (c->garbage)
|
|
453
|
+
continue;
|
|
454
|
+
if (c->redundant)
|
|
455
|
+
redundant++;
|
|
456
|
+
else
|
|
457
|
+
irredundant++;
|
|
458
|
+
if (!c->redundant)
|
|
459
|
+
irrlits += c->size;
|
|
460
|
+
total++;
|
|
461
|
+
}
|
|
462
|
+
assert (stats.current.irredundant == irredundant);
|
|
463
|
+
assert (stats.current.redundant == redundant);
|
|
464
|
+
assert (stats.current.total == total);
|
|
465
|
+
assert (stats.irrlits == irrlits);
|
|
466
|
+
#endif
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/*------------------------------------------------------------------------*/
|
|
470
|
+
|
|
471
|
+
// only delete binary clauses from watch list that are already mark as
|
|
472
|
+
// deleted.
|
|
473
|
+
void Internal::remove_garbage_binaries () {
|
|
474
|
+
if (unsat)
|
|
475
|
+
return;
|
|
476
|
+
START (collect);
|
|
477
|
+
|
|
478
|
+
if (!protected_reasons)
|
|
479
|
+
protect_reasons ();
|
|
480
|
+
int backtrack_level = level + 1;
|
|
481
|
+
Watches saved;
|
|
482
|
+
for (auto v : vars) {
|
|
483
|
+
for (auto lit : {-v, v}) {
|
|
484
|
+
assert (saved.empty ());
|
|
485
|
+
Watches &ws = watches (lit);
|
|
486
|
+
const const_watch_iterator end = ws.end ();
|
|
487
|
+
watch_iterator j = ws.begin ();
|
|
488
|
+
const_watch_iterator i;
|
|
489
|
+
for (i = j; i != end; i++) {
|
|
490
|
+
Watch w = *i;
|
|
491
|
+
*j++ = w;
|
|
492
|
+
Clause *c = w.clause;
|
|
493
|
+
COVER (!w.binary () && c->size == 2);
|
|
494
|
+
if (!w.binary ())
|
|
495
|
+
continue;
|
|
496
|
+
if (c->reason && c->garbage) {
|
|
497
|
+
COVER (true);
|
|
498
|
+
assert (c->size == 2);
|
|
499
|
+
backtrack_level =
|
|
500
|
+
min (backtrack_level, var (c->literals[0]).level);
|
|
501
|
+
LOG ("need to backtrack to before level %d", backtrack_level);
|
|
502
|
+
--j;
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
if (!c->collect ())
|
|
506
|
+
continue;
|
|
507
|
+
LOG (c, "removing from watch list");
|
|
508
|
+
--j;
|
|
509
|
+
}
|
|
510
|
+
ws.resize (j - ws.begin ());
|
|
511
|
+
shrink_vector (ws);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
delete_garbage_clauses ();
|
|
515
|
+
unprotect_reasons ();
|
|
516
|
+
if (backtrack_level - 1 < level)
|
|
517
|
+
backtrack (backtrack_level - 1);
|
|
518
|
+
STOP (collect);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/*------------------------------------------------------------------------*/
|
|
522
|
+
|
|
523
|
+
bool Internal::arenaing () { return opts.arena && (stats.collections > 1); }
|
|
524
|
+
|
|
525
|
+
void Internal::garbage_collection () {
|
|
526
|
+
if (unsat)
|
|
527
|
+
return;
|
|
528
|
+
START (collect);
|
|
529
|
+
report ('G', 1);
|
|
530
|
+
stats.collections++;
|
|
531
|
+
mark_satisfied_clauses_as_garbage ();
|
|
532
|
+
if (!protected_reasons)
|
|
533
|
+
protect_reasons ();
|
|
534
|
+
if (arenaing ())
|
|
535
|
+
copy_non_garbage_clauses ();
|
|
536
|
+
else
|
|
537
|
+
delete_garbage_clauses ();
|
|
538
|
+
check_clause_stats ();
|
|
539
|
+
check_var_stats ();
|
|
540
|
+
unprotect_reasons ();
|
|
541
|
+
report ('C', 1);
|
|
542
|
+
STOP (collect);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
} // namespace CaDiCaL
|