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,23 @@
|
|
|
1
|
+
#ifndef _decompose_hpp_INCLUDED
|
|
2
|
+
#define _decompose_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
namespace CaDiCaL {
|
|
5
|
+
|
|
6
|
+
// This implements Tarjan's algorithm for decomposing the binary implication
|
|
7
|
+
// graph intro strongly connected components (SCCs). Literals in one SCC
|
|
8
|
+
// are equivalent and we replace them all by the literal with the smallest
|
|
9
|
+
// index in the SCC. These variables are marked 'substituted' and will be
|
|
10
|
+
// removed from all clauses. Their value will be fixed during 'extend'.
|
|
11
|
+
|
|
12
|
+
#define TRAVERSED UINT_MAX // mark completely traversed
|
|
13
|
+
|
|
14
|
+
struct DFS {
|
|
15
|
+
unsigned idx; // depth first search index
|
|
16
|
+
unsigned min; // minimum reachable index
|
|
17
|
+
Clause *parent; // for lrat
|
|
18
|
+
DFS () : idx (0), min (0), parent (0) {}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
} // namespace CaDiCaL
|
|
22
|
+
|
|
23
|
+
#endif
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
// Equivalent literal substitution in 'decompose' and shrinking in 'subsume'
|
|
6
|
+
// or 'vivify' might produce duplicated binary clauses. They can not be
|
|
7
|
+
// found in 'subsume' nor 'vivify' since we explicitly do not consider
|
|
8
|
+
// binary clauses as candidates to be shrunken or subsumed. They are
|
|
9
|
+
// detected here by a simple scan of watch lists and then marked as garbage.
|
|
10
|
+
// This is actually also quite fast.
|
|
11
|
+
|
|
12
|
+
// Further it might also be possible that two binary clauses can be resolved
|
|
13
|
+
// to produce a unit (we call it 'hyper unary resolution'). For example
|
|
14
|
+
// resolving the binary clauses '1 -2' and '1 2' produces the unit '1'.
|
|
15
|
+
// This could be found by probing in 'probe' unless '-1' also occurs in a
|
|
16
|
+
// binary clause (add the clause '-1 2' to those two clauses) in which case
|
|
17
|
+
// '1' as well as '2' both occur positively as well as negatively and none
|
|
18
|
+
// of them nor their negation is considered as probe
|
|
19
|
+
|
|
20
|
+
void Internal::mark_duplicated_binary_clauses_as_garbage () {
|
|
21
|
+
|
|
22
|
+
if (!opts.deduplicate)
|
|
23
|
+
return;
|
|
24
|
+
if (unsat)
|
|
25
|
+
return;
|
|
26
|
+
if (terminated_asynchronously ())
|
|
27
|
+
return;
|
|
28
|
+
|
|
29
|
+
START_SIMPLIFIER (deduplicate, DEDUP);
|
|
30
|
+
stats.deduplications++;
|
|
31
|
+
|
|
32
|
+
assert (!level);
|
|
33
|
+
assert (watching ());
|
|
34
|
+
|
|
35
|
+
vector<int> stack; // To save marked literals and unmark them later.
|
|
36
|
+
|
|
37
|
+
int64_t subsumed = 0;
|
|
38
|
+
int64_t units = 0;
|
|
39
|
+
|
|
40
|
+
for (auto idx : vars) {
|
|
41
|
+
|
|
42
|
+
if (unsat)
|
|
43
|
+
break;
|
|
44
|
+
if (!active (idx))
|
|
45
|
+
continue;
|
|
46
|
+
int unit = 0;
|
|
47
|
+
|
|
48
|
+
for (int sign = -1; !unit && sign <= 1; sign += 2) {
|
|
49
|
+
|
|
50
|
+
const int lit = sign * idx; // Consider all literals.
|
|
51
|
+
|
|
52
|
+
assert (stack.empty ());
|
|
53
|
+
Watches &ws = watches (lit);
|
|
54
|
+
|
|
55
|
+
// We are removing references to garbage clause. Thus no 'auto'.
|
|
56
|
+
|
|
57
|
+
const const_watch_iterator end = ws.end ();
|
|
58
|
+
watch_iterator j = ws.begin ();
|
|
59
|
+
const_watch_iterator i;
|
|
60
|
+
|
|
61
|
+
for (i = j; !unit && i != end; i++) {
|
|
62
|
+
Watch w = *j++ = *i;
|
|
63
|
+
if (!w.binary ())
|
|
64
|
+
continue;
|
|
65
|
+
int other = w.blit;
|
|
66
|
+
const int tmp = marked (other);
|
|
67
|
+
Clause *c = w.clause;
|
|
68
|
+
|
|
69
|
+
if (tmp > 0) { // Found duplicated binary clause.
|
|
70
|
+
|
|
71
|
+
if (c->garbage) {
|
|
72
|
+
j--;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
LOG (c, "found duplicated");
|
|
76
|
+
|
|
77
|
+
// The previous identical clause 'd' might be redundant and if the
|
|
78
|
+
// second clause 'c' is not (so irredundant), then we have to keep
|
|
79
|
+
// 'c' instead of 'd', thus we search for it and replace it.
|
|
80
|
+
|
|
81
|
+
if (!c->redundant) {
|
|
82
|
+
watch_iterator k;
|
|
83
|
+
for (k = ws.begin ();; k++) {
|
|
84
|
+
assert (k != i);
|
|
85
|
+
if (!k->binary ())
|
|
86
|
+
continue;
|
|
87
|
+
if (k->blit != other)
|
|
88
|
+
continue;
|
|
89
|
+
Clause *d = k->clause;
|
|
90
|
+
if (d->garbage)
|
|
91
|
+
continue;
|
|
92
|
+
c = d;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
*k = w;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
LOG (c, "mark garbage duplicated");
|
|
99
|
+
stats.subsumed++;
|
|
100
|
+
stats.deduplicated++;
|
|
101
|
+
subsumed++;
|
|
102
|
+
mark_garbage (c);
|
|
103
|
+
j--;
|
|
104
|
+
|
|
105
|
+
} else if (tmp < 0) { // Hyper unary resolution.
|
|
106
|
+
|
|
107
|
+
LOG ("found %d %d and %d %d which produces unit %d", lit, -other,
|
|
108
|
+
lit, other, lit);
|
|
109
|
+
unit = lit;
|
|
110
|
+
if (lrat) {
|
|
111
|
+
// taken from fradical
|
|
112
|
+
assert (lrat_chain.empty ());
|
|
113
|
+
lrat_chain.push_back (c->id);
|
|
114
|
+
// We've forgotten where the other binary clause is, so go find
|
|
115
|
+
// it again
|
|
116
|
+
for (watch_iterator k = ws.begin ();; k++) {
|
|
117
|
+
assert (k != i);
|
|
118
|
+
if (!k->binary ())
|
|
119
|
+
continue;
|
|
120
|
+
if (k->blit != -other)
|
|
121
|
+
continue;
|
|
122
|
+
lrat_chain.push_back (k->clause->id);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
j = ws.begin (); // Flush 'ws'.
|
|
127
|
+
units++;
|
|
128
|
+
|
|
129
|
+
} else {
|
|
130
|
+
if (c->garbage) {
|
|
131
|
+
j--;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
mark (other);
|
|
135
|
+
stack.push_back (other);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (j == ws.begin ())
|
|
140
|
+
erase_vector (ws);
|
|
141
|
+
else if (j != end)
|
|
142
|
+
ws.resize (j - ws.begin ()); // Shrink watchers.
|
|
143
|
+
|
|
144
|
+
for (const auto &other : stack)
|
|
145
|
+
unmark (other);
|
|
146
|
+
|
|
147
|
+
stack.clear ();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Propagation potentially messes up the watches and thus we can not
|
|
151
|
+
// propagate the unit immediately after finding it. Instead we break
|
|
152
|
+
// out of both loops and assign and propagate the unit here.
|
|
153
|
+
|
|
154
|
+
if (unit) {
|
|
155
|
+
|
|
156
|
+
stats.failed++;
|
|
157
|
+
stats.hyperunary++;
|
|
158
|
+
assign_unit (unit);
|
|
159
|
+
// lrat_chain.clear (); done in search_assign
|
|
160
|
+
|
|
161
|
+
if (!propagate ()) {
|
|
162
|
+
LOG ("empty clause after propagating unit");
|
|
163
|
+
learn_empty_clause ();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
STOP_SIMPLIFIER (deduplicate, DEDUP);
|
|
168
|
+
|
|
169
|
+
report ('2', !opts.reportall && !(subsumed + units));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/*------------------------------------------------------------------------*/
|
|
173
|
+
|
|
174
|
+
// See the comment for vivifyflush.
|
|
175
|
+
//
|
|
176
|
+
struct deduplicate_flush_smaller {
|
|
177
|
+
|
|
178
|
+
bool operator() (Clause *a, Clause *b) const {
|
|
179
|
+
|
|
180
|
+
const auto eoa = a->end (), eob = b->end ();
|
|
181
|
+
auto i = a->begin (), j = b->begin ();
|
|
182
|
+
for (; i != eoa && j != eob; i++, j++)
|
|
183
|
+
if (*i != *j)
|
|
184
|
+
return *i < *j;
|
|
185
|
+
const bool smaller =
|
|
186
|
+
(j == eob && i != eoa) ||
|
|
187
|
+
(j == eob && i == eoa && !a->redundant && b->redundant) ||
|
|
188
|
+
(j == eob && i == eoa && (a->redundant == b->redundant) &&
|
|
189
|
+
b->id < a->id);
|
|
190
|
+
return smaller;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/*------------------------------------------------------------------------*/
|
|
195
|
+
|
|
196
|
+
// We discovered in a bug report
|
|
197
|
+
// (https://github.com/arminbiere/cadical/issues/147) that some problems
|
|
198
|
+
// contains clauses several times. This was handled properly before (as a
|
|
199
|
+
// side effect of vivifyflush), but the proper ticks scheduling limitation
|
|
200
|
+
// makes this impossible since 2.2. Therefore, we have implemented this
|
|
201
|
+
// detection as a proper inprocessing technique that is off by default and
|
|
202
|
+
// run only once during preprocess quickly. As we do not want to assume
|
|
203
|
+
// anything on the input clauses, we also remove the true/false literals.
|
|
204
|
+
//
|
|
205
|
+
// In essence, the code is simply taken from vivifyflush (without all the
|
|
206
|
+
// rest of the code around obviously).
|
|
207
|
+
//
|
|
208
|
+
void Internal::deduplicate_all_clauses () {
|
|
209
|
+
assert (!level);
|
|
210
|
+
clear_watches ();
|
|
211
|
+
|
|
212
|
+
mark_satisfied_clauses_as_garbage ();
|
|
213
|
+
garbage_collection ();
|
|
214
|
+
|
|
215
|
+
// in order to do the inprocessing inplace, we remove the deleted clauses,
|
|
216
|
+
// put the binary deleted clauses first. Then we work on the non-deleted
|
|
217
|
+
// clauses by sorting them and sorting the clause w.r.t each other.
|
|
218
|
+
auto start = clauses.begin ();
|
|
219
|
+
auto mid = std::partition (clauses.begin (), clauses.end (),
|
|
220
|
+
[] (Clause *c) { return !c->garbage; });
|
|
221
|
+
std::for_each (start, mid,
|
|
222
|
+
[] (Clause *c) { return sort (c->begin (), c->end ()); });
|
|
223
|
+
assert (std::all_of (start, mid, [] (Clause *c) { return !c->garbage; }));
|
|
224
|
+
assert (std::all_of (mid, end (clauses),
|
|
225
|
+
[] (Clause *c) { return c->garbage; }));
|
|
226
|
+
|
|
227
|
+
stable_sort (start, mid, deduplicate_flush_smaller ());
|
|
228
|
+
auto j = start, i = j;
|
|
229
|
+
|
|
230
|
+
Clause *prev = 0;
|
|
231
|
+
int64_t subsumed = 0;
|
|
232
|
+
for (; i != mid; i++) {
|
|
233
|
+
Clause *c = *j++ = *i;
|
|
234
|
+
if (!prev || c->size < prev->size) {
|
|
235
|
+
prev = c;
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const auto eop = prev->end ();
|
|
239
|
+
auto k = prev->begin ();
|
|
240
|
+
for (auto l = c->begin (); k != eop; k++, l++)
|
|
241
|
+
if (*k != *l)
|
|
242
|
+
break;
|
|
243
|
+
if (k == eop) {
|
|
244
|
+
LOG (c, "found subsumed");
|
|
245
|
+
LOG (prev, "subsuming");
|
|
246
|
+
assert (!c->garbage);
|
|
247
|
+
assert (!prev->garbage);
|
|
248
|
+
assert (c->redundant || !prev->redundant);
|
|
249
|
+
mark_garbage (c);
|
|
250
|
+
delete_clause (c);
|
|
251
|
+
subsumed++;
|
|
252
|
+
j--;
|
|
253
|
+
} else
|
|
254
|
+
prev = c;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
for (; i != clauses.end (); ++i) {
|
|
258
|
+
Clause *c = *i;
|
|
259
|
+
assert (c->garbage);
|
|
260
|
+
delete_clause (c);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
clauses.resize (j - clauses.begin ());
|
|
264
|
+
|
|
265
|
+
++stats.deduplicatedinitrounds;
|
|
266
|
+
PHASE ("deduplicate-all", stats.deduplicatedinitrounds,
|
|
267
|
+
"flushed %" PRId64 " subsumed clauses out of %zd", subsumed,
|
|
268
|
+
clauses.end () - start);
|
|
269
|
+
stats.subsumed += subsumed;
|
|
270
|
+
stats.deduplicatedinit += subsumed;
|
|
271
|
+
check_clause_stats ();
|
|
272
|
+
connect_watches ();
|
|
273
|
+
report ('d', !opts.reportall && !subsumed);
|
|
274
|
+
}
|
|
275
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
#define INVALID_LIT UINT_MAX
|
|
6
|
+
|
|
7
|
+
// functions below are passed to kitten
|
|
8
|
+
//
|
|
9
|
+
struct definition_extractor {
|
|
10
|
+
Eliminator *eliminator;
|
|
11
|
+
Internal *internal;
|
|
12
|
+
vector<Clause *> clauses[2];
|
|
13
|
+
int lit;
|
|
14
|
+
vector<vector<int>> implicants;
|
|
15
|
+
int unit;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
extern "C" {
|
|
19
|
+
|
|
20
|
+
// used to extract definitions from kitten
|
|
21
|
+
//
|
|
22
|
+
static void traverse_definition_core (void *state, unsigned id) {
|
|
23
|
+
definition_extractor *extractor = (definition_extractor *) state;
|
|
24
|
+
Clause *clause;
|
|
25
|
+
const vector<Clause *> &clauses0 = extractor->clauses[0];
|
|
26
|
+
const vector<Clause *> &clauses1 = extractor->clauses[1];
|
|
27
|
+
Eliminator *eliminator = extractor->eliminator;
|
|
28
|
+
const size_t size_clauses0 = clauses0.size ();
|
|
29
|
+
const size_t size_clauses1 = clauses1.size ();
|
|
30
|
+
assert (size_clauses0 <= UINT_MAX);
|
|
31
|
+
unsigned sign;
|
|
32
|
+
assert (id < size_clauses0 + size_clauses1);
|
|
33
|
+
if (id < size_clauses0) {
|
|
34
|
+
clause = clauses0[id];
|
|
35
|
+
sign = 1;
|
|
36
|
+
} else {
|
|
37
|
+
unsigned tmp = id - size_clauses0;
|
|
38
|
+
#ifndef NDEBUG
|
|
39
|
+
assert (size_clauses1 <= UINT_MAX);
|
|
40
|
+
assert (tmp < size_clauses1);
|
|
41
|
+
#endif
|
|
42
|
+
clause = clauses1[tmp];
|
|
43
|
+
sign = 2;
|
|
44
|
+
}
|
|
45
|
+
(void) size_clauses1;
|
|
46
|
+
clause->gate = true;
|
|
47
|
+
eliminator->gates.push_back (clause);
|
|
48
|
+
#ifdef LOGGING
|
|
49
|
+
Internal *internal = extractor->internal;
|
|
50
|
+
LOG (clause, "extracted gate");
|
|
51
|
+
#endif
|
|
52
|
+
eliminator->definition_unit |= sign;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// extracts relevant learned clauses from kissat for drat proofs
|
|
56
|
+
//
|
|
57
|
+
static void traverse_one_sided_core_lemma (void *state, bool learned,
|
|
58
|
+
size_t size,
|
|
59
|
+
const unsigned *lits) {
|
|
60
|
+
if (!learned)
|
|
61
|
+
return;
|
|
62
|
+
definition_extractor *extractor = (definition_extractor *) state;
|
|
63
|
+
Eliminator *eliminator = extractor->eliminator;
|
|
64
|
+
Internal *internal = extractor->internal;
|
|
65
|
+
Proof *proof = internal->proof;
|
|
66
|
+
const int unit = extractor->unit;
|
|
67
|
+
vector<proof_clause> &proof_clauses = eliminator->proof_clauses;
|
|
68
|
+
if (size) {
|
|
69
|
+
proof_clause pc;
|
|
70
|
+
pc.id = ++(internal->clause_id);
|
|
71
|
+
pc.literals.push_back (unit);
|
|
72
|
+
const unsigned *end = lits + size;
|
|
73
|
+
for (const unsigned *p = lits; p != end; p++)
|
|
74
|
+
pc.literals.push_back (internal->citten2lit (*p)); // conversion
|
|
75
|
+
proof_clauses.push_back (pc);
|
|
76
|
+
assert (proof);
|
|
77
|
+
proof->add_derived_clause (pc.id, true, pc.literals, pc.chain);
|
|
78
|
+
} else {
|
|
79
|
+
internal->assign_unit (unit);
|
|
80
|
+
for (const auto &pc : proof_clauses) {
|
|
81
|
+
proof->delete_clause (pc.id, true, pc.literals);
|
|
82
|
+
}
|
|
83
|
+
proof_clauses.clear ();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// extract lrat proofs for relevant clauses
|
|
88
|
+
//
|
|
89
|
+
static void traverse_one_sided_core_lemma_with_lrat (
|
|
90
|
+
void *state, unsigned cid, unsigned id, bool learned, size_t size,
|
|
91
|
+
const unsigned *lits, size_t chain_size, const unsigned *chain) {
|
|
92
|
+
definition_extractor *extractor = (definition_extractor *) state;
|
|
93
|
+
Eliminator *eliminator = extractor->eliminator;
|
|
94
|
+
Internal *internal = extractor->internal;
|
|
95
|
+
Proof *proof = internal->proof;
|
|
96
|
+
const int unit = extractor->unit;
|
|
97
|
+
const vector<Clause *> &clauses0 = extractor->clauses[0];
|
|
98
|
+
const vector<Clause *> &clauses1 = extractor->clauses[1];
|
|
99
|
+
vector<proof_clause> &proof_clauses = eliminator->proof_clauses;
|
|
100
|
+
if (!learned) { // remember clauses for mapping to kitten internal
|
|
101
|
+
assert (size);
|
|
102
|
+
assert (!chain_size);
|
|
103
|
+
proof_clause pc;
|
|
104
|
+
pc.cid = cid;
|
|
105
|
+
pc.learned = false;
|
|
106
|
+
const size_t size_clauses0 = clauses0.size ();
|
|
107
|
+
assert (size_clauses0 <= UINT_MAX);
|
|
108
|
+
if (id < size_clauses0) {
|
|
109
|
+
pc.id = clauses0[id]->id;
|
|
110
|
+
} else {
|
|
111
|
+
unsigned tmp = id - size_clauses0;
|
|
112
|
+
#ifndef NDEBUG
|
|
113
|
+
const size_t size_clauses1 = clauses1.size ();
|
|
114
|
+
assert (size_clauses1 <= UINT_MAX);
|
|
115
|
+
assert (tmp < size_clauses1);
|
|
116
|
+
#endif
|
|
117
|
+
pc.id = clauses1[tmp]->id;
|
|
118
|
+
}
|
|
119
|
+
proof_clauses.push_back (pc);
|
|
120
|
+
} else { // actually add to proof
|
|
121
|
+
assert (chain_size);
|
|
122
|
+
if (size) {
|
|
123
|
+
proof_clause pc;
|
|
124
|
+
pc.id = ++(internal->clause_id);
|
|
125
|
+
pc.cid = cid;
|
|
126
|
+
pc.learned = true;
|
|
127
|
+
pc.literals.push_back (unit);
|
|
128
|
+
const unsigned *end = lits + size;
|
|
129
|
+
for (const unsigned *p = lits; p != end; p++)
|
|
130
|
+
pc.literals.push_back (internal->citten2lit (*p)); // conversion
|
|
131
|
+
for (const unsigned *p = chain + chain_size; p != chain; p--) {
|
|
132
|
+
int64_t id = 0;
|
|
133
|
+
for (const auto &cpc : proof_clauses) {
|
|
134
|
+
if (cpc.cid == *(p - 1)) {
|
|
135
|
+
id = cpc.id;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
assert (id);
|
|
140
|
+
pc.chain.push_back (id);
|
|
141
|
+
}
|
|
142
|
+
proof_clauses.push_back (pc);
|
|
143
|
+
assert (proof);
|
|
144
|
+
proof->add_derived_clause (pc.id, true, pc.literals, pc.chain);
|
|
145
|
+
} else { // learn unit finish proof
|
|
146
|
+
assert (internal->lrat_chain.empty ());
|
|
147
|
+
for (const unsigned *p = chain + chain_size; p != chain; p--) {
|
|
148
|
+
int64_t id = 0;
|
|
149
|
+
for (const auto &cpc : proof_clauses) {
|
|
150
|
+
if (cpc.cid == *(p - 1)) {
|
|
151
|
+
id = cpc.id;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
assert (id);
|
|
156
|
+
internal->lrat_chain.push_back (id);
|
|
157
|
+
}
|
|
158
|
+
internal->assign_unit (unit);
|
|
159
|
+
assert (internal->lrat_chain.empty ());
|
|
160
|
+
for (const auto &pc : proof_clauses) {
|
|
161
|
+
if (pc.learned)
|
|
162
|
+
proof->delete_clause (pc.id, true, pc.literals);
|
|
163
|
+
}
|
|
164
|
+
proof_clauses.clear ();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
} // end extern C
|
|
170
|
+
|
|
171
|
+
// Code ported from kissat. Kitten (and kissat) use unsigned representation
|
|
172
|
+
// for literals whereas CaDiCaL uses signed representation. Conversion is
|
|
173
|
+
// necessary for communication using lit2citten and citten2lit.
|
|
174
|
+
// This code is called in elim and kitten is initialized beforehand.
|
|
175
|
+
// To avoid confusion all cadical interal definitions with kitten are called
|
|
176
|
+
// citten.
|
|
177
|
+
//
|
|
178
|
+
void Internal::find_definition (Eliminator &eliminator, int lit) {
|
|
179
|
+
if (!opts.elimdef)
|
|
180
|
+
return;
|
|
181
|
+
if (unsat)
|
|
182
|
+
return;
|
|
183
|
+
if (val (lit))
|
|
184
|
+
return;
|
|
185
|
+
if (!eliminator.gates.empty ())
|
|
186
|
+
return;
|
|
187
|
+
assert (!val (lit));
|
|
188
|
+
assert (!level);
|
|
189
|
+
assert (citten);
|
|
190
|
+
const int not_lit = -lit;
|
|
191
|
+
definition_extractor extractor;
|
|
192
|
+
extractor.lit = lit;
|
|
193
|
+
extractor.clauses[0] = occs (lit);
|
|
194
|
+
extractor.clauses[1] = occs (not_lit);
|
|
195
|
+
extractor.eliminator = &eliminator;
|
|
196
|
+
extractor.internal = internal;
|
|
197
|
+
citten_clear_track_log_terminate ();
|
|
198
|
+
unsigned exported = 0;
|
|
199
|
+
for (unsigned sign = 0; sign < 2; sign++) {
|
|
200
|
+
const unsigned except = sign ? lit2citten (not_lit) : lit2citten (lit);
|
|
201
|
+
for (auto c : extractor.clauses[sign]) {
|
|
202
|
+
// to avoid copying the literals of c in their unsigned
|
|
203
|
+
// representation we instead implement the translation in kitten
|
|
204
|
+
if (!c->garbage) {
|
|
205
|
+
LOG (c, "adding to kitten");
|
|
206
|
+
citten_clause_with_id_and_exception (citten, exported, c->size,
|
|
207
|
+
c->literals, except);
|
|
208
|
+
}
|
|
209
|
+
exported++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
stats.definitions_checked++;
|
|
213
|
+
const size_t limit = opts.elimdefticks;
|
|
214
|
+
kitten_set_ticks_limit (citten, limit);
|
|
215
|
+
int status = kitten_solve (citten);
|
|
216
|
+
if (!exported)
|
|
217
|
+
goto ABORT;
|
|
218
|
+
if (status == 20) {
|
|
219
|
+
LOG ("sub-solver result UNSAT shows definition exists");
|
|
220
|
+
uint64_t learned;
|
|
221
|
+
unsigned reduced = kitten_compute_clausal_core (citten, &learned);
|
|
222
|
+
LOG ("1st sub-solver core of size %u original clauses out of %u",
|
|
223
|
+
reduced, exported);
|
|
224
|
+
for (int i = 2; i <= opts.elimdefcores; i++) {
|
|
225
|
+
kitten_shrink_to_clausal_core (citten);
|
|
226
|
+
kitten_shuffle_clauses (citten);
|
|
227
|
+
kitten_set_ticks_limit (citten, 10 * limit);
|
|
228
|
+
int tmp = kitten_solve (citten);
|
|
229
|
+
assert (!tmp || tmp == 20);
|
|
230
|
+
if (!tmp) {
|
|
231
|
+
LOG ("aborting core extraction");
|
|
232
|
+
goto ABORT;
|
|
233
|
+
}
|
|
234
|
+
#ifndef NDEBUG
|
|
235
|
+
unsigned previous = reduced;
|
|
236
|
+
#endif
|
|
237
|
+
reduced = kitten_compute_clausal_core (citten, &learned);
|
|
238
|
+
LOG ("%d sub-solver core of size %u original clauses out of %u", i,
|
|
239
|
+
reduced, exported);
|
|
240
|
+
assert (reduced <= previous);
|
|
241
|
+
#if not defined(LOGGING) && defined(NDEBUG)
|
|
242
|
+
(void) reduced;
|
|
243
|
+
#endif
|
|
244
|
+
}
|
|
245
|
+
stats.definitions_extracted++;
|
|
246
|
+
eliminator.gatetype = DEF;
|
|
247
|
+
eliminator.definition_unit = 0;
|
|
248
|
+
kitten_traverse_core_ids (citten, &extractor, traverse_definition_core);
|
|
249
|
+
assert (eliminator.definition_unit);
|
|
250
|
+
int unit = 0;
|
|
251
|
+
if (eliminator.definition_unit == 2) {
|
|
252
|
+
unit = not_lit;
|
|
253
|
+
} else if (eliminator.definition_unit == 1)
|
|
254
|
+
unit = lit;
|
|
255
|
+
|
|
256
|
+
if (unit) {
|
|
257
|
+
stats.definition_units++;
|
|
258
|
+
VERBOSE (2, "one sided core "
|
|
259
|
+
"definition extraction yields "
|
|
260
|
+
"failed literal");
|
|
261
|
+
if (proof) {
|
|
262
|
+
if (lrat) {
|
|
263
|
+
extractor.unit = unit;
|
|
264
|
+
kitten_trace_core (citten, &extractor,
|
|
265
|
+
traverse_one_sided_core_lemma_with_lrat);
|
|
266
|
+
} else {
|
|
267
|
+
extractor.unit = unit;
|
|
268
|
+
kitten_traverse_core_clauses (citten, &extractor,
|
|
269
|
+
traverse_one_sided_core_lemma);
|
|
270
|
+
}
|
|
271
|
+
} else
|
|
272
|
+
assign_unit (unit);
|
|
273
|
+
elim_propagate (eliminator, unit);
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
ABORT:
|
|
277
|
+
LOG ("sub-solver failed to show that definition exists");
|
|
278
|
+
}
|
|
279
|
+
stats.definition_ticks += kitten_current_ticks (citten);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#ifndef _delay_hpp_INCLUDED
|
|
2
|
+
#define _delay_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
#include <limits>
|
|
6
|
+
|
|
7
|
+
namespace CaDiCaL {
|
|
8
|
+
struct Delay {
|
|
9
|
+
unsigned count;
|
|
10
|
+
unsigned current;
|
|
11
|
+
|
|
12
|
+
Delay () : count (0), current (0) {}
|
|
13
|
+
|
|
14
|
+
bool delay () {
|
|
15
|
+
if (count) {
|
|
16
|
+
--count;
|
|
17
|
+
return true;
|
|
18
|
+
} else {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
void bump_delay () {
|
|
24
|
+
current += current < std::numeric_limits<unsigned>::max ();
|
|
25
|
+
count = current;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void reduce_delay () {
|
|
29
|
+
if (!current)
|
|
30
|
+
return;
|
|
31
|
+
current /= 2;
|
|
32
|
+
count = current;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
} // namespace CaDiCaL
|
|
37
|
+
|
|
38
|
+
#endif
|