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,90 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ // Slightly different than 'bump_variable' since the variable is not
6
+ // enqueued at all.
7
+
8
+ inline void Internal::init_enqueue (int idx) {
9
+ Link &l = links[idx];
10
+ if (opts.reverse) {
11
+ l.prev = 0;
12
+ if (queue.first) {
13
+ assert (!links[queue.first].prev);
14
+ links[queue.first].prev = idx;
15
+ btab[idx] = btab[queue.first] - 1;
16
+ } else {
17
+ assert (!queue.last);
18
+ queue.last = idx;
19
+ btab[idx] = 0;
20
+ }
21
+ assert (btab[idx] <= stats.bumped);
22
+ l.next = queue.first;
23
+ queue.first = idx;
24
+ if (!queue.unassigned)
25
+ update_queue_unassigned (queue.last);
26
+ } else {
27
+ l.next = 0;
28
+ if (queue.last) {
29
+ assert (!links[queue.last].next);
30
+ links[queue.last].next = idx;
31
+ } else {
32
+ assert (!queue.first);
33
+ queue.first = idx;
34
+ }
35
+ btab[idx] = ++stats.bumped;
36
+ l.prev = queue.last;
37
+ queue.last = idx;
38
+ update_queue_unassigned (queue.last);
39
+ }
40
+ }
41
+
42
+ // Initialize VMTF queue from current 'old_max_var + 1' to 'new_max_var'.
43
+ // This incorporates an initial variable order. We currently simply assume
44
+ // that variables with smaller index are more important. This is the same
45
+ // as in MiniSAT (implicitly) and also matches the 'scores' initialization.
46
+ //
47
+ void Internal::init_queue (int old_max_var, int new_max_var) {
48
+ LOG ("initializing VMTF queue from %d to %d", old_max_var + 1,
49
+ new_max_var);
50
+ assert (old_max_var < new_max_var);
51
+ // New variables can be created that can invoke enlarge anytime (eg via
52
+ // calls during ipasir-up call-backs), thus assuming (!level) is not
53
+ // correct
54
+ for (int idx = old_max_var; idx < new_max_var; idx++)
55
+ init_enqueue (idx + 1);
56
+ }
57
+
58
+ // Shuffle the VMTF queue.
59
+
60
+ void Internal::shuffle_queue () {
61
+ if (!opts.shuffle)
62
+ return;
63
+ if (!opts.shufflequeue)
64
+ return;
65
+ stats.shuffled++;
66
+ LOG ("shuffling queue");
67
+ vector<int> shuffle;
68
+ if (opts.shufflerandom) {
69
+ for (int idx = max_var; idx; idx--)
70
+ shuffle.push_back (idx);
71
+ Random random (opts.seed); // global seed
72
+ random += stats.shuffled; // different every time
73
+ for (int i = 0; i <= max_var - 2; i++) {
74
+ const int j = random.pick_int (i, max_var - 1);
75
+ swap (shuffle[i], shuffle[j]);
76
+ }
77
+ } else {
78
+ for (int idx = queue.last; idx; idx = links[idx].prev)
79
+ shuffle.push_back (idx);
80
+ }
81
+ queue.first = queue.last = 0;
82
+ for (const int idx : shuffle)
83
+ queue.enqueue (links, idx);
84
+ int64_t bumped = queue.bumped;
85
+ for (int idx = queue.last; idx; idx = links[idx].prev)
86
+ btab[idx] = bumped--;
87
+ queue.unassigned = queue.last;
88
+ }
89
+
90
+ } // namespace CaDiCaL
@@ -0,0 +1,74 @@
1
+ #ifndef _queue_hpp_INCLUDED
2
+ #define _queue_hpp_INCLUDED
3
+
4
+ #include <vector>
5
+
6
+ namespace CaDiCaL {
7
+
8
+ // Links for double linked decision queue.
9
+
10
+ struct Link {
11
+
12
+ int prev, next; // variable indices
13
+
14
+ // initialized explicitly in 'init_queue'
15
+ };
16
+
17
+ typedef std::vector<Link> Links;
18
+
19
+ // Variable move to front (VMTF) decision queue ordered by 'bumped'. See
20
+ // our SAT'15 paper for an explanation on how this works.
21
+
22
+ struct Queue {
23
+
24
+ // We use integers instead of variable pointers. This is more compact and
25
+ // also avoids issues due to moving the variable table during 'resize'.
26
+
27
+ int first, last; // anchors (head/tail) for doubly linked list
28
+ int unassigned; // all variables after this one are assigned
29
+ int64_t bumped; // see 'Internal.update_queue_unassigned'
30
+
31
+ Queue () : first (0), last (0), unassigned (0), bumped (0) {}
32
+
33
+ // We explicitly provide the mapping of integer indices to links to the
34
+ // following two (inlined) functions. This avoids including
35
+ // 'internal.hpp' and breaks a cyclic dependency, so we can keep their
36
+ // code here in this header file. Otherwise they are just ordinary doubly
37
+ // linked list 'dequeue' and 'enqueue' operations.
38
+
39
+ inline void dequeue (Links &links, int idx) {
40
+ Link &l = links[idx];
41
+ if (l.prev)
42
+ links[l.prev].next = l.next;
43
+ else
44
+ first = l.next;
45
+ if (l.next)
46
+ links[l.next].prev = l.prev;
47
+ else
48
+ last = l.prev;
49
+ }
50
+
51
+ inline void enqueue (Links &links, int idx) {
52
+ Link &l = links[idx];
53
+ if ((l.prev = last))
54
+ links[last].next = idx;
55
+ else
56
+ first = idx;
57
+ last = idx;
58
+ l.next = 0;
59
+ }
60
+
61
+ inline void bury (Links &links, int idx) {
62
+ Link &l = links[idx];
63
+ if ((l.next = first))
64
+ links[first].prev = idx;
65
+ else
66
+ last = idx;
67
+ first = idx;
68
+ l.prev = 0;
69
+ }
70
+ };
71
+
72
+ } // namespace CaDiCaL
73
+
74
+ #endif
@@ -0,0 +1,180 @@
1
+ #ifndef _radix_hpp_INCLUDED
2
+ #define _radix_hpp_INCLUDED
3
+
4
+ #include <cassert>
5
+ #include <cstring>
6
+ #include <iterator>
7
+ #include <vector>
8
+
9
+ namespace CaDiCaL {
10
+
11
+ using namespace std;
12
+
13
+ // This provides an implementation of a generic radix sort algorithm. The
14
+ // reason for having it is that for certain benchmarks and certain parts of
15
+ // CaDiCaL where sorting is used, the standard sorting algorithm 'sort'
16
+ // turned out to be a hot-spot. Up to 30% of the total running time was for
17
+ // instance used for some benchmarks in sorting variables during bumping
18
+ // to make sure to bump them in 'enqueued' order.
19
+ //
20
+ // Further, in most cases, where we need to sort something, sorting is
21
+ // actually performed on positive numbers (such as the 'enqueued' time stamp
22
+ // during bumping), which allows to use radix sort or variants. At least
23
+ // starting with medium sized arrays to be sorted (say above 1000 elements,
24
+ // but see discussion on 'MSORT' below), radix sort can be way faster.
25
+ //
26
+ // Finally it is stable, which is actually preferred most of the time too.
27
+ //
28
+ // This template algorithm 'rsort' takes as first template parameter the
29
+ // iterator class similar to the standard 'sort' algorithm template, but
30
+ // then as second parameter a function class (similar to the second 'less
31
+ // than' parameter of 'sort') which can obtain a 'rank' from each element,
32
+ // on which they are compared. The 'rank' should be able to turn an element
33
+ // into a number. The type of these ranks is determined automatically but
34
+ // should be 'unsigned'.
35
+
36
+ struct pointer_rank {
37
+ typedef size_t Type;
38
+ Type operator() (void *ptr) { return (size_t) ptr; }
39
+ };
40
+
41
+ template <class I, class Rank> void rsort (I first, I last, Rank rank) {
42
+ typedef typename iterator_traits<I>::value_type T;
43
+ typedef typename Rank::Type R;
44
+
45
+ assert (first <= last);
46
+ const size_t n = last - first;
47
+ if (n <= 1)
48
+ return;
49
+
50
+ const size_t l = 8; // Radix 8, thus byte-wise.
51
+ const size_t w = (1 << l); // So many buckets.
52
+
53
+ const unsigned mask = w - 1; // Fast mod 'w'.
54
+
55
+ // Uncomment the following define for large values of 'w' in order to keep
56
+ // the large bucket array 'count' on the heap instead of the stack.
57
+ //
58
+ // #define CADICAL_RADIX_BUCKETS_ON_THE_HEAP
59
+ //
60
+ #ifdef CADICAL_RADIX_BUCKETS_ON_THE_HEAP
61
+ size_t *count = new size_t[w]; // Put buckets on the heap.
62
+ #else
63
+ size_t count[w]; // Put buckets on the stack.
64
+ #endif
65
+
66
+ I a = first, b = last, c = a;
67
+ bool initialized = false;
68
+ std::vector<T> v;
69
+
70
+ R upper = 0, lower = ~upper;
71
+ R shifted = mask;
72
+ bool bounded = false;
73
+
74
+ R masked_lower = 0, masked_upper = mask;
75
+
76
+ for (size_t i = 0; i < 8 * sizeof (rank (*first));
77
+ i += l, shifted <<= l) {
78
+
79
+ if (bounded && (lower & shifted) == (upper & shifted))
80
+ continue;
81
+
82
+ memset (count + masked_lower, 0,
83
+ (masked_upper - masked_lower + 1) * sizeof *count);
84
+
85
+ const I end = c + n;
86
+ bool sorted = true;
87
+ R last = 0;
88
+
89
+ for (I p = c; p != end; p++) {
90
+ const auto r = rank (*p);
91
+ if (!bounded)
92
+ lower &= r, upper |= r;
93
+ const auto s = r >> i;
94
+ const auto m = s & mask;
95
+ if (sorted && last > m)
96
+ sorted = false;
97
+ else
98
+ last = m;
99
+ count[m]++;
100
+ }
101
+
102
+ masked_lower = (lower >> i) & mask;
103
+ masked_upper = (upper >> i) & mask;
104
+
105
+ if (!bounded) {
106
+ bounded = true;
107
+ if ((lower & shifted) == (upper & shifted))
108
+ continue;
109
+ }
110
+
111
+ if (sorted)
112
+ continue;
113
+
114
+ size_t pos = 0;
115
+ for (R j = masked_lower; j <= masked_upper; j++) {
116
+ const size_t delta = count[j];
117
+ count[j] = pos;
118
+ pos += delta;
119
+ }
120
+
121
+ if (!initialized) {
122
+ assert (&*c == &*a); // MS VC++
123
+ v.resize (n);
124
+ b = v.begin ();
125
+ initialized = true;
126
+ }
127
+
128
+ I d = (&*c == &*a) ? b : a; // MS VC++
129
+
130
+ for (I p = c; p != end; p++) {
131
+ const auto r = rank (*p);
132
+ const auto s = r >> i;
133
+ const auto m = s & mask;
134
+ d[count[m]++] = *p;
135
+ }
136
+ c = d;
137
+ }
138
+
139
+ if (c == b) {
140
+ for (size_t i = 0; i < n; i++)
141
+ a[i] = b[i];
142
+ }
143
+
144
+ #ifdef CADICAL_RADIX_BUCKETS_ON_THE_HEAP
145
+ delete[] count;
146
+ #endif
147
+
148
+ #ifndef NDEBUG
149
+ for (I p = first; p + 1 != last; p++)
150
+ assert (rank (p[0]) <= rank (p[1]));
151
+ #endif
152
+ }
153
+
154
+ // It turns out that for small number of elements (like '100') and in
155
+ // particular for large value ranges the standard sorting function is
156
+ // considerably faster than our radix sort (like 2.5x). This negative effect
157
+ // vanishes at around 800 elements (sorting integers) and thus we provide a
158
+ // function 'MSORT' which selects between standard sort and radix sort based
159
+ // on the number of elements. However we failed to put this into proper C++
160
+ // style template code and thus have to use a macro instead. We also do not
161
+ // use it everywhere instead of 'rsort' since it requires a fourth
162
+ // parameter, which is awkward, particular in those situation where we
163
+ // expect large arrays to be sorted anyhow (such as during sorting the
164
+ // clauses in an arena or the probes during probing). The first argument
165
+ // is the limit up to which we use the standard sort. Above the limit we
166
+ // use radix sort. As usual we do not want to hard code it here (default
167
+ // is '800') in order to make fuzzing and delta debugging more effective.
168
+
169
+ #define MSORT(LIMIT, FIRST, LAST, RANK, LESS) \
170
+ do { \
171
+ const size_t N = LAST - FIRST; \
172
+ if (N <= (size_t) (LIMIT)) \
173
+ sort (FIRST, LAST, LESS); \
174
+ else \
175
+ rsort (FIRST, LAST, RANK); \
176
+ } while (0)
177
+
178
+ } // namespace CaDiCaL
179
+
180
+ #endif
@@ -0,0 +1,207 @@
1
+ #include "internal.hpp"
2
+
3
+ /*------------------------------------------------------------------------*/
4
+
5
+ // Our random number generator is seeded by default (i.e., in the default
6
+ // constructor) with random seeds, which should be unique across machines,
7
+ // processes and time. This makes this code below rather operating system
8
+ // dependent. We also use in essence defensive programming, overlaying
9
+ // several methods to get randomness since in the past we were bitten a
10
+ // couple of times (and got the same seeds). Having several methods makes
11
+ // it also simpler to port randomly initializing seeds to different
12
+ // operating systems (even though currently it is only tested on Linux).
13
+ // This functionality is only used in the 'Mobical' model based tester at
14
+ // this point, since the main solver explicitly sets a random seed ('0' by
15
+ // default in 'options.hpp') and also currently only uses this seed in the
16
+ // local search procedure explicitly without using the default constructor.
17
+ // It is crucial for 'Mobical' to make sure that concurrent runs are really
18
+ // independent.
19
+
20
+ /*------------------------------------------------------------------------*/
21
+
22
+ // Uncomment the following definition to force printing the computed hash
23
+ // values for individual machine and process properties. This is only needed
24
+ // for testing, porting and debugging different ports of this seeding and
25
+ // hashing functions (uncomment and run 'mobical' for instance).
26
+
27
+ /*
28
+ #define DO_PRINT_HASH
29
+ */
30
+
31
+ #ifdef DO_PRINT_HASH
32
+ #define PRINT_HASH(H) \
33
+ do { \
34
+ printf ("c PRINT_HASH %32s () = %020" PRIu64 "\n", __func__, H); \
35
+ fflush (stdout); \
36
+ } while (0)
37
+ #else
38
+ #define PRINT_HASH(...) \
39
+ do { \
40
+ } while (0)
41
+ #endif
42
+
43
+ /*------------------------------------------------------------------------*/
44
+
45
+ // This is Linux specific but if '/var/lib/dbus/machine-id' does not exist
46
+ // does not have any effect. TODO: add a similar machine identity hashing
47
+ // function for other operating systems (Windows and macOS).
48
+
49
+ namespace CaDiCaL {
50
+
51
+ static uint64_t hash_machine_identifier () {
52
+ FILE *file = fopen ("/var/lib/dbus/machine-id", "r");
53
+ uint64_t res = 0;
54
+ if (file) {
55
+ char buffer[128];
56
+ memset (buffer, 0, sizeof buffer);
57
+ size_t bytes = fread (buffer, 1, sizeof buffer - 1, file);
58
+ assert (bytes);
59
+ fclose (file);
60
+ if (bytes && bytes < sizeof buffer) {
61
+ buffer[bytes] = 0;
62
+ res = hash_string (buffer);
63
+ }
64
+ }
65
+ PRINT_HASH (res);
66
+ return res;
67
+ }
68
+
69
+ } // namespace CaDiCaL
70
+
71
+ /*------------------------------------------------------------------------*/
72
+
73
+ // On our Linux cluster where we used an NFS mounted root disk the
74
+ // 'machine-id' above (even on a locally mounted '/var' disk on each node)
75
+ // was copied from '/etc/machine-id' which was shared among all nodes
76
+ // (before figuring this out and fixing it). Thus the main idea of getting
77
+ // different hash values through this machine identifier machines did not
78
+ // work. As an additional measure to increase the possibility to get
79
+ // different seeds we are now also using network addresses (explicitly).
80
+
81
+ #ifndef _WIN32
82
+
83
+ extern "C" {
84
+ #include <ifaddrs.h>
85
+ #include <netdb.h>
86
+ #include <netinet/in.h>
87
+ #include <stdio.h>
88
+ #include <stdlib.h>
89
+ #include <sys/socket.h>
90
+ }
91
+
92
+ #endif
93
+
94
+ namespace CaDiCaL {
95
+
96
+ static uint64_t hash_network_addresses () {
97
+ uint64_t res = 0;
98
+
99
+ // We still need to properly port this to Windows, but since accessing the
100
+ // IP address is only required for better randomization during testing
101
+ // (running 'mobical' on a cluster for instance) it is not crucial unless
102
+ // you really need to run 'mobical' on a Windows cluster where each node
103
+ // has identical IP addresses.
104
+
105
+ #ifndef _WIN32
106
+ struct ifaddrs *addrs;
107
+ if (!getifaddrs (&addrs)) {
108
+ for (struct ifaddrs *addr = addrs; addr; addr = addr->ifa_next) {
109
+ if (!addr->ifa_addr)
110
+ continue;
111
+ const int family = addr->ifa_addr->sa_family;
112
+ if (family == AF_INET || family == AF_INET6) {
113
+ const int size = (family == AF_INET) ? sizeof (struct sockaddr_in)
114
+ : sizeof (struct sockaddr_in6);
115
+ char buffer[128];
116
+ if (!getnameinfo (addr->ifa_addr, size, buffer, sizeof buffer, 0, 0,
117
+ NI_NUMERICHOST)) {
118
+ uint64_t tmp = hash_string (buffer);
119
+ #ifdef DO_PRINT_HASH
120
+ printf ("c PRINT_HASH %35s = %020" PRIu64 "\n", buffer, tmp);
121
+ fflush (stdout);
122
+ #endif
123
+ res ^= tmp;
124
+ res *= 10000000000000000051ul;
125
+ }
126
+ }
127
+ }
128
+ freeifaddrs (addrs);
129
+ }
130
+ #endif
131
+
132
+ PRINT_HASH (res);
133
+ return res;
134
+ }
135
+
136
+ } // namespace CaDiCaL
137
+
138
+ /*------------------------------------------------------------------------*/
139
+
140
+ // Hash the current wall-clock time in seconds.
141
+
142
+ extern "C" {
143
+ #include <time.h>
144
+ }
145
+
146
+ namespace CaDiCaL {
147
+
148
+ static uint64_t hash_time () {
149
+ uint64_t res = ::time (0);
150
+ PRINT_HASH (res);
151
+ return res;
152
+ }
153
+
154
+ } // namespace CaDiCaL
155
+
156
+ /*------------------------------------------------------------------------*/
157
+
158
+ // Hash the process identified.
159
+
160
+ extern "C" {
161
+ #include <sys/types.h>
162
+ #include <unistd.h>
163
+ }
164
+
165
+ namespace CaDiCaL {
166
+
167
+ static uint64_t hash_process () {
168
+ uint64_t res = getpid ();
169
+ PRINT_HASH (res);
170
+ return res;
171
+ }
172
+
173
+ } // namespace CaDiCaL
174
+
175
+ /*------------------------------------------------------------------------*/
176
+
177
+ // Hash the current number of clock cycles.
178
+
179
+ #include <ctime>
180
+
181
+ namespace CaDiCaL {
182
+
183
+ static uint64_t hash_clock_cycles () {
184
+ uint64_t res = std::clock ();
185
+ PRINT_HASH (res);
186
+ return res;
187
+ }
188
+
189
+ } // namespace CaDiCaL
190
+
191
+ /*------------------------------------------------------------------------*/
192
+
193
+ namespace CaDiCaL {
194
+
195
+ Random::Random () : state (1) {
196
+ add (hash_machine_identifier ());
197
+ add (hash_network_addresses ());
198
+ add (hash_clock_cycles ());
199
+ add (hash_process ());
200
+ add (hash_time ());
201
+ #ifdef DO_PRINT_HASH
202
+ printf ("c PRINT_HASH %32s = %020" PRIu64 "\n", "combined", state);
203
+ fflush (stdout);
204
+ #endif
205
+ }
206
+
207
+ } // namespace CaDiCaL
@@ -0,0 +1,44 @@
1
+ #ifndef _random_h_INCLUDED
2
+ #define _random_h_INCLUDED
3
+
4
+ #include <assert.h>
5
+ #include <stdbool.h>
6
+ #include <stdint.h>
7
+
8
+ typedef uint64_t generator;
9
+
10
+ static inline uint64_t kissat_next_random64 (generator *rng) {
11
+ *rng *= 6364136223846793005ul;
12
+ *rng += 1442695040888963407ul;
13
+ return *rng;
14
+ }
15
+
16
+ static inline unsigned kissat_next_random32 (generator *rng) {
17
+ return kissat_next_random64 (rng) >> 32;
18
+ }
19
+
20
+ static inline unsigned kissat_pick_random (generator *rng, unsigned l,
21
+ unsigned r) {
22
+ assert (l <= r);
23
+ if (l == r)
24
+ return l;
25
+ const unsigned delta = r - l;
26
+ const unsigned tmp = kissat_next_random32 (rng);
27
+ const double fraction = tmp / 4294967296.0;
28
+ assert (0 <= fraction), assert (fraction < 1);
29
+ const unsigned scaled = delta * fraction;
30
+ assert (scaled < delta);
31
+ const unsigned res = l + scaled;
32
+ assert (l <= res), assert (res < r);
33
+ return res;
34
+ }
35
+
36
+ static inline bool kissat_pick_bool (generator *rng) {
37
+ return kissat_pick_random (rng, 0, 2);
38
+ }
39
+
40
+ static inline double kissat_pick_double (generator *rng) {
41
+ return kissat_next_random32 (rng) / 4294967296.0;
42
+ }
43
+
44
+ #endif
@@ -0,0 +1,98 @@
1
+ #ifndef _random_hpp_INCLUDED
2
+ #define _random_hpp_INCLUDED
3
+
4
+ #include <cstdint>
5
+
6
+ // Random number generator.
7
+
8
+ namespace CaDiCaL {
9
+
10
+ class Random {
11
+
12
+ uint64_t state;
13
+
14
+ void add (uint64_t a) {
15
+ if (!(state += a))
16
+ state = 1;
17
+ next ();
18
+ }
19
+
20
+ public:
21
+ // Without argument use a machine, process and time dependent seed.
22
+ //
23
+ Random ();
24
+
25
+ Random (uint64_t seed) : state (seed) {}
26
+ void operator= (uint64_t seed) { state = seed; }
27
+ Random (const Random &other) : state (other.seed ()) {}
28
+
29
+ void operator+= (uint64_t a) { add (a); }
30
+ uint64_t seed () const { return state; }
31
+
32
+ uint64_t next () {
33
+ state *= 6364136223846793005ul;
34
+ state += 1442695040888963407ul;
35
+ assert (state);
36
+ return state;
37
+ }
38
+
39
+ uint32_t generate () {
40
+ next ();
41
+ return state >> 32;
42
+ }
43
+ int generate_int () { return (int) generate (); }
44
+ bool generate_bool () { return generate () < 2147483648u; }
45
+
46
+ // Generate 'double' value in the range '[0,1]' excluding '1'.
47
+ //
48
+ double generate_double () { return generate () / 4294967295.0; }
49
+
50
+ // Generate 'int' value in the range '[l,r]'.
51
+ //
52
+ int pick_int (int l, int r) {
53
+ assert (l <= r);
54
+ const unsigned delta = 1 + r - (unsigned) l;
55
+ unsigned tmp = generate (), scaled;
56
+ if (delta) {
57
+ const double fraction = tmp / 4294967296.0;
58
+ scaled = delta * fraction;
59
+ } else
60
+ scaled = tmp;
61
+ const int res = scaled + l;
62
+ assert (l <= res);
63
+ assert (res <= r);
64
+ return res;
65
+ }
66
+
67
+ int pick_log (int l, int r) {
68
+ assert (l <= r);
69
+ const unsigned delta = 1 + r - (unsigned) l;
70
+ int log_delta = delta ? 0 : 32;
71
+ while (log_delta < 32 && (1u << log_delta) < delta)
72
+ log_delta++;
73
+ const int log_res = pick_int (0, log_delta);
74
+ unsigned tmp = generate ();
75
+ if (log_res < 32)
76
+ tmp &= (1u << log_res) - 1;
77
+ if (delta)
78
+ tmp %= delta;
79
+ const int res = l + tmp;
80
+ assert (l <= res), assert (res <= r);
81
+ return res;
82
+ }
83
+
84
+ // Generate 'double' value in the range '[l,r]'.
85
+ //
86
+ double pick_double (double l, double r) {
87
+ assert (l <= r);
88
+ double res = (r - l) * generate_double ();
89
+ res += l;
90
+ assert (l <= res);
91
+ assert (res <= r);
92
+ return res;
93
+ }
94
+ };
95
+
96
+ } // namespace CaDiCaL
97
+
98
+ #endif