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,506 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
// It turns out that even in the competition there are formulas which are
|
|
6
|
+
// easy to satisfy by either setting all variables to the same truth value
|
|
7
|
+
// or by assigning variables to the same value and propagating it. In the
|
|
8
|
+
// latter situation this can be done either in the order of all variables
|
|
9
|
+
// (forward or backward) or in the order of all clauses. These lucky
|
|
10
|
+
// assignments can be tested initially in a kind of pre-solving step.
|
|
11
|
+
|
|
12
|
+
// This function factors out clean up code common among the 'lucky'
|
|
13
|
+
// functions for backtracking and resetting a potential conflict. One could
|
|
14
|
+
// also use exceptions here, but there are two different reasons for
|
|
15
|
+
// aborting early. The first kind of aborting is due to asynchronous
|
|
16
|
+
// termination and the second kind due to a situation in which it is clear
|
|
17
|
+
// that a particular function will not be successful (for instance a
|
|
18
|
+
// completely negative clause is found). The latter situation returns zero
|
|
19
|
+
// and will just abort the particular lucky function, while the former will
|
|
20
|
+
// abort all (by returning '-1').
|
|
21
|
+
|
|
22
|
+
int Internal::unlucky (int res) {
|
|
23
|
+
if (level > 0)
|
|
24
|
+
backtrack_without_updating_phases ();
|
|
25
|
+
if (conflict)
|
|
26
|
+
conflict = 0;
|
|
27
|
+
return res;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
int Internal::trivially_false_satisfiable () {
|
|
31
|
+
LOG ("checking that all clauses contain a negative literal");
|
|
32
|
+
assert (!level);
|
|
33
|
+
int res = lucky_decide_assumptions ();
|
|
34
|
+
if (res)
|
|
35
|
+
return res;
|
|
36
|
+
for (const auto &c : clauses) {
|
|
37
|
+
if (terminated_asynchronously (100))
|
|
38
|
+
return unlucky (-1);
|
|
39
|
+
if (c->garbage)
|
|
40
|
+
continue;
|
|
41
|
+
if (c->redundant)
|
|
42
|
+
continue;
|
|
43
|
+
bool satisfied = false, found_negative_literal = false;
|
|
44
|
+
for (const auto &lit : *c) {
|
|
45
|
+
const signed char tmp = val (lit);
|
|
46
|
+
if (tmp > 0) {
|
|
47
|
+
satisfied = true;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (tmp < 0)
|
|
51
|
+
continue;
|
|
52
|
+
if (lit > 0)
|
|
53
|
+
continue;
|
|
54
|
+
found_negative_literal = true;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
if (satisfied || found_negative_literal)
|
|
58
|
+
continue;
|
|
59
|
+
LOG (c, "found purely positively");
|
|
60
|
+
return unlucky (0);
|
|
61
|
+
}
|
|
62
|
+
VERBOSE (1, "all clauses contain a negative literal");
|
|
63
|
+
for (auto idx : vars) {
|
|
64
|
+
if (terminated_asynchronously (10))
|
|
65
|
+
return unlucky (-1);
|
|
66
|
+
if (val (idx))
|
|
67
|
+
continue;
|
|
68
|
+
search_assume_decision (-idx);
|
|
69
|
+
if (propagate ())
|
|
70
|
+
continue;
|
|
71
|
+
assert (level > 0);
|
|
72
|
+
LOG ("propagation failed including redundant clauses");
|
|
73
|
+
return unlucky (0);
|
|
74
|
+
}
|
|
75
|
+
stats.lucky.constant.zero++;
|
|
76
|
+
return 10;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
int Internal::trivially_true_satisfiable () {
|
|
80
|
+
LOG ("checking that all clauses contain a positive literal");
|
|
81
|
+
assert (!level);
|
|
82
|
+
int res = lucky_decide_assumptions ();
|
|
83
|
+
if (res)
|
|
84
|
+
return res;
|
|
85
|
+
for (const auto &c : clauses) {
|
|
86
|
+
if (terminated_asynchronously (100))
|
|
87
|
+
return unlucky (-1);
|
|
88
|
+
if (c->garbage)
|
|
89
|
+
continue;
|
|
90
|
+
if (c->redundant)
|
|
91
|
+
continue;
|
|
92
|
+
bool satisfied = false, found_positive_literal = false;
|
|
93
|
+
for (const auto &lit : *c) {
|
|
94
|
+
const signed char tmp = val (lit);
|
|
95
|
+
if (tmp > 0) {
|
|
96
|
+
satisfied = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
if (tmp < 0)
|
|
100
|
+
continue;
|
|
101
|
+
if (lit < 0)
|
|
102
|
+
continue;
|
|
103
|
+
found_positive_literal = true;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
if (satisfied || found_positive_literal)
|
|
107
|
+
continue;
|
|
108
|
+
LOG (c, "found purely negatively");
|
|
109
|
+
return unlucky (0);
|
|
110
|
+
}
|
|
111
|
+
VERBOSE (1, "all clauses contain a positive literal");
|
|
112
|
+
for (auto idx : vars) {
|
|
113
|
+
if (terminated_asynchronously (10))
|
|
114
|
+
return unlucky (-1);
|
|
115
|
+
if (val (idx))
|
|
116
|
+
continue;
|
|
117
|
+
search_assume_decision (idx);
|
|
118
|
+
if (propagate ())
|
|
119
|
+
continue;
|
|
120
|
+
assert (level > 0);
|
|
121
|
+
LOG ("propagation failed including redundant clauses");
|
|
122
|
+
return unlucky (0);
|
|
123
|
+
}
|
|
124
|
+
stats.lucky.constant.one++;
|
|
125
|
+
return 10;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*------------------------------------------------------------------------*/
|
|
129
|
+
inline bool Internal::lucky_propagate_discrepency (int dec) {
|
|
130
|
+
search_assume_decision (dec);
|
|
131
|
+
bool no_conflict = propagate ();
|
|
132
|
+
if (no_conflict)
|
|
133
|
+
return false;
|
|
134
|
+
if (level > 1) {
|
|
135
|
+
conflict = nullptr;
|
|
136
|
+
backtrack_without_updating_phases (level - 1);
|
|
137
|
+
search_assume_decision (-dec);
|
|
138
|
+
no_conflict = propagate ();
|
|
139
|
+
if (no_conflict)
|
|
140
|
+
return false;
|
|
141
|
+
return true;
|
|
142
|
+
} else {
|
|
143
|
+
analyze ();
|
|
144
|
+
assert (!level);
|
|
145
|
+
no_conflict = propagate ();
|
|
146
|
+
if (!no_conflict) {
|
|
147
|
+
analyze ();
|
|
148
|
+
LOG ("lucky inconsistency backward assigning to true");
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
int Internal::forward_false_satisfiable () {
|
|
156
|
+
LOG ("checking increasing variable index false assignment");
|
|
157
|
+
assert (!unsat);
|
|
158
|
+
assert (!level);
|
|
159
|
+
int res = lucky_decide_assumptions ();
|
|
160
|
+
if (res)
|
|
161
|
+
return res;
|
|
162
|
+
for (auto idx : vars) {
|
|
163
|
+
START:
|
|
164
|
+
if (terminated_asynchronously (100))
|
|
165
|
+
return unlucky (-1);
|
|
166
|
+
if (val (idx))
|
|
167
|
+
continue;
|
|
168
|
+
if (lucky_propagate_discrepency (-idx)) {
|
|
169
|
+
if (unsat)
|
|
170
|
+
return 20;
|
|
171
|
+
else
|
|
172
|
+
return unlucky (0);
|
|
173
|
+
} else
|
|
174
|
+
goto START;
|
|
175
|
+
}
|
|
176
|
+
VERBOSE (1, "forward assuming variables false satisfies formula");
|
|
177
|
+
assert (satisfied ());
|
|
178
|
+
stats.lucky.forward.zero++;
|
|
179
|
+
return 10;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
int Internal::forward_true_satisfiable () {
|
|
183
|
+
LOG ("checking increasing variable index true assignment");
|
|
184
|
+
assert (!unsat);
|
|
185
|
+
assert (!level);
|
|
186
|
+
int res = lucky_decide_assumptions ();
|
|
187
|
+
if (res)
|
|
188
|
+
return res;
|
|
189
|
+
for (auto idx : vars) {
|
|
190
|
+
START:
|
|
191
|
+
if (terminated_asynchronously (10))
|
|
192
|
+
return unlucky (-1);
|
|
193
|
+
if (val (idx))
|
|
194
|
+
continue;
|
|
195
|
+
if (lucky_propagate_discrepency (idx)) {
|
|
196
|
+
if (unsat)
|
|
197
|
+
return 20;
|
|
198
|
+
else
|
|
199
|
+
return unlucky (0);
|
|
200
|
+
} else
|
|
201
|
+
goto START;
|
|
202
|
+
}
|
|
203
|
+
VERBOSE (1, "forward assuming variables true satisfies formula");
|
|
204
|
+
assert (satisfied ());
|
|
205
|
+
stats.lucky.forward.one++;
|
|
206
|
+
return 10;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/*------------------------------------------------------------------------*/
|
|
210
|
+
|
|
211
|
+
int Internal::backward_false_satisfiable () {
|
|
212
|
+
LOG ("checking decreasing variable index false assignment");
|
|
213
|
+
assert (!unsat);
|
|
214
|
+
assert (!level);
|
|
215
|
+
int res = lucky_decide_assumptions ();
|
|
216
|
+
if (res)
|
|
217
|
+
return res;
|
|
218
|
+
for (auto it = vars.rbegin (); it != vars.rend (); ++it) {
|
|
219
|
+
int idx = *it;
|
|
220
|
+
START:
|
|
221
|
+
if (terminated_asynchronously (10))
|
|
222
|
+
return unlucky (-1);
|
|
223
|
+
if (val (idx))
|
|
224
|
+
continue;
|
|
225
|
+
if (lucky_propagate_discrepency (-idx)) {
|
|
226
|
+
if (unsat)
|
|
227
|
+
return 20;
|
|
228
|
+
else
|
|
229
|
+
return unlucky (0);
|
|
230
|
+
} else
|
|
231
|
+
goto START;
|
|
232
|
+
}
|
|
233
|
+
VERBOSE (1, "backward assuming variables false satisfies formula");
|
|
234
|
+
assert (satisfied ());
|
|
235
|
+
stats.lucky.backward.zero++;
|
|
236
|
+
return 10;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
int Internal::backward_true_satisfiable () {
|
|
240
|
+
LOG ("checking decreasing variable index true assignment");
|
|
241
|
+
assert (!unsat);
|
|
242
|
+
assert (!level);
|
|
243
|
+
int res = lucky_decide_assumptions ();
|
|
244
|
+
if (res)
|
|
245
|
+
return res;
|
|
246
|
+
for (auto it = vars.rbegin (); it != vars.rend (); ++it) {
|
|
247
|
+
int idx = *it;
|
|
248
|
+
START:
|
|
249
|
+
if (terminated_asynchronously (10))
|
|
250
|
+
return unlucky (-1);
|
|
251
|
+
if (val (idx))
|
|
252
|
+
continue;
|
|
253
|
+
if (lucky_propagate_discrepency (idx)) {
|
|
254
|
+
if (unsat)
|
|
255
|
+
return 20;
|
|
256
|
+
else
|
|
257
|
+
return unlucky (0);
|
|
258
|
+
} else
|
|
259
|
+
goto START;
|
|
260
|
+
}
|
|
261
|
+
VERBOSE (1, "backward assuming variables true satisfies formula");
|
|
262
|
+
assert (satisfied ());
|
|
263
|
+
stats.lucky.backward.one++;
|
|
264
|
+
return 10;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/*------------------------------------------------------------------------*/
|
|
268
|
+
|
|
269
|
+
// The following two functions test if the formula is a satisfiable horn
|
|
270
|
+
// formula. Actually the test is slightly more general. It goes over all
|
|
271
|
+
// clauses and assigns the first positive literal to true and propagates.
|
|
272
|
+
// Already satisfied clauses are of course skipped. A reverse function
|
|
273
|
+
// is not implemented yet.
|
|
274
|
+
|
|
275
|
+
int Internal::positive_horn_satisfiable () {
|
|
276
|
+
LOG ("checking that all clauses are positive horn satisfiable");
|
|
277
|
+
assert (!level);
|
|
278
|
+
int res = lucky_decide_assumptions ();
|
|
279
|
+
if (res)
|
|
280
|
+
return res;
|
|
281
|
+
for (const auto &c : clauses) {
|
|
282
|
+
if (terminated_asynchronously (10))
|
|
283
|
+
return unlucky (-1);
|
|
284
|
+
if (c->garbage)
|
|
285
|
+
continue;
|
|
286
|
+
if (c->redundant)
|
|
287
|
+
continue;
|
|
288
|
+
int positive_literal = 0;
|
|
289
|
+
bool satisfied = false;
|
|
290
|
+
for (const auto &lit : *c) {
|
|
291
|
+
const signed char tmp = val (lit);
|
|
292
|
+
if (tmp > 0) {
|
|
293
|
+
satisfied = true;
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
if (tmp < 0)
|
|
297
|
+
continue;
|
|
298
|
+
if (lit < 0)
|
|
299
|
+
continue;
|
|
300
|
+
positive_literal = lit;
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
if (satisfied)
|
|
304
|
+
continue;
|
|
305
|
+
if (!positive_literal) {
|
|
306
|
+
LOG (c, "no positive unassigned literal in");
|
|
307
|
+
return unlucky (0);
|
|
308
|
+
}
|
|
309
|
+
assert (positive_literal > 0);
|
|
310
|
+
LOG (c, "found positive literal %d in", positive_literal);
|
|
311
|
+
search_assume_decision (positive_literal);
|
|
312
|
+
if (propagate ())
|
|
313
|
+
continue;
|
|
314
|
+
LOG ("propagation of positive literal %d leads to conflict",
|
|
315
|
+
positive_literal);
|
|
316
|
+
return unlucky (0);
|
|
317
|
+
}
|
|
318
|
+
for (auto idx : vars) {
|
|
319
|
+
if (terminated_asynchronously (10))
|
|
320
|
+
return unlucky (-1);
|
|
321
|
+
if (val (idx))
|
|
322
|
+
continue;
|
|
323
|
+
search_assume_decision (-idx);
|
|
324
|
+
if (propagate ())
|
|
325
|
+
continue;
|
|
326
|
+
LOG ("propagation of remaining literal %d leads to conflict", -idx);
|
|
327
|
+
return unlucky (0);
|
|
328
|
+
}
|
|
329
|
+
VERBOSE (1, "clauses are positive horn satisfied");
|
|
330
|
+
assert (!conflict);
|
|
331
|
+
assert (satisfied ());
|
|
332
|
+
stats.lucky.horn.positive++;
|
|
333
|
+
return 10;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
int Internal::lucky_decide_assumptions () {
|
|
337
|
+
assert (!level);
|
|
338
|
+
assert (!constraint.size ());
|
|
339
|
+
int res = 0;
|
|
340
|
+
while ((size_t) level < assumptions.size ()) {
|
|
341
|
+
res = decide ();
|
|
342
|
+
if (res == 20) {
|
|
343
|
+
marked_failed = false;
|
|
344
|
+
return 20;
|
|
345
|
+
}
|
|
346
|
+
if (!propagate ()) {
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (conflict) {
|
|
352
|
+
// analyze and learn from the conflict.
|
|
353
|
+
LOG (conflict, "setting assumption lead to conflict");
|
|
354
|
+
analyze_wrapper ();
|
|
355
|
+
backtrack (0);
|
|
356
|
+
assert (!conflict);
|
|
357
|
+
int res = 0;
|
|
358
|
+
while (!res) {
|
|
359
|
+
assert ((size_t) level <= assumptions.size ());
|
|
360
|
+
if (unsat)
|
|
361
|
+
res = 20;
|
|
362
|
+
else if (!propagate ()) {
|
|
363
|
+
analyze_wrapper ();
|
|
364
|
+
} else {
|
|
365
|
+
res = decide_wrapper ();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
assert (res == 20);
|
|
369
|
+
return 20;
|
|
370
|
+
}
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
int Internal::negative_horn_satisfiable () {
|
|
375
|
+
assert (!level);
|
|
376
|
+
LOG ("checking that all clauses are negative horn satisfiable");
|
|
377
|
+
int res = lucky_decide_assumptions ();
|
|
378
|
+
if (res)
|
|
379
|
+
return res;
|
|
380
|
+
for (const auto &c : clauses) {
|
|
381
|
+
if (terminated_asynchronously (10))
|
|
382
|
+
return unlucky (-1);
|
|
383
|
+
if (c->garbage)
|
|
384
|
+
continue;
|
|
385
|
+
if (c->redundant)
|
|
386
|
+
continue;
|
|
387
|
+
int negative_literal = 0;
|
|
388
|
+
bool satisfied = false;
|
|
389
|
+
for (const auto &lit : *c) {
|
|
390
|
+
const signed char tmp = val (lit);
|
|
391
|
+
if (tmp > 0) {
|
|
392
|
+
satisfied = true;
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
if (tmp < 0)
|
|
396
|
+
continue;
|
|
397
|
+
if (lit > 0)
|
|
398
|
+
continue;
|
|
399
|
+
negative_literal = lit;
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
if (satisfied)
|
|
403
|
+
continue;
|
|
404
|
+
if (!negative_literal) {
|
|
405
|
+
if (level > 0)
|
|
406
|
+
backtrack_without_updating_phases ();
|
|
407
|
+
LOG (c, "no negative unassigned literal in");
|
|
408
|
+
return unlucky (0);
|
|
409
|
+
}
|
|
410
|
+
assert (negative_literal < 0);
|
|
411
|
+
LOG (c, "found negative literal %d in", negative_literal);
|
|
412
|
+
search_assume_decision (negative_literal);
|
|
413
|
+
if (propagate ())
|
|
414
|
+
continue;
|
|
415
|
+
LOG ("propagation of negative literal %d leads to conflict",
|
|
416
|
+
negative_literal);
|
|
417
|
+
return unlucky (0);
|
|
418
|
+
}
|
|
419
|
+
for (auto idx : vars) {
|
|
420
|
+
if (terminated_asynchronously (10))
|
|
421
|
+
return unlucky (-1);
|
|
422
|
+
if (val (idx))
|
|
423
|
+
continue;
|
|
424
|
+
search_assume_decision (idx);
|
|
425
|
+
if (propagate ())
|
|
426
|
+
continue;
|
|
427
|
+
LOG ("propagation of remaining literal %d leads to conflict", idx);
|
|
428
|
+
return unlucky (0);
|
|
429
|
+
}
|
|
430
|
+
VERBOSE (1, "clauses are negative horn satisfied");
|
|
431
|
+
assert (!conflict);
|
|
432
|
+
assert (satisfied ());
|
|
433
|
+
stats.lucky.horn.negative++;
|
|
434
|
+
return 10;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/*------------------------------------------------------------------------*/
|
|
438
|
+
|
|
439
|
+
int Internal::lucky_phases () {
|
|
440
|
+
assert (!level);
|
|
441
|
+
require_mode (SEARCH);
|
|
442
|
+
if (!opts.lucky)
|
|
443
|
+
return 0;
|
|
444
|
+
|
|
445
|
+
if (!opts.luckyassumptions && !assumptions.empty ())
|
|
446
|
+
return 0;
|
|
447
|
+
// TODO: Some of the lucky assignments can also be found if there are
|
|
448
|
+
// constraint.
|
|
449
|
+
// External propagator assumes a CDCL loop, so lucky is not tried here.
|
|
450
|
+
if (!constraint.empty () || external_prop)
|
|
451
|
+
return 0;
|
|
452
|
+
if (!propagate ()) {
|
|
453
|
+
learn_empty_clause ();
|
|
454
|
+
return 20;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
START (search);
|
|
458
|
+
START (lucky);
|
|
459
|
+
LOG ("starting lucky");
|
|
460
|
+
assert (!searching_lucky_phases);
|
|
461
|
+
searching_lucky_phases = true;
|
|
462
|
+
stats.lucky.tried++;
|
|
463
|
+
const int64_t active_before = stats.active;
|
|
464
|
+
int res = trivially_false_satisfiable ();
|
|
465
|
+
if (!res)
|
|
466
|
+
res = trivially_true_satisfiable ();
|
|
467
|
+
if (!res)
|
|
468
|
+
res = forward_false_satisfiable ();
|
|
469
|
+
if (!res)
|
|
470
|
+
res = forward_true_satisfiable ();
|
|
471
|
+
if (!res)
|
|
472
|
+
res = backward_false_satisfiable ();
|
|
473
|
+
if (!res)
|
|
474
|
+
res = backward_true_satisfiable ();
|
|
475
|
+
if (!res)
|
|
476
|
+
res = negative_horn_satisfiable ();
|
|
477
|
+
if (!res)
|
|
478
|
+
res = positive_horn_satisfiable ();
|
|
479
|
+
if (res < 0)
|
|
480
|
+
assert (termination_forced), res = 0;
|
|
481
|
+
if (res == 10)
|
|
482
|
+
stats.lucky.succeeded++;
|
|
483
|
+
report ('l', !res);
|
|
484
|
+
assert (searching_lucky_phases);
|
|
485
|
+
|
|
486
|
+
assert (res || !level);
|
|
487
|
+
if (res != 20) {
|
|
488
|
+
if (!propagate ()) {
|
|
489
|
+
LOG ("propagating units after elimination results in empty clause");
|
|
490
|
+
learn_empty_clause ();
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const int64_t units = active_before - stats.active;
|
|
495
|
+
|
|
496
|
+
if (!res && units)
|
|
497
|
+
LOG ("lucky %" PRId64 " units", units);
|
|
498
|
+
searching_lucky_phases = false;
|
|
499
|
+
|
|
500
|
+
STOP (lucky);
|
|
501
|
+
STOP (search);
|
|
502
|
+
|
|
503
|
+
return res;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
#ifndef QUIET
|
|
7
|
+
/*------------------------------------------------------------------------*/
|
|
8
|
+
|
|
9
|
+
void Internal::print_prefix () { fputs (prefix.c_str (), stdout); }
|
|
10
|
+
|
|
11
|
+
void Internal::vmessage (const char *fmt, va_list &ap) {
|
|
12
|
+
#ifdef LOGGING
|
|
13
|
+
if (!opts.log)
|
|
14
|
+
#endif
|
|
15
|
+
if (opts.quiet)
|
|
16
|
+
return;
|
|
17
|
+
print_prefix ();
|
|
18
|
+
vprintf (fmt, ap);
|
|
19
|
+
fputc ('\n', stdout);
|
|
20
|
+
fflush (stdout);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
void Internal::message (const char *fmt, ...) {
|
|
24
|
+
#ifdef LOGGING
|
|
25
|
+
if (!opts.log)
|
|
26
|
+
#endif
|
|
27
|
+
if (opts.quiet)
|
|
28
|
+
return;
|
|
29
|
+
|
|
30
|
+
va_list ap;
|
|
31
|
+
va_start (ap, fmt);
|
|
32
|
+
vmessage (fmt, ap);
|
|
33
|
+
va_end (ap);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void Internal::message () {
|
|
37
|
+
#ifdef LOGGING
|
|
38
|
+
if (!opts.log)
|
|
39
|
+
#endif
|
|
40
|
+
if (opts.quiet)
|
|
41
|
+
return;
|
|
42
|
+
print_prefix ();
|
|
43
|
+
fputc ('\n', stdout);
|
|
44
|
+
fflush (stdout);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*------------------------------------------------------------------------*/
|
|
48
|
+
|
|
49
|
+
void Internal::vverbose (int level, const char *fmt, va_list &ap) {
|
|
50
|
+
#ifdef LOGGING
|
|
51
|
+
if (!opts.log)
|
|
52
|
+
#endif
|
|
53
|
+
if (opts.quiet || level > opts.verbose)
|
|
54
|
+
return;
|
|
55
|
+
print_prefix ();
|
|
56
|
+
vprintf (fmt, ap);
|
|
57
|
+
fputc ('\n', stdout);
|
|
58
|
+
fflush (stdout);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void Internal::verbose (int level, const char *fmt, ...) {
|
|
62
|
+
va_list ap;
|
|
63
|
+
va_start (ap, fmt);
|
|
64
|
+
vverbose (level, fmt, ap);
|
|
65
|
+
va_end (ap);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void Internal::verbose (int level) {
|
|
69
|
+
#ifdef LOGGING
|
|
70
|
+
if (!opts.log)
|
|
71
|
+
#endif
|
|
72
|
+
if (opts.quiet || level > opts.verbose)
|
|
73
|
+
return;
|
|
74
|
+
print_prefix ();
|
|
75
|
+
fputc ('\n', stdout);
|
|
76
|
+
fflush (stdout);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/*------------------------------------------------------------------------*/
|
|
80
|
+
|
|
81
|
+
void Internal::section (const char *title) {
|
|
82
|
+
#ifdef LOGGING
|
|
83
|
+
if (!opts.log)
|
|
84
|
+
#endif
|
|
85
|
+
if (opts.quiet)
|
|
86
|
+
return;
|
|
87
|
+
if (stats.sections++)
|
|
88
|
+
MSG ();
|
|
89
|
+
print_prefix ();
|
|
90
|
+
tout.blue ();
|
|
91
|
+
fputs ("--- [ ", stdout);
|
|
92
|
+
tout.blue (true);
|
|
93
|
+
fputs (title, stdout);
|
|
94
|
+
tout.blue ();
|
|
95
|
+
fputs (" ] ", stdout);
|
|
96
|
+
for (int i = strlen (title) + strlen (prefix.c_str ()) + 9; i < 78; i++)
|
|
97
|
+
fputc ('-', stdout);
|
|
98
|
+
tout.normal ();
|
|
99
|
+
fputc ('\n', stdout);
|
|
100
|
+
MSG ();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/*------------------------------------------------------------------------*/
|
|
104
|
+
|
|
105
|
+
void Internal::phase (const char *phase, const char *fmt, ...) {
|
|
106
|
+
#ifdef LOGGING
|
|
107
|
+
if (!opts.log)
|
|
108
|
+
#endif
|
|
109
|
+
if (opts.quiet || (!force_phase_messages && opts.verbose < 2))
|
|
110
|
+
return;
|
|
111
|
+
print_prefix ();
|
|
112
|
+
printf ("[%s] ", phase);
|
|
113
|
+
va_list ap;
|
|
114
|
+
va_start (ap, fmt);
|
|
115
|
+
vprintf (fmt, ap);
|
|
116
|
+
va_end (ap);
|
|
117
|
+
fputc ('\n', stdout);
|
|
118
|
+
fflush (stdout);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
void Internal::phase (const char *phase, int64_t count, const char *fmt,
|
|
122
|
+
...) {
|
|
123
|
+
#ifdef LOGGING
|
|
124
|
+
if (!opts.log)
|
|
125
|
+
#endif
|
|
126
|
+
if (opts.quiet || (!force_phase_messages && opts.verbose < 2))
|
|
127
|
+
return;
|
|
128
|
+
print_prefix ();
|
|
129
|
+
printf ("[%s-%" PRId64 "] ", phase, count);
|
|
130
|
+
va_list ap;
|
|
131
|
+
va_start (ap, fmt);
|
|
132
|
+
vprintf (fmt, ap);
|
|
133
|
+
va_end (ap);
|
|
134
|
+
fputc ('\n', stdout);
|
|
135
|
+
fflush (stdout);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/*------------------------------------------------------------------------*/
|
|
139
|
+
#endif // ifndef QUIET
|
|
140
|
+
/*------------------------------------------------------------------------*/
|
|
141
|
+
|
|
142
|
+
void Internal::warning (const char *fmt, ...) {
|
|
143
|
+
fflush (stdout);
|
|
144
|
+
terr.bold ();
|
|
145
|
+
fputs ("cadical: ", stderr);
|
|
146
|
+
terr.red (1);
|
|
147
|
+
fputs ("warning:", stderr);
|
|
148
|
+
terr.normal ();
|
|
149
|
+
fputc (' ', stderr);
|
|
150
|
+
va_list ap;
|
|
151
|
+
va_start (ap, fmt);
|
|
152
|
+
vfprintf (stderr, fmt, ap);
|
|
153
|
+
va_end (ap);
|
|
154
|
+
fputc ('\n', stderr);
|
|
155
|
+
fflush (stderr);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/*------------------------------------------------------------------------*/
|
|
159
|
+
|
|
160
|
+
void Internal::error_message_start () {
|
|
161
|
+
fflush (stdout);
|
|
162
|
+
terr.bold ();
|
|
163
|
+
fputs ("cadical: ", stderr);
|
|
164
|
+
terr.red (1);
|
|
165
|
+
fputs ("error:", stderr);
|
|
166
|
+
terr.normal ();
|
|
167
|
+
fputc (' ', stderr);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
void Internal::error_message_end () {
|
|
171
|
+
fputc ('\n', stderr);
|
|
172
|
+
fflush (stderr);
|
|
173
|
+
// TODO add possibility to use call back instead.
|
|
174
|
+
exit (1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
void Internal::verror (const char *fmt, va_list &ap) {
|
|
178
|
+
error_message_start ();
|
|
179
|
+
vfprintf (stderr, fmt, ap);
|
|
180
|
+
error_message_end ();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void Internal::error (const char *fmt, ...) {
|
|
184
|
+
va_list ap;
|
|
185
|
+
va_start (ap, fmt);
|
|
186
|
+
verror (fmt, ap);
|
|
187
|
+
va_end (ap); // unreachable
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/*------------------------------------------------------------------------*/
|
|
191
|
+
|
|
192
|
+
void fatal_message_start () {
|
|
193
|
+
fflush (stdout);
|
|
194
|
+
terr.bold ();
|
|
195
|
+
fputs ("cadical: ", stderr);
|
|
196
|
+
terr.red (1);
|
|
197
|
+
fputs ("fatal error:", stderr);
|
|
198
|
+
terr.normal ();
|
|
199
|
+
fputc (' ', stderr);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
void fatal_message_end () {
|
|
203
|
+
fputc ('\n', stderr);
|
|
204
|
+
fflush (stderr);
|
|
205
|
+
abort ();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
void fatal (const char *fmt, ...) {
|
|
209
|
+
fatal_message_start ();
|
|
210
|
+
va_list ap;
|
|
211
|
+
va_start (ap, fmt);
|
|
212
|
+
vfprintf (stderr, fmt, ap);
|
|
213
|
+
va_end (ap);
|
|
214
|
+
fatal_message_end ();
|
|
215
|
+
abort ();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
} // namespace CaDiCaL
|