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,1026 @@
1
+ /*------------------------------------------------------------------------*/
2
+
3
+ // Do include 'internal.hpp' but try to minimize internal dependencies.
4
+
5
+ #include "internal.hpp"
6
+ #include "signal.hpp" // Separate, only need for apps.
7
+
8
+ /*------------------------------------------------------------------------*/
9
+
10
+ namespace CaDiCaL {
11
+
12
+ // A wrapper app which makes up the CaDiCaL stand alone solver. It in
13
+ // essence only consists of the 'App::main' function. So this class
14
+ // contains code, which is not required if only the library interface in
15
+ // the class 'Solver' is used (defined in 'cadical.hpp'). It further uses
16
+ // static data structures in order to have a signal handler catch signals.
17
+ //
18
+ // It is thus neither thread-safe nor reentrant. If you want to use
19
+ // multiple instances of the solver use the 'Solver' interface directly
20
+ // which is thread-safe and reentrant among different solver instances.
21
+
22
+ /*------------------------------------------------------------------------*/
23
+
24
+ class App : public Handler, public Terminator {
25
+
26
+ Solver *solver; // Global solver.
27
+
28
+ #ifndef _WIN32
29
+ // Command line options.
30
+ //
31
+ int time_limit; // '-t <sec>'
32
+ #endif
33
+
34
+ // Strictness of (DIMACS) parsing:
35
+ //
36
+ // 0 = force parsing and completely ignore header
37
+ // 1 = relaxed header handling (default)
38
+ // 2 = strict header handling
39
+ //
40
+ // To use '0' use '-f' of '--force'.
41
+ // To use '2' use '--strict'.
42
+ //
43
+ int force_strict_parsing;
44
+
45
+ bool force_writing;
46
+ static bool most_likely_existing_cnf_file (const char *path);
47
+
48
+ // Internal variables.
49
+ //
50
+ int max_var; // Set after parsing.
51
+ volatile bool timesup; // Asynchronous termination.
52
+
53
+ // Printing.
54
+ //
55
+ void print_usage (bool all = false);
56
+ void print_witness (FILE *);
57
+
58
+ #ifndef QUIET
59
+ void signal_message (const char *msg, int sig);
60
+ #endif
61
+
62
+ // Option handling.
63
+ //
64
+ bool set (const char *);
65
+ bool set (const char *, int);
66
+ int get (const char *);
67
+ bool verbose () { return get ("verbose") && !get ("quiet"); }
68
+
69
+ /*----------------------------------------------------------------------*/
70
+
71
+ // The actual initialization.
72
+ //
73
+ void init ();
74
+
75
+ // Terminator interface.
76
+ //
77
+ bool terminate () { return timesup; }
78
+
79
+ // Handler interface.
80
+ //
81
+ void catch_signal (int sig);
82
+ void catch_alarm ();
83
+
84
+ public:
85
+ App ();
86
+ ~App ();
87
+
88
+ // Parse the arguments and run the solver.
89
+ //
90
+ int main (int arg, char **argv);
91
+ };
92
+
93
+ /*------------------------------------------------------------------------*/
94
+
95
+ // clang-format off
96
+
97
+ void App::print_usage (bool all) {
98
+ printf (
99
+
100
+ "usage: cadical [ <option> ... ] [ <input> [ <proof> ] ]\n"
101
+ "\n"
102
+ "where '<option>' is one of the following common options:\n"
103
+ "\n"
104
+ );
105
+
106
+ if (!all) { // Print only a short list of common options.
107
+ printf (
108
+
109
+ " -h print this short list of common options\n"
110
+ " --help print complete list of all options\n"
111
+ " --version print version\n"
112
+ "\n"
113
+ " -n do not print witness\n"
114
+ #ifndef QUIET
115
+ " -v increase verbosity\n"
116
+ " -q be quiet\n"
117
+ #endif
118
+ "\n"
119
+ #ifndef _WIN32
120
+ " -t <sec> set wall clock time limit\n"
121
+ #endif
122
+
123
+ );
124
+ } else { // Print complete list of all options.
125
+ printf (
126
+
127
+ " -h print alternatively only a list of common options\n"
128
+ " --help print this complete list of all options\n"
129
+ " --version print version\n"
130
+ "\n"
131
+ " -n do not print witness (same as '--no-witness')\n"
132
+ #ifndef QUIET
133
+ " -v increase verbosity (see also '--verbose' below)\n"
134
+ " -q be quiet (same as '--quiet')\n"
135
+ #endif
136
+ #ifndef _WIN32
137
+ " -t <sec> set wall clock time limit\n"
138
+ #endif
139
+ "\n"
140
+ "Or '<option>' is one of the less common options\n"
141
+ "\n"
142
+ " -L<rounds> run local search initially (default '0' rounds)\n"
143
+ " -O<level> increase limits by '2^<level>' or '10^<level>'\n"
144
+ " -P<rounds> initial preprocessing (default '0' rounds)\n"
145
+ "\n"
146
+ "Note there is no separating space for the options above while the\n"
147
+ "following options require a space after the option name:\n"
148
+ "\n"
149
+ " -c <limit> limit the number of conflicts (default unlimited)\n"
150
+ " -d <limit> limit the number of decisions (default unlimited)\n"
151
+ "\n"
152
+ " -o <output> write simplified CNF in DIMACS format to file\n"
153
+ " -e <extend> write reconstruction/extension stack to file\n"
154
+ #ifdef LOGGING
155
+ " -l enable logging messages (same as '--log')\n"
156
+ #endif
157
+ "\n"
158
+ " --force | -f parsing broken DIMACS header and writing proofs\n"
159
+ " --strict strict parsing (no white space in header)\n"
160
+ "\n"
161
+ " -r <sol> read solution in competition output format\n"
162
+ " to check consistency of learned clauses\n"
163
+ " during testing and debugging\n"
164
+ "\n"
165
+ " -w <sol> write result including a potential witness\n"
166
+ " solution in competition format to the given "
167
+ "file\n"
168
+ "\n"
169
+ " --colors force colored output\n"
170
+ " --no-colors disable colored output to terminal\n"
171
+ " --no-witness do not print witness (see also '-n' above)\n"
172
+ "\n"
173
+ " --build print build configuration\n"
174
+ " --copyright print copyright information\n");
175
+
176
+ printf (
177
+
178
+ "\n"
179
+ "There are pre-defined configurations of advanced internal options:\n"
180
+ "\n"
181
+
182
+ );
183
+
184
+ solver->configurations ();
185
+
186
+ printf (
187
+ "\n"
188
+ "Or '<option>' is one of the following advanced internal options:\n"
189
+ "\n"
190
+ );
191
+
192
+ solver->usage ();
193
+
194
+ printf (
195
+
196
+ "\n"
197
+ "The internal options have their default value printed in brackets\n"
198
+ "after their description. They can also be used in the form\n"
199
+ "'--<name>' which is equivalent to '--<name>=1' and in the form\n"
200
+ "'--no-<name>' which is equivalent to '--<name>=0'. One can also\n"
201
+ "use 'true' instead of '1', 'false' instead of '0', as well as\n"
202
+ "numbers with positive exponent such as '1e3' instead of '1000'.\n"
203
+ "\n"
204
+ "Alternatively option values can also be specified in the header\n"
205
+ "of the DIMACS file, e.g., 'c --elim=false', or through environment\n"
206
+ "variables, such as 'CADICAL_ELIM=false'. The embedded options in\n"
207
+ "the DIMACS file have highest priority, followed by command line\n"
208
+ "options and then values specified through environment variables.\n"
209
+
210
+ );
211
+ }
212
+
213
+ //------------------------------------------------------------------------
214
+ // Common to both complete and common option usage.
215
+
216
+ printf (
217
+
218
+ "\n"
219
+ "The input is read from '<input>' assumed to be in DIMACS format.\n"
220
+ "Incremental 'p inccnf' files are supported too with cubes at the end.\n"
221
+ "If '<proof>' is given then a DRAT proof is written to that file.\n"
222
+
223
+ );
224
+
225
+ //------------------------------------------------------------------------
226
+ // More explanations for complete option usage.
227
+
228
+ if (all) {
229
+ printf (
230
+
231
+ "\n"
232
+ "If '<input>' is missing then the solver reads from '<stdin>',\n"
233
+ "also if '-' is used as input path name '<input>'. Similarly,\n"
234
+ "\n"
235
+ "For incremental files each cube is solved in turn. The solver\n"
236
+ "stops at the first satisfied cube if there is one and uses that\n"
237
+ "one for the witness to print. Conflict and decision limits are\n"
238
+ "applied to each individual cube solving call while '-P', '-L'"
239
+ #ifdef _WIN32
240
+ "\n"
241
+ #else
242
+ " and\n"
243
+ "'-t' "
244
+ #endif
245
+ "remain global. Only if all cubes were unsatisfiable the solver\n"
246
+ "prints the standard unsatisfiable solution line ('s UNSATISFIABLE').\n"
247
+ "\n"
248
+ "By default the proof is stored in the binary DRAT format unless\n"
249
+ "the option '--no-binary' is specified or the proof is written\n"
250
+ "to '<stdout>' and '<stdout>' is connected to a terminal.\n"
251
+ "\n"
252
+ "The input is assumed to be compressed if it is given explicitly\n"
253
+ "and has a '.gz', '.bz2', '.xz' or '.7z' suffix. The same applies\n"
254
+ "to the output file. In order to use compression and decompression\n"
255
+ "the corresponding utilities 'gzip', 'bzip', 'xz', and '7z' (depending\n"
256
+ "on the format) are required and need to be installed on the system.\n"
257
+ "The solver checks file type signatures though and falls back to\n"
258
+ "non-compressed file reading if the signature does not match.\n"
259
+
260
+ );
261
+ }
262
+ }
263
+
264
+ // clang-format on
265
+
266
+ /*------------------------------------------------------------------------*/
267
+
268
+ // Pretty print competition format witness with 'v' lines.
269
+
270
+ void App::print_witness (FILE *file) {
271
+ int c = 0, i = 0, tmp;
272
+ do {
273
+ if (!c)
274
+ fputc ('v', file), c = 1;
275
+ if (i++ == max_var)
276
+ tmp = 0;
277
+ else if (solver->external->ervars[i])
278
+ continue;
279
+ else
280
+ tmp = solver->val (i) < 0 ? -i : i;
281
+ char str[32];
282
+ snprintf (str, sizeof str, " %d", tmp);
283
+ int l = strlen (str);
284
+ if (c + l > 78)
285
+ fputs ("\nv", file), c = 1;
286
+ fputs (str, file);
287
+ c += l;
288
+ } while (tmp);
289
+ if (c)
290
+ fputc ('\n', file);
291
+ }
292
+
293
+ /*------------------------------------------------------------------------*/
294
+
295
+ // Wrapper around option setting.
296
+
297
+ int App::get (const char *o) { return solver->get (o); }
298
+ bool App::set (const char *o, int v) { return solver->set (o, v); }
299
+ bool App::set (const char *arg) { return solver->set_long_option (arg); }
300
+
301
+ /*------------------------------------------------------------------------*/
302
+
303
+ bool App::most_likely_existing_cnf_file (const char *path) {
304
+ if (!File::exists (path))
305
+ return false;
306
+
307
+ if (has_suffix (path, ".dimacs"))
308
+ return true;
309
+ if (has_suffix (path, ".dimacs.gz"))
310
+ return true;
311
+ if (has_suffix (path, ".dimacs.xz"))
312
+ return true;
313
+ if (has_suffix (path, ".dimacs.bz2"))
314
+ return true;
315
+ if (has_suffix (path, ".dimacs.7z"))
316
+ return true;
317
+ if (has_suffix (path, ".dimacs.lzma"))
318
+ return true;
319
+
320
+ if (has_suffix (path, ".cnf"))
321
+ return true;
322
+ if (has_suffix (path, ".cnf.gz"))
323
+ return true;
324
+ if (has_suffix (path, ".cnf.xz"))
325
+ return true;
326
+ if (has_suffix (path, ".cnf.bz2"))
327
+ return true;
328
+ if (has_suffix (path, ".cnf.7z"))
329
+ return true;
330
+ if (has_suffix (path, ".cnf.lzma"))
331
+ return true;
332
+
333
+ return false;
334
+ }
335
+
336
+ /*------------------------------------------------------------------------*/
337
+
338
+ // Short-cut for errors to avoid a hard 'exit'.
339
+
340
+ #define APPERR(...) \
341
+ do { \
342
+ solver->error (__VA_ARGS__); \
343
+ } while (0)
344
+
345
+ /*------------------------------------------------------------------------*/
346
+
347
+ int App::main (int argc, char **argv) {
348
+
349
+ // Handle options which lead to immediate exit first.
350
+
351
+ if (argc == 2) {
352
+ const char *arg = argv[1];
353
+ if (!strcmp (arg, "-h")) {
354
+ print_usage ();
355
+ return 0;
356
+ } else if (!strcmp (arg, "--help")) {
357
+ print_usage (true);
358
+ return 0;
359
+ } else if (!strcmp (arg, "--version")) {
360
+ printf ("%s\n", CaDiCaL::version ());
361
+ return 0;
362
+ } else if (!strcmp (arg, "--build")) {
363
+ tout.disable ();
364
+ Solver::build (stdout, "");
365
+ return 0;
366
+ } else if (!strcmp (arg, "--copyright")) {
367
+ printf ("%s\n", copyright ());
368
+ printf ("%s\n", authors ());
369
+ printf ("%s\n", affiliations ());
370
+ return 0;
371
+ }
372
+ }
373
+
374
+ // Now initialize solver.
375
+
376
+ init ();
377
+
378
+ // Set all argument option values to not used yet.
379
+
380
+ const char *preprocessing_specified = 0, *optimization_specified = 0;
381
+ const char *read_solution_path = 0, *write_result_path = 0;
382
+ const char *dimacs_path = 0, *proof_path = 0;
383
+ bool proof_specified = false, dimacs_specified = false;
384
+ int optimize = 0, preprocessing = 0, localsearch = 0;
385
+ const char *output_path = 0, *extension_path = 0;
386
+ int conflict_limit = -1, decision_limit = -1;
387
+ const char *conflict_limit_specified = 0;
388
+ const char *decision_limit_specified = 0;
389
+ const char *localsearch_specified = 0;
390
+ #ifndef __MINGW32__
391
+ const char *time_limit_specified = 0;
392
+ #endif
393
+ bool witness = true, less = false, status = true;
394
+ const char *dimacs_name, *err;
395
+
396
+ for (int i = 1; i < argc; i++) {
397
+ if (!strcmp (argv[i], "-h") || !strcmp (argv[i], "--help") ||
398
+ !strcmp (argv[i], "--build") || !strcmp (argv[i], "--version") ||
399
+ !strcmp (argv[i], "--copyright")) {
400
+ APPERR ("can only use '%s' as single first option", argv[i]);
401
+ } else if (!strcmp (argv[i], "-")) {
402
+ if (proof_specified)
403
+ APPERR ("too many arguments");
404
+ else if (!dimacs_specified)
405
+ dimacs_specified = true;
406
+ else
407
+ proof_specified = true;
408
+ } else if (!strcmp (argv[i], "-r")) {
409
+ if (++i == argc)
410
+ APPERR ("argument to '-r' missing");
411
+ else if (read_solution_path)
412
+ APPERR ("multiple read solution file options '-r %s' and '-r %s'",
413
+ read_solution_path, argv[i]);
414
+ else
415
+ read_solution_path = argv[i];
416
+ } else if (!strcmp (argv[i], "-w")) {
417
+ if (++i == argc)
418
+ APPERR ("argument to '-w' missing");
419
+ else if (write_result_path)
420
+ APPERR ("multiple solution file options '-w %s' and '-w %s'",
421
+ write_result_path, argv[i]);
422
+ else
423
+ write_result_path = argv[i];
424
+ } else if (!strcmp (argv[i], "-o")) {
425
+ if (++i == argc)
426
+ APPERR ("argument to '-o' missing");
427
+ else if (output_path)
428
+ APPERR ("multiple output file options '-o %s' and '-o %s'",
429
+ output_path, argv[i]);
430
+ else if (!force_writing && most_likely_existing_cnf_file (argv[i]))
431
+ APPERR ("output file '%s' most likely existing CNF (use '-f')",
432
+ argv[i]);
433
+ else if (!File::writable (argv[i]))
434
+ APPERR ("output file '%s' not writable", argv[i]);
435
+ else
436
+ output_path = argv[i];
437
+ } else if (!strcmp (argv[i], "-e")) {
438
+ if (++i == argc)
439
+ APPERR ("argument to '-e' missing");
440
+ else if (extension_path)
441
+ APPERR ("multiple extension file options '-e %s' and '-e %s'",
442
+ extension_path, argv[i]);
443
+ else if (!force_writing && most_likely_existing_cnf_file (argv[i]))
444
+ APPERR ("extension file '%s' most likely existing CNF (use '-f')",
445
+ argv[i]);
446
+ else if (!File::writable (argv[i]))
447
+ APPERR ("extension file '%s' not writable", argv[i]);
448
+ else
449
+ extension_path = argv[i];
450
+ } else if (is_color_option (argv[i])) {
451
+ tout.force_colors ();
452
+ terr.force_colors ();
453
+ } else if (is_no_color_option (argv[i])) {
454
+ tout.force_no_colors ();
455
+ terr.force_no_colors ();
456
+ } else if (!strcmp (argv[i], "--witness") ||
457
+ !strcmp (argv[i], "--witness=true") ||
458
+ !strcmp (argv[i], "--witness=1"))
459
+ witness = true;
460
+ else if (!strcmp (argv[i], "-n") || !strcmp (argv[i], "--no-witness") ||
461
+ !strcmp (argv[i], "--witness=false") ||
462
+ !strcmp (argv[i], "--witness=0"))
463
+ witness = false;
464
+ else if (!strcmp (argv[i], "--status") ||
465
+ !strcmp (argv[i], "--status=true") ||
466
+ !strcmp (argv[i], "--status=1"))
467
+ status = true;
468
+ else if (!strcmp (argv[i], "-n") || !strcmp (argv[i], "--no-status") ||
469
+ !strcmp (argv[i], "--status=false") ||
470
+ !strcmp (argv[i], "--status=0"))
471
+ status = false;
472
+ else if (!strcmp (argv[i], "--less")) { // EXPERIMENTAL!
473
+ if (less)
474
+ APPERR ("multiple '--less' options");
475
+ else if (!isatty (1))
476
+ APPERR ("'--less' without '<stdout>' connected to terminal");
477
+ else
478
+ less = true;
479
+ } else if (!strcmp (argv[i], "-c")) {
480
+ if (++i == argc)
481
+ APPERR ("argument to '-c' missing");
482
+ else if (conflict_limit_specified)
483
+ APPERR ("multiple conflict limits '-c %s' and '-c %s'",
484
+ conflict_limit_specified, argv[i]);
485
+ else if (!parse_int_str (argv[i], conflict_limit))
486
+ APPERR ("invalid argument in '-c %s'", argv[i]);
487
+ else if (conflict_limit < 0)
488
+ APPERR ("invalid conflict limit");
489
+ else
490
+ conflict_limit_specified = argv[i];
491
+ } else if (!strcmp (argv[i], "-d")) {
492
+ if (++i == argc)
493
+ APPERR ("argument to '-d' missing");
494
+ else if (decision_limit_specified)
495
+ APPERR ("multiple decision limits '-d %s' and '-d %s'",
496
+ decision_limit_specified, argv[i]);
497
+ else if (!parse_int_str (argv[i], decision_limit))
498
+ APPERR ("invalid argument in '-d %s'", argv[i]);
499
+ else if (decision_limit < 0)
500
+ APPERR ("invalid decision limit");
501
+ else
502
+ decision_limit_specified = argv[i];
503
+ }
504
+ #ifndef _WIN32
505
+ else if (!strcmp (argv[i], "-t")) {
506
+ if (++i == argc)
507
+ APPERR ("argument to '-t' missing");
508
+ else if (time_limit_specified)
509
+ APPERR ("multiple time limit '-t %s' and '-t %s'",
510
+ time_limit_specified, argv[i]);
511
+ else if (!parse_int_str (argv[i], time_limit))
512
+ APPERR ("invalid argument in '-d %s'", argv[i]);
513
+ else if (time_limit < 0)
514
+ APPERR ("invalid time limit");
515
+ else
516
+ time_limit_specified = argv[i];
517
+ }
518
+ #endif
519
+ #ifndef QUIET
520
+ else if (!strcmp (argv[i], "-q"))
521
+ set ("--quiet");
522
+ else if (!strcmp (argv[i], "-v"))
523
+ set ("verbose", get ("verbose") + 1);
524
+ #endif
525
+ #ifdef LOGGING
526
+ else if (!strcmp (argv[i], "-l"))
527
+ set ("--log");
528
+ #endif
529
+ else if (!strcmp (argv[i], "-f") || !strcmp (argv[i], "--force") ||
530
+ !strcmp (argv[i], "--force=1") ||
531
+ !strcmp (argv[i], "--force=true"))
532
+ force_strict_parsing = 0, force_writing = true;
533
+ else if (!strcmp (argv[i], "--strict") ||
534
+ !strcmp (argv[i], "--strict=1") ||
535
+ !strcmp (argv[i], "--strict=true"))
536
+ force_strict_parsing = 2;
537
+ else if (has_prefix (argv[i], "-O")) {
538
+ if (optimization_specified)
539
+ APPERR ("multiple optimization options '%s' and '%s'",
540
+ optimization_specified, argv[i]);
541
+ optimization_specified = argv[i];
542
+ if (!parse_int_str (argv[i] + 2, optimize))
543
+ APPERR ("invalid optimization option '%s'", argv[i]);
544
+ if (optimize < 0 || optimize > 31)
545
+ APPERR ("invalid argument in '%s' (expected '0..31')", argv[i]);
546
+ } else if (has_prefix (argv[i], "-P")) {
547
+ if (preprocessing_specified)
548
+ APPERR ("multiple preprocessing options '%s' and '%s'",
549
+ preprocessing_specified, argv[i]);
550
+ preprocessing_specified = argv[i];
551
+ if (!parse_int_str (argv[i] + 2, preprocessing))
552
+ APPERR ("invalid preprocessing option '%s'", argv[i]);
553
+ if (preprocessing < 0)
554
+ APPERR ("invalid argument in '%s' (expected non-negative number)",
555
+ argv[i]);
556
+ } else if (has_prefix (argv[i], "-L")) {
557
+ if (localsearch_specified)
558
+ APPERR ("multiple local search options '%s' and '%s'",
559
+ localsearch_specified, argv[i]);
560
+ localsearch_specified = argv[i];
561
+ if (!parse_int_str (argv[i] + 2, localsearch))
562
+ APPERR ("invalid local search option '%s'", argv[i]);
563
+ if (localsearch < 0)
564
+ APPERR ("invalid argument in '%s' (expected non-negative number)",
565
+ argv[i]);
566
+ } else if (has_prefix (argv[i], "--") &&
567
+ solver->is_valid_configuration (argv[i] + 2)) {
568
+ solver->configure (argv[i] + 2);
569
+ } else if (set (argv[i])) {
570
+ /* nothing do be done */
571
+ } else if (argv[i][0] == '-')
572
+ APPERR ("invalid option '%s'", argv[i]);
573
+ else if (proof_specified)
574
+ APPERR ("too many arguments");
575
+ else if (dimacs_specified) {
576
+ proof_path = argv[i];
577
+ proof_specified = true;
578
+ if (!force_writing && most_likely_existing_cnf_file (proof_path))
579
+ APPERR ("DRAT proof file '%s' most likely existing CNF (use '-f')",
580
+ proof_path);
581
+ else if (!File::writable (proof_path))
582
+ APPERR ("DRAT proof file '%s' not writable", proof_path);
583
+ } else
584
+ dimacs_specified = true, dimacs_path = argv[i];
585
+ }
586
+
587
+ /*----------------------------------------------------------------------*/
588
+
589
+ if (dimacs_specified && dimacs_path && !File::exists (dimacs_path))
590
+ APPERR ("DIMACS input file '%s' does not exist", dimacs_path);
591
+ if (read_solution_path && !File::exists (read_solution_path))
592
+ APPERR ("solution file '%s' does not exist", read_solution_path);
593
+ if (dimacs_specified && dimacs_path && proof_specified && proof_path &&
594
+ !strcmp (dimacs_path, proof_path) && strcmp (dimacs_path, "-"))
595
+ APPERR ("DIMACS input file '%s' also specified as DRAT proof file",
596
+ dimacs_path);
597
+
598
+ /*----------------------------------------------------------------------*/
599
+ // The '--less' option is not fully functional yet (it is also not
600
+ // mentioned in the 'usage' message yet). It only works as expected if
601
+ // you let the solver run until it exits. The goal is to have a similar
602
+ // experience as with 'git diff' if the terminal is too small for the
603
+ // printed messages, but this needs substantial hacking.
604
+ //
605
+ // TODO: add proper forking, waiting, signal catching & propagating ...
606
+ //
607
+ FILE *less_pipe;
608
+ if (less) {
609
+ assert (isatty (1));
610
+ less_pipe = popen ("less -r", "w");
611
+ if (!less_pipe)
612
+ APPERR ("could not execute and open pipe to 'less -r' command");
613
+ dup2 (fileno (less_pipe), 1);
614
+ } else
615
+ less_pipe = 0;
616
+
617
+ /*----------------------------------------------------------------------*/
618
+
619
+ if (read_solution_path && !get ("check"))
620
+ set ("--check");
621
+ #ifndef QUIET
622
+ if (!get ("quiet")) {
623
+ solver->section ("banner");
624
+ solver->message ("%sCaDiCaL SAT Solver%s", tout.bright_magenta_code (),
625
+ tout.normal_code ());
626
+ solver->message ("%s%s%s", tout.bright_magenta_code (), copyright (),
627
+ tout.normal_code ());
628
+ solver->message ("%s%s%s", tout.bright_magenta_code (), authors (),
629
+ tout.normal_code ());
630
+ solver->message ("%s%s%s", tout.bright_magenta_code (), affiliations (),
631
+ tout.normal_code ());
632
+ solver->message ();
633
+ CaDiCaL::Solver::build (stdout, "c ");
634
+ }
635
+ #endif
636
+ if (preprocessing > 0 || localsearch > 0 ||
637
+ #ifndef _WIN32
638
+ time_limit >= 0 ||
639
+ #endif
640
+ conflict_limit >= 0 || decision_limit >= 0) {
641
+ solver->section ("limit");
642
+ if (preprocessing > 0) {
643
+ solver->message (
644
+ "enabling %d initial rounds of preprocessing (due to '%s')",
645
+ preprocessing, preprocessing_specified);
646
+ solver->limit ("preprocessing", preprocessing);
647
+ }
648
+ if (localsearch > 0) {
649
+ solver->message (
650
+ "enabling %d initial rounds of local search (due to '%s')",
651
+ localsearch, localsearch_specified);
652
+ solver->limit ("localsearch", localsearch);
653
+ }
654
+ #ifndef _WIN32
655
+ if (time_limit >= 0) {
656
+ solver->message (
657
+ "setting time limit to %d seconds real time (due to '-t %s')",
658
+ time_limit, time_limit_specified);
659
+ Signal::alarm (time_limit);
660
+ solver->connect_terminator (this);
661
+ }
662
+ #endif
663
+ if (conflict_limit >= 0) {
664
+ solver->message (
665
+ "setting conflict limit to %d conflicts (due to '%s')",
666
+ conflict_limit, conflict_limit_specified);
667
+ bool succeeded = solver->limit ("conflicts", conflict_limit);
668
+ assert (succeeded), (void) succeeded;
669
+ }
670
+ if (decision_limit >= 0) {
671
+ solver->message (
672
+ "setting decision limit to %d decisions (due to '%s')",
673
+ decision_limit, decision_limit_specified);
674
+ bool succeeded = solver->limit ("decisions", decision_limit);
675
+ assert (succeeded), (void) succeeded;
676
+ }
677
+ }
678
+ if (verbose () || proof_specified)
679
+ solver->section ("proof tracing");
680
+ if (proof_specified) {
681
+ if (!proof_path) {
682
+ const bool force_binary = (isatty (1) && get ("binary"));
683
+ if (force_binary)
684
+ set ("--no-binary");
685
+ solver->message ("writing %s proof trace to %s'<stdout>'%s",
686
+ (get ("binary") ? "binary" : "non-binary"),
687
+ tout.green_code (), tout.normal_code ());
688
+ if (force_binary)
689
+ solver->message (
690
+ "connected to terminal thus non-binary proof forced");
691
+ solver->trace_proof (stdout, "<stdout>");
692
+ } else if (!solver->trace_proof (proof_path))
693
+ APPERR ("can not open and write proof trace to '%s'", proof_path);
694
+ else
695
+ solver->message ("writing %s proof trace to %s'%s'%s",
696
+ (get ("binary") ? "binary" : "non-binary"),
697
+ tout.green_code (), proof_path, tout.normal_code ());
698
+ } else
699
+ solver->verbose (1, "will not generate nor write DRAT proof");
700
+ solver->section ("parsing input");
701
+ dimacs_name = dimacs_path ? dimacs_path : "<stdin>";
702
+ string help;
703
+ if (!dimacs_path) {
704
+ help += " ";
705
+ help += tout.magenta_code ();
706
+ help += "(use '-h' for a list of common options)";
707
+ help += tout.normal_code ();
708
+ }
709
+ solver->message ("reading DIMACS file from %s'%s'%s%s",
710
+ tout.green_code (), dimacs_name, tout.normal_code (),
711
+ help.c_str ());
712
+ bool incremental;
713
+ vector<int> cube_literals;
714
+ if (dimacs_path)
715
+ err = solver->read_dimacs (dimacs_path, max_var, force_strict_parsing,
716
+ incremental, cube_literals);
717
+ else
718
+ err = solver->read_dimacs (stdin, dimacs_name, max_var,
719
+ force_strict_parsing, incremental,
720
+ cube_literals);
721
+ if (err)
722
+ APPERR ("%s", err);
723
+ if (read_solution_path) {
724
+ solver->section ("parsing solution");
725
+ solver->message ("reading solution file from '%s'", read_solution_path);
726
+ if ((err = solver->read_solution (read_solution_path)))
727
+ APPERR ("%s", err);
728
+ }
729
+
730
+ solver->section ("options");
731
+ if (optimize > 0) {
732
+ solver->optimize (optimize);
733
+ solver->message ();
734
+ }
735
+ solver->options ();
736
+
737
+ int res = 0;
738
+
739
+ if (incremental) {
740
+ bool reporting = get ("report") > 1 || get ("verbose") > 0;
741
+ if (!reporting)
742
+ set ("report", 0);
743
+ if (!reporting)
744
+ solver->section ("incremental solving");
745
+ size_t cubes = 0, solved = 0;
746
+ size_t satisfiable = 0, unsatisfiable = 0, inconclusive = 0;
747
+ #ifndef QUIET
748
+ bool quiet = get ("quiet");
749
+ struct {
750
+ double start, delta, sum;
751
+ } time = {0, 0, 0};
752
+ #endif
753
+ for (auto lit : cube_literals)
754
+ if (!lit)
755
+ cubes++;
756
+ if (!reporting) {
757
+ if (cubes)
758
+ solver->message ("starting to solve %zu cubes", cubes),
759
+ solver->message ();
760
+ else
761
+ solver->message ("no cube to solve");
762
+ }
763
+ vector<int> cube, failed;
764
+ for (auto lit : cube_literals) {
765
+ if (lit)
766
+ cube.push_back (lit);
767
+ else {
768
+ reverse (cube.begin (), cube.end ());
769
+ for (auto other : cube)
770
+ solver->assume (other);
771
+ if (solved++) {
772
+ if (conflict_limit >= 0)
773
+ (void) solver->limit ("conflicts", conflict_limit);
774
+ if (decision_limit >= 0)
775
+ (void) solver->limit ("decisions", decision_limit);
776
+ }
777
+ #ifndef QUIET
778
+ char buffer[256];
779
+ if (!quiet) {
780
+ if (reporting) {
781
+ snprintf (buffer, sizeof buffer,
782
+ "solving cube %zu / %zu %.0f%%", solved, cubes,
783
+ percent (solved, cubes));
784
+ solver->section (buffer);
785
+ }
786
+ time.start = absolute_process_time ();
787
+ }
788
+ #endif
789
+ res = solver->solve ();
790
+ #ifndef QUIET
791
+ if (!quiet) {
792
+ time.delta = absolute_process_time () - time.start;
793
+ time.sum += time.delta;
794
+ snprintf (buffer, sizeof buffer,
795
+ "%s"
796
+ "in %.3f sec "
797
+ "(%.0f%% after %.2f sec at %.0f ms/cube)"
798
+ "%s",
799
+ tout.magenta_code (), time.delta,
800
+ percent (solved, cubes), time.sum,
801
+ relative (1e3 * time.sum, solved), tout.normal_code ());
802
+ if (reporting)
803
+ solver->message ();
804
+ const char *cube_str, *status_str, *color_code;
805
+ if (res == 10) {
806
+ cube_str = "CUBE";
807
+ color_code = tout.green_code ();
808
+ status_str = "SATISFIABLE";
809
+ } else if (res == 20) {
810
+ cube_str = "CUBE";
811
+ color_code = tout.cyan_code ();
812
+ status_str = "UNSATISFIABLE";
813
+ } else {
814
+ cube_str = "cube";
815
+ color_code = tout.magenta_code ();
816
+ status_str = "inconclusive";
817
+ }
818
+ const char *fmt;
819
+ if (reporting)
820
+ fmt = "%s%s %zu %s%s %s";
821
+ else
822
+ fmt = "%s%s %zu %-13s%s %s";
823
+ solver->message (fmt, color_code, cube_str, solved, status_str,
824
+ tout.normal_code (), buffer);
825
+ }
826
+ #endif
827
+ if (res == 10) {
828
+ satisfiable++;
829
+ solver->conclude ();
830
+ break;
831
+ } else if (res == 20) {
832
+ unsatisfiable++;
833
+ solver->conclude ();
834
+ for (auto other : cube)
835
+ if (solver->failed (other))
836
+ failed.push_back (other);
837
+ for (auto other : failed)
838
+ solver->add (-other);
839
+ solver->add (0);
840
+ failed.clear ();
841
+ } else {
842
+ assert (!res);
843
+ inconclusive++;
844
+ if (timesup)
845
+ break;
846
+ }
847
+ cube.clear ();
848
+ }
849
+ }
850
+ solver->section ("incremental summary");
851
+ solver->message ("%zu cubes solved %.0f%%", solved,
852
+ percent (solved, cubes));
853
+ solver->message ("%zu cubes inconclusive %.0f%%", inconclusive,
854
+ percent (inconclusive, solved));
855
+ solver->message ("%zu cubes unsatisfiable %.0f%%", unsatisfiable,
856
+ percent (unsatisfiable, solved));
857
+ solver->message ("%zu cubes satisfiable %.0f%%", satisfiable,
858
+ percent (satisfiable, solved));
859
+
860
+ if (inconclusive && res == 20)
861
+ res = 0;
862
+ } else {
863
+ solver->section ("solving");
864
+ res = solver->solve ();
865
+ }
866
+
867
+ if (proof_specified) {
868
+ solver->section ("closing proof");
869
+ solver->close_proof_trace (!get ("quiet"));
870
+ }
871
+
872
+ if (output_path) {
873
+ solver->section ("writing output");
874
+ solver->message ("writing simplified CNF to DIMACS file %s'%s'%s",
875
+ tout.green_code (), output_path, tout.normal_code ());
876
+ err = solver->write_dimacs (output_path, max_var);
877
+ if (err)
878
+ APPERR ("%s", err);
879
+ }
880
+
881
+ if (extension_path) {
882
+ solver->section ("writing extension");
883
+ solver->message ("writing extension stack to %s'%s'%s",
884
+ tout.green_code (), extension_path,
885
+ tout.normal_code ());
886
+ err = solver->write_extension (extension_path);
887
+ if (err)
888
+ APPERR ("%s", err);
889
+ }
890
+
891
+ solver->section ("result");
892
+
893
+ FILE *write_result_file;
894
+ write_result_file = stdout;
895
+ if (write_result_path) {
896
+ write_result_file = fopen (write_result_path, "w");
897
+ if (!write_result_file)
898
+ APPERR ("could not write solution to '%s'", write_result_path);
899
+ solver->message ("writing result to '%s'", write_result_path);
900
+ }
901
+
902
+ if (res == 10) {
903
+ if (status)
904
+ fputs ("s SATISFIABLE\n", write_result_file);
905
+ if (witness)
906
+ print_witness (write_result_file);
907
+ } else if (res == 20 && status)
908
+ fputs ("s UNSATISFIABLE\n", write_result_file);
909
+ else if (status)
910
+ fputs ("c UNKNOWN\n", write_result_file);
911
+ fflush (write_result_file);
912
+ if (write_result_path)
913
+ fclose (write_result_file);
914
+ solver->statistics ();
915
+ solver->resources ();
916
+ solver->section ("shutting down");
917
+ solver->message ("exit %d", res);
918
+ if (!res && timesup)
919
+ fputs ("c Timeout reached! 😅 This instance is a real thinker.\n"
920
+ "c 🚧 🚧 🚧 Please consider contributing it to the page\n"
921
+ "c https://mysolvertimesout.org/#sat in order to improve\n"
922
+ "c automated reasoning. 🚧 🚧 🚧\n",
923
+ write_result_file);
924
+ if (less_pipe) {
925
+ close (1);
926
+ pclose (less_pipe);
927
+ }
928
+ #ifndef _WIN32
929
+ if (time_limit > 0)
930
+ alarm (0);
931
+ #endif
932
+
933
+ return res;
934
+ }
935
+
936
+ /*------------------------------------------------------------------------*/
937
+
938
+ // The real initialization is delayed.
939
+
940
+ void App::init () {
941
+
942
+ assert (!solver);
943
+
944
+ #ifndef _WIN32
945
+ time_limit = -1;
946
+ #endif
947
+ force_strict_parsing = 1;
948
+ force_writing = false;
949
+ max_var = 0;
950
+ timesup = false;
951
+
952
+ // Call 'new Solver' only after setting 'reportdefault' and do not
953
+ // add this call to the member initialization above. This is because for
954
+ // stand-alone usage the default report default value is 'true' while for
955
+ // library usage it should remain 'false'. See the explanation in
956
+ // 'options.hpp' related to 'reportdefault' for details.
957
+
958
+ CaDiCaL::Options::reportdefault = 1;
959
+ solver = new Solver ();
960
+ Signal::set (this);
961
+ }
962
+
963
+ /*------------------------------------------------------------------------*/
964
+
965
+ App::App () : solver (0) {} // Only partially initialize the app.
966
+
967
+ App::~App () {
968
+ if (!solver)
969
+ return; // Only partially initialized.
970
+ Signal::reset ();
971
+ delete solver;
972
+ }
973
+
974
+ /*------------------------------------------------------------------------*/
975
+
976
+ #ifndef QUIET
977
+
978
+ void App::signal_message (const char *msg, int sig) {
979
+ solver->message ("%s%s %ssignal %d%s (%s)%s", tout.red_code (), msg,
980
+ tout.bright_red_code (), sig, tout.red_code (),
981
+ Signal::name (sig), tout.normal_code ());
982
+ }
983
+
984
+ #endif
985
+
986
+ void App::catch_signal (int sig) {
987
+ #ifndef QUIET
988
+ if (!get ("quiet")) {
989
+ solver->message ();
990
+ signal_message ("caught", sig);
991
+ solver->section ("result");
992
+ solver->message ("UNKNOWN");
993
+ solver->statistics ();
994
+ solver->resources ();
995
+ solver->message ();
996
+ signal_message ("raising", sig);
997
+ }
998
+ #else
999
+ (void) sig;
1000
+ #endif
1001
+ }
1002
+
1003
+ void App::catch_alarm () {
1004
+ // Both approaches work. We keep them here for illustration purposes.
1005
+ #if 0 // THIS IS AN ALTERNATIVE WE WANT TO KEEP AROUND.
1006
+ solver->terminate (); // Immediate asynchronous call into solver.
1007
+ #else
1008
+ timesup = true; // Wait for solver to call 'App::terminate ()'.
1009
+ #endif
1010
+ }
1011
+
1012
+ } // namespace CaDiCaL
1013
+
1014
+ /*------------------------------------------------------------------------*/
1015
+
1016
+ // The actual app is allocated on the stack and then its 'main' function is
1017
+ // called. This looks like that there are no static variables, which is not
1018
+ // completely true, since both the signal handler connected to the app as
1019
+ // well as the terminal have statically allocated components as well as the
1020
+ // options table 'Options::table'. All are shared among solvers.
1021
+
1022
+ int main (int argc, char **argv) {
1023
+ CaDiCaL::App app;
1024
+ int res = app.main (argc, argv);
1025
+ return res;
1026
+ }