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.
- checksums.yaml +7 -0
- data/LICENSE.txt +26 -0
- data/README.md +101 -0
- data/ext/cadical/cadical/LICENSE +28 -0
- data/ext/cadical/cadical/README.md +65 -0
- data/ext/cadical/cadical/VERSION +1 -0
- data/ext/cadical/cadical/src/analyze.cpp +1360 -0
- data/ext/cadical/cadical/src/arena.cpp +30 -0
- data/ext/cadical/cadical/src/arena.hpp +105 -0
- data/ext/cadical/cadical/src/assume.cpp +616 -0
- data/ext/cadical/cadical/src/averages.cpp +34 -0
- data/ext/cadical/cadical/src/averages.hpp +37 -0
- data/ext/cadical/cadical/src/backbone.cpp +631 -0
- data/ext/cadical/cadical/src/backtrack.cpp +177 -0
- data/ext/cadical/cadical/src/backward.cpp +231 -0
- data/ext/cadical/cadical/src/bins.cpp +22 -0
- data/ext/cadical/cadical/src/bins.hpp +22 -0
- data/ext/cadical/cadical/src/block.cpp +824 -0
- data/ext/cadical/cadical/src/block.hpp +37 -0
- data/ext/cadical/cadical/src/cadical.cpp +1026 -0
- data/ext/cadical/cadical/src/cadical.hpp +1419 -0
- data/ext/cadical/cadical/src/ccadical.cpp +208 -0
- data/ext/cadical/cadical/src/ccadical.h +74 -0
- data/ext/cadical/cadical/src/checker.cpp +649 -0
- data/ext/cadical/cadical/src/checker.hpp +173 -0
- data/ext/cadical/cadical/src/clause.cpp +689 -0
- data/ext/cadical/cadical/src/clause.hpp +190 -0
- data/ext/cadical/cadical/src/collect.cpp +545 -0
- data/ext/cadical/cadical/src/compact.cpp +550 -0
- data/ext/cadical/cadical/src/condition.cpp +940 -0
- data/ext/cadical/cadical/src/config.cpp +101 -0
- data/ext/cadical/cadical/src/config.hpp +20 -0
- data/ext/cadical/cadical/src/congruence.cpp +7880 -0
- data/ext/cadical/cadical/src/congruence.hpp +757 -0
- data/ext/cadical/cadical/src/constrain.cpp +64 -0
- data/ext/cadical/cadical/src/contract.cpp +27 -0
- data/ext/cadical/cadical/src/contract.hpp +139 -0
- data/ext/cadical/cadical/src/cover.cpp +704 -0
- data/ext/cadical/cadical/src/cover.hpp +34 -0
- data/ext/cadical/cadical/src/decide.cpp +347 -0
- data/ext/cadical/cadical/src/decompose.cpp +738 -0
- data/ext/cadical/cadical/src/decompose.hpp +23 -0
- data/ext/cadical/cadical/src/deduplicate.cpp +275 -0
- data/ext/cadical/cadical/src/definition.cpp +283 -0
- data/ext/cadical/cadical/src/delay.hpp +38 -0
- data/ext/cadical/cadical/src/drattracer.cpp +153 -0
- data/ext/cadical/cadical/src/drattracer.hpp +55 -0
- data/ext/cadical/cadical/src/elim.cpp +1171 -0
- data/ext/cadical/cadical/src/elim.hpp +53 -0
- data/ext/cadical/cadical/src/elimfast.cpp +570 -0
- data/ext/cadical/cadical/src/ema.cpp +95 -0
- data/ext/cadical/cadical/src/ema.hpp +68 -0
- data/ext/cadical/cadical/src/extend.cpp +289 -0
- data/ext/cadical/cadical/src/external.cpp +1034 -0
- data/ext/cadical/cadical/src/external.hpp +487 -0
- data/ext/cadical/cadical/src/external_propagate.cpp +1316 -0
- data/ext/cadical/cadical/src/factor.cpp +1011 -0
- data/ext/cadical/cadical/src/factor.hpp +54 -0
- data/ext/cadical/cadical/src/file.cpp +506 -0
- data/ext/cadical/cadical/src/file.hpp +210 -0
- data/ext/cadical/cadical/src/flags.cpp +135 -0
- data/ext/cadical/cadical/src/flags.hpp +93 -0
- data/ext/cadical/cadical/src/flip.cpp +269 -0
- data/ext/cadical/cadical/src/format.cpp +89 -0
- data/ext/cadical/cadical/src/format.hpp +36 -0
- data/ext/cadical/cadical/src/frattracer.cpp +277 -0
- data/ext/cadical/cadical/src/frattracer.hpp +67 -0
- data/ext/cadical/cadical/src/gates.cpp +766 -0
- data/ext/cadical/cadical/src/heap.hpp +212 -0
- data/ext/cadical/cadical/src/idruptracer.cpp +566 -0
- data/ext/cadical/cadical/src/idruptracer.hpp +112 -0
- data/ext/cadical/cadical/src/instantiate.cpp +365 -0
- data/ext/cadical/cadical/src/instantiate.hpp +45 -0
- data/ext/cadical/cadical/src/internal.cpp +1265 -0
- data/ext/cadical/cadical/src/internal.hpp +1941 -0
- data/ext/cadical/cadical/src/inttypes.hpp +34 -0
- data/ext/cadical/cadical/src/ipasir.cpp +47 -0
- data/ext/cadical/cadical/src/ipasir.h +37 -0
- data/ext/cadical/cadical/src/kitten.c +2599 -0
- data/ext/cadical/cadical/src/kitten.h +97 -0
- data/ext/cadical/cadical/src/level.hpp +33 -0
- data/ext/cadical/cadical/src/lidruptracer.cpp +657 -0
- data/ext/cadical/cadical/src/lidruptracer.hpp +122 -0
- data/ext/cadical/cadical/src/limit.cpp +146 -0
- data/ext/cadical/cadical/src/limit.hpp +168 -0
- data/ext/cadical/cadical/src/logging.cpp +214 -0
- data/ext/cadical/cadical/src/logging.hpp +98 -0
- data/ext/cadical/cadical/src/lookahead.cpp +520 -0
- data/ext/cadical/cadical/src/lratchecker.cpp +833 -0
- data/ext/cadical/cadical/src/lratchecker.hpp +168 -0
- data/ext/cadical/cadical/src/lrattracer.cpp +200 -0
- data/ext/cadical/cadical/src/lrattracer.hpp +61 -0
- data/ext/cadical/cadical/src/lucky.cpp +506 -0
- data/ext/cadical/cadical/src/message.cpp +218 -0
- data/ext/cadical/cadical/src/message.hpp +65 -0
- data/ext/cadical/cadical/src/minimize.cpp +224 -0
- data/ext/cadical/cadical/src/mobical.cpp +5588 -0
- data/ext/cadical/cadical/src/occs.cpp +52 -0
- data/ext/cadical/cadical/src/occs.hpp +36 -0
- data/ext/cadical/cadical/src/options.cpp +359 -0
- data/ext/cadical/cadical/src/options.hpp +442 -0
- data/ext/cadical/cadical/src/parse.cpp +471 -0
- data/ext/cadical/cadical/src/parse.hpp +75 -0
- data/ext/cadical/cadical/src/phases.cpp +56 -0
- data/ext/cadical/cadical/src/phases.hpp +19 -0
- data/ext/cadical/cadical/src/probe.cpp +990 -0
- data/ext/cadical/cadical/src/profile.cpp +107 -0
- data/ext/cadical/cadical/src/profile.hpp +283 -0
- data/ext/cadical/cadical/src/proof.cpp +691 -0
- data/ext/cadical/cadical/src/proof.hpp +125 -0
- data/ext/cadical/cadical/src/propagate.cpp +584 -0
- data/ext/cadical/cadical/src/queue.cpp +90 -0
- data/ext/cadical/cadical/src/queue.hpp +74 -0
- data/ext/cadical/cadical/src/radix.hpp +180 -0
- data/ext/cadical/cadical/src/random.cpp +207 -0
- data/ext/cadical/cadical/src/random.h +44 -0
- data/ext/cadical/cadical/src/random.hpp +98 -0
- data/ext/cadical/cadical/src/range.hpp +125 -0
- data/ext/cadical/cadical/src/reap.cpp +127 -0
- data/ext/cadical/cadical/src/reap.hpp +28 -0
- data/ext/cadical/cadical/src/reduce.cpp +278 -0
- data/ext/cadical/cadical/src/reluctant.hpp +82 -0
- data/ext/cadical/cadical/src/rephase.cpp +402 -0
- data/ext/cadical/cadical/src/report.cpp +313 -0
- data/ext/cadical/cadical/src/resources.cpp +160 -0
- data/ext/cadical/cadical/src/resources.hpp +16 -0
- data/ext/cadical/cadical/src/restart.cpp +178 -0
- data/ext/cadical/cadical/src/restore.cpp +267 -0
- data/ext/cadical/cadical/src/score.cpp +51 -0
- data/ext/cadical/cadical/src/score.hpp +16 -0
- data/ext/cadical/cadical/src/shrink.cpp +507 -0
- data/ext/cadical/cadical/src/signal.cpp +136 -0
- data/ext/cadical/cadical/src/signal.hpp +33 -0
- data/ext/cadical/cadical/src/solution.cpp +50 -0
- data/ext/cadical/cadical/src/solver.cpp +1871 -0
- data/ext/cadical/cadical/src/stable.cpp +31 -0
- data/ext/cadical/cadical/src/stack.h +110 -0
- data/ext/cadical/cadical/src/stats.cpp +920 -0
- data/ext/cadical/cadical/src/stats.hpp +418 -0
- data/ext/cadical/cadical/src/subsume.cpp +645 -0
- data/ext/cadical/cadical/src/sweep.cpp +1960 -0
- data/ext/cadical/cadical/src/sweep.hpp +61 -0
- data/ext/cadical/cadical/src/terminal.cpp +38 -0
- data/ext/cadical/cadical/src/terminal.hpp +96 -0
- data/ext/cadical/cadical/src/ternary.cpp +450 -0
- data/ext/cadical/cadical/src/testing.hpp +24 -0
- data/ext/cadical/cadical/src/tier.cpp +189 -0
- data/ext/cadical/cadical/src/tracer.hpp +186 -0
- data/ext/cadical/cadical/src/transred.cpp +253 -0
- data/ext/cadical/cadical/src/unstable.cpp +29 -0
- data/ext/cadical/cadical/src/util.cpp +129 -0
- data/ext/cadical/cadical/src/util.hpp +181 -0
- data/ext/cadical/cadical/src/var.cpp +39 -0
- data/ext/cadical/cadical/src/var.hpp +22 -0
- data/ext/cadical/cadical/src/veripbtracer.cpp +427 -0
- data/ext/cadical/cadical/src/veripbtracer.hpp +106 -0
- data/ext/cadical/cadical/src/version.cpp +107 -0
- data/ext/cadical/cadical/src/version.hpp +13 -0
- data/ext/cadical/cadical/src/vivify.cpp +1893 -0
- data/ext/cadical/cadical/src/vivify.hpp +50 -0
- data/ext/cadical/cadical/src/walk.cpp +1088 -0
- data/ext/cadical/cadical/src/walk.hpp +91 -0
- data/ext/cadical/cadical/src/walk_full_occs.cpp +966 -0
- data/ext/cadical/cadical/src/warmup.cpp +403 -0
- data/ext/cadical/cadical/src/watch.cpp +126 -0
- data/ext/cadical/cadical/src/watch.hpp +77 -0
- data/ext/cadical/cadical_ext.c +778 -0
- data/ext/cadical/extconf.rb +26 -0
- data/lib/cadical/version.rb +3 -0
- data/lib/cadical.rb +12 -0
- metadata +218 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
/*------------------------------------------------------------------------*/
|
|
4
|
+
|
|
5
|
+
namespace CaDiCaL {
|
|
6
|
+
|
|
7
|
+
/*------------------------------------------------------------------------*/
|
|
8
|
+
|
|
9
|
+
// Parse error.
|
|
10
|
+
|
|
11
|
+
#define PER(...) \
|
|
12
|
+
do { \
|
|
13
|
+
internal->error_message.init ( \
|
|
14
|
+
"%s:%" PRIu64 ": parse error: ", file->name (), \
|
|
15
|
+
(uint64_t) file->lineno ()); \
|
|
16
|
+
return internal->error_message.append (__VA_ARGS__); \
|
|
17
|
+
} while (0)
|
|
18
|
+
|
|
19
|
+
/*------------------------------------------------------------------------*/
|
|
20
|
+
|
|
21
|
+
// Parsing utilities.
|
|
22
|
+
|
|
23
|
+
inline int Parser::parse_char () { return file->get (); }
|
|
24
|
+
|
|
25
|
+
// Return an non zero error string if a parse error occurred.
|
|
26
|
+
|
|
27
|
+
inline const char *Parser::parse_string (const char *str, char prev) {
|
|
28
|
+
for (const char *p = str; *p; p++)
|
|
29
|
+
if (parse_char () == *p)
|
|
30
|
+
prev = *p;
|
|
31
|
+
else if (*p == ' ')
|
|
32
|
+
PER ("expected space after '%c'", prev);
|
|
33
|
+
else
|
|
34
|
+
PER ("expected '%c' after '%c'", *p, prev);
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
inline const char *Parser::parse_positive_int (int &ch, int &res,
|
|
39
|
+
const char *name) {
|
|
40
|
+
assert (isdigit (ch));
|
|
41
|
+
res = ch - '0';
|
|
42
|
+
while (isdigit (ch = parse_char ())) {
|
|
43
|
+
int digit = ch - '0';
|
|
44
|
+
if (INT_MAX / 10 < res || INT_MAX - digit < 10 * res)
|
|
45
|
+
PER ("too large '%s' in header", name);
|
|
46
|
+
res = 10 * res + digit;
|
|
47
|
+
}
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
inline const char *Parser::parse_positive_uint64_t (int &ch, uint64_t &res,
|
|
52
|
+
const char *name) {
|
|
53
|
+
assert (isdigit (ch));
|
|
54
|
+
res = ch - '0';
|
|
55
|
+
while (isdigit (ch = parse_char ())) {
|
|
56
|
+
int digit = ch - '0';
|
|
57
|
+
if (UINT64_MAX / 10 < res || UINT64_MAX - digit < 10 * res)
|
|
58
|
+
PER ("too large '%s' in header", name);
|
|
59
|
+
res = 10 * res + digit;
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
static const char *cube_token = "unexpected 'a' in CNF";
|
|
64
|
+
|
|
65
|
+
inline const char *Parser::parse_lit (int &ch, int &lit, int &vars,
|
|
66
|
+
int strict) {
|
|
67
|
+
if (ch == 'a')
|
|
68
|
+
return cube_token;
|
|
69
|
+
int sign = 0;
|
|
70
|
+
if (ch == '-') {
|
|
71
|
+
if (!isdigit (ch = parse_char ()))
|
|
72
|
+
PER ("expected digit after '-'");
|
|
73
|
+
sign = -1;
|
|
74
|
+
} else if (!isdigit (ch))
|
|
75
|
+
PER ("expected digit or '-'");
|
|
76
|
+
else
|
|
77
|
+
sign = 1;
|
|
78
|
+
lit = ch - '0';
|
|
79
|
+
while (isdigit (ch = parse_char ())) {
|
|
80
|
+
int digit = ch - '0';
|
|
81
|
+
if (INT_MAX / 10 < lit || INT_MAX - digit < 10 * lit)
|
|
82
|
+
PER ("literal too large");
|
|
83
|
+
lit = 10 * lit + digit;
|
|
84
|
+
}
|
|
85
|
+
if (ch == '\r')
|
|
86
|
+
ch = parse_char ();
|
|
87
|
+
if (ch != 'c' && ch != ' ' && ch != '\t' && ch != '\n' && ch != EOF)
|
|
88
|
+
PER ("expected white space after '%d'", sign * lit);
|
|
89
|
+
if (lit > vars) {
|
|
90
|
+
if (strict != FORCED)
|
|
91
|
+
PER ("literal %d exceeds maximum variable %d", sign * lit, vars);
|
|
92
|
+
else
|
|
93
|
+
vars = lit;
|
|
94
|
+
}
|
|
95
|
+
lit *= sign;
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/*------------------------------------------------------------------------*/
|
|
100
|
+
|
|
101
|
+
// Parsing CNF in DIMACS format.
|
|
102
|
+
|
|
103
|
+
const char *Parser::parse_dimacs_non_profiled (int &vars, int strict) {
|
|
104
|
+
|
|
105
|
+
#ifndef QUIET
|
|
106
|
+
double start = internal->time ();
|
|
107
|
+
#endif
|
|
108
|
+
|
|
109
|
+
bool found_inccnf_header = false;
|
|
110
|
+
int ch = 0, declared = 0;
|
|
111
|
+
uint64_t clauses = 0;
|
|
112
|
+
|
|
113
|
+
vars = 0;
|
|
114
|
+
|
|
115
|
+
// First read comments before header with possibly embedded options.
|
|
116
|
+
//
|
|
117
|
+
for (;;) {
|
|
118
|
+
ch = parse_char ();
|
|
119
|
+
if (strict != STRICT)
|
|
120
|
+
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r')
|
|
121
|
+
continue;
|
|
122
|
+
if (ch != 'c')
|
|
123
|
+
break;
|
|
124
|
+
string buf;
|
|
125
|
+
while ((ch = parse_char ()) != '\n')
|
|
126
|
+
if (ch == EOF)
|
|
127
|
+
PER ("unexpected end-of-file in header comment");
|
|
128
|
+
else if (ch != '\r')
|
|
129
|
+
buf.push_back (ch);
|
|
130
|
+
const char *o;
|
|
131
|
+
for (o = buf.c_str (); *o && *o != '-'; o++)
|
|
132
|
+
;
|
|
133
|
+
if (!*o)
|
|
134
|
+
continue;
|
|
135
|
+
PHASE ("parse-dimacs", "found option '%s'", o);
|
|
136
|
+
if (*o)
|
|
137
|
+
solver->set_long_option (o);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (ch != 'p')
|
|
141
|
+
PER ("expected 'c' or 'p'");
|
|
142
|
+
|
|
143
|
+
ch = parse_char ();
|
|
144
|
+
if (strict == STRICT) {
|
|
145
|
+
if (ch != ' ')
|
|
146
|
+
PER ("expected space after 'p'");
|
|
147
|
+
ch = parse_char ();
|
|
148
|
+
} else if (ch != ' ' && ch != '\t')
|
|
149
|
+
PER ("expected white space after 'p'");
|
|
150
|
+
else {
|
|
151
|
+
do
|
|
152
|
+
ch = parse_char ();
|
|
153
|
+
while (ch == ' ' || ch == '\t');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Now read 'p cnf <var> <clauses>' header of DIMACS file
|
|
157
|
+
// or 'p inccnf' of incremental 'INCCNF' file.
|
|
158
|
+
//
|
|
159
|
+
if (ch == 'c') {
|
|
160
|
+
assert (!found_inccnf_header);
|
|
161
|
+
if (strict == STRICT) {
|
|
162
|
+
const char *err = parse_string ("nf ", 'c');
|
|
163
|
+
if (err)
|
|
164
|
+
return err;
|
|
165
|
+
ch = parse_char ();
|
|
166
|
+
if (!isdigit (ch))
|
|
167
|
+
PER ("expected digit after 'p cnf '");
|
|
168
|
+
err = parse_positive_int (ch, vars, "<max-var>");
|
|
169
|
+
if (err)
|
|
170
|
+
return err;
|
|
171
|
+
if (ch != ' ')
|
|
172
|
+
PER ("expected ' ' after 'p cnf %d'", vars);
|
|
173
|
+
if (!isdigit (ch = parse_char ()))
|
|
174
|
+
PER ("expected digit after 'p cnf %d '", vars);
|
|
175
|
+
err = parse_positive_uint64_t (ch, clauses, "<num-clauses>");
|
|
176
|
+
if (err)
|
|
177
|
+
return err;
|
|
178
|
+
if (ch != '\n')
|
|
179
|
+
PER ("expected new-line after 'p cnf %d %" PRIu64 "'", vars,
|
|
180
|
+
clauses);
|
|
181
|
+
} else {
|
|
182
|
+
if (parse_char () != 'n')
|
|
183
|
+
PER ("expected 'n' after 'p c'");
|
|
184
|
+
if (parse_char () != 'f')
|
|
185
|
+
PER ("expected 'f' after 'p cn'");
|
|
186
|
+
ch = parse_char ();
|
|
187
|
+
if (!isspace (ch))
|
|
188
|
+
PER ("expected space after 'p cnf'");
|
|
189
|
+
do
|
|
190
|
+
ch = parse_char ();
|
|
191
|
+
while (isspace (ch));
|
|
192
|
+
if (!isdigit (ch))
|
|
193
|
+
PER ("expected digit after 'p cnf '");
|
|
194
|
+
const char *err = parse_positive_int (ch, vars, "<max-var>");
|
|
195
|
+
if (err)
|
|
196
|
+
return err;
|
|
197
|
+
if (!isspace (ch))
|
|
198
|
+
PER ("expected space after 'p cnf %d'", vars);
|
|
199
|
+
do
|
|
200
|
+
ch = parse_char ();
|
|
201
|
+
while (isspace (ch));
|
|
202
|
+
if (!isdigit (ch))
|
|
203
|
+
PER ("expected digit after 'p cnf %d '", vars);
|
|
204
|
+
err = parse_positive_uint64_t (ch, clauses, "<num-clauses>");
|
|
205
|
+
if (err)
|
|
206
|
+
return err;
|
|
207
|
+
while (ch != '\n') {
|
|
208
|
+
if (ch != '\r' && !isspace (ch))
|
|
209
|
+
PER ("expected new-line after 'p cnf %d %" PRIu64 "'", vars,
|
|
210
|
+
clauses);
|
|
211
|
+
ch = parse_char ();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
MSG ("found %s'p cnf %d %" PRIu64 "'%s header", tout.green_code (),
|
|
216
|
+
vars, clauses, tout.normal_code ());
|
|
217
|
+
|
|
218
|
+
if (vars) {
|
|
219
|
+
assert (vars > 0);
|
|
220
|
+
solver->resize (vars);
|
|
221
|
+
declared = vars;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
internal->reserve_ids (clauses);
|
|
225
|
+
|
|
226
|
+
} else if (!parse_inccnf_too)
|
|
227
|
+
PER ("expected 'c' after 'p '");
|
|
228
|
+
else if (ch == 'i') {
|
|
229
|
+
found_inccnf_header = true;
|
|
230
|
+
const char *err = parse_string ("nccnf", 'i');
|
|
231
|
+
if (err)
|
|
232
|
+
return err;
|
|
233
|
+
ch = parse_char ();
|
|
234
|
+
if (strict == STRICT) {
|
|
235
|
+
if (ch != '\n')
|
|
236
|
+
PER ("expected new-line after 'p inccnf'");
|
|
237
|
+
} else {
|
|
238
|
+
while (ch != '\n') {
|
|
239
|
+
if (ch != '\r' && !isspace (ch))
|
|
240
|
+
PER ("expected new-line after 'p inccnf'");
|
|
241
|
+
ch = parse_char ();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
MSG ("found %s'p inccnf'%s header", tout.green_code (),
|
|
246
|
+
tout.normal_code ());
|
|
247
|
+
|
|
248
|
+
// Cube & Conquer 'inccnf' format is not compatible with factor:
|
|
249
|
+
internal->opts.factor = 0;
|
|
250
|
+
|
|
251
|
+
strict = FORCED;
|
|
252
|
+
} else
|
|
253
|
+
PER ("expected 'c' or 'i' after 'p '");
|
|
254
|
+
|
|
255
|
+
if (parse_inccnf_too)
|
|
256
|
+
*parse_inccnf_too = false;
|
|
257
|
+
|
|
258
|
+
// Now read body of DIMACS part.
|
|
259
|
+
//
|
|
260
|
+
int lit = 0;
|
|
261
|
+
uint64_t parsed = 0;
|
|
262
|
+
while ((ch = parse_char ()) != EOF) {
|
|
263
|
+
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r')
|
|
264
|
+
continue;
|
|
265
|
+
if (ch == 'c') {
|
|
266
|
+
while ((ch = parse_char ()) != '\n' && ch != EOF)
|
|
267
|
+
;
|
|
268
|
+
if (ch == EOF)
|
|
269
|
+
break;
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (ch == 'a' && found_inccnf_header)
|
|
273
|
+
break;
|
|
274
|
+
const char *err = parse_lit (ch, lit, vars, strict);
|
|
275
|
+
if (err)
|
|
276
|
+
return err;
|
|
277
|
+
if (ch == 'c') {
|
|
278
|
+
while ((ch = parse_char ()) != '\n')
|
|
279
|
+
if (ch == EOF)
|
|
280
|
+
PER ("unexpected end-of-file in comment");
|
|
281
|
+
}
|
|
282
|
+
if (vars > declared) {
|
|
283
|
+
assert (strict == FORCED);
|
|
284
|
+
const int more_vars = vars - declared;
|
|
285
|
+
assert (more_vars > 0);
|
|
286
|
+
const int start = solver->declare_more_variables (more_vars);
|
|
287
|
+
assert (vars == start + more_vars - 1);
|
|
288
|
+
declared = vars;
|
|
289
|
+
#ifdef NDEBUG
|
|
290
|
+
(void) start;
|
|
291
|
+
#endif
|
|
292
|
+
}
|
|
293
|
+
solver->add (lit);
|
|
294
|
+
if (!found_inccnf_header && !lit && parsed++ >= clauses &&
|
|
295
|
+
strict != FORCED)
|
|
296
|
+
PER ("too many clauses");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (lit)
|
|
300
|
+
PER ("last clause without terminating '0'");
|
|
301
|
+
|
|
302
|
+
if (!found_inccnf_header && parsed < clauses && strict != FORCED)
|
|
303
|
+
PER ("clause missing");
|
|
304
|
+
|
|
305
|
+
#ifndef QUIET
|
|
306
|
+
double end = internal->time ();
|
|
307
|
+
MSG ("parsed %" PRIu64 " clauses in %.2f seconds %s time", parsed,
|
|
308
|
+
end - start, internal->opts.realtime ? "real" : "process");
|
|
309
|
+
#endif
|
|
310
|
+
|
|
311
|
+
#ifndef QUIET
|
|
312
|
+
start = end;
|
|
313
|
+
size_t num_cubes = 0;
|
|
314
|
+
#endif
|
|
315
|
+
if (ch == 'a') {
|
|
316
|
+
assert (parse_inccnf_too);
|
|
317
|
+
assert (found_inccnf_header);
|
|
318
|
+
if (!*parse_inccnf_too)
|
|
319
|
+
*parse_inccnf_too = true;
|
|
320
|
+
for (;;) {
|
|
321
|
+
ch = parse_char ();
|
|
322
|
+
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r')
|
|
323
|
+
continue;
|
|
324
|
+
if (ch == 'c') {
|
|
325
|
+
while ((ch = parse_char ()) != '\n' && ch != EOF)
|
|
326
|
+
;
|
|
327
|
+
if (ch == EOF)
|
|
328
|
+
break;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const char *err = parse_lit (ch, lit, vars, strict);
|
|
332
|
+
if (err == cube_token)
|
|
333
|
+
PER ("two 'a' in a row");
|
|
334
|
+
else if (err)
|
|
335
|
+
return err;
|
|
336
|
+
if (ch == 'c') {
|
|
337
|
+
while ((ch = parse_char ()) != '\n')
|
|
338
|
+
if (ch == EOF)
|
|
339
|
+
PER ("unexpected end-of-file in comment");
|
|
340
|
+
}
|
|
341
|
+
if (cubes)
|
|
342
|
+
cubes->push_back (lit);
|
|
343
|
+
if (!lit) {
|
|
344
|
+
#ifndef QUIET
|
|
345
|
+
num_cubes++;
|
|
346
|
+
#endif
|
|
347
|
+
for (;;) {
|
|
348
|
+
ch = parse_char ();
|
|
349
|
+
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r')
|
|
350
|
+
continue;
|
|
351
|
+
if (ch == 'c') {
|
|
352
|
+
while ((ch = parse_char ()) != '\n' && ch != EOF)
|
|
353
|
+
;
|
|
354
|
+
if (ch == EOF)
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
if (ch == EOF)
|
|
358
|
+
break;
|
|
359
|
+
if (ch != 'a')
|
|
360
|
+
PER ("expected 'a' or end-of-file after zero");
|
|
361
|
+
lit = INT_MIN;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
if (ch == EOF)
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (lit)
|
|
369
|
+
PER ("last cube without terminating '0'");
|
|
370
|
+
}
|
|
371
|
+
#ifndef QUIET
|
|
372
|
+
if (found_inccnf_header) {
|
|
373
|
+
double end = internal->time ();
|
|
374
|
+
MSG ("parsed %zd cubes in %.2f seconds %s time", num_cubes, end - start,
|
|
375
|
+
internal->opts.realtime ? "real" : "process");
|
|
376
|
+
}
|
|
377
|
+
#endif
|
|
378
|
+
return 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/*------------------------------------------------------------------------*/
|
|
382
|
+
|
|
383
|
+
// Parsing solution in competition output format.
|
|
384
|
+
|
|
385
|
+
const char *Parser::parse_solution_non_profiled () {
|
|
386
|
+
external->solution = new signed char[external->max_var + 1u];
|
|
387
|
+
external->solution_size = external->max_var;
|
|
388
|
+
clear_n (external->solution, external->max_var + 1u);
|
|
389
|
+
int ch;
|
|
390
|
+
for (;;) {
|
|
391
|
+
ch = parse_char ();
|
|
392
|
+
if (ch == EOF)
|
|
393
|
+
PER ("missing 's' line");
|
|
394
|
+
else if (ch == 'c') {
|
|
395
|
+
while ((ch = parse_char ()) != '\n')
|
|
396
|
+
if (ch == EOF)
|
|
397
|
+
PER ("unexpected end-of-file in comment");
|
|
398
|
+
} else if (ch == 's')
|
|
399
|
+
break;
|
|
400
|
+
else
|
|
401
|
+
PER ("expected 'c' or 's'");
|
|
402
|
+
}
|
|
403
|
+
const char *err = parse_string (" SATISFIABLE", 's');
|
|
404
|
+
if (err)
|
|
405
|
+
return err;
|
|
406
|
+
if ((ch = parse_char ()) == '\r')
|
|
407
|
+
ch = parse_char ();
|
|
408
|
+
if (ch != '\n')
|
|
409
|
+
PER ("expected new-line after 's SATISFIABLE'");
|
|
410
|
+
#ifndef QUIET
|
|
411
|
+
int count = 0;
|
|
412
|
+
#endif
|
|
413
|
+
for (;;) {
|
|
414
|
+
ch = parse_char ();
|
|
415
|
+
if (ch != 'v')
|
|
416
|
+
PER ("expected 'v' at start-of-line");
|
|
417
|
+
if ((ch = parse_char ()) != ' ')
|
|
418
|
+
PER ("expected ' ' after 'v'");
|
|
419
|
+
int lit = 0;
|
|
420
|
+
ch = parse_char ();
|
|
421
|
+
do {
|
|
422
|
+
if (ch == ' ' || ch == '\t') {
|
|
423
|
+
ch = parse_char ();
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
err = parse_lit (ch, lit, external->max_var, false);
|
|
427
|
+
if (err)
|
|
428
|
+
return err;
|
|
429
|
+
if (ch == 'c')
|
|
430
|
+
PER ("unexpected comment");
|
|
431
|
+
if (!lit)
|
|
432
|
+
break;
|
|
433
|
+
if (external->solution[abs (lit)])
|
|
434
|
+
PER ("variable %d occurs twice", abs (lit));
|
|
435
|
+
LOG ("solution %d", lit);
|
|
436
|
+
external->solution[abs (lit)] = sign (lit);
|
|
437
|
+
#ifndef QUIET
|
|
438
|
+
count++;
|
|
439
|
+
#endif
|
|
440
|
+
if (ch == '\r')
|
|
441
|
+
ch = parse_char ();
|
|
442
|
+
} while (ch != '\n');
|
|
443
|
+
if (!lit)
|
|
444
|
+
break;
|
|
445
|
+
}
|
|
446
|
+
MSG ("parsed %d values %.2f%%", count,
|
|
447
|
+
percent (count, external->max_var));
|
|
448
|
+
return 0;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/*------------------------------------------------------------------------*/
|
|
452
|
+
|
|
453
|
+
// Wrappers to profile parsing and at the same time use the convenient
|
|
454
|
+
// implicit 'return' in PER in the non-profiled versions.
|
|
455
|
+
|
|
456
|
+
const char *Parser::parse_dimacs (int &vars, int strict) {
|
|
457
|
+
assert (strict == FORCED || strict == RELAXED || strict == STRICT);
|
|
458
|
+
START (parse);
|
|
459
|
+
const char *err = parse_dimacs_non_profiled (vars, strict);
|
|
460
|
+
STOP (parse);
|
|
461
|
+
return err;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const char *Parser::parse_solution () {
|
|
465
|
+
START (parse);
|
|
466
|
+
const char *err = parse_solution_non_profiled ();
|
|
467
|
+
STOP (parse);
|
|
468
|
+
return err;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#ifndef _parse_hpp_INCLUDED
|
|
2
|
+
#define _parse_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include <cassert>
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
namespace CaDiCaL {
|
|
9
|
+
|
|
10
|
+
// Factors out common functions for parsing of DIMACS and solution files.
|
|
11
|
+
|
|
12
|
+
class File;
|
|
13
|
+
struct External;
|
|
14
|
+
struct Internal;
|
|
15
|
+
|
|
16
|
+
class Parser {
|
|
17
|
+
|
|
18
|
+
Solver *solver;
|
|
19
|
+
Internal *internal;
|
|
20
|
+
External *external;
|
|
21
|
+
File *file;
|
|
22
|
+
|
|
23
|
+
void perr (const char *fmt, ...) CADICAL_ATTRIBUTE_FORMAT (2, 3);
|
|
24
|
+
int parse_char ();
|
|
25
|
+
|
|
26
|
+
enum {
|
|
27
|
+
FORCED = 0, // Force reading even if header is broken.
|
|
28
|
+
RELAXED = 1, // Relaxed white space treatment in header.
|
|
29
|
+
STRICT = 2, // Strict white space and header compliance.
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const char *parse_string (const char *str, char prev);
|
|
33
|
+
const char *parse_positive_int (int &ch, int &res, const char *name);
|
|
34
|
+
const char *parse_positive_uint64_t (int &ch, uint64_t &res,
|
|
35
|
+
const char *name);
|
|
36
|
+
const char *parse_lit (int &ch, int &lit, int &vars, int strict);
|
|
37
|
+
const char *parse_dimacs_non_profiled (int &vars, int strict);
|
|
38
|
+
const char *parse_solution_non_profiled ();
|
|
39
|
+
|
|
40
|
+
bool *parse_inccnf_too;
|
|
41
|
+
vector<int> *cubes;
|
|
42
|
+
|
|
43
|
+
public:
|
|
44
|
+
// Parse a DIMACS CNF or ICNF file.
|
|
45
|
+
//
|
|
46
|
+
// Return zero if successful. Otherwise parse error.
|
|
47
|
+
Parser (Solver *s, File *f, bool *i, vector<int> *c)
|
|
48
|
+
: solver (s), internal (s->internal), external (s->external),
|
|
49
|
+
file (f), parse_inccnf_too (i), cubes (c) {}
|
|
50
|
+
|
|
51
|
+
// Parse a DIMACS file. Return zero if successful. Otherwise a parse
|
|
52
|
+
// error is return. The parsed clauses are added to the solver and the
|
|
53
|
+
// maximum variable index found is returned in the 'vars' argument. The
|
|
54
|
+
// 'strict' argument can be '0' in which case the numbers in the header
|
|
55
|
+
// can be arbitrary, e.g., 'p cnf 0 0' all the time, without producing a
|
|
56
|
+
// parse error. Only for this setting the parsed literals are not checked
|
|
57
|
+
// to overflow the maximum variable index of the header. The strictest
|
|
58
|
+
// form of parsing is enforced for the value '2' of 'strict', in which
|
|
59
|
+
// case the header can not have additional white space, while a value of
|
|
60
|
+
// '1' exactly relaxes this, e.g., 'p cnf \t 1 3 \r\n' becomes legal.
|
|
61
|
+
//
|
|
62
|
+
const char *parse_dimacs (int &vars, int strict);
|
|
63
|
+
|
|
64
|
+
// Parse a solution file as used in the SAT competition, e.g., with
|
|
65
|
+
// comment lines 'c ...', a status line 's ...' and value lines 'v ...'.
|
|
66
|
+
// Returns zero if successful. Otherwise a string is returned describing
|
|
67
|
+
// the parse error. The parsed solution is saved in 'solution' and can be
|
|
68
|
+
// accessed with 'sol (int lit)'. We use it for checking learned clauses.
|
|
69
|
+
//
|
|
70
|
+
const char *parse_solution ();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
} // namespace CaDiCaL
|
|
74
|
+
|
|
75
|
+
#endif
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
namespace CaDiCaL {
|
|
4
|
+
|
|
5
|
+
void Internal::copy_phases (vector<signed char> &dst) {
|
|
6
|
+
START (copy);
|
|
7
|
+
for (auto i : vars) {
|
|
8
|
+
const signed char tmp = phases.saved[i];
|
|
9
|
+
if (tmp)
|
|
10
|
+
dst[i] = tmp;
|
|
11
|
+
}
|
|
12
|
+
STOP (copy);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
void Internal::save_assigned_phases (vector<signed char> &dst) {
|
|
16
|
+
START (copy);
|
|
17
|
+
for (auto i : vars) {
|
|
18
|
+
if (vals[i])
|
|
19
|
+
dst[i] = vals[i];
|
|
20
|
+
}
|
|
21
|
+
STOP (copy);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void Internal::clear_phases (vector<signed char> &dst) {
|
|
25
|
+
START (copy);
|
|
26
|
+
for (auto i : vars)
|
|
27
|
+
dst[i] = 0;
|
|
28
|
+
STOP (copy);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
void Internal::phase (int lit) {
|
|
32
|
+
const int idx = vidx (lit);
|
|
33
|
+
signed char old_forced_phase = phases.forced[idx];
|
|
34
|
+
signed char new_forced_phase = sign (lit);
|
|
35
|
+
if (old_forced_phase == new_forced_phase) {
|
|
36
|
+
LOG ("forced phase remains at %d", old_forced_phase * idx);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (old_forced_phase)
|
|
40
|
+
LOG ("overwriting old forced phase %d", old_forced_phase * idx);
|
|
41
|
+
LOG ("new forced phase %d", new_forced_phase * idx);
|
|
42
|
+
phases.forced[idx] = new_forced_phase;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void Internal::unphase (int lit) {
|
|
46
|
+
const int idx = vidx (lit);
|
|
47
|
+
signed char old_forced_phase = phases.forced[idx];
|
|
48
|
+
if (!old_forced_phase) {
|
|
49
|
+
LOG ("forced phase of %d already reset", lit);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
LOG ("clearing old forced phase %d", old_forced_phase * idx);
|
|
53
|
+
phases.forced[idx] = 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
} // namespace CaDiCaL
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#ifndef _phases_hpp_INCLUDED
|
|
2
|
+
#define _phases_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include <vector>
|
|
5
|
+
|
|
6
|
+
namespace CaDiCaL {
|
|
7
|
+
|
|
8
|
+
struct Phases {
|
|
9
|
+
|
|
10
|
+
std::vector<signed char> best; // The current largest trail phase.
|
|
11
|
+
std::vector<signed char> forced; // Forced through 'phase'.
|
|
12
|
+
std::vector<signed char> prev; // Previous during local search.
|
|
13
|
+
std::vector<signed char> saved; // The actual saved phase.
|
|
14
|
+
std::vector<signed char> target; // The current target phase.
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
} // namespace CaDiCaL
|
|
18
|
+
|
|
19
|
+
#endif
|