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,1265 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
static Clause external_reason_clause;
|
|
7
|
+
|
|
8
|
+
Internal::Internal ()
|
|
9
|
+
: mode (SEARCH), unsat (false), iterating (false),
|
|
10
|
+
localsearching (false), lookingahead (false), preprocessing (false),
|
|
11
|
+
protected_reasons (false), force_saved_phase (false),
|
|
12
|
+
searching_lucky_phases (false), stable (false), reported (false),
|
|
13
|
+
external_prop (false), did_external_prop (false),
|
|
14
|
+
external_prop_is_lazy (true), forced_backt_allowed (false),
|
|
15
|
+
|
|
16
|
+
private_steps (false), rephased (0), vsize (0), max_var (0),
|
|
17
|
+
clause_id (0), original_id (0), reserved_ids (0), conflict_id (0),
|
|
18
|
+
saved_decisions (0), concluded (false), lrat (false), frat (false),
|
|
19
|
+
level (0), vals (0), score_inc (1.0), scores (this), conflict (0),
|
|
20
|
+
ignore (0), external_reason (&external_reason_clause),
|
|
21
|
+
newest_clause (0), force_no_backtrack (false),
|
|
22
|
+
from_propagator (false), ext_clause_forgettable (false),
|
|
23
|
+
changed_val (0), notified (0), probe_reason (0), propagated (0),
|
|
24
|
+
propagated2 (0), propergated (0), best_assigned (0),
|
|
25
|
+
target_assigned (0), no_conflict_until (0), unsat_constraint (false),
|
|
26
|
+
marked_failed (true), sweep_incomplete (false),
|
|
27
|
+
randomized_deciding (false), citten (0), num_assigned (0), proof (0),
|
|
28
|
+
opts (this),
|
|
29
|
+
#ifndef QUIET
|
|
30
|
+
profiles (this), force_phase_messages (false),
|
|
31
|
+
#endif
|
|
32
|
+
arena (this), prefix ("c "), internal (this), external (0),
|
|
33
|
+
termination_forced (false), vars (this->max_var),
|
|
34
|
+
lits (this->max_var) {
|
|
35
|
+
control.push_back (Level (0, 0));
|
|
36
|
+
|
|
37
|
+
// The 'dummy_binary' is used in 'try_to_subsume_clause' to fake a real
|
|
38
|
+
// clause (which then can be used to subsume or strengthen the given
|
|
39
|
+
// clause in one routine for both binary and non binary clauses) and
|
|
40
|
+
// in walk (which is only used as a placeholder in the watch lists
|
|
41
|
+
// when logging is off, since the clause is not accessed). This
|
|
42
|
+
// fake binary clause is always kept non-redundant (and not-moved etc.)
|
|
43
|
+
// due to the following 'memset'. Only literals will be changed.
|
|
44
|
+
|
|
45
|
+
// In a previous version we used local automatic allocated 'Clause' on the
|
|
46
|
+
// stack, which became incompatible with several compilers (see the
|
|
47
|
+
// discussion on flexible array member in 'Clause.cpp').
|
|
48
|
+
|
|
49
|
+
size_t bytes = Clause::bytes (2);
|
|
50
|
+
dummy_binary = (Clause *) new char[bytes];
|
|
51
|
+
memset (dummy_binary, 0, bytes);
|
|
52
|
+
dummy_binary->size = 2;
|
|
53
|
+
|
|
54
|
+
/*with C++17: static_*/ assert (max_used == (1 << USED_SIZE) - 1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Internal::~Internal () {
|
|
58
|
+
// If a memory exception ocurred a profile might still be active.
|
|
59
|
+
#ifndef QUIET
|
|
60
|
+
#define PROFILE(NAME, LEVEL) \
|
|
61
|
+
if (PROFILE_ACTIVE (NAME)) \
|
|
62
|
+
STOP (NAME);
|
|
63
|
+
PROFILES
|
|
64
|
+
#undef PROFILE
|
|
65
|
+
#endif
|
|
66
|
+
delete[] (char *) dummy_binary;
|
|
67
|
+
for (const auto &c : clauses)
|
|
68
|
+
delete_clause (c);
|
|
69
|
+
if (proof)
|
|
70
|
+
delete proof;
|
|
71
|
+
for (auto &tracer : tracers)
|
|
72
|
+
delete tracer;
|
|
73
|
+
for (auto &filetracer : file_tracers)
|
|
74
|
+
delete filetracer;
|
|
75
|
+
for (auto &stattracer : stat_tracers)
|
|
76
|
+
delete stattracer;
|
|
77
|
+
if (vals) {
|
|
78
|
+
vals -= vsize;
|
|
79
|
+
delete[] vals;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*------------------------------------------------------------------------*/
|
|
84
|
+
|
|
85
|
+
// Values in 'vals' can be accessed in the range '[-max_var,max_var]' that
|
|
86
|
+
// is directly by a literal. This is crucial for performance. By shifting
|
|
87
|
+
// the start of 'vals' appropriately, we achieve that negative offsets from
|
|
88
|
+
// the start of 'vals' can be used. We also need to set both values at
|
|
89
|
+
// 'lit' and '-lit' during assignments. In MiniSAT integer literals are
|
|
90
|
+
// encoded, using the least significant bit as negation. This avoids taking
|
|
91
|
+
// the 'abs ()' (as in our solution) and thus also avoids a branch in the
|
|
92
|
+
// hot-spot of the solver (clause traversal in propagation). That solution
|
|
93
|
+
// requires another (branch less) negation of the values though and
|
|
94
|
+
// debugging is harder since literals occur only encoded in clauses.
|
|
95
|
+
// The main draw-back of our solution is that we have to shift the memory
|
|
96
|
+
// and access it through negative indices, which looks less clean (but still
|
|
97
|
+
// as far I can tell is properly defined C / C++). You might get a warning
|
|
98
|
+
// by static analyzers though. Clang with '--analyze' thought that this
|
|
99
|
+
// idiom would generate a memory leak thus we use the following dummy.
|
|
100
|
+
|
|
101
|
+
static signed char *ignore_clang_analyze_memory_leak_warning;
|
|
102
|
+
|
|
103
|
+
void Internal::enlarge_vals (size_t new_vsize) {
|
|
104
|
+
signed char *new_vals;
|
|
105
|
+
const size_t bytes = 2u * new_vsize;
|
|
106
|
+
new_vals = new signed char[bytes]; // g++-4.8 does not like ... { 0 };
|
|
107
|
+
memset (new_vals, 0, bytes);
|
|
108
|
+
ignore_clang_analyze_memory_leak_warning = new_vals;
|
|
109
|
+
new_vals += new_vsize;
|
|
110
|
+
|
|
111
|
+
if (vals) {
|
|
112
|
+
memcpy (new_vals - max_var, vals - max_var, 2u * max_var + 1u);
|
|
113
|
+
vals -= vsize;
|
|
114
|
+
delete[] vals;
|
|
115
|
+
} else
|
|
116
|
+
assert (!vsize);
|
|
117
|
+
vals = new_vals;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*------------------------------------------------------------------------*/
|
|
121
|
+
|
|
122
|
+
void Internal::enlarge (int new_max_var) {
|
|
123
|
+
// New variables can be created that can invoke enlarge anytime (via calls
|
|
124
|
+
// during ipasir-up call-backs), thus assuming (!level) is not correct
|
|
125
|
+
size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) new_max_var;
|
|
126
|
+
while (new_vsize <= (size_t) new_max_var)
|
|
127
|
+
new_vsize *= 2;
|
|
128
|
+
LOG ("enlarge internal size from %zd to new size %zd", vsize, new_vsize);
|
|
129
|
+
// Ordered in the size of allocated memory (larger block first).
|
|
130
|
+
if (lrat || frat)
|
|
131
|
+
enlarge_zero (unit_clauses_idx, 2 * new_vsize);
|
|
132
|
+
enlarge_only (wtab, 2 * new_vsize);
|
|
133
|
+
enlarge_only (vtab, new_vsize);
|
|
134
|
+
enlarge_zero (parents, new_vsize);
|
|
135
|
+
enlarge_only (links, new_vsize);
|
|
136
|
+
enlarge_zero (btab, new_vsize);
|
|
137
|
+
enlarge_zero (gtab, new_vsize);
|
|
138
|
+
enlarge_zero (stab, new_vsize);
|
|
139
|
+
enlarge_init (ptab, 2 * new_vsize, -1);
|
|
140
|
+
enlarge_only (ftab, new_vsize);
|
|
141
|
+
enlarge_vals (new_vsize);
|
|
142
|
+
vsize = new_vsize;
|
|
143
|
+
if (external)
|
|
144
|
+
enlarge_zero (relevanttab, new_vsize);
|
|
145
|
+
const signed char val = opts.phase ? 1 : -1;
|
|
146
|
+
enlarge_init (phases.saved, new_vsize, val);
|
|
147
|
+
enlarge_zero (phases.forced, new_vsize);
|
|
148
|
+
enlarge_zero (phases.target, new_vsize);
|
|
149
|
+
enlarge_zero (phases.best, new_vsize);
|
|
150
|
+
enlarge_zero (phases.prev, new_vsize);
|
|
151
|
+
enlarge_zero (marks, new_vsize);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
void Internal::init_vars (int new_max_var) {
|
|
155
|
+
if (new_max_var <= max_var)
|
|
156
|
+
return;
|
|
157
|
+
// New variables can be created that can invoke enlarge anytime (via calls
|
|
158
|
+
// during ipasir-up call-backs), thus assuming (!level) is not correct
|
|
159
|
+
LOG ("initializing %d internal variables from %d to %d",
|
|
160
|
+
new_max_var - max_var, max_var + 1, new_max_var);
|
|
161
|
+
if ((size_t) new_max_var >= vsize)
|
|
162
|
+
enlarge (new_max_var);
|
|
163
|
+
#ifndef NDEBUG
|
|
164
|
+
for (int64_t i = -new_max_var; i < -max_var; i++)
|
|
165
|
+
assert (!vals[i]);
|
|
166
|
+
for (unsigned i = max_var + 1; i <= (unsigned) new_max_var; i++)
|
|
167
|
+
assert (!vals[i]), assert (!btab[i]), assert (!gtab[i]);
|
|
168
|
+
for (uint64_t i = 2 * ((uint64_t) max_var + 1);
|
|
169
|
+
i <= 2 * (uint64_t) new_max_var + 1; i++)
|
|
170
|
+
assert (ptab[i] == -1);
|
|
171
|
+
#endif
|
|
172
|
+
assert (!btab[0]);
|
|
173
|
+
int old_max_var = max_var;
|
|
174
|
+
max_var = new_max_var;
|
|
175
|
+
init_queue (old_max_var, new_max_var);
|
|
176
|
+
init_scores (old_max_var, new_max_var);
|
|
177
|
+
int initialized = new_max_var - old_max_var;
|
|
178
|
+
stats.vars += initialized;
|
|
179
|
+
stats.unused += initialized;
|
|
180
|
+
stats.inactive += initialized;
|
|
181
|
+
LOG ("finished initializing %d internal variables", initialized);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
void Internal::add_original_lit (int lit) {
|
|
185
|
+
assert (abs (lit) <= max_var);
|
|
186
|
+
if (lit) {
|
|
187
|
+
original.push_back (lit);
|
|
188
|
+
} else {
|
|
189
|
+
const int64_t id =
|
|
190
|
+
original_id < reserved_ids ? ++original_id : ++clause_id;
|
|
191
|
+
if (proof) {
|
|
192
|
+
// Use the external form of the clause for printing in proof
|
|
193
|
+
// Externalize(internalized literal) != external literal
|
|
194
|
+
assert (!original.size () || !external->eclause.empty ());
|
|
195
|
+
proof->add_external_original_clause (id, false, external->eclause);
|
|
196
|
+
}
|
|
197
|
+
if (internal->opts.check &&
|
|
198
|
+
(internal->opts.checkwitness || internal->opts.checkfailed)) {
|
|
199
|
+
bool forgettable = from_propagator && ext_clause_forgettable;
|
|
200
|
+
if (forgettable && opts.check) {
|
|
201
|
+
assert (!original.size () || !external->eclause.empty ());
|
|
202
|
+
|
|
203
|
+
// First integer is the presence-flag (even if the clause is empty)
|
|
204
|
+
external->forgettable_original[id] = {1};
|
|
205
|
+
|
|
206
|
+
for (auto const &elit : external->eclause)
|
|
207
|
+
external->forgettable_original[id].push_back (elit);
|
|
208
|
+
|
|
209
|
+
LOG (external->eclause,
|
|
210
|
+
"clause added to external forgettable map:");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
add_new_original_clause (id);
|
|
215
|
+
original.clear ();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
void Internal::finish_added_clause_with_id (int64_t id, bool restore) {
|
|
220
|
+
if (proof) {
|
|
221
|
+
// Use the external form of the clause for printing in proof
|
|
222
|
+
// Externalize(internalized literal) != external literal
|
|
223
|
+
assert (!original.size () || !external->eclause.empty ());
|
|
224
|
+
proof->add_external_original_clause (id, false, external->eclause,
|
|
225
|
+
restore);
|
|
226
|
+
}
|
|
227
|
+
add_new_original_clause (id);
|
|
228
|
+
original.clear ();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/*------------------------------------------------------------------------*/
|
|
232
|
+
|
|
233
|
+
void Internal::reserve_ids (int number) {
|
|
234
|
+
// return;
|
|
235
|
+
LOG ("reserving %d ids", number);
|
|
236
|
+
assert (number >= 0);
|
|
237
|
+
assert (!clause_id && !reserved_ids && !original_id);
|
|
238
|
+
clause_id = reserved_ids = number;
|
|
239
|
+
if (proof)
|
|
240
|
+
proof->begin_proof (reserved_ids);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/*------------------------------------------------------------------------*/
|
|
244
|
+
|
|
245
|
+
#ifdef PROFILE_MODE
|
|
246
|
+
|
|
247
|
+
// Separating these makes it easier to profile stable and unstable search.
|
|
248
|
+
|
|
249
|
+
bool Internal::propagate_wrapper () {
|
|
250
|
+
if (stable)
|
|
251
|
+
return propagate_stable ();
|
|
252
|
+
else
|
|
253
|
+
return propagate_unstable ();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
void Internal::analyze_wrapper () {
|
|
257
|
+
if (stable)
|
|
258
|
+
analyze_stable ();
|
|
259
|
+
else
|
|
260
|
+
analyze_unstable ();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
int Internal::decide_wrapper () {
|
|
264
|
+
if (stable)
|
|
265
|
+
return decide_stable ();
|
|
266
|
+
else
|
|
267
|
+
return decide_unstable ();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
#endif
|
|
271
|
+
|
|
272
|
+
/*------------------------------------------------------------------------*/
|
|
273
|
+
|
|
274
|
+
// This is the main CDCL loop with interleaved inprocessing.
|
|
275
|
+
|
|
276
|
+
int Internal::cdcl_loop_with_inprocessing () {
|
|
277
|
+
|
|
278
|
+
int res = 0;
|
|
279
|
+
|
|
280
|
+
START (search);
|
|
281
|
+
|
|
282
|
+
if (stable) {
|
|
283
|
+
START (stable);
|
|
284
|
+
report ('[');
|
|
285
|
+
} else {
|
|
286
|
+
START (unstable);
|
|
287
|
+
report ('{');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
while (!res) {
|
|
291
|
+
if (unsat)
|
|
292
|
+
res = 20;
|
|
293
|
+
else if (unsat_constraint)
|
|
294
|
+
res = 20;
|
|
295
|
+
else if (!propagate_wrapper ())
|
|
296
|
+
analyze_wrapper (); // propagate and analyze
|
|
297
|
+
else if (iterating)
|
|
298
|
+
iterate (); // report learned unit
|
|
299
|
+
else if (!external_propagate () || unsat) { // external propagation
|
|
300
|
+
if (unsat)
|
|
301
|
+
continue;
|
|
302
|
+
else
|
|
303
|
+
analyze ();
|
|
304
|
+
} else if (satisfied ()) { // found model
|
|
305
|
+
if (!external_check_solution () || unsat) {
|
|
306
|
+
if (unsat)
|
|
307
|
+
continue;
|
|
308
|
+
else
|
|
309
|
+
analyze ();
|
|
310
|
+
} else if (satisfied ())
|
|
311
|
+
res = 10;
|
|
312
|
+
} else if (search_limits_hit ())
|
|
313
|
+
break; // decision or conflict limit
|
|
314
|
+
else if (terminated_asynchronously ()) // externally terminated
|
|
315
|
+
break;
|
|
316
|
+
else if (restarting ())
|
|
317
|
+
restart (); // restart by backtracking
|
|
318
|
+
else if (rephasing ())
|
|
319
|
+
rephase (); // reset variable phases
|
|
320
|
+
else if (reducing ())
|
|
321
|
+
reduce (); // collect useless clauses
|
|
322
|
+
else if (inprobing ())
|
|
323
|
+
inprobe (); // schedule of inprocessing
|
|
324
|
+
else if (ineliminating ())
|
|
325
|
+
elim (); // variable elimination
|
|
326
|
+
else if (compacting ())
|
|
327
|
+
compact (); // collect variables
|
|
328
|
+
else if (conditioning ())
|
|
329
|
+
condition (); // globally blocked clauses
|
|
330
|
+
else
|
|
331
|
+
res = decide (); // next decision
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (stable) {
|
|
335
|
+
STOP (stable);
|
|
336
|
+
report (']');
|
|
337
|
+
} else {
|
|
338
|
+
STOP (unstable);
|
|
339
|
+
report ('}');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
STOP (search);
|
|
343
|
+
|
|
344
|
+
return res;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
int Internal::propagate_assumptions () {
|
|
348
|
+
if (proof)
|
|
349
|
+
proof->solve_query ();
|
|
350
|
+
if (opts.ilb) {
|
|
351
|
+
sort_and_reuse_assumptions ();
|
|
352
|
+
assert (opts.ilb == 2 || (size_t) level <= assumptions.size ());
|
|
353
|
+
stats.ilbtriggers++;
|
|
354
|
+
stats.ilbsuccess += (level > 0);
|
|
355
|
+
stats.levelsreused += level;
|
|
356
|
+
if (level) {
|
|
357
|
+
assert (control.size () > 1);
|
|
358
|
+
stats.literalsreused += num_assigned - control[1].trail;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
init_search_limits ();
|
|
362
|
+
init_report_limits ();
|
|
363
|
+
|
|
364
|
+
int res = already_solved (); // root-level propagation is done here
|
|
365
|
+
|
|
366
|
+
int last_assumption_level = assumptions.size ();
|
|
367
|
+
if (constraint.size ())
|
|
368
|
+
last_assumption_level++;
|
|
369
|
+
|
|
370
|
+
if (!res) {
|
|
371
|
+
restore_clauses ();
|
|
372
|
+
while (!res) {
|
|
373
|
+
if (unsat)
|
|
374
|
+
res = 20;
|
|
375
|
+
else if (unsat_constraint)
|
|
376
|
+
res = 20;
|
|
377
|
+
else if (!propagate ()) {
|
|
378
|
+
// let analyze run to get failed assumptions
|
|
379
|
+
analyze ();
|
|
380
|
+
} else if (!external_propagate () || unsat) { // external propagation
|
|
381
|
+
if (unsat)
|
|
382
|
+
continue;
|
|
383
|
+
else
|
|
384
|
+
analyze ();
|
|
385
|
+
} else if (satisfied ()) { // found model
|
|
386
|
+
if (!external_check_solution () || unsat) {
|
|
387
|
+
if (unsat)
|
|
388
|
+
continue;
|
|
389
|
+
else
|
|
390
|
+
analyze ();
|
|
391
|
+
} else if (satisfied ())
|
|
392
|
+
res = 10;
|
|
393
|
+
} else if (search_limits_hit ())
|
|
394
|
+
break; // decision or conflict limit
|
|
395
|
+
else if (terminated_asynchronously ()) // externally terminated
|
|
396
|
+
break;
|
|
397
|
+
else {
|
|
398
|
+
if (level >= last_assumption_level)
|
|
399
|
+
break;
|
|
400
|
+
res = decide ();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (unsat || unsat_constraint)
|
|
406
|
+
res = 20;
|
|
407
|
+
|
|
408
|
+
if (!res && satisfied ())
|
|
409
|
+
res = 10;
|
|
410
|
+
|
|
411
|
+
finalize (res);
|
|
412
|
+
reset_solving ();
|
|
413
|
+
report_solving (res);
|
|
414
|
+
|
|
415
|
+
return res;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
void Internal::implied (std::vector<int> &entrailed) {
|
|
419
|
+
int last_assumption_level = assumptions.size ();
|
|
420
|
+
if (constraint.size ())
|
|
421
|
+
last_assumption_level++;
|
|
422
|
+
|
|
423
|
+
size_t trail_limit = trail.size ();
|
|
424
|
+
if (level > last_assumption_level)
|
|
425
|
+
trail_limit = control[last_assumption_level + 1].trail;
|
|
426
|
+
|
|
427
|
+
for (size_t i = 0; i < trail_limit; i++)
|
|
428
|
+
entrailed.push_back (trail[i]);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/*------------------------------------------------------------------------*/
|
|
432
|
+
|
|
433
|
+
// Most of the limits are only initialized in the first 'solve' call and
|
|
434
|
+
// increased as in a stand-alone non-incremental SAT call except for those
|
|
435
|
+
// explicitly marked as being reset below.
|
|
436
|
+
|
|
437
|
+
void Internal::init_report_limits () {
|
|
438
|
+
reported = false;
|
|
439
|
+
lim.report = 0;
|
|
440
|
+
lim.recompute_tier = 5000;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
void Internal::init_preprocessing_limits () {
|
|
444
|
+
|
|
445
|
+
const bool incremental = lim.initialized;
|
|
446
|
+
if (incremental)
|
|
447
|
+
LOG ("reinitializing preprocessing limits incrementally");
|
|
448
|
+
else
|
|
449
|
+
LOG ("initializing preprocessing limits and increments");
|
|
450
|
+
|
|
451
|
+
const char *mode = 0;
|
|
452
|
+
|
|
453
|
+
/*----------------------------------------------------------------------*/
|
|
454
|
+
|
|
455
|
+
if (incremental)
|
|
456
|
+
mode = "keeping";
|
|
457
|
+
else {
|
|
458
|
+
last.elim.marked = -1;
|
|
459
|
+
lim.elim = stats.conflicts + scale (opts.elimint);
|
|
460
|
+
mode = "initial";
|
|
461
|
+
}
|
|
462
|
+
(void) mode;
|
|
463
|
+
LOG ("%s elim limit %" PRId64 " after %" PRId64 " conflicts", mode,
|
|
464
|
+
lim.elim, lim.elim - stats.conflicts);
|
|
465
|
+
|
|
466
|
+
// Initialize and reset elimination bounds in any case.
|
|
467
|
+
|
|
468
|
+
lim.elimbound = opts.elimboundmin;
|
|
469
|
+
LOG ("elimination bound %" PRId64 "", lim.elimbound);
|
|
470
|
+
|
|
471
|
+
/*----------------------------------------------------------------------*/
|
|
472
|
+
|
|
473
|
+
if (!incremental) {
|
|
474
|
+
|
|
475
|
+
last.ternary.marked = -1; // TODO this should not be necessary...
|
|
476
|
+
|
|
477
|
+
lim.compact = stats.conflicts + opts.compactint;
|
|
478
|
+
LOG ("initial compact limit %" PRId64 " increment %" PRId64 "",
|
|
479
|
+
lim.compact, lim.compact - stats.conflicts);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/*----------------------------------------------------------------------*/
|
|
483
|
+
|
|
484
|
+
if (incremental)
|
|
485
|
+
mode = "keeping";
|
|
486
|
+
else {
|
|
487
|
+
double delta = log10 (stats.added.irredundant + 10);
|
|
488
|
+
delta = delta * delta;
|
|
489
|
+
lim.inprobe = stats.conflicts + opts.inprobeint * delta;
|
|
490
|
+
mode = "initial";
|
|
491
|
+
}
|
|
492
|
+
(void) mode;
|
|
493
|
+
LOG ("%s probe limit %" PRId64 " after %" PRId64 " conflicts", mode,
|
|
494
|
+
lim.inprobe, lim.inprobe - stats.conflicts);
|
|
495
|
+
|
|
496
|
+
/*----------------------------------------------------------------------*/
|
|
497
|
+
|
|
498
|
+
if (incremental)
|
|
499
|
+
mode = "keeping";
|
|
500
|
+
else {
|
|
501
|
+
lim.condition = stats.conflicts + opts.conditionint;
|
|
502
|
+
mode = "initial";
|
|
503
|
+
}
|
|
504
|
+
LOG ("%s condition limit %" PRId64 " increment %" PRId64, mode,
|
|
505
|
+
lim.condition, lim.condition - stats.conflicts);
|
|
506
|
+
|
|
507
|
+
/*----------------------------------------------------------------------*/
|
|
508
|
+
|
|
509
|
+
// Initial preprocessing rounds.
|
|
510
|
+
|
|
511
|
+
if (inc.preprocessing <= 0) {
|
|
512
|
+
lim.preprocessing = 0;
|
|
513
|
+
LOG ("no preprocessing");
|
|
514
|
+
} else {
|
|
515
|
+
lim.preprocessing = inc.preprocessing;
|
|
516
|
+
LOG ("limiting to %" PRId64 " preprocessing rounds", lim.preprocessing);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
void Internal::init_search_limits () {
|
|
521
|
+
|
|
522
|
+
const bool incremental = lim.initialized;
|
|
523
|
+
if (incremental)
|
|
524
|
+
LOG ("reinitializing search limits incrementally");
|
|
525
|
+
else
|
|
526
|
+
LOG ("initializing search limits and increments");
|
|
527
|
+
|
|
528
|
+
const char *mode = 0;
|
|
529
|
+
|
|
530
|
+
/*----------------------------------------------------------------------*/
|
|
531
|
+
|
|
532
|
+
if (incremental)
|
|
533
|
+
mode = "keeping";
|
|
534
|
+
else {
|
|
535
|
+
last.reduce.conflicts = -1;
|
|
536
|
+
lim.reduce = stats.conflicts + opts.reduceinit;
|
|
537
|
+
mode = "initial";
|
|
538
|
+
}
|
|
539
|
+
(void) mode;
|
|
540
|
+
LOG ("%s reduce limit %" PRId64 " after %" PRId64 " conflicts", mode,
|
|
541
|
+
lim.reduce, lim.reduce - stats.conflicts);
|
|
542
|
+
|
|
543
|
+
/*----------------------------------------------------------------------*/
|
|
544
|
+
|
|
545
|
+
if (incremental)
|
|
546
|
+
mode = "keeping";
|
|
547
|
+
else {
|
|
548
|
+
lim.flush = opts.flushint;
|
|
549
|
+
inc.flush = opts.flushint;
|
|
550
|
+
mode = "initial";
|
|
551
|
+
}
|
|
552
|
+
(void) mode;
|
|
553
|
+
LOG ("%s flush limit %" PRId64 " interval %" PRId64 "", mode, lim.flush,
|
|
554
|
+
inc.flush);
|
|
555
|
+
|
|
556
|
+
/*----------------------------------------------------------------------*/
|
|
557
|
+
|
|
558
|
+
// Initialize or reset 'rephase' limits in any case.
|
|
559
|
+
|
|
560
|
+
lim.rephase = stats.conflicts + opts.rephaseint;
|
|
561
|
+
lim.rephased[0] = lim.rephased[1] = 0;
|
|
562
|
+
last.stabilize.rephased = 0;
|
|
563
|
+
LOG ("new rephase limit %" PRId64 " after %" PRId64 " conflicts",
|
|
564
|
+
lim.rephase, lim.rephase - stats.conflicts);
|
|
565
|
+
|
|
566
|
+
/*----------------------------------------------------------------------*/
|
|
567
|
+
|
|
568
|
+
// Initialize or reset 'restart' limits in any case.
|
|
569
|
+
|
|
570
|
+
lim.restart = stats.conflicts + opts.restartint;
|
|
571
|
+
LOG ("new restart limit %" PRId64 " increment %" PRId64 "", lim.restart,
|
|
572
|
+
lim.restart - stats.conflicts);
|
|
573
|
+
|
|
574
|
+
/*----------------------------------------------------------------------*/
|
|
575
|
+
|
|
576
|
+
if (!incremental) {
|
|
577
|
+
stable = opts.stabilize && opts.stabilizeonly;
|
|
578
|
+
if (stable)
|
|
579
|
+
LOG ("starting in always forced stable phase");
|
|
580
|
+
else
|
|
581
|
+
LOG ("starting in default non-stable phase");
|
|
582
|
+
init_averages ();
|
|
583
|
+
} else if (opts.stabilize && opts.stabilizeonly) {
|
|
584
|
+
LOG ("keeping always forced stable phase");
|
|
585
|
+
assert (stable);
|
|
586
|
+
} else if (stable) {
|
|
587
|
+
LOG ("switching back to default non-stable phase");
|
|
588
|
+
stable = false;
|
|
589
|
+
swap_averages ();
|
|
590
|
+
} else
|
|
591
|
+
LOG ("keeping non-stable phase");
|
|
592
|
+
|
|
593
|
+
inc.stabilize = 0;
|
|
594
|
+
last.stabilize.conflicts = stats.conflicts;
|
|
595
|
+
lim.stabilize = stats.conflicts + opts.stabilizeinit;
|
|
596
|
+
last.stabilize.ticks = stats.ticks.search[0];
|
|
597
|
+
stats.stabphases = 0;
|
|
598
|
+
LOG ("new ticks-based stabilize limit %" PRId64 " after %d conflicts",
|
|
599
|
+
lim.stabilize, (int) opts.stabilizeinit);
|
|
600
|
+
|
|
601
|
+
if (opts.stabilize && opts.reluctant && opts.reluctantint) {
|
|
602
|
+
LOG ("new restart reluctant doubling sequence period %d",
|
|
603
|
+
opts.reluctant);
|
|
604
|
+
reluctant.enable (opts.reluctantint, opts.reluctantmax);
|
|
605
|
+
} else
|
|
606
|
+
reluctant.disable ();
|
|
607
|
+
|
|
608
|
+
/*----------------------------------------------------------------------*/
|
|
609
|
+
|
|
610
|
+
// Conflict and decision limits.
|
|
611
|
+
|
|
612
|
+
if (inc.conflicts < 0) {
|
|
613
|
+
lim.conflicts = -1;
|
|
614
|
+
LOG ("no limit on conflicts");
|
|
615
|
+
} else {
|
|
616
|
+
lim.conflicts = stats.conflicts + inc.conflicts;
|
|
617
|
+
LOG ("conflict limit after %" PRId64 " conflicts at %" PRId64
|
|
618
|
+
" conflicts",
|
|
619
|
+
inc.conflicts, lim.conflicts);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (inc.decisions < 0) {
|
|
623
|
+
lim.decisions = -1;
|
|
624
|
+
LOG ("no limit on decisions");
|
|
625
|
+
} else {
|
|
626
|
+
lim.decisions = stats.decisions + inc.decisions;
|
|
627
|
+
LOG ("decision limit after %" PRId64 " decisions at %" PRId64
|
|
628
|
+
" decisions",
|
|
629
|
+
inc.decisions, lim.decisions);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (inc.ticks < 0) {
|
|
633
|
+
lim.ticks = -1;
|
|
634
|
+
LOG ("no limit on ticks");
|
|
635
|
+
} else {
|
|
636
|
+
lim.ticks = stats.ticks.search[0] + stats.ticks.search[1] + inc.ticks;
|
|
637
|
+
LOG ("ticks limit after %" PRId64 " ticks at %" PRId64 " ticks",
|
|
638
|
+
inc.ticks, lim.ticks);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/*----------------------------------------------------------------------*/
|
|
642
|
+
|
|
643
|
+
// Initial preprocessing rounds.
|
|
644
|
+
|
|
645
|
+
if (inc.localsearch <= 0) {
|
|
646
|
+
lim.localsearch = 0;
|
|
647
|
+
LOG ("no local search");
|
|
648
|
+
} else {
|
|
649
|
+
lim.localsearch = inc.localsearch;
|
|
650
|
+
LOG ("limiting to %" PRId64 " local search rounds", lim.localsearch);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/*----------------------------------------------------------------------*/
|
|
654
|
+
// tier 1 and tier 2 limits
|
|
655
|
+
if (incremental && opts.recomputetier) {
|
|
656
|
+
for (auto m : {true, false})
|
|
657
|
+
for (auto &u : stats.used[m])
|
|
658
|
+
u = 0;
|
|
659
|
+
stats.bump_used = {0, 0};
|
|
660
|
+
for (auto u : {true, false}) {
|
|
661
|
+
tier1[u] = max (tier1[u], opts.tier1minglue ? opts.tier1minglue : 2);
|
|
662
|
+
tier2[u] = max (tier2[u], opts.tier2minglue ? opts.tier2minglue : 6);
|
|
663
|
+
}
|
|
664
|
+
stats.tierecomputed = 0;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/*----------------------------------------------------------------------*/
|
|
668
|
+
// clause decaying
|
|
669
|
+
if (incremental)
|
|
670
|
+
last.incremental_decay.last_id = 0;
|
|
671
|
+
else {
|
|
672
|
+
lim.incremental_decay = opts.incdecayint;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/*----------------------------------------------------------------------*/
|
|
676
|
+
|
|
677
|
+
if (incremental)
|
|
678
|
+
mode = "keeping";
|
|
679
|
+
else {
|
|
680
|
+
lim.random_decision = stats.conflicts + opts.randecinit;
|
|
681
|
+
mode = "initial";
|
|
682
|
+
}
|
|
683
|
+
(void) mode;
|
|
684
|
+
LOG ("%s randomize decision limit %" PRId64 " after %" PRId64
|
|
685
|
+
" conflicts",
|
|
686
|
+
mode, lim.random_decision, lim.random_decision - stats.conflicts);
|
|
687
|
+
|
|
688
|
+
/*----------------------------------------------------------------------*/
|
|
689
|
+
|
|
690
|
+
lim.initialized = true;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/*------------------------------------------------------------------------*/
|
|
694
|
+
|
|
695
|
+
bool Internal::preprocess_round (int round) {
|
|
696
|
+
(void) round;
|
|
697
|
+
if (unsat)
|
|
698
|
+
return false;
|
|
699
|
+
if (!max_var)
|
|
700
|
+
return false;
|
|
701
|
+
START (preprocess);
|
|
702
|
+
struct {
|
|
703
|
+
int64_t vars, clauses;
|
|
704
|
+
} before, after;
|
|
705
|
+
before.vars = active ();
|
|
706
|
+
before.clauses = stats.current.irredundant;
|
|
707
|
+
stats.preprocessings++;
|
|
708
|
+
assert (!preprocessing);
|
|
709
|
+
preprocessing = true;
|
|
710
|
+
PHASE ("preprocessing", stats.preprocessings,
|
|
711
|
+
"starting round %d with %" PRId64 " variables and %" PRId64
|
|
712
|
+
" clauses",
|
|
713
|
+
round, before.vars, before.clauses);
|
|
714
|
+
int old_elimbound = lim.elimbound;
|
|
715
|
+
if (opts.inprobing)
|
|
716
|
+
inprobe (false);
|
|
717
|
+
if (opts.elim)
|
|
718
|
+
elim (false);
|
|
719
|
+
if (opts.condition)
|
|
720
|
+
condition (false);
|
|
721
|
+
|
|
722
|
+
after.vars = active ();
|
|
723
|
+
after.clauses = stats.current.irredundant;
|
|
724
|
+
assert (preprocessing);
|
|
725
|
+
preprocessing = false;
|
|
726
|
+
PHASE ("preprocessing", stats.preprocessings,
|
|
727
|
+
"finished round %d with %" PRId64 " variables and %" PRId64
|
|
728
|
+
" clauses",
|
|
729
|
+
round, after.vars, after.clauses);
|
|
730
|
+
STOP (preprocess);
|
|
731
|
+
report ('P');
|
|
732
|
+
if (unsat)
|
|
733
|
+
return false;
|
|
734
|
+
if (after.vars < before.vars)
|
|
735
|
+
return true;
|
|
736
|
+
if (old_elimbound < lim.elimbound)
|
|
737
|
+
return true;
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// for now counts as one of the preprocessing rounds TODO: change this?
|
|
742
|
+
void Internal::preprocess_quickly (bool always) {
|
|
743
|
+
if (unsat)
|
|
744
|
+
return;
|
|
745
|
+
if (!max_var)
|
|
746
|
+
return;
|
|
747
|
+
if (!opts.preprocesslight)
|
|
748
|
+
return;
|
|
749
|
+
if (!always && stats.searches > 1)
|
|
750
|
+
return;
|
|
751
|
+
START (preprocess);
|
|
752
|
+
#ifndef QUIET
|
|
753
|
+
struct {
|
|
754
|
+
int64_t vars, clauses;
|
|
755
|
+
} before, after;
|
|
756
|
+
before.vars = active ();
|
|
757
|
+
before.clauses = stats.current.irredundant;
|
|
758
|
+
#endif
|
|
759
|
+
// stats.preprocessings++;
|
|
760
|
+
assert (!preprocessing);
|
|
761
|
+
preprocessing = true;
|
|
762
|
+
report ('(');
|
|
763
|
+
PHASE ("preprocessing", stats.preprocessings,
|
|
764
|
+
"starting with %" PRId64 " variables and %" PRId64 " clauses",
|
|
765
|
+
before.vars, before.clauses);
|
|
766
|
+
|
|
767
|
+
if (extract_gates (true))
|
|
768
|
+
decompose ();
|
|
769
|
+
binary_clauses_backbone ();
|
|
770
|
+
|
|
771
|
+
if (sweep ())
|
|
772
|
+
decompose ();
|
|
773
|
+
|
|
774
|
+
if (opts.factor)
|
|
775
|
+
factor ();
|
|
776
|
+
|
|
777
|
+
if (opts.fastelim)
|
|
778
|
+
elimfast ();
|
|
779
|
+
// if (opts.condition)
|
|
780
|
+
// condition (false);
|
|
781
|
+
#ifndef QUIET
|
|
782
|
+
after.vars = active ();
|
|
783
|
+
after.clauses = stats.current.irredundant;
|
|
784
|
+
#endif
|
|
785
|
+
assert (preprocessing);
|
|
786
|
+
preprocessing = false;
|
|
787
|
+
PHASE ("preprocessing", stats.preprocessings,
|
|
788
|
+
"finished with %" PRId64 " variables and %" PRId64 " clauses",
|
|
789
|
+
after.vars, after.clauses);
|
|
790
|
+
STOP (preprocess);
|
|
791
|
+
report ('P');
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
int Internal::preprocess (bool always) {
|
|
795
|
+
int res = 0;
|
|
796
|
+
if (!level && !unsat && opts.luckyearly)
|
|
797
|
+
res = lucky_phases ();
|
|
798
|
+
if (res)
|
|
799
|
+
return res;
|
|
800
|
+
|
|
801
|
+
if (opts.deduplicateallinit && !stats.deduplicatedinitrounds)
|
|
802
|
+
deduplicate_all_clauses ();
|
|
803
|
+
|
|
804
|
+
preprocess_quickly (always);
|
|
805
|
+
for (int i = 0; i < lim.preprocessing; i++)
|
|
806
|
+
if (!preprocess_round (i))
|
|
807
|
+
break;
|
|
808
|
+
report (')');
|
|
809
|
+
if (unsat)
|
|
810
|
+
return 20;
|
|
811
|
+
return 0;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/*------------------------------------------------------------------------*/
|
|
815
|
+
|
|
816
|
+
int Internal::try_to_satisfy_formula_by_saved_phases () {
|
|
817
|
+
LOG ("satisfying formula by saved phases");
|
|
818
|
+
assert (!level);
|
|
819
|
+
assert (!force_saved_phase);
|
|
820
|
+
assert (propagated == trail.size ());
|
|
821
|
+
force_saved_phase = true;
|
|
822
|
+
if (external_prop) {
|
|
823
|
+
assert (!level);
|
|
824
|
+
LOG ("external notifications are turned off during preprocessing.");
|
|
825
|
+
private_steps = true;
|
|
826
|
+
}
|
|
827
|
+
int res = 0;
|
|
828
|
+
while (!res) {
|
|
829
|
+
if (satisfied ()) {
|
|
830
|
+
LOG ("formula indeed satisfied by saved phases");
|
|
831
|
+
res = 10;
|
|
832
|
+
} else if (decide ()) {
|
|
833
|
+
LOG ("inconsistent assumptions with redundant clauses and phases");
|
|
834
|
+
res = 20;
|
|
835
|
+
} else if (!propagate ()) {
|
|
836
|
+
LOG ("saved phases do not satisfy redundant clauses");
|
|
837
|
+
assert (level > 0);
|
|
838
|
+
backtrack ();
|
|
839
|
+
conflict = 0; // ignore conflict
|
|
840
|
+
assert (!res);
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
assert (force_saved_phase);
|
|
845
|
+
force_saved_phase = false;
|
|
846
|
+
if (external_prop) {
|
|
847
|
+
private_steps = false;
|
|
848
|
+
LOG ("external notifications are turned back on.");
|
|
849
|
+
if (!level)
|
|
850
|
+
notify_assignments (); // In case fixed assignments were found.
|
|
851
|
+
else {
|
|
852
|
+
renotify_trail_after_local_search ();
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return res;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/*------------------------------------------------------------------------*/
|
|
859
|
+
|
|
860
|
+
void Internal::produce_failed_assumptions () {
|
|
861
|
+
LOG ("producing failed assumptions");
|
|
862
|
+
assert (!level);
|
|
863
|
+
assert (!assumptions.empty ());
|
|
864
|
+
while (!unsat) {
|
|
865
|
+
assert (!satisfied ());
|
|
866
|
+
notify_assignments ();
|
|
867
|
+
if (decide ())
|
|
868
|
+
break;
|
|
869
|
+
while (!unsat && !propagate ())
|
|
870
|
+
analyze ();
|
|
871
|
+
}
|
|
872
|
+
notify_assignments ();
|
|
873
|
+
if (unsat)
|
|
874
|
+
LOG ("formula is actually unsatisfiable unconditionally");
|
|
875
|
+
else
|
|
876
|
+
LOG ("assumptions indeed failing");
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/*------------------------------------------------------------------------*/
|
|
880
|
+
|
|
881
|
+
int Internal::local_search_round (int round) {
|
|
882
|
+
|
|
883
|
+
assert (round > 0);
|
|
884
|
+
|
|
885
|
+
if (unsat)
|
|
886
|
+
return false;
|
|
887
|
+
if (!max_var)
|
|
888
|
+
return false;
|
|
889
|
+
|
|
890
|
+
START_OUTER_WALK ();
|
|
891
|
+
assert (!localsearching);
|
|
892
|
+
localsearching = true;
|
|
893
|
+
|
|
894
|
+
// Determine propagation limit quadratically scaled with rounds.
|
|
895
|
+
//
|
|
896
|
+
int64_t limit = opts.walkmineff;
|
|
897
|
+
limit *= round;
|
|
898
|
+
if (LONG_MAX / round > limit)
|
|
899
|
+
limit *= round;
|
|
900
|
+
else
|
|
901
|
+
limit = LONG_MAX;
|
|
902
|
+
|
|
903
|
+
int res;
|
|
904
|
+
if (opts.walkfullocc)
|
|
905
|
+
res = walk_full_occs_round (limit, true);
|
|
906
|
+
else
|
|
907
|
+
res = walk_round (limit, true);
|
|
908
|
+
|
|
909
|
+
assert (localsearching);
|
|
910
|
+
localsearching = false;
|
|
911
|
+
STOP_OUTER_WALK ();
|
|
912
|
+
|
|
913
|
+
report ('L');
|
|
914
|
+
|
|
915
|
+
return res;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
int Internal::local_search () {
|
|
919
|
+
|
|
920
|
+
if (unsat)
|
|
921
|
+
return 0;
|
|
922
|
+
if (!max_var)
|
|
923
|
+
return 0;
|
|
924
|
+
if (!opts.walk)
|
|
925
|
+
return 0;
|
|
926
|
+
if (constraint.size ())
|
|
927
|
+
return 0;
|
|
928
|
+
|
|
929
|
+
int res = 0;
|
|
930
|
+
|
|
931
|
+
for (int i = 1; !res && i <= lim.localsearch; i++)
|
|
932
|
+
res = local_search_round (i);
|
|
933
|
+
|
|
934
|
+
if (res == 10) {
|
|
935
|
+
LOG ("local search determined formula to be satisfiable");
|
|
936
|
+
assert (!stats.walk.minimum);
|
|
937
|
+
res = try_to_satisfy_formula_by_saved_phases ();
|
|
938
|
+
} else if (res == 20) {
|
|
939
|
+
LOG ("local search determined assumptions to be inconsistent");
|
|
940
|
+
assert (!assumptions.empty ());
|
|
941
|
+
produce_failed_assumptions ();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
return res;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/*------------------------------------------------------------------------*/
|
|
948
|
+
|
|
949
|
+
// if preprocess_only is false and opts.ilb is true we do not preprocess
|
|
950
|
+
// such that we do not have to backtrack to level 0.
|
|
951
|
+
//
|
|
952
|
+
int Internal::solve (bool preprocess_only) {
|
|
953
|
+
assert (clause.empty ());
|
|
954
|
+
stats.searches++;
|
|
955
|
+
START (solve);
|
|
956
|
+
if (proof)
|
|
957
|
+
proof->solve_query ();
|
|
958
|
+
if (opts.ilb) {
|
|
959
|
+
sort_and_reuse_assumptions ();
|
|
960
|
+
assert (opts.ilb || (size_t) level <= assumptions.size ());
|
|
961
|
+
stats.ilbtriggers++;
|
|
962
|
+
stats.ilbsuccess += (level > 0);
|
|
963
|
+
stats.levelsreused += level;
|
|
964
|
+
if (level) {
|
|
965
|
+
assert (control.size () > 1);
|
|
966
|
+
stats.literalsreused += num_assigned - control[1].trail;
|
|
967
|
+
}
|
|
968
|
+
if (external->propagator)
|
|
969
|
+
renotify_trail_after_ilb ();
|
|
970
|
+
}
|
|
971
|
+
if (preprocess_only)
|
|
972
|
+
LOG ("internal solving in preprocessing only mode");
|
|
973
|
+
else
|
|
974
|
+
LOG ("internal solving in full mode");
|
|
975
|
+
init_report_limits ();
|
|
976
|
+
int res = already_solved ();
|
|
977
|
+
if (!res && preprocess_only && level)
|
|
978
|
+
backtrack ();
|
|
979
|
+
if (!res)
|
|
980
|
+
res = restore_clauses ();
|
|
981
|
+
if (!res || (res == 10 && external_prop)) {
|
|
982
|
+
init_preprocessing_limits ();
|
|
983
|
+
if (!preprocess_only)
|
|
984
|
+
init_search_limits ();
|
|
985
|
+
}
|
|
986
|
+
if (!preprocess_only) {
|
|
987
|
+
if (!res && !level)
|
|
988
|
+
res = local_search ();
|
|
989
|
+
}
|
|
990
|
+
if (!res && !level)
|
|
991
|
+
res = preprocess (preprocess_only);
|
|
992
|
+
if (!preprocess_only) {
|
|
993
|
+
if (!res && !level && opts.luckylate)
|
|
994
|
+
res = lucky_phases ();
|
|
995
|
+
if (!res && !level)
|
|
996
|
+
res = local_search ();
|
|
997
|
+
if (!res)
|
|
998
|
+
decay_clauses_upon_incremental_clauses ();
|
|
999
|
+
if (!res || (res == 10 && external_prop)) {
|
|
1000
|
+
if (res == 10 && external_prop && level)
|
|
1001
|
+
backtrack ();
|
|
1002
|
+
res = cdcl_loop_with_inprocessing ();
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
finalize (res);
|
|
1006
|
+
reset_solving ();
|
|
1007
|
+
report_solving (res);
|
|
1008
|
+
STOP (solve);
|
|
1009
|
+
return res;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
int Internal::already_solved () {
|
|
1013
|
+
int res = 0;
|
|
1014
|
+
if (unsat || unsat_constraint) {
|
|
1015
|
+
LOG ("already inconsistent");
|
|
1016
|
+
res = 20;
|
|
1017
|
+
} else {
|
|
1018
|
+
if (level && !opts.ilb)
|
|
1019
|
+
backtrack ();
|
|
1020
|
+
if (!level && !propagate ()) {
|
|
1021
|
+
LOG ("root level propagation produces conflict");
|
|
1022
|
+
learn_empty_clause ();
|
|
1023
|
+
res = 20;
|
|
1024
|
+
}
|
|
1025
|
+
if (max_var == 0 && res == 0)
|
|
1026
|
+
res = 10;
|
|
1027
|
+
}
|
|
1028
|
+
return res;
|
|
1029
|
+
}
|
|
1030
|
+
void Internal::report_solving (int res) {
|
|
1031
|
+
if (res == 10)
|
|
1032
|
+
report ('1');
|
|
1033
|
+
else if (res == 20)
|
|
1034
|
+
report ('0');
|
|
1035
|
+
else
|
|
1036
|
+
report ('?');
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
void Internal::reset_solving () {
|
|
1040
|
+
if (termination_forced) {
|
|
1041
|
+
|
|
1042
|
+
// TODO this leads potentially to a data race if the external
|
|
1043
|
+
// user is calling 'terminate' twice within one 'solve' call.
|
|
1044
|
+
// A proper solution would be to guard / protect setting the
|
|
1045
|
+
// 'termination_forced' flag and only allow it during solving and
|
|
1046
|
+
// ignore it otherwise thus also the second time it is called during a
|
|
1047
|
+
// 'solve' call. We could move resetting it also the start of
|
|
1048
|
+
// 'solve'.
|
|
1049
|
+
//
|
|
1050
|
+
termination_forced = false;
|
|
1051
|
+
|
|
1052
|
+
LOG ("reset forced termination");
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
int Internal::restore_clauses () {
|
|
1057
|
+
int res = 0;
|
|
1058
|
+
if (opts.restoreall <= 1 && external->tainted.empty ()) {
|
|
1059
|
+
LOG ("no tainted literals and nothing to restore");
|
|
1060
|
+
report ('*');
|
|
1061
|
+
} else {
|
|
1062
|
+
report ('+');
|
|
1063
|
+
// remove_garbage_binaries ();
|
|
1064
|
+
external->restore_clauses ();
|
|
1065
|
+
internal->report ('r');
|
|
1066
|
+
if (!unsat && !level && !propagate ()) {
|
|
1067
|
+
LOG ("root level propagation after restore produces conflict");
|
|
1068
|
+
learn_empty_clause ();
|
|
1069
|
+
res = 20;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
return res;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
int Internal::lookahead () {
|
|
1076
|
+
assert (clause.empty ());
|
|
1077
|
+
START (lookahead);
|
|
1078
|
+
assert (!lookingahead);
|
|
1079
|
+
lookingahead = true;
|
|
1080
|
+
if (external_prop) {
|
|
1081
|
+
if (level) {
|
|
1082
|
+
// Combining lookahead with external propagator is limited
|
|
1083
|
+
// Note that lookahead_probing (); would also force backtrack anyway
|
|
1084
|
+
backtrack ();
|
|
1085
|
+
}
|
|
1086
|
+
LOG ("external notifications are turned off during preprocessing.");
|
|
1087
|
+
private_steps = true;
|
|
1088
|
+
}
|
|
1089
|
+
int tmp = already_solved ();
|
|
1090
|
+
if (!tmp)
|
|
1091
|
+
tmp = restore_clauses ();
|
|
1092
|
+
int res = 0;
|
|
1093
|
+
if (!tmp)
|
|
1094
|
+
res = lookahead_probing ();
|
|
1095
|
+
if (res == INT_MIN)
|
|
1096
|
+
res = 0;
|
|
1097
|
+
reset_solving ();
|
|
1098
|
+
report_solving (tmp);
|
|
1099
|
+
assert (lookingahead);
|
|
1100
|
+
lookingahead = false;
|
|
1101
|
+
STOP (lookahead);
|
|
1102
|
+
if (external_prop) {
|
|
1103
|
+
private_steps = false;
|
|
1104
|
+
LOG ("external notifications are turned back on.");
|
|
1105
|
+
notify_assignments (); // In case fixed assignments were found.
|
|
1106
|
+
}
|
|
1107
|
+
return res;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/*------------------------------------------------------------------------*/
|
|
1111
|
+
|
|
1112
|
+
void Internal::finalize (int res) {
|
|
1113
|
+
if (!proof)
|
|
1114
|
+
return;
|
|
1115
|
+
LOG ("finalizing");
|
|
1116
|
+
// finalize external units
|
|
1117
|
+
if (frat) {
|
|
1118
|
+
for (const auto &evar : external->vars) {
|
|
1119
|
+
assert (evar > 0);
|
|
1120
|
+
const auto eidx = 2 * evar;
|
|
1121
|
+
int sign = 1;
|
|
1122
|
+
int64_t id = external->ext_units[eidx];
|
|
1123
|
+
if (!id) {
|
|
1124
|
+
sign = -1;
|
|
1125
|
+
id = external->ext_units[eidx + 1];
|
|
1126
|
+
}
|
|
1127
|
+
if (id) {
|
|
1128
|
+
proof->finalize_external_unit (id, evar * sign);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
// finalize internal units
|
|
1132
|
+
for (const auto &lit : lits) {
|
|
1133
|
+
const auto elit = externalize (lit);
|
|
1134
|
+
if (elit) {
|
|
1135
|
+
const unsigned eidx = (elit < 0) + 2u * (unsigned) abs (elit);
|
|
1136
|
+
const int64_t id = external->ext_units[eidx];
|
|
1137
|
+
if (id) {
|
|
1138
|
+
assert (unit_clauses (vlit (lit)) == id);
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
const int64_t id = unit_clauses (vlit (lit));
|
|
1143
|
+
if (!id)
|
|
1144
|
+
continue;
|
|
1145
|
+
proof->finalize_unit (id, lit);
|
|
1146
|
+
}
|
|
1147
|
+
// See the discussion in 'propagate' on why garbage binary clauses stick
|
|
1148
|
+
// around.
|
|
1149
|
+
for (const auto &c : clauses)
|
|
1150
|
+
if (!c->garbage || (c->size == 2 && !c->flushed))
|
|
1151
|
+
proof->finalize_clause (c);
|
|
1152
|
+
|
|
1153
|
+
// finalize conflict and proof
|
|
1154
|
+
if (conflict_id) {
|
|
1155
|
+
proof->finalize_clause (conflict_id, {});
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
proof->report_status (res, conflict_id);
|
|
1159
|
+
if (res == 10)
|
|
1160
|
+
external->conclude_sat ();
|
|
1161
|
+
else if (res == 20)
|
|
1162
|
+
conclude_unsat ();
|
|
1163
|
+
else if (!res)
|
|
1164
|
+
external->conclude_unknown ();
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/*------------------------------------------------------------------------*/
|
|
1168
|
+
|
|
1169
|
+
void Internal::print_statistics () {
|
|
1170
|
+
stats.print (this);
|
|
1171
|
+
for (auto &st : stat_tracers)
|
|
1172
|
+
st->print_stats ();
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/*------------------------------------------------------------------------*/
|
|
1176
|
+
|
|
1177
|
+
// Only useful for debugging purposes.
|
|
1178
|
+
|
|
1179
|
+
void Internal::dump (Clause *c) {
|
|
1180
|
+
for (const auto &lit : *c)
|
|
1181
|
+
printf ("%d ", lit);
|
|
1182
|
+
printf ("0\n");
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
void Internal::dump () {
|
|
1186
|
+
int64_t m = assumptions.size ();
|
|
1187
|
+
for (auto idx : vars)
|
|
1188
|
+
if (fixed (idx))
|
|
1189
|
+
m++;
|
|
1190
|
+
for (const auto &c : clauses)
|
|
1191
|
+
if (!c->garbage)
|
|
1192
|
+
m++;
|
|
1193
|
+
printf ("p cnf %d %" PRId64 "\n", max_var, m);
|
|
1194
|
+
for (auto idx : vars) {
|
|
1195
|
+
const int tmp = fixed (idx);
|
|
1196
|
+
if (tmp)
|
|
1197
|
+
printf ("%d 0\n", tmp < 0 ? -idx : idx);
|
|
1198
|
+
}
|
|
1199
|
+
for (const auto &c : clauses)
|
|
1200
|
+
if (!c->garbage)
|
|
1201
|
+
dump (c);
|
|
1202
|
+
for (const auto &lit : assumptions)
|
|
1203
|
+
printf ("%d 0\n", lit);
|
|
1204
|
+
fflush (stdout);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/*------------------------------------------------------------------------*/
|
|
1208
|
+
|
|
1209
|
+
bool Internal::traverse_constraint (ClauseIterator &it) {
|
|
1210
|
+
if (constraint.empty () && !unsat_constraint)
|
|
1211
|
+
return true;
|
|
1212
|
+
|
|
1213
|
+
vector<int> eclause;
|
|
1214
|
+
if (unsat)
|
|
1215
|
+
return it.clause (eclause);
|
|
1216
|
+
|
|
1217
|
+
LOG (constraint, "traversing constraint");
|
|
1218
|
+
bool satisfied = false;
|
|
1219
|
+
for (auto ilit : constraint) {
|
|
1220
|
+
const int tmp = fixed (ilit);
|
|
1221
|
+
if (tmp > 0) {
|
|
1222
|
+
satisfied = true;
|
|
1223
|
+
break;
|
|
1224
|
+
}
|
|
1225
|
+
if (tmp < 0)
|
|
1226
|
+
continue;
|
|
1227
|
+
const int elit = externalize (ilit);
|
|
1228
|
+
eclause.push_back (elit);
|
|
1229
|
+
}
|
|
1230
|
+
if (!satisfied && !it.clause (eclause))
|
|
1231
|
+
return false;
|
|
1232
|
+
|
|
1233
|
+
return true;
|
|
1234
|
+
}
|
|
1235
|
+
/*------------------------------------------------------------------------*/
|
|
1236
|
+
|
|
1237
|
+
bool Internal::traverse_clauses (ClauseIterator &it) {
|
|
1238
|
+
vector<int> eclause;
|
|
1239
|
+
if (unsat)
|
|
1240
|
+
return it.clause (eclause);
|
|
1241
|
+
for (const auto &c : clauses) {
|
|
1242
|
+
if (c->garbage)
|
|
1243
|
+
continue;
|
|
1244
|
+
if (c->redundant)
|
|
1245
|
+
continue;
|
|
1246
|
+
bool satisfied = false;
|
|
1247
|
+
for (const auto &ilit : *c) {
|
|
1248
|
+
const int tmp = fixed (ilit);
|
|
1249
|
+
if (tmp > 0) {
|
|
1250
|
+
satisfied = true;
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
if (tmp < 0)
|
|
1254
|
+
continue;
|
|
1255
|
+
const int elit = externalize (ilit);
|
|
1256
|
+
eclause.push_back (elit);
|
|
1257
|
+
}
|
|
1258
|
+
if (!satisfied && !it.clause (eclause))
|
|
1259
|
+
return false;
|
|
1260
|
+
eclause.clear ();
|
|
1261
|
+
}
|
|
1262
|
+
return true;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
} // namespace CaDiCaL
|