Skip to content

Commit 14419d2

Browse files
author
Norbert Manthey
committed
solvers: add ipasir driver
Add the necessary source changes to allow CBMC to use IPASIR solvers.
1 parent 8aa89be commit 14419d2

File tree

5 files changed

+314
-1
lines changed

5 files changed

+314
-1
lines changed

src/solvers/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ ifneq ($(MINISAT2),)
2121
CP_CXXFLAGS += -DHAVE_MINISAT2 -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
2222
endif
2323

24+
ifneq ($(IPASIR),)
25+
IPASIR_SRC=sat/satcheck_ipasir.cpp
26+
IPASIR_INCLUDE=-I $(IPASIR)
27+
IPASIR_LIB=$(IPASIR)/ipasir.a
28+
CP_CXXFLAGS += -DHAVE_IPASIR -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
29+
override CXXFLAGS := $(filter-out -pedantic, $(CXXFLAGS))
30+
endif
31+
2432
ifneq ($(GLUCOSE),)
2533
GLUCOSE_SRC=sat/satcheck_glucose.cpp
2634
GLUCOSE_INCLUDE=-I $(GLUCOSE)
@@ -82,6 +90,7 @@ SRC = $(BOOLEFORCE_SRC) \
8290
$(GLUCOSE_SRC) \
8391
$(LINGELING_SRC) \
8492
$(MINISAT2_SRC) \
93+
$(IPASIR_SRC) \
8594
$(MINISAT_SRC) \
8695
$(PICOSAT_SRC) \
8796
$(PRECOSAT_SRC) \
@@ -198,6 +207,7 @@ SRC = $(BOOLEFORCE_SRC) \
198207

199208
INCLUDES += -I .. \
200209
$(CHAFF_INCLUDE) $(BOOLEFORCE_INCLUDE) $(MINISAT_INCLUDE) $(MINISAT2_INCLUDE) \
210+
$(IPASIR_INCLUDE) \
201211
$(SMVSAT_INCLUDE) $(SQUOLEM2_INC) $(CUDD_INCLUDE) $(GLUCOSE_INCLUDE) \
202212
$(PRECOSAT_INCLUDE) $(PICOSAT_INCLUDE) $(LINGELING_INCLUDE)
203213

src/solvers/prop/literal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ inline literalt neg(literalt a) { return !a; }
193193
inline literalt pos(literalt a) { return a; }
194194

195195

196+
inline bool is_false (const literalt &l) { return (l.is_false()); }
197+
inline bool is_true (const literalt &l) { return (l.is_true()); }
198+
196199
// bit-vectors
197200
typedef std::vector<literalt> bvt;
198201

src/solvers/sat/satcheck.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Author: Daniel Kroening, [email protected]
1010
#ifndef CPROVER_SOLVERS_SAT_SATCHECK_H
1111
#define CPROVER_SOLVERS_SAT_SATCHECK_H
1212

13-
// this picks the "default" SAT solver
13+
// This sets a define for the SAT solver
14+
// based on set flags that come via the compiler
15+
// command line.
1416

1517
// #define SATCHECK_ZCHAFF
1618
// #define SATCHECK_MINISAT1
@@ -21,6 +23,42 @@ Author: Daniel Kroening, [email protected]
2123
// #define SATCHECK_PICOSAT
2224
// #define SATCHECK_LINGELING
2325

26+
#if defined(HAVE_IPASIR) && !defined(SATCHECK_IPASIR)
27+
#define SATCHECK_IPASIR
28+
#endif
29+
30+
#if defined(HAVE_ZCHAFF) && !defined(SATCHECK_ZCHAFF)
31+
#define SATCHECK_ZCHAFF
32+
#endif
33+
34+
#if defined(HAVE_MINISAT1) && !defined(SATCHECK_MINISAT1)
35+
#define SATCHECK_MINISAT1
36+
#endif
37+
38+
#if defined(HAVE_MINISAT2) && !defined(SATCHECK_MINISAT2)
39+
#define SATCHECK_MINISAT2
40+
#endif
41+
42+
#if defined(HAVE_GLUCOSE) && !defined(SATCHECK_GLUCOSE)
43+
#define SATCHECK_GLUCOSE
44+
#endif
45+
46+
#if defined(HAVE_BOOLEFORCE) && !defined(SATCHECK_BOOLEFORCE)
47+
#define SATCHECK_BOOLEFORCE
48+
#endif
49+
50+
#if defined(HAVE_PRECOSAT) && !defined(SATCHECK_PRECOSAT)
51+
#define SATCHECK_PRECOSAT
52+
#endif
53+
54+
#if defined(HAVE_PICOSAT) && !defined(SATCHECK_PICOSAT)
55+
#define SATCHECK_PICOSAT
56+
#endif
57+
58+
#if defined(HAVE_LINGELING) && !defined(SATCHECK_LINGELING)
59+
#define SATCHECK_LINGELING
60+
#endif
61+
2462
#if defined SATCHECK_ZCHAFF
2563

2664
#include "satcheck_zchaff.h"
@@ -49,6 +87,13 @@ typedef satcheck_minisat1t satcheck_no_simplifiert;
4987
typedef satcheck_minisat_simplifiert satcheckt;
5088
typedef satcheck_minisat_no_simplifiert satcheck_no_simplifiert;
5189

90+
#elif defined SATCHECK_IPASIR
91+
92+
#include "satcheck_ipasir.h"
93+
94+
typedef satcheck_ipasirt satcheckt;
95+
typedef satcheck_ipasirt satcheck_no_simplifiert;
96+
5297
#elif defined SATCHECK_PRECOSAT
5398

5499
#include "satcheck_precosat.h"

src/solvers/sat/satcheck_ipasir.cpp

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*******************************************************************\
2+
3+
Module: External SAT Solver Binding
4+
5+
Author: Norbert Manthey, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef _MSC_VER
10+
#include <inttypes.h>
11+
#endif
12+
13+
#include <algorithm>
14+
#include <cassert>
15+
#include <stack>
16+
17+
#include <util/threeval.h>
18+
19+
#include "satcheck_ipasir.h"
20+
21+
#ifdef HAVE_IPASIR
22+
23+
extern "C"
24+
{
25+
#include <ipasir.h>
26+
}
27+
28+
/*
29+
30+
Interface description:
31+
https://github.com/biotomas/ipasir/blob/master/ipasir.h
32+
33+
Representation:
34+
Variables for a formula start with 1! 0 is used as termination symbol.
35+
36+
*/
37+
38+
tvt satcheck_ipasirt::l_get(literalt a) const
39+
{
40+
if(a.is_true())
41+
return tvt(true);
42+
else if(a.is_false())
43+
return tvt(false);
44+
45+
tvt result;
46+
47+
// compare to internal no_variables number
48+
if(a.var_no()>=(unsigned)no_variables())
49+
return tvt::unknown();
50+
51+
const int val=ipasir_val(solver, a.var_no());
52+
53+
if(val>0)
54+
result=tvt(true);
55+
else if(val<0)
56+
result=tvt(false);
57+
else
58+
return tvt::unknown();
59+
60+
if(a.sign())
61+
result=!result;
62+
63+
return result;
64+
}
65+
66+
const std::string satcheck_ipasirt::solver_text()
67+
{
68+
return std::string(ipasir_signature());
69+
}
70+
71+
void satcheck_ipasirt::lcnf(const bvt &bv)
72+
{
73+
forall_literals(it, bv)
74+
{
75+
if(it->is_true())
76+
return;
77+
else if(!it->is_false())
78+
INVARIANT(it->var_no()<(unsigned)no_variables(),
79+
"reject out of bound variables");
80+
}
81+
82+
forall_literals(it, bv)
83+
{
84+
if(!it->is_false())
85+
{
86+
// add literal with correct sign
87+
ipasir_add(solver, it->dimacs());
88+
}
89+
}
90+
ipasir_add(solver, 0); // terminate clause
91+
92+
clause_counter++;
93+
}
94+
95+
propt::resultt satcheck_ipasirt::prop_solve()
96+
{
97+
INVARIANT(status!=statust::ERROR, "there cannot be an error");
98+
99+
{
100+
messaget::status() <<
101+
(no_variables()-1) << " variables, " <<
102+
clause_counter << " clauses" << eom;
103+
}
104+
105+
// use the internal representation, as ipasir does not support reporting the
106+
// status
107+
if(status==statust::UNSAT)
108+
{
109+
messaget::status() <<
110+
"SAT checker inconsistent: instance is UNSATISFIABLE" << eom;
111+
}
112+
else
113+
{
114+
// if assumptions contains false, we need this to be UNSAT
115+
bvt::const_iterator it = std::find_if(assumptions.begin(),
116+
assumptions.end(), is_false);
117+
const bool has_false = it != assumptions.end();
118+
119+
if(has_false)
120+
{
121+
messaget::status() <<
122+
"got FALSE as assumption: instance is UNSATISFIABLE" << eom;
123+
}
124+
else
125+
{
126+
forall_literals(it, assumptions)
127+
if(!it->is_false())
128+
ipasir_assume(solver, it->dimacs());
129+
130+
// solve the formula, and handle the return code (10=SAT, 20=UNSAT)
131+
int solver_state=ipasir_solve(solver);
132+
if(10==solver_state)
133+
{
134+
messaget::status() <<
135+
"SAT checker: instance is SATISFIABLE" << eom;
136+
status=statust::SAT;
137+
return resultt::P_SATISFIABLE;
138+
}
139+
else if(20==solver_state)
140+
{
141+
messaget::status() <<
142+
"SAT checker: instance is UNSATISFIABLE" << eom;
143+
}
144+
else
145+
{
146+
messaget::status() <<
147+
"SAT checker: solving returned without solution" << eom;
148+
throw "solving inside IPASIR SAT solver has been interrupted";
149+
}
150+
}
151+
}
152+
153+
status=statust::UNSAT;
154+
return resultt::P_UNSATISFIABLE;
155+
}
156+
157+
void satcheck_ipasirt::set_assignment(literalt a, bool value)
158+
{
159+
INVARIANT(!a.is_constant(), "cannot set an assignment for a constant");
160+
INVARIANT(false, "method not supported");
161+
}
162+
163+
satcheck_ipasirt::satcheck_ipasirt()
164+
: solver(nullptr)
165+
{
166+
INVARIANT(!solver, "there cannot be a solver already");
167+
solver=ipasir_init();
168+
}
169+
170+
satcheck_ipasirt::~satcheck_ipasirt()
171+
{
172+
if(solver)
173+
ipasir_release(solver);
174+
solver=nullptr;
175+
}
176+
177+
bool satcheck_ipasirt::is_in_conflict(literalt a) const
178+
{
179+
return ipasir_failed(solver, a.var_no());
180+
}
181+
182+
void satcheck_ipasirt::set_assumptions(const bvt &bv)
183+
{
184+
bvt::const_iterator it = std::find_if(bv.begin(), bv.end(), is_true);
185+
const bool has_true = it != bv.end();
186+
187+
if(has_true)
188+
{
189+
assumptions.clear();
190+
return;
191+
}
192+
// only copy assertions, if there is no false in bt parameter
193+
assumptions=bv;
194+
}
195+
196+
#endif

src/solvers/sat/satcheck_ipasir.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Norbert Manthey, [email protected]
6+
7+
Sample compilation command:
8+
(to be executed from base directory of project)
9+
10+
make clean
11+
make ipasir-build
12+
CXXFLAGS=-g IPASIR=../../ipasir LIBSOLVER=$(pwd)/ipasir/libipasir.a \
13+
CFLAGS="-Wall -O2 -DSATCHECK_IPSAIR" LINKFLAGS="-static" \
14+
make -j 7 -C $(pwd)/src/;
15+
16+
Note: Make sure, the LIBSOLVER variable is set in the environment!
17+
The variable should point to the solver you actually want to
18+
link against.
19+
20+
\*******************************************************************/
21+
22+
#ifndef CPROVER_SOLVERS_SAT_SATCHECK_IPASIR_H
23+
#define CPROVER_SOLVERS_SAT_SATCHECK_IPASIR_H
24+
25+
#include "cnf.h"
26+
27+
/// Interface for generic SAT solver interface IPASIR
28+
class satcheck_ipasirt:public cnf_solvert
29+
{
30+
public:
31+
satcheck_ipasirt();
32+
virtual ~satcheck_ipasirt() override;
33+
34+
/// This method returns the description produced by the linked SAT solver
35+
virtual const std::string solver_text() override;
36+
37+
virtual resultt prop_solve() override;
38+
39+
/// This method returns the truth value for a literal of the current SAT model
40+
virtual tvt l_get(literalt a) const override final;
41+
42+
virtual void lcnf(const bvt &bv) override final;
43+
44+
/* This method is not supported, and currently not called anywhere in CBMC */
45+
virtual void set_assignment(literalt a, bool value) override;
46+
47+
virtual void set_assumptions(const bvt &_assumptions) override;
48+
49+
virtual bool is_in_conflict(literalt a) const override;
50+
virtual bool has_set_assumptions() const override final { return true; }
51+
virtual bool has_is_in_conflict() const override final { return true; }
52+
53+
protected:
54+
void *solver;
55+
56+
bvt assumptions;
57+
};
58+
59+
#endif // CPROVER_SOLVERS_SAT_SATCHECK_IPASIR_H

0 commit comments

Comments
 (0)