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,160 @@
1
+ #include "internal.hpp"
2
+
3
+ /*------------------------------------------------------------------------*/
4
+
5
+ // This is operating system specific code. We mostly develop on Linux and
6
+ // there it should be fine and mostly works out-of-the-box on MacOS too but
7
+ // Windows needs special treatment (as probably other operating systems
8
+ // too).
9
+
10
+ extern "C" {
11
+
12
+ #ifdef _WIN32
13
+
14
+ #ifndef _WIN32_WINNT
15
+ #define _WIN32_WINNT 0x0600
16
+ #endif
17
+
18
+ // Clang-format would reorder the includes which breaks the Windows code
19
+ // as it expects 'windows.h' to be included first. So disable it here.
20
+
21
+ // clang-format off
22
+
23
+ #include <windows.h>
24
+ #include <psapi.h>
25
+
26
+ // clang-format on
27
+
28
+ #else
29
+
30
+ #include <sys/resource.h>
31
+ #include <sys/time.h>
32
+ #include <sys/types.h>
33
+ #include <unistd.h>
34
+
35
+ #endif
36
+
37
+ #include <string.h>
38
+ }
39
+
40
+ namespace CaDiCaL {
41
+
42
+ /*------------------------------------------------------------------------*/
43
+
44
+ #ifdef _WIN32
45
+
46
+ double absolute_real_time () {
47
+ FILETIME f;
48
+ GetSystemTimeAsFileTime (&f);
49
+ ULARGE_INTEGER t;
50
+ t.LowPart = f.dwLowDateTime;
51
+ t.HighPart = f.dwHighDateTime;
52
+ double res = (__int64) t.QuadPart;
53
+ res *= 1e-7;
54
+ return res;
55
+ }
56
+
57
+ double absolute_process_time () {
58
+ double res = 0;
59
+ FILETIME fc, fe, fu, fs;
60
+ if (GetProcessTimes (GetCurrentProcess (), &fc, &fe, &fu, &fs)) {
61
+ ULARGE_INTEGER u, s;
62
+ u.LowPart = fu.dwLowDateTime;
63
+ u.HighPart = fu.dwHighDateTime;
64
+ s.LowPart = fs.dwLowDateTime;
65
+ s.HighPart = fs.dwHighDateTime;
66
+ res = (__int64) u.QuadPart + (__int64) s.QuadPart;
67
+ res *= 1e-7;
68
+ }
69
+ return res;
70
+ }
71
+
72
+ #else
73
+
74
+ double absolute_real_time () {
75
+ struct timeval tv;
76
+ if (gettimeofday (&tv, 0))
77
+ return 0;
78
+ return 1e-6 * tv.tv_usec + tv.tv_sec;
79
+ }
80
+
81
+ // We use 'getrusage' for 'process_time' and 'maximum_resident_set_size'
82
+ // which is pretty standard on Unix but probably not available on Windows
83
+ // etc. For different variants of Unix not all fields are meaningful.
84
+
85
+ double absolute_process_time () {
86
+ double res;
87
+ struct rusage u;
88
+ if (getrusage (RUSAGE_SELF, &u))
89
+ return 0;
90
+ res = u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec; // user time
91
+ res += u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec; // + system time
92
+ return res;
93
+ }
94
+
95
+ #endif
96
+
97
+ double Internal::real_time () const {
98
+ return absolute_real_time () - stats.time.real;
99
+ }
100
+
101
+ double Internal::process_time () const {
102
+ return absolute_process_time () - stats.time.process;
103
+ }
104
+
105
+ /*------------------------------------------------------------------------*/
106
+
107
+ #ifdef _WIN32
108
+
109
+ uint64_t current_resident_set_size () {
110
+ PROCESS_MEMORY_COUNTERS pmc;
111
+ if (GetProcessMemoryInfo (GetCurrentProcess (), &pmc, sizeof (pmc))) {
112
+ return pmc.WorkingSetSize;
113
+ } else
114
+ return 0;
115
+ }
116
+
117
+ uint64_t maximum_resident_set_size () {
118
+ PROCESS_MEMORY_COUNTERS pmc;
119
+ if (GetProcessMemoryInfo (GetCurrentProcess (), &pmc, sizeof (pmc))) {
120
+ return pmc.PeakWorkingSetSize;
121
+ } else
122
+ return 0;
123
+ }
124
+
125
+ #else
126
+
127
+ // This seems to work on Linux (man page says since Linux 2.6.32).
128
+
129
+ uint64_t maximum_resident_set_size () {
130
+ struct rusage u;
131
+ if (getrusage (RUSAGE_SELF, &u))
132
+ return 0;
133
+ return ((uint64_t) u.ru_maxrss) << 10;
134
+ }
135
+
136
+ // Unfortunately 'getrusage' on Linux does not support current resident set
137
+ // size (the field 'ru_ixrss' is there but according to the man page
138
+ // 'unused'). Thus we fall back to use the '/proc' file system instead. So
139
+ // this is not portable at all and needs to be replaced on other systems
140
+ // The code would still compile though (assuming 'sysconf' and
141
+ // '_SC_PAGESIZE' are available).
142
+
143
+ uint64_t current_resident_set_size () {
144
+ char path[64];
145
+ snprintf (path, sizeof path, "/proc/%" PRId64 "/statm",
146
+ (int64_t) getpid ());
147
+ FILE *file = fopen (path, "r");
148
+ if (!file)
149
+ return 0;
150
+ uint64_t dummy, rss;
151
+ int scanned = fscanf (file, "%" PRIu64 " %" PRIu64 "", &dummy, &rss);
152
+ fclose (file);
153
+ return scanned == 2 ? rss * sysconf (_SC_PAGESIZE) : 0;
154
+ }
155
+
156
+ #endif
157
+
158
+ /*------------------------------------------------------------------------*/
159
+
160
+ } // namespace CaDiCaL
@@ -0,0 +1,16 @@
1
+ #ifndef _resources_hpp_INCLUDED
2
+ #define _resources_hpp_INCLUDED
3
+
4
+ #include <cstdint>
5
+
6
+ namespace CaDiCaL {
7
+
8
+ double absolute_real_time ();
9
+ double absolute_process_time ();
10
+
11
+ uint64_t maximum_resident_set_size ();
12
+ uint64_t current_resident_set_size ();
13
+
14
+ } // namespace CaDiCaL
15
+
16
+ #endif // ifndef _resources_hpp_INCLUDED
@@ -0,0 +1,178 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ // As observed by Chanseok Oh and implemented in MapleSAT solvers too,
6
+ // various mostly satisfiable instances benefit from long quiet phases
7
+ // with less or almost no restarts. We implement this idea by prohibiting
8
+ // the Glucose style restart scheme in a geometric fashion, which is very
9
+ // similar to how originally restarts were scheduled in MiniSAT and earlier
10
+ // solvers. We start with say 1e3 = 1000 (opts.stabilizeinit) conflicts of
11
+ // Glucose restarts. Then in a "stabilizing" phase we disable these
12
+ // until 1e4 = 2000 conflicts (if 'opts.stabilizefactor' is '200' percent)
13
+ // have passed. After that we switch back to regular Glucose style restarts
14
+ // until again 2 times more conflicts than the previous limit are reached.
15
+ // Actually, in the latest version we still restarts during stabilization
16
+ // but only in a reluctant doubling scheme with a rather high interval.
17
+
18
+ bool Internal::stabilizing () {
19
+ if (!opts.stabilize)
20
+ return false;
21
+ if (stable && opts.stabilizeonly)
22
+ return true;
23
+ if (!inc.stabilize) {
24
+ assert (!stable);
25
+ if (stats.conflicts <= lim.stabilize)
26
+ return false;
27
+ } else if (stats.ticks.search[stable] <= lim.stabilize)
28
+ return stable;
29
+ report (stable ? ']' : '}');
30
+ if (stable)
31
+ STOP (stable);
32
+ else
33
+ STOP (unstable);
34
+
35
+ assert (last.stabilize.ticks >= 0);
36
+ assert (last.stabilize.conflicts >= 0 &&
37
+ last.stabilize.conflicts <= stats.conflicts);
38
+ assert (last.stabilize.ticks <= stats.ticks.search[stable]);
39
+ const int64_t delta_ticks =
40
+ stats.ticks.search[stable] - last.stabilize.ticks;
41
+ #ifndef QUIET
42
+ const int64_t delta_conflicts =
43
+ stats.conflicts - last.stabilize.conflicts;
44
+ const char *current_mode = stable ? "stable" : "unstable";
45
+ const char *next_mode = stable ? "unstable" : "stable";
46
+ #endif
47
+ PHASE ("stabilizing", stats.stabphases,
48
+ "reached %s stabilization limit %" PRId64 " after %" PRId64
49
+ " conflicts and %" PRId64 " ticks at %" PRId64
50
+ " conflicts and %" PRId64 " ticks",
51
+ current_mode, lim.stabilize, delta_conflicts, delta_ticks,
52
+ stats.conflicts, stats.ticks.search[stable]);
53
+ if (!inc.stabilize)
54
+ inc.stabilize = delta_ticks;
55
+ if (!inc.stabilize) // rare occurence in incremental calls requiring no
56
+ // ticks
57
+ inc.stabilize = 1;
58
+
59
+ int64_t next_delta_ticks = inc.stabilize;
60
+ int64_t stabphases = stats.stabphases + 1;
61
+ next_delta_ticks *= stabphases * stabphases;
62
+
63
+ const bool next_stable = !stable;
64
+ lim.stabilize = stats.ticks.search[next_stable] + next_delta_ticks;
65
+ last.stabilize.ticks = stats.ticks.search[next_stable];
66
+ if (lim.stabilize <= stats.ticks.search[next_stable])
67
+ lim.stabilize = stats.ticks.search[next_stable] + 1;
68
+ PHASE ("stabilizing", stats.stabphases,
69
+ "next %s stabilization limit %" PRId64
70
+ " at ticks interval %" PRId64,
71
+ next_mode, lim.stabilize, next_delta_ticks);
72
+
73
+ stable = !stable; // Switch!!!!!
74
+
75
+ if (stable)
76
+ stats.stabphases++;
77
+
78
+ swap_averages ();
79
+ report (stable ? '[' : '{');
80
+ if (stable)
81
+ START (stable);
82
+ else
83
+ START (unstable);
84
+ return stable;
85
+ }
86
+
87
+ // Restarts are scheduled by a variant of the Glucose scheme as presented
88
+ // in our POS'15 paper using exponential moving averages. There is a slow
89
+ // moving average of the average recent glucose level of learned clauses
90
+ // as well as a fast moving average of those glues. If the end of a base
91
+ // restart conflict interval has passed and the fast moving average is
92
+ // above a certain margin over the slow moving average then we restart.
93
+
94
+ bool Internal::restarting () {
95
+ if (!opts.restart)
96
+ return false;
97
+ if ((size_t) level < assumptions.size () + 2)
98
+ return false;
99
+ if (stabilizing () && opts.reluctant)
100
+ return reluctant;
101
+ if (stats.conflicts <= lim.restart)
102
+ return false;
103
+ double f = averages.current.glue.fast;
104
+ int p = stable ? opts.restartmarginstable : opts.restartmarginfocused;
105
+ double m = (100.0 + p) / 100.0;
106
+ double s = averages.current.glue.slow;
107
+ double l = m * s;
108
+
109
+ #ifndef QUIET
110
+ char c = l > f ? '>' : l < f ? '<' : '=';
111
+ VERBOSE (3,
112
+ "restart glue limit "
113
+ "%g = %.2f * %g (slow glue) %c %g (fast glue)",
114
+ l, m, s, c, f);
115
+ #endif
116
+
117
+ return l <= f;
118
+ }
119
+
120
+ // This is Marijn's reuse trail idea. Instead of always backtracking to
121
+ // the top we figure out which decisions will be made again anyhow and
122
+ // only backtrack to the level of the last such decision or to the top if
123
+ // no such decision exists top (in which case we do not reuse any level).
124
+
125
+ int Internal::reuse_trail () {
126
+ const int trivial_decisions =
127
+ assumptions.size ()
128
+ // Plus 1 if the constraint is satisfied via implications of
129
+ // assumptions and a pseudo-decision level was introduced.
130
+ + !control[assumptions.size () + 1].decision;
131
+ if (!opts.restartreusetrail)
132
+ return trivial_decisions;
133
+ int next_decision = next_decision_variable ();
134
+ assert (1 <= next_decision);
135
+ int res = trivial_decisions;
136
+ if (use_scores ()) {
137
+ while (res < level) {
138
+ int decision = control[res + 1].decision;
139
+ if (decision && score_smaller (this) (abs (decision), next_decision))
140
+ break;
141
+ res++;
142
+ }
143
+ } else {
144
+ int64_t limit = bumped (next_decision);
145
+ while (res < level) {
146
+ int decision = control[res + 1].decision;
147
+ if (decision && bumped (decision) < limit)
148
+ break;
149
+ res++;
150
+ }
151
+ }
152
+ int reused = res - trivial_decisions;
153
+ if (reused > 0) {
154
+ stats.reused++;
155
+ stats.reusedlevels += reused;
156
+ if (stable)
157
+ stats.reusedstable++;
158
+ }
159
+ return res;
160
+ }
161
+
162
+ void Internal::restart () {
163
+ START (restart);
164
+ stats.restarts++;
165
+ stats.restartlevels += level;
166
+ if (stable)
167
+ stats.restartstable++;
168
+ LOG ("restart %" PRId64 "", stats.restarts);
169
+ backtrack (reuse_trail ());
170
+
171
+ lim.restart = stats.conflicts + opts.restartint;
172
+ LOG ("new restart limit at %" PRId64 " conflicts", lim.restart);
173
+
174
+ report ('R', 2);
175
+ STOP (restart);
176
+ }
177
+
178
+ } // namespace CaDiCaL
@@ -0,0 +1,267 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ /*------------------------------------------------------------------------*/
6
+
7
+ // In incremental solving after a first call to 'solve' has finished and
8
+ // before calling the internal 'solve' again incrementally we have to
9
+ // restore clauses which have the negation of a literal as a witness literal
10
+ // on the extension stack, which was added as original literal in a new
11
+ // clause or in an assumption. This procedure has to be applied
12
+ // recursively, i.e., the literals of restored clauses are treated in the
13
+ // same way as literals of a new original clause.
14
+ //
15
+ // To figure out whether literals are such witnesses we have a 'witness'
16
+ // bit for each external literal, which is set in 'block', 'elim', and
17
+ // 'decompose' if a clause is pushed on the extension stack. The witness
18
+ // bits are recomputed after restoring clauses.
19
+ //
20
+ // We further mark in the external solver newly internalized external
21
+ // literals in 'add' and 'assume' since the last call to 'solve' as tainted
22
+ // if they occur negated as a witness literal on the extension stack. Then
23
+ // we go through the extension stack and restore all clauses which have a
24
+ // tainted literal (and its negation a marked as witness).
25
+ //
26
+ // Since the API contract disallows to call 'val' and 'failed' in an
27
+ // 'UNKNOWN' state. We do not have to internalize literals there.
28
+ //
29
+ // In order to have tainted literals accepted by the internal solver they
30
+ // have to be active and thus we might need to 'reactivate' them before
31
+ // restoring clauses if they are inactive. In case they have completely
32
+ // been eliminated and removed from the internal solver in 'compact', then
33
+ // we just use a new internal variable. This is performed in 'internalize'
34
+ // during marking external literals as tainted.
35
+ //
36
+ // To check that this approach is correct the external solver can maintain a
37
+ // stack of original clauses and current assumptions both in terms of
38
+ // external literals. Whenever 'solve' determines that the current
39
+ // incremental call is satisfiable we check that the (extended) witness does
40
+ // satisfy the saved original clauses, as well as all the assumptions. To
41
+ // enable these checks set 'opts.check' as well as 'opts.checkwitness' and
42
+ // 'opts.checkassumptions' all to 'true'. The model based tester actually
43
+ // prefers to enable the 'opts.check' option and the other two are 'true' by
44
+ // default anyhow.
45
+ //
46
+ // See our SAT'19 paper [FazekasBiereScholl-SAT'19] for more details.
47
+
48
+ /*------------------------------------------------------------------------*/
49
+
50
+ void External::restore_clause (const vector<int>::const_iterator &begin,
51
+ const vector<int>::const_iterator &end,
52
+ const int64_t id) {
53
+ LOG (begin, end, "restoring external clause[%" PRId64 "]", id);
54
+ assert (eclause.empty ());
55
+ assert (id);
56
+ for (auto p = begin; p != end; p++) {
57
+ eclause.push_back (*p);
58
+ if (internal->proof && internal->lrat) {
59
+ const auto &elit = *p;
60
+ unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
61
+ assert ((size_t) eidx < ext_units.size ());
62
+ const int64_t id = ext_units[eidx];
63
+ bool added = ext_flags[abs (elit)];
64
+ if (id && !added) {
65
+ ext_flags[abs (elit)] = true;
66
+ internal->lrat_chain.push_back (id);
67
+ }
68
+ }
69
+ int ilit = internalize (*p);
70
+ internal->add_original_lit (ilit), internal->stats.restoredlits++;
71
+ }
72
+ if (internal->proof && internal->lrat) {
73
+ for (const auto &elit : eclause) {
74
+ ext_flags[abs (elit)] = false;
75
+ }
76
+ }
77
+ internal->finish_added_clause_with_id (id, true);
78
+ eclause.clear ();
79
+ internal->stats.restored++;
80
+ }
81
+
82
+ /*------------------------------------------------------------------------*/
83
+
84
+ void External::restore_clauses () {
85
+
86
+ assert (internal->opts.restoreall == 2 || !tainted.empty ());
87
+
88
+ START (restore);
89
+ internal->stats.restorations++;
90
+
91
+ struct {
92
+ int64_t weakened, satisfied, restored, removed;
93
+ } clauses;
94
+ memset (&clauses, 0, sizeof clauses);
95
+
96
+ if (internal->opts.restoreall && tainted.empty ())
97
+ PHASE ("restore", internal->stats.restorations,
98
+ "forced to restore all clauses");
99
+
100
+ #ifndef QUIET
101
+ {
102
+ unsigned numtainted = 0;
103
+ for (const auto b : tainted)
104
+ if (b)
105
+ numtainted++;
106
+
107
+ PHASE ("restore", internal->stats.restorations,
108
+ "starting with %u tainted literals %.0f%%", numtainted,
109
+ percent (numtainted, 2u * max_var));
110
+ }
111
+ #endif
112
+
113
+ auto end_of_extension = extension.end ();
114
+ auto p = extension.begin (), q = p;
115
+
116
+ // Go over all witness labelled clauses on the extension stack, restore
117
+ // those necessary, remove restored and flush satisfied clauses.
118
+ //
119
+ while (p != end_of_extension) {
120
+
121
+ clauses.weakened++;
122
+
123
+ assert (!*p);
124
+ const auto saved = q; // Save old start.
125
+ *q++ = *p++; // Copy zero '0'.
126
+
127
+ // Copy witness part and try to find a tainted witness literal in it.
128
+ //
129
+ int tlit = 0; // Negation tainted.
130
+ int elit;
131
+ //
132
+ assert (p != end_of_extension);
133
+ //
134
+ while ((elit = *q++ = *p++)) {
135
+
136
+ if (marked (tainted, -elit)) {
137
+ tlit = elit;
138
+ LOG ("negation of witness literal %d tainted", tlit);
139
+ }
140
+
141
+ assert (p != end_of_extension);
142
+ }
143
+
144
+ // now copy the id of the clause
145
+ const int64_t id = ((int64_t) (*p) << 32) + (int64_t) * (p + 1);
146
+ LOG ("id is %" PRId64, id);
147
+ *q++ = *p++;
148
+ *q++ = *p++;
149
+ assert (id);
150
+ assert (!*p);
151
+ *q++ = *p++;
152
+
153
+ // Now find 'end_of_clause' (clause starts at 'p') and at the same time
154
+ // figure out whether the clause is actually root level satisfied.
155
+ //
156
+ int satisfied = 0;
157
+ auto end_of_clause = p;
158
+ while (end_of_clause != end_of_extension && (elit = *end_of_clause)) {
159
+ if (!satisfied && fixed (elit) > 0)
160
+ satisfied = elit;
161
+ end_of_clause++;
162
+ }
163
+ assert (id);
164
+
165
+ // Do not apply our 'FLUSH' rule to remove satisfied (implied) clauses
166
+ // if the corresponding option is set simply by resetting 'satisfied'.
167
+ //
168
+ if (satisfied && !internal->opts.restoreflush) {
169
+ LOG (p, end_of_clause, "forced to not remove %d satisfied",
170
+ satisfied);
171
+ satisfied = 0;
172
+ }
173
+
174
+ if (satisfied || tlit || internal->opts.restoreall) {
175
+
176
+ if (satisfied) {
177
+ LOG (p, end_of_clause,
178
+ "flushing implied clause satisfied by %d from extension stack",
179
+ satisfied);
180
+ clauses.satisfied++;
181
+ } else {
182
+ restore_clause (p, end_of_clause, id); // Might taint literals.
183
+ clauses.restored++;
184
+ }
185
+
186
+ clauses.removed++;
187
+ p = end_of_clause;
188
+ q = saved;
189
+
190
+ } else {
191
+
192
+ LOG (p, end_of_clause, "keeping clause on extension stack");
193
+
194
+ while (p != end_of_clause) // Copy clause too.
195
+ *q++ = *p++;
196
+ }
197
+ }
198
+
199
+ extension.resize (q - extension.begin ());
200
+ shrink_vector (extension);
201
+
202
+ #ifndef QUIET
203
+ if (clauses.satisfied)
204
+ PHASE ("restore", internal->stats.restorations,
205
+ "removed %" PRId64 " satisfied %.0f%% of %" PRId64
206
+ " weakened clauses",
207
+ clauses.satisfied, percent (clauses.satisfied, clauses.weakened),
208
+ clauses.weakened);
209
+ else
210
+ PHASE ("restore", internal->stats.restorations,
211
+ "no satisfied clause removed out of %" PRId64
212
+ " weakened clauses",
213
+ clauses.weakened);
214
+
215
+ if (clauses.restored)
216
+ PHASE ("restore", internal->stats.restorations,
217
+ "restored %" PRId64 " clauses %.0f%% out of %" PRId64
218
+ " weakened clauses",
219
+ clauses.restored, percent (clauses.restored, clauses.weakened),
220
+ clauses.weakened);
221
+ else
222
+ PHASE ("restore", internal->stats.restorations,
223
+ "no clause restored out of %" PRId64 " weakened clauses",
224
+ clauses.weakened);
225
+ {
226
+ unsigned numtainted = 0;
227
+ for (const auto &b : tainted)
228
+ if (b)
229
+ numtainted++;
230
+
231
+ PHASE ("restore", internal->stats.restorations,
232
+ "finishing with %u tainted literals %.0f%%", numtainted,
233
+ percent (numtainted, 2u * max_var));
234
+ }
235
+
236
+ #endif
237
+ LOG ("extension stack clean");
238
+ tainted.clear ();
239
+
240
+ // Finally recompute the witness bits.
241
+ //
242
+ witness.clear ();
243
+ const auto begin_of_extension = extension.begin ();
244
+ p = extension.end ();
245
+ while (p != begin_of_extension) {
246
+ while (*--p)
247
+ assert (p != begin_of_extension);
248
+ int elit;
249
+ assert (p != begin_of_extension);
250
+ --p;
251
+ assert (p != begin_of_extension);
252
+ assert (*p || *(p - 1));
253
+ --p;
254
+ assert (p != begin_of_extension);
255
+ assert (!*p);
256
+ --p;
257
+ assert (p != begin_of_extension);
258
+ while ((elit = *--p)) {
259
+ mark (witness, elit);
260
+ assert (p != begin_of_extension);
261
+ }
262
+ }
263
+
264
+ STOP (restore);
265
+ }
266
+
267
+ } // namespace CaDiCaL
@@ -0,0 +1,51 @@
1
+ #include "internal.hpp"
2
+
3
+ namespace CaDiCaL {
4
+
5
+ // This initializes variables on the binary 'scores' heap also with
6
+ // smallest variable index first (thus picked first) and larger indices at
7
+ // the end.
8
+ //
9
+ void Internal::init_scores (int old_max_var, int new_max_var) {
10
+ LOG ("initializing EVSIDS scores from %d to %d", old_max_var + 1,
11
+ new_max_var);
12
+ for (int i = old_max_var; i < new_max_var; i++)
13
+ scores.push_back (i + 1);
14
+ }
15
+
16
+ // Shuffle the EVSIDS heap.
17
+
18
+ void Internal::shuffle_scores () {
19
+ if (!opts.shuffle)
20
+ return;
21
+ if (!opts.shufflescores)
22
+ return;
23
+ assert (!level);
24
+ stats.shuffled++;
25
+ LOG ("shuffling scores");
26
+ vector<int> shuffle;
27
+ if (opts.shufflerandom) {
28
+ scores.erase ();
29
+ for (int idx = max_var; idx; idx--)
30
+ shuffle.push_back (idx);
31
+ Random random (opts.seed); // global seed
32
+ random += stats.shuffled; // different every time
33
+ for (int i = 0; i <= max_var - 2; i++) {
34
+ const int j = random.pick_int (i, max_var - 1);
35
+ swap (shuffle[i], shuffle[j]);
36
+ }
37
+ } else {
38
+ while (!scores.empty ()) {
39
+ int idx = scores.front ();
40
+ (void) scores.pop_front ();
41
+ shuffle.push_back (idx);
42
+ }
43
+ }
44
+ score_inc = 0;
45
+ for (const auto &idx : shuffle) {
46
+ stab[idx] = score_inc++;
47
+ scores.push_back (idx);
48
+ }
49
+ }
50
+
51
+ } // namespace CaDiCaL
@@ -0,0 +1,16 @@
1
+ #ifndef _score_hpp_INCLUDED
2
+ #define _score_hpp_INCLUDED
3
+
4
+ namespace CaDiCaL {
5
+
6
+ struct score_smaller {
7
+ Internal *internal;
8
+ score_smaller (Internal *i) : internal (i) {}
9
+ bool operator() (unsigned a, unsigned b);
10
+ };
11
+
12
+ typedef heap<score_smaller> ScoreSchedule;
13
+
14
+ } // namespace CaDiCaL
15
+
16
+ #endif