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,616 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
#include "options.hpp"
|
|
3
|
+
|
|
4
|
+
namespace CaDiCaL {
|
|
5
|
+
|
|
6
|
+
// Failed literal handling as pioneered by MiniSAT. This first function
|
|
7
|
+
// adds an assumption literal onto the assumption stack.
|
|
8
|
+
|
|
9
|
+
void Internal::assume (int lit) {
|
|
10
|
+
if (level && !opts.ilb)
|
|
11
|
+
backtrack ();
|
|
12
|
+
else if (val (lit) < 0)
|
|
13
|
+
backtrack (max (0, var (lit).level - 1));
|
|
14
|
+
Flags &f = flags (lit);
|
|
15
|
+
const unsigned char bit = bign (lit);
|
|
16
|
+
if (f.assumed & bit) {
|
|
17
|
+
LOG ("ignoring already assumed %d", lit);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
LOG ("assume %d", lit);
|
|
21
|
+
f.assumed |= bit;
|
|
22
|
+
assumptions.push_back (lit);
|
|
23
|
+
freeze (lit);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// for LRAT we actually need to implement recursive DFS
|
|
27
|
+
// for non-lrat use BFS. TODO: maybe derecursify to avoid stack overflow
|
|
28
|
+
//
|
|
29
|
+
void Internal::assume_analyze_literal (int lit) {
|
|
30
|
+
assert (lit);
|
|
31
|
+
Flags &f = flags (lit);
|
|
32
|
+
if (f.seen)
|
|
33
|
+
return;
|
|
34
|
+
f.seen = true;
|
|
35
|
+
analyzed.push_back (lit);
|
|
36
|
+
Var &v = var (lit);
|
|
37
|
+
assert (val (lit) < 0);
|
|
38
|
+
if (v.reason == external_reason) {
|
|
39
|
+
v.reason = wrapped_learn_external_reason_clause (-lit);
|
|
40
|
+
assert (v.reason || !v.level);
|
|
41
|
+
}
|
|
42
|
+
assert (v.reason != external_reason);
|
|
43
|
+
if (!v.level) {
|
|
44
|
+
int64_t id = unit_id (-lit);
|
|
45
|
+
lrat_chain.push_back (id);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (v.reason) {
|
|
49
|
+
assert (v.level);
|
|
50
|
+
LOG (v.reason, "analyze reason");
|
|
51
|
+
for (const auto &other : *v.reason) {
|
|
52
|
+
assume_analyze_literal (other);
|
|
53
|
+
}
|
|
54
|
+
lrat_chain.push_back (v.reason->id);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
assert (assumed (-lit));
|
|
58
|
+
LOG ("failed assumption %d", -lit);
|
|
59
|
+
clause.push_back (lit);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void Internal::assume_analyze_reason (int lit, Clause *reason) {
|
|
63
|
+
assert (reason);
|
|
64
|
+
assert (lrat_chain.empty ());
|
|
65
|
+
assert (reason != external_reason);
|
|
66
|
+
assert (lrat);
|
|
67
|
+
for (const auto &other : *reason)
|
|
68
|
+
if (other != lit)
|
|
69
|
+
assume_analyze_literal (other);
|
|
70
|
+
lrat_chain.push_back (reason->id);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Find all failing assumptions starting from the one on the assumption
|
|
74
|
+
// stack with the lowest decision level. This goes back to MiniSAT and is
|
|
75
|
+
// called 'analyze_final' there.
|
|
76
|
+
|
|
77
|
+
void Internal::failing () {
|
|
78
|
+
|
|
79
|
+
START (analyze);
|
|
80
|
+
|
|
81
|
+
LOG ("analyzing failing assumptions");
|
|
82
|
+
|
|
83
|
+
assert (analyzed.empty ());
|
|
84
|
+
assert (clause.empty ());
|
|
85
|
+
assert (lrat_chain.empty ());
|
|
86
|
+
assert (!marked_failed);
|
|
87
|
+
assert (!conflict_id);
|
|
88
|
+
|
|
89
|
+
if (!unsat_constraint) {
|
|
90
|
+
// Search for failing assumptions in the (internal) assumption stack.
|
|
91
|
+
|
|
92
|
+
// There are in essence three cases: (1) An assumption is falsified on
|
|
93
|
+
// the root-level and then 'failed_unit' is set to that assumption, (2)
|
|
94
|
+
// two clashing assumptions are assumed and then 'failed_clashing' is
|
|
95
|
+
// set to the second assumed one, or otherwise (3) there is a failing
|
|
96
|
+
// assumption 'first_failed' with minimum (non-zero) decision level
|
|
97
|
+
// 'failed_level'.
|
|
98
|
+
|
|
99
|
+
int failed_unit = 0;
|
|
100
|
+
int failed_clashing = 0;
|
|
101
|
+
int first_failed = 0;
|
|
102
|
+
int failed_level = INT_MAX;
|
|
103
|
+
int efailed = 0;
|
|
104
|
+
|
|
105
|
+
for (auto &elit : external->assumptions) {
|
|
106
|
+
int lit = external->e2i[abs (elit)];
|
|
107
|
+
if (elit < 0)
|
|
108
|
+
lit = -lit;
|
|
109
|
+
if (val (lit) >= 0)
|
|
110
|
+
continue;
|
|
111
|
+
const Var &v = var (lit);
|
|
112
|
+
if (!v.level) {
|
|
113
|
+
failed_unit = lit;
|
|
114
|
+
efailed = elit;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
if (failed_clashing)
|
|
118
|
+
continue;
|
|
119
|
+
if (v.reason == external_reason) {
|
|
120
|
+
Var &ev = var (lit);
|
|
121
|
+
ev.reason = learn_external_reason_clause (-lit);
|
|
122
|
+
if (!ev.reason) {
|
|
123
|
+
ev.level = 0;
|
|
124
|
+
failed_unit = lit;
|
|
125
|
+
efailed = elit;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
ev.level = 0;
|
|
129
|
+
// Recalculate assignment level
|
|
130
|
+
for (const auto &other : *ev.reason) {
|
|
131
|
+
if (other == -lit)
|
|
132
|
+
continue;
|
|
133
|
+
assert (val (other));
|
|
134
|
+
int tmp = var (other).level;
|
|
135
|
+
if (tmp > ev.level)
|
|
136
|
+
ev.level = tmp;
|
|
137
|
+
}
|
|
138
|
+
if (!ev.level) {
|
|
139
|
+
failed_unit = lit;
|
|
140
|
+
efailed = elit;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
assert (v.reason != external_reason);
|
|
145
|
+
if (!v.reason) {
|
|
146
|
+
failed_clashing = lit;
|
|
147
|
+
efailed = elit;
|
|
148
|
+
} else if (!first_failed || v.level < failed_level) {
|
|
149
|
+
first_failed = lit;
|
|
150
|
+
efailed = elit;
|
|
151
|
+
failed_level = v.level;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
assert (clause.empty ());
|
|
156
|
+
|
|
157
|
+
// Get the 'failed' assumption from one of the three cases.
|
|
158
|
+
int failed;
|
|
159
|
+
if (failed_unit)
|
|
160
|
+
failed = failed_unit;
|
|
161
|
+
else if (failed_clashing)
|
|
162
|
+
failed = failed_clashing;
|
|
163
|
+
else
|
|
164
|
+
failed = first_failed;
|
|
165
|
+
assert (failed);
|
|
166
|
+
assert (efailed);
|
|
167
|
+
|
|
168
|
+
// In any case mark literal 'failed' as failed assumption.
|
|
169
|
+
{
|
|
170
|
+
Flags &f = flags (failed);
|
|
171
|
+
const unsigned bit = bign (failed);
|
|
172
|
+
assert (!(f.failed & bit));
|
|
173
|
+
f.failed |= bit;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// First case (1).
|
|
177
|
+
if (failed_unit) {
|
|
178
|
+
assert (failed == failed_unit);
|
|
179
|
+
LOG ("root-level falsified assumption %d", failed);
|
|
180
|
+
if (proof) {
|
|
181
|
+
if (lrat) {
|
|
182
|
+
unsigned eidx = (efailed > 0) + 2u * (unsigned) abs (efailed);
|
|
183
|
+
assert ((size_t) eidx < external->ext_units.size ());
|
|
184
|
+
const int64_t id = external->ext_units[eidx];
|
|
185
|
+
if (id) {
|
|
186
|
+
lrat_chain.push_back (id);
|
|
187
|
+
} else {
|
|
188
|
+
int64_t id = unit_id (-failed_unit);
|
|
189
|
+
lrat_chain.push_back (id);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
proof->add_assumption_clause (++clause_id, -efailed, lrat_chain);
|
|
193
|
+
conclusion.push_back (clause_id);
|
|
194
|
+
lrat_chain.clear ();
|
|
195
|
+
}
|
|
196
|
+
goto DONE;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Second case (2).
|
|
200
|
+
if (failed_clashing) {
|
|
201
|
+
assert (failed == failed_clashing);
|
|
202
|
+
LOG ("clashing assumptions %d and %d", failed, -failed);
|
|
203
|
+
Flags &f = flags (-failed);
|
|
204
|
+
const unsigned bit = bign (-failed);
|
|
205
|
+
assert (!(f.failed & bit));
|
|
206
|
+
f.failed |= bit;
|
|
207
|
+
if (proof) {
|
|
208
|
+
vector<int> clash = {externalize (failed), externalize (-failed)};
|
|
209
|
+
proof->add_assumption_clause (++clause_id, clash, lrat_chain);
|
|
210
|
+
conclusion.push_back (clause_id);
|
|
211
|
+
}
|
|
212
|
+
goto DONE;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Fall through to third case (3).
|
|
216
|
+
LOG ("starting with assumption %d falsified on minimum decision level "
|
|
217
|
+
"%d",
|
|
218
|
+
first_failed, failed_level);
|
|
219
|
+
|
|
220
|
+
assert (first_failed);
|
|
221
|
+
assert (failed_level > 0);
|
|
222
|
+
|
|
223
|
+
// The 'analyzed' stack serves as working stack for a BFS through the
|
|
224
|
+
// implication graph until decisions, which are all assumptions, or
|
|
225
|
+
// units are reached. This is simpler than corresponding code in
|
|
226
|
+
// 'analyze'.
|
|
227
|
+
{
|
|
228
|
+
LOG ("failed assumption %d", first_failed);
|
|
229
|
+
Flags &f = flags (first_failed);
|
|
230
|
+
assert (!f.seen);
|
|
231
|
+
f.seen = true;
|
|
232
|
+
assert (f.failed & bign (first_failed));
|
|
233
|
+
analyzed.push_back (-first_failed);
|
|
234
|
+
clause.push_back (-first_failed);
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
// unsat_constraint
|
|
238
|
+
// The assumptions necessary to fail each literal in the constraint are
|
|
239
|
+
// collected.
|
|
240
|
+
for (auto lit : constraint) {
|
|
241
|
+
lit *= -1;
|
|
242
|
+
assert (lit != INT_MIN);
|
|
243
|
+
flags (lit).seen = true;
|
|
244
|
+
analyzed.push_back (lit);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
{
|
|
249
|
+
// used for unsat_constraint lrat
|
|
250
|
+
vector<vector<int64_t>> constraint_chains;
|
|
251
|
+
vector<vector<int>> constraint_clauses;
|
|
252
|
+
vector<int> sum_constraints;
|
|
253
|
+
vector<int> econstraints;
|
|
254
|
+
for (auto &elit : external->constraint) {
|
|
255
|
+
int lit = external->e2i[abs (elit)];
|
|
256
|
+
if (elit < 0)
|
|
257
|
+
lit = -lit;
|
|
258
|
+
if (!lit)
|
|
259
|
+
continue;
|
|
260
|
+
Flags &f = flags (lit);
|
|
261
|
+
if (f.seen)
|
|
262
|
+
continue;
|
|
263
|
+
if (std::find (econstraints.begin (), econstraints.end (), elit) !=
|
|
264
|
+
econstraints.end ())
|
|
265
|
+
continue;
|
|
266
|
+
econstraints.push_back (elit);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// no LRAT do bfs as it was before
|
|
270
|
+
if (!lrat) {
|
|
271
|
+
size_t next = 0;
|
|
272
|
+
while (next < analyzed.size ()) {
|
|
273
|
+
const int lit = analyzed[next++];
|
|
274
|
+
assert (val (lit) > 0);
|
|
275
|
+
Var &v = var (lit);
|
|
276
|
+
if (!v.level)
|
|
277
|
+
continue;
|
|
278
|
+
if (v.reason == external_reason) {
|
|
279
|
+
v.reason = wrapped_learn_external_reason_clause (lit);
|
|
280
|
+
if (!v.reason) {
|
|
281
|
+
v.level = 0;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
assert (v.reason != external_reason);
|
|
286
|
+
if (v.reason) {
|
|
287
|
+
assert (v.level);
|
|
288
|
+
LOG (v.reason, "analyze reason");
|
|
289
|
+
for (const auto &other : *v.reason) {
|
|
290
|
+
Flags &f = flags (other);
|
|
291
|
+
if (f.seen)
|
|
292
|
+
continue;
|
|
293
|
+
f.seen = true;
|
|
294
|
+
assert (val (other) < 0);
|
|
295
|
+
analyzed.push_back (-other);
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
assert (assumed (lit));
|
|
299
|
+
LOG ("failed assumption %d", lit);
|
|
300
|
+
clause.push_back (-lit);
|
|
301
|
+
Flags &f = flags (lit);
|
|
302
|
+
const unsigned bit = bign (lit);
|
|
303
|
+
assert (!(f.failed & bit));
|
|
304
|
+
f.failed |= bit;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
clear_analyzed_literals ();
|
|
308
|
+
} else if (!unsat_constraint) { // LRAT for case (3)
|
|
309
|
+
assert (clause.size () == 1);
|
|
310
|
+
const int lit = clause[0];
|
|
311
|
+
Var &v = var (lit);
|
|
312
|
+
assert (v.reason);
|
|
313
|
+
if (v.reason == external_reason) { // does this even happen?
|
|
314
|
+
v.reason = wrapped_learn_external_reason_clause (lit);
|
|
315
|
+
}
|
|
316
|
+
assert (v.reason != external_reason);
|
|
317
|
+
if (v.reason)
|
|
318
|
+
assume_analyze_reason (lit, v.reason);
|
|
319
|
+
else {
|
|
320
|
+
int64_t id = unit_id (lit);
|
|
321
|
+
lrat_chain.push_back (id);
|
|
322
|
+
}
|
|
323
|
+
for (auto &lit : clause) {
|
|
324
|
+
Flags &f = flags (lit);
|
|
325
|
+
const unsigned bit = bign (-lit);
|
|
326
|
+
if (!(f.failed & bit))
|
|
327
|
+
f.failed |= bit;
|
|
328
|
+
}
|
|
329
|
+
clear_analyzed_literals ();
|
|
330
|
+
} else { // LRAT for unsat_constraint
|
|
331
|
+
assert (clause.empty ());
|
|
332
|
+
clear_analyzed_literals ();
|
|
333
|
+
for (auto lit : constraint) {
|
|
334
|
+
// make sure nothing gets marked failed twice
|
|
335
|
+
// also might shortcut the case where
|
|
336
|
+
// lrat_chain is empty because clause is tautological
|
|
337
|
+
assert (lit != INT_MIN);
|
|
338
|
+
assume_analyze_literal (lit);
|
|
339
|
+
vector<int64_t> empty;
|
|
340
|
+
vector<int> empty2;
|
|
341
|
+
constraint_chains.push_back (empty);
|
|
342
|
+
constraint_clauses.push_back (empty2);
|
|
343
|
+
for (auto ign : clause) {
|
|
344
|
+
constraint_clauses.back ().push_back (ign);
|
|
345
|
+
Flags &f = flags (ign);
|
|
346
|
+
const unsigned bit = bign (-ign);
|
|
347
|
+
if (!(f.failed & bit)) {
|
|
348
|
+
sum_constraints.push_back (ign);
|
|
349
|
+
assert (!(f.failed & bit));
|
|
350
|
+
f.failed |= bit;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
clause.clear ();
|
|
354
|
+
clear_analyzed_literals ();
|
|
355
|
+
for (auto p : lrat_chain) {
|
|
356
|
+
constraint_chains.back ().push_back (p);
|
|
357
|
+
}
|
|
358
|
+
lrat_chain.clear ();
|
|
359
|
+
}
|
|
360
|
+
for (auto &lit : sum_constraints)
|
|
361
|
+
clause.push_back (lit);
|
|
362
|
+
}
|
|
363
|
+
clear_analyzed_literals ();
|
|
364
|
+
|
|
365
|
+
// Doing clause minimization here does not do anything because
|
|
366
|
+
// the clause already contains only one literal of each level
|
|
367
|
+
// and minimization can never reduce the number of levels
|
|
368
|
+
|
|
369
|
+
VERBOSE (1, "found %zd failed assumptions %.0f%%", clause.size (),
|
|
370
|
+
percent (clause.size (), assumptions.size ()));
|
|
371
|
+
|
|
372
|
+
// We do not actually need to learn this clause, since the conflict is
|
|
373
|
+
// forced already by some other clauses. There is also no bumping
|
|
374
|
+
// of variables nor clauses necessary. But we still want to check
|
|
375
|
+
// correctness of the claim that the determined subset of failing
|
|
376
|
+
// assumptions are a high-level core or equivalently their negations
|
|
377
|
+
// form a unit-implied clause.
|
|
378
|
+
//
|
|
379
|
+
if (!unsat_constraint) {
|
|
380
|
+
external->check_learned_clause ();
|
|
381
|
+
if (proof) {
|
|
382
|
+
vector<int> eclause;
|
|
383
|
+
for (auto &lit : clause)
|
|
384
|
+
eclause.push_back (externalize (lit));
|
|
385
|
+
proof->add_assumption_clause (++clause_id, eclause, lrat_chain);
|
|
386
|
+
conclusion.push_back (clause_id);
|
|
387
|
+
}
|
|
388
|
+
} else {
|
|
389
|
+
assert (!lrat || (constraint.size () == constraint_clauses.size () &&
|
|
390
|
+
constraint.size () == constraint_chains.size ()));
|
|
391
|
+
for (auto p = constraint.rbegin (); p != constraint.rend (); p++) {
|
|
392
|
+
const auto &lit = *p;
|
|
393
|
+
if (lrat) {
|
|
394
|
+
clause.clear ();
|
|
395
|
+
for (auto &ign : constraint_clauses.back ())
|
|
396
|
+
clause.push_back (ign);
|
|
397
|
+
constraint_clauses.pop_back ();
|
|
398
|
+
}
|
|
399
|
+
clause.push_back (-lit);
|
|
400
|
+
external->check_learned_clause ();
|
|
401
|
+
if (proof) {
|
|
402
|
+
if (lrat) {
|
|
403
|
+
for (auto p : constraint_chains.back ()) {
|
|
404
|
+
lrat_chain.push_back (p);
|
|
405
|
+
}
|
|
406
|
+
constraint_chains.pop_back ();
|
|
407
|
+
LOG (lrat_chain, "assume proof chain with constraints");
|
|
408
|
+
}
|
|
409
|
+
vector<int> eclause;
|
|
410
|
+
for (auto &lit : clause)
|
|
411
|
+
eclause.push_back (externalize (lit));
|
|
412
|
+
proof->add_assumption_clause (++clause_id, eclause, lrat_chain);
|
|
413
|
+
conclusion.push_back (clause_id);
|
|
414
|
+
lrat_chain.clear ();
|
|
415
|
+
}
|
|
416
|
+
clause.pop_back ();
|
|
417
|
+
}
|
|
418
|
+
if (proof) {
|
|
419
|
+
for (auto &elit : econstraints) {
|
|
420
|
+
if (lrat) {
|
|
421
|
+
unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
|
|
422
|
+
assert ((size_t) eidx < external->ext_units.size ());
|
|
423
|
+
const int64_t id = external->ext_units[eidx];
|
|
424
|
+
if (id) {
|
|
425
|
+
lrat_chain.push_back (id);
|
|
426
|
+
} else {
|
|
427
|
+
int lit = external->e2i[abs (elit)];
|
|
428
|
+
if (elit < 0)
|
|
429
|
+
lit = -lit;
|
|
430
|
+
int64_t id = unit_id (-lit);
|
|
431
|
+
lrat_chain.push_back (id);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
proof->add_assumption_clause (++clause_id, -elit, lrat_chain);
|
|
435
|
+
conclusion.push_back (clause_id);
|
|
436
|
+
lrat_chain.clear ();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
lrat_chain.clear ();
|
|
441
|
+
clause.clear ();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
DONE:
|
|
445
|
+
|
|
446
|
+
STOP (analyze);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
bool Internal::failed (int lit) {
|
|
450
|
+
if (!marked_failed) {
|
|
451
|
+
if (!conflict_id)
|
|
452
|
+
failing ();
|
|
453
|
+
marked_failed = true;
|
|
454
|
+
}
|
|
455
|
+
conclude_unsat ();
|
|
456
|
+
Flags &f = flags (lit);
|
|
457
|
+
const unsigned bit = bign (lit);
|
|
458
|
+
return (f.failed & bit) != 0;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
void Internal::conclude_unsat () {
|
|
462
|
+
if (!proof || concluded)
|
|
463
|
+
return;
|
|
464
|
+
concluded = true;
|
|
465
|
+
if (!marked_failed) {
|
|
466
|
+
assert (conclusion.empty ());
|
|
467
|
+
if (!conflict_id)
|
|
468
|
+
failing ();
|
|
469
|
+
marked_failed = true;
|
|
470
|
+
}
|
|
471
|
+
ConclusionType con;
|
|
472
|
+
if (conflict_id)
|
|
473
|
+
con = CONFLICT;
|
|
474
|
+
else if (unsat_constraint)
|
|
475
|
+
con = CONSTRAINT;
|
|
476
|
+
else
|
|
477
|
+
con = ASSUMPTIONS;
|
|
478
|
+
proof->conclude_unsat (con, conclusion);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
void Internal::reset_concluded () {
|
|
482
|
+
if (proof)
|
|
483
|
+
proof->reset_assumptions ();
|
|
484
|
+
if (concluded) {
|
|
485
|
+
LOG ("reset concluded");
|
|
486
|
+
concluded = false;
|
|
487
|
+
}
|
|
488
|
+
if (conflict_id) {
|
|
489
|
+
assert (conclusion.size () == 1);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
conclusion.clear ();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Add the start of each incremental phase (leaving the state
|
|
496
|
+
// 'UNSATISFIABLE' actually) we reset all assumptions.
|
|
497
|
+
|
|
498
|
+
void Internal::reset_assumptions () {
|
|
499
|
+
for (const auto &lit : assumptions) {
|
|
500
|
+
Flags &f = flags (lit);
|
|
501
|
+
const unsigned char bit = bign (lit);
|
|
502
|
+
f.assumed &= ~bit;
|
|
503
|
+
f.failed &= ~bit;
|
|
504
|
+
melt (lit);
|
|
505
|
+
}
|
|
506
|
+
LOG ("cleared %zd assumptions", assumptions.size ());
|
|
507
|
+
assumptions.clear ();
|
|
508
|
+
marked_failed = true;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
struct sort_assumptions_positive_rank {
|
|
512
|
+
Internal *internal;
|
|
513
|
+
|
|
514
|
+
// Decision level could be 'INT_MAX' and thus 'level + 1' could overflow.
|
|
515
|
+
// Therefore we carefully have to use 'unsigned' for levels below.
|
|
516
|
+
|
|
517
|
+
const unsigned max_level;
|
|
518
|
+
|
|
519
|
+
sort_assumptions_positive_rank (Internal *s)
|
|
520
|
+
: internal (s), max_level (s->level + 1u) {}
|
|
521
|
+
|
|
522
|
+
typedef uint64_t Type;
|
|
523
|
+
|
|
524
|
+
// Set assumptions first, then sorted by position on the trail
|
|
525
|
+
// unset literals are sorted by literal value.
|
|
526
|
+
|
|
527
|
+
Type operator() (const int &a) const {
|
|
528
|
+
const int val = internal->val (a);
|
|
529
|
+
const bool assigned = (val != 0);
|
|
530
|
+
const Var &v = internal->var (a);
|
|
531
|
+
uint64_t res = (assigned ? (unsigned) v.level : max_level);
|
|
532
|
+
res <<= 32;
|
|
533
|
+
res |= (assigned ? v.trail : abs (a));
|
|
534
|
+
return res;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
struct sort_assumptions_smaller {
|
|
539
|
+
Internal *internal;
|
|
540
|
+
sort_assumptions_smaller (Internal *s) : internal (s) {}
|
|
541
|
+
bool operator() (const int &a, const int &b) const {
|
|
542
|
+
return sort_assumptions_positive_rank (internal) (a) <
|
|
543
|
+
sort_assumptions_positive_rank (internal) (b);
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// Sort the assumptions by the current position on the trail and backtrack
|
|
548
|
+
// to the first place where the assumptions and the current trail differ.
|
|
549
|
+
|
|
550
|
+
void Internal::sort_and_reuse_assumptions () {
|
|
551
|
+
assert (opts.ilb >= 1);
|
|
552
|
+
if (assumptions.empty ()) {
|
|
553
|
+
if (opts.ilb == 1) {
|
|
554
|
+
LOG ("no assumptions, reusing nothing (ilb == 1)");
|
|
555
|
+
backtrack (0);
|
|
556
|
+
} else { // reuse full trail
|
|
557
|
+
LOG ("no assumptions, reusing everything (ilb == 2)");
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
MSORT (opts.radixsortlim, assumptions.begin (), assumptions.end (),
|
|
562
|
+
sort_assumptions_positive_rank (this),
|
|
563
|
+
sort_assumptions_smaller (this));
|
|
564
|
+
|
|
565
|
+
unsigned max_level = 0;
|
|
566
|
+
// assumptions are sorted by level, with unset at the end
|
|
567
|
+
for (auto lit : assumptions) {
|
|
568
|
+
if (val (lit))
|
|
569
|
+
max_level = var (lit).level;
|
|
570
|
+
else
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const unsigned size = min (level + 1u, max_level + 1);
|
|
575
|
+
assert ((size_t) level == control.size () - 1);
|
|
576
|
+
LOG (assumptions, "sorted assumptions");
|
|
577
|
+
int target = 0;
|
|
578
|
+
for (unsigned i = 1, j = 0; i < size;) {
|
|
579
|
+
const Level &l = control[i];
|
|
580
|
+
const int lit = l.decision;
|
|
581
|
+
const int alit = assumptions[j];
|
|
582
|
+
const int lev = i;
|
|
583
|
+
target = lev;
|
|
584
|
+
if (val (alit) > 0 &&
|
|
585
|
+
var (alit).level < lev) { // we can ignore propagated assumptions
|
|
586
|
+
LOG ("ILB skipping propagation %d", alit);
|
|
587
|
+
++j;
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
if (!lit) { // skip fake decisions
|
|
591
|
+
target = lev - 1;
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
++i, ++j;
|
|
595
|
+
assert (var (lit).level == lev);
|
|
596
|
+
if (l.decision == alit) {
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
target = lev - 1;
|
|
600
|
+
LOG ("first different literal %d on the trail and %d from the "
|
|
601
|
+
"assumptions",
|
|
602
|
+
lit, alit);
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
if (opts.ilb == 1 &&
|
|
606
|
+
(size_t) target > assumptions.size ()) // reusing only assumptions
|
|
607
|
+
target = assumptions.size ();
|
|
608
|
+
if (target < level)
|
|
609
|
+
backtrack_without_updating_phases (target);
|
|
610
|
+
LOG ("assumptions allow for reuse of trail up to level %d", level);
|
|
611
|
+
if ((size_t) level > assumptions.size ())
|
|
612
|
+
stats.assumptionsreused += assumptions.size ();
|
|
613
|
+
else
|
|
614
|
+
stats.assumptionsreused += level;
|
|
615
|
+
}
|
|
616
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
void Internal::init_averages () {
|
|
6
|
+
|
|
7
|
+
LOG ("initializing averages");
|
|
8
|
+
|
|
9
|
+
INIT_EMA (averages.current.jump, opts.emajump);
|
|
10
|
+
INIT_EMA (averages.current.level, opts.emalevel);
|
|
11
|
+
INIT_EMA (averages.current.size, opts.emasize);
|
|
12
|
+
|
|
13
|
+
INIT_EMA (averages.current.glue.fast, opts.emagluefast);
|
|
14
|
+
INIT_EMA (averages.current.glue.slow, opts.emaglueslow);
|
|
15
|
+
|
|
16
|
+
INIT_EMA (averages.current.decisions, opts.emadecisions);
|
|
17
|
+
|
|
18
|
+
INIT_EMA (averages.current.trail.fast, opts.ematrailfast);
|
|
19
|
+
INIT_EMA (averages.current.trail.slow, opts.ematrailslow);
|
|
20
|
+
|
|
21
|
+
assert (!averages.swapped);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void Internal::swap_averages () {
|
|
25
|
+
LOG ("saving current averages");
|
|
26
|
+
swap (averages.current, averages.saved);
|
|
27
|
+
if (!averages.swapped)
|
|
28
|
+
init_averages ();
|
|
29
|
+
else
|
|
30
|
+
LOG ("swapping in previously saved averages");
|
|
31
|
+
averages.swapped++;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#ifndef _averages_hpp_INCLUDED
|
|
2
|
+
#define _averages_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include "ema.hpp" // alphabetically after 'averages.hpp'
|
|
5
|
+
|
|
6
|
+
namespace CaDiCaL {
|
|
7
|
+
|
|
8
|
+
struct Averages {
|
|
9
|
+
|
|
10
|
+
int64_t swapped;
|
|
11
|
+
|
|
12
|
+
struct {
|
|
13
|
+
|
|
14
|
+
struct {
|
|
15
|
+
EMA fast; // average fast (small window) moving glucose level
|
|
16
|
+
EMA slow; // average slow (large window) moving glucose level
|
|
17
|
+
} glue;
|
|
18
|
+
|
|
19
|
+
struct {
|
|
20
|
+
EMA fast; // average fast (small window) moving trail level
|
|
21
|
+
EMA slow; // average slow (large window) moving trail level
|
|
22
|
+
} trail;
|
|
23
|
+
|
|
24
|
+
EMA decisions;
|
|
25
|
+
|
|
26
|
+
EMA size; // average learned clause size
|
|
27
|
+
EMA jump; // average (potential non-chronological) back-jump level
|
|
28
|
+
EMA level; // average back track level after conflict
|
|
29
|
+
|
|
30
|
+
} current, saved;
|
|
31
|
+
|
|
32
|
+
Averages () : swapped (0) {}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
} // namespace CaDiCaL
|
|
36
|
+
|
|
37
|
+
#endif
|