3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 09:35:32 +00:00

adding smt parallel solving

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-04-15 16:16:48 -07:00
parent 252fb4af6e
commit 012a96fd81
17 changed files with 174 additions and 73 deletions

View file

@ -8,6 +8,7 @@ z3_add_component(portfolio
pb2bv_solver.cpp
smt_strategic_solver.cpp
solver2lookahead.cpp
solver_sat_extension.cpp
COMPONENT_DEPENDENCIES
aig_tactic
fp

View file

@ -41,8 +41,13 @@ Notes:
#include "solver/solver.h"
#include "solver/solver2tactic.h"
#include "tactic/tactic.h"
#include "tactic/tactical.h"
#include "tactic/portfolio/fd_solver.h"
#include "tactic/smtlogics/parallel_params.hpp"
#include "smt/tactic/smt_tactic.h"
#include "smt/smt_solver.h"
#include "sat/sat_solver/inc_sat_solver.h"
#include "sat/tactic/sat_tactic.h"
class parallel_tactic : public tactic {
@ -184,7 +189,6 @@ class parallel_tactic : public tactic {
ref<solver> m_solver; // solver state
unsigned m_depth; // number of nested calls to cubing
double m_width; // estimate of fraction of problem handled by state
unsigned m_restart_max; // saved configuration value
public:
solver_state(ast_manager* m, solver* s, params_ref const& p, task_type t):
@ -196,8 +200,6 @@ class parallel_tactic : public tactic {
m_depth(0),
m_width(1.0)
{
parallel_params pp(p);
m_restart_max = pp.restart_max();
}
ast_manager& m() { return m_solver->get_manager(); }
@ -255,27 +257,12 @@ class parallel_tactic : public tactic {
lbool simplify() {
lbool r = l_undef;
if (m_depth == 1) {
IF_VERBOSE(2, verbose_stream() << "(parallel.tactic simplify-1)\n";);
set_simplify_params(true, true); // retain PB, retain blocked
r = get_solver().check_sat(0,0);
if (r != l_undef) return r;
// copy over the resulting clauses with a configuration that blasts PB constraints
set_simplify_params(false, true);
expr_ref_vector fmls(m());
get_solver().get_assertions(fmls);
model_converter_ref mc = get_solver().get_model_converter();
m_solver = mk_fd_solver(m(), m_params);
m_solver->set_model_converter(mc.get());
m_solver->assert_expr(fmls);
}
IF_VERBOSE(2, verbose_stream() << "(parallel.tactic simplify-2)\n";);
set_simplify_params(false, true); // remove PB, retain blocked
IF_VERBOSE(2, verbose_stream() << "(parallel.tactic simplify-1)\n";);
set_simplify_params(true); // retain blocked
r = get_solver().check_sat(0,0);
if (r != l_undef) return r;
IF_VERBOSE(2, verbose_stream() << "(parallel.tactic simplify-3)\n";);
set_simplify_params(false, false); // remove any PB, remove blocked
IF_VERBOSE(2, verbose_stream() << "(parallel.tactic simplify-2)\n";);
set_simplify_params(false); // remove blocked
r = get_solver().check_sat(0,0);
return r;
}
@ -299,27 +286,26 @@ class parallel_tactic : public tactic {
}
void set_conquer_params(solver& s) {
parallel_params pp(m_params);
params_ref p;
p.copy(m_params);
p.set_bool("gc.burst", true); // apply eager gc
p.set_uint("simplify.delay", 1000); // delay simplification by 1000 conflicts
p.set_bool("lookahead_simplify", false);
p.set_uint("restart.max", m_restart_max);
p.set_uint("restart.max", pp.conquer_restart_max());
p.set_uint("inprocess.max", UINT_MAX); // base bounds on restart.max
s.updt_params(p);
}
void set_simplify_params(bool pb_simp, bool retain_blocked) {
void set_simplify_params(bool retain_blocked) {
parallel_params pp(m_params);
double mul = pp.simplify_multiplier();
unsigned mult = (mul == 0 ? 1 : std::max((unsigned)1, static_cast<unsigned>(m_depth * mul)));
params_ref p;
p.copy(m_params);
p.set_bool("cardinality.solver", pb_simp);
p.set_sym ("pb.solver", pb_simp ? symbol("solver") : symbol("circuit"));
if (p.get_uint("inprocess.max", UINT_MAX) == UINT_MAX)
p.set_uint("inprocess.max", pp.inprocess_max());
p.set_uint("inprocess.max", pp.simplify_inprocess_max() * mult);
p.set_uint("restart.max", pp.simplify_restart_max() * mult);
p.set_bool("lookahead_simplify", true);
p.set_uint("restart.max", UINT_MAX);
p.set_bool("retain_blocked_clauses", retain_blocked);
get_solver().updt_params(p);
}
@ -337,6 +323,7 @@ class parallel_tactic : public tactic {
private:
solver_ref m_solver;
ast_manager& m_manager;
params_ref m_params;
sref_vector<model> m_models;
@ -355,7 +342,8 @@ private:
std::string m_exn_msg;
void init() {
m_num_threads = omp_get_num_procs(); // TBD adjust by possible threads used inside each solver.
parallel_params pp(m_params);
m_num_threads = std::min((unsigned)omp_get_num_procs(), pp.threads_max());
m_progress = 0;
m_has_undef = false;
m_allsat = false;
@ -375,6 +363,7 @@ private:
}
void add_branches(unsigned b) {
if (b == 0) return;
{
std::lock_guard<std::mutex> lock(m_mutex);
m_branches += b;
@ -617,7 +606,6 @@ private:
}
else if (cubes.empty()) {
dec_branch();
return;
}
else {
s.inc_width(width);
@ -746,15 +734,16 @@ private:
public:
parallel_tactic(ast_manager& m, params_ref const& p) :
m_manager(m),
parallel_tactic(solver* s, params_ref const& p) :
m_solver(s),
m_manager(s->get_manager()),
m_params(p) {
init();
}
void operator ()(const goal_ref & g,goal_ref_buffer & result) {
ast_manager& m = g->m();
solver* s = mk_fd_solver(m, m_params);
solver* s = m_solver->translate(m, m_params);
solver_state* st = alloc(solver_state, 0, s, m_params, cube_task);
m_queue.add_task(st);
expr_ref_vector clauses(m);
@ -799,7 +788,8 @@ public:
}
tactic* translate(ast_manager& m) {
return alloc(parallel_tactic, m, m_params);
solver* s = m_solver->translate(m, m_params);
return alloc(parallel_tactic, s, m_params);
}
virtual void updt_params(params_ref const & p) {
@ -817,12 +807,40 @@ public:
virtual void reset_statistics() {
m_stats.reset();
}
};
tactic * mk_parallel_tactic(ast_manager& m, params_ref const& p) {
return alloc(parallel_tactic, m, p);
tactic * mk_parallel_qffd_tactic(ast_manager& m, params_ref const& p) {
solver* s = mk_fd_solver(m, p);
return alloc(parallel_tactic, s, p);
}
tactic * mk_parallel_tactic(solver* s, params_ref const& p) {
return alloc(parallel_tactic, s, p);
}
tactic * mk_psat_tactic(ast_manager& m, params_ref const& p) {
parallel_params pp(p);
bool use_parallel = pp.enable();
return pp.enable() ? mk_parallel_tactic(mk_inc_sat_solver(m, p), p) : mk_sat_tactic(m);
}
tactic * mk_psmt_tactic(ast_manager& m, params_ref const& p, symbol const& logic) {
parallel_params pp(p);
bool use_parallel = pp.enable();
return pp.enable() ? mk_parallel_tactic(mk_smt_solver(m, p, logic), p) : mk_smt_tactic(p);
}
tactic * mk_psmt_tactic_using(ast_manager& m, bool auto_config, params_ref const& _p, symbol const& logic) {
parallel_params pp(_p);
bool use_parallel = pp.enable();
params_ref p = _p;
p.set_bool("auto_config", auto_config);
return using_params(pp.enable() ? mk_parallel_tactic(mk_smt_solver(m, p, logic), p) : mk_smt_tactic(p), p);
}
tactic * mk_parallel_smt_tactic(ast_manager& m, params_ref const& p) {
return mk_parallel_tactic(mk_smt_solver(m, p, symbol::null), p);
}

View file

@ -21,11 +21,20 @@ Notes:
class solver;
class tactic;
class solver;
tactic * mk_parallel_tactic(ast_manager& m, params_ref const& p);
tactic * mk_parallel_tactic(solver* s, params_ref const& p);
tactic * mk_parallel_qffd_tactic(ast_manager& m, params_ref const& p);
tactic * mk_parallel_smt_tactic(ast_manager& m, params_ref const& p);
// create parallel sat/smt tactics if parallel.enable=true, otherwise return sequential versions.
tactic * mk_psat_tactic(ast_manager& m, params_ref const& p);
tactic * mk_psmt_tactic(ast_manager& m, params_ref const& p, symbol const& logic = symbol::null);
tactic * mk_psmt_tactic_using(ast_manager& m, bool auto_config, params_ref const& p, symbol const& logic = symbol::null);
/*
ADD_TACTIC("qffdp", "builtin strategy for solving QF_FD problems in parallel.", "mk_parallel_tactic(m, p)")
ADD_TACTIC("pqffd", "builtin strategy for solving QF_FD problems in parallel.", "mk_parallel_qffd_tactic(m, p)")
ADD_TACTIC("psmt", "builtin strategy for SMT tactic in parallel.", "mk_parallel_smt_tactic(m, p)")
*/
#endif

View file

@ -19,13 +19,13 @@ Notes:
#include "tactic/tactical.h"
#include "tactic/core/simplify_tactic.h"
#include "tactic/core/propagate_values_tactic.h"
#include "smt/tactic/smt_tactic.h"
#include "tactic/core/nnf_tactic.h"
#include "tactic/arith/probe_arith.h"
#include "smt/tactic/smt_tactic.h"
#include "qe/qe_tactic.h"
#include "qe/nlqsat.h"
#include "nlsat/tactic/qfnra_nlsat_tactic.h"
#include "qe/qe_lite.h"
#include "tactic/arith/probe_arith.h"
#include "nlsat/tactic/qfnra_nlsat_tactic.h"
tactic * mk_nra_tactic(ast_manager & m, params_ref const& p) {
params_ref p1 = p;

View file

@ -4,8 +4,11 @@ def_module_params('parallel',
export=True,
params=(
('enable', BOOL, False, 'enable parallel solver by default on selected tactics (for QF_BV)'),
('conquer_batch_size', UINT, 1000, 'number of cubes to batch together for fast conquer'),
('inprocess.max', UINT, 2, 'maximal number of inprocessing steps during simplification'),
('restart.max', UINT, 5, 'maximal number of restarts during conquer phase'),
('conquer_threshold', UINT, 10, 'number of cubes generated before simple conquer solver is created'),
('threads.max', UINT, 10000, 'caps maximal number of threads below the number of processors'),
('simplify.multiplier', DOUBLE, 0, 'restart and inprocess max is increased by depth * simplify.multipler, unless the multiplier is 0'),
('conquer.batch_size', UINT, 1000, 'number of cubes to batch together for fast conquer'),
('conquer.threshold', UINT, 10, 'number of cubes generated before simple conquer solver is created'),
('conquer.restart.max', UINT, 5, 'maximal number of restarts during conquer phase'),
('simplify.restart.max', UINT, 5000, 'maximal number of restarts during simplification phase'),
('simplify.inprocess.max', UINT, 2, 'maximal number of inprocessing steps during simplification'),
))

View file

@ -28,6 +28,7 @@ Notes:
#include "tactic/bv/bv_size_reduction_tactic.h"
#include "tactic/aig/aig_tactic.h"
#include "sat/tactic/sat_tactic.h"
#include "sat/sat_solver/inc_sat_solver.h"
#include "tactic/portfolio/parallel_tactic.h"
#include "tactic/smtlogics/parallel_params.hpp"
#include "ackermannization/ackermannize_bv_tactic.h"
@ -129,12 +130,10 @@ static tactic * mk_qfbv_tactic(ast_manager& m, params_ref const & p, tactic* sat
tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) {
parallel_params pp(p);
bool use_parallel = pp.enable();
tactic * new_sat = cond(mk_produce_proofs_probe(),
and_then(mk_simplify_tactic(m), mk_smt_tactic()),
use_parallel ? mk_parallel_tactic(m, p): mk_sat_tactic(m));
mk_psat_tactic(m, p));
return mk_qfbv_tactic(m, p, new_sat, mk_smt_tactic());
return mk_qfbv_tactic(m, p, new_sat, mk_psmt_tactic(m, p));
}

View file

@ -24,7 +24,6 @@ Notes:
#include "tactic/core/solve_eqs_tactic.h"
#include "tactic/core/elim_uncnstr_tactic.h"
#include "smt/tactic/smt_tactic.h"
// include"mip_tactic.h"
#include "tactic/arith/add_bounds_tactic.h"
#include "tactic/arith/pb2bv_tactic.h"
#include "tactic/arith/lia2pb_tactic.h"
@ -35,6 +34,7 @@ Notes:
#include "sat/tactic/sat_tactic.h"
#include "tactic/arith/bound_manager.h"
#include "tactic/arith/probe_arith.h"
#include "tactic/portfolio/parallel_tactic.h"
struct quasi_pb_probe : public probe {
virtual result operator()(goal const & g) {
@ -42,10 +42,7 @@ struct quasi_pb_probe : public probe {
bound_manager bm(g.m());
bm(g);
rational l, u; bool st;
bound_manager::iterator it = bm.begin();
bound_manager::iterator end = bm.end();
for (; it != end; ++it) {
expr * t = *it;
for (expr * t : bm) {
if (bm.has_lower(t, l, st) && bm.has_upper(t, u, st) && (l.is_zero() || l.is_one()) && (u.is_zero() || u.is_one()))
continue;
if (found_non_01)
@ -93,7 +90,7 @@ static tactic * mk_bv2sat_tactic(ast_manager & m) {
mk_max_bv_sharing_tactic(m),
mk_bit_blaster_tactic(m),
mk_aig_tactic(),
mk_sat_tactic(m)),
mk_sat_tactic(m, solver_p)),
solver_p);
}
@ -224,7 +221,7 @@ tactic * mk_qflia_tactic(ast_manager & m, params_ref const & p) {
using_params(mk_lia2sat_tactic(m), quasi_pb_p),
mk_fail_if_undecided_tactic()),
mk_bounded_tactic(m),
mk_smt_tactic())),
mk_psmt_tactic(m, p))),
main_p);
st->updt_params(p);