Skip to content

Commit c0b29cb

Browse files
authored
Merge pull request #4758 from tautschnig/cadical
Add CaDiCaL support to CMake
2 parents 60feede + 528164d commit c0b29cb

11 files changed

+210
-48
lines changed

.github/workflows/pull-request-checks.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ jobs:
332332
run: |
333333
mkdir build
334334
cd build
335-
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
335+
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -Dsat_impl=cadical
336336
- name: Build using Ninja
337337
run: |
338338
cd build

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ endif()
6565
set(enable_cbmc_tests on CACHE BOOL "Whether CBMC tests should be enabled")
6666

6767
set(sat_impl "minisat2" CACHE STRING
68-
"This setting controls the SAT library which is used. Valid values are 'minisat2' and 'glucose'"
68+
"This setting controls the SAT library which is used. Valid values are
69+
'minisat2', 'glucose', or 'cadical'"
6970
)
7071

7172
if(${enable_cbmc_tests})

scripts/cadical-patch

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,14 @@ glucose-download:
152152
@(cd ../glucose-syrup; patch -p1 < ../scripts/glucose-syrup-patch)
153153
@rm glucose-syrup.tgz
154154

155-
cadical_release = rel-06w
155+
cadical_release = rel-1.3.0
156156
cadical-download:
157157
@echo "Downloading CaDiCaL $(cadical_release)"
158158
@$(DOWNLOADER) https://github.com/arminbiere/cadical/archive/$(cadical_release).tar.gz
159159
@$(TAR) xfz $(cadical_release).tar.gz
160160
@rm -Rf ../cadical
161161
@mv cadical-$(cadical_release) ../cadical
162-
@(cd ../cadical; patch -p1 < ../scripts/cadical-patch)
163-
@cd ../cadical && CXX=$(CXX) CXXFLAGS=-O3 ./configure --debug && make
162+
@cd ../cadical && CXX=$(CXX) ./configure -O3 -s -j && make
164163
@$(RM) $(cadical_release).tar.gz
165164

166165
doc :

src/solvers/CMakeLists.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,36 @@ elseif("${sat_impl}" STREQUAL "glucose")
9898
target_sources(solvers PRIVATE ${glucose_source})
9999

100100
target_link_libraries(solvers glucose-condensed)
101+
elseif("${sat_impl}" STREQUAL "cadical")
102+
message(STATUS "Building solvers with cadical")
103+
104+
download_project(PROJ cadical
105+
URL https://github.com/arminbiere/cadical/archive/rel-1.3.0.tar.gz
106+
PATCH_COMMAND true
107+
COMMAND CXX=${CMAKE_CXX_COMPILER} ./configure -O3 -s -j
108+
URL_MD5 5bd15d1e198d2e904a8af8b7873dd341
109+
)
110+
111+
message(STATUS "Building CaDiCaL")
112+
execute_process(COMMAND make WORKING_DIRECTORY ${cadical_SOURCE_DIR})
113+
114+
target_compile_definitions(solvers PUBLIC
115+
SATCHECK_CADICAL HAVE_CADICAL
116+
)
117+
118+
add_library(cadical STATIC IMPORTED)
119+
120+
set_target_properties(
121+
cadical
122+
PROPERTIES IMPORTED_LOCATION ${cadical_SOURCE_DIR}/build/libcadical.a
123+
)
124+
125+
target_include_directories(solvers
126+
PUBLIC
127+
${cadical_SOURCE_DIR}/src
128+
)
129+
130+
target_link_libraries(solvers cadical)
101131
endif()
102132

103133
if(CMAKE_USE_CUDD)

src/solvers/refinement/bv_refinement_loop.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ void bv_refinementt::check_SAT()
123123

124124
arrays_overapproximated();
125125

126+
// get values before modifying the formula
127+
for(approximationt &approximation : this->approximations)
128+
get_values(approximation);
129+
126130
for(approximationt &approximation : this->approximations)
127131
check_SAT(approximation);
128132
}

src/solvers/refinement/refine_arithmetic.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,6 @@ void bv_refinementt::get_values(approximationt &a)
158158
/// refine overapproximation
159159
void bv_refinementt::check_SAT(approximationt &a)
160160
{
161-
// get values
162-
get_values(a);
163-
164161
// see if the satisfying assignment is spurious in any way
165162

166163
const typet &type = a.expr.type();

src/solvers/sat/satcheck_cadical.cpp

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Michael Tautschnig
1010

1111
#include <util/exception_utils.h>
1212
#include <util/invariant.h>
13+
#include <util/narrow.h>
1314
#include <util/threeval.h>
1415

1516
#ifdef HAVE_CADICAL
@@ -23,7 +24,7 @@ tvt satcheck_cadicalt::l_get(literalt a) const
2324

2425
tvt result;
2526

26-
if(a.var_no() > static_cast<unsigned>(solver->max()))
27+
if(a.var_no() > narrow<unsigned>(solver->vars()))
2728
return tvt(tvt::tv_enumt::TV_UNKNOWN);
2829

2930
const int val = solver->val(a.dimacs());
@@ -62,6 +63,23 @@ void satcheck_cadicalt::lcnf(const bvt &bv)
6263
}
6364
solver->add(0); // terminate clause
6465

66+
with_solver_hardness([this, &bv](solver_hardnesst &hardness) {
67+
// To map clauses to lines of program code, track clause indices in the
68+
// dimacs cnf output. Dimacs output is generated after processing
69+
// clauses to remove duplicates and clauses that are trivially true.
70+
// Here, a clause is checked to see if it can be thus eliminated. If
71+
// not, add the clause index to list of clauses in
72+
// solver_hardnesst::register_clause().
73+
static size_t cnf_clause_index = 0;
74+
bvt cnf;
75+
bool clause_removed = process_clause(bv, cnf);
76+
77+
if(!clause_removed)
78+
cnf_clause_index++;
79+
80+
hardness.register_clause(bv, cnf, cnf_clause_index, !clause_removed);
81+
});
82+
6583
clause_counter++;
6684
}
6785

@@ -72,31 +90,37 @@ propt::resultt satcheck_cadicalt::do_prop_solve()
7290
log.statistics() << (no_variables() - 1) << " variables, " << clause_counter
7391
<< " clauses" << messaget::eom;
7492

75-
if(status == statust::UNSAT)
93+
// if assumptions contains false, we need this to be UNSAT
94+
for(const auto &a : assumptions)
7695
{
77-
log.status() << "SAT checker inconsistent: instance is UNSATISFIABLE"
78-
<< messaget::eom;
79-
}
80-
else
81-
{
82-
switch(solver->solve())
96+
if(a.is_false())
8397
{
84-
case 10:
85-
log.status() << "SAT checker: instance is SATISFIABLE" << messaget::eom;
86-
status = statust::SAT;
87-
return resultt::P_SATISFIABLE;
88-
case 20:
89-
log.status() << "SAT checker: instance is UNSATISFIABLE"
90-
<< messaget::eom;
91-
break;
92-
default:
93-
log.status() << "SAT checker: solving returned without solution"
94-
<< messaget::eom;
95-
throw analysis_exceptiont(
96-
"solving inside CaDiCaL SAT solver has been interrupted");
98+
log.status() << "got FALSE as assumption: instance is UNSATISFIABLE"
99+
<< messaget::eom;
100+
status = statust::UNSAT;
101+
return resultt::P_UNSATISFIABLE;
97102
}
98103
}
99104

105+
for(const auto &a : assumptions)
106+
solver->assume(a.dimacs());
107+
108+
switch(solver->solve())
109+
{
110+
case 10:
111+
log.status() << "SAT checker: instance is SATISFIABLE" << messaget::eom;
112+
status = statust::SAT;
113+
return resultt::P_SATISFIABLE;
114+
case 20:
115+
log.status() << "SAT checker: instance is UNSATISFIABLE" << messaget::eom;
116+
break;
117+
default:
118+
log.status() << "SAT checker: solving returned without solution"
119+
<< messaget::eom;
120+
throw analysis_exceptiont(
121+
"solving inside CaDiCaL SAT solver has been interrupted");
122+
}
123+
100124
status = statust::UNSAT;
101125
return resultt::P_UNSATISFIABLE;
102126
}
@@ -107,8 +131,8 @@ void satcheck_cadicalt::set_assignment(literalt a, bool value)
107131
INVARIANT(false, "method not supported");
108132
}
109133

110-
satcheck_cadicalt::satcheck_cadicalt() :
111-
solver(new CaDiCaL::Solver())
134+
satcheck_cadicalt::satcheck_cadicalt(message_handlert &message_handler)
135+
: cnf_solvert(message_handler), solver(new CaDiCaL::Solver())
112136
{
113137
solver->set("quiet", 1);
114138
}
@@ -120,13 +144,20 @@ satcheck_cadicalt::~satcheck_cadicalt()
120144

121145
void satcheck_cadicalt::set_assumptions(const bvt &bv)
122146
{
123-
INVARIANT(false, "method not supported");
147+
// We filter out 'true' assumptions which cause spurious results with CaDiCaL.
148+
assumptions.clear();
149+
for(const auto &assumption : bv)
150+
{
151+
if(!assumption.is_true())
152+
{
153+
assumptions.push_back(assumption);
154+
}
155+
}
124156
}
125157

126158
bool satcheck_cadicalt::is_in_conflict(literalt a) const
127159
{
128-
INVARIANT(false, "method not supported");
129-
return false;
160+
return solver->failed(a.dimacs());
130161
}
131162

132163
#endif

src/solvers/sat/satcheck_cadical.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ Author: Michael Tautschnig
1212

1313
#include "cnf.h"
1414

15+
#include <solvers/hardness_collector.h>
16+
1517
namespace CaDiCaL // NOLINT(readability/namespace)
1618
{
1719
class Solver; // NOLINT(readability/identifiers)
1820
}
1921

20-
class satcheck_cadicalt:public cnf_solvert
22+
class satcheck_cadicalt : public cnf_solvert, public hardness_collectort
2123
{
2224
public:
23-
satcheck_cadicalt();
25+
explicit satcheck_cadicalt(message_handlert &message_handler);
2426
virtual ~satcheck_cadicalt();
2527

2628
const std::string solver_text() override;
@@ -32,19 +34,37 @@ class satcheck_cadicalt:public cnf_solvert
3234
void set_assumptions(const bvt &_assumptions) override;
3335
bool has_set_assumptions() const override
3436
{
35-
return false;
37+
return true;
3638
}
3739
bool has_is_in_conflict() const override
3840
{
39-
return false;
41+
return true;
4042
}
4143
bool is_in_conflict(literalt a) const override;
4244

45+
void
46+
with_solver_hardness(std::function<void(solver_hardnesst &)> handler) override
47+
{
48+
if(solver_hardness.has_value())
49+
{
50+
handler(solver_hardness.value());
51+
}
52+
}
53+
54+
void enable_hardness_collection() override
55+
{
56+
solver_hardness = solver_hardnesst{};
57+
}
58+
4359
protected:
4460
resultt do_prop_solve() override;
4561

4662
// NOLINTNEXTLINE(readability/identifiers)
4763
CaDiCaL::Solver * solver;
64+
65+
bvt assumptions;
66+
67+
optionalt<solver_hardnesst> solver_hardness;
4868
};
4969

5070
#endif // CPROVER_SOLVERS_SAT_SATCHECK_CADICAL_H

unit/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ SRC += analyses/ai/ai.cpp \
6969
solvers/lowering/byte_operators.cpp \
7070
solvers/prop/bdd_expr.cpp \
7171
solvers/sat/external_sat.cpp \
72+
solvers/sat/satcheck_cadical.cpp \
7273
solvers/sat/satcheck_minisat2.cpp \
7374
solvers/strings/array_pool/array_pool.cpp \
7475
solvers/strings/string_constraint_generator_valueof/calculate_max_string_length.cpp \
@@ -228,6 +229,9 @@ endif
228229
ifeq ($(MINISAT2),)
229230
EXCLUDED_TESTS += satcheck_minisat2.cpp
230231
endif
232+
ifeq ($(CADICAL),)
233+
EXCLUDED_TESTS += satcheck_cadical.cpp
234+
endif
231235

232236
N_CATCH_TESTS = $(shell \
233237
cat $$(find . -name "*.cpp" \

0 commit comments

Comments
 (0)