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,53 @@
|
|
|
1
|
+
#ifndef _elim_hpp_INCLUDED
|
|
2
|
+
#define _elim_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include "heap.hpp" // Alphabetically after 'elim.hpp'.
|
|
5
|
+
|
|
6
|
+
namespace CaDiCaL {
|
|
7
|
+
|
|
8
|
+
struct Internal;
|
|
9
|
+
|
|
10
|
+
struct elim_more {
|
|
11
|
+
Internal *internal;
|
|
12
|
+
elim_more (Internal *i) : internal (i) {}
|
|
13
|
+
bool operator() (unsigned a, unsigned b);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
typedef heap<elim_more> ElimSchedule;
|
|
17
|
+
|
|
18
|
+
struct proof_clause {
|
|
19
|
+
int64_t id;
|
|
20
|
+
vector<int> literals;
|
|
21
|
+
// for lrat
|
|
22
|
+
unsigned cid; // kitten id
|
|
23
|
+
bool learned;
|
|
24
|
+
vector<int64_t> chain;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
enum GateType { NO = 0, EQUI = 1, AND = 2, ITE = 3, XOR = 4, DEF = 5 };
|
|
28
|
+
|
|
29
|
+
struct Eliminator {
|
|
30
|
+
|
|
31
|
+
Internal *internal;
|
|
32
|
+
ElimSchedule schedule;
|
|
33
|
+
|
|
34
|
+
Eliminator (Internal *i)
|
|
35
|
+
: internal (i), schedule (elim_more (i)), definition_unit (0),
|
|
36
|
+
gatetype (NO) {}
|
|
37
|
+
~Eliminator ();
|
|
38
|
+
|
|
39
|
+
queue<Clause *> backward;
|
|
40
|
+
|
|
41
|
+
Clause *dequeue ();
|
|
42
|
+
void enqueue (Clause *);
|
|
43
|
+
|
|
44
|
+
vector<Clause *> gates;
|
|
45
|
+
unsigned definition_unit;
|
|
46
|
+
vector<proof_clause> proof_clauses;
|
|
47
|
+
vector<int> marked;
|
|
48
|
+
GateType gatetype;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
} // namespace CaDiCaL
|
|
52
|
+
|
|
53
|
+
#endif
|
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
// Implements a variant of elimination with a much lower limit to be run as
|
|
8
|
+
// preprocessing. See elim for comments
|
|
9
|
+
|
|
10
|
+
/*------------------------------------------------------------------------*/
|
|
11
|
+
|
|
12
|
+
// Flush garbage clause, check fast elimination limits and return number of
|
|
13
|
+
// remaining occurrences (or 'fastelimbound + 1' if some limit was hit).
|
|
14
|
+
|
|
15
|
+
int64_t Internal::flush_elimfast_occs (int lit) {
|
|
16
|
+
const int64_t occslim = opts.fastelimocclim;
|
|
17
|
+
const int64_t clslim = opts.fastelimclslim;
|
|
18
|
+
const int64_t failed = occslim + 1;
|
|
19
|
+
Occs &os = occs (lit);
|
|
20
|
+
const const_occs_iterator end = os.end ();
|
|
21
|
+
occs_iterator j = os.begin (), i = j;
|
|
22
|
+
int64_t res = 0;
|
|
23
|
+
while (i != end) {
|
|
24
|
+
Clause *c = *i++;
|
|
25
|
+
if (c->collect ())
|
|
26
|
+
continue;
|
|
27
|
+
*j++ = c;
|
|
28
|
+
if (c->size > clslim) {
|
|
29
|
+
res = failed;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
if (++res > occslim) {
|
|
33
|
+
assert (opts.fastelimbound < 0 || res == failed);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (i != j) {
|
|
38
|
+
while (i != end)
|
|
39
|
+
*j++ = *i++;
|
|
40
|
+
os.resize (j - os.begin ());
|
|
41
|
+
shrink_occs (os);
|
|
42
|
+
}
|
|
43
|
+
return res;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/*------------------------------------------------------------------------*/
|
|
47
|
+
|
|
48
|
+
// Check whether the number of non-tautological resolvents on 'pivot' is
|
|
49
|
+
// smaller or equal to the number of clauses with 'pivot' or '-pivot'. This
|
|
50
|
+
// is the main criteria of bounded variable elimination. As a side effect
|
|
51
|
+
// it flushes garbage clauses with that variable, sorts its occurrence lists
|
|
52
|
+
// (smallest clauses first) and also negates pivot if it has more positive
|
|
53
|
+
// than negative occurrences.
|
|
54
|
+
|
|
55
|
+
bool Internal::elimfast_resolvents_are_bounded (Eliminator &eliminator,
|
|
56
|
+
int pivot) {
|
|
57
|
+
assert (eliminator.gates.empty ());
|
|
58
|
+
assert (!eliminator.definition_unit);
|
|
59
|
+
|
|
60
|
+
stats.elimtried++;
|
|
61
|
+
|
|
62
|
+
assert (!unsat);
|
|
63
|
+
assert (active (pivot));
|
|
64
|
+
|
|
65
|
+
const Occs &ps = occs (pivot);
|
|
66
|
+
const Occs &ns = occs (-pivot);
|
|
67
|
+
|
|
68
|
+
int64_t pos = ps.size ();
|
|
69
|
+
int64_t neg = ns.size ();
|
|
70
|
+
|
|
71
|
+
int64_t bound = opts.fastelimbound;
|
|
72
|
+
|
|
73
|
+
if (!pos || !neg)
|
|
74
|
+
return bound >= 0;
|
|
75
|
+
|
|
76
|
+
const int64_t sum = pos + neg;
|
|
77
|
+
const int64_t product = pos * neg;
|
|
78
|
+
if (bound > sum)
|
|
79
|
+
bound = sum;
|
|
80
|
+
|
|
81
|
+
LOG ("checking number resolvents on %d bounded by "
|
|
82
|
+
"%" PRId64 " = %" PRId64 " + %" PRId64 " + %d",
|
|
83
|
+
pivot, bound, pos, neg, opts.fastelimbound);
|
|
84
|
+
|
|
85
|
+
if (product <= bound) {
|
|
86
|
+
LOG ("fast elimination occurrence limits sufficiently small enough");
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Try all resolutions between a positive occurrence (outer loop) of
|
|
91
|
+
// 'pivot' and a negative occurrence of 'pivot' (inner loop) as long the
|
|
92
|
+
// bound on non-tautological resolvents is not hit and the size of the
|
|
93
|
+
// generated resolvents does not exceed the resolvent clause size limit.
|
|
94
|
+
|
|
95
|
+
int64_t resolvents = 0; // Non-tautological resolvents.
|
|
96
|
+
|
|
97
|
+
for (const auto &c : ps) {
|
|
98
|
+
assert (!c->redundant);
|
|
99
|
+
if (c->garbage)
|
|
100
|
+
continue;
|
|
101
|
+
for (const auto &d : ns) {
|
|
102
|
+
assert (!d->redundant);
|
|
103
|
+
if (d->garbage)
|
|
104
|
+
continue;
|
|
105
|
+
if (resolve_clauses (eliminator, c, pivot, d, true)) {
|
|
106
|
+
resolvents++;
|
|
107
|
+
int size = clause.size ();
|
|
108
|
+
clause.clear ();
|
|
109
|
+
LOG ("now at least %" PRId64
|
|
110
|
+
" non-tautological resolvents on pivot %d",
|
|
111
|
+
resolvents, pivot);
|
|
112
|
+
if (size > opts.fastelimclslim) {
|
|
113
|
+
LOG ("resolvent size %d too big after %" PRId64
|
|
114
|
+
" resolvents on %d",
|
|
115
|
+
size, resolvents, pivot);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (resolvents > bound) {
|
|
119
|
+
LOG ("too many non-tautological resolvents on %d", pivot);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
} else if (unsat)
|
|
123
|
+
return false;
|
|
124
|
+
else if (val (pivot))
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
LOG ("need %" PRId64 " <= %" PRId64 " non-tautological resolvents",
|
|
130
|
+
resolvents, bound);
|
|
131
|
+
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
/*------------------------------------------------------------------------*/
|
|
135
|
+
|
|
136
|
+
/*------------------------------------------------------------------------*/
|
|
137
|
+
// Add all resolvents on 'pivot' and connect them.
|
|
138
|
+
|
|
139
|
+
inline void Internal::elimfast_add_resolvents (Eliminator &eliminator,
|
|
140
|
+
int pivot) {
|
|
141
|
+
|
|
142
|
+
assert (eliminator.gates.empty ());
|
|
143
|
+
assert (!eliminator.definition_unit);
|
|
144
|
+
|
|
145
|
+
LOG ("adding all resolvents on %d", pivot);
|
|
146
|
+
|
|
147
|
+
assert (!val (pivot));
|
|
148
|
+
assert (!flags (pivot).eliminated ());
|
|
149
|
+
|
|
150
|
+
const Occs &ps = occs (pivot);
|
|
151
|
+
const Occs &ns = occs (-pivot);
|
|
152
|
+
#ifdef LOGGING
|
|
153
|
+
int64_t resolvents = 0;
|
|
154
|
+
#endif
|
|
155
|
+
for (auto &c : ps) {
|
|
156
|
+
if (unsat)
|
|
157
|
+
break;
|
|
158
|
+
if (c->garbage)
|
|
159
|
+
continue;
|
|
160
|
+
for (auto &d : ns) {
|
|
161
|
+
if (unsat)
|
|
162
|
+
break;
|
|
163
|
+
if (d->garbage)
|
|
164
|
+
continue;
|
|
165
|
+
if (!resolve_clauses (eliminator, c, pivot, d, false))
|
|
166
|
+
continue;
|
|
167
|
+
assert (!lrat || !lrat_chain.empty ());
|
|
168
|
+
Clause *r = new_resolved_irredundant_clause ();
|
|
169
|
+
elim_update_added_clause (eliminator, r);
|
|
170
|
+
eliminator.enqueue (r);
|
|
171
|
+
lrat_chain.clear ();
|
|
172
|
+
clause.clear ();
|
|
173
|
+
#ifdef LOGGING
|
|
174
|
+
resolvents++;
|
|
175
|
+
#endif
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
LOG ("added %" PRId64 " resolvents to eliminate %d", resolvents, pivot);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/*------------------------------------------------------------------------*/
|
|
183
|
+
|
|
184
|
+
// Try to eliminate 'pivot' by bounded variable elimination.
|
|
185
|
+
void Internal::try_to_fasteliminate_variable (Eliminator &eliminator,
|
|
186
|
+
int pivot,
|
|
187
|
+
bool &deleted_binary_clause) {
|
|
188
|
+
|
|
189
|
+
if (!active (pivot))
|
|
190
|
+
return;
|
|
191
|
+
assert (!frozen (pivot));
|
|
192
|
+
|
|
193
|
+
// First flush garbage clauses and check limits.
|
|
194
|
+
|
|
195
|
+
const int64_t occ_bound = opts.fastelimocclim;
|
|
196
|
+
int64_t bound = opts.fastelimbound;
|
|
197
|
+
|
|
198
|
+
int64_t pos = flush_elimfast_occs (pivot);
|
|
199
|
+
int64_t neg = flush_elimfast_occs (-pivot);
|
|
200
|
+
if (neg && pos > occ_bound) {
|
|
201
|
+
LOG ("too many occurrences thus not eliminated %d", pivot);
|
|
202
|
+
assert (!eliminator.schedule.contains (abs (pivot)));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (pos && neg > occ_bound) {
|
|
207
|
+
LOG ("too many occurrences thus not eliminated %d", -pivot);
|
|
208
|
+
assert (!eliminator.schedule.contains (abs (pivot)));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const int64_t product = pos * neg;
|
|
213
|
+
const int64_t sum = pos + neg;
|
|
214
|
+
if (bound > sum)
|
|
215
|
+
bound = sum;
|
|
216
|
+
|
|
217
|
+
if (pos > neg) {
|
|
218
|
+
pivot = -pivot;
|
|
219
|
+
swap (pos, neg);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
LOG ("pivot %d occurs positively %" PRId64
|
|
223
|
+
" times and negatively %" PRId64 " times",
|
|
224
|
+
pivot, pos, neg);
|
|
225
|
+
|
|
226
|
+
assert (!eliminator.schedule.contains (abs (pivot)));
|
|
227
|
+
assert (pos <= neg);
|
|
228
|
+
|
|
229
|
+
LOG ("trying to eliminate %d", pivot);
|
|
230
|
+
assert (!flags (pivot).eliminated ());
|
|
231
|
+
|
|
232
|
+
// Sort occurrence lists, such that shorter clauses come first.
|
|
233
|
+
Occs &ps = occs (pivot);
|
|
234
|
+
stable_sort (ps.begin (), ps.end (), clause_smaller_size ());
|
|
235
|
+
Occs &ns = occs (-pivot);
|
|
236
|
+
stable_sort (ns.begin (), ns.end (), clause_smaller_size ());
|
|
237
|
+
|
|
238
|
+
if (!unsat && !val (pivot)) {
|
|
239
|
+
if (product <= bound ||
|
|
240
|
+
elimfast_resolvents_are_bounded (eliminator, pivot)) {
|
|
241
|
+
LOG ("number of resolvents on %d are bounded", pivot);
|
|
242
|
+
elimfast_add_resolvents (eliminator, pivot);
|
|
243
|
+
if (!unsat)
|
|
244
|
+
mark_eliminated_clauses_as_garbage (eliminator, pivot,
|
|
245
|
+
deleted_binary_clause);
|
|
246
|
+
if (active (pivot))
|
|
247
|
+
mark_eliminated (pivot);
|
|
248
|
+
} else {
|
|
249
|
+
LOG ("too many resolvents on %d so not eliminated", pivot);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
unmark_gate_clauses (eliminator);
|
|
254
|
+
elim_backward_clauses (eliminator);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/*------------------------------------------------------------------------*/
|
|
258
|
+
|
|
259
|
+
// This function performs one round of bounded variable elimination and
|
|
260
|
+
// returns the number of eliminated variables. The additional result
|
|
261
|
+
// 'completed' is true if this elimination round ran to completion (all
|
|
262
|
+
// variables have been tried). Otherwise it was asynchronously terminated
|
|
263
|
+
// or the resolution limit was hit.
|
|
264
|
+
|
|
265
|
+
int Internal::elimfast_round (bool &completed,
|
|
266
|
+
bool &deleted_binary_clause) {
|
|
267
|
+
|
|
268
|
+
assert (opts.fastelim);
|
|
269
|
+
assert (!unsat);
|
|
270
|
+
|
|
271
|
+
START_SIMPLIFIER (fastelim, ELIM);
|
|
272
|
+
|
|
273
|
+
stats.elimfastrounds++;
|
|
274
|
+
|
|
275
|
+
assert (!level);
|
|
276
|
+
|
|
277
|
+
int64_t resolution_limit;
|
|
278
|
+
|
|
279
|
+
if (opts.elimlimited) {
|
|
280
|
+
int64_t delta = stats.propagations.search;
|
|
281
|
+
delta *= 1e-3 * opts.elimeffort;
|
|
282
|
+
if (delta < opts.elimmineff)
|
|
283
|
+
delta = opts.elimmineff;
|
|
284
|
+
if (delta > opts.elimmaxeff)
|
|
285
|
+
delta = opts.elimmaxeff;
|
|
286
|
+
|
|
287
|
+
PHASE ("fastelim-round", stats.elimfastrounds,
|
|
288
|
+
"limit of %" PRId64 " resolutions", delta);
|
|
289
|
+
|
|
290
|
+
resolution_limit = stats.elimres + delta;
|
|
291
|
+
} else {
|
|
292
|
+
PHASE ("fastelim-round", stats.elimfastrounds, "resolutions unlimited");
|
|
293
|
+
resolution_limit = LONG_MAX;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
init_noccs ();
|
|
297
|
+
|
|
298
|
+
// First compute the number of occurrences of each literal and at the same
|
|
299
|
+
// time mark satisfied clauses and update 'elim' flags of variables in
|
|
300
|
+
// clauses with root level assigned literals (both false and true).
|
|
301
|
+
//
|
|
302
|
+
for (const auto &c : clauses) {
|
|
303
|
+
if (c->garbage || c->redundant)
|
|
304
|
+
continue;
|
|
305
|
+
bool satisfied = false, falsified = false;
|
|
306
|
+
for (const auto &lit : *c) {
|
|
307
|
+
const signed char tmp = val (lit);
|
|
308
|
+
if (tmp > 0)
|
|
309
|
+
satisfied = true;
|
|
310
|
+
else if (tmp < 0)
|
|
311
|
+
falsified = true;
|
|
312
|
+
else
|
|
313
|
+
assert (active (lit));
|
|
314
|
+
}
|
|
315
|
+
if (satisfied)
|
|
316
|
+
mark_garbage (c); // forces more precise counts
|
|
317
|
+
else {
|
|
318
|
+
for (const auto &lit : *c) {
|
|
319
|
+
if (!active (lit))
|
|
320
|
+
continue;
|
|
321
|
+
if (falsified)
|
|
322
|
+
mark_elim (lit); // simulate unit propagation
|
|
323
|
+
noccs (lit)++;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
init_occs ();
|
|
329
|
+
|
|
330
|
+
Eliminator eliminator (this);
|
|
331
|
+
ElimSchedule &schedule = eliminator.schedule;
|
|
332
|
+
assert (schedule.empty ());
|
|
333
|
+
|
|
334
|
+
// Now find elimination candidates which occurred in clauses removed since
|
|
335
|
+
// the last time we ran bounded variable elimination, which in turned
|
|
336
|
+
// triggered their 'elim' bit to be set.
|
|
337
|
+
//
|
|
338
|
+
for (auto idx : vars) {
|
|
339
|
+
if (!active (idx))
|
|
340
|
+
continue;
|
|
341
|
+
if (frozen (idx))
|
|
342
|
+
continue;
|
|
343
|
+
if (!flags (idx).elim)
|
|
344
|
+
continue;
|
|
345
|
+
LOG ("scheduling %d for elimination initially", idx);
|
|
346
|
+
schedule.push_back (idx);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
schedule.shrink ();
|
|
350
|
+
|
|
351
|
+
#ifndef QUIET
|
|
352
|
+
int64_t scheduled = schedule.size ();
|
|
353
|
+
#endif
|
|
354
|
+
|
|
355
|
+
PHASE ("fastelim-round", stats.elimfastrounds,
|
|
356
|
+
"scheduled %" PRId64 " variables %.0f%% for elimination",
|
|
357
|
+
scheduled, percent (scheduled, active ()));
|
|
358
|
+
|
|
359
|
+
// Connect irredundant clauses.
|
|
360
|
+
//
|
|
361
|
+
for (const auto &c : clauses)
|
|
362
|
+
if (!c->garbage && !c->redundant)
|
|
363
|
+
for (const auto &lit : *c)
|
|
364
|
+
if (active (lit))
|
|
365
|
+
occs (lit).push_back (c);
|
|
366
|
+
|
|
367
|
+
#ifndef QUIET
|
|
368
|
+
const int64_t old_resolutions = stats.elimres;
|
|
369
|
+
#endif
|
|
370
|
+
const int old_eliminated = stats.all.eliminated;
|
|
371
|
+
const int old_fixed = stats.all.fixed;
|
|
372
|
+
|
|
373
|
+
// Limit on garbage literals during variable elimination. If the limit is
|
|
374
|
+
// hit a garbage collection is performed.
|
|
375
|
+
//
|
|
376
|
+
const int64_t garbage_limit = (2 * stats.irrlits / 3) + (1 << 20);
|
|
377
|
+
|
|
378
|
+
// Main loops tries to eliminate variables according to the schedule. The
|
|
379
|
+
// schedule is updated dynamically and variables are potentially
|
|
380
|
+
// rescheduled to be tried again if they occur in a removed clause.
|
|
381
|
+
//
|
|
382
|
+
#ifndef QUIET
|
|
383
|
+
int64_t tried = 0;
|
|
384
|
+
#endif
|
|
385
|
+
while (!unsat && !terminated_asynchronously () &&
|
|
386
|
+
stats.elimres <= resolution_limit && !schedule.empty ()) {
|
|
387
|
+
int idx = schedule.front ();
|
|
388
|
+
schedule.pop_front ();
|
|
389
|
+
flags (idx).elim = false;
|
|
390
|
+
try_to_fasteliminate_variable (eliminator, idx, deleted_binary_clause);
|
|
391
|
+
#ifndef QUIET
|
|
392
|
+
tried++;
|
|
393
|
+
#endif
|
|
394
|
+
if (stats.garbage.literals <= garbage_limit)
|
|
395
|
+
continue;
|
|
396
|
+
mark_redundant_clauses_with_eliminated_variables_as_garbage ();
|
|
397
|
+
garbage_collection ();
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// If the schedule is empty all variables have been tried (even
|
|
401
|
+
// rescheduled ones). Otherwise asynchronous termination happened or we
|
|
402
|
+
// ran into the resolution limit (or derived unsatisfiability).
|
|
403
|
+
//
|
|
404
|
+
completed = !schedule.size ();
|
|
405
|
+
|
|
406
|
+
PHASE ("fastelim-round", stats.elimfastrounds,
|
|
407
|
+
"tried to eliminate %" PRId64 " variables %.0f%% (%zd remain)",
|
|
408
|
+
tried, percent (tried, scheduled), schedule.size ());
|
|
409
|
+
|
|
410
|
+
schedule.erase ();
|
|
411
|
+
|
|
412
|
+
reset_occs ();
|
|
413
|
+
reset_noccs ();
|
|
414
|
+
|
|
415
|
+
// Mark all redundant clauses with eliminated variables as garbage.
|
|
416
|
+
//
|
|
417
|
+
if (!unsat)
|
|
418
|
+
mark_redundant_clauses_with_eliminated_variables_as_garbage ();
|
|
419
|
+
|
|
420
|
+
int eliminated = stats.all.eliminated - old_eliminated;
|
|
421
|
+
stats.all.fasteliminated += eliminated;
|
|
422
|
+
#ifndef QUIET
|
|
423
|
+
int64_t resolutions = stats.elimres - old_resolutions;
|
|
424
|
+
PHASE ("fastelim-round", stats.elimfastrounds,
|
|
425
|
+
"eliminated %d variables %.0f%% in %" PRId64 " resolutions",
|
|
426
|
+
eliminated, percent (eliminated, scheduled), resolutions);
|
|
427
|
+
#endif
|
|
428
|
+
|
|
429
|
+
const int units = stats.all.fixed - old_fixed;
|
|
430
|
+
report ('e', !opts.reportall && !(eliminated + units));
|
|
431
|
+
STOP_SIMPLIFIER (fastelim, ELIM);
|
|
432
|
+
|
|
433
|
+
return eliminated; // non-zero if successful
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/*------------------------------------------------------------------------*/
|
|
437
|
+
|
|
438
|
+
void Internal::elimfast () {
|
|
439
|
+
|
|
440
|
+
if (unsat)
|
|
441
|
+
return;
|
|
442
|
+
if (level)
|
|
443
|
+
backtrack ();
|
|
444
|
+
if (!propagate ()) {
|
|
445
|
+
learn_empty_clause ();
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
stats.elimfastphases++;
|
|
450
|
+
PHASE ("fastelim-phase", stats.elimfastphases,
|
|
451
|
+
"starting at most %d elimination rounds", opts.fastelimrounds);
|
|
452
|
+
|
|
453
|
+
if (external_prop) {
|
|
454
|
+
assert (!level);
|
|
455
|
+
private_steps = true;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
#ifndef QUIET
|
|
459
|
+
int old_active_variables = active ();
|
|
460
|
+
int old_eliminated = stats.all.eliminated;
|
|
461
|
+
#endif
|
|
462
|
+
|
|
463
|
+
reset_watches (); // saves lots of memory
|
|
464
|
+
|
|
465
|
+
// Alternate one round of bounded variable elimination ('elim_round') and
|
|
466
|
+
// subsumption ('subsume_round'), blocked ('block') and covered clause
|
|
467
|
+
// elimination ('cover') until nothing changes, or the round limit is hit.
|
|
468
|
+
// The loop also aborts early if no variable could be eliminated, the
|
|
469
|
+
// empty clause is resolved, it is asynchronously terminated or a
|
|
470
|
+
// resolution limit is hit.
|
|
471
|
+
|
|
472
|
+
// This variable determines whether the whole loop of this bounded
|
|
473
|
+
// variable elimination phase ('elim') ran until completion. This
|
|
474
|
+
// potentially triggers an incremental increase of the elimination bound.
|
|
475
|
+
//
|
|
476
|
+
bool phase_complete = false, deleted_binary_clause = false;
|
|
477
|
+
|
|
478
|
+
int round = 1;
|
|
479
|
+
#ifndef QUIET
|
|
480
|
+
int eliminated = 0;
|
|
481
|
+
#endif
|
|
482
|
+
|
|
483
|
+
bool round_complete = false;
|
|
484
|
+
while (!unsat && !phase_complete && !terminated_asynchronously ()) {
|
|
485
|
+
#ifndef QUIET
|
|
486
|
+
int eliminated =
|
|
487
|
+
#endif
|
|
488
|
+
elimfast_round (round_complete, deleted_binary_clause);
|
|
489
|
+
|
|
490
|
+
if (!round_complete) {
|
|
491
|
+
PHASE ("fastelim-phase", stats.elimphases,
|
|
492
|
+
"last round %d incomplete %s", round,
|
|
493
|
+
eliminated ? "but successful" : "and unsuccessful");
|
|
494
|
+
assert (!phase_complete);
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (round++ >= opts.fastelimrounds) {
|
|
499
|
+
PHASE ("fastelim-phase", stats.elimphases, "round limit %d hit (%s)",
|
|
500
|
+
round - 1,
|
|
501
|
+
eliminated ? "though last round successful"
|
|
502
|
+
: "last round unsuccessful anyhow");
|
|
503
|
+
assert (!phase_complete);
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Prioritize 'subsumption' over blocked and covered clause elimination.
|
|
508
|
+
|
|
509
|
+
if (subsume_round ())
|
|
510
|
+
continue;
|
|
511
|
+
|
|
512
|
+
// Was not able to generate new variable elimination candidates after
|
|
513
|
+
// variable elimination round, neither through subsumption, nor blocked,
|
|
514
|
+
// nor covered clause elimination.
|
|
515
|
+
//
|
|
516
|
+
PHASE ("fastelim-phase", stats.elimphases,
|
|
517
|
+
"no new variable elimination candidates");
|
|
518
|
+
|
|
519
|
+
assert (round_complete);
|
|
520
|
+
phase_complete = true;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
for (auto idx : vars) {
|
|
524
|
+
if (active (idx))
|
|
525
|
+
flags (idx).elim = true;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (phase_complete) {
|
|
529
|
+
stats.elimcompleted++;
|
|
530
|
+
PHASE ("fastelim-phase", stats.elimphases,
|
|
531
|
+
"fully completed elimination %" PRId64
|
|
532
|
+
" at elimination bound %" PRId64 "",
|
|
533
|
+
stats.elimcompleted, lim.elimbound);
|
|
534
|
+
} else {
|
|
535
|
+
PHASE ("fastelim-phase", stats.elimphases,
|
|
536
|
+
"incomplete elimination %" PRId64
|
|
537
|
+
" at elimination bound %" PRId64 "",
|
|
538
|
+
stats.elimcompleted + 1, lim.elimbound);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (deleted_binary_clause)
|
|
542
|
+
delete_garbage_clauses ();
|
|
543
|
+
init_watches ();
|
|
544
|
+
connect_watches ();
|
|
545
|
+
|
|
546
|
+
if (unsat)
|
|
547
|
+
LOG ("elimination derived empty clause");
|
|
548
|
+
else if (propagated < trail.size ()) {
|
|
549
|
+
LOG ("elimination produced %zd units",
|
|
550
|
+
(size_t) (trail.size () - propagated));
|
|
551
|
+
if (!propagate ()) {
|
|
552
|
+
LOG ("propagating units after elimination results in empty clause");
|
|
553
|
+
learn_empty_clause ();
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
#ifndef QUIET
|
|
558
|
+
eliminated = stats.all.eliminated - old_eliminated;
|
|
559
|
+
PHASE ("fastelim-phase", stats.elimphases,
|
|
560
|
+
"eliminated %d variables %.2f%%", eliminated,
|
|
561
|
+
percent (eliminated, old_active_variables));
|
|
562
|
+
#endif
|
|
563
|
+
|
|
564
|
+
if (external_prop) {
|
|
565
|
+
assert (!level);
|
|
566
|
+
private_steps = false;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
} // namespace CaDiCaL
|