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,1011 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
#define FACTORS 1
|
|
6
|
+
#define QUOTIENT 2
|
|
7
|
+
#define NOUNTED 4
|
|
8
|
+
|
|
9
|
+
inline bool factor_occs_size::operator() (unsigned a, unsigned b) {
|
|
10
|
+
size_t s = internal->occs (internal->u2i (a)).size ();
|
|
11
|
+
size_t t = internal->occs (internal->u2i (b)).size ();
|
|
12
|
+
if (s > t)
|
|
13
|
+
return true;
|
|
14
|
+
if (s < t)
|
|
15
|
+
return false;
|
|
16
|
+
return a > b;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// do full occurence list as in elim.cpp but filter out useless clauses
|
|
20
|
+
void Internal::factor_mode () {
|
|
21
|
+
reset_watches ();
|
|
22
|
+
|
|
23
|
+
assert (!watching ());
|
|
24
|
+
init_occs ();
|
|
25
|
+
|
|
26
|
+
const int size_limit = opts.factorsize;
|
|
27
|
+
|
|
28
|
+
vector<unsigned> bincount, largecount;
|
|
29
|
+
const unsigned max_lit = 2 * (max_var + 1);
|
|
30
|
+
enlarge_zero (bincount, max_lit);
|
|
31
|
+
if (size_limit > 2)
|
|
32
|
+
enlarge_zero (largecount, max_lit);
|
|
33
|
+
|
|
34
|
+
vector<Clause *> candidates;
|
|
35
|
+
int64_t &ticks = stats.ticks.factor;
|
|
36
|
+
ticks += 1 + cache_lines (clauses.size (), sizeof (Clause *));
|
|
37
|
+
|
|
38
|
+
// push binary clauses on the occurrence stack.
|
|
39
|
+
for (const auto &c : clauses) {
|
|
40
|
+
ticks++;
|
|
41
|
+
if (c->garbage)
|
|
42
|
+
continue;
|
|
43
|
+
if (c->redundant && c->size > 2)
|
|
44
|
+
continue;
|
|
45
|
+
if (c->size > size_limit)
|
|
46
|
+
continue;
|
|
47
|
+
if (c->size == 2) {
|
|
48
|
+
const int lit = c->literals[0];
|
|
49
|
+
const int other = c->literals[1];
|
|
50
|
+
bincount[vlit (lit)]++;
|
|
51
|
+
bincount[vlit (other)]++;
|
|
52
|
+
occs (lit).push_back (c);
|
|
53
|
+
occs (other).push_back (c);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
candidates.push_back (c);
|
|
57
|
+
for (const auto &lit : *c) {
|
|
58
|
+
largecount[vlit (lit)]++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (size_limit == 2)
|
|
62
|
+
return;
|
|
63
|
+
|
|
64
|
+
// iterate counts of larger clauses rounds often
|
|
65
|
+
const unsigned rounds = opts.factorcandrounds;
|
|
66
|
+
unsigned candidates_before = 0;
|
|
67
|
+
for (unsigned round = 1; round <= rounds; round++) {
|
|
68
|
+
LOG ("factor round %d", round);
|
|
69
|
+
if (candidates.size () == candidates_before)
|
|
70
|
+
break;
|
|
71
|
+
ticks += 1 + cache_lines (candidates.size (), sizeof (Clause *));
|
|
72
|
+
candidates_before = candidates.size ();
|
|
73
|
+
vector<unsigned> newlargecount;
|
|
74
|
+
enlarge_zero (newlargecount, max_lit);
|
|
75
|
+
const auto begin = candidates.begin ();
|
|
76
|
+
auto p = candidates.begin ();
|
|
77
|
+
auto q = p;
|
|
78
|
+
const auto end = candidates.end ();
|
|
79
|
+
while (p != end) {
|
|
80
|
+
Clause *c = *q++ = *p++;
|
|
81
|
+
ticks++;
|
|
82
|
+
for (const auto &lit : *c) {
|
|
83
|
+
const auto idx = vlit (lit);
|
|
84
|
+
if (bincount[idx] + largecount[idx] < 2) {
|
|
85
|
+
q--;
|
|
86
|
+
goto CONTINUE_WITH_NEXT_CLAUSE;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const auto &lit : *c) {
|
|
90
|
+
const auto idx = vlit (lit);
|
|
91
|
+
newlargecount[idx]++;
|
|
92
|
+
}
|
|
93
|
+
CONTINUE_WITH_NEXT_CLAUSE:
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
candidates.resize (q - begin);
|
|
97
|
+
largecount.swap (newlargecount);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// finally push remaining clause on the occurrence stack
|
|
101
|
+
for (const auto &c : candidates)
|
|
102
|
+
for (const auto &lit : *c)
|
|
103
|
+
occs (lit).push_back (c);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// go back to two watch scheme
|
|
107
|
+
void Internal::reset_factor_mode () {
|
|
108
|
+
reset_occs ();
|
|
109
|
+
init_watches ();
|
|
110
|
+
connect_watches ();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Factoring::Factoring (Internal *i, int64_t l)
|
|
114
|
+
: internal (i), limit (l), schedule (i) {
|
|
115
|
+
const unsigned max_var = internal->max_var;
|
|
116
|
+
const unsigned max_lit = 2 * (max_var + 1);
|
|
117
|
+
initial = max_var;
|
|
118
|
+
bound = internal->lim.elimbound;
|
|
119
|
+
enlarge_zero (count, max_lit);
|
|
120
|
+
quotients.first = quotients.last = 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Factoring::~Factoring () {
|
|
124
|
+
assert (counted.empty ());
|
|
125
|
+
assert (nounted.empty ());
|
|
126
|
+
assert (flauses.empty ());
|
|
127
|
+
internal->release_quotients (*this);
|
|
128
|
+
schedule.erase (); // actually not necessary
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
double Internal::tied_next_factor_score (int lit) {
|
|
132
|
+
double res = occs (lit).size ();
|
|
133
|
+
LOG ("watches score %g of %d", res, lit);
|
|
134
|
+
return res;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// the marks in cadical have 6 bits for marking but work on idx
|
|
138
|
+
// to mark everything (FACTORS, QUOTIENT, NOUNTED) we shift the bits
|
|
139
|
+
// depending on the sign of factor (+ bitmask)
|
|
140
|
+
// i.e. if factor is positive, we apply a bitmask to only get
|
|
141
|
+
// the first three bits (& 7u)
|
|
142
|
+
// otherwise we leftshift by 3 (>> 3) to get the bits 4,5,6
|
|
143
|
+
// use markfact, unmarkfact, getfact for this purpose.
|
|
144
|
+
//
|
|
145
|
+
Quotient *Internal::new_quotient (Factoring &factoring, int factor) {
|
|
146
|
+
assert (!getfact (factor, FACTORS));
|
|
147
|
+
markfact (factor, FACTORS);
|
|
148
|
+
Quotient *res = new Quotient (factor);
|
|
149
|
+
res->next = 0;
|
|
150
|
+
res->matched = 0;
|
|
151
|
+
Quotient *last = factoring.quotients.last;
|
|
152
|
+
res->bid = 0;
|
|
153
|
+
if (last) {
|
|
154
|
+
assert (factoring.quotients.first);
|
|
155
|
+
assert (!last->next);
|
|
156
|
+
last->next = res;
|
|
157
|
+
res->id = last->id + 1;
|
|
158
|
+
} else {
|
|
159
|
+
assert (!factoring.quotients.first);
|
|
160
|
+
factoring.quotients.first = res;
|
|
161
|
+
res->id = 0;
|
|
162
|
+
}
|
|
163
|
+
factoring.quotients.last = res;
|
|
164
|
+
res->prev = last;
|
|
165
|
+
LOG ("new quotient[%zu] with factor %d", res->id, factor);
|
|
166
|
+
return res;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
void Internal::release_quotients (Factoring &factoring) {
|
|
170
|
+
for (Quotient *q = factoring.quotients.first, *next; q; q = next) {
|
|
171
|
+
next = q->next;
|
|
172
|
+
int factor = q->factor;
|
|
173
|
+
assert (getfact (factor, FACTORS));
|
|
174
|
+
unmarkfact (factor, FACTORS);
|
|
175
|
+
delete q;
|
|
176
|
+
}
|
|
177
|
+
factoring.quotients.first = factoring.quotients.last = 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
size_t Internal::first_factor (Factoring &factoring, int factor) {
|
|
181
|
+
assert (!factoring.quotients.first);
|
|
182
|
+
Quotient *quotient = new_quotient (factoring, factor);
|
|
183
|
+
vector<Clause *> &qlauses = quotient->qlauses;
|
|
184
|
+
int64_t ticks = 0;
|
|
185
|
+
for (const auto &c : occs (factor)) {
|
|
186
|
+
qlauses.push_back (c);
|
|
187
|
+
ticks++;
|
|
188
|
+
}
|
|
189
|
+
size_t res = qlauses.size ();
|
|
190
|
+
LOG ("quotient[0] factor %d size %zu", factor, res);
|
|
191
|
+
// This invariant can of course be broken by previous factorings
|
|
192
|
+
// assert (res > 1);
|
|
193
|
+
stats.ticks.factor += ticks;
|
|
194
|
+
return res;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
void Internal::clear_nounted (vector<int> &nounted) {
|
|
198
|
+
for (const auto &lit : nounted) {
|
|
199
|
+
assert (getfact (lit, NOUNTED));
|
|
200
|
+
unmarkfact (lit, NOUNTED);
|
|
201
|
+
}
|
|
202
|
+
nounted.clear ();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
void Internal::clear_flauses (vector<Clause *> &flauses) {
|
|
206
|
+
for (auto c : flauses) {
|
|
207
|
+
assert (c->swept);
|
|
208
|
+
c->swept = false;
|
|
209
|
+
}
|
|
210
|
+
flauses.clear ();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
Quotient *Internal::best_quotient (Factoring &factoring,
|
|
214
|
+
size_t *best_reduction_ptr) {
|
|
215
|
+
size_t factors = 1, best_reduction = 0;
|
|
216
|
+
Quotient *best = 0;
|
|
217
|
+
for (Quotient *q = factoring.quotients.first; q; q = q->next) {
|
|
218
|
+
size_t quotients = q->qlauses.size ();
|
|
219
|
+
size_t before_factorization = quotients * factors;
|
|
220
|
+
size_t after_factorization = quotients + factors;
|
|
221
|
+
if (before_factorization == after_factorization)
|
|
222
|
+
LOG ("quotient[%zu] factors %zu clauses into %zu thus no change",
|
|
223
|
+
factors - 1, before_factorization, after_factorization);
|
|
224
|
+
else if (before_factorization < after_factorization)
|
|
225
|
+
LOG ("quotient[%zu] factors %zu clauses into %zu thus %zu more",
|
|
226
|
+
factors - 1, before_factorization, after_factorization,
|
|
227
|
+
after_factorization - before_factorization);
|
|
228
|
+
else {
|
|
229
|
+
size_t delta = before_factorization - after_factorization;
|
|
230
|
+
LOG ("quotient[%zu] factors %zu clauses into %zu thus %zu less",
|
|
231
|
+
factors - 1, before_factorization, after_factorization, delta);
|
|
232
|
+
if (!best || best_reduction < delta) {
|
|
233
|
+
best_reduction = delta;
|
|
234
|
+
best = q;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
factors++;
|
|
238
|
+
}
|
|
239
|
+
if (!best) {
|
|
240
|
+
LOG ("no decreasing quotient found");
|
|
241
|
+
return 0;
|
|
242
|
+
}
|
|
243
|
+
LOG ("best decreasing quotient[%zu] with reduction %zu", best->id,
|
|
244
|
+
best_reduction);
|
|
245
|
+
*best_reduction_ptr = best_reduction;
|
|
246
|
+
return best;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
int Internal::next_factor (Factoring &factoring, unsigned *next_count_ptr) {
|
|
250
|
+
Quotient *last_quotient = factoring.quotients.last;
|
|
251
|
+
assert (last_quotient);
|
|
252
|
+
vector<Clause *> &last_clauses = last_quotient->qlauses;
|
|
253
|
+
vector<unsigned> &count = factoring.count;
|
|
254
|
+
vector<int> &counted = factoring.counted;
|
|
255
|
+
vector<Clause *> &flauses = factoring.flauses;
|
|
256
|
+
assert (counted.empty ());
|
|
257
|
+
assert (flauses.empty ());
|
|
258
|
+
const int initial = factoring.initial;
|
|
259
|
+
int64_t ticks = 1 + cache_lines (last_clauses.size (), sizeof (Clause *));
|
|
260
|
+
for (auto c : last_clauses) {
|
|
261
|
+
assert (!c->swept);
|
|
262
|
+
int min_lit = 0;
|
|
263
|
+
unsigned factors = 0;
|
|
264
|
+
size_t min_size = 0;
|
|
265
|
+
ticks++;
|
|
266
|
+
for (const auto &other : *c) {
|
|
267
|
+
if (getfact (other, FACTORS)) {
|
|
268
|
+
if (factors++)
|
|
269
|
+
break;
|
|
270
|
+
} else {
|
|
271
|
+
assert (!getfact (other, QUOTIENT));
|
|
272
|
+
markfact (other, QUOTIENT);
|
|
273
|
+
const size_t other_size = occs (other).size ();
|
|
274
|
+
if (!min_lit || other_size < min_size) {
|
|
275
|
+
min_lit = other;
|
|
276
|
+
min_size = other_size;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
assert (factors);
|
|
281
|
+
if (factors == 1) {
|
|
282
|
+
assert (min_lit);
|
|
283
|
+
const int c_size = c->size;
|
|
284
|
+
vector<int> &nounted = factoring.nounted;
|
|
285
|
+
assert (nounted.empty ());
|
|
286
|
+
ticks += 1 + cache_lines (occs (min_lit).size (), sizeof (Clause *));
|
|
287
|
+
for (auto d : occs (min_lit)) {
|
|
288
|
+
if (c == d)
|
|
289
|
+
continue;
|
|
290
|
+
ticks++;
|
|
291
|
+
if (d->swept)
|
|
292
|
+
continue;
|
|
293
|
+
if (d->size != c_size)
|
|
294
|
+
continue;
|
|
295
|
+
int next = 0;
|
|
296
|
+
for (const auto &other : *d) {
|
|
297
|
+
if (getfact (other, QUOTIENT))
|
|
298
|
+
continue;
|
|
299
|
+
if (getfact (other, FACTORS))
|
|
300
|
+
goto CONTINUE_WITH_NEXT_MIN_WATCH;
|
|
301
|
+
if (getfact (other, NOUNTED))
|
|
302
|
+
goto CONTINUE_WITH_NEXT_MIN_WATCH;
|
|
303
|
+
if (next)
|
|
304
|
+
goto CONTINUE_WITH_NEXT_MIN_WATCH;
|
|
305
|
+
next = other;
|
|
306
|
+
}
|
|
307
|
+
assert (next);
|
|
308
|
+
if (abs (next) > abs (initial))
|
|
309
|
+
continue;
|
|
310
|
+
if (!active (next))
|
|
311
|
+
continue;
|
|
312
|
+
assert (!getfact (next, FACTORS));
|
|
313
|
+
assert (!getfact (next, NOUNTED));
|
|
314
|
+
markfact (next, NOUNTED);
|
|
315
|
+
nounted.push_back (next);
|
|
316
|
+
d->swept = true;
|
|
317
|
+
flauses.push_back (d);
|
|
318
|
+
if (!count[vlit (next)])
|
|
319
|
+
counted.push_back (next);
|
|
320
|
+
count[vlit (next)]++;
|
|
321
|
+
CONTINUE_WITH_NEXT_MIN_WATCH:;
|
|
322
|
+
}
|
|
323
|
+
clear_nounted (nounted);
|
|
324
|
+
}
|
|
325
|
+
for (const auto &other : *c)
|
|
326
|
+
if (getfact (other, QUOTIENT))
|
|
327
|
+
unmarkfact (other, QUOTIENT);
|
|
328
|
+
stats.ticks.factor += ticks;
|
|
329
|
+
ticks = 0;
|
|
330
|
+
if (stats.ticks.factor > factoring.limit)
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
clear_flauses (flauses);
|
|
334
|
+
unsigned next_count = 0;
|
|
335
|
+
int next = 0;
|
|
336
|
+
if (stats.ticks.factor <= factoring.limit) {
|
|
337
|
+
unsigned ties = 0;
|
|
338
|
+
for (const auto &lit : counted) {
|
|
339
|
+
const unsigned lit_count = count[vlit (lit)];
|
|
340
|
+
if (lit_count < next_count)
|
|
341
|
+
continue;
|
|
342
|
+
if (lit_count == next_count) {
|
|
343
|
+
assert (lit_count);
|
|
344
|
+
ties++;
|
|
345
|
+
} else {
|
|
346
|
+
assert (lit_count > next_count);
|
|
347
|
+
next_count = lit_count;
|
|
348
|
+
next = lit;
|
|
349
|
+
ties = 1;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (next_count < 2) {
|
|
353
|
+
LOG ("next factor count %u smaller than 2", next_count);
|
|
354
|
+
next = 0;
|
|
355
|
+
} else if (ties > 1) {
|
|
356
|
+
LOG ("found %u tied next factor candidate literals with count %u",
|
|
357
|
+
ties, next_count);
|
|
358
|
+
double next_score = -1;
|
|
359
|
+
for (const auto &lit : counted) {
|
|
360
|
+
const unsigned lit_count = count[vlit (lit)];
|
|
361
|
+
if (lit_count != next_count)
|
|
362
|
+
continue;
|
|
363
|
+
double lit_score = tied_next_factor_score (lit);
|
|
364
|
+
assert (lit_score >= 0);
|
|
365
|
+
LOG ("score %g of next factor candidate %d", lit_score, lit);
|
|
366
|
+
if (lit_score <= next_score)
|
|
367
|
+
continue;
|
|
368
|
+
next_score = lit_score;
|
|
369
|
+
next = lit;
|
|
370
|
+
}
|
|
371
|
+
assert (next_score >= 0);
|
|
372
|
+
assert (next);
|
|
373
|
+
LOG ("best score %g of next factor %d", next_score, next);
|
|
374
|
+
} else {
|
|
375
|
+
assert (ties == 1);
|
|
376
|
+
LOG ("single next factor %d with count %u", next, next_count);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
for (const auto &lit : counted)
|
|
380
|
+
count[vlit (lit)] = 0;
|
|
381
|
+
counted.clear ();
|
|
382
|
+
assert (!next || next_count > 1);
|
|
383
|
+
*next_count_ptr = next_count;
|
|
384
|
+
return next;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
void Internal::factorize_next (Factoring &factoring, int next,
|
|
388
|
+
unsigned expected_next_count) {
|
|
389
|
+
Quotient *last_quotient = factoring.quotients.last;
|
|
390
|
+
Quotient *next_quotient = new_quotient (factoring, next);
|
|
391
|
+
|
|
392
|
+
assert (last_quotient);
|
|
393
|
+
vector<Clause *> &last_clauses = last_quotient->qlauses;
|
|
394
|
+
vector<Clause *> &next_clauses = next_quotient->qlauses;
|
|
395
|
+
vector<size_t> &matches = next_quotient->matches;
|
|
396
|
+
vector<Clause *> &flauses = factoring.flauses;
|
|
397
|
+
assert (flauses.empty ());
|
|
398
|
+
|
|
399
|
+
int64_t ticks = 1 + cache_lines (last_clauses.size (), sizeof (Clause *));
|
|
400
|
+
|
|
401
|
+
size_t i = 0;
|
|
402
|
+
|
|
403
|
+
for (auto c : last_clauses) {
|
|
404
|
+
assert (!c->swept);
|
|
405
|
+
int min_lit = 0;
|
|
406
|
+
unsigned factors = 0;
|
|
407
|
+
size_t min_size = 0;
|
|
408
|
+
ticks++;
|
|
409
|
+
for (const auto &other : *c) {
|
|
410
|
+
if (getfact (other, FACTORS)) {
|
|
411
|
+
if (factors++)
|
|
412
|
+
break;
|
|
413
|
+
} else {
|
|
414
|
+
assert (!getfact (other, QUOTIENT));
|
|
415
|
+
markfact (other, QUOTIENT);
|
|
416
|
+
const size_t other_size = occs (other).size ();
|
|
417
|
+
if (!min_lit || other_size < min_size) {
|
|
418
|
+
min_lit = other;
|
|
419
|
+
min_size = other_size;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
assert (factors);
|
|
424
|
+
if (factors == 1) {
|
|
425
|
+
assert (min_lit);
|
|
426
|
+
const int c_size = c->size;
|
|
427
|
+
ticks += 1 + cache_lines (occs (min_lit).size (), sizeof (Clause *));
|
|
428
|
+
for (auto d : occs (min_lit)) {
|
|
429
|
+
if (c == d)
|
|
430
|
+
continue;
|
|
431
|
+
ticks++;
|
|
432
|
+
if (d->swept)
|
|
433
|
+
continue;
|
|
434
|
+
if (d->size != c_size)
|
|
435
|
+
continue;
|
|
436
|
+
for (const auto &other : *d) {
|
|
437
|
+
if (getfact (other, QUOTIENT))
|
|
438
|
+
continue;
|
|
439
|
+
if (other != next)
|
|
440
|
+
goto CONTINUE_WITH_NEXT_MIN_WATCH;
|
|
441
|
+
}
|
|
442
|
+
LOG (c, "matched");
|
|
443
|
+
LOG (d, "keeping");
|
|
444
|
+
|
|
445
|
+
next_clauses.push_back (d);
|
|
446
|
+
matches.push_back (i);
|
|
447
|
+
flauses.push_back (d);
|
|
448
|
+
d->swept = true;
|
|
449
|
+
break;
|
|
450
|
+
|
|
451
|
+
CONTINUE_WITH_NEXT_MIN_WATCH:;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
for (const auto &other : *c)
|
|
455
|
+
if (getfact (other, QUOTIENT))
|
|
456
|
+
unmarkfact (other, QUOTIENT);
|
|
457
|
+
i++;
|
|
458
|
+
}
|
|
459
|
+
clear_flauses (flauses);
|
|
460
|
+
stats.ticks.factor += ticks;
|
|
461
|
+
|
|
462
|
+
assert (expected_next_count <= next_clauses.size ());
|
|
463
|
+
(void) expected_next_count;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// We only need to enlarge factoring.count as everything else is
|
|
467
|
+
// initialized in internal
|
|
468
|
+
void Internal::resize_factoring (Factoring &factoring, int lit) {
|
|
469
|
+
assert (lit > 0);
|
|
470
|
+
size_t new_var_size = lit + 1;
|
|
471
|
+
size_t new_lit_size = 2 * new_var_size;
|
|
472
|
+
enlarge_zero (factoring.count, new_lit_size);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
void Internal::flush_unmatched_clauses (Quotient *q) {
|
|
476
|
+
Quotient *prev = q->prev;
|
|
477
|
+
vector<size_t> &q_matches = q->matches, &prev_matches = prev->matches;
|
|
478
|
+
vector<Clause *> &q_clauses = q->qlauses, &prev_clauses = prev->qlauses;
|
|
479
|
+
const size_t n = q_clauses.size ();
|
|
480
|
+
assert (n == q_matches.size ());
|
|
481
|
+
bool prev_is_first = !prev->id;
|
|
482
|
+
size_t i = 0;
|
|
483
|
+
while (i < q_matches.size ()) {
|
|
484
|
+
size_t j = q_matches[i];
|
|
485
|
+
q_matches[i] = i;
|
|
486
|
+
assert (i <= j);
|
|
487
|
+
if (!prev_is_first) {
|
|
488
|
+
size_t matches = prev_matches[j];
|
|
489
|
+
prev_matches[i] = matches;
|
|
490
|
+
}
|
|
491
|
+
Clause *c = prev_clauses[j];
|
|
492
|
+
prev_clauses[i] = c;
|
|
493
|
+
i++;
|
|
494
|
+
}
|
|
495
|
+
LOG ("flushing %zu clauses of quotient[%zu]", prev_clauses.size () - n,
|
|
496
|
+
prev->id);
|
|
497
|
+
if (!prev_is_first)
|
|
498
|
+
prev_matches.resize (n);
|
|
499
|
+
prev_clauses.resize (n);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// special case when we have two quotients with negated factors.
|
|
503
|
+
// in this case, factoring does not make sense, and instead we
|
|
504
|
+
// can resolve the clauses of the two quotients.
|
|
505
|
+
// this subsumes all clauses in all quotients.
|
|
506
|
+
void Internal::add_self_subsuming_factor (Quotient *q, Quotient *p) {
|
|
507
|
+
const int factor = q->factor;
|
|
508
|
+
const int not_factor = p->factor;
|
|
509
|
+
assert (-factor == not_factor);
|
|
510
|
+
LOG (
|
|
511
|
+
"adding self subsuming factor because blocked clause is a tautology");
|
|
512
|
+
for (auto c : q->qlauses) {
|
|
513
|
+
for (const auto &lit : *c) {
|
|
514
|
+
if (lit == factor)
|
|
515
|
+
continue;
|
|
516
|
+
clause.push_back (lit);
|
|
517
|
+
}
|
|
518
|
+
if (lrat) {
|
|
519
|
+
for (auto d : p->qlauses) {
|
|
520
|
+
bool match = true;
|
|
521
|
+
for (const auto &lit : *d) {
|
|
522
|
+
if (lit == not_factor)
|
|
523
|
+
continue;
|
|
524
|
+
if (std::find (clause.begin (), clause.end (), lit) ==
|
|
525
|
+
clause.end ()) {
|
|
526
|
+
match = false;
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (match) {
|
|
531
|
+
lrat_chain.push_back (d->id);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
lrat_chain.push_back (c->id);
|
|
536
|
+
assert (lrat_chain.size () == 2);
|
|
537
|
+
}
|
|
538
|
+
if (clause.size () > 1) {
|
|
539
|
+
new_factor_clause (0);
|
|
540
|
+
} else {
|
|
541
|
+
const int unit = clause[0];
|
|
542
|
+
const signed char tmp = val (unit);
|
|
543
|
+
if (!tmp)
|
|
544
|
+
assign_unit (unit);
|
|
545
|
+
else if (tmp < 0) {
|
|
546
|
+
if (lrat) {
|
|
547
|
+
int64_t id = unit_id (-unit);
|
|
548
|
+
lrat_chain.push_back (id);
|
|
549
|
+
std::reverse (lrat_chain.begin (), lrat_chain.end ());
|
|
550
|
+
}
|
|
551
|
+
learn_empty_clause ();
|
|
552
|
+
clause.clear ();
|
|
553
|
+
lrat_chain.clear ();
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
clause.clear ();
|
|
558
|
+
lrat_chain.clear ();
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
bool Internal::self_subsuming_factor (Quotient *q) {
|
|
563
|
+
Quotient *x = 0, *y = 0;
|
|
564
|
+
bool found = false;
|
|
565
|
+
for (Quotient *p = q; p; p = p->prev) {
|
|
566
|
+
const int factor = p->factor;
|
|
567
|
+
Flags &f = flags (factor);
|
|
568
|
+
if (f.seen) {
|
|
569
|
+
assert (std::find (analyzed.begin (), analyzed.end (), -factor) !=
|
|
570
|
+
analyzed.end ());
|
|
571
|
+
found = true;
|
|
572
|
+
x = p;
|
|
573
|
+
for (Quotient *r = q; r; r = r->prev) {
|
|
574
|
+
if (r->factor != -factor)
|
|
575
|
+
continue;
|
|
576
|
+
y = r;
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
analyzed.push_back (factor);
|
|
582
|
+
f.seen = true;
|
|
583
|
+
}
|
|
584
|
+
assert (!found || (x && y));
|
|
585
|
+
clear_analyzed_literals ();
|
|
586
|
+
if (found) {
|
|
587
|
+
add_self_subsuming_factor (x, y);
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// this is a pure binary clauses containing fresh and one other literal
|
|
594
|
+
// it is added for all applicable quotients.
|
|
595
|
+
void Internal::add_factored_divider (Quotient *q, int fresh) {
|
|
596
|
+
const int factor = q->factor;
|
|
597
|
+
LOG ("factored %d divider %d", factor, fresh);
|
|
598
|
+
clause.push_back (fresh);
|
|
599
|
+
clause.push_back (factor);
|
|
600
|
+
new_factor_clause (fresh);
|
|
601
|
+
clause.clear ();
|
|
602
|
+
if (lrat)
|
|
603
|
+
mini_chain.push_back (-clause_id);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// this clause is blocked on fresh, i.e., it contains all literals from
|
|
607
|
+
// the binaries above, but negated. This is only added to the proof, to
|
|
608
|
+
// make checking easier.
|
|
609
|
+
void Internal::blocked_clause (Quotient *q, int not_fresh) {
|
|
610
|
+
if (!proof)
|
|
611
|
+
return;
|
|
612
|
+
int64_t new_id = ++clause_id;
|
|
613
|
+
q->bid = new_id;
|
|
614
|
+
assert (clause.empty ());
|
|
615
|
+
clause.push_back (not_fresh);
|
|
616
|
+
for (Quotient *p = q; p; p = p->prev)
|
|
617
|
+
clause.push_back (-p->factor);
|
|
618
|
+
assert (!lrat || mini_chain.size ());
|
|
619
|
+
proof->add_derived_rat_clause (new_id, true, externalize (not_fresh),
|
|
620
|
+
clause, mini_chain);
|
|
621
|
+
mini_chain.clear ();
|
|
622
|
+
clause.clear ();
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// this is the other side of the factored clauses. To derive these,
|
|
626
|
+
// one can resolved the blocked clause on all matching clauses of
|
|
627
|
+
// one type
|
|
628
|
+
void Internal::add_factored_quotient (Quotient *q, int not_fresh) {
|
|
629
|
+
LOG ("adding factored quotient[%zu] clauses", q->id);
|
|
630
|
+
const int factor = q->factor;
|
|
631
|
+
assert (lrat_chain.empty ());
|
|
632
|
+
auto qlauses = q->qlauses;
|
|
633
|
+
for (unsigned idx = 0; idx < qlauses.size (); idx++) {
|
|
634
|
+
const auto c = qlauses[idx];
|
|
635
|
+
assert (clause.empty ());
|
|
636
|
+
for (const auto &other : *c) {
|
|
637
|
+
if (other == factor) {
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
clause.push_back (other);
|
|
641
|
+
}
|
|
642
|
+
if (lrat) {
|
|
643
|
+
assert (proof);
|
|
644
|
+
assert (q->bid);
|
|
645
|
+
unsigned idxtoo = idx;
|
|
646
|
+
for (Quotient *p = q; p; p = p->prev) {
|
|
647
|
+
lrat_chain.push_back (p->qlauses[idxtoo]->id);
|
|
648
|
+
if (p->prev)
|
|
649
|
+
idxtoo = p->matches[idx];
|
|
650
|
+
}
|
|
651
|
+
lrat_chain.push_back (q->bid);
|
|
652
|
+
}
|
|
653
|
+
clause.push_back (not_fresh);
|
|
654
|
+
new_factor_clause (0);
|
|
655
|
+
clause.clear ();
|
|
656
|
+
lrat_chain.clear ();
|
|
657
|
+
}
|
|
658
|
+
if (proof) {
|
|
659
|
+
clause.push_back (not_fresh);
|
|
660
|
+
for (Quotient *p = q; p; p = p->prev) {
|
|
661
|
+
clause.push_back (-p->factor);
|
|
662
|
+
}
|
|
663
|
+
proof->delete_clause (q->bid, true, clause);
|
|
664
|
+
clause.clear ();
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// remove deleted clauses once factored.
|
|
669
|
+
void Internal::eagerly_remove_from_occurences (Clause *c) {
|
|
670
|
+
for (const auto &lit : *c) {
|
|
671
|
+
auto &occ = occs (lit);
|
|
672
|
+
auto p = occ.begin ();
|
|
673
|
+
auto q = occ.begin ();
|
|
674
|
+
auto begin = occ.begin ();
|
|
675
|
+
auto end = occ.end ();
|
|
676
|
+
while (p != end) {
|
|
677
|
+
*q = *p++;
|
|
678
|
+
if (*q != c)
|
|
679
|
+
q++;
|
|
680
|
+
}
|
|
681
|
+
assert (q + 1 == p);
|
|
682
|
+
occ.resize (q - begin);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// delete the factored clauses
|
|
687
|
+
void Internal::delete_unfactored (Quotient *q) {
|
|
688
|
+
LOG ("deleting unfactored quotient[%zu] clauses", q->id);
|
|
689
|
+
for (auto c : q->qlauses) {
|
|
690
|
+
eagerly_remove_from_occurences (c);
|
|
691
|
+
mark_garbage (c);
|
|
692
|
+
stats.literals_unfactored += c->size;
|
|
693
|
+
stats.clauses_unfactored++;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// update the priority queue for scheduling
|
|
698
|
+
void Internal::update_factored (Factoring &factoring, Quotient *q) {
|
|
699
|
+
const int factor = q->factor;
|
|
700
|
+
update_factor_candidate (factoring, factor);
|
|
701
|
+
update_factor_candidate (factoring, -factor);
|
|
702
|
+
for (auto c : q->qlauses) {
|
|
703
|
+
LOG (c, "deleting unfactored");
|
|
704
|
+
for (const auto &lit : *c)
|
|
705
|
+
if (lit != factor)
|
|
706
|
+
update_factor_candidate (factoring, lit);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
bool Internal::apply_factoring (Factoring &factoring, Quotient *q) {
|
|
711
|
+
for (Quotient *p = q; p->prev; p = p->prev)
|
|
712
|
+
flush_unmatched_clauses (p);
|
|
713
|
+
if (self_subsuming_factor (q)) {
|
|
714
|
+
for (Quotient *p = q; p; p = p->prev)
|
|
715
|
+
delete_unfactored (p);
|
|
716
|
+
for (Quotient *p = q; p; p = p->prev)
|
|
717
|
+
update_factored (factoring, p);
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
const int fresh = get_new_extension_variable ();
|
|
721
|
+
if (!fresh)
|
|
722
|
+
return false;
|
|
723
|
+
stats.factored++;
|
|
724
|
+
factoring.fresh.push_back (fresh);
|
|
725
|
+
for (Quotient *p = q; p; p = p->prev)
|
|
726
|
+
add_factored_divider (p, fresh);
|
|
727
|
+
const int not_fresh = -fresh;
|
|
728
|
+
blocked_clause (q, not_fresh);
|
|
729
|
+
add_factored_quotient (q, not_fresh);
|
|
730
|
+
for (Quotient *p = q; p; p = p->prev)
|
|
731
|
+
delete_unfactored (p);
|
|
732
|
+
for (Quotient *p = q; p; p = p->prev)
|
|
733
|
+
update_factored (factoring, p);
|
|
734
|
+
assert (fresh > 0);
|
|
735
|
+
resize_factoring (factoring, fresh);
|
|
736
|
+
return true;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
void Internal::update_factor_candidate (Factoring &factoring, int lit) {
|
|
740
|
+
FactorSchedule &schedule = factoring.schedule;
|
|
741
|
+
const size_t size = occs (lit).size ();
|
|
742
|
+
const unsigned idx = vlit (lit);
|
|
743
|
+
if (schedule.contains (idx))
|
|
744
|
+
schedule.update (idx);
|
|
745
|
+
else if (size > 1) {
|
|
746
|
+
schedule.push_back (idx);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
void Internal::schedule_factorization (Factoring &factoring) {
|
|
751
|
+
for (const auto &idx : vars) {
|
|
752
|
+
if (active (idx)) {
|
|
753
|
+
Flags &f = flags (idx);
|
|
754
|
+
const int lit = idx;
|
|
755
|
+
const int not_lit = -lit;
|
|
756
|
+
if (f.factor & 1)
|
|
757
|
+
update_factor_candidate (factoring, lit);
|
|
758
|
+
if (f.factor & 2)
|
|
759
|
+
update_factor_candidate (factoring, not_lit);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
#ifndef QUIET
|
|
763
|
+
size_t size_cands = factoring.schedule.size ();
|
|
764
|
+
VERBOSE (2, "scheduled %zu factorization candidate literals %.0f %%",
|
|
765
|
+
size_cands, percent (size_cands, max_var));
|
|
766
|
+
#endif
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
void Internal::adjust_scores_and_phases_of_fresh_variables (
|
|
770
|
+
Factoring &factoring) {
|
|
771
|
+
if (!opts.factorunbump) {
|
|
772
|
+
factoring.fresh.clear ();
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
if (factoring.fresh.empty ())
|
|
776
|
+
return;
|
|
777
|
+
|
|
778
|
+
#if 0 // the scores are very low anyway
|
|
779
|
+
for (auto lit : factoring.fresh) {
|
|
780
|
+
assert (lit > 0 && internal->max_var);
|
|
781
|
+
const double old_score = internal->stab[lit];
|
|
782
|
+
// make the scores a little different from each other with the newest having the highest score
|
|
783
|
+
const double new_score = 1.0 / (double)(internal->max_var - lit);
|
|
784
|
+
if (old_score == new_score)
|
|
785
|
+
continue;
|
|
786
|
+
if (!scores.contains (lit))
|
|
787
|
+
continue;
|
|
788
|
+
LOG ("unbumping %s", LOGLIT(lit));
|
|
789
|
+
internal->stab[lit] = new_score;
|
|
790
|
+
scores.update (lit);
|
|
791
|
+
}
|
|
792
|
+
#endif
|
|
793
|
+
|
|
794
|
+
for (auto lit : factoring.fresh) {
|
|
795
|
+
LOG ("dequeuing %s", LOGLIT (lit));
|
|
796
|
+
queue.dequeue (links, lit);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
for (auto lit : factoring.fresh) {
|
|
800
|
+
LOG ("dequeuing %s", LOGLIT (lit));
|
|
801
|
+
queue.bury (links, lit);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// fix the scores with negative numbers
|
|
805
|
+
int lit = queue.first;
|
|
806
|
+
queue.bumped = 0;
|
|
807
|
+
while (lit) {
|
|
808
|
+
btab[lit] = ++queue.bumped;
|
|
809
|
+
lit = links[lit].next;
|
|
810
|
+
}
|
|
811
|
+
stats.bumped = queue.bumped;
|
|
812
|
+
update_queue_unassigned (queue.last);
|
|
813
|
+
|
|
814
|
+
#ifndef NDEBUG
|
|
815
|
+
for (auto v : vars)
|
|
816
|
+
assert (val (v) || scores.contains (v));
|
|
817
|
+
lit = queue.first;
|
|
818
|
+
int next_lit = links[lit].next;
|
|
819
|
+
while (next_lit) {
|
|
820
|
+
assert (btab[lit] < btab[next_lit]);
|
|
821
|
+
const int tmp = links[next_lit].next;
|
|
822
|
+
assert (!tmp || links[tmp].prev == next_lit);
|
|
823
|
+
lit = next_lit;
|
|
824
|
+
next_lit = tmp;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
lit = queue.last;
|
|
828
|
+
next_lit = links[lit].prev;
|
|
829
|
+
while (next_lit) {
|
|
830
|
+
assert (btab[lit] > btab[next_lit]);
|
|
831
|
+
const int tmp = links[next_lit].prev;
|
|
832
|
+
assert (!tmp || links[tmp].next == next_lit);
|
|
833
|
+
lit = next_lit;
|
|
834
|
+
next_lit = tmp;
|
|
835
|
+
}
|
|
836
|
+
assert (queue.first);
|
|
837
|
+
assert (queue.last);
|
|
838
|
+
#endif
|
|
839
|
+
factoring.fresh.clear ();
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
bool Internal::run_factorization (int64_t limit) {
|
|
843
|
+
Factoring factoring = Factoring (this, limit);
|
|
844
|
+
schedule_factorization (factoring);
|
|
845
|
+
bool done = false;
|
|
846
|
+
#ifndef QUIET
|
|
847
|
+
unsigned factored = 0;
|
|
848
|
+
#endif
|
|
849
|
+
int64_t *ticks = &stats.ticks.factor;
|
|
850
|
+
VERBOSE (3, "factorization limit of %" PRIu64 " ticks", limit - *ticks);
|
|
851
|
+
|
|
852
|
+
while (!unsat && !done && !factoring.schedule.empty ()) {
|
|
853
|
+
const unsigned ufirst = factoring.schedule.pop_front ();
|
|
854
|
+
LOG ("next factor candidate %d", ufirst);
|
|
855
|
+
const int first = u2i (ufirst);
|
|
856
|
+
const int first_idx = vidx (first);
|
|
857
|
+
if (!active (first_idx))
|
|
858
|
+
continue;
|
|
859
|
+
if (!occs (first).size ()) {
|
|
860
|
+
factoring.schedule.clear ();
|
|
861
|
+
break;
|
|
862
|
+
}
|
|
863
|
+
if (*ticks > limit) {
|
|
864
|
+
VERBOSE (2, "factorization ticks limit hit");
|
|
865
|
+
break;
|
|
866
|
+
}
|
|
867
|
+
if (terminated_asynchronously ())
|
|
868
|
+
break;
|
|
869
|
+
Flags &f = flags (first_idx);
|
|
870
|
+
const unsigned bit = 1u << (first < 0);
|
|
871
|
+
if (!(f.factor & bit))
|
|
872
|
+
continue;
|
|
873
|
+
f.factor &= ~bit;
|
|
874
|
+
const size_t first_count = first_factor (factoring, first);
|
|
875
|
+
if (first_count > 1) {
|
|
876
|
+
for (;;) {
|
|
877
|
+
unsigned next_count;
|
|
878
|
+
const int next = next_factor (factoring, &next_count);
|
|
879
|
+
if (next == 0)
|
|
880
|
+
break;
|
|
881
|
+
assert (next_count > 1);
|
|
882
|
+
if (next_count < 2)
|
|
883
|
+
break;
|
|
884
|
+
factorize_next (factoring, next, next_count);
|
|
885
|
+
}
|
|
886
|
+
size_t reduction;
|
|
887
|
+
Quotient *q = best_quotient (factoring, &reduction);
|
|
888
|
+
if (q && (int) reduction > factoring.bound) {
|
|
889
|
+
if (apply_factoring (factoring, q)) {
|
|
890
|
+
#ifndef QUIET
|
|
891
|
+
factored++;
|
|
892
|
+
#endif
|
|
893
|
+
} else
|
|
894
|
+
done = true;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
release_quotients (factoring);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// since we cannot remove elements from the heap we check wether the
|
|
901
|
+
// first element in the heap has occurences
|
|
902
|
+
bool completed = factoring.schedule.empty ();
|
|
903
|
+
if (!completed) {
|
|
904
|
+
const unsigned idx = factoring.schedule.front ();
|
|
905
|
+
completed = occs (u2i (idx)).empty ();
|
|
906
|
+
}
|
|
907
|
+
adjust_scores_and_phases_of_fresh_variables (factoring);
|
|
908
|
+
#ifndef QUIET
|
|
909
|
+
report ('f', !factored);
|
|
910
|
+
#endif
|
|
911
|
+
return completed;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
int Internal::get_new_extension_variable () {
|
|
915
|
+
const int current_max_external = external->max_var;
|
|
916
|
+
const int new_external = current_max_external + 1;
|
|
917
|
+
const int new_internal = external->internalize (new_external, true);
|
|
918
|
+
// one sideeffect of internalize is enlarging the internal datastructures
|
|
919
|
+
// which can initialize the watches (wtab)
|
|
920
|
+
if (watching ())
|
|
921
|
+
reset_watches ();
|
|
922
|
+
// it does not enlarge otab, however, so we do this manually
|
|
923
|
+
init_occs ();
|
|
924
|
+
assert (vlit (new_internal));
|
|
925
|
+
return new_internal;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
bool Internal::factor () {
|
|
929
|
+
if (unsat)
|
|
930
|
+
return false;
|
|
931
|
+
if (terminated_asynchronously ())
|
|
932
|
+
return false;
|
|
933
|
+
if (!opts.factor)
|
|
934
|
+
return false;
|
|
935
|
+
|
|
936
|
+
int v_active = active ();
|
|
937
|
+
if (!v_active)
|
|
938
|
+
return false;
|
|
939
|
+
size_t log_active = log10 (v_active);
|
|
940
|
+
size_t eliminations = stats.elimrounds;
|
|
941
|
+
size_t delay = opts.factordelay;
|
|
942
|
+
size_t delay_limit = eliminations + delay;
|
|
943
|
+
if (log_active > delay_limit) {
|
|
944
|
+
VERBOSE (3,
|
|
945
|
+
"factorization delayed as %zu = log10 (%u)"
|
|
946
|
+
"> eliminations + delay = %zu + %zu = %zu",
|
|
947
|
+
log_active, v_active, eliminations, delay, delay_limit);
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
// The following assertion fails if there are *only* user propagator
|
|
951
|
+
// clauses (which are redundant).
|
|
952
|
+
// assert (stats.mark.factor || clauses.empty ());
|
|
953
|
+
if (last.factor.marked >= stats.mark.factor) {
|
|
954
|
+
VERBOSE (3,
|
|
955
|
+
"factorization skipped as no literals have been"
|
|
956
|
+
"marked to be added (%" PRIu64 " < %" PRIu64 ")",
|
|
957
|
+
last.factor.marked, stats.mark.factor);
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
assert (!level);
|
|
961
|
+
|
|
962
|
+
SET_EFFORT_LIMIT (limit, factor, stats.factor);
|
|
963
|
+
if (!stats.factor)
|
|
964
|
+
limit += opts.factoriniticks * 1e6;
|
|
965
|
+
|
|
966
|
+
mark_duplicated_binary_clauses_as_garbage ();
|
|
967
|
+
|
|
968
|
+
START_SIMPLIFIER (factor, FACTOR);
|
|
969
|
+
stats.factor++;
|
|
970
|
+
|
|
971
|
+
#ifndef QUIET
|
|
972
|
+
struct {
|
|
973
|
+
int64_t variables, clauses, ticks;
|
|
974
|
+
} before, after, delta;
|
|
975
|
+
before.variables = stats.variables_extension + stats.variables_original;
|
|
976
|
+
before.ticks = stats.ticks.factor;
|
|
977
|
+
before.clauses = stats.current.irredundant;
|
|
978
|
+
#endif
|
|
979
|
+
|
|
980
|
+
factor_mode ();
|
|
981
|
+
bool completed = run_factorization (limit);
|
|
982
|
+
reset_factor_mode ();
|
|
983
|
+
|
|
984
|
+
propagated = 0;
|
|
985
|
+
if (!unsat && !propagate ()) {
|
|
986
|
+
learn_empty_clause ();
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
#ifndef QUIET
|
|
990
|
+
after.variables = stats.variables_extension + stats.variables_original;
|
|
991
|
+
after.clauses = stats.current.irredundant;
|
|
992
|
+
after.ticks = stats.ticks.factor;
|
|
993
|
+
delta.variables = after.variables - before.variables;
|
|
994
|
+
delta.clauses = before.clauses - after.clauses;
|
|
995
|
+
delta.ticks = after.ticks - before.ticks;
|
|
996
|
+
VERBOSE (2, "used %f million factorization ticks", delta.ticks * 1e-6);
|
|
997
|
+
phase ("factorization", stats.factor,
|
|
998
|
+
"introduced %" PRId64 " extension variables %.0f%%",
|
|
999
|
+
delta.variables, percent (delta.variables, before.variables));
|
|
1000
|
+
phase ("factorization", stats.factor,
|
|
1001
|
+
"removed %" PRId64 " irredundant clauses %.0f%%", delta.clauses,
|
|
1002
|
+
percent (delta.clauses, before.clauses));
|
|
1003
|
+
#endif
|
|
1004
|
+
|
|
1005
|
+
if (completed)
|
|
1006
|
+
last.factor.marked = stats.mark.factor;
|
|
1007
|
+
STOP_SIMPLIFIER (factor, FACTOR);
|
|
1008
|
+
return true;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
} // namespace CaDiCaL
|