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,125 @@
|
|
|
1
|
+
#ifndef _range_hpp_INCLUDED
|
|
2
|
+
#define _range_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include <cassert>
|
|
5
|
+
|
|
6
|
+
namespace CaDiCaL {
|
|
7
|
+
|
|
8
|
+
struct Clause;
|
|
9
|
+
|
|
10
|
+
/*----------------------------------------------------------------------*/
|
|
11
|
+
|
|
12
|
+
// Used for compact and safe iteration over positive ranges of integers,
|
|
13
|
+
// particularly for iterating over all variable indices.
|
|
14
|
+
//
|
|
15
|
+
// Range vars (max_var);
|
|
16
|
+
// for (auto idx : vars) ...
|
|
17
|
+
//
|
|
18
|
+
// This iterates over '1, ..., max_var' and is safe for non-negative
|
|
19
|
+
// numbers, thus also for 'max_var == 0' or 'max_var == INT_MAX'.
|
|
20
|
+
//
|
|
21
|
+
// Note that
|
|
22
|
+
//
|
|
23
|
+
// for (int idx = 1; idx <= max_var; idx++) ...
|
|
24
|
+
//
|
|
25
|
+
// leads to an overflow if 'max_var == INT_MAX' and thus depending on what
|
|
26
|
+
// the compiler does ('int' overflow is undefined) might lead to any
|
|
27
|
+
// behaviour (infinite loop or worse array access way out of bounds).
|
|
28
|
+
//
|
|
29
|
+
// If we make 'idx' in this last 'for' loop an 'unsigned' then it is safe to
|
|
30
|
+
// use this idiom, but we would need to cast 'max_var' explicitly to 'int'
|
|
31
|
+
// in order to avoid a warning in the loop condition and actually everywhere
|
|
32
|
+
// where 'idx' is compared to a 'signed' expression. Worse for instance
|
|
33
|
+
// 'vals[-idx]' will lead to out of bounds access too. This is awkward and
|
|
34
|
+
// using the range iterator provided here is safer in general.
|
|
35
|
+
//
|
|
36
|
+
// Another issue is that the dereferencing operator '*' below is required to
|
|
37
|
+
// return a reference to the internal index of the iterator. Thus the 'idx'
|
|
38
|
+
// in the auto loop is actually of the same type as the internal state of
|
|
39
|
+
// the iterator. To keep it 'signed' and still avoid overflow issues we
|
|
40
|
+
// just have to make sure to use the proper increment (with two implicit
|
|
41
|
+
// casts, i.e., from 'int' to 'unsigned', then 'unsigned' addition and the
|
|
42
|
+
// result is cast back from 'unsigned' to 'int').
|
|
43
|
+
//
|
|
44
|
+
// For simplicity we keep a reference to the actual maximum integer, e.g.,
|
|
45
|
+
// 'max_var', which makes the idiom 'for (auto idx : vars) ...' possible.
|
|
46
|
+
// Further note that the referenced integer has to be non-negative before
|
|
47
|
+
// starting to iterate (it can be zero though), otherwise it breaks.
|
|
48
|
+
|
|
49
|
+
class Range {
|
|
50
|
+
static unsigned inc (unsigned u) { return u + 1u; }
|
|
51
|
+
static unsigned dec (unsigned u) { return u - 1u; }
|
|
52
|
+
class iterator {
|
|
53
|
+
int idx;
|
|
54
|
+
|
|
55
|
+
public:
|
|
56
|
+
iterator (int i) : idx (i) {}
|
|
57
|
+
void operator++ () { idx = inc (idx); }
|
|
58
|
+
const int &operator* () const { return idx; }
|
|
59
|
+
friend bool operator!= (const iterator &a, const iterator &b) {
|
|
60
|
+
return a.idx != b.idx;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Reverse iterator for iterating from max_var down to 1
|
|
65
|
+
class reverse_iterator {
|
|
66
|
+
int idx;
|
|
67
|
+
|
|
68
|
+
public:
|
|
69
|
+
reverse_iterator (int i) : idx (i) {}
|
|
70
|
+
void operator++ () { idx = dec (idx); }
|
|
71
|
+
const int &operator* () const { return idx; }
|
|
72
|
+
friend bool operator!= (const reverse_iterator &a,
|
|
73
|
+
const reverse_iterator &b) {
|
|
74
|
+
return a.idx != b.idx;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
int &n;
|
|
79
|
+
|
|
80
|
+
public:
|
|
81
|
+
// forward iterator
|
|
82
|
+
iterator begin () const { return assert (n >= 0), iterator (inc (0)); }
|
|
83
|
+
iterator end () const { return assert (n >= 0), iterator (inc (n)); }
|
|
84
|
+
|
|
85
|
+
// Reverse iteration methods
|
|
86
|
+
reverse_iterator rbegin () const {
|
|
87
|
+
return assert (n >= 0), reverse_iterator (n);
|
|
88
|
+
}
|
|
89
|
+
reverse_iterator rend () const {
|
|
90
|
+
return assert (n >= 0), reverse_iterator (0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
Range (int &m) : n (m) { assert (m >= 0); }
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Same, but iterating over literals '-1,1,-2,2,....,-max_var,max_var'.
|
|
97
|
+
//
|
|
98
|
+
// The only difference to 'Range' is the 'inc' function, but I am too lazy
|
|
99
|
+
// to figure out how to properly factor the code into a generic range
|
|
100
|
+
// template with 'inc' as only parameter. This gives at least clean code.
|
|
101
|
+
|
|
102
|
+
class Sange {
|
|
103
|
+
static unsigned inc (unsigned u) { return ~u + (u >> 31); }
|
|
104
|
+
class iterator {
|
|
105
|
+
int lit;
|
|
106
|
+
|
|
107
|
+
public:
|
|
108
|
+
iterator (int i) : lit (i) {}
|
|
109
|
+
void operator++ () { lit = inc (lit); }
|
|
110
|
+
const int &operator* () const { return lit; }
|
|
111
|
+
friend bool operator!= (const iterator &a, const iterator &b) {
|
|
112
|
+
return a.lit != b.lit;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
int &n;
|
|
116
|
+
|
|
117
|
+
public:
|
|
118
|
+
iterator begin () const { return assert (n >= 0), iterator (inc (0)); }
|
|
119
|
+
iterator end () const { return assert (n >= 0), iterator (inc (n)); }
|
|
120
|
+
Sange (int &m) : n (m) { assert (m >= 0); }
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
} // namespace CaDiCaL
|
|
124
|
+
|
|
125
|
+
#endif
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#include "reap.hpp"
|
|
2
|
+
#include <cassert>
|
|
3
|
+
#include <climits>
|
|
4
|
+
#include <cstring>
|
|
5
|
+
|
|
6
|
+
void Reap::init () {
|
|
7
|
+
for (auto &bucket : buckets)
|
|
8
|
+
bucket = {0};
|
|
9
|
+
assert (!num_elements);
|
|
10
|
+
assert (!last_deleted);
|
|
11
|
+
min_bucket = 32;
|
|
12
|
+
assert (!max_bucket);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
void Reap::release () {
|
|
16
|
+
num_elements = 0;
|
|
17
|
+
last_deleted = 0;
|
|
18
|
+
min_bucket = 32;
|
|
19
|
+
max_bucket = 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Reap::Reap () {
|
|
23
|
+
num_elements = 0;
|
|
24
|
+
last_deleted = 0;
|
|
25
|
+
min_bucket = 32;
|
|
26
|
+
max_bucket = 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static inline unsigned leading_zeroes_of_unsigned (unsigned x) {
|
|
30
|
+
return x ? __builtin_clz (x) : sizeof (unsigned) * 8;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void Reap::push (unsigned e) {
|
|
34
|
+
assert (last_deleted <= e);
|
|
35
|
+
const unsigned diff = e ^ last_deleted;
|
|
36
|
+
const unsigned bucket = 32 - leading_zeroes_of_unsigned (diff);
|
|
37
|
+
buckets[bucket].push_back (e);
|
|
38
|
+
if (min_bucket > bucket)
|
|
39
|
+
min_bucket = bucket;
|
|
40
|
+
if (max_bucket < bucket)
|
|
41
|
+
max_bucket = bucket;
|
|
42
|
+
assert (num_elements != UINT_MAX);
|
|
43
|
+
num_elements++;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
unsigned Reap::pop () {
|
|
47
|
+
assert (num_elements > 0);
|
|
48
|
+
unsigned i = min_bucket;
|
|
49
|
+
for (;;) {
|
|
50
|
+
assert (i < 33);
|
|
51
|
+
assert (i <= max_bucket);
|
|
52
|
+
std::vector<unsigned> &s = buckets[i];
|
|
53
|
+
if (s.empty ()) {
|
|
54
|
+
min_bucket = ++i;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
unsigned res;
|
|
58
|
+
if (i) {
|
|
59
|
+
res = UINT_MAX;
|
|
60
|
+
const auto begin = std::begin (s);
|
|
61
|
+
const auto end = std::end (s);
|
|
62
|
+
auto q = std::begin (s);
|
|
63
|
+
assert (begin < end);
|
|
64
|
+
for (auto p = begin; p != end; ++p) {
|
|
65
|
+
const unsigned tmp = *p;
|
|
66
|
+
if (tmp >= res)
|
|
67
|
+
continue;
|
|
68
|
+
res = tmp;
|
|
69
|
+
q = p;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (auto p = begin; p != end; ++p) {
|
|
73
|
+
if (p == q)
|
|
74
|
+
continue;
|
|
75
|
+
const unsigned other = *p;
|
|
76
|
+
const unsigned diff = other ^ res;
|
|
77
|
+
assert (sizeof (unsigned) == 4);
|
|
78
|
+
const unsigned j = 32 - leading_zeroes_of_unsigned (diff);
|
|
79
|
+
assert (j < i);
|
|
80
|
+
buckets[j].push_back (other);
|
|
81
|
+
if (min_bucket > j)
|
|
82
|
+
min_bucket = j;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
s.clear ();
|
|
86
|
+
|
|
87
|
+
if (i && max_bucket == i) {
|
|
88
|
+
#ifndef NDEBUG
|
|
89
|
+
for (unsigned j = i + 1; j < 33; j++)
|
|
90
|
+
assert (buckets[j].empty ());
|
|
91
|
+
#endif
|
|
92
|
+
if (s.empty ())
|
|
93
|
+
max_bucket = i - 1;
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
res = last_deleted;
|
|
97
|
+
assert (!buckets[0].empty ());
|
|
98
|
+
assert (buckets[0].at (0) == res);
|
|
99
|
+
buckets[0].pop_back ();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (min_bucket == i) {
|
|
103
|
+
#ifndef NDEBUG
|
|
104
|
+
for (unsigned j = 0; j < i; j++)
|
|
105
|
+
assert (buckets[j].empty ());
|
|
106
|
+
#endif
|
|
107
|
+
if (s.empty ())
|
|
108
|
+
min_bucket = std::min ((int) (i + 1), 32);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
--num_elements;
|
|
112
|
+
assert (last_deleted <= res);
|
|
113
|
+
last_deleted = res;
|
|
114
|
+
|
|
115
|
+
return res;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void Reap::clear () {
|
|
120
|
+
assert (max_bucket <= 32);
|
|
121
|
+
for (unsigned i = 0; i < 33; i++)
|
|
122
|
+
buckets[i].clear ();
|
|
123
|
+
num_elements = 0;
|
|
124
|
+
last_deleted = 0;
|
|
125
|
+
min_bucket = 32;
|
|
126
|
+
max_bucket = 0;
|
|
127
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#ifndef _reap_h_INCLUDED
|
|
2
|
+
#define _reap_h_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include <cstddef>
|
|
5
|
+
#include <vector>
|
|
6
|
+
|
|
7
|
+
class Reap {
|
|
8
|
+
public:
|
|
9
|
+
Reap ();
|
|
10
|
+
void init ();
|
|
11
|
+
void release ();
|
|
12
|
+
inline bool empty () { return !num_elements; }
|
|
13
|
+
|
|
14
|
+
inline size_t size () { return num_elements; }
|
|
15
|
+
|
|
16
|
+
void push (unsigned);
|
|
17
|
+
void clear ();
|
|
18
|
+
unsigned pop ();
|
|
19
|
+
|
|
20
|
+
private:
|
|
21
|
+
size_t num_elements;
|
|
22
|
+
unsigned last_deleted;
|
|
23
|
+
unsigned min_bucket;
|
|
24
|
+
unsigned max_bucket;
|
|
25
|
+
std::vector<unsigned> buckets[33];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
#endif
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
/*------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
// Once in a while we reduce, e.g., we remove learned clauses which are
|
|
8
|
+
// supposed to be less useful in the future. This is done in increasing
|
|
9
|
+
// intervals, which has the effect of allowing more and more learned clause
|
|
10
|
+
// to be kept for a longer period. The number of learned clauses kept
|
|
11
|
+
// in memory corresponds to an upper bound on the 'space' of a resolution
|
|
12
|
+
// proof needed to refute a formula in proof complexity sense.
|
|
13
|
+
|
|
14
|
+
bool Internal::reducing () {
|
|
15
|
+
if (!opts.reduce)
|
|
16
|
+
return false;
|
|
17
|
+
if (!stats.current.redundant)
|
|
18
|
+
return false;
|
|
19
|
+
return stats.conflicts >= lim.reduce;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/*------------------------------------------------------------------------*/
|
|
23
|
+
|
|
24
|
+
// Even less regularly we are flushing all redundant clauses.
|
|
25
|
+
|
|
26
|
+
bool Internal::flushing () {
|
|
27
|
+
if (!opts.flush)
|
|
28
|
+
return false;
|
|
29
|
+
return stats.conflicts >= lim.flush;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/*------------------------------------------------------------------------*/
|
|
33
|
+
|
|
34
|
+
void Internal::mark_clauses_to_be_flushed () {
|
|
35
|
+
const int tier1limit = tier1[false];
|
|
36
|
+
const int tier2limit = max (tier1limit, tier2[false]);
|
|
37
|
+
for (const auto &c : clauses) {
|
|
38
|
+
if (!c->redundant)
|
|
39
|
+
continue; // keep irredundant
|
|
40
|
+
if (c->garbage)
|
|
41
|
+
continue; // already marked as garbage
|
|
42
|
+
if (c->reason)
|
|
43
|
+
continue; // need to keep reasons
|
|
44
|
+
const unsigned used = c->used;
|
|
45
|
+
if (used)
|
|
46
|
+
c->used--;
|
|
47
|
+
if (c->glue <= tier1limit && used)
|
|
48
|
+
continue;
|
|
49
|
+
if (c->glue <= tier2limit && used >= max_used - 1)
|
|
50
|
+
continue;
|
|
51
|
+
mark_garbage (c); // flush unused clauses
|
|
52
|
+
if (c->hyper)
|
|
53
|
+
stats.flush.hyper++;
|
|
54
|
+
else
|
|
55
|
+
stats.flush.learned++;
|
|
56
|
+
}
|
|
57
|
+
// No change to 'lim.kept{size,glue}'.
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*------------------------------------------------------------------------*/
|
|
61
|
+
|
|
62
|
+
// Clauses of larger glue or larger size are considered less useful.
|
|
63
|
+
//
|
|
64
|
+
// We also follow the observations made by the Glucose team in their
|
|
65
|
+
// IJCAI'09 paper and keep all low glue clauses limited by
|
|
66
|
+
// 'options.keepglue' (typically '2').
|
|
67
|
+
//
|
|
68
|
+
// In earlier versions we pre-computed a 64-bit sort key per clause and
|
|
69
|
+
// wrapped a pointer to the clause and the 64-bit sort key into a separate
|
|
70
|
+
// data structure for sorting. This was probably faster but awkward and
|
|
71
|
+
// so we moved back to a simpler scheme which also uses 'stable_sort'
|
|
72
|
+
// instead of 'rsort' below. Sorting here is not a hot-spot anyhow.
|
|
73
|
+
|
|
74
|
+
struct reduce_less_useful {
|
|
75
|
+
bool operator() (const Clause *c, const Clause *d) const {
|
|
76
|
+
if (c->glue > d->glue)
|
|
77
|
+
return true;
|
|
78
|
+
if (c->glue < d->glue)
|
|
79
|
+
return false;
|
|
80
|
+
return c->size > d->size;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// This function implements the important reduction policy. It determines
|
|
85
|
+
// which redundant clauses are considered not useful and thus will be
|
|
86
|
+
// collected in a subsequent garbage collection phase.
|
|
87
|
+
|
|
88
|
+
void Internal::mark_useless_redundant_clauses_as_garbage () {
|
|
89
|
+
|
|
90
|
+
// We use a separate stack for sorting candidates for removal. This uses
|
|
91
|
+
// (slightly) more memory but has the advantage to keep the relative order
|
|
92
|
+
// in 'clauses' intact, which actually due to using stable sorting goes
|
|
93
|
+
// into the candidate selection (more recently learned clauses are kept if
|
|
94
|
+
// they otherwise have the same glue and size).
|
|
95
|
+
|
|
96
|
+
vector<Clause *> stack;
|
|
97
|
+
const int tier1limit = tier1[false];
|
|
98
|
+
const int tier2limit = max (tier1limit, tier2[false]);
|
|
99
|
+
|
|
100
|
+
stack.reserve (stats.current.redundant);
|
|
101
|
+
|
|
102
|
+
for (const auto &c : clauses) {
|
|
103
|
+
if (!c->redundant)
|
|
104
|
+
continue; // Keep irredundant.
|
|
105
|
+
if (c->garbage)
|
|
106
|
+
continue; // Skip already marked.
|
|
107
|
+
if (c->reason)
|
|
108
|
+
continue; // Need to keep reasons.
|
|
109
|
+
const unsigned used = c->used;
|
|
110
|
+
if (used)
|
|
111
|
+
c->used--;
|
|
112
|
+
if (c->glue <= tier1limit && used)
|
|
113
|
+
continue;
|
|
114
|
+
if (c->glue <= tier2limit && used >= max_used - 1)
|
|
115
|
+
continue;
|
|
116
|
+
if (c->hyper) { // Hyper binary and ternary resolvents
|
|
117
|
+
assert (c->size <= 3); // are only kept for one reduce round
|
|
118
|
+
if (!used)
|
|
119
|
+
mark_garbage (c); // unless
|
|
120
|
+
continue; // used recently.
|
|
121
|
+
}
|
|
122
|
+
stack.push_back (c);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
stable_sort (stack.begin (), stack.end (), reduce_less_useful ());
|
|
126
|
+
size_t target = 1e-2 * opts.reducetarget * stack.size ();
|
|
127
|
+
|
|
128
|
+
// This is defensive code, which I usually consider a bug, but here I am
|
|
129
|
+
// just not sure that using floating points in the line above is precise
|
|
130
|
+
// in all situations and instead of figuring that out, I just use this.
|
|
131
|
+
//
|
|
132
|
+
if (target > stack.size ())
|
|
133
|
+
target = stack.size ();
|
|
134
|
+
|
|
135
|
+
PHASE ("reduce", stats.reductions, "reducing %zd clauses %.0f%%", target,
|
|
136
|
+
percent (target, stats.current.redundant));
|
|
137
|
+
|
|
138
|
+
auto i = stack.begin ();
|
|
139
|
+
const auto t = i + target;
|
|
140
|
+
while (i != t) {
|
|
141
|
+
Clause *c = *i++;
|
|
142
|
+
LOG (c, "marking useless to be collected");
|
|
143
|
+
mark_garbage (c);
|
|
144
|
+
stats.reduced++;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
lim.keptsize = lim.keptglue = 0;
|
|
148
|
+
|
|
149
|
+
const auto end = stack.end ();
|
|
150
|
+
for (i = t; i != end; i++) {
|
|
151
|
+
Clause *c = *i;
|
|
152
|
+
LOG (c, "keeping");
|
|
153
|
+
if (c->size > lim.keptsize)
|
|
154
|
+
lim.keptsize = c->size;
|
|
155
|
+
if (c->glue > lim.keptglue)
|
|
156
|
+
lim.keptglue = c->glue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
erase_vector (stack);
|
|
160
|
+
|
|
161
|
+
PHASE ("reduce", stats.reductions, "maximum kept size %d glue %d",
|
|
162
|
+
lim.keptsize, lim.keptglue);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/*------------------------------------------------------------------------*/
|
|
166
|
+
|
|
167
|
+
// If chronological backtracking produces out-of-order assigned units, then
|
|
168
|
+
// it is necessary to completely propagate them at the root level in order
|
|
169
|
+
// to derive all implied units. Otherwise the blocking literals in
|
|
170
|
+
// 'flush_watches' are messed up and assertion 'FW1' fails.
|
|
171
|
+
|
|
172
|
+
bool Internal::propagate_out_of_order_units () {
|
|
173
|
+
if (!level)
|
|
174
|
+
return true;
|
|
175
|
+
int oou = 0;
|
|
176
|
+
for (size_t i = control[1].trail; !oou && i < trail.size (); i++) {
|
|
177
|
+
const int lit = trail[i];
|
|
178
|
+
assert (val (lit) > 0);
|
|
179
|
+
if (var (lit).level)
|
|
180
|
+
continue;
|
|
181
|
+
LOG ("found out-of-order assigned unit %d", oou);
|
|
182
|
+
oou = lit;
|
|
183
|
+
}
|
|
184
|
+
if (!oou)
|
|
185
|
+
return true;
|
|
186
|
+
assert (opts.chrono || external_prop || did_external_prop);
|
|
187
|
+
backtrack (0);
|
|
188
|
+
if (propagate ())
|
|
189
|
+
return true;
|
|
190
|
+
learn_empty_clause ();
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/*------------------------------------------------------------------------*/
|
|
195
|
+
|
|
196
|
+
// reduction is scheduled with reduceint, reducetarget and reduceopt.
|
|
197
|
+
// with reduceopt=1 the number of learnt clauses scale with
|
|
198
|
+
// sqrt of conflicts times reduceint
|
|
199
|
+
// the scaling is the same as with reduceopt=0 (the classical default)
|
|
200
|
+
// however, the constants are different. To avoid this (and get roughly the
|
|
201
|
+
// same behaviour with reduceopt=0 and reduceopt=1) we need to scale the
|
|
202
|
+
// interval, namely (reduceint^2/2)
|
|
203
|
+
// Lastly, reduceopt=2 just replaces sqrt conflicts with log conflicts.
|
|
204
|
+
// The learnt clauses should not be bigger than
|
|
205
|
+
// 1/reducetarget * reduceint * function (conflicts)
|
|
206
|
+
// for function being log if reduceint=2 an sqrt otherwise.
|
|
207
|
+
// This is however only the theoretical target and second chance for
|
|
208
|
+
// tier2 clauses and very long lifespan of tier1 clauses (through used flag)
|
|
209
|
+
// make this behave differently.
|
|
210
|
+
// reduceinit shifts the curve to the right, increasing the number of
|
|
211
|
+
// clauses in the solver. This impact will decrease over time.
|
|
212
|
+
|
|
213
|
+
void Internal::reduce () {
|
|
214
|
+
START (reduce);
|
|
215
|
+
|
|
216
|
+
stats.reductions++;
|
|
217
|
+
report ('.', 1);
|
|
218
|
+
|
|
219
|
+
bool flush = flushing ();
|
|
220
|
+
if (flush)
|
|
221
|
+
stats.flush.count++;
|
|
222
|
+
|
|
223
|
+
if (!propagate_out_of_order_units ())
|
|
224
|
+
goto DONE;
|
|
225
|
+
|
|
226
|
+
mark_satisfied_clauses_as_garbage ();
|
|
227
|
+
protect_reasons ();
|
|
228
|
+
if (flush)
|
|
229
|
+
mark_clauses_to_be_flushed ();
|
|
230
|
+
else
|
|
231
|
+
mark_useless_redundant_clauses_as_garbage ();
|
|
232
|
+
garbage_collection ();
|
|
233
|
+
|
|
234
|
+
{
|
|
235
|
+
int64_t delta = opts.reduceint;
|
|
236
|
+
double factor = stats.reductions + 1;
|
|
237
|
+
if (opts.reduceopt ==
|
|
238
|
+
0) // adjust delta such this is the same as reduceopt=1
|
|
239
|
+
delta = delta * delta / 2;
|
|
240
|
+
else if (opts.reduceopt == 1) {
|
|
241
|
+
// this is the same as reduceopt=0 if reduceint = sqrt (reduceint) =
|
|
242
|
+
// 17
|
|
243
|
+
factor = sqrt ((double) stats.conflicts);
|
|
244
|
+
} else if (opts.reduceopt == 2)
|
|
245
|
+
// log scaling instead
|
|
246
|
+
factor = log ((double) stats.conflicts);
|
|
247
|
+
if (factor < 1)
|
|
248
|
+
factor = 1;
|
|
249
|
+
delta = delta * factor;
|
|
250
|
+
if (irredundant () > 1e5) {
|
|
251
|
+
delta *= log (irredundant () / 1e4) / log (10);
|
|
252
|
+
}
|
|
253
|
+
if (delta < 1)
|
|
254
|
+
delta = 1;
|
|
255
|
+
lim.reduce = stats.conflicts + delta;
|
|
256
|
+
PHASE ("reduce", stats.reductions,
|
|
257
|
+
"new reduce limit %" PRId64 " after %" PRId64 " conflicts",
|
|
258
|
+
lim.reduce, delta);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (flush) {
|
|
262
|
+
PHASE ("flush", stats.flush.count, "new flush increment %" PRId64 "",
|
|
263
|
+
inc.flush);
|
|
264
|
+
inc.flush *= opts.flushfactor;
|
|
265
|
+
lim.flush = stats.conflicts + inc.flush;
|
|
266
|
+
PHASE ("flush", stats.flush.count, "new flush limit %" PRId64 "",
|
|
267
|
+
lim.flush);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
last.reduce.conflicts = stats.conflicts;
|
|
271
|
+
|
|
272
|
+
DONE:
|
|
273
|
+
|
|
274
|
+
report (flush ? 'f' : '-');
|
|
275
|
+
STOP (reduce);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#ifndef _reluctant_hpp_INCLUDED
|
|
2
|
+
#define _reluctant_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include <cassert>
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
|
|
7
|
+
namespace CaDiCaL {
|
|
8
|
+
|
|
9
|
+
// This is Donald Knuth's version of the Luby restart sequence which he
|
|
10
|
+
// called 'reluctant doubling'. His bit-twiddling formulation in line (DK)
|
|
11
|
+
// requires to keep two words around which are updated every time the
|
|
12
|
+
// reluctant doubling sequence is advanced. The original version in the
|
|
13
|
+
// literature uses a complex recursive function which computes the length of
|
|
14
|
+
// the next inactive sub-sequence every time (but is state-less).
|
|
15
|
+
//
|
|
16
|
+
// In our code we incorporate a base interval 'period' and only after period
|
|
17
|
+
// many calls to 'tick' times the current sequence value we update the
|
|
18
|
+
// reluctant doubling sequence value. The 'tick' call is decoupled from
|
|
19
|
+
// the activation signal of the sequence (the 'bool ()' operator) through
|
|
20
|
+
// 'trigger'. It is also possible to set an upper limit to the length of an
|
|
21
|
+
// inactive sub-sequence. If that limit is reached the whole reluctant
|
|
22
|
+
// doubling sequence starts over with the initial values.
|
|
23
|
+
|
|
24
|
+
class Reluctant {
|
|
25
|
+
|
|
26
|
+
uint64_t u, v, limit;
|
|
27
|
+
uint64_t period, countdown;
|
|
28
|
+
bool trigger, limited;
|
|
29
|
+
|
|
30
|
+
public:
|
|
31
|
+
Reluctant () : period (0), trigger (false) {}
|
|
32
|
+
|
|
33
|
+
void enable (int p, int64_t l) {
|
|
34
|
+
assert (p > 0);
|
|
35
|
+
u = v = 1;
|
|
36
|
+
period = countdown = p;
|
|
37
|
+
trigger = false;
|
|
38
|
+
if (l <= 0)
|
|
39
|
+
limited = false;
|
|
40
|
+
else
|
|
41
|
+
limited = true, limit = l;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
void disable () { period = 0, trigger = false; }
|
|
45
|
+
|
|
46
|
+
// Increments the count until the 'period' is hit. Then it performs the
|
|
47
|
+
// actual increment of reluctant doubling. This gives the common 'Luby'
|
|
48
|
+
// sequence with the specified base interval period. As soon the limit is
|
|
49
|
+
// reached (countdown goes to zero) we remember this event and then
|
|
50
|
+
// disable updating the reluctant sequence until the signal is delivered.
|
|
51
|
+
|
|
52
|
+
void tick () {
|
|
53
|
+
|
|
54
|
+
if (!period)
|
|
55
|
+
return; // disabled
|
|
56
|
+
if (trigger)
|
|
57
|
+
return; // already triggered
|
|
58
|
+
if (--countdown)
|
|
59
|
+
return; // not there yet
|
|
60
|
+
|
|
61
|
+
if ((u & -u) == v)
|
|
62
|
+
u = u + 1, v = 1;
|
|
63
|
+
else
|
|
64
|
+
v = 2 * v; // (DK)
|
|
65
|
+
|
|
66
|
+
if (limited && v >= limit)
|
|
67
|
+
u = v = 1;
|
|
68
|
+
countdown = v * period;
|
|
69
|
+
trigger = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
operator bool () {
|
|
73
|
+
if (!trigger)
|
|
74
|
+
return false;
|
|
75
|
+
trigger = false;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
} // namespace CaDiCaL
|
|
81
|
+
|
|
82
|
+
#endif
|