Skip to content

Commit d070932

Browse files
committed
Introduce a new --sat-solver option to allow selecting the backend SAT solver
1 parent 6bf4dad commit d070932

File tree

11 files changed

+219
-11
lines changed

11 files changed

+219
-11
lines changed

doc/man/cbmc.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ enable caching of repeated dereferences
388388
\fB\-\-object\-bits\fR n
389389
number of bits used for object addresses
390390
.TP
391+
\fB\-\-sat\-solver\fR solver
392+
use specified SAT solver
393+
.TP
391394
\fB\-\-external\-sat\-solver\fR cmd
392395
command to invoke SAT solver process
393396
.TP

doc/man/jbmc.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ enable caching of repeated dereferences
382382
\fB\-\-object\-bits\fR n
383383
number of bits used for object addresses
384384
.TP
385+
\fB\-\-sat\-solver\fR solver
386+
use specified SAT solver
387+
.TP
385388
\fB\-\-external\-sat\-solver\fR \fIcmd\fR
386389
command to invoke SAT solver process
387390
.TP
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
unsigned x;
6+
unsigned y = 0;
7+
assert(x * y == y);
8+
return 0;
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE broken-z3-smt-backend broken-cprover-smt-backend paths-lifo-expected-failure
2+
test.c
3+
--sat-solver non-existing-solver
4+
^EXIT=1$
5+
^SIGNAL=0$
6+
unknown solver 'non-existing-solver'
7+
--
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
unsigned x;
6+
unsigned y = x;
7+
x /= 2;
8+
y /= 2;
9+
assert(x == y);
10+
return 0;
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE broken-z3-smt-backend broken-cprover-smt-backend
2+
test.c
3+
--sat-solver lingeling
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
The specified solver, 'lingeling', is not available\. The default solver will be used instead\.
7+
\[main\.assertion\.1] line \d+ assertion x == y: SUCCESS
8+
^VERIFICATION SUCCESSFUL$
9+
--

regression/cbmc/sat-solver/test.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
unsigned x;
6+
unsigned y = x / 2;
7+
assert(y != x);
8+
assert(y <= x);
9+
return 0;
10+
}

regression/cbmc/sat-solver/test.desc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE broken-z3-smt-backend broken-cprover-smt-backend
2+
test.c
3+
--sat-solver cadical
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
Solving with CaDiCaL|The specified solver, 'cadical', is not available. The default solver will be used instead.
7+
\[main\.assertion\.1] line \d+ assertion y != x: FAILURE
8+
\[main\.assertion\.2] line \d+ assertion y <= x: SUCCESS
9+
^VERIFICATION FAILED$
10+
--

regression/validate-trace-xml-schema/check.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
['bad_option', 'test_multiple.desc'],
4343
['bad_option', 'test.desc'],
4444
['unknown-argument-suggestion', 'test.desc'],
45+
['sat-solver-error', 'test.desc'],
4546
# this one produces XML intermingled with main XML output when used with --xml-ui
4647
['graphml_witness2', 'test.desc'],
4748
# these are producing coverage goals which aren't included in the schema

src/goto-checker/solver_factory.cpp

Lines changed: 150 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, Peter Schrammel
1313

1414
#include <util/cmdline.h>
1515
#include <util/exception_utils.h>
16+
#include <util/exit_codes.h>
1617
#include <util/make_unique.h>
1718
#include <util/message.h>
1819
#include <util/options.h>
@@ -151,7 +152,7 @@ std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_solver()
151152
return get_incremental_smt2(incremental_smt2_solver);
152153
if(options.get_bool_option("smt2"))
153154
return get_smt2(get_smt2_solver_type());
154-
return get_default();
155+
return get_sat_solver();
155156
}
156157

157158
/// Uses the options to pick an SMT 2.0 solver
@@ -213,20 +214,148 @@ make_satcheck_prop(message_handlert &message_handler, const optionst &options)
213214
return satcheck;
214215
}
215216

216-
std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_default()
217+
std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_sat_solver()
217218
{
218219
auto solver = util_make_unique<solvert>();
219-
if(
220-
options.get_bool_option("beautify") ||
221-
!options.get_bool_option("sat-preprocessor")) // no simplifier
220+
bool solver_set = false;
221+
if(options.is_set("sat-solver"))
222222
{
223-
// simplifier won't work with beautification
224-
solver->set_prop(
225-
make_satcheck_prop<satcheck_no_simplifiert>(message_handler, options));
223+
const std::string &solver_option = options.get_option("sat-solver");
224+
if(solver_option == "zchaff")
225+
{
226+
#if defined SATCHECK_ZCHAFF
227+
solver->set_prop(
228+
make_satcheck_prop<satcheck_zchafft>(message_handler, options));
229+
solver_set = true;
230+
#else
231+
emit_solver_warning("zchaff");
232+
#endif
233+
}
234+
else if(solver_option == "booleforce")
235+
{
236+
#if defined SATCHECK_BOOLERFORCE
237+
solver->set_prop(
238+
make_satcheck_prop<satcheck_booleforcet>(message_handler, options));
239+
solver_set = true;
240+
#else
241+
emit_solver_warning("booleforce");
242+
#endif
243+
}
244+
else if(solver_option == "minisat1")
245+
{
246+
#if defined SATCHECK_MINISAT1
247+
solver->set_prop(
248+
make_satcheck_prop<satcheck_minisat1t>(message_handler, options));
249+
solver_set = true;
250+
#else
251+
emit_solver_warning("minisat1");
252+
#endif
253+
}
254+
else if(solver_option == "minisat2")
255+
{
256+
#if defined SATCHECK_MINISAT2
257+
if(
258+
options.get_bool_option("beautify") ||
259+
!options.get_bool_option("sat-preprocessor")) // no simplifier
260+
{
261+
// simplifier won't work with beautification
262+
solver->set_prop(make_satcheck_prop<satcheck_minisat_no_simplifiert>(
263+
message_handler, options));
264+
}
265+
else // with simplifier
266+
{
267+
solver->set_prop(make_satcheck_prop<satcheck_minisat_simplifiert>(
268+
message_handler, options));
269+
}
270+
solver_set = true;
271+
#else
272+
emit_solver_warning("minisat2");
273+
#endif
274+
}
275+
else if(solver_option == "ipasir")
276+
{
277+
#if defined SATCHECK_IPASIR
278+
solver->set_prop(
279+
make_satcheck_prop<satcheck_ipasirt>(message_handler, options));
280+
solver_set = true;
281+
#else
282+
emit_solver_warning("ipasir");
283+
#endif
284+
}
285+
else if(solver_option == "picosat")
286+
{
287+
#if defined SATCHECK_PICOSAT
288+
solver->set_prop(
289+
make_satcheck_prop<satcheck_picosatt>(message_handler, options));
290+
solver_set = true;
291+
#else
292+
emit_solver_warning("picosat");
293+
#endif
294+
}
295+
else if(solver_option == "lingeling")
296+
{
297+
#if defined SATCHECK_LINGELING
298+
solver->set_prop(
299+
make_satcheck_prop<satcheck_lingelingt>(message_handler, options));
300+
solver_set = true;
301+
#else
302+
emit_solver_warning("lingeling");
303+
#endif
304+
}
305+
else if(solver_option == "glucose")
306+
{
307+
#if defined SATCHECK_GLUCOSE
308+
if(
309+
options.get_bool_option("beautify") ||
310+
!options.get_bool_option("sat-preprocessor")) // no simplifier
311+
{
312+
// simplifier won't work with beautification
313+
solver->set_prop(make_satcheck_prop<satcheck_glucose_no_simplifiert>(
314+
message_handler, options));
315+
}
316+
else // with simplifier
317+
{
318+
solver->set_prop(make_satcheck_prop<satcheck_glucose_simplifiert>(
319+
message_handler, options));
320+
}
321+
solver_set = true;
322+
#else
323+
emit_solver_warning("glucose");
324+
#endif
325+
}
326+
else if(solver_option == "cadical")
327+
{
328+
#if defined SATCHECK_CADICAL
329+
solver->set_prop(
330+
make_satcheck_prop<satcheck_cadicalt>(message_handler, options));
331+
solver_set = true;
332+
#else
333+
emit_solver_warning("cadical");
334+
#endif
335+
}
336+
else
337+
{
338+
messaget log(message_handler);
339+
log.error() << "unknown solver '" << solver_option << "'"
340+
<< messaget::eom;
341+
exit(CPROVER_EXIT_USAGE_ERROR);
342+
}
226343
}
227-
else // with simplifier
344+
if(!solver_set)
228345
{
229-
solver->set_prop(make_satcheck_prop<satcheckt>(message_handler, options));
346+
// default solver
347+
if(
348+
options.get_bool_option("beautify") ||
349+
!options.get_bool_option("sat-preprocessor")) // no simplifier
350+
{
351+
// simplifier won't work with beautification
352+
solver->set_prop(
353+
make_satcheck_prop<satcheck_no_simplifiert>(message_handler, options));
354+
}
355+
else // with simplifier
356+
{
357+
solver->set_prop(make_satcheck_prop<satcheckt>(message_handler, options));
358+
}
230359
}
231360

232361
bool get_array_constraints =
@@ -245,6 +374,14 @@ std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_default()
245374
return solver;
246375
}
247376

377+
void solver_factoryt::emit_solver_warning(const std::string &solver)
378+
{
379+
messaget log(message_handler);
380+
log.warning() << "The specified solver, '" << solver
381+
<< "', is not available. "
382+
<< "The default solver will be used instead." << messaget::eom;
383+
}
384+
248385
std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_dimacs()
249386
{
250387
no_beautification();
@@ -517,6 +654,9 @@ static void parse_sat_options(const cmdlinet &cmdline, optionst &options)
517654

518655
if(cmdline.isset("dimacs"))
519656
options.set_option("dimacs", true);
657+
658+
if(cmdline.isset("sat-solver"))
659+
options.set_option("sat-solver", cmdline.get_value("sat-solver"));
520660
}
521661

522662
static void parse_smt2_options(const cmdlinet &cmdline, optionst &options)

src/goto-checker/solver_factory.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class solver_factoryt final
7070
message_handlert &message_handler;
7171
const bool output_xml_in_refinement;
7272

73-
std::unique_ptr<solvert> get_default();
73+
std::unique_ptr<solvert> get_sat_solver();
7474
std::unique_ptr<solvert> get_dimacs();
7575
std::unique_ptr<solvert> get_external_sat();
7676
std::unique_ptr<solvert> get_bv_refinement();
@@ -89,6 +89,9 @@ class solver_factoryt final
8989
// consistency checks during solver creation
9090
void no_beautification();
9191
void no_incremental_check();
92+
93+
// emit a warning for non-existent solver
94+
void emit_solver_warning(const std::string &solver);
9295
};
9396

9497
/// Parse solver-related command-line parameters in \p cmdline and set
@@ -104,6 +107,7 @@ void parse_solver_options(const cmdlinet &cmdline, optionst &options);
104107
"(mathsat)" \
105108
"(cprover-smt2)" \
106109
"(incremental-smt2-solver):" \
110+
"(sat-solver):" \
107111
"(external-sat-solver):" \
108112
"(no-sat-preprocessor)" \
109113
"(beautify)" \
@@ -126,6 +130,7 @@ void parse_solver_options(const cmdlinet &cmdline, optionst &options);
126130
" --smt2 use default SMT2 solver (Z3)\n" \
127131
" --bitwuzla use Bitwuzla\n" \
128132
" --boolector use Boolector\n" \
133+
" --sat-solver solver use specified SAT solver\n" \
129134
" --cprover-smt2 use CPROVER SMT2 solver\n" \
130135
" --cvc3 use CVC3\n" \
131136
" --cvc4 use CVC4\n" \

0 commit comments

Comments
 (0)