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,689 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
// Signed marking or unmarking of a clause or the global 'clause'.
|
|
8
|
+
|
|
9
|
+
void Internal::mark (Clause *c) {
|
|
10
|
+
for (const auto &lit : *c)
|
|
11
|
+
mark (lit);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
void Internal::mark2 (Clause *c) {
|
|
15
|
+
for (const auto &lit : *c)
|
|
16
|
+
mark2 (lit);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void Internal::unmark (Clause *c) {
|
|
20
|
+
for (const auto &lit : *c)
|
|
21
|
+
unmark (lit);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void Internal::mark_clause () {
|
|
25
|
+
for (const auto &lit : clause)
|
|
26
|
+
mark (lit);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void Internal::unmark_clause () {
|
|
30
|
+
for (const auto &lit : clause)
|
|
31
|
+
unmark (lit);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*------------------------------------------------------------------------*/
|
|
35
|
+
|
|
36
|
+
// Mark the variables of an irredundant clause to 'have been removed', which
|
|
37
|
+
// will trigger these variables to be considered again in the next bounded
|
|
38
|
+
// variable elimination phase. This is called from 'mark_garbage' below.
|
|
39
|
+
// Note that 'mark_removed (int lit)' will also mark the blocking flag of
|
|
40
|
+
// '-lit' to trigger reconsidering blocking clauses on '-lit'.
|
|
41
|
+
|
|
42
|
+
void Internal::mark_removed (Clause *c, int except) {
|
|
43
|
+
LOG (c, "marking removed");
|
|
44
|
+
assert (!c->redundant);
|
|
45
|
+
for (const auto &lit : *c)
|
|
46
|
+
if (lit != except)
|
|
47
|
+
mark_removed (lit);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Mark the variables of a (redundant or irredundant) clause to 'have been
|
|
51
|
+
// added', which triggers clauses with such a variables, to be considered
|
|
52
|
+
// both as a subsumed or subsuming clause in the next subsumption phase.
|
|
53
|
+
// This function is called from 'new_clause' below as well as in situations
|
|
54
|
+
// where a clause is shrunken (and thus needs to be at least considered
|
|
55
|
+
// again to subsume a larger clause). We also use this to tell
|
|
56
|
+
// 'ternary' preprocessing reconsider clauses on an added literal as well as
|
|
57
|
+
// trying to block clauses on it.
|
|
58
|
+
|
|
59
|
+
inline void Internal::mark_added (int lit, int size, bool redundant) {
|
|
60
|
+
mark_subsume (lit);
|
|
61
|
+
if (size == 3)
|
|
62
|
+
mark_ternary (lit);
|
|
63
|
+
if (!redundant)
|
|
64
|
+
mark_block (lit);
|
|
65
|
+
if ((!redundant || size == 2))
|
|
66
|
+
mark_factor (lit);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
void Internal::mark_added (Clause *c) {
|
|
70
|
+
LOG (c, "marking added");
|
|
71
|
+
assert (likely_to_be_kept_clause (c));
|
|
72
|
+
for (const auto &lit : *c)
|
|
73
|
+
mark_added (lit, c->size, c->redundant);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*------------------------------------------------------------------------*/
|
|
77
|
+
|
|
78
|
+
Clause *Internal::new_clause (bool red, int glue) {
|
|
79
|
+
|
|
80
|
+
assert (clause.size () <= (size_t) INT_MAX);
|
|
81
|
+
const int size = (int) clause.size ();
|
|
82
|
+
assert (size >= 2);
|
|
83
|
+
|
|
84
|
+
if (glue > size)
|
|
85
|
+
glue = size;
|
|
86
|
+
|
|
87
|
+
size_t bytes = Clause::bytes (size);
|
|
88
|
+
Clause *c = (Clause *) new char[bytes];
|
|
89
|
+
DeferDeleteArray<char> clause_delete ((char *) c);
|
|
90
|
+
|
|
91
|
+
c->id = ++clause_id;
|
|
92
|
+
|
|
93
|
+
c->conditioned = false;
|
|
94
|
+
c->covered = false;
|
|
95
|
+
c->enqueued = false;
|
|
96
|
+
c->frozen = false;
|
|
97
|
+
c->garbage = false;
|
|
98
|
+
c->gate = false;
|
|
99
|
+
c->hyper = false;
|
|
100
|
+
c->instantiated = false;
|
|
101
|
+
c->moved = false;
|
|
102
|
+
c->reason = false;
|
|
103
|
+
c->redundant = red;
|
|
104
|
+
c->transred = false;
|
|
105
|
+
c->subsume = false;
|
|
106
|
+
c->swept = false;
|
|
107
|
+
c->flushed = false;
|
|
108
|
+
c->vivified = false;
|
|
109
|
+
c->vivify = false;
|
|
110
|
+
c->used = 0;
|
|
111
|
+
|
|
112
|
+
c->glue = glue;
|
|
113
|
+
c->size = size;
|
|
114
|
+
c->pos = 2;
|
|
115
|
+
|
|
116
|
+
for (int i = 0; i < size; i++)
|
|
117
|
+
c->literals[i] = clause[i];
|
|
118
|
+
|
|
119
|
+
// Just checking that we did not mess up our sophisticated memory layout.
|
|
120
|
+
// This might be compiler dependent though. Crucial for correctness.
|
|
121
|
+
//
|
|
122
|
+
assert (c->bytes () == bytes);
|
|
123
|
+
|
|
124
|
+
stats.current.total++;
|
|
125
|
+
stats.added.total++;
|
|
126
|
+
|
|
127
|
+
if (red) {
|
|
128
|
+
stats.current.redundant++;
|
|
129
|
+
stats.added.redundant++;
|
|
130
|
+
} else {
|
|
131
|
+
stats.irrlits += size;
|
|
132
|
+
stats.current.irredundant++;
|
|
133
|
+
stats.added.irredundant++;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
clauses.push_back (c);
|
|
137
|
+
clause_delete.release ();
|
|
138
|
+
LOG (c, "new pointer %p", (void *) c);
|
|
139
|
+
|
|
140
|
+
if (likely_to_be_kept_clause (c))
|
|
141
|
+
mark_added (c);
|
|
142
|
+
|
|
143
|
+
return c;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/*------------------------------------------------------------------------*/
|
|
147
|
+
|
|
148
|
+
void Internal::promote_clause (Clause *c, int new_glue) {
|
|
149
|
+
assert (c->redundant);
|
|
150
|
+
assert (new_glue);
|
|
151
|
+
const int tier1limit = tier1[false];
|
|
152
|
+
const int tier2limit = max (tier1limit, tier2[false]);
|
|
153
|
+
if (!c->redundant)
|
|
154
|
+
return;
|
|
155
|
+
if (c->hyper)
|
|
156
|
+
return;
|
|
157
|
+
int old_glue = c->glue;
|
|
158
|
+
if (new_glue >= old_glue)
|
|
159
|
+
return;
|
|
160
|
+
c->used = max_used;
|
|
161
|
+
if (old_glue > tier1limit && new_glue <= tier1limit) {
|
|
162
|
+
LOG (c, "promoting with new glue %d to tier1", new_glue);
|
|
163
|
+
stats.promoted1++;
|
|
164
|
+
} else if (old_glue > tier2limit && new_glue <= tier2limit) {
|
|
165
|
+
LOG (c, "promoting with new glue %d to tier2", new_glue);
|
|
166
|
+
stats.promoted2++;
|
|
167
|
+
} else if (old_glue <= tier2limit)
|
|
168
|
+
LOG (c, "keeping with new glue %d in tier2", new_glue);
|
|
169
|
+
else
|
|
170
|
+
LOG (c, "keeping with new glue %d in tier3", new_glue);
|
|
171
|
+
stats.improvedglue++;
|
|
172
|
+
c->glue = new_glue;
|
|
173
|
+
}
|
|
174
|
+
/*------------------------------------------------------------------------*/
|
|
175
|
+
|
|
176
|
+
void Internal::promote_clause_glue_only (Clause *c, int new_glue) {
|
|
177
|
+
assert (c->redundant);
|
|
178
|
+
assert (new_glue);
|
|
179
|
+
if (c->hyper)
|
|
180
|
+
return;
|
|
181
|
+
int old_glue = c->glue;
|
|
182
|
+
const int tier1limit = tier1[false];
|
|
183
|
+
const int tier2limit = max (tier1limit, tier2[false]);
|
|
184
|
+
if (new_glue >= old_glue)
|
|
185
|
+
return;
|
|
186
|
+
if (new_glue <= tier1limit) {
|
|
187
|
+
LOG (c, "promoting with new glue %d to tier1", new_glue);
|
|
188
|
+
stats.promoted1++;
|
|
189
|
+
} else if (old_glue > tier2limit && new_glue <= tier2limit) {
|
|
190
|
+
LOG (c, "promoting with new glue %d to tier2", new_glue);
|
|
191
|
+
stats.promoted2++;
|
|
192
|
+
} else if (old_glue <= tier2limit)
|
|
193
|
+
LOG (c, "keeping with new glue %d in tier2", new_glue);
|
|
194
|
+
else
|
|
195
|
+
LOG (c, "keeping with new glue %d in tier3", new_glue);
|
|
196
|
+
stats.improvedglue++;
|
|
197
|
+
c->glue = new_glue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/*------------------------------------------------------------------------*/
|
|
201
|
+
|
|
202
|
+
// Shrinking a clause, e.g., removing one or more literals, requires to fix
|
|
203
|
+
// the 'pos' field, if it exists and points after the new last literal. We
|
|
204
|
+
// also have adjust the global statistics counter of irredundant literals
|
|
205
|
+
// for irredundant clauses, and also adjust the glue value of redundant
|
|
206
|
+
// clauses if the size becomes smaller than the glue. Also mark the
|
|
207
|
+
// literals in the resulting clause as 'added'. The result is the number of
|
|
208
|
+
// (aligned) removed bytes, resulting from shrinking the clause.
|
|
209
|
+
//
|
|
210
|
+
size_t Internal::shrink_clause (Clause *c, int new_size) {
|
|
211
|
+
if (opts.check && is_external_forgettable (c->id))
|
|
212
|
+
mark_garbage_external_forgettable (c->id);
|
|
213
|
+
assert (new_size >= 2);
|
|
214
|
+
int old_size = c->size;
|
|
215
|
+
assert (new_size < old_size);
|
|
216
|
+
#ifndef NDEBUG
|
|
217
|
+
for (int i = c->size; i < new_size; i++)
|
|
218
|
+
c->literals[i] = 0;
|
|
219
|
+
#endif
|
|
220
|
+
|
|
221
|
+
if (c->pos >= new_size)
|
|
222
|
+
c->pos = 2;
|
|
223
|
+
|
|
224
|
+
size_t old_bytes = c->bytes ();
|
|
225
|
+
c->size = new_size;
|
|
226
|
+
size_t new_bytes = c->bytes ();
|
|
227
|
+
size_t res = old_bytes - new_bytes;
|
|
228
|
+
|
|
229
|
+
if (c->redundant)
|
|
230
|
+
promote_clause_glue_only (c, min (c->size - 1, c->glue));
|
|
231
|
+
else {
|
|
232
|
+
int delta_size = old_size - new_size;
|
|
233
|
+
assert (stats.irrlits >= delta_size);
|
|
234
|
+
stats.irrlits -= delta_size;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (likely_to_be_kept_clause (c))
|
|
238
|
+
mark_added (c);
|
|
239
|
+
|
|
240
|
+
return res;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// This is the 'raw' deallocation of a clause. If the clause is in the
|
|
244
|
+
// arena nothing happens. If the clause is not in the arena its memory is
|
|
245
|
+
// reclaimed immediately.
|
|
246
|
+
|
|
247
|
+
void Internal::deallocate_clause (Clause *c) {
|
|
248
|
+
char *p = (char *) c;
|
|
249
|
+
if (arena.contains (p))
|
|
250
|
+
return;
|
|
251
|
+
LOG (c, "deallocate pointer %p", (void *) c);
|
|
252
|
+
delete[] p;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
void Internal::delete_clause (Clause *c) {
|
|
256
|
+
LOG (c, "delete pointer %p", (void *) c);
|
|
257
|
+
size_t bytes = c->bytes ();
|
|
258
|
+
stats.collected += bytes;
|
|
259
|
+
if (c->garbage) {
|
|
260
|
+
assert (stats.garbage.bytes >= (int64_t) bytes);
|
|
261
|
+
stats.garbage.bytes -= bytes;
|
|
262
|
+
assert (stats.garbage.clauses > 0);
|
|
263
|
+
stats.garbage.clauses--;
|
|
264
|
+
assert (stats.garbage.literals >= c->size);
|
|
265
|
+
stats.garbage.literals -= c->size;
|
|
266
|
+
|
|
267
|
+
// See the discussion in 'propagate' on avoiding to eagerly trace binary
|
|
268
|
+
// clauses as deleted (produce 'd ...' lines) as soon they are marked
|
|
269
|
+
// garbage. We avoid this and only trace them as deleted when they are
|
|
270
|
+
// actually deleted here. This allows the solver to propagate binary
|
|
271
|
+
// garbage clauses without producing incorrect 'd' lines. The effect
|
|
272
|
+
// from the proof perspective is that the deletion of these binary
|
|
273
|
+
// clauses occurs later in the proof file.
|
|
274
|
+
//
|
|
275
|
+
if (proof && c->size == 2 && !c->flushed) {
|
|
276
|
+
proof->delete_clause (c);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
deallocate_clause (c);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// We want to eagerly update statistics as soon clauses are marked garbage.
|
|
283
|
+
// Otherwise 'report' for instance gives wrong numbers after 'subsume'
|
|
284
|
+
// before the next 'reduce'. Thus we factored out marking and accounting
|
|
285
|
+
// for garbage clauses.
|
|
286
|
+
//
|
|
287
|
+
// Eagerly deleting clauses instead is problematic, since references to
|
|
288
|
+
// these clauses need to be flushed, which is too costly to do eagerly.
|
|
289
|
+
//
|
|
290
|
+
// We also update garbage statistics at this point. This helps to
|
|
291
|
+
// determine whether the garbage collector should be called during for
|
|
292
|
+
// instance bounded variable elimination, which usually generates lots of
|
|
293
|
+
// garbage clauses.
|
|
294
|
+
//
|
|
295
|
+
// In order not to miss any update to these clause statistics we call
|
|
296
|
+
// 'check_clause_stats' after garbage collection in debugging mode.
|
|
297
|
+
//
|
|
298
|
+
void Internal::mark_garbage (Clause *c) {
|
|
299
|
+
|
|
300
|
+
assert (!c->garbage);
|
|
301
|
+
|
|
302
|
+
// Delay tracing deletion of binary clauses. See the discussion above in
|
|
303
|
+
// 'delete_clause' and also in 'propagate'.
|
|
304
|
+
//
|
|
305
|
+
if (proof && (c->size != 2 || !watching ())) {
|
|
306
|
+
c->flushed = true;
|
|
307
|
+
proof->delete_clause (c);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Because of the internal model checking, external forgettable clauses
|
|
311
|
+
// must be marked as removed already upon mark_garbage, can not wait until
|
|
312
|
+
// actual deletion.
|
|
313
|
+
if (opts.check && is_external_forgettable (c->id))
|
|
314
|
+
mark_garbage_external_forgettable (c->id);
|
|
315
|
+
|
|
316
|
+
assert (stats.current.total > 0);
|
|
317
|
+
stats.current.total--;
|
|
318
|
+
|
|
319
|
+
size_t bytes = c->bytes ();
|
|
320
|
+
if (c->redundant) {
|
|
321
|
+
assert (stats.current.redundant > 0);
|
|
322
|
+
stats.current.redundant--;
|
|
323
|
+
} else {
|
|
324
|
+
assert (stats.current.irredundant > 0);
|
|
325
|
+
stats.current.irredundant--;
|
|
326
|
+
assert (stats.irrlits >= c->size);
|
|
327
|
+
stats.irrlits -= c->size;
|
|
328
|
+
mark_removed (c);
|
|
329
|
+
}
|
|
330
|
+
stats.garbage.bytes += bytes;
|
|
331
|
+
stats.garbage.clauses++;
|
|
332
|
+
stats.garbage.literals += c->size;
|
|
333
|
+
c->garbage = true;
|
|
334
|
+
c->used = 0;
|
|
335
|
+
|
|
336
|
+
LOG (c, "marked garbage pointer %p", (void *) c);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/*------------------------------------------------------------------------*/
|
|
340
|
+
|
|
341
|
+
// Almost the same function as 'search_assign' except that we do not pretend
|
|
342
|
+
// to learn a new unit clause (which was confusing in log files).
|
|
343
|
+
|
|
344
|
+
void Internal::assign_original_unit (int64_t id, int lit) {
|
|
345
|
+
assert (!level || opts.chrono);
|
|
346
|
+
assert (!unsat);
|
|
347
|
+
const int idx = vidx (lit);
|
|
348
|
+
assert (!vals[idx]);
|
|
349
|
+
assert (!flags (idx).eliminated ());
|
|
350
|
+
Var &v = var (idx);
|
|
351
|
+
v.level = 0;
|
|
352
|
+
v.trail = (int) trail.size ();
|
|
353
|
+
v.reason = 0;
|
|
354
|
+
const signed char tmp = sign (lit);
|
|
355
|
+
set_val (idx, tmp);
|
|
356
|
+
trail.push_back (lit);
|
|
357
|
+
num_assigned++;
|
|
358
|
+
const unsigned uidx = vlit (lit);
|
|
359
|
+
if (lrat || frat)
|
|
360
|
+
unit_clauses (uidx) = id;
|
|
361
|
+
LOG ("original unit assign %d", lit);
|
|
362
|
+
assert (num_assigned == trail.size () || level);
|
|
363
|
+
mark_fixed (lit);
|
|
364
|
+
if (level)
|
|
365
|
+
return;
|
|
366
|
+
if (propagate ())
|
|
367
|
+
return;
|
|
368
|
+
assert (conflict);
|
|
369
|
+
LOG ("propagation of original unit results in conflict");
|
|
370
|
+
learn_empty_clause ();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// New clause added through the API, e.g., while parsing a DIMACS file.
|
|
374
|
+
// Also used by external_propagate in various different modes.
|
|
375
|
+
// clause, original, lrat_chain and external->eclause are set.
|
|
376
|
+
// from_propagator and force_no_backtrack change the behaviour.
|
|
377
|
+
// sometimes the pointer to the new clause is needed, therefore it is
|
|
378
|
+
// made sure that newest_clause points to the new clause upon return.
|
|
379
|
+
|
|
380
|
+
void Internal::add_new_original_clause (int64_t id) {
|
|
381
|
+
|
|
382
|
+
if (!from_propagator && level && !opts.ilb) {
|
|
383
|
+
backtrack ();
|
|
384
|
+
} else if (changed_val) {
|
|
385
|
+
assert (val (changed_val));
|
|
386
|
+
int new_level = var (changed_val).level - 1;
|
|
387
|
+
assert (new_level >= 0);
|
|
388
|
+
backtrack (new_level);
|
|
389
|
+
}
|
|
390
|
+
assert (!changed_val);
|
|
391
|
+
LOG (original, "original clause");
|
|
392
|
+
assert (clause.empty ());
|
|
393
|
+
bool skip = false;
|
|
394
|
+
unordered_set<int> learned_levels;
|
|
395
|
+
size_t unassigned = 0;
|
|
396
|
+
newest_clause = 0;
|
|
397
|
+
if (unsat) {
|
|
398
|
+
LOG ("skipping clause since formula is already inconsistent");
|
|
399
|
+
skip = true;
|
|
400
|
+
} else {
|
|
401
|
+
assert (clause.empty ());
|
|
402
|
+
for (const auto &lit : original) {
|
|
403
|
+
int tmp = marked (lit);
|
|
404
|
+
if (tmp > 0) {
|
|
405
|
+
LOG ("removing duplicated literal %d", lit);
|
|
406
|
+
} else if (tmp < 0) {
|
|
407
|
+
LOG ("tautological since both %d and %d occur", -lit, lit);
|
|
408
|
+
skip = true;
|
|
409
|
+
} else {
|
|
410
|
+
mark (lit);
|
|
411
|
+
tmp = fixed (lit);
|
|
412
|
+
if (tmp < 0) {
|
|
413
|
+
LOG ("removing falsified literal %d", lit);
|
|
414
|
+
if (lrat) {
|
|
415
|
+
int elit = externalize (lit);
|
|
416
|
+
unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
|
|
417
|
+
if (!external->ext_units[eidx]) {
|
|
418
|
+
int64_t uid = unit_id (-lit);
|
|
419
|
+
lrat_chain.push_back (uid);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
} else if (tmp > 0) {
|
|
423
|
+
LOG ("satisfied since literal %d true", lit);
|
|
424
|
+
skip = true;
|
|
425
|
+
} else {
|
|
426
|
+
clause.push_back (lit);
|
|
427
|
+
assert (flags (lit).status != Flags::UNUSED);
|
|
428
|
+
tmp = val (lit);
|
|
429
|
+
if (tmp)
|
|
430
|
+
learned_levels.insert (var (lit).level);
|
|
431
|
+
else
|
|
432
|
+
unassigned++;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
for (const auto &lit : original)
|
|
437
|
+
unmark (lit);
|
|
438
|
+
}
|
|
439
|
+
if (skip) {
|
|
440
|
+
if (from_propagator) {
|
|
441
|
+
stats.ext_prop.elearn_conf++;
|
|
442
|
+
|
|
443
|
+
// In case it was a skipped external forgettable, we need to mark it
|
|
444
|
+
// immediately as removed
|
|
445
|
+
|
|
446
|
+
if (opts.check && is_external_forgettable (id))
|
|
447
|
+
mark_garbage_external_forgettable (id);
|
|
448
|
+
}
|
|
449
|
+
if (proof) {
|
|
450
|
+
proof->delete_external_original_clause (id, false, external->eclause);
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
int64_t new_id = id;
|
|
454
|
+
const size_t size = clause.size ();
|
|
455
|
+
if (original.size () > size) {
|
|
456
|
+
new_id = ++clause_id;
|
|
457
|
+
if (proof) {
|
|
458
|
+
if (lrat)
|
|
459
|
+
lrat_chain.push_back (id);
|
|
460
|
+
proof->add_derived_clause (new_id, false, clause, lrat_chain);
|
|
461
|
+
proof->delete_external_original_clause (id, false,
|
|
462
|
+
external->eclause);
|
|
463
|
+
}
|
|
464
|
+
external->check_learned_clause ();
|
|
465
|
+
|
|
466
|
+
if (from_propagator) {
|
|
467
|
+
// The original form of the added clause is immediately forgotten
|
|
468
|
+
// TODO: shall we save and check the simplified form? (one with
|
|
469
|
+
// new_id)
|
|
470
|
+
if (opts.check && is_external_forgettable (id))
|
|
471
|
+
mark_garbage_external_forgettable (id);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
external->eclause.clear ();
|
|
475
|
+
lrat_chain.clear ();
|
|
476
|
+
if (!size) {
|
|
477
|
+
if (from_propagator)
|
|
478
|
+
stats.ext_prop.elearn_conf++;
|
|
479
|
+
assert (!unsat);
|
|
480
|
+
if (!original.size ())
|
|
481
|
+
VERBOSE (1, "found empty original clause");
|
|
482
|
+
else
|
|
483
|
+
VERBOSE (1, "found falsified original clause");
|
|
484
|
+
unsat = true;
|
|
485
|
+
conflict_id = new_id;
|
|
486
|
+
marked_failed = true;
|
|
487
|
+
conclusion.push_back (new_id);
|
|
488
|
+
} else if (size == 1) {
|
|
489
|
+
if (force_no_backtrack) {
|
|
490
|
+
assert (level);
|
|
491
|
+
const int idx = vidx (clause[0]);
|
|
492
|
+
assert (val (clause[0]) >= 0);
|
|
493
|
+
assert (!flags (idx).eliminated ());
|
|
494
|
+
Var &v = var (idx);
|
|
495
|
+
assert (val (clause[0]));
|
|
496
|
+
v.level = 0;
|
|
497
|
+
v.reason = 0;
|
|
498
|
+
did_external_prop = true;
|
|
499
|
+
const unsigned uidx = vlit (clause[0]);
|
|
500
|
+
if (lrat || frat)
|
|
501
|
+
unit_clauses (uidx) = new_id;
|
|
502
|
+
mark_fixed (clause[0]);
|
|
503
|
+
} else {
|
|
504
|
+
const int lit = clause[0];
|
|
505
|
+
assert (!val (lit) || var (lit).level);
|
|
506
|
+
if (val (lit) < 0)
|
|
507
|
+
backtrack (var (lit).level - 1);
|
|
508
|
+
assert (val (lit) >= 0);
|
|
509
|
+
handle_external_clause (0);
|
|
510
|
+
assign_original_unit (new_id, lit);
|
|
511
|
+
}
|
|
512
|
+
} else {
|
|
513
|
+
move_literals_to_watch ();
|
|
514
|
+
#ifndef NDEBUG
|
|
515
|
+
check_watched_literal_invariants ();
|
|
516
|
+
#endif
|
|
517
|
+
int glue = (int) (learned_levels.size () + unassigned);
|
|
518
|
+
assert (glue <= (int) clause.size ());
|
|
519
|
+
bool clause_redundancy = from_propagator && ext_clause_forgettable;
|
|
520
|
+
Clause *c = new_clause (clause_redundancy, glue);
|
|
521
|
+
c->id = new_id;
|
|
522
|
+
clause_id--;
|
|
523
|
+
watch_clause (c);
|
|
524
|
+
clause.clear ();
|
|
525
|
+
original.clear ();
|
|
526
|
+
handle_external_clause (c);
|
|
527
|
+
newest_clause = c;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
clause.clear ();
|
|
531
|
+
lrat_chain.clear ();
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Add learned new clause during conflict analysis and watch it. Requires
|
|
535
|
+
// that the clause is at least of size 2, and the first two literals
|
|
536
|
+
// are assigned at the highest decision level.
|
|
537
|
+
//
|
|
538
|
+
Clause *Internal::new_learned_redundant_clause (int glue) {
|
|
539
|
+
assert (clause.size () > 1);
|
|
540
|
+
#ifndef NDEBUG
|
|
541
|
+
for (size_t i = 2; i < clause.size (); i++)
|
|
542
|
+
assert (var (clause[0]).level >= var (clause[i]).level),
|
|
543
|
+
assert (var (clause[1]).level >= var (clause[i]).level);
|
|
544
|
+
#endif
|
|
545
|
+
external->check_learned_clause ();
|
|
546
|
+
Clause *res = new_clause (true, glue);
|
|
547
|
+
if (proof) {
|
|
548
|
+
proof->add_derived_clause (res, lrat_chain);
|
|
549
|
+
}
|
|
550
|
+
assert (watching ());
|
|
551
|
+
watch_clause (res);
|
|
552
|
+
return res;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Add hyper binary resolved clause during 'probing'.
|
|
556
|
+
//
|
|
557
|
+
Clause *Internal::new_hyper_binary_resolved_clause (bool red, int glue) {
|
|
558
|
+
external->check_learned_clause ();
|
|
559
|
+
Clause *res = new_clause (red, glue);
|
|
560
|
+
if (proof) {
|
|
561
|
+
proof->add_derived_clause (res, lrat_chain);
|
|
562
|
+
}
|
|
563
|
+
assert (watching ());
|
|
564
|
+
watch_clause (res);
|
|
565
|
+
return res;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Add hyper ternary resolved clause during 'ternary'.
|
|
569
|
+
//
|
|
570
|
+
Clause *Internal::new_hyper_ternary_resolved_clause (bool red) {
|
|
571
|
+
external->check_learned_clause ();
|
|
572
|
+
size_t size = clause.size ();
|
|
573
|
+
Clause *res = new_clause (red, size);
|
|
574
|
+
if (proof) {
|
|
575
|
+
proof->add_derived_clause (res, lrat_chain);
|
|
576
|
+
}
|
|
577
|
+
assert (!watching ());
|
|
578
|
+
return res;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
Clause *Internal::new_factor_clause (int witness) {
|
|
582
|
+
external->check_learned_clause ();
|
|
583
|
+
stats.factor_added++;
|
|
584
|
+
stats.literals_factored += clause.size ();
|
|
585
|
+
Clause *res = new_clause (false, 0);
|
|
586
|
+
if (proof) {
|
|
587
|
+
if (witness)
|
|
588
|
+
proof->add_derived_rat_clause (res, externalize (witness),
|
|
589
|
+
lrat_chain);
|
|
590
|
+
else
|
|
591
|
+
proof->add_derived_clause (res, lrat_chain);
|
|
592
|
+
}
|
|
593
|
+
assert (!watching ());
|
|
594
|
+
assert (occurring ());
|
|
595
|
+
for (const auto &lit : *res) {
|
|
596
|
+
occs (lit).push_back (res);
|
|
597
|
+
}
|
|
598
|
+
return res;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Add hyper ternary resolved clause during 'congruence' and watch it
|
|
602
|
+
//
|
|
603
|
+
Clause *
|
|
604
|
+
Internal::new_hyper_ternary_resolved_clause_and_watch (bool red,
|
|
605
|
+
bool full_watching) {
|
|
606
|
+
external->check_learned_clause ();
|
|
607
|
+
size_t size = clause.size ();
|
|
608
|
+
Clause *res = new_clause (red, size);
|
|
609
|
+
if (proof) {
|
|
610
|
+
proof->add_derived_clause (res, lrat_chain);
|
|
611
|
+
}
|
|
612
|
+
if (full_watching) {
|
|
613
|
+
assert (watching ());
|
|
614
|
+
watch_clause (res);
|
|
615
|
+
}
|
|
616
|
+
return res;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Add a new clause with same glue and redundancy as 'orig' but literals are
|
|
620
|
+
// assumed to be in 'clause' in 'decompose' and 'vivify'.
|
|
621
|
+
//
|
|
622
|
+
Clause *Internal::new_clause_as (const Clause *orig) {
|
|
623
|
+
external->check_learned_clause ();
|
|
624
|
+
const int new_glue = orig->glue;
|
|
625
|
+
Clause *res = new_clause (orig->redundant, new_glue);
|
|
626
|
+
if (proof) {
|
|
627
|
+
proof->add_derived_clause (res, lrat_chain);
|
|
628
|
+
}
|
|
629
|
+
assert (watching ());
|
|
630
|
+
watch_clause (res);
|
|
631
|
+
return res;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Add resolved clause during resolution, e.g., bounded variable
|
|
635
|
+
// elimination, but do not connect its occurrences here.
|
|
636
|
+
//
|
|
637
|
+
Clause *Internal::new_resolved_irredundant_clause () {
|
|
638
|
+
external->check_learned_clause ();
|
|
639
|
+
if (proof) {
|
|
640
|
+
proof->add_derived_clause (clause_id + 1, false, clause, lrat_chain);
|
|
641
|
+
}
|
|
642
|
+
Clause *res = new_clause (false);
|
|
643
|
+
assert (!watching ());
|
|
644
|
+
return res;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
void Internal::decay_clauses_upon_incremental_clauses () {
|
|
648
|
+
if (!opts.incdecay)
|
|
649
|
+
return;
|
|
650
|
+
if (!stats.searches)
|
|
651
|
+
return;
|
|
652
|
+
if (stats.conflicts < lim.incremental_decay)
|
|
653
|
+
return;
|
|
654
|
+
|
|
655
|
+
PHASE ("decay", stats.incremental_decay,
|
|
656
|
+
"decaying clauses with next decaying at conflict %" PRId64
|
|
657
|
+
"(after the next incremental call)",
|
|
658
|
+
lim.incremental_decay);
|
|
659
|
+
|
|
660
|
+
for (auto c : clauses) {
|
|
661
|
+
if (c->garbage)
|
|
662
|
+
continue;
|
|
663
|
+
if (!c->redundant)
|
|
664
|
+
continue;
|
|
665
|
+
if (c->id >= last.incremental_decay.last_id)
|
|
666
|
+
continue;
|
|
667
|
+
switch (opts.incdecay) {
|
|
668
|
+
case 1: // my intuition
|
|
669
|
+
++c->glue;
|
|
670
|
+
break;
|
|
671
|
+
case 2: // Armin's idea
|
|
672
|
+
if (c->glue < tier1[false])
|
|
673
|
+
c->used = 1;
|
|
674
|
+
break;
|
|
675
|
+
case 3:
|
|
676
|
+
if (c->glue < tier1[false])
|
|
677
|
+
c->used = 1;
|
|
678
|
+
++c->glue;
|
|
679
|
+
break;
|
|
680
|
+
default:
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
lim.incremental_decay += stats.conflicts + opts.incdecayint;
|
|
686
|
+
++stats.incremental_decay;
|
|
687
|
+
last.incremental_decay.last_id = clause_id;
|
|
688
|
+
}
|
|
689
|
+
} // namespace CaDiCaL
|