Skip to content

Commit 2a1c22b

Browse files
Merge pull request #4810 from peterschrammel/minisat2-unit-test
satcheck_minisat2 assumptions bug fix and unit tests
2 parents 8d42d90 + c2de887 commit 2a1c22b

File tree

4 files changed

+151
-67
lines changed

4 files changed

+151
-67
lines changed

src/solvers/sat/satcheck_minisat2.cpp

Lines changed: 60 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -178,89 +178,80 @@ propt::resultt satcheck_minisat2_baset<T>::do_prop_solve()
178178
{
179179
log.status() << "SAT checker inconsistent: instance is UNSATISFIABLE"
180180
<< messaget::eom;
181+
status = statust::UNSAT;
182+
return resultt::P_UNSATISFIABLE;
181183
}
182-
else
183-
{
184-
// if assumptions contains false, we need this to be UNSAT
185-
bool has_false=false;
186-
187-
forall_literals(it, assumptions)
188-
if(it->is_false())
189-
has_false=true;
190184

191-
if(has_false)
185+
// if assumptions contains false, we need this to be UNSAT
186+
for(const auto &assumption : assumptions)
187+
{
188+
if(assumption.is_false())
192189
{
193190
log.status() << "got FALSE as assumption: instance is UNSATISFIABLE"
194191
<< messaget::eom;
192+
status = statust::UNSAT;
193+
return resultt::P_UNSATISFIABLE;
195194
}
196-
else
197-
{
198-
Minisat::vec<Minisat::Lit> solver_assumptions;
199-
convert(assumptions, solver_assumptions);
195+
}
200196

201-
using Minisat::lbool;
197+
Minisat::vec<Minisat::Lit> solver_assumptions;
198+
convert(assumptions, solver_assumptions);
199+
200+
using Minisat::lbool;
202201

203202
#ifndef _WIN32
204203

205-
void (*old_handler)(int)=SIG_ERR;
204+
void (*old_handler)(int) = SIG_ERR;
206205

207-
if(time_limit_seconds!=0)
208-
{
209-
solver_to_interrupt=solver;
210-
old_handler=signal(SIGALRM, interrupt_solver);
211-
if(old_handler==SIG_ERR)
212-
log.warning() << "Failed to set solver time limit" << messaget::eom;
213-
else
214-
alarm(time_limit_seconds);
215-
}
206+
if(time_limit_seconds != 0)
207+
{
208+
solver_to_interrupt = solver;
209+
old_handler = signal(SIGALRM, interrupt_solver);
210+
if(old_handler == SIG_ERR)
211+
log.warning() << "Failed to set solver time limit" << messaget::eom;
212+
else
213+
alarm(time_limit_seconds);
214+
}
216215

217-
lbool solver_result=solver->solveLimited(solver_assumptions);
216+
lbool solver_result = solver->solveLimited(solver_assumptions);
218217

219-
if(old_handler!=SIG_ERR)
220-
{
221-
alarm(0);
222-
signal(SIGALRM, old_handler);
223-
solver_to_interrupt=solver;
224-
}
218+
if(old_handler != SIG_ERR)
219+
{
220+
alarm(0);
221+
signal(SIGALRM, old_handler);
222+
solver_to_interrupt = solver;
223+
}
225224

226225
#else // _WIN32
227226

228-
if(time_limit_seconds!=0)
229-
{
230-
log.warning() << "Time limit ignored (not supported on Win32 yet)"
231-
<< messaget::eom;
232-
}
227+
if(time_limit_seconds != 0)
228+
{
229+
log.warning() << "Time limit ignored (not supported on Win32 yet)"
230+
<< messaget::eom;
231+
}
233232

234-
lbool solver_result=
235-
solver->solve(solver_assumptions) ? l_True : l_False;
233+
lbool solver_result = solver->solve(solver_assumptions) ? l_True : l_False;
236234

237235
#endif
238236

239-
if(solver_result==l_True)
240-
{
241-
log.status() << "SAT checker: instance is SATISFIABLE"
242-
<< messaget::eom;
243-
CHECK_RETURN(solver->model.size()>0);
244-
status=statust::SAT;
245-
return resultt::P_SATISFIABLE;
246-
}
247-
else if(solver_result==l_False)
248-
{
249-
log.status() << "SAT checker: instance is UNSATISFIABLE"
250-
<< messaget::eom;
251-
}
252-
else
253-
{
254-
log.status() << "SAT checker: timed out or other error"
255-
<< messaget::eom;
256-
status=statust::ERROR;
257-
return resultt::P_ERROR;
258-
}
259-
}
237+
if(solver_result == l_True)
238+
{
239+
log.status() << "SAT checker: instance is SATISFIABLE" << messaget::eom;
240+
CHECK_RETURN(solver->model.size() > 0);
241+
status = statust::SAT;
242+
return resultt::P_SATISFIABLE;
243+
}
244+
245+
if(solver_result == l_False)
246+
{
247+
log.status() << "SAT checker: instance is UNSATISFIABLE" << messaget::eom;
248+
status = statust::UNSAT;
249+
return resultt::P_UNSATISFIABLE;
260250
}
261251

262-
status=statust::UNSAT;
263-
return resultt::P_UNSATISFIABLE;
252+
log.status() << "SAT checker: timed out or other error" << messaget::eom;
253+
status = statust::ERROR;
254+
return resultt::P_ERROR;
264255
}
265256
catch(const Minisat::OutOfMemoryException &)
266257
{
@@ -328,14 +319,16 @@ bool satcheck_minisat2_baset<T>::is_in_conflict(literalt a) const
328319
template<typename T>
329320
void satcheck_minisat2_baset<T>::set_assumptions(const bvt &bv)
330321
{
331-
assumptions=bv;
332-
333-
forall_literals(it, assumptions)
334-
if(it->is_true())
322+
// We filter out 'true' assumptions which cause an assertion violation
323+
// in Minisat2.
324+
assumptions.clear();
325+
for(const auto &assumption : bv)
326+
{
327+
if(!assumption.is_true())
335328
{
336-
assumptions.clear();
337-
break;
329+
assumptions.push_back(assumption);
338330
}
331+
}
339332
}
340333

341334
satcheck_minisat_no_simplifiert::satcheck_minisat_no_simplifiert(

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ SRC += analyses/ai/ai.cpp \
4545
solvers/floatbv/float_utils.cpp \
4646
solvers/lowering/byte_operators.cpp \
4747
solvers/prop/bdd_expr.cpp \
48+
solvers/sat/satcheck_minisat2.cpp \
4849
solvers/strings/array_pool/array_pool.cpp \
4950
solvers/strings/string_constraint_generator_valueof/calculate_max_string_length.cpp \
5051
solvers/strings/string_constraint_generator_valueof/get_numeric_value_from_character.cpp \
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
solvers/prop
2+
solvers/sat
3+
testing-utils
4+
util
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for satcheck_minisat2
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Unit tests for satcheck_minisat2
11+
12+
#ifdef HAVE_MINISAT2
13+
14+
# include <testing-utils/use_catch.h>
15+
16+
# include <solvers/prop/literal.h>
17+
# include <solvers/sat/satcheck_minisat2.h>
18+
# include <util/cout_message.h>
19+
20+
SCENARIO("satcheck_minisat2", "[core][solvers][sat][satcheck_minisat2]")
21+
{
22+
console_message_handlert message_handler;
23+
24+
GIVEN("A satisfiable formula f")
25+
{
26+
satcheck_minisat_no_simplifiert satcheck(message_handler);
27+
literalt f = satcheck.new_variable();
28+
satcheck.l_set_to_true(f);
29+
30+
THEN("is indeed satisfiable")
31+
{
32+
REQUIRE(satcheck.prop_solve() == propt::resultt::P_SATISFIABLE);
33+
}
34+
THEN("is unsatisfiable under a false assumption")
35+
{
36+
bvt assumptions;
37+
assumptions.push_back(const_literal(false));
38+
satcheck.set_assumptions(assumptions);
39+
REQUIRE(satcheck.prop_solve() == propt::resultt::P_UNSATISFIABLE);
40+
}
41+
}
42+
43+
GIVEN("An unsatisfiable formula f && !f")
44+
{
45+
satcheck_minisat_no_simplifiert satcheck(message_handler);
46+
literalt f = satcheck.new_variable();
47+
satcheck.l_set_to_true(satcheck.land(f, !f));
48+
49+
THEN("is indeed unsatisfiable")
50+
{
51+
REQUIRE(satcheck.prop_solve() == propt::resultt::P_UNSATISFIABLE);
52+
}
53+
}
54+
55+
GIVEN("An unsatisfiable formula false implied by a")
56+
{
57+
satcheck_minisat_no_simplifiert satcheck(message_handler);
58+
literalt a = satcheck.new_variable();
59+
literalt a_implies_false = satcheck.lor(!a, const_literal(false));
60+
satcheck.l_set_to_true(a_implies_false);
61+
62+
THEN("is indeed unsatisfiable under assumption a")
63+
{
64+
bvt assumptions;
65+
assumptions.push_back(a);
66+
satcheck.set_assumptions(assumptions);
67+
REQUIRE(satcheck.prop_solve() == propt::resultt::P_UNSATISFIABLE);
68+
}
69+
THEN("is still unsatisfiable under assumption a and true")
70+
{
71+
bvt assumptions;
72+
assumptions.push_back(const_literal(true));
73+
assumptions.push_back(a);
74+
satcheck.set_assumptions(assumptions);
75+
REQUIRE(satcheck.prop_solve() == propt::resultt::P_UNSATISFIABLE);
76+
}
77+
THEN("becomes satisfiable when assumption a is lifted")
78+
{
79+
bvt assumptions;
80+
satcheck.set_assumptions(assumptions);
81+
REQUIRE(satcheck.prop_solve() == propt::resultt::P_SATISFIABLE);
82+
}
83+
}
84+
}
85+
86+
#endif

0 commit comments

Comments
 (0)