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,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
|