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.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +26 -0
  3. data/README.md +101 -0
  4. data/ext/cadical/cadical/LICENSE +28 -0
  5. data/ext/cadical/cadical/README.md +65 -0
  6. data/ext/cadical/cadical/VERSION +1 -0
  7. data/ext/cadical/cadical/src/analyze.cpp +1360 -0
  8. data/ext/cadical/cadical/src/arena.cpp +30 -0
  9. data/ext/cadical/cadical/src/arena.hpp +105 -0
  10. data/ext/cadical/cadical/src/assume.cpp +616 -0
  11. data/ext/cadical/cadical/src/averages.cpp +34 -0
  12. data/ext/cadical/cadical/src/averages.hpp +37 -0
  13. data/ext/cadical/cadical/src/backbone.cpp +631 -0
  14. data/ext/cadical/cadical/src/backtrack.cpp +177 -0
  15. data/ext/cadical/cadical/src/backward.cpp +231 -0
  16. data/ext/cadical/cadical/src/bins.cpp +22 -0
  17. data/ext/cadical/cadical/src/bins.hpp +22 -0
  18. data/ext/cadical/cadical/src/block.cpp +824 -0
  19. data/ext/cadical/cadical/src/block.hpp +37 -0
  20. data/ext/cadical/cadical/src/cadical.cpp +1026 -0
  21. data/ext/cadical/cadical/src/cadical.hpp +1419 -0
  22. data/ext/cadical/cadical/src/ccadical.cpp +208 -0
  23. data/ext/cadical/cadical/src/ccadical.h +74 -0
  24. data/ext/cadical/cadical/src/checker.cpp +649 -0
  25. data/ext/cadical/cadical/src/checker.hpp +173 -0
  26. data/ext/cadical/cadical/src/clause.cpp +689 -0
  27. data/ext/cadical/cadical/src/clause.hpp +190 -0
  28. data/ext/cadical/cadical/src/collect.cpp +545 -0
  29. data/ext/cadical/cadical/src/compact.cpp +550 -0
  30. data/ext/cadical/cadical/src/condition.cpp +940 -0
  31. data/ext/cadical/cadical/src/config.cpp +101 -0
  32. data/ext/cadical/cadical/src/config.hpp +20 -0
  33. data/ext/cadical/cadical/src/congruence.cpp +7880 -0
  34. data/ext/cadical/cadical/src/congruence.hpp +757 -0
  35. data/ext/cadical/cadical/src/constrain.cpp +64 -0
  36. data/ext/cadical/cadical/src/contract.cpp +27 -0
  37. data/ext/cadical/cadical/src/contract.hpp +139 -0
  38. data/ext/cadical/cadical/src/cover.cpp +704 -0
  39. data/ext/cadical/cadical/src/cover.hpp +34 -0
  40. data/ext/cadical/cadical/src/decide.cpp +347 -0
  41. data/ext/cadical/cadical/src/decompose.cpp +738 -0
  42. data/ext/cadical/cadical/src/decompose.hpp +23 -0
  43. data/ext/cadical/cadical/src/deduplicate.cpp +275 -0
  44. data/ext/cadical/cadical/src/definition.cpp +283 -0
  45. data/ext/cadical/cadical/src/delay.hpp +38 -0
  46. data/ext/cadical/cadical/src/drattracer.cpp +153 -0
  47. data/ext/cadical/cadical/src/drattracer.hpp +55 -0
  48. data/ext/cadical/cadical/src/elim.cpp +1171 -0
  49. data/ext/cadical/cadical/src/elim.hpp +53 -0
  50. data/ext/cadical/cadical/src/elimfast.cpp +570 -0
  51. data/ext/cadical/cadical/src/ema.cpp +95 -0
  52. data/ext/cadical/cadical/src/ema.hpp +68 -0
  53. data/ext/cadical/cadical/src/extend.cpp +289 -0
  54. data/ext/cadical/cadical/src/external.cpp +1034 -0
  55. data/ext/cadical/cadical/src/external.hpp +487 -0
  56. data/ext/cadical/cadical/src/external_propagate.cpp +1316 -0
  57. data/ext/cadical/cadical/src/factor.cpp +1011 -0
  58. data/ext/cadical/cadical/src/factor.hpp +54 -0
  59. data/ext/cadical/cadical/src/file.cpp +506 -0
  60. data/ext/cadical/cadical/src/file.hpp +210 -0
  61. data/ext/cadical/cadical/src/flags.cpp +135 -0
  62. data/ext/cadical/cadical/src/flags.hpp +93 -0
  63. data/ext/cadical/cadical/src/flip.cpp +269 -0
  64. data/ext/cadical/cadical/src/format.cpp +89 -0
  65. data/ext/cadical/cadical/src/format.hpp +36 -0
  66. data/ext/cadical/cadical/src/frattracer.cpp +277 -0
  67. data/ext/cadical/cadical/src/frattracer.hpp +67 -0
  68. data/ext/cadical/cadical/src/gates.cpp +766 -0
  69. data/ext/cadical/cadical/src/heap.hpp +212 -0
  70. data/ext/cadical/cadical/src/idruptracer.cpp +566 -0
  71. data/ext/cadical/cadical/src/idruptracer.hpp +112 -0
  72. data/ext/cadical/cadical/src/instantiate.cpp +365 -0
  73. data/ext/cadical/cadical/src/instantiate.hpp +45 -0
  74. data/ext/cadical/cadical/src/internal.cpp +1265 -0
  75. data/ext/cadical/cadical/src/internal.hpp +1941 -0
  76. data/ext/cadical/cadical/src/inttypes.hpp +34 -0
  77. data/ext/cadical/cadical/src/ipasir.cpp +47 -0
  78. data/ext/cadical/cadical/src/ipasir.h +37 -0
  79. data/ext/cadical/cadical/src/kitten.c +2599 -0
  80. data/ext/cadical/cadical/src/kitten.h +97 -0
  81. data/ext/cadical/cadical/src/level.hpp +33 -0
  82. data/ext/cadical/cadical/src/lidruptracer.cpp +657 -0
  83. data/ext/cadical/cadical/src/lidruptracer.hpp +122 -0
  84. data/ext/cadical/cadical/src/limit.cpp +146 -0
  85. data/ext/cadical/cadical/src/limit.hpp +168 -0
  86. data/ext/cadical/cadical/src/logging.cpp +214 -0
  87. data/ext/cadical/cadical/src/logging.hpp +98 -0
  88. data/ext/cadical/cadical/src/lookahead.cpp +520 -0
  89. data/ext/cadical/cadical/src/lratchecker.cpp +833 -0
  90. data/ext/cadical/cadical/src/lratchecker.hpp +168 -0
  91. data/ext/cadical/cadical/src/lrattracer.cpp +200 -0
  92. data/ext/cadical/cadical/src/lrattracer.hpp +61 -0
  93. data/ext/cadical/cadical/src/lucky.cpp +506 -0
  94. data/ext/cadical/cadical/src/message.cpp +218 -0
  95. data/ext/cadical/cadical/src/message.hpp +65 -0
  96. data/ext/cadical/cadical/src/minimize.cpp +224 -0
  97. data/ext/cadical/cadical/src/mobical.cpp +5588 -0
  98. data/ext/cadical/cadical/src/occs.cpp +52 -0
  99. data/ext/cadical/cadical/src/occs.hpp +36 -0
  100. data/ext/cadical/cadical/src/options.cpp +359 -0
  101. data/ext/cadical/cadical/src/options.hpp +442 -0
  102. data/ext/cadical/cadical/src/parse.cpp +471 -0
  103. data/ext/cadical/cadical/src/parse.hpp +75 -0
  104. data/ext/cadical/cadical/src/phases.cpp +56 -0
  105. data/ext/cadical/cadical/src/phases.hpp +19 -0
  106. data/ext/cadical/cadical/src/probe.cpp +990 -0
  107. data/ext/cadical/cadical/src/profile.cpp +107 -0
  108. data/ext/cadical/cadical/src/profile.hpp +283 -0
  109. data/ext/cadical/cadical/src/proof.cpp +691 -0
  110. data/ext/cadical/cadical/src/proof.hpp +125 -0
  111. data/ext/cadical/cadical/src/propagate.cpp +584 -0
  112. data/ext/cadical/cadical/src/queue.cpp +90 -0
  113. data/ext/cadical/cadical/src/queue.hpp +74 -0
  114. data/ext/cadical/cadical/src/radix.hpp +180 -0
  115. data/ext/cadical/cadical/src/random.cpp +207 -0
  116. data/ext/cadical/cadical/src/random.h +44 -0
  117. data/ext/cadical/cadical/src/random.hpp +98 -0
  118. data/ext/cadical/cadical/src/range.hpp +125 -0
  119. data/ext/cadical/cadical/src/reap.cpp +127 -0
  120. data/ext/cadical/cadical/src/reap.hpp +28 -0
  121. data/ext/cadical/cadical/src/reduce.cpp +278 -0
  122. data/ext/cadical/cadical/src/reluctant.hpp +82 -0
  123. data/ext/cadical/cadical/src/rephase.cpp +402 -0
  124. data/ext/cadical/cadical/src/report.cpp +313 -0
  125. data/ext/cadical/cadical/src/resources.cpp +160 -0
  126. data/ext/cadical/cadical/src/resources.hpp +16 -0
  127. data/ext/cadical/cadical/src/restart.cpp +178 -0
  128. data/ext/cadical/cadical/src/restore.cpp +267 -0
  129. data/ext/cadical/cadical/src/score.cpp +51 -0
  130. data/ext/cadical/cadical/src/score.hpp +16 -0
  131. data/ext/cadical/cadical/src/shrink.cpp +507 -0
  132. data/ext/cadical/cadical/src/signal.cpp +136 -0
  133. data/ext/cadical/cadical/src/signal.hpp +33 -0
  134. data/ext/cadical/cadical/src/solution.cpp +50 -0
  135. data/ext/cadical/cadical/src/solver.cpp +1871 -0
  136. data/ext/cadical/cadical/src/stable.cpp +31 -0
  137. data/ext/cadical/cadical/src/stack.h +110 -0
  138. data/ext/cadical/cadical/src/stats.cpp +920 -0
  139. data/ext/cadical/cadical/src/stats.hpp +418 -0
  140. data/ext/cadical/cadical/src/subsume.cpp +645 -0
  141. data/ext/cadical/cadical/src/sweep.cpp +1960 -0
  142. data/ext/cadical/cadical/src/sweep.hpp +61 -0
  143. data/ext/cadical/cadical/src/terminal.cpp +38 -0
  144. data/ext/cadical/cadical/src/terminal.hpp +96 -0
  145. data/ext/cadical/cadical/src/ternary.cpp +450 -0
  146. data/ext/cadical/cadical/src/testing.hpp +24 -0
  147. data/ext/cadical/cadical/src/tier.cpp +189 -0
  148. data/ext/cadical/cadical/src/tracer.hpp +186 -0
  149. data/ext/cadical/cadical/src/transred.cpp +253 -0
  150. data/ext/cadical/cadical/src/unstable.cpp +29 -0
  151. data/ext/cadical/cadical/src/util.cpp +129 -0
  152. data/ext/cadical/cadical/src/util.hpp +181 -0
  153. data/ext/cadical/cadical/src/var.cpp +39 -0
  154. data/ext/cadical/cadical/src/var.hpp +22 -0
  155. data/ext/cadical/cadical/src/veripbtracer.cpp +427 -0
  156. data/ext/cadical/cadical/src/veripbtracer.hpp +106 -0
  157. data/ext/cadical/cadical/src/version.cpp +107 -0
  158. data/ext/cadical/cadical/src/version.hpp +13 -0
  159. data/ext/cadical/cadical/src/vivify.cpp +1893 -0
  160. data/ext/cadical/cadical/src/vivify.hpp +50 -0
  161. data/ext/cadical/cadical/src/walk.cpp +1088 -0
  162. data/ext/cadical/cadical/src/walk.hpp +91 -0
  163. data/ext/cadical/cadical/src/walk_full_occs.cpp +966 -0
  164. data/ext/cadical/cadical/src/warmup.cpp +403 -0
  165. data/ext/cadical/cadical/src/watch.cpp +126 -0
  166. data/ext/cadical/cadical/src/watch.hpp +77 -0
  167. data/ext/cadical/cadical_ext.c +778 -0
  168. data/ext/cadical/extconf.rb +26 -0
  169. data/lib/cadical/version.rb +3 -0
  170. data/lib/cadical.rb +12 -0
  171. 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