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,1871 @@
1
+ #include "cadical.hpp"
2
+ #include "internal.hpp"
3
+ #include <atomic>
4
+
5
+ /*------------------------------------------------------------------------*/
6
+
7
+ namespace CaDiCaL {
8
+
9
+ /*------------------------------------------------------------------------*/
10
+
11
+ // See corresponding header file 'cadical.hpp' (!) for more information.
12
+ //
13
+ // Again, to avoid confusion, note that, 'cadical.hpp' is the header file of
14
+ // this file 'solver.cpp', since we want to call the application and main
15
+ // file 'cadical.cpp', while at the same time using 'cadical.hpp' as the
16
+ // main header file of the library (and not 'solver.hpp').
17
+
18
+ /*------------------------------------------------------------------------*/
19
+ #ifdef LOGGING
20
+
21
+ // Needs to be kept in sync with the color schemes used in 'logging.cpp'.
22
+ //
23
+ #define api_code blue_code // API call color
24
+ #define log_code magenta_code // standard/default logging color
25
+ #define emph_code bright_magenta_code // emphasized logging color
26
+
27
+ #endif
28
+ /*------------------------------------------------------------------------*/
29
+
30
+ // Log state transitions.
31
+
32
+ #define STATE(S) \
33
+ do { \
34
+ assert (is_power_of_two (S)); \
35
+ if (_state == S) \
36
+ break; \
37
+ _state = S; \
38
+ LOG ("API enters state %s" #S "%s", tout.emph_code (), \
39
+ tout.normal_code ()); \
40
+ } while (0)
41
+
42
+ void Solver::transition_to_steady_state () {
43
+ if (state () == CONFIGURING) {
44
+ LOG ("API leaves state %sCONFIGURING%s", tout.emph_code (),
45
+ tout.normal_code ());
46
+ if (internal->opts.check && internal->opts.checkproof) {
47
+ internal->check ();
48
+ }
49
+ } else if (state () == SATISFIED) {
50
+ LOG ("API leaves state %sSATISFIED%s", tout.emph_code (),
51
+ tout.normal_code ());
52
+ external->reset_assumptions ();
53
+ external->reset_concluded ();
54
+ external->reset_constraint ();
55
+ } else if (state () == UNSATISFIED) {
56
+ LOG ("API leaves state %sUNSATISFIED%s", tout.emph_code (),
57
+ tout.normal_code ());
58
+ external->reset_assumptions ();
59
+ external->reset_concluded ();
60
+ external->reset_constraint ();
61
+ } else if (state () == INCONCLUSIVE) {
62
+ external->reset_assumptions ();
63
+ external->reset_concluded ();
64
+ external->reset_constraint ();
65
+ }
66
+ if (state () != STEADY)
67
+ STATE (STEADY);
68
+ }
69
+
70
+ /*------------------------------------------------------------------------*/
71
+ #ifdef LOGGING
72
+ /*------------------------------------------------------------------------*/
73
+
74
+ // The following logging code is useful for debugging mostly (or trying to
75
+ // understand what the solver is actually doing). It needs to be enabled
76
+ // during configuration using the '-l' option for './configure', which
77
+ // forces 'LOGGING' to be defined during compilation. This includes all the
78
+ // logging code, which then still needs to enabled during run-time with the
79
+ // '-l' or 'log' option.
80
+
81
+ static void log_api_call (Internal *internal, const char *name,
82
+ const char *suffix) {
83
+ Logger::log (internal, "API call %s'%s ()'%s %s", tout.api_code (), name,
84
+ tout.log_code (), suffix);
85
+ }
86
+
87
+ static void log_api_call (Internal *internal, const char *name, int arg,
88
+ const char *suffix) {
89
+ Logger::log (internal, "API call %s'%s (%d)'%s %s", tout.api_code (),
90
+ name, arg, tout.log_code (), suffix);
91
+ }
92
+
93
+ static void log_api_call (Internal *internal, const char *name, int arg,
94
+ int b, const char *suffix) {
95
+ Logger::log (internal, "API call %s'%s (%d, %d)'%s %s", tout.api_code (),
96
+ name, arg, b, tout.log_code (), suffix);
97
+ }
98
+
99
+ static void log_api_call (Internal *internal, const char *name, int arg,
100
+ int b, int c) {
101
+ Logger::log (internal, "API call %s'%s (%d, %d)'%s %d", tout.api_code (),
102
+ name, arg, b, tout.log_code (), c);
103
+ }
104
+
105
+ static void log_api_call (Internal *internal, const char *name,
106
+ const char *arg, const char *suffix) {
107
+ Logger::log (internal, "API call %s'%s (\"%s\")'%s %s", tout.api_code (),
108
+ name, arg, tout.log_code (), suffix);
109
+ }
110
+
111
+ static void log_api_call (Internal *internal, const char *name,
112
+ const char *a1, int a2, const char *s) {
113
+ Logger::log (internal, "API call %s'%s (\"%s\", %d)'%s %s",
114
+ tout.api_code (), name, a1, a2, tout.log_code (), s);
115
+ }
116
+
117
+ /*------------------------------------------------------------------------*/
118
+
119
+ // We factored out API call begin/end logging and use overloaded functions.
120
+
121
+ static void log_api_call_begin (Internal *internal, const char *name) {
122
+ Logger::log_empty_line (internal);
123
+ log_api_call (internal, name, "started");
124
+ }
125
+
126
+ static void log_api_call_begin (Internal *internal, const char *name,
127
+ int arg) {
128
+ Logger::log_empty_line (internal);
129
+ log_api_call (internal, name, arg, "started");
130
+ }
131
+
132
+ static void log_api_call_begin (Internal *internal, const char *name,
133
+ int arg, int b) {
134
+ Logger::log_empty_line (internal);
135
+ log_api_call (internal, name, arg, b, "started");
136
+ }
137
+
138
+ static void log_api_call_begin (Internal *internal, const char *name,
139
+ const char *arg) {
140
+ Logger::log_empty_line (internal);
141
+ log_api_call (internal, name, arg, "started");
142
+ }
143
+
144
+ static void log_api_call_begin (Internal *internal, const char *name,
145
+ const char *arg1, int arg2) {
146
+ Logger::log_empty_line (internal);
147
+ log_api_call (internal, name, arg1, arg2, "started");
148
+ }
149
+
150
+ /*------------------------------------------------------------------------*/
151
+
152
+ static void log_api_call_end (Internal *internal, const char *name) {
153
+ log_api_call (internal, name, "succeeded");
154
+ }
155
+
156
+ static void log_api_call_end (Internal *internal, const char *name,
157
+ int lit) {
158
+ log_api_call (internal, name, lit, "succeeded");
159
+ }
160
+
161
+ static void log_api_call_end (Internal *internal, const char *name,
162
+ const char *arg) {
163
+ Logger::log_empty_line (internal);
164
+ log_api_call (internal, name, arg, "succeeded");
165
+ }
166
+
167
+ static void log_api_call_end (Internal *internal, const char *name,
168
+ const char *arg, bool res) {
169
+ log_api_call (internal, name, arg, res ? "succeeded" : "failed");
170
+ }
171
+
172
+ static void log_api_call_end (Internal *internal, const char *name,
173
+ const char *arg, int val, bool res) {
174
+ log_api_call (internal, name, arg, val, res ? "succeeded" : "failed");
175
+ }
176
+
177
+ static void log_api_call_returns (Internal *internal, const char *name,
178
+ bool res) {
179
+ log_api_call (internal, name, res ? "returns 'true'" : "returns 'false'");
180
+ }
181
+
182
+ static void log_api_call_returns (Internal *internal, const char *name,
183
+ int res) {
184
+ char fmt[32];
185
+ snprintf (fmt, sizeof fmt, "returns '%d'", res);
186
+ log_api_call (internal, name, fmt);
187
+ }
188
+
189
+ static void log_api_call_returns (Internal *internal, const char *name,
190
+ int64_t res) {
191
+ char fmt[32];
192
+ snprintf (fmt, sizeof fmt, "returns '%" PRId64 "'", res);
193
+ log_api_call (internal, name, fmt);
194
+ }
195
+
196
+ static void log_api_call_returns (Internal *internal, const char *name,
197
+ int lit, int res) {
198
+ char fmt[32];
199
+ snprintf (fmt, sizeof fmt, "returns '%d'", res);
200
+ log_api_call (internal, name, lit, fmt);
201
+ }
202
+
203
+ static void log_api_call_returns (Internal *internal, const char *name,
204
+ const char *arg, bool res) {
205
+ log_api_call (internal, name, arg,
206
+ res ? "returns 'true'" : "returns 'false'");
207
+ }
208
+
209
+ static void log_api_call_returns (Internal *internal, const char *name,
210
+ int lit, bool res) {
211
+ log_api_call (internal, name, lit,
212
+ res ? "returns 'true'" : "returns 'false'");
213
+ }
214
+
215
+ static void log_api_call_returns (Internal *internal, const char *name,
216
+ int lit, int b, int res) {
217
+ log_api_call (internal, name, lit, b, res);
218
+ }
219
+
220
+ static void log_api_call_returns (Internal *internal, const char *name,
221
+ const char *arg, const char *res) {
222
+ Logger::log (internal, "API call %s'%s (\"%s\")'%s returns '%s'",
223
+ tout.api_code (), name, arg, tout.log_code (),
224
+ res ? res : "<null>");
225
+ }
226
+
227
+ static void log_api_call_returns (Internal *internal, const char *name,
228
+ const char *arg1, int arg2,
229
+ const char *res) {
230
+ Logger::log (internal, "API call %s'%s (\"%s\", %d)'%s returns '%s'",
231
+ tout.api_code (), name, arg1, arg2, tout.log_code (),
232
+ res ? res : "<null>");
233
+ }
234
+
235
+ /*------------------------------------------------------------------------*/
236
+
237
+ #define LOG_API_CALL_BEGIN(...) \
238
+ do { \
239
+ if (!internal->opts.log) \
240
+ break; \
241
+ log_api_call_begin (internal, __VA_ARGS__); \
242
+ } while (0)
243
+
244
+ #define LOG_API_CALL_END(...) \
245
+ do { \
246
+ if (!internal->opts.log) \
247
+ break; \
248
+ log_api_call_end (internal, __VA_ARGS__); \
249
+ } while (0)
250
+
251
+ #define LOG_API_CALL_RETURNS(...) \
252
+ do { \
253
+ if (!internal->opts.log) \
254
+ break; \
255
+ log_api_call_returns (internal, __VA_ARGS__); \
256
+ } while (0)
257
+
258
+ /*------------------------------------------------------------------------*/
259
+ #else // end of 'then' part of 'ifdef LOGGING'
260
+ /*------------------------------------------------------------------------*/
261
+
262
+ #define LOG_API_CALL_BEGIN(...) \
263
+ do { \
264
+ } while (0)
265
+ #define LOG_API_CALL_END(...) \
266
+ do { \
267
+ } while (0)
268
+ #define LOG_API_CALL_RETURNS(...) \
269
+ do { \
270
+ } while (0)
271
+
272
+ /*------------------------------------------------------------------------*/
273
+ #endif // end of 'else' part of 'ifdef LOGGING'
274
+ /*------------------------------------------------------------------------*/
275
+
276
+ /*------------------------------------------------------------------------*/
277
+ #ifndef NTRACING
278
+ /*------------------------------------------------------------------------*/
279
+
280
+ #define TRACE(...) \
281
+ do { \
282
+ /*if ((this == 0)) break; */ /* gcc-12 produces warning */ \
283
+ if ((internal == 0)) \
284
+ break; \
285
+ LOG_API_CALL_BEGIN (__VA_ARGS__); \
286
+ if (!trace_api_file) \
287
+ break; \
288
+ trace_api_call (__VA_ARGS__); \
289
+ } while (0)
290
+
291
+ void Solver::trace_api_call (const char *s0) const {
292
+ assert (trace_api_file);
293
+ LOG ("TRACE %s", s0);
294
+ fprintf (trace_api_file, "%s\n", s0);
295
+ fflush (trace_api_file);
296
+ }
297
+
298
+ void Solver::trace_api_call (const char *s0, int i1) const {
299
+ assert (trace_api_file);
300
+ LOG ("TRACE %s %d", s0, i1);
301
+ fprintf (trace_api_file, "%s %d\n", s0, i1);
302
+ fflush (trace_api_file);
303
+ }
304
+
305
+ void Solver::trace_api_call (const char *s0, int i1, int b) const {
306
+ assert (trace_api_file);
307
+ LOG ("TRACE %s %d %d", s0, i1, b);
308
+ fprintf (trace_api_file, "%s %d %d\n", s0, i1, b);
309
+ fflush (trace_api_file);
310
+ }
311
+
312
+ void Solver::trace_api_call (const char *s0, const char *s1) const {
313
+ assert (trace_api_file);
314
+ LOG ("TRACE %s %s", s0, s1);
315
+ fprintf (trace_api_file, "%s %s\n", s0, s1);
316
+ fflush (trace_api_file);
317
+ }
318
+
319
+ void Solver::trace_api_call (const char *s0, const char *s1, int i2) const {
320
+ assert (trace_api_file);
321
+ LOG ("TRACE %s %s %d", s0, s1, i2);
322
+ fprintf (trace_api_file, "%s %s %d\n", s0, s1, i2);
323
+ fflush (trace_api_file);
324
+ }
325
+
326
+ /*------------------------------------------------------------------------*/
327
+
328
+ // The global 'tracing_api_calls_through_environment_variable_method' flag
329
+ // is used to ensure that only one solver traces to a file. Otherwise the
330
+ // method to use an environment variable to point to the trace file is
331
+ // bogus, since those different solver instances would all write to the same
332
+ // file producing garbage. A more sophisticated solution would use a
333
+ // different mechanism to tell the solver to which file to trace to, but in
334
+ // our experience it is quite convenient to get traces out of applications
335
+ // which use the solver as library by just setting an environment variable
336
+ // without requiring to change any application code.
337
+ //
338
+ // We initially had static but Mate Soos reported a helgrind error
339
+ // (https://github.com/arminbiere/cadical/issues/155) so we fixed it to
340
+ // static atomic.
341
+ //
342
+ static atomic<bool> tracing_api_calls_through_environment_variable_method{
343
+ false};
344
+
345
+ /*------------------------------------------------------------------------*/
346
+ #else // NTRACING
347
+ /*------------------------------------------------------------------------*/
348
+
349
+ #define TRACE(...) \
350
+ do { \
351
+ } while (0)
352
+
353
+ /*------------------------------------------------------------------------*/
354
+ #endif
355
+ /*------------------------------------------------------------------------*/
356
+
357
+ // The global 'tracing_nb_lidrup_env_var_method' flag is used to ensure that
358
+ // only one solver produces a proof file. Otherwise the method to use an
359
+ // environment variable to point to the trace file is bogus, since those
360
+ // different solver instances would all write to the same file producing
361
+ // garbage. See also the comment on
362
+ // `tracing_api_calls_through_environment_variable_method` above.
363
+ //
364
+ static atomic<bool> tracing_nb_lidrup_env_var_method{false};
365
+
366
+ Solver::Solver () {
367
+
368
+ #ifndef NTRACING
369
+ const char *path = getenv ("CADICAL_API_TRACE");
370
+ if (!path)
371
+ path = getenv ("CADICALAPITRACE");
372
+ if (path) {
373
+ if (tracing_api_calls_through_environment_variable_method)
374
+ FATAL ("can not trace API calls of two solver instances "
375
+ "using environment variable 'CADICAL_API_TRACE'");
376
+ if (!(trace_api_file = fopen (path, "w")))
377
+ FATAL ("failed to open file '%s' to trace API calls "
378
+ "using environment variable 'CADICAL_API_TRACE'",
379
+ path);
380
+ close_trace_api_file = true;
381
+ tracing_api_calls_through_environment_variable_method = true;
382
+ } else {
383
+ tracing_api_calls_through_environment_variable_method = false;
384
+ close_trace_api_file = false;
385
+ trace_api_file = 0;
386
+ }
387
+ #endif
388
+
389
+ adding_clause = false;
390
+ adding_constraint = false;
391
+ _state = INITIALIZING;
392
+ internal = new Internal ();
393
+ DeferDeletePtr<Internal> delete_internal (internal);
394
+ TRACE ("init");
395
+ external = new External (internal);
396
+ DeferDeletePtr<External> delete_external (external);
397
+ STATE (CONFIGURING);
398
+ #ifndef NTRACING
399
+ if (tracing_api_calls_through_environment_variable_method)
400
+ message ("tracing API calls to '%s'", path);
401
+ #endif
402
+
403
+ const char *lidrup_path = getenv ("CADICAL_LIDRUP_TRACE");
404
+ if (!lidrup_path)
405
+ lidrup_path = getenv ("CADICALLIDRUPTRACE");
406
+ if (lidrup_path) {
407
+ if (tracing_nb_lidrup_env_var_method)
408
+ FATAL ("can not trace LIDRUP of two solver instances "
409
+ "using environment variable 'CADICAL_LIDRUP_TRACE'");
410
+ // Here we use the solver interface to setup non-binary IDRUP tracing to
411
+ // the defined file. Options set by the user can and will overwrite
412
+ // these settings if neeed be.
413
+ set ("lidrup", 1);
414
+ set ("binary", 0);
415
+ trace_proof (lidrup_path);
416
+ tracing_nb_lidrup_env_var_method = true;
417
+ } else {
418
+ tracing_nb_lidrup_env_var_method = false;
419
+ }
420
+
421
+ delete_internal.release ();
422
+ delete_external.release ();
423
+ }
424
+
425
+ Solver::~Solver () {
426
+
427
+ TRACE ("reset");
428
+ REQUIRE_VALID_OR_SOLVING_STATE ();
429
+ STATE (DELETING);
430
+
431
+ tracing_nb_lidrup_env_var_method = false;
432
+
433
+ #ifdef LOGGING
434
+ //
435
+ // After deleting 'internal' logging does not work anymore.
436
+ //
437
+ bool logging = internal->opts.log;
438
+ int level = internal->level;
439
+ string prefix = internal->prefix;
440
+ #endif
441
+
442
+ delete internal;
443
+ delete external;
444
+
445
+ #ifndef NTRACING
446
+ if (close_trace_api_file) {
447
+ close_trace_api_file = false;
448
+ assert (trace_api_file);
449
+ assert (tracing_api_calls_through_environment_variable_method);
450
+ fclose (trace_api_file);
451
+ tracing_api_calls_through_environment_variable_method = false;
452
+ }
453
+ #endif
454
+
455
+ #ifdef LOGGING
456
+ //
457
+ // Need to log success of this API call manually.
458
+ //
459
+ if (logging) {
460
+ printf ("%s%sLOG %s%d%s API call %s'reset ()'%s succeeded%s\n",
461
+ prefix.c_str (), tout.log_code (), tout.emph_code (), level,
462
+ tout.log_code (), tout.api_code (), tout.log_code (),
463
+ tout.normal_code ());
464
+ fflush (stdout);
465
+ }
466
+ #endif
467
+ }
468
+
469
+ /*------------------------------------------------------------------------*/
470
+
471
+ int Solver::vars () {
472
+ TRACE ("vars");
473
+ REQUIRE_VALID_OR_SOLVING_STATE ();
474
+ int res = external->max_var;
475
+ LOG_API_CALL_RETURNS ("vars", res);
476
+ return res;
477
+ }
478
+
479
+ void Solver::resize (int min_max_var) {
480
+ TRACE ("resize", min_max_var);
481
+ REQUIRE_VALID_STATE ();
482
+ transition_to_steady_state ();
483
+ external->reset_extended ();
484
+ external->init (min_max_var);
485
+ LOG_API_CALL_END ("resize", min_max_var);
486
+ }
487
+
488
+ int Solver::declare_more_variables (int number_of_vars) {
489
+ TRACE ("declare_more_variables", number_of_vars);
490
+ REQUIRE_VALID_STATE ();
491
+ transition_to_steady_state ();
492
+ external->reset_extended ();
493
+ int new_max_var = external->max_var + number_of_vars;
494
+ external->init (new_max_var);
495
+ LOG_API_CALL_END ("declare_more_variables", number_of_vars);
496
+ return new_max_var;
497
+ }
498
+
499
+ int Solver::declare_one_more_variable () {
500
+ TRACE ("declare_one_more_variable");
501
+ REQUIRE_VALID_STATE ();
502
+ transition_to_steady_state ();
503
+ external->reset_extended ();
504
+ int new_max_var = external->max_var + 1;
505
+ external->init (new_max_var);
506
+ LOG_API_CALL_END ("declare_one_more_variable");
507
+ return new_max_var;
508
+ }
509
+
510
+ /*------------------------------------------------------------------------*/
511
+ #ifndef NTRACING
512
+
513
+ void Solver::trace_api_calls (FILE *file) {
514
+ LOG_API_CALL_BEGIN ("trace_api_calls");
515
+ REQUIRE_VALID_STATE ();
516
+ REQUIRE (file != 0, "invalid zero file argument");
517
+ REQUIRE (!tracing_api_calls_through_environment_variable_method,
518
+ "already tracing API calls "
519
+ "using environment variable 'CADICAL_API_TRACE'");
520
+ REQUIRE (!trace_api_file, "called twice");
521
+ trace_api_file = file;
522
+ LOG_API_CALL_END ("trace_api_calls");
523
+ trace_api_call ("init");
524
+ }
525
+
526
+ #endif
527
+ /*------------------------------------------------------------------------*/
528
+
529
+ bool Solver::is_valid_option (const char *name) {
530
+ return Options::has (name);
531
+ }
532
+
533
+ bool Solver::is_preprocessing_option (const char *name) {
534
+ return Options::is_preprocessing_option (name);
535
+ }
536
+
537
+ bool Solver::is_valid_long_option (const char *arg) {
538
+ string name;
539
+ int tmp;
540
+ return Options::parse_long_option (arg, name, tmp);
541
+ }
542
+
543
+ int Solver::get (const char *arg) {
544
+ REQUIRE_VALID_OR_SOLVING_STATE ();
545
+ return internal->opts.get (arg);
546
+ }
547
+
548
+ bool Solver::set (const char *arg, int val) {
549
+ TRACE ("set", arg, val);
550
+ REQUIRE_VALID_STATE ();
551
+ if (strcmp (arg, "log") && strcmp (arg, "quiet") &&
552
+ strcmp (arg, "report") && strcmp (arg, "verbose")) {
553
+ REQUIRE (
554
+ state () == CONFIGURING,
555
+ "can only set option 'set (\"%s\", %d)' right after initialization",
556
+ arg, val);
557
+ }
558
+ bool res = internal->opts.set (arg, val);
559
+ LOG_API_CALL_END ("set", arg, val, res);
560
+
561
+ return res;
562
+ }
563
+
564
+ bool Solver::set_long_option (const char *arg) {
565
+ LOG_API_CALL_BEGIN ("set", arg);
566
+ REQUIRE_VALID_STATE ();
567
+ REQUIRE (state () == CONFIGURING,
568
+ "can only set option '%s' right after initialization", arg);
569
+ bool res;
570
+ if (arg[0] != '-' || arg[1] != '-')
571
+ res = false;
572
+ else {
573
+ int val;
574
+ string name;
575
+ res = Options::parse_long_option (arg, name, val);
576
+ if (res)
577
+ set (name.c_str (), val);
578
+ }
579
+ LOG_API_CALL_END ("set", arg, res);
580
+ return res;
581
+ }
582
+
583
+ void Solver::optimize (int arg) {
584
+ LOG_API_CALL_BEGIN ("optimize", arg);
585
+ REQUIRE_VALID_STATE ();
586
+ internal->opts.optimize (arg);
587
+ LOG_API_CALL_END ("optimize", arg);
588
+ }
589
+
590
+ bool Solver::limit (const char *arg, int val) {
591
+ TRACE ("limit", arg, val);
592
+ REQUIRE_VALID_STATE ();
593
+ bool res = internal->limit (arg, val);
594
+ LOG_API_CALL_END ("limit", arg, val, res);
595
+ return res;
596
+ }
597
+
598
+ bool Solver::is_valid_limit (const char *arg) {
599
+ return Internal::is_valid_limit (arg);
600
+ }
601
+
602
+ void Solver::prefix (const char *str) {
603
+ LOG_API_CALL_BEGIN ("prefix", str);
604
+ REQUIRE_VALID_OR_SOLVING_STATE ();
605
+ internal->prefix = str;
606
+ LOG_API_CALL_END ("prefix", str);
607
+ }
608
+
609
+ bool Solver::is_valid_configuration (const char *name) {
610
+ return Config::has (name);
611
+ }
612
+
613
+ bool Solver::configure (const char *name) {
614
+ TRACE ("configure", name);
615
+ LOG_API_CALL_BEGIN ("configure", name);
616
+ REQUIRE_VALID_STATE ();
617
+ REQUIRE (state () == CONFIGURING,
618
+ "can only set configuration '%s' right after initialization",
619
+ name);
620
+ bool res = Config::set (internal->opts, name);
621
+ LOG_API_CALL_END ("configure", name, res);
622
+ return res;
623
+ }
624
+
625
+ /*===== IPASIR BEGIN =====================================================*/
626
+
627
+ void Solver::add (int lit) {
628
+ TRACE ("add", lit);
629
+ REQUIRE_VALID_STATE ();
630
+ if (lit) {
631
+ if (internal->opts.factor && internal->opts.factorcheck == 1)
632
+ REQUIRE (
633
+ abs (lit) <= external->max_var,
634
+ "adding literal '%d' with undeclared variable '%d' "
635
+ "(checking that user variables are declared explicitly failed "
636
+ "as both 'factor' and 'factorcheck' are enabled)",
637
+ lit, (int) abs (lit));
638
+ if (internal->opts.factorcheck == 2)
639
+ REQUIRE (
640
+ abs (lit) <= external->max_var,
641
+ "adding literal '%d' with undeclared variable '%d' "
642
+ "(checking that user variables are declared explicitly failed "
643
+ "as 'factorcheck == 2' even if 'factor' is disabled)",
644
+ lit, (int) abs (lit));
645
+ }
646
+ if (lit)
647
+ REQUIRE_VALID_LIT (lit);
648
+ transition_to_steady_state ();
649
+ external->add (lit);
650
+ adding_clause = lit;
651
+ if (adding_clause)
652
+ STATE (ADDING);
653
+ else if (!adding_constraint)
654
+ STATE (STEADY);
655
+ LOG_API_CALL_END ("add", lit);
656
+ }
657
+
658
+ void Solver::clause (int a) {
659
+ REQUIRE_VALID_LIT (a);
660
+ add (a), add (0);
661
+ }
662
+
663
+ void Solver::clause (int a, int b) {
664
+ REQUIRE_VALID_LIT (a);
665
+ REQUIRE_VALID_LIT (b);
666
+ add (a), add (b), add (0);
667
+ }
668
+
669
+ void Solver::clause (int a, int b, int c) {
670
+ REQUIRE_VALID_LIT (a);
671
+ REQUIRE_VALID_LIT (b);
672
+ REQUIRE_VALID_LIT (c);
673
+ add (a), add (b), add (c), add (0);
674
+ }
675
+
676
+ void Solver::clause (int a, int b, int c, int d) {
677
+ REQUIRE_VALID_LIT (a);
678
+ REQUIRE_VALID_LIT (b);
679
+ REQUIRE_VALID_LIT (c);
680
+ REQUIRE_VALID_LIT (d);
681
+ add (a), add (b), add (c), add (d), add (0);
682
+ }
683
+
684
+ void Solver::clause (int a, int b, int c, int d, int e) {
685
+ REQUIRE_VALID_LIT (a);
686
+ REQUIRE_VALID_LIT (b);
687
+ REQUIRE_VALID_LIT (c);
688
+ REQUIRE_VALID_LIT (d);
689
+ REQUIRE_VALID_LIT (e);
690
+ add (a), add (b), add (c), add (d), add (e), add (0);
691
+ }
692
+
693
+ void Solver::clause (const int *lits, size_t size) {
694
+ REQUIRE (!size || lits,
695
+ "first argument 'lits' zero while second argument 'size' not");
696
+ const int *end = lits + size;
697
+ for (const int *p = lits; p != end; p++) {
698
+ const int lit = *p;
699
+ REQUIRE_VALID_LIT (lit);
700
+ add (lit);
701
+ }
702
+ add (0);
703
+ }
704
+
705
+ void Solver::clause (const std::vector<int> &lits) {
706
+ for (auto lit : lits) {
707
+ REQUIRE_VALID_LIT (lit);
708
+ add (lit);
709
+ }
710
+ add (0);
711
+ }
712
+
713
+ bool Solver::inconsistent () { return internal->unsat; }
714
+
715
+ void Solver::constrain (int lit) {
716
+ TRACE ("constrain", lit);
717
+ REQUIRE_VALID_STATE ();
718
+ if (lit)
719
+ REQUIRE_VALID_LIT (lit);
720
+ transition_to_steady_state ();
721
+ external->constrain (lit);
722
+ adding_constraint = lit;
723
+ if (adding_constraint)
724
+ STATE (ADDING);
725
+ else if (!adding_clause)
726
+ STATE (STEADY);
727
+ LOG_API_CALL_END ("constrain", lit);
728
+ }
729
+
730
+ void Solver::assume (int lit) {
731
+ TRACE ("assume", lit);
732
+ REQUIRE_VALID_STATE ();
733
+ REQUIRE_VALID_LIT (lit);
734
+ transition_to_steady_state ();
735
+ external->assume (lit);
736
+ LOG_API_CALL_END ("assume", lit);
737
+ }
738
+
739
+ int Solver::lookahead () {
740
+ TRACE ("lookahead");
741
+ REQUIRE_VALID_OR_SOLVING_STATE ();
742
+ transition_to_steady_state ();
743
+ int lit = external->lookahead ();
744
+ LOG_API_CALL_END ("lookahead", lit);
745
+ return lit;
746
+ }
747
+
748
+ Solver::CubesWithStatus Solver::generate_cubes (int depth, int min_depth) {
749
+ TRACE ("lookahead_cubes");
750
+ REQUIRE_VALID_OR_SOLVING_STATE ();
751
+ auto cubes = external->generate_cubes (depth, min_depth);
752
+ TRACE ("lookahead_cubes");
753
+
754
+ CubesWithStatus cubes2;
755
+ cubes2.status = cubes.status;
756
+ cubes2.cubes = cubes.cubes;
757
+ return cubes2;
758
+ }
759
+
760
+ void Solver::reset_assumptions () {
761
+ TRACE ("reset_assumptions");
762
+ REQUIRE_VALID_STATE ();
763
+ transition_to_steady_state ();
764
+ external->reset_assumptions ();
765
+ external->reset_concluded ();
766
+ LOG_API_CALL_END ("reset_assumptions");
767
+ }
768
+
769
+ void Solver::reset_constraint () {
770
+ TRACE ("reset_constraint");
771
+ REQUIRE_VALID_STATE ();
772
+ transition_to_steady_state ();
773
+ external->reset_constraint ();
774
+ external->reset_concluded ();
775
+ LOG_API_CALL_END ("reset_constraint");
776
+ }
777
+
778
+ /*------------------------------------------------------------------------*/
779
+
780
+ int Solver::propagate () {
781
+ TRACE ("propagate_assumptions");
782
+ REQUIRE_VALID_STATE ();
783
+ transition_to_steady_state ();
784
+ const int res = external->propagate_assumptions ();
785
+ if (tracing_nb_lidrup_env_var_method)
786
+ flush_proof_trace (true);
787
+ LOG_API_CALL_RETURNS ("propagate_assumptions", res);
788
+ if (res == 10)
789
+ STATE (SATISFIED);
790
+ else if (res == 20)
791
+ STATE (UNSATISFIED);
792
+ else
793
+ STATE (INCONCLUSIVE);
794
+ return res;
795
+ }
796
+
797
+ void Solver::implied (std::vector<int> &entrailed) {
798
+ TRACE ("implied");
799
+ REQUIRE_VALID_STATE ();
800
+ REQUIRE (
801
+ state () == INCONCLUSIVE || state () == SATISFIED,
802
+ "can only get implied literals only in unknown or satisfied state");
803
+ external->conclude_unknown ();
804
+ external->implied (entrailed);
805
+ if (tracing_nb_lidrup_env_var_method)
806
+ flush_proof_trace (true);
807
+ LOG_API_CALL_RETURNS ("implied", (int) entrailed.size ());
808
+ }
809
+
810
+ /*------------------------------------------------------------------------*/
811
+
812
+ int Solver::call_external_solve_and_check_results (bool preprocess_only) {
813
+ transition_to_steady_state ();
814
+ assert (state () & READY);
815
+ STATE (SOLVING);
816
+ const int res = external->solve (preprocess_only);
817
+ if (res == 10)
818
+ STATE (SATISFIED);
819
+ else if (res == 20)
820
+ STATE (UNSATISFIED);
821
+ else
822
+ STATE (INCONCLUSIVE);
823
+ #if 0 // EXPENSIVE ALTERNATIVE ASSUMPTION CHECKING
824
+ // This checks that the set of failed assumptions form a core using the
825
+ // external 'copy (...)' function to copy the solver, which can be trusted
826
+ // less, since it involves copying the extension stack too. The
827
+ // 'External::check_assumptions_failing' is a better alternative and can
828
+ // be enabled by options too. We keep this code though to have an
829
+ // alternative failed assumption checking available for debugging.
830
+ //
831
+ if (res == 20 && !external->assumptions.empty ()) {
832
+ Solver checker;
833
+ // checking restored clauses does not work (because the clauses are not added)
834
+ checker.set("checkproof", 1);
835
+ checker.set("lrat", 0);
836
+ checker.set("factorcheck", 0);
837
+ checker.prefix ("checker ");
838
+ copy (checker);
839
+ checker.set("log", 1);
840
+ for (const auto & lit : external->assumptions)
841
+ if (failed (lit))
842
+ checker.add (lit), checker.add (0);
843
+ if (checker.solve () != 20)
844
+ FATAL ("copying assumption checker failed");
845
+ }
846
+ #endif
847
+ #if 0 // was necessary when INCONCLUSIVE state did not exist
848
+ if (!res) {
849
+ external->reset_assumptions ();
850
+ external->reset_constraint ();
851
+ external->reset_concluded ();
852
+ }
853
+ #endif
854
+ return res;
855
+ }
856
+
857
+ int Solver::solve () {
858
+ TRACE ("solve");
859
+ REQUIRE_READY_STATE ();
860
+ const int res = call_external_solve_and_check_results (false);
861
+ LOG_API_CALL_RETURNS ("solve", res);
862
+ if (tracing_nb_lidrup_env_var_method)
863
+ flush_proof_trace (true);
864
+ return res;
865
+ }
866
+
867
+ int Solver::simplify (int rounds) {
868
+ TRACE ("simplify", rounds);
869
+ REQUIRE_READY_STATE ();
870
+ REQUIRE (rounds >= 0, "negative number of simplification rounds '%d'",
871
+ rounds);
872
+ internal->limit ("preprocessing", rounds);
873
+ const int lucky = internal->opts.lucky;
874
+ internal->opts.lucky = 0;
875
+ const int res = call_external_solve_and_check_results (true);
876
+ internal->opts.lucky = lucky;
877
+ LOG_API_CALL_RETURNS ("simplify", rounds, res);
878
+ return res;
879
+ }
880
+
881
+ /*------------------------------------------------------------------------*/
882
+
883
+ int Solver::val (
884
+ int lit, bool use_default_value_for_declared_but_not_used_variable) {
885
+ LOG_API_CALL_BEGIN (
886
+ "val", lit,
887
+ (int) use_default_value_for_declared_but_not_used_variable);
888
+ REQUIRE_VALID_STATE ();
889
+ REQUIRE_VALID_LIT (lit);
890
+ REQUIRE (state () == SATISFIED, "can only get value in satisfied state");
891
+ if (!use_default_value_for_declared_but_not_used_variable)
892
+ REQUIRE (lit < external->max_var, "lit of undeclare variable");
893
+ if (!external->extended)
894
+ external->extend ();
895
+ external->conclude_sat ();
896
+ int res = external->ival (lit);
897
+ LOG_API_CALL_RETURNS (
898
+ "val", lit, use_default_value_for_declared_but_not_used_variable,
899
+ res);
900
+ assert (state () == SATISFIED);
901
+ assert (res == lit || res == -lit);
902
+ return res;
903
+ }
904
+
905
+ bool Solver::flip (int lit) {
906
+ TRACE ("flip", lit);
907
+ REQUIRE_VALID_STATE ();
908
+ REQUIRE_VALID_LIT (lit);
909
+ REQUIRE (state () == SATISFIED, "can only flip value in satisfied state");
910
+ REQUIRE (!external->propagator,
911
+ "can only flip when no external propagator is present");
912
+ bool res = external->flip (lit);
913
+ LOG_API_CALL_RETURNS ("flip", lit, res);
914
+ assert (state () == SATISFIED);
915
+ return res;
916
+ }
917
+
918
+ bool Solver::flippable (int lit) {
919
+ TRACE ("flippable", lit);
920
+ REQUIRE_VALID_STATE ();
921
+ REQUIRE_VALID_LIT (lit);
922
+ REQUIRE (state () == SATISFIED, "can only flip value in satisfied state");
923
+ REQUIRE (!external->propagator,
924
+ "can only flip when no external propagator is present");
925
+ bool res = external->flippable (lit);
926
+ LOG_API_CALL_RETURNS ("flippable", lit, res);
927
+ assert (state () == SATISFIED);
928
+ return res;
929
+ }
930
+
931
+ bool Solver::failed (int lit) {
932
+ TRACE ("failed", lit);
933
+ REQUIRE_VALID_STATE ();
934
+ REQUIRE_VALID_LIT (lit);
935
+ REQUIRE (state () == UNSATISFIED,
936
+ "can only get failed assumptions in unsatisfied state");
937
+ bool res = external->failed (lit);
938
+ LOG_API_CALL_RETURNS ("failed", lit, res);
939
+ assert (state () == UNSATISFIED);
940
+ return res;
941
+ }
942
+
943
+ bool Solver::constraint_failed () {
944
+ TRACE ("constraint_failed");
945
+ REQUIRE_VALID_STATE ();
946
+ REQUIRE (state () == UNSATISFIED,
947
+ "can only determine if constraint failed in unsatisfied state");
948
+ bool res = external->failed_constraint ();
949
+ LOG_API_CALL_RETURNS ("constraint_failed", res);
950
+ assert (state () == UNSATISFIED);
951
+ return res;
952
+ }
953
+
954
+ int Solver::fixed (int lit) const {
955
+ TRACE ("fixed", lit);
956
+ REQUIRE_VALID_STATE ();
957
+ REQUIRE_VALID_LIT (lit);
958
+ int res = external->fixed (lit);
959
+ LOG_API_CALL_RETURNS ("fixed", lit, res);
960
+ return res;
961
+ }
962
+
963
+ void Solver::phase (int lit) {
964
+ TRACE ("phase", lit);
965
+ REQUIRE_VALID_OR_SOLVING_STATE ();
966
+ REQUIRE_VALID_LIT (lit);
967
+ external->phase (lit);
968
+ LOG_API_CALL_END ("phase", lit);
969
+ }
970
+
971
+ void Solver::unphase (int lit) {
972
+ TRACE ("unphase", lit);
973
+ REQUIRE_VALID_OR_SOLVING_STATE ();
974
+ REQUIRE_VALID_LIT (lit);
975
+ external->unphase (lit);
976
+ LOG_API_CALL_END ("unphase", lit);
977
+ }
978
+
979
+ /*------------------------------------------------------------------------*/
980
+
981
+ void Solver::terminate () {
982
+ LOG_API_CALL_BEGIN ("terminate");
983
+ REQUIRE_VALID_OR_SOLVING_STATE ();
984
+ external->terminate ();
985
+ LOG_API_CALL_END ("terminate");
986
+ }
987
+
988
+ void Solver::connect_terminator (Terminator *terminator) {
989
+ LOG_API_CALL_BEGIN ("connect_terminator");
990
+ REQUIRE_VALID_STATE ();
991
+ REQUIRE (terminator, "can not connect zero terminator");
992
+ #ifdef LOGGING
993
+ if (external->terminator)
994
+ LOG ("connecting new terminator (disconnecting previous one)");
995
+ else
996
+ LOG ("connecting new terminator (no previous one)");
997
+ #endif
998
+ external->terminator = terminator;
999
+ LOG_API_CALL_END ("connect_terminator");
1000
+ }
1001
+
1002
+ void Solver::disconnect_terminator () {
1003
+ LOG_API_CALL_BEGIN ("disconnect_terminator");
1004
+ REQUIRE_VALID_STATE ();
1005
+ #ifdef LOGGING
1006
+ if (external->terminator)
1007
+ LOG ("disconnecting previous terminator");
1008
+ else
1009
+ LOG ("ignoring to disconnect terminator (no previous one)");
1010
+ #endif
1011
+ external->terminator = 0;
1012
+ LOG_API_CALL_END ("disconnect_terminator");
1013
+ }
1014
+
1015
+ /*------------------------------------------------------------------------*/
1016
+
1017
+ void Solver::connect_learner (Learner *learner) {
1018
+ LOG_API_CALL_BEGIN ("connect_learner");
1019
+ REQUIRE_VALID_STATE ();
1020
+ REQUIRE (learner, "can not connect zero learner");
1021
+ #ifdef LOGGING
1022
+ if (external->learner)
1023
+ LOG ("connecting new learner (disconnecting previous one)");
1024
+ else
1025
+ LOG ("connecting new learner (no previous one)");
1026
+ #endif
1027
+ external->learner = learner;
1028
+ LOG_API_CALL_END ("connect_learner");
1029
+ }
1030
+
1031
+ void Solver::disconnect_learner () {
1032
+ LOG_API_CALL_BEGIN ("disconnect_learner");
1033
+ REQUIRE_VALID_STATE ();
1034
+ #ifdef LOGGING
1035
+ if (external->learner)
1036
+ LOG ("disconnecting previous learner");
1037
+ else
1038
+ LOG ("ignoring to disconnect learner (no previous one)");
1039
+ #endif
1040
+ external->learner = 0;
1041
+ LOG_API_CALL_END ("disconnect_learner");
1042
+ }
1043
+
1044
+ /*===== IPASIR END =======================================================*/
1045
+
1046
+ void Solver::connect_fixed_listener (
1047
+ FixedAssignmentListener *fixed_listener) {
1048
+ LOG_API_CALL_BEGIN ("connect_fixed_listener");
1049
+ REQUIRE_VALID_STATE ();
1050
+ REQUIRE (fixed_listener, "can not connect zero fixed listener");
1051
+
1052
+ #ifdef LOGGING
1053
+ if (external->fixed_listener)
1054
+ LOG ("connecting new listener of fixed assignments (disconnecting "
1055
+ "previous one)");
1056
+ else
1057
+ LOG ("connecting new listener of fixed assigments (no previous one)");
1058
+ #endif
1059
+ if (external->fixed_listener)
1060
+ disconnect_fixed_listener ();
1061
+ external->fixed_listener = fixed_listener;
1062
+ // Listeners are treated as real-time listeners, thus previously found
1063
+ // fixed assignments are not sent out (would be rather expensive to
1064
+ // recover it retrospect, see external_propagate.cpp/get_fixed_literals ()
1065
+ // function).
1066
+ LOG_API_CALL_END ("connect_fixed_listener");
1067
+ }
1068
+
1069
+ void Solver::disconnect_fixed_listener () {
1070
+ LOG_API_CALL_BEGIN ("disconnect_fixed_listener");
1071
+ REQUIRE_VALID_STATE ();
1072
+ #ifdef LOGGING
1073
+ if (external->fixed_listener)
1074
+ LOG ("disconnecting previous listener of fixed assignments");
1075
+ else
1076
+ LOG ("ignoring to disconnect listener of fixed assignments (no "
1077
+ "previous one)");
1078
+ #endif
1079
+ external->fixed_listener = 0;
1080
+ LOG_API_CALL_END ("disconnect_fixed_listener");
1081
+ }
1082
+
1083
+ /*===== IPASIR-UP BEGIN ==================================================*/
1084
+
1085
+ void Solver::connect_external_propagator (ExternalPropagator *propagator) {
1086
+ LOG_API_CALL_BEGIN ("connect_external_propagator");
1087
+ REQUIRE_VALID_STATE ();
1088
+ REQUIRE (propagator, "can not connect zero propagator");
1089
+ REQUIRE (!external->propagator,
1090
+ "can not connect more than one propagator");
1091
+
1092
+ if (external->propagator)
1093
+ disconnect_external_propagator ();
1094
+
1095
+ external->propagator = propagator;
1096
+ internal->connect_propagator ();
1097
+ internal->external_prop = true;
1098
+ internal->external_prop_is_lazy = propagator->is_lazy;
1099
+ LOG_API_CALL_END ("connect_external_propagator");
1100
+ }
1101
+
1102
+ void Solver::disconnect_external_propagator () {
1103
+ LOG_API_CALL_BEGIN ("disconnect_external_propagator");
1104
+ REQUIRE_VALID_STATE ();
1105
+ REQUIRE (external->propagator,
1106
+ "can not disconnect propagator without a connected propagator");
1107
+ external->reset_observed_vars ();
1108
+
1109
+ external->propagator = 0;
1110
+ internal->set_changed_val ();
1111
+ internal->external_prop = false;
1112
+ internal->external_prop_is_lazy = true;
1113
+ internal->notified = 0;
1114
+ LOG_API_CALL_END ("disconnect_external_propagator");
1115
+ }
1116
+
1117
+ void Solver::add_observed_var (int idx) {
1118
+ TRACE ("observe", idx);
1119
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1120
+ REQUIRE_VALID_LIT (idx);
1121
+ REQUIRE (external->propagator,
1122
+ "can not observe variables without a connected propagator");
1123
+ external->add_observed_var (idx);
1124
+ LOG_API_CALL_END ("observe", idx);
1125
+ }
1126
+
1127
+ void Solver::remove_observed_var (int idx) {
1128
+ TRACE ("unobserve", idx);
1129
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1130
+ REQUIRE_VALID_LIT (idx);
1131
+ REQUIRE (external->propagator,
1132
+ "can not unobserve variables without a connected propagator");
1133
+ external->remove_observed_var (idx);
1134
+ LOG_API_CALL_END ("unobserve", idx);
1135
+ }
1136
+
1137
+ void Solver::reset_observed_vars () {
1138
+ TRACE ("reset_observed_vars");
1139
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1140
+ REQUIRE (
1141
+ external->propagator,
1142
+ "can not reset observed variables without a connected propagator");
1143
+ external->reset_observed_vars ();
1144
+ LOG_API_CALL_END ("reset_observed_vars");
1145
+ }
1146
+
1147
+ /*===== IPASIR-UP END ====================================================*/
1148
+
1149
+ int Solver::active () const {
1150
+ TRACE ("active");
1151
+ REQUIRE_VALID_STATE ();
1152
+ int res = internal->active ();
1153
+ LOG_API_CALL_RETURNS ("active", res);
1154
+ return res;
1155
+ }
1156
+
1157
+ int64_t Solver::redundant () const {
1158
+ TRACE ("redundant");
1159
+ REQUIRE_VALID_STATE ();
1160
+ int64_t res = internal->redundant ();
1161
+ LOG_API_CALL_RETURNS ("redundant", res);
1162
+ return res;
1163
+ }
1164
+
1165
+ int64_t Solver::irredundant () const {
1166
+ TRACE ("irredundant");
1167
+ REQUIRE_VALID_STATE ();
1168
+ int64_t res = internal->irredundant ();
1169
+ LOG_API_CALL_RETURNS ("irredundant", res);
1170
+ return res;
1171
+ }
1172
+
1173
+ /*------------------------------------------------------------------------*/
1174
+
1175
+ void Solver::freeze (int lit) {
1176
+ TRACE ("freeze", lit);
1177
+ REQUIRE_VALID_STATE ();
1178
+ REQUIRE_VALID_LIT (lit);
1179
+ external->freeze (lit);
1180
+ LOG_API_CALL_END ("freeze", lit);
1181
+ }
1182
+
1183
+ void Solver::melt (int lit) {
1184
+ TRACE ("melt", lit);
1185
+ REQUIRE_VALID_STATE ();
1186
+ REQUIRE_VALID_LIT (lit);
1187
+ REQUIRE (external->frozen (lit),
1188
+ "can not melt completely melted literal '%d'", lit);
1189
+ external->melt (lit);
1190
+ LOG_API_CALL_END ("melt", lit);
1191
+ }
1192
+
1193
+ bool Solver::frozen (int lit) const {
1194
+ TRACE ("frozen", lit);
1195
+ REQUIRE_VALID_STATE ();
1196
+ REQUIRE_VALID_LIT (lit);
1197
+ bool res = external->frozen (lit);
1198
+ LOG_API_CALL_RETURNS ("frozen", lit, res);
1199
+ return res;
1200
+ }
1201
+
1202
+ /*------------------------------------------------------------------------*/
1203
+
1204
+ bool Solver::trace_proof (FILE *external_file, const char *name) {
1205
+ TRACE ("trace_proof", name);
1206
+ REQUIRE_VALID_STATE ();
1207
+ REQUIRE (
1208
+ state () == CONFIGURING,
1209
+ "can only start proof tracing to '%s' right after initialization",
1210
+ name);
1211
+ File *internal_file = File::write (internal, external_file, name);
1212
+ assert (internal_file);
1213
+ internal->trace (internal_file);
1214
+ LOG_API_CALL_RETURNS ("trace_proof", name, true);
1215
+ return true;
1216
+ }
1217
+
1218
+ bool Solver::trace_proof (const char *path) {
1219
+ TRACE ("trace_proof", path);
1220
+ REQUIRE_VALID_STATE ();
1221
+ REQUIRE (
1222
+ state () == CONFIGURING,
1223
+ "can only start proof tracing to '%s' right after initialization",
1224
+ path);
1225
+ File *internal_file = File::write (internal, path);
1226
+ bool res = (internal_file != 0);
1227
+ internal->trace (internal_file);
1228
+ LOG_API_CALL_RETURNS ("trace_proof", path, res);
1229
+ return res;
1230
+ }
1231
+
1232
+ void Solver::flush_proof_trace (bool print_statistics_unless_quiet) {
1233
+ TRACE ("flush_proof_trace");
1234
+ REQUIRE_VALID_STATE ();
1235
+ REQUIRE (!internal->file_tracers.empty (), "proof is not traced");
1236
+ REQUIRE (!internal->file_tracers.back ()->closed (),
1237
+ "proof trace already closed");
1238
+ internal->flush_trace (print_statistics_unless_quiet);
1239
+ LOG_API_CALL_END ("flush_proof_trace");
1240
+ }
1241
+
1242
+ void Solver::close_proof_trace (bool print_statistics_unless_quiet) {
1243
+ TRACE ("close_proof_trace");
1244
+ REQUIRE_VALID_STATE ();
1245
+ REQUIRE (!internal->file_tracers.empty (), "proof is not traced");
1246
+ REQUIRE (!internal->file_tracers.back ()->closed (),
1247
+ "proof trace already closed");
1248
+ internal->close_trace (print_statistics_unless_quiet);
1249
+ LOG_API_CALL_END ("close_proof_trace");
1250
+ }
1251
+
1252
+ /*------------------------------------------------------------------------*/
1253
+
1254
+ void Solver::connect_proof_tracer (Tracer *tracer, bool antecedents,
1255
+ bool finalize_clauses) {
1256
+ LOG_API_CALL_BEGIN ("connect proof tracer");
1257
+ REQUIRE_VALID_STATE ();
1258
+ REQUIRE (state () == CONFIGURING,
1259
+ "can only start proof tracing to right after initialization");
1260
+ REQUIRE (tracer, "can not connect zero tracer");
1261
+ internal->connect_proof_tracer (tracer, antecedents, finalize_clauses);
1262
+ LOG_API_CALL_END ("connect proof tracer");
1263
+ }
1264
+
1265
+ void Solver::connect_proof_tracer (InternalTracer *tracer, bool antecedents,
1266
+ bool finalize_clauses) {
1267
+ LOG_API_CALL_BEGIN ("connect proof tracer");
1268
+ REQUIRE_VALID_STATE ();
1269
+ REQUIRE (state () == CONFIGURING,
1270
+ "can only start proof tracing to right after initialization");
1271
+ REQUIRE (tracer, "can not connect zero tracer");
1272
+ internal->connect_proof_tracer (tracer, antecedents, finalize_clauses);
1273
+ LOG_API_CALL_END ("connect proof tracer");
1274
+ }
1275
+
1276
+ void Solver::connect_proof_tracer (StatTracer *tracer, bool antecedents,
1277
+ bool finalize_clauses) {
1278
+ LOG_API_CALL_BEGIN ("connect proof tracer with stats");
1279
+ REQUIRE_VALID_STATE ();
1280
+ REQUIRE (state () == CONFIGURING,
1281
+ "can only start proof tracing to right after initialization");
1282
+ REQUIRE (tracer, "can not connect zero tracer");
1283
+ internal->connect_proof_tracer (tracer, antecedents, finalize_clauses);
1284
+ LOG_API_CALL_END ("connect proof tracer with stats");
1285
+ }
1286
+
1287
+ void Solver::connect_proof_tracer (FileTracer *tracer, bool antecedents,
1288
+ bool finalize_clauses) {
1289
+ LOG_API_CALL_BEGIN ("connect proof tracer with file");
1290
+ REQUIRE_VALID_STATE ();
1291
+ REQUIRE (state () == CONFIGURING,
1292
+ "can only start proof tracing right after initialization");
1293
+ REQUIRE (tracer, "can not connect zero tracer");
1294
+ internal->connect_proof_tracer (tracer, antecedents, finalize_clauses);
1295
+ LOG_API_CALL_END ("connect proof tracer with file");
1296
+ }
1297
+
1298
+ bool Solver::disconnect_proof_tracer (Tracer *tracer) {
1299
+ LOG_API_CALL_BEGIN ("disconnect proof tracer");
1300
+ REQUIRE_VALID_STATE ();
1301
+ REQUIRE (tracer, "can not disconnect zero tracer");
1302
+ bool res = internal->disconnect_proof_tracer (tracer);
1303
+ LOG_API_CALL_RETURNS ("connect proof tracer", res);
1304
+ return res;
1305
+ }
1306
+
1307
+ bool Solver::disconnect_proof_tracer (StatTracer *tracer) {
1308
+ LOG_API_CALL_BEGIN ("disconnect proof tracer");
1309
+ REQUIRE_VALID_STATE ();
1310
+ REQUIRE (tracer, "can not disconnect zero tracer");
1311
+ bool res = internal->disconnect_proof_tracer (tracer);
1312
+ LOG_API_CALL_RETURNS ("disconnect proof tracer", res);
1313
+ return res;
1314
+ }
1315
+
1316
+ bool Solver::disconnect_proof_tracer (FileTracer *tracer) {
1317
+ LOG_API_CALL_BEGIN ("disconnect proof tracer");
1318
+ REQUIRE_VALID_STATE ();
1319
+ REQUIRE (tracer, "can not disconnect zero tracer");
1320
+ bool res = internal->disconnect_proof_tracer (tracer);
1321
+ LOG_API_CALL_RETURNS ("disconnect proof tracer", res);
1322
+ return res;
1323
+ }
1324
+
1325
+ /*------------------------------------------------------------------------*/
1326
+
1327
+ void Solver::conclude () {
1328
+ TRACE ("conclude");
1329
+ REQUIRE_VALID_STATE ();
1330
+ REQUIRE (
1331
+ state () == UNSATISFIED || state () == SATISFIED ||
1332
+ state () == INCONCLUSIVE,
1333
+ "can only conclude in satisfied, unsatisfied or inconclusive state");
1334
+ if (state () == UNSATISFIED)
1335
+ internal->conclude_unsat ();
1336
+ else if (state () == SATISFIED)
1337
+ external->conclude_sat ();
1338
+ else if (state () == INCONCLUSIVE)
1339
+ external->conclude_unknown ();
1340
+ assert (state () == UNSATISFIED || state () == SATISFIED ||
1341
+ state () == INCONCLUSIVE);
1342
+ LOG_API_CALL_END ("conclude");
1343
+ }
1344
+
1345
+ /*------------------------------------------------------------------------*/
1346
+
1347
+ void Solver::build (FILE *file, const char *prefix) {
1348
+
1349
+ assert (file == stdout || file == stderr);
1350
+
1351
+ Terminal *terminal;
1352
+
1353
+ if (file == stdout)
1354
+ terminal = &tout;
1355
+ else if (file == stderr)
1356
+ terminal = &terr;
1357
+ else
1358
+ terminal = 0;
1359
+
1360
+ const char *v = CaDiCaL::version ();
1361
+ const char *i = identifier ();
1362
+ const char *c = compiler ();
1363
+ const char *b = date ();
1364
+ const char *f = flags ();
1365
+
1366
+ assert (v);
1367
+
1368
+ fputs (prefix, file);
1369
+ if (terminal)
1370
+ terminal->magenta ();
1371
+ fputs ("Version ", file);
1372
+ if (terminal)
1373
+ terminal->normal ();
1374
+ fputs (v, file);
1375
+ if (i) {
1376
+ if (terminal)
1377
+ terminal->magenta ();
1378
+ fputc (' ', file);
1379
+ fputs (i, file);
1380
+ if (terminal)
1381
+ terminal->normal ();
1382
+ }
1383
+ fputc ('\n', file);
1384
+
1385
+ if (c) {
1386
+ fputs (prefix, file);
1387
+ if (terminal)
1388
+ terminal->magenta ();
1389
+ fputs (c, file);
1390
+ if (f) {
1391
+ fputc (' ', file);
1392
+ fputs (f, file);
1393
+ }
1394
+ if (terminal)
1395
+ terminal->normal ();
1396
+ fputc ('\n', file);
1397
+ }
1398
+
1399
+ if (b) {
1400
+ fputs (prefix, file);
1401
+ if (terminal)
1402
+ terminal->magenta ();
1403
+ fputs (b, file);
1404
+ if (terminal)
1405
+ terminal->normal ();
1406
+ fputc ('\n', file);
1407
+ }
1408
+
1409
+ fflush (file);
1410
+ }
1411
+
1412
+ const char *Solver::version () { return CaDiCaL::version (); }
1413
+
1414
+ const char *Solver::signature () { return CaDiCaL::signature (); }
1415
+
1416
+ void Solver::options () {
1417
+ REQUIRE_VALID_STATE ();
1418
+ internal->opts.print ();
1419
+ }
1420
+
1421
+ void Solver::usage () { Options::usage (); }
1422
+
1423
+ void Solver::configurations () { Config::usage (); }
1424
+
1425
+ void Solver::statistics () {
1426
+ if (state () == DELETING)
1427
+ return;
1428
+ TRACE ("stats");
1429
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1430
+ internal->print_statistics ();
1431
+ LOG_API_CALL_END ("stats");
1432
+ }
1433
+
1434
+ void Solver::resources () {
1435
+ if (state () == DELETING)
1436
+ return;
1437
+ TRACE ("resources");
1438
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1439
+ internal->print_resource_usage ();
1440
+ LOG_API_CALL_END ("resources");
1441
+ }
1442
+
1443
+ /*------------------------------------------------------------------------*/
1444
+
1445
+ const char *Solver::read_dimacs (File *file, int &vars, int strict,
1446
+ bool *incremental, vector<int> *cubes) {
1447
+ REQUIRE_VALID_STATE ();
1448
+ REQUIRE (state () == CONFIGURING,
1449
+ "can only read DIMACS file right after initialization");
1450
+ Parser *parser = new Parser (this, file, incremental, cubes);
1451
+ const char *err = parser->parse_dimacs (vars, strict);
1452
+ delete parser;
1453
+ return err;
1454
+ }
1455
+
1456
+ const char *Solver::read_dimacs (FILE *external_file, const char *name,
1457
+ int &vars, int strict) {
1458
+ LOG_API_CALL_BEGIN ("read_dimacs", name);
1459
+ REQUIRE_VALID_STATE ();
1460
+ REQUIRE (state () == CONFIGURING,
1461
+ "can only read DIMACS file right after initialization");
1462
+ File *file = File::read (internal, external_file, name);
1463
+ assert (file);
1464
+ const char *err = read_dimacs (file, vars, strict);
1465
+ delete file;
1466
+ LOG_API_CALL_RETURNS ("read_dimacs", name, err);
1467
+ return err;
1468
+ }
1469
+
1470
+ const char *Solver::read_dimacs (const char *path, int &vars, int strict) {
1471
+ LOG_API_CALL_BEGIN ("read_dimacs", path);
1472
+ REQUIRE_VALID_STATE ();
1473
+ REQUIRE (state () == CONFIGURING,
1474
+ "can only read DIMACS file right after initialization");
1475
+ File *file = File::read (internal, path);
1476
+ if (!file)
1477
+ return internal->error_message.init ("failed to read DIMACS file '%s'",
1478
+ path);
1479
+ const char *err = read_dimacs (file, vars, strict);
1480
+ delete file;
1481
+ LOG_API_CALL_RETURNS ("read_dimacs", path, err);
1482
+ return err;
1483
+ }
1484
+
1485
+ const char *Solver::read_dimacs (FILE *external_file, const char *name,
1486
+ int &vars, int strict, bool &incremental,
1487
+ vector<int> &cubes) {
1488
+ LOG_API_CALL_BEGIN ("read_dimacs", name);
1489
+ REQUIRE_VALID_STATE ();
1490
+ REQUIRE (state () == CONFIGURING,
1491
+ "can only read DIMACS file right after initialization");
1492
+ File *file = File::read (internal, external_file, name);
1493
+ assert (file);
1494
+ const char *err = read_dimacs (file, vars, strict, &incremental, &cubes);
1495
+ delete file;
1496
+ LOG_API_CALL_RETURNS ("read_dimacs", name, err);
1497
+ return err;
1498
+ }
1499
+
1500
+ const char *Solver::read_dimacs (const char *path, int &vars, int strict,
1501
+ bool &incremental, vector<int> &cubes) {
1502
+ LOG_API_CALL_BEGIN ("read_dimacs", path);
1503
+ REQUIRE_VALID_STATE ();
1504
+ REQUIRE (state () == CONFIGURING,
1505
+ "can only read DIMACS file right after initialization");
1506
+ File *file = File::read (internal, path);
1507
+ if (!file)
1508
+ return internal->error_message.init ("failed to read DIMACS file '%s'",
1509
+ path);
1510
+ const char *err = read_dimacs (file, vars, strict, &incremental, &cubes);
1511
+ delete file;
1512
+ LOG_API_CALL_RETURNS ("read_dimacs", path, err);
1513
+ return err;
1514
+ }
1515
+
1516
+ const char *Solver::read_solution (const char *path) {
1517
+ LOG_API_CALL_BEGIN ("solution", path);
1518
+ REQUIRE_VALID_STATE ();
1519
+ File *file = File::read (internal, path);
1520
+ if (!file)
1521
+ return internal->error_message.init (
1522
+ "failed to read solution file '%s'", path);
1523
+ Parser *parser = new Parser (this, file, 0, 0);
1524
+ const char *err = parser->parse_solution ();
1525
+ delete parser;
1526
+ delete file;
1527
+ if (!err)
1528
+ external->check_assignment (&External::sol);
1529
+ LOG_API_CALL_RETURNS ("read_solution", path, err);
1530
+ return err;
1531
+ }
1532
+
1533
+ /*------------------------------------------------------------------------*/
1534
+
1535
+ void Solver::dump_cnf () {
1536
+ TRACE ("dump");
1537
+ REQUIRE_INITIALIZED ();
1538
+ internal->dump ();
1539
+ LOG_API_CALL_END ("dump");
1540
+ }
1541
+
1542
+ /*------------------------------------------------------------------------*/
1543
+
1544
+ ExternalPropagator *Solver::get_propagator () {
1545
+ return external->propagator;
1546
+ }
1547
+
1548
+ bool Solver::observed (int lit) {
1549
+ TRACE ("observed", lit);
1550
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1551
+ REQUIRE_VALID_LIT (lit);
1552
+ bool res = external->observed (lit);
1553
+ LOG_API_CALL_RETURNS ("observed", lit, res);
1554
+ return res;
1555
+ }
1556
+
1557
+ bool Solver::is_witness (int lit) {
1558
+ TRACE ("is_witness", lit);
1559
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1560
+ REQUIRE_VALID_LIT (lit);
1561
+ bool res = external->is_witness (lit);
1562
+ LOG_API_CALL_RETURNS ("is_witness", lit, res);
1563
+ return res;
1564
+ }
1565
+
1566
+ bool Solver::is_decision (int lit) {
1567
+ TRACE ("is_decision", lit);
1568
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1569
+ REQUIRE_VALID_LIT (lit);
1570
+ bool res = external->is_decision (lit);
1571
+ LOG_API_CALL_RETURNS ("is_decision", lit, res);
1572
+ return res;
1573
+ }
1574
+
1575
+ void Solver::force_backtrack (int new_level) {
1576
+ TRACE ("force_backtrack", new_level);
1577
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1578
+ REQUIRE (external->propagator,
1579
+ "can not force backtrack without a connected propagator");
1580
+ external->force_backtrack (new_level);
1581
+ }
1582
+
1583
+ /*------------------------------------------------------------------------*/
1584
+
1585
+ bool Solver::traverse_clauses (ClauseIterator &it) const {
1586
+ LOG_API_CALL_BEGIN ("traverse_clauses");
1587
+ REQUIRE_VALID_STATE ();
1588
+ bool res = external->traverse_all_frozen_units_as_clauses (it) &&
1589
+ internal->traverse_clauses (it) &&
1590
+ internal->traverse_constraint (it);
1591
+ LOG_API_CALL_RETURNS ("traverse_clauses", res);
1592
+ return res;
1593
+ }
1594
+
1595
+ bool Solver::traverse_witnesses_backward (WitnessIterator &it) const {
1596
+ LOG_API_CALL_BEGIN ("traverse_witnesses_backward");
1597
+ REQUIRE_VALID_STATE ();
1598
+ bool res = external->traverse_all_non_frozen_units_as_witnesses (it) &&
1599
+ external->traverse_witnesses_backward (it);
1600
+ LOG_API_CALL_RETURNS ("traverse_witnesses_backward", res);
1601
+ return res;
1602
+ }
1603
+
1604
+ bool Solver::traverse_witnesses_forward (WitnessIterator &it) const {
1605
+ LOG_API_CALL_BEGIN ("traverse_witnesses_forward");
1606
+ REQUIRE_VALID_STATE ();
1607
+ bool res = external->traverse_witnesses_forward (it) &&
1608
+ external->traverse_all_non_frozen_units_as_witnesses (it);
1609
+ LOG_API_CALL_RETURNS ("traverse_witnesses_forward", res);
1610
+ return res;
1611
+ }
1612
+
1613
+ /*------------------------------------------------------------------------*/
1614
+
1615
+ class ClauseCounter : public ClauseIterator {
1616
+ public:
1617
+ int vars;
1618
+ int64_t clauses;
1619
+ ClauseCounter () : vars (0), clauses (0) {}
1620
+ bool clause (const vector<int> &c) {
1621
+ for (const auto &lit : c) {
1622
+ assert (lit != INT_MIN);
1623
+ int idx = abs (lit);
1624
+ if (idx > vars)
1625
+ vars = idx;
1626
+ }
1627
+ clauses++;
1628
+ return true;
1629
+ }
1630
+ };
1631
+
1632
+ class ClauseWriter : public ClauseIterator {
1633
+ File *file;
1634
+
1635
+ public:
1636
+ ClauseWriter (File *f) : file (f) {}
1637
+ bool clause (const vector<int> &c) {
1638
+ for (const auto &lit : c) {
1639
+ if (!file->put (lit))
1640
+ return false;
1641
+ if (!file->put (' '))
1642
+ return false;
1643
+ }
1644
+ return file->put ("0\n");
1645
+ }
1646
+ };
1647
+
1648
+ const char *Solver::write_dimacs (const char *path, int min_max_var) {
1649
+ LOG_API_CALL_BEGIN ("write_dimacs", path, min_max_var);
1650
+ REQUIRE_VALID_STATE ();
1651
+ #ifndef QUIET
1652
+ const double start = internal->time ();
1653
+ #endif
1654
+ internal->restore_clauses ();
1655
+ ClauseCounter counter;
1656
+ (void) traverse_clauses (counter);
1657
+ LOG ("found maximal variable %d and %" PRId64 " clauses", counter.vars,
1658
+ counter.clauses);
1659
+ File *file = File::write (internal, path);
1660
+ const char *res = 0;
1661
+ if (file) {
1662
+ int actual_max_vars = max (min_max_var, counter.vars);
1663
+ MSG ("writing %s'p cnf %d %" PRId64 "'%s header", tout.green_code (),
1664
+ actual_max_vars, counter.clauses, tout.normal_code ());
1665
+ file->put ("p cnf ");
1666
+ file->put (actual_max_vars);
1667
+ file->put (' ');
1668
+ file->put (counter.clauses);
1669
+ file->put ('\n');
1670
+ ClauseWriter writer (file);
1671
+ if (!traverse_clauses (writer))
1672
+ res = internal->error_message.init (
1673
+ "writing to DIMACS file '%s' failed", path);
1674
+ delete file;
1675
+ } else
1676
+ res = internal->error_message.init (
1677
+ "failed to open DIMACS file '%s' for writing", path);
1678
+ #ifndef QUIET
1679
+ if (!res) {
1680
+ const double end = internal->time ();
1681
+ MSG ("wrote %" PRId64 " clauses in %.2f seconds %s time",
1682
+ counter.clauses, end - start,
1683
+ internal->opts.realtime ? "real" : "process");
1684
+ }
1685
+ #endif
1686
+ LOG_API_CALL_RETURNS ("write_dimacs", path, min_max_var, res);
1687
+ return res;
1688
+ }
1689
+
1690
+ /*------------------------------------------------------------------------*/
1691
+
1692
+ struct WitnessWriter : public WitnessIterator {
1693
+ File *file;
1694
+ int64_t witnesses;
1695
+ WitnessWriter (File *f) : file (f), witnesses (0) {}
1696
+ bool write (const vector<int> &a) {
1697
+ for (const auto &lit : a) {
1698
+ if (!file->put (lit))
1699
+ return false;
1700
+ if (!file->put (' '))
1701
+ return false;
1702
+ }
1703
+ return file->put ('0');
1704
+ }
1705
+ bool witness (const vector<int> &c, const vector<int> &w, int64_t) {
1706
+ if (!write (c))
1707
+ return false;
1708
+ if (!file->put (' '))
1709
+ return false;
1710
+ if (!write (w))
1711
+ return false;
1712
+ if (!file->put ('\n'))
1713
+ return false;
1714
+ witnesses++;
1715
+ return true;
1716
+ }
1717
+ };
1718
+
1719
+ const char *Solver::write_extension (const char *path) {
1720
+ LOG_API_CALL_BEGIN ("write_extension", path);
1721
+ REQUIRE_VALID_STATE ();
1722
+ const char *res = 0;
1723
+ #ifndef QUIET
1724
+ const double start = internal->time ();
1725
+ #endif
1726
+ File *file = File::write (internal, path);
1727
+ WitnessWriter writer (file);
1728
+ if (file) {
1729
+ if (!traverse_witnesses_backward (writer))
1730
+ res = internal->error_message.init (
1731
+ "writing to DIMACS file '%s' failed", path);
1732
+ delete file;
1733
+ } else
1734
+ res = internal->error_message.init (
1735
+ "failed to open extension file '%s' for writing", path);
1736
+ #ifndef QUIET
1737
+ if (!res) {
1738
+ const double end = internal->time ();
1739
+ MSG ("wrote %" PRId64 " witnesses in %.2f seconds %s time",
1740
+ writer.witnesses, end - start,
1741
+ internal->opts.realtime ? "real" : "process");
1742
+ }
1743
+ #endif
1744
+ LOG_API_CALL_RETURNS ("write_extension", path, res);
1745
+ return res;
1746
+ }
1747
+
1748
+ /*------------------------------------------------------------------------*/
1749
+
1750
+ struct ClauseCopier : public ClauseIterator {
1751
+ Solver &dst;
1752
+
1753
+ public:
1754
+ ClauseCopier (Solver &d) : dst (d) {}
1755
+ bool clause (const vector<int> &c) {
1756
+ for (const auto &lit : c)
1757
+ dst.add (lit);
1758
+ dst.add (0);
1759
+ return true;
1760
+ }
1761
+ };
1762
+
1763
+ struct WitnessCopier : public WitnessIterator {
1764
+ External *dst;
1765
+
1766
+ public:
1767
+ WitnessCopier (External *d) : dst (d) {}
1768
+ bool witness (const vector<int> &c, const vector<int> &w, int64_t id) {
1769
+ dst->push_external_clause_and_witness_on_extension_stack (c, w, id);
1770
+ return true;
1771
+ }
1772
+ };
1773
+
1774
+ void Solver::copy (Solver &other) const {
1775
+ REQUIRE_READY_STATE ();
1776
+ REQUIRE (other.state () & CONFIGURING, "target solver already modified");
1777
+ internal->opts.copy (other.internal->opts);
1778
+ ClauseCopier clause_copier (other);
1779
+ traverse_clauses (clause_copier);
1780
+ WitnessCopier witness_copier (other.external);
1781
+ traverse_witnesses_forward (witness_copier);
1782
+ external->copy_flags (*other.external);
1783
+ }
1784
+
1785
+ /*------------------------------------------------------------------------*/
1786
+
1787
+ void Solver::section (const char *title) {
1788
+ if (state () == DELETING)
1789
+ return;
1790
+ #ifdef QUIET
1791
+ (void) title;
1792
+ #endif
1793
+ REQUIRE_INITIALIZED ();
1794
+ SECTION (title);
1795
+ }
1796
+
1797
+ void Solver::message (const char *fmt, ...) {
1798
+ if (state () == DELETING)
1799
+ return;
1800
+ #ifdef QUIET
1801
+ (void) fmt;
1802
+ #else
1803
+ REQUIRE_INITIALIZED ();
1804
+ va_list ap;
1805
+ va_start (ap, fmt);
1806
+ internal->vmessage (fmt, ap);
1807
+ va_end (ap);
1808
+ #endif
1809
+ }
1810
+
1811
+ void Solver::message () {
1812
+ if (state () == DELETING)
1813
+ return;
1814
+ REQUIRE_INITIALIZED ();
1815
+ #ifndef QUIET
1816
+ internal->message ();
1817
+ #endif
1818
+ }
1819
+
1820
+ void Solver::verbose (int level, const char *fmt, ...) {
1821
+ if (state () == DELETING)
1822
+ return;
1823
+ REQUIRE_VALID_OR_SOLVING_STATE ();
1824
+ #ifdef QUIET
1825
+ (void) level;
1826
+ (void) fmt;
1827
+ #else
1828
+ va_list ap;
1829
+ va_start (ap, fmt);
1830
+ internal->vverbose (level, fmt, ap);
1831
+ va_end (ap);
1832
+ #endif
1833
+ }
1834
+
1835
+ void Solver::error (const char *fmt, ...) {
1836
+ if (state () == DELETING)
1837
+ return;
1838
+ REQUIRE_INITIALIZED ();
1839
+ va_list ap;
1840
+ va_start (ap, fmt);
1841
+ internal->verror (fmt, ap);
1842
+ va_end (ap);
1843
+ }
1844
+
1845
+ int64_t Solver::get_statistic_value (const char *opt) const {
1846
+ REQUIRE_INITIALIZED ();
1847
+ if (!strcmp (opt, "conflicts"))
1848
+ return internal->stats.conflicts;
1849
+ if (!strcmp (opt, "decisions"))
1850
+ return internal->stats.decisions;
1851
+ if (!strcmp (opt, "ticks"))
1852
+ return internal->stats.ticks.search[0] +
1853
+ internal->stats.ticks.search[1];
1854
+ if (!strcmp (opt, "propagations"))
1855
+ return internal->stats.propagations.search;
1856
+ if (!strcmp (opt, "clauses"))
1857
+ return internal->stats.current.total;
1858
+ if (!strcmp (opt, "redundant"))
1859
+ return internal->stats.current.redundant;
1860
+ if (!strcmp (opt, "irredundant"))
1861
+ return internal->stats.current.irredundant;
1862
+ if (!strcmp (opt, "fixed"))
1863
+ return internal->stats.all.fixed;
1864
+ if (!strcmp (opt, "eliminated"))
1865
+ return internal->stats.all.eliminated +
1866
+ internal->stats.all.fasteliminated;
1867
+ if (!strcmp (opt, "subsitutued"))
1868
+ return internal->stats.all.substituted;
1869
+ return -1;
1870
+ }
1871
+ } // namespace CaDiCaL