mirror of
https://github.com/Z3Prover/z3
synced 2025-06-28 17:08:45 +00:00
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
8357ac1cfc
commit
586343ce64
24 changed files with 708 additions and 513 deletions
|
@ -932,13 +932,13 @@ unsigned bv_util::get_int2bv_size(parameter const& p) {
|
||||||
return static_cast<unsigned>(sz);
|
return static_cast<unsigned>(sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
app * bv_util::mk_bv2int(expr* e) {
|
app * bv_util::mk_bv2int(expr* e) const {
|
||||||
sort* s = m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT);
|
sort* s = m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT);
|
||||||
parameter p(s);
|
parameter p(s);
|
||||||
return m_manager.mk_app(get_fid(), OP_BV2INT, 1, &p, 1, &e);
|
return m_manager.mk_app(get_fid(), OP_BV2INT, 1, &p, 1, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
app* bv_util::mk_int2bv(unsigned sz, expr* e) {
|
app* bv_util::mk_int2bv(unsigned sz, expr* e) const {
|
||||||
parameter p(sz);
|
parameter p(sz);
|
||||||
return m_manager.mk_app(get_fid(), OP_INT2BV, 1, &p, 1, &e);
|
return m_manager.mk_app(get_fid(), OP_INT2BV, 1, &p, 1, &e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,8 +549,8 @@ public:
|
||||||
app * mk_bv_ashr(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_BASHR, arg1, arg2); }
|
app * mk_bv_ashr(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_BASHR, arg1, arg2); }
|
||||||
app * mk_bv_lshr(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_BLSHR, arg1, arg2); }
|
app * mk_bv_lshr(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_BLSHR, arg1, arg2); }
|
||||||
|
|
||||||
app * mk_bv2int(expr* e);
|
app * mk_bv2int(expr* e) const;
|
||||||
app * mk_int2bv(unsigned sz, expr* e);
|
app * mk_int2bv(unsigned sz, expr* e) const;
|
||||||
|
|
||||||
app* mk_bv_rotate_left(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_LEFT, arg1, arg2); }
|
app* mk_bv_rotate_left(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_LEFT, arg1, arg2); }
|
||||||
app* mk_bv_rotate_right(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_RIGHT, arg1, arg2); }
|
app* mk_bv_rotate_right(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_RIGHT, arg1, arg2); }
|
||||||
|
|
|
@ -10,8 +10,9 @@ z3_add_component(ast_sls
|
||||||
sls_basic_plugin.cpp
|
sls_basic_plugin.cpp
|
||||||
sls_bv_plugin.cpp
|
sls_bv_plugin.cpp
|
||||||
sls_cc.cpp
|
sls_cc.cpp
|
||||||
|
sls_context.cpp
|
||||||
sls_engine.cpp
|
sls_engine.cpp
|
||||||
sls_smt.cpp
|
sls_smt_solver.cpp
|
||||||
sls_valuation.cpp
|
sls_valuation.cpp
|
||||||
COMPONENT_DEPENDENCIES
|
COMPONENT_DEPENDENCIES
|
||||||
ast
|
ast
|
||||||
|
|
|
@ -14,6 +14,7 @@ Author:
|
||||||
#include "ast/ast_pp.h"
|
#include "ast/ast_pp.h"
|
||||||
#include "ast/ast_ll_pp.h"
|
#include "ast/ast_ll_pp.h"
|
||||||
#include "ast/sls/bv_sls.h"
|
#include "ast/sls/bv_sls.h"
|
||||||
|
#include "ast/rewriter/th_rewriter.h"
|
||||||
|
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
|
||||||
|
@ -25,29 +26,28 @@ namespace bv {
|
||||||
m_fix(*this, terms, ctx)
|
m_fix(*this, terms, ctx)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void sls_eval::init_eval(std::function<bool(expr*, unsigned)> const& eval) {
|
|
||||||
for (expr* e : ctx.subterms()) {
|
void sls_eval::register_term(expr* e) {
|
||||||
if (!is_app(e))
|
if (!is_app(e))
|
||||||
continue;
|
return;
|
||||||
app* a = to_app(e);
|
app* a = to_app(e);
|
||||||
if (!bv.is_bv(e))
|
add_bit_vector(a);
|
||||||
continue;
|
if (a->get_family_id() == bv.get_family_id())
|
||||||
add_bit_vector(a);
|
init_eval_bv(a);
|
||||||
if (a->get_family_id() == bv.get_family_id())
|
else if (bv.is_bv(e)) {
|
||||||
init_eval_bv(a);
|
auto& v = wval(e);
|
||||||
else if (is_uninterp(e)) {
|
for (unsigned i = 0; i < v.bw; ++i)
|
||||||
auto& v = wval(e);
|
m_tmp.set(i, false);
|
||||||
for (unsigned i = 0; i < v.bw; ++i)
|
v.set_repair(random_bool(), m_tmp);
|
||||||
m_tmp.set(i, eval(e, i));
|
|
||||||
v.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_eval::add_bit_vector(app* e) {
|
void sls_eval::add_bit_vector(app* e) {
|
||||||
|
if (!bv.is_bv(e))
|
||||||
|
return;
|
||||||
m_values.reserve(e->get_id() + 1);
|
m_values.reserve(e->get_id() + 1);
|
||||||
if (m_values.get(e->get_id()))
|
if (m_values.get(e->get_id()))
|
||||||
return false;
|
return;
|
||||||
auto v = alloc_valuation(e);
|
auto v = alloc_valuation(e);
|
||||||
m_values.set(e->get_id(), v);
|
m_values.set(e->get_id(), v);
|
||||||
expr* x, * y;
|
expr* x, * y;
|
||||||
|
@ -57,7 +57,7 @@ namespace bv {
|
||||||
else if (bv.is_bv_ashr(e, x, y) && bv.is_numeral(y, val) &&
|
else if (bv.is_bv_ashr(e, x, y) && bv.is_numeral(y, val) &&
|
||||||
val.is_unsigned() && val.get_unsigned() <= bv.get_bv_size(e))
|
val.is_unsigned() && val.get_unsigned() <= bv.get_bv_size(e))
|
||||||
v->set_signed(val.get_unsigned());
|
v->set_signed(val.get_unsigned());
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sls_valuation* sls_eval::alloc_valuation(app* e) {
|
sls_valuation* sls_eval::alloc_valuation(app* e) {
|
||||||
|
@ -575,11 +575,19 @@ namespace bv {
|
||||||
val.set(val.eval, 0);
|
val.set(val.eval, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_INT2BV: {
|
||||||
|
expr_ref v = ctx.get_value(e->get_arg(0));
|
||||||
|
th_rewriter rw(m);
|
||||||
|
v = bv.mk_int2bv(bv.get_bv_size(e), v);
|
||||||
|
rw(v);
|
||||||
|
rational r;
|
||||||
|
VERIFY(bv.is_numeral(v, r));
|
||||||
|
val.set_value(m_tmp, r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OP_BREDAND:
|
case OP_BREDAND:
|
||||||
case OP_BREDOR:
|
case OP_BREDOR:
|
||||||
case OP_BXNOR:
|
case OP_BXNOR:
|
||||||
case OP_INT2BV:
|
|
||||||
|
|
||||||
verbose_stream() << mk_bounded_pp(e, m) << "\n";
|
verbose_stream() << mk_bounded_pp(e, m) << "\n";
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
break;
|
break;
|
||||||
|
@ -672,7 +680,7 @@ namespace bv {
|
||||||
case OP_BV2INT:
|
case OP_BV2INT:
|
||||||
return false;
|
return false;
|
||||||
case OP_INT2BV:
|
case OP_INT2BV:
|
||||||
return false;
|
return try_repair_int2bv(eval_value(e), e->get_arg(0));
|
||||||
case OP_ULEQ:
|
case OP_ULEQ:
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return try_repair_ule(bval0(e), wval(e, i), wval(e, 1 - i));
|
return try_repair_ule(bval0(e), wval(e, i), wval(e, 1 - i));
|
||||||
|
@ -1804,6 +1812,16 @@ namespace bv {
|
||||||
return a.set_random(m_rand);
|
return a.set_random(m_rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sls_eval::try_repair_int2bv(bvect const& e, expr* arg) {
|
||||||
|
expr_ref intval(m);
|
||||||
|
intval = bv.mk_bv2int(bv.mk_numeral(e.get_value(e.nw), e.bw));
|
||||||
|
th_rewriter rw(m);
|
||||||
|
rw(intval);
|
||||||
|
verbose_stream() << "repair " << mk_pp(arg, m) << " " << intval << "\n";
|
||||||
|
ctx.set_value(arg, intval);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void sls_eval::set_div(bvect const& a, bvect const& b, unsigned bw,
|
void sls_eval::set_div(bvect const& a, bvect const& b, unsigned bw,
|
||||||
bvect& quot, bvect& rem) const {
|
bvect& quot, bvect& rem) const {
|
||||||
unsigned nw = (bw + 8 * sizeof(digit_t) - 1) / (8 * sizeof(digit_t));
|
unsigned nw = (bw + 8 * sizeof(digit_t) - 1) / (8 * sizeof(digit_t));
|
||||||
|
@ -1853,8 +1871,10 @@ namespace bv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls_eval::commit_eval(app* e) {
|
void sls_eval::commit_eval(app* e) {
|
||||||
if (bv.is_bv(e))
|
if (!bv.is_bv(e))
|
||||||
VERIFY(wval(e).commit_eval());
|
return;
|
||||||
|
VERIFY(wval(e).commit_eval());
|
||||||
|
// todo: if e is shared, then ctx.set_value().
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls_eval::set_random(app* e) {
|
void sls_eval::set_random(app* e) {
|
||||||
|
@ -1899,7 +1919,7 @@ namespace bv {
|
||||||
return expr_ref(m);
|
return expr_ref(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& sls_eval::display(std::ostream& out) {
|
std::ostream& sls_eval::display(std::ostream& out) const {
|
||||||
auto& terms = ctx.subterms();
|
auto& terms = ctx.subterms();
|
||||||
for (expr* e : terms) {
|
for (expr* e : terms) {
|
||||||
if (!bv.is_bv(e))
|
if (!bv.is_bv(e))
|
||||||
|
@ -1912,7 +1932,7 @@ namespace bv {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& sls_eval::display_value(std::ostream& out, expr* e) {
|
std::ostream& sls_eval::display_value(std::ostream& out, expr* e) const {
|
||||||
if (bv.is_bv(e))
|
if (bv.is_bv(e))
|
||||||
return out << wval(e);
|
return out << wval(e);
|
||||||
return out << "?";
|
return out << "?";
|
||||||
|
|
|
@ -19,7 +19,7 @@ Author:
|
||||||
#include "ast/ast.h"
|
#include "ast/ast.h"
|
||||||
#include "ast/sls/sls_valuation.h"
|
#include "ast/sls/sls_valuation.h"
|
||||||
#include "ast/sls/bv_sls_fixed.h"
|
#include "ast/sls/bv_sls_fixed.h"
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
#include "ast/bv_decl_plugin.h"
|
#include "ast/bv_decl_plugin.h"
|
||||||
|
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
@ -58,7 +58,7 @@ namespace bv {
|
||||||
* Register e as a bit-vector.
|
* Register e as a bit-vector.
|
||||||
* Return true if not already registered, false if already registered.
|
* Return true if not already registered, false if already registered.
|
||||||
*/
|
*/
|
||||||
bool add_bit_vector(app* e);
|
void add_bit_vector(app* e);
|
||||||
sls_valuation* alloc_valuation(app* e);
|
sls_valuation* alloc_valuation(app* e);
|
||||||
|
|
||||||
//bool bval1_basic(app* e) const;
|
//bool bval1_basic(app* e) const;
|
||||||
|
@ -109,6 +109,7 @@ namespace bv {
|
||||||
bool try_repair_extract(bvect const& e, bvval& a, unsigned lo);
|
bool try_repair_extract(bvect const& e, bvval& a, unsigned lo);
|
||||||
bool try_repair_comp(bvect const& e, bvval& a, bvval& b, unsigned i);
|
bool try_repair_comp(bvect const& e, bvval& a, bvval& b, unsigned i);
|
||||||
bool try_repair_eq(bool is_true, bvval& a, bvval const& b);
|
bool try_repair_eq(bool is_true, bvval& a, bvval const& b);
|
||||||
|
bool try_repair_int2bv(bvect const& e, expr* arg);
|
||||||
void add_p2_1(bvval const& a, bvect& t) const;
|
void add_p2_1(bvval const& a, bvect& t) const;
|
||||||
|
|
||||||
bool add_overflow_on_fixed(bvval const& a, bvect const& t);
|
bool add_overflow_on_fixed(bvval const& a, bvect const& t);
|
||||||
|
@ -136,10 +137,12 @@ namespace bv {
|
||||||
public:
|
public:
|
||||||
sls_eval(sls_terms& terms, sls::context& ctx);
|
sls_eval(sls_terms& terms, sls::context& ctx);
|
||||||
|
|
||||||
void init_eval(std::function<bool(expr*, unsigned)> const& eval);
|
// void init_eval(std::function<bool(expr*, unsigned)> const& eval);
|
||||||
|
|
||||||
void tighten_range() { m_fix.init(); }
|
void tighten_range() { m_fix.init(); }
|
||||||
|
|
||||||
|
void register_term(expr* e);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve evaluation based on cache.
|
* Retrieve evaluation based on cache.
|
||||||
* bval - Boolean values
|
* bval - Boolean values
|
||||||
|
@ -178,8 +181,8 @@ namespace bv {
|
||||||
bool repair_up(expr* e);
|
bool repair_up(expr* e);
|
||||||
|
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out);
|
std::ostream& display(std::ostream& out) const;
|
||||||
|
|
||||||
std::ostream& display_value(std::ostream& out, expr* e);
|
std::ostream& display_value(std::ostream& out, expr* e) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ Author:
|
||||||
|
|
||||||
#include "ast/ast.h"
|
#include "ast/ast.h"
|
||||||
#include "ast/sls/sls_valuation.h"
|
#include "ast/sls/sls_valuation.h"
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
#include "ast/bv_decl_plugin.h"
|
#include "ast/bv_decl_plugin.h"
|
||||||
|
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace bv {
|
||||||
ctx(ctx),
|
ctx(ctx),
|
||||||
m(ctx.get_manager()),
|
m(ctx.get_manager()),
|
||||||
bv(m),
|
bv(m),
|
||||||
m_axioms(m) {}
|
m_axioms(m) {}
|
||||||
|
|
||||||
void sls_terms::register_term(expr* e) {
|
void sls_terms::register_term(expr* e) {
|
||||||
auto r = ensure_binary(e);
|
auto r = ensure_binary(e);
|
||||||
|
|
|
@ -24,7 +24,7 @@ Author:
|
||||||
#include "ast/sls/sls_stats.h"
|
#include "ast/sls/sls_stats.h"
|
||||||
#include "ast/sls/sls_powers.h"
|
#include "ast/sls/sls_powers.h"
|
||||||
#include "ast/sls/sls_valuation.h"
|
#include "ast/sls/sls_valuation.h"
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
|
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
|
||||||
|
|
|
@ -243,10 +243,14 @@ namespace sat {
|
||||||
// access clause information and state of Boolean search
|
// access clause information and state of Boolean search
|
||||||
indexed_uint_set& unsat_set() { return m_unsat; }
|
indexed_uint_set& unsat_set() { return m_unsat; }
|
||||||
|
|
||||||
|
indexed_uint_set const& unsat_set() const { return m_unsat; }
|
||||||
|
|
||||||
vector<clause_info> const& clauses() const { return m_clauses; }
|
vector<clause_info> const& clauses() const { return m_clauses; }
|
||||||
|
|
||||||
clause_info& get_clause_info(unsigned idx) { return m_clauses[idx]; }
|
clause_info& get_clause_info(unsigned idx) { return m_clauses[idx]; }
|
||||||
|
|
||||||
|
clause_info const& get_clause_info(unsigned idx) const { return m_clauses[idx]; }
|
||||||
|
|
||||||
void remove_assumptions();
|
void remove_assumptions();
|
||||||
|
|
||||||
void flip(bool_var v);
|
void flip(bool_var v);
|
||||||
|
|
|
@ -317,32 +317,16 @@ namespace sls {
|
||||||
SASSERT(dtt(sign(bv), ineq) == 0);
|
SASSERT(dtt(sign(bv), ineq) == 0);
|
||||||
}
|
}
|
||||||
vi.m_value = new_value;
|
vi.m_value = new_value;
|
||||||
if (vi.m_shared) {
|
|
||||||
sort* s = vi.m_sort == var_sort::INT ? a.mk_int() : a.mk_real();
|
|
||||||
expr_ref num = from_num(s, new_value);
|
|
||||||
ctx.set_value(vi.m_expr, num);
|
|
||||||
}
|
|
||||||
for (auto idx : vi.m_muls) {
|
for (auto idx : vi.m_muls) {
|
||||||
auto const& [v, monomial] = m_muls[idx];
|
auto const& [w, coeff, monomial] = m_muls[idx];
|
||||||
num_t prod(1);
|
ctx.new_value_eh(m_vars[w].m_expr);
|
||||||
for (auto w : monomial)
|
|
||||||
prod *= value(w);
|
|
||||||
if (value(v) != prod)
|
|
||||||
m_vars_to_update.push_back({ v, prod });
|
|
||||||
}
|
}
|
||||||
for (auto const& idx : vi.m_adds) {
|
for (auto idx : vi.m_adds) {
|
||||||
auto const& ad = m_adds[idx];
|
auto const& ad = m_adds[idx];
|
||||||
auto const& args = ad.m_args;
|
ctx.new_value_eh(m_vars[ad.m_var].m_expr);
|
||||||
auto v = ad.m_var;
|
|
||||||
num_t sum(ad.m_coeff);
|
|
||||||
for (auto [c, w] : args)
|
|
||||||
sum += c * value(w);
|
|
||||||
if (value(v) != sum)
|
|
||||||
m_vars_to_update.push_back({ v, sum });
|
|
||||||
}
|
}
|
||||||
if (vi.m_def_idx != UINT_MAX)
|
expr* e = vi.m_expr;
|
||||||
// add repair actions for additions and multiplications
|
ctx.new_value_eh(e);
|
||||||
m_defs_to_update.push_back(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
|
@ -375,10 +359,10 @@ namespace sls {
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
bool arith_base<num_t>::is_num(expr* e, num_t& i) {
|
bool arith_base<num_t>::is_num(expr* e, num_t& i) {
|
||||||
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
expr_ref arith_base<rational>::from_num(sort* s, rational const& n) {
|
expr_ref arith_base<rational>::from_num(sort* s, rational const& n) {
|
||||||
return expr_ref(a.mk_numeral(n, s), m);
|
return expr_ref(a.mk_numeral(n, s), m);
|
||||||
}
|
}
|
||||||
|
@ -389,6 +373,7 @@ namespace sls {
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
expr_ref arith_base<num_t>::from_num(sort* s, num_t const& n) {
|
expr_ref arith_base<num_t>::from_num(sort* s, num_t const& n) {
|
||||||
|
UNREACHABLE();
|
||||||
return expr_ref(m);
|
return expr_ref(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,14 +412,14 @@ namespace sls {
|
||||||
default: {
|
default: {
|
||||||
v = mk_var(e);
|
v = mk_var(e);
|
||||||
unsigned idx = m_muls.size();
|
unsigned idx = m_muls.size();
|
||||||
m_muls.push_back({ v, m });
|
m_muls.push_back({ v, c, m });
|
||||||
num_t prod(1);
|
num_t prod(c);
|
||||||
for (auto w : m)
|
for (auto w : m)
|
||||||
m_vars[w].m_muls.push_back(idx), prod *= value(w);
|
m_vars[w].m_muls.push_back(idx), prod *= value(w);
|
||||||
m_vars[v].m_def_idx = idx;
|
m_vars[v].m_def_idx = idx;
|
||||||
m_vars[v].m_op = arith_op_kind::OP_MUL;
|
m_vars[v].m_op = arith_op_kind::OP_MUL;
|
||||||
m_vars[v].m_value = prod;
|
m_vars[v].m_value = prod;
|
||||||
add_arg(term, c, v);
|
add_arg(term, num_t(1), v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,22 +458,21 @@ namespace sls {
|
||||||
num_t val;
|
num_t val;
|
||||||
switch (k) {
|
switch (k) {
|
||||||
case arith_op_kind::OP_MOD:
|
case arith_op_kind::OP_MOD:
|
||||||
if (value(v) != 0)
|
val = value(v) == 0 ? num_t(0) : mod(value(w), value(v));
|
||||||
val = mod(value(w), value(v));
|
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_REM:
|
case arith_op_kind::OP_REM:
|
||||||
if (value(v) != 0) {
|
if (value(v) == 0)
|
||||||
|
val = 0;
|
||||||
|
else {
|
||||||
val = value(w);
|
val = value(w);
|
||||||
val %= value(v);
|
val %= value(v);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_IDIV:
|
case arith_op_kind::OP_IDIV:
|
||||||
if (value(v) != 0)
|
val = value(v) == 0 ? num_t(0): div(value(w), value(v));
|
||||||
val = div(value(w), value(v));
|
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_DIV:
|
case arith_op_kind::OP_DIV:
|
||||||
if (value(v) != 0)
|
val = value(v) == 0? num_t(0) : value(w) / value(v);
|
||||||
val = value(w) / value(v);
|
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_ABS:
|
case arith_op_kind::OP_ABS:
|
||||||
val = abs(value(w));
|
val = abs(value(w));
|
||||||
|
@ -511,7 +495,7 @@ namespace sls {
|
||||||
return v;
|
return v;
|
||||||
linear_term t;
|
linear_term t;
|
||||||
add_args(t, e, num_t(1));
|
add_args(t, e, num_t(1));
|
||||||
if (t.m_coeff == 1 && t.m_args.size() == 1 && t.m_args[0].first == 1)
|
if (t.m_coeff == 0 && t.m_args.size() == 1 && t.m_args[0].first == 1)
|
||||||
return t.m_args[0].second;
|
return t.m_args[0].second;
|
||||||
v = mk_var(e);
|
v = mk_var(e);
|
||||||
auto idx = m_adds.size();
|
auto idx = m_adds.size();
|
||||||
|
@ -531,7 +515,7 @@ namespace sls {
|
||||||
if (v == UINT_MAX) {
|
if (v == UINT_MAX) {
|
||||||
v = m_vars.size();
|
v = m_vars.size();
|
||||||
m_expr2var.setx(e->get_id(), v, UINT_MAX);
|
m_expr2var.setx(e->get_id(), v, UINT_MAX);
|
||||||
m_vars.push_back(var_info(e, a.is_int(e) ? var_sort::INT : var_sort::REAL));
|
m_vars.push_back(var_info(e, a.is_int(e) ? var_sort::INT : var_sort::REAL));
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -541,7 +525,7 @@ namespace sls {
|
||||||
if (m_bool_vars.get(bv, nullptr))
|
if (m_bool_vars.get(bv, nullptr))
|
||||||
return;
|
return;
|
||||||
expr* e = ctx.atom(bv);
|
expr* e = ctx.atom(bv);
|
||||||
// verbose_stream() << "bool var " << bv << " " << mk_bounded_pp(e, m) << "\n";
|
verbose_stream() << "bool var " << bv << " " << mk_bounded_pp(e, m) << "\n";
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
expr* x, * y;
|
expr* x, * y;
|
||||||
|
@ -570,6 +554,9 @@ namespace sls {
|
||||||
add_args(ineq, y, num_t(-1));
|
add_args(ineq, y, num_t(-1));
|
||||||
init_ineq(bv, ineq);
|
init_ineq(bv, ineq);
|
||||||
}
|
}
|
||||||
|
else if (m.is_distinct(e) && a.is_int_real(e->get_arg(0))) {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
}
|
||||||
else if (a.is_is_int(e, x))
|
else if (a.is_is_int(e, x))
|
||||||
{
|
{
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
|
@ -601,77 +588,127 @@ namespace sls {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::repair(sat::literal lit) {
|
void arith_base<num_t>::propagate_literal(sat::literal lit) {
|
||||||
|
TRACE("sls", tout << "repair is-true: " << ctx.is_true(lit) << " lit: " << lit << "\n");
|
||||||
if (!ctx.is_true(lit))
|
if (!ctx.is_true(lit))
|
||||||
return;
|
return;
|
||||||
auto const* ineq = atom(lit.var());
|
auto const* ineq = atom(lit.var());
|
||||||
if (!ineq)
|
if (!ineq)
|
||||||
return;
|
return;
|
||||||
|
TRACE("sls", tout << "repair lit: " << lit << " ineq-is-true: " << ineq->is_true() << "\n");
|
||||||
if (ineq->is_true() != lit.sign())
|
if (ineq->is_true() != lit.sign())
|
||||||
return;
|
return;
|
||||||
TRACE("sls", tout << "repair " << lit << "\n");
|
|
||||||
repair(lit, *ineq);
|
repair(lit, *ineq);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::repair_defs_and_updates() {
|
bool arith_base<num_t>::propagate() {
|
||||||
while (!m_defs_to_update.empty() || !m_vars_to_update.empty()) {
|
return false;
|
||||||
repair_updates();
|
}
|
||||||
repair_defs();
|
|
||||||
|
template<typename num_t>
|
||||||
|
void arith_base<num_t>::repair_up(app* e) {
|
||||||
|
auto v = m_expr2var.get(e->get_id(), UINT_MAX);
|
||||||
|
if (v == UINT_MAX)
|
||||||
|
return;
|
||||||
|
auto const& vi = m_vars[v];
|
||||||
|
if (vi.m_def_idx == UINT_MAX)
|
||||||
|
return;
|
||||||
|
m_ops.reserve(vi.m_def_idx + 1);
|
||||||
|
auto const& od = m_ops[vi.m_def_idx];
|
||||||
|
num_t v1, v2;
|
||||||
|
switch (vi.m_op) {
|
||||||
|
case LAST_ARITH_OP:
|
||||||
|
break;
|
||||||
|
case OP_ADD: {
|
||||||
|
auto const& ad = m_adds[vi.m_def_idx];
|
||||||
|
auto const& args = ad.m_args;
|
||||||
|
num_t sum(ad.m_coeff);
|
||||||
|
for (auto [c, w] : args)
|
||||||
|
sum += c * value(w);
|
||||||
|
update(v, sum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP_MUL: {
|
||||||
|
auto const& [w, coeff, monomial] = m_muls[vi.m_def_idx];
|
||||||
|
num_t prod(coeff);
|
||||||
|
for (auto w : monomial)
|
||||||
|
prod *= value(w);
|
||||||
|
update(v, prod);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP_MOD:
|
||||||
|
v1 = value(od.m_arg1);
|
||||||
|
v2 = value(od.m_arg2);
|
||||||
|
update(v, v2 == 0 ? num_t(0) : mod(v1, v2));
|
||||||
|
break;
|
||||||
|
case OP_DIV:
|
||||||
|
v1 = value(od.m_arg1);
|
||||||
|
v2 = value(od.m_arg2);
|
||||||
|
update(v, v2 == 0 ? num_t(0) : v1 / v2);
|
||||||
|
break;
|
||||||
|
case OP_IDIV:
|
||||||
|
v1 = value(od.m_arg1);
|
||||||
|
v2 = value(od.m_arg2);
|
||||||
|
update(v, v2 == 0 ? num_t(0) : div(v1, v2));
|
||||||
|
break;
|
||||||
|
case OP_REM:
|
||||||
|
v1 = value(od.m_arg1);
|
||||||
|
v2 = value(od.m_arg2);
|
||||||
|
update(v, v2 == 0 ? num_t(0) : v1 %= v2);
|
||||||
|
break;
|
||||||
|
case OP_ABS:
|
||||||
|
update(v, abs(value(od.m_arg1)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::repair_updates() {
|
void arith_base<num_t>::repair_down(app* e) {
|
||||||
while (!m_vars_to_update.empty()) {
|
auto v = m_expr2var.get(e->get_id(), UINT_MAX);
|
||||||
auto [w, new_value1] = m_vars_to_update.back();
|
if (v == UINT_MAX)
|
||||||
m_vars_to_update.pop_back();
|
return;
|
||||||
update(w, new_value1);
|
auto const& vi = m_vars[v];
|
||||||
}
|
if (vi.m_def_idx == UINT_MAX)
|
||||||
}
|
return;
|
||||||
|
TRACE("sls", tout << "repair def " << mk_bounded_pp(vi.m_expr, m) << "\n");
|
||||||
template<typename num_t>
|
switch (vi.m_op) {
|
||||||
void arith_base<num_t>::repair_defs() {
|
case arith_op_kind::LAST_ARITH_OP:
|
||||||
while (!m_defs_to_update.empty()) {
|
break;
|
||||||
auto v = m_defs_to_update.back();
|
case arith_op_kind::OP_ADD:
|
||||||
m_defs_to_update.pop_back();
|
repair_add(m_adds[vi.m_def_idx]);
|
||||||
auto const& vi = m_vars[v];
|
break;
|
||||||
switch (vi.m_op) {
|
case arith_op_kind::OP_MUL:
|
||||||
case arith_op_kind::LAST_ARITH_OP:
|
repair_mul(m_muls[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_ADD:
|
case arith_op_kind::OP_MOD:
|
||||||
repair_add(m_adds[vi.m_def_idx]);
|
repair_mod(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_MUL:
|
case arith_op_kind::OP_REM:
|
||||||
repair_mul(m_muls[vi.m_def_idx]);
|
repair_rem(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_MOD:
|
case arith_op_kind::OP_POWER:
|
||||||
repair_mod(m_ops[vi.m_def_idx]);
|
repair_power(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_REM:
|
case arith_op_kind::OP_IDIV:
|
||||||
repair_rem(m_ops[vi.m_def_idx]);
|
repair_idiv(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_POWER:
|
case arith_op_kind::OP_DIV:
|
||||||
repair_power(m_ops[vi.m_def_idx]);
|
repair_div(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_IDIV:
|
case arith_op_kind::OP_ABS:
|
||||||
repair_idiv(m_ops[vi.m_def_idx]);
|
repair_abs(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_DIV:
|
case arith_op_kind::OP_TO_INT:
|
||||||
repair_div(m_ops[vi.m_def_idx]);
|
repair_to_int(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_ABS:
|
case arith_op_kind::OP_TO_REAL:
|
||||||
repair_abs(m_ops[vi.m_def_idx]);
|
repair_to_real(m_ops[vi.m_def_idx]);
|
||||||
break;
|
break;
|
||||||
case arith_op_kind::OP_TO_INT:
|
default:
|
||||||
repair_to_int(m_ops[vi.m_def_idx]);
|
NOT_IMPLEMENTED_YET();
|
||||||
break;
|
|
||||||
case arith_op_kind::OP_TO_REAL:
|
|
||||||
repair_to_real(m_ops[vi.m_def_idx]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOT_IMPLEMENTED_YET();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,23 +736,24 @@ namespace sls {
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::repair_mul(mul_def const& md) {
|
void arith_base<num_t>::repair_mul(mul_def const& md) {
|
||||||
num_t product(1);
|
auto const& [v, coeff, monomial] = md;
|
||||||
num_t val = value(md.m_var);
|
num_t product(coeff);
|
||||||
for (auto v : md.m_monomial)
|
num_t val = value(v);
|
||||||
|
for (auto v : monomial)
|
||||||
product *= value(v);
|
product *= value(v);
|
||||||
if (product == val)
|
if (product == val)
|
||||||
return;
|
return;
|
||||||
if (rand() % 20 == 0) {
|
if (rand() % 20 == 0) {
|
||||||
update(md.m_var, product);
|
update(v, product);
|
||||||
}
|
}
|
||||||
else if (val == 0) {
|
else if (val == 0) {
|
||||||
auto v = md.m_monomial[rand() % md.m_monomial.size()];
|
auto v = monomial[ctx.rand(monomial.size())];
|
||||||
num_t zero(0);
|
num_t zero(0);
|
||||||
update(v, zero);
|
update(v, zero);
|
||||||
}
|
}
|
||||||
else if (val == 1 || val == -1) {
|
else if (val == 1 || val == -1) {
|
||||||
product = 1;
|
product = coeff;
|
||||||
for (auto v : md.m_monomial) {
|
for (auto v : monomial) {
|
||||||
num_t new_value(1);
|
num_t new_value(1);
|
||||||
if (rand() % 2 == 0)
|
if (rand() % 2 == 0)
|
||||||
new_value = -1;
|
new_value = -1;
|
||||||
|
@ -723,14 +761,14 @@ namespace sls {
|
||||||
update(v, new_value);
|
update(v, new_value);
|
||||||
}
|
}
|
||||||
if (product != val) {
|
if (product != val) {
|
||||||
auto last = md.m_monomial.back();
|
auto last = monomial.back();
|
||||||
update(last, -value(last));
|
update(last, -value(last));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rand() % 2 == 0 && product != 0) {
|
else if (rand() % 2 == 0 && product != 0) {
|
||||||
// value1(v) * product / value(v) = val
|
// value1(v) * product / value(v) = val
|
||||||
// value1(v) = value(v) * val / product
|
// value1(v) = value(v) * val / product
|
||||||
auto w = md.m_monomial[rand() % md.m_monomial.size()];
|
auto w = monomial[ctx.rand(monomial.size())];
|
||||||
auto old_value = value(w);
|
auto old_value = value(w);
|
||||||
num_t new_value;
|
num_t new_value;
|
||||||
if (m_vars[w].m_sort == var_sort::REAL)
|
if (m_vars[w].m_sort == var_sort::REAL)
|
||||||
|
@ -740,15 +778,15 @@ namespace sls {
|
||||||
update(w, new_value);
|
update(w, new_value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
product = 1;
|
product = coeff;
|
||||||
for (auto v : md.m_monomial) {
|
for (auto v : monomial) {
|
||||||
num_t new_value{ 1 };
|
num_t new_value{ 1 };
|
||||||
if (rand() % 2 == 0)
|
if (rand() % 2 == 0)
|
||||||
new_value = -1;
|
new_value = -1;
|
||||||
product *= new_value;
|
product *= new_value;
|
||||||
update(v, new_value);
|
update(v, new_value);
|
||||||
}
|
}
|
||||||
auto v = md.m_monomial[rand() % md.m_monomial.size()];
|
auto v = monomial[ctx.rand(monomial.size())];
|
||||||
if ((product < 0 && 0 < val) || (val < 0 && 0 < product))
|
if ((product < 0 && 0 < val) || (val < 0 && 0 < product))
|
||||||
update(v, -val * value(v));
|
update(v, -val * value(v));
|
||||||
else
|
else
|
||||||
|
@ -761,8 +799,10 @@ namespace sls {
|
||||||
auto val = value(od.m_var);
|
auto val = value(od.m_var);
|
||||||
auto v1 = value(od.m_arg1);
|
auto v1 = value(od.m_arg1);
|
||||||
auto v2 = value(od.m_arg2);
|
auto v2 = value(od.m_arg2);
|
||||||
if (v2 == 0)
|
if (v2 == 0) {
|
||||||
|
update(od.m_var, num_t(0));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IF_VERBOSE(0, verbose_stream() << "todo repair rem");
|
IF_VERBOSE(0, verbose_stream() << "todo repair rem");
|
||||||
// bail
|
// bail
|
||||||
|
@ -784,7 +824,11 @@ namespace sls {
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::repair_to_int(op_def const& od) {
|
void arith_base<num_t>::repair_to_int(op_def const& od) {
|
||||||
NOT_IMPLEMENTED_YET();
|
auto val = value(od.m_var);
|
||||||
|
auto v1 = value(od.m_arg1);
|
||||||
|
if (val - 1 < v1 && v1 <= val)
|
||||||
|
return;
|
||||||
|
update(od.m_arg1, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
|
@ -800,8 +844,10 @@ namespace sls {
|
||||||
auto val = value(od.m_var);
|
auto val = value(od.m_var);
|
||||||
auto v1 = value(od.m_arg1);
|
auto v1 = value(od.m_arg1);
|
||||||
auto v2 = value(od.m_arg2);
|
auto v2 = value(od.m_arg2);
|
||||||
if (v1 == 0 && v2 == 0)
|
if (v1 == 0 && v2 == 0) {
|
||||||
|
update(od.m_var, num_t(0));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IF_VERBOSE(0, verbose_stream() << "todo repair ^");
|
IF_VERBOSE(0, verbose_stream() << "todo repair ^");
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
}
|
}
|
||||||
|
@ -832,10 +878,7 @@ namespace sls {
|
||||||
update(od.m_arg1, v1);
|
update(od.m_arg1, v1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (v2 == 0)
|
update(od.m_var, v2 == 0 ? num_t(0) : mod(v1, v2));
|
||||||
return;
|
|
||||||
// bail
|
|
||||||
update(od.m_var, mod(v1, v2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
|
@ -843,11 +886,9 @@ namespace sls {
|
||||||
auto val = value(od.m_var);
|
auto val = value(od.m_var);
|
||||||
auto v1 = value(od.m_arg1);
|
auto v1 = value(od.m_arg1);
|
||||||
auto v2 = value(od.m_arg2);
|
auto v2 = value(od.m_arg2);
|
||||||
if (v2 == 0)
|
|
||||||
return;
|
|
||||||
IF_VERBOSE(0, verbose_stream() << "todo repair div");
|
IF_VERBOSE(0, verbose_stream() << "todo repair div");
|
||||||
// bail
|
// bail
|
||||||
update(od.m_var, div(v1, v2));
|
update(od.m_var, v2 == 0 ? num_t(0) : div(v1, v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
|
@ -855,11 +896,9 @@ namespace sls {
|
||||||
auto val = value(od.m_var);
|
auto val = value(od.m_var);
|
||||||
auto v1 = value(od.m_arg1);
|
auto v1 = value(od.m_arg1);
|
||||||
auto v2 = value(od.m_arg2);
|
auto v2 = value(od.m_arg2);
|
||||||
if (v2 == 0)
|
|
||||||
return;
|
|
||||||
IF_VERBOSE(0, verbose_stream() << "todo repair /");
|
IF_VERBOSE(0, verbose_stream() << "todo repair /");
|
||||||
// bail
|
// bail
|
||||||
update(od.m_var, v1 / v2);
|
update(od.m_var, v2 == 0 ? num_t(0) : v1 / v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
|
@ -956,27 +995,31 @@ namespace sls {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::register_term(expr* e) {
|
void arith_base<num_t>::register_term(expr* _e) {
|
||||||
}
|
if (!is_app(_e))
|
||||||
|
|
||||||
template<typename num_t>
|
|
||||||
void arith_base<num_t>::set_shared(expr* e) {
|
|
||||||
if (!a.is_int_real(e))
|
|
||||||
return;
|
return;
|
||||||
var_t v = m_expr2var.get(e->get_id(), UINT_MAX);
|
app* e = to_app(_e);
|
||||||
if (v == UINT_MAX)
|
auto v = ctx.atom2bool_var(e);
|
||||||
v = mk_term(e);
|
if (v != sat::null_bool_var)
|
||||||
m_vars[v].m_shared = true;
|
init_bool_var(v);
|
||||||
|
if (!a.is_arith_expr(e) && !m.is_eq(e) && !m.is_distinct(e))
|
||||||
|
for (auto arg : *e)
|
||||||
|
if (a.is_int_real(arg))
|
||||||
|
mk_term(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
void arith_base<num_t>::set_value(expr* e, expr* v) {
|
void arith_base<num_t>::set_value(expr* e, expr* v) {
|
||||||
auto w = m_expr2var.get(e->get_id(), UINT_MAX);
|
if (!a.is_int_real(e))
|
||||||
if (w == UINT_MAX)
|
|
||||||
return;
|
return;
|
||||||
|
var_t w = m_expr2var.get(e->get_id(), UINT_MAX);
|
||||||
|
if (w == UINT_MAX)
|
||||||
|
w = mk_term(e);
|
||||||
|
|
||||||
num_t n;
|
num_t n;
|
||||||
if (!is_num(v, n))
|
if (!is_num(v, n))
|
||||||
return;
|
return;
|
||||||
|
verbose_stream() << "set value " << w << " " << mk_bounded_pp(e, m) << " " << n << " " << value(w) << "\n";
|
||||||
if (n == value(w))
|
if (n == value(w))
|
||||||
return;
|
return;
|
||||||
update(w, n);
|
update(w, n);
|
||||||
|
@ -988,21 +1031,6 @@ namespace sls {
|
||||||
return expr_ref(a.mk_numeral(rational(m_vars[v].m_value.get_int64(), rational::i64()), a.is_int(e)), m);
|
return expr_ref(a.mk_numeral(rational(m_vars[v].m_value.get_int64(), rational::i64()), a.is_int(e)), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename num_t>
|
|
||||||
lbool arith_base<num_t>::check() {
|
|
||||||
// repair each root literal
|
|
||||||
for (sat::literal lit : ctx.root_literals())
|
|
||||||
repair(lit);
|
|
||||||
|
|
||||||
repair_defs_and_updates();
|
|
||||||
|
|
||||||
// update literal assignment based on current model
|
|
||||||
for (unsigned v = 0; v < ctx.num_bool_vars(); ++v)
|
|
||||||
init_bool_var_assignment(v);
|
|
||||||
|
|
||||||
return ctx.unsat().empty() ? l_true : l_undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename num_t>
|
template<typename num_t>
|
||||||
bool arith_base<num_t>::is_sat() {
|
bool arith_base<num_t>::is_sat() {
|
||||||
for (auto const& clause : ctx.clauses()) {
|
for (auto const& clause : ctx.clauses()) {
|
||||||
|
@ -1035,8 +1063,8 @@ namespace sls {
|
||||||
}
|
}
|
||||||
for (unsigned v = 0; v < m_vars.size(); ++v) {
|
for (unsigned v = 0; v < m_vars.size(); ++v) {
|
||||||
auto const& vi = m_vars[v];
|
auto const& vi = m_vars[v];
|
||||||
out << "v" << v << " := " << vi.m_value << " " << vi.m_best_value << " ";
|
out << "v" << v << " := " << vi.m_value << " (best " << vi.m_best_value << ") ";
|
||||||
out << mk_bounded_pp(vi.m_expr, m) << " - ";
|
out << mk_bounded_pp(vi.m_expr, m) << " : ";
|
||||||
for (auto [c, bv] : vi.m_bool_vars)
|
for (auto [c, bv] : vi.m_bool_vars)
|
||||||
out << c << "@" << bv << " ";
|
out << c << "@" << bv << " ";
|
||||||
out << "\n";
|
out << "\n";
|
||||||
|
@ -1049,9 +1077,11 @@ namespace sls {
|
||||||
}
|
}
|
||||||
for (auto ad : m_adds) {
|
for (auto ad : m_adds) {
|
||||||
out << "v" << ad.m_var << " := ";
|
out << "v" << ad.m_var << " := ";
|
||||||
|
bool first = true;
|
||||||
for (auto [c, w] : ad.m_args)
|
for (auto [c, w] : ad.m_args)
|
||||||
out << c << "* v" << w << " + ";
|
out << (first?"":" + ") << c << "* v" << w;
|
||||||
out << ad.m_coeff;
|
if (ad.m_coeff != 0)
|
||||||
|
out << " + " << ad.m_coeff;
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
for (auto od : m_ops) {
|
for (auto od : m_ops) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ Author:
|
||||||
#include "util/checked_int64.h"
|
#include "util/checked_int64.h"
|
||||||
#include "ast/ast_trail.h"
|
#include "ast/ast_trail.h"
|
||||||
#include "ast/arith_decl_plugin.h"
|
#include "ast/arith_decl_plugin.h"
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
@ -75,11 +75,11 @@ namespace sls {
|
||||||
out << " + " << m_coeff;
|
out << " + " << m_coeff;
|
||||||
switch (m_op) {
|
switch (m_op) {
|
||||||
case ineq_kind::LE:
|
case ineq_kind::LE:
|
||||||
return out << " <= " << 0 << "(" << m_args_value << ")";
|
return out << " <= " << 0 << "(" << m_args_value + m_coeff << ")";
|
||||||
case ineq_kind::EQ:
|
case ineq_kind::EQ:
|
||||||
return out << " == " << 0 << "(" << m_args_value << ")";
|
return out << " == " << 0 << "(" << m_args_value + m_coeff << ")";
|
||||||
default:
|
default:
|
||||||
return out << " < " << 0 << "(" << m_args_value << ")";
|
return out << " < " << 0 << "(" << m_args_value + m_coeff << ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -101,6 +101,7 @@ namespace sls {
|
||||||
|
|
||||||
struct mul_def {
|
struct mul_def {
|
||||||
unsigned m_var;
|
unsigned m_var;
|
||||||
|
num_t m_coeff;
|
||||||
unsigned_vector m_monomial;
|
unsigned_vector m_monomial;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,8 +110,8 @@ namespace sls {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct op_def {
|
struct op_def {
|
||||||
unsigned m_var;
|
unsigned m_var = UINT_MAX;
|
||||||
arith_op_kind m_op;
|
arith_op_kind m_op = LAST_ARITH_OP;
|
||||||
unsigned m_arg1, m_arg2;
|
unsigned m_arg1, m_arg2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,8 +125,6 @@ namespace sls {
|
||||||
unsigned_vector m_expr2var;
|
unsigned_vector m_expr2var;
|
||||||
bool m_dscore_mode = false;
|
bool m_dscore_mode = false;
|
||||||
arith_util a;
|
arith_util a;
|
||||||
unsigned_vector m_defs_to_update;
|
|
||||||
vector<std::pair<var_t, num_t>> m_vars_to_update;
|
|
||||||
|
|
||||||
unsigned get_num_vars() const { return m_vars.size(); }
|
unsigned get_num_vars() const { return m_vars.size(); }
|
||||||
|
|
||||||
|
@ -139,10 +138,6 @@ namespace sls {
|
||||||
void repair_abs(op_def const& od);
|
void repair_abs(op_def const& od);
|
||||||
void repair_to_int(op_def const& od);
|
void repair_to_int(op_def const& od);
|
||||||
void repair_to_real(op_def const& od);
|
void repair_to_real(op_def const& od);
|
||||||
void repair_defs_and_updates();
|
|
||||||
void repair_defs();
|
|
||||||
void repair_updates();
|
|
||||||
void repair(sat::literal lit);
|
|
||||||
void repair(sat::literal lit, ineq const& ineq);
|
void repair(sat::literal lit, ineq const& ineq);
|
||||||
|
|
||||||
double reward(sat::literal lit);
|
double reward(sat::literal lit);
|
||||||
|
@ -179,15 +174,18 @@ namespace sls {
|
||||||
bool is_num(expr* e, num_t& i);
|
bool is_num(expr* e, num_t& i);
|
||||||
expr_ref from_num(sort* s, num_t const& n);
|
expr_ref from_num(sort* s, num_t const& n);
|
||||||
void check_ineqs();
|
void check_ineqs();
|
||||||
|
void init_bool_var(sat::bool_var v);
|
||||||
public:
|
public:
|
||||||
arith_base(context& ctx);
|
arith_base(context& ctx);
|
||||||
~arith_base() override {}
|
~arith_base() override {}
|
||||||
void init_bool_var(sat::bool_var v) override;
|
|
||||||
void register_term(expr* e) override;
|
void register_term(expr* e) override;
|
||||||
void set_shared(expr* e) override;
|
|
||||||
void set_value(expr* e, expr* v) override;
|
void set_value(expr* e, expr* v) override;
|
||||||
expr_ref get_value(expr* e) override;
|
expr_ref get_value(expr* e) override;
|
||||||
lbool check() override;
|
void initialize() override {}
|
||||||
|
void propagate_literal(sat::literal lit) override;
|
||||||
|
bool propagate() override;
|
||||||
|
void repair_up(app* e) override;
|
||||||
|
void repair_down(app* e) override;
|
||||||
bool is_sat() override;
|
bool is_sat() override;
|
||||||
void on_rescale() override;
|
void on_rescale() override;
|
||||||
void on_restart() override;
|
void on_restart() override;
|
||||||
|
|
|
@ -21,21 +21,9 @@ Author:
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
void arith_plugin::init_bool_var(sat::bool_var v) {
|
void arith_plugin::init_backup() {
|
||||||
if (!m_arith) {
|
m_arith = alloc(arith_base<rational>, ctx);
|
||||||
try {
|
m_arith->initialize();
|
||||||
m_arith64->init_bool_var(v);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (overflow_exception&) {
|
|
||||||
m_arith = alloc(arith_base<rational>, ctx);
|
|
||||||
for (auto e : m_shared)
|
|
||||||
m_arith->set_shared(e);
|
|
||||||
return; // initialization happens on check-sat calls
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_arith->init_bool_var(v);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_plugin::register_term(expr* e) {
|
void arith_plugin::register_term(expr* e) {
|
||||||
|
@ -45,9 +33,7 @@ namespace sls {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (overflow_exception&) {
|
catch (overflow_exception&) {
|
||||||
m_arith = alloc(arith_base<rational>, ctx);
|
init_backup();
|
||||||
for (auto e : m_shared)
|
|
||||||
m_arith->set_shared(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_arith->register_term(e);
|
m_arith->register_term(e);
|
||||||
|
@ -59,32 +45,49 @@ namespace sls {
|
||||||
return m_arith64->get_value(e);
|
return m_arith64->get_value(e);
|
||||||
}
|
}
|
||||||
catch (overflow_exception&) {
|
catch (overflow_exception&) {
|
||||||
m_arith = alloc(arith_base<rational>, ctx);
|
init_backup();
|
||||||
for (auto e : m_shared)
|
|
||||||
m_arith->set_shared(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_arith->get_value(e);
|
return m_arith->get_value(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool arith_plugin::check() {
|
void arith_plugin::initialize() {
|
||||||
|
if (m_arith)
|
||||||
|
m_arith->initialize();
|
||||||
|
else
|
||||||
|
m_arith64->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arith_plugin::propagate_literal(sat::literal lit) {
|
||||||
if (!m_arith) {
|
if (!m_arith) {
|
||||||
try {
|
try {
|
||||||
return m_arith64->check();
|
m_arith64->propagate_literal(lit);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
catch (overflow_exception&) {
|
catch (overflow_exception&) {
|
||||||
m_arith = alloc(arith_base<rational>, ctx);
|
init_backup();
|
||||||
for (auto e : m_shared)
|
|
||||||
m_arith->set_shared(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_arith->check();
|
m_arith->propagate_literal(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool arith_plugin::propagate() {
|
||||||
|
if (!m_arith) {
|
||||||
|
try {
|
||||||
|
return m_arith64->propagate();
|
||||||
|
}
|
||||||
|
catch (overflow_exception&) {
|
||||||
|
init_backup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_arith->propagate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arith_plugin::is_sat() {
|
bool arith_plugin::is_sat() {
|
||||||
if (!m_arith)
|
if (m_arith)
|
||||||
|
return m_arith->is_sat();
|
||||||
|
else
|
||||||
return m_arith64->is_sat();
|
return m_arith64->is_sat();
|
||||||
return m_arith->is_sat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_plugin::on_rescale() {
|
void arith_plugin::on_rescale() {
|
||||||
|
@ -115,19 +118,30 @@ namespace sls {
|
||||||
m_arith64->mk_model(mdl);
|
m_arith64->mk_model(mdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_plugin::set_shared(expr* e) {
|
void arith_plugin::repair_down(app* e) {
|
||||||
|
if (m_arith)
|
||||||
|
m_arith->repair_down(e);
|
||||||
|
else
|
||||||
|
m_arith64->repair_down(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arith_plugin::repair_up(app* e) {
|
||||||
if (m_arith)
|
if (m_arith)
|
||||||
m_arith->set_shared(e);
|
m_arith->repair_up(e);
|
||||||
else {
|
else
|
||||||
m_arith64->set_shared(e);
|
m_arith64->repair_up(e);
|
||||||
m_shared.push_back(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_plugin::set_value(expr* e, expr* v) {
|
void arith_plugin::set_value(expr* e, expr* v) {
|
||||||
if (m_arith)
|
if (!m_arith) {
|
||||||
m_arith->set_value(e, v);
|
try {
|
||||||
else
|
m_arith64->set_value(e, v);
|
||||||
m_arith->set_value(e, v);
|
return;
|
||||||
|
}
|
||||||
|
catch (overflow_exception&) {
|
||||||
|
init_backup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_arith->set_value(e, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ Author:
|
||||||
--*/
|
--*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
#include "ast/sls/sls_arith_base.h"
|
#include "ast/sls/sls_arith_base.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
@ -25,23 +25,28 @@ namespace sls {
|
||||||
scoped_ptr<arith_base<checked_int64<true>>> m_arith64;
|
scoped_ptr<arith_base<checked_int64<true>>> m_arith64;
|
||||||
scoped_ptr<arith_base<rational>> m_arith;
|
scoped_ptr<arith_base<rational>> m_arith;
|
||||||
expr_ref_vector m_shared;
|
expr_ref_vector m_shared;
|
||||||
|
|
||||||
|
void init_backup();
|
||||||
public:
|
public:
|
||||||
arith_plugin(context& ctx) :
|
arith_plugin(context& ctx) :
|
||||||
plugin(ctx), m_shared(ctx.get_manager()) {
|
plugin(ctx), m_shared(ctx.get_manager()) {
|
||||||
m_arith64 = alloc(arith_base<checked_int64<true>>,ctx);
|
m_arith64 = alloc(arith_base<checked_int64<true>>,ctx);
|
||||||
|
m_fid = m_arith64->fid();
|
||||||
}
|
}
|
||||||
~arith_plugin() override {}
|
~arith_plugin() override {}
|
||||||
void init_bool_var(sat::bool_var v) override;
|
|
||||||
void register_term(expr* e) override;
|
void register_term(expr* e) override;
|
||||||
expr_ref get_value(expr* e) override;
|
expr_ref get_value(expr* e) override;
|
||||||
lbool check() override;
|
void initialize() override;
|
||||||
|
void propagate_literal(sat::literal lit) override;
|
||||||
|
bool propagate() override;
|
||||||
|
void repair_down(app* e) override;
|
||||||
|
void repair_up(app* e) override;
|
||||||
bool is_sat() override;
|
bool is_sat() override;
|
||||||
|
|
||||||
void on_rescale() override;
|
void on_rescale() override;
|
||||||
void on_restart() override;
|
void on_restart() override;
|
||||||
std::ostream& display(std::ostream& out) const override;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
void mk_model(model& mdl) override;
|
void mk_model(model& mdl) override;
|
||||||
void set_shared(expr* e) override;
|
|
||||||
void set_value(expr* e, expr* v) override;
|
void set_value(expr* e, expr* v) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,24 +24,21 @@ namespace sls {
|
||||||
return expr_ref(m.mk_bool_val(bval0(e)), m);
|
return expr_ref(m.mk_bool_val(bval0(e)), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool basic_plugin::check() {
|
void basic_plugin::propagate_literal(sat::literal lit) {
|
||||||
init();
|
auto a = ctx.atom(lit.var());
|
||||||
for (sat::literal lit : ctx.root_literals())
|
if (!a || !is_app(a))
|
||||||
repair_literal(lit);
|
return;
|
||||||
repair_defs_and_updates();
|
SASSERT(to_app(a)->get_family_id() != basic_family_id);
|
||||||
return ctx.unsat().empty() ? l_true : l_undef;
|
if (bval1(to_app(a)) != bval0(to_app(a)))
|
||||||
|
ctx.new_value_eh(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_plugin::init() {
|
void basic_plugin::register_term(expr* e) {
|
||||||
m_repair_down = UINT_MAX;
|
if (is_app(e) && m.is_bool(e) && to_app(e)->get_family_id() == basic_family_id)
|
||||||
m_repair_roots.reset();
|
m_values.setx(e->get_id(), bval1(to_app(e)), false);
|
||||||
m_repair_up.reset();
|
}
|
||||||
if (m_initialized)
|
|
||||||
return;
|
void basic_plugin::initialize() {
|
||||||
m_initialized = true;
|
|
||||||
for (auto t : ctx.subterms())
|
|
||||||
if (is_app(t) && m.is_bool(t) && to_app(t)->get_family_id() == basic_family_id)
|
|
||||||
m_values.setx(t->get_id(), bval1(to_app(t)), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::is_sat() {
|
bool basic_plugin::is_sat() {
|
||||||
|
@ -70,7 +67,6 @@ namespace sls {
|
||||||
if (bval0(e) != m.is_true(v))
|
if (bval0(e) != m.is_true(v))
|
||||||
return;
|
return;
|
||||||
set_value(e, m.is_true(v));
|
set_value(e, m.is_true(v));
|
||||||
m_repair_roots.insert(e->get_id());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::bval1(app* e) const {
|
bool basic_plugin::bval1(app* e) const {
|
||||||
|
@ -133,7 +129,7 @@ namespace sls {
|
||||||
if (v == sat::null_bool_var)
|
if (v == sat::null_bool_var)
|
||||||
return m_values.get(e->get_id(), false);
|
return m_values.get(e->get_id(), false);
|
||||||
else
|
else
|
||||||
return ctx.is_true(sat::literal(v, false));
|
return ctx.is_true(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::try_repair(app* e, unsigned i) {
|
bool basic_plugin::try_repair(app* e, unsigned i) {
|
||||||
|
@ -157,8 +153,7 @@ namespace sls {
|
||||||
case OP_ITE:
|
case OP_ITE:
|
||||||
return try_repair_ite(e, i);
|
return try_repair_ite(e, i);
|
||||||
case OP_DISTINCT:
|
case OP_DISTINCT:
|
||||||
NOT_IMPLEMENTED_YET();
|
return try_repair_distinct(e, i);
|
||||||
return false;
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
|
@ -167,17 +162,21 @@ namespace sls {
|
||||||
|
|
||||||
bool basic_plugin::try_repair_and_or(app* e, unsigned i) {
|
bool basic_plugin::try_repair_and_or(app* e, unsigned i) {
|
||||||
auto b = bval0(e);
|
auto b = bval0(e);
|
||||||
|
if ((b && m.is_and(e)) || (!b && m.is_or(e))) {
|
||||||
|
for (auto arg : *e)
|
||||||
|
if (!set_value(arg, b))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
auto child = e->get_arg(i);
|
auto child = e->get_arg(i);
|
||||||
if (b == bval0(child))
|
if (b == bval0(child))
|
||||||
return false;
|
return false;
|
||||||
set_value(child, b);
|
return set_value(child, b);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::try_repair_not(app* e) {
|
bool basic_plugin::try_repair_not(app* e) {
|
||||||
auto child = e->get_arg(0);
|
auto child = e->get_arg(0);
|
||||||
set_value(child, !bval0(e));
|
return set_value(child, !bval0(e));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::try_repair_eq(app* e, unsigned i) {
|
bool basic_plugin::try_repair_eq(app* e, unsigned i) {
|
||||||
|
@ -185,129 +184,111 @@ namespace sls {
|
||||||
auto sibling = e->get_arg(1 - i);
|
auto sibling = e->get_arg(1 - i);
|
||||||
if (!m.is_bool(child))
|
if (!m.is_bool(child))
|
||||||
return false;
|
return false;
|
||||||
set_value(child, bval0(e) == bval0(sibling));
|
return set_value(child, bval0(e) == bval0(sibling));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::try_repair_xor(app* e, unsigned i) {
|
bool basic_plugin::try_repair_xor(app* e, unsigned i) {
|
||||||
bool ev = bval0(e);
|
|
||||||
bool bv = bval0(e->get_arg(1 - i));
|
|
||||||
auto child = e->get_arg(i);
|
auto child = e->get_arg(i);
|
||||||
set_value(child, ev != bv);
|
bool bv = false;
|
||||||
return true;
|
for (unsigned j = 0; j < e->get_num_args(); ++j)
|
||||||
|
if (j != i)
|
||||||
|
bv ^= bval0(e->get_arg(j));
|
||||||
|
bool ev = bval0(e);
|
||||||
|
return set_value(child, ev != bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::try_repair_ite(app* e, unsigned i) {
|
bool basic_plugin::try_repair_ite(app* e, unsigned i) {
|
||||||
auto child = e->get_arg(i);
|
auto child = e->get_arg(i);
|
||||||
bool c = bval0(e->get_arg(0));
|
bool c = bval0(e->get_arg(0));
|
||||||
if (i == 0) {
|
if (i == 0)
|
||||||
set_value(child, !c);
|
return set_value(child, !c);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c != (i == 1))
|
if (c != (i == 1))
|
||||||
return false;
|
return false;
|
||||||
if (m.is_bool(e)) {
|
if (m.is_bool(e))
|
||||||
set_value(child, bval0(e));
|
return set_value(child, bval0(e));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::try_repair_implies(app* e, unsigned i) {
|
bool basic_plugin::try_repair_implies(app* e, unsigned i) {
|
||||||
auto child = e->get_arg(i);
|
auto child = e->get_arg(i);
|
||||||
|
auto sibling = e->get_arg(1 - i);
|
||||||
bool ev = bval0(e);
|
bool ev = bval0(e);
|
||||||
bool av = bval0(child);
|
bool av = bval0(child);
|
||||||
bool bv = bval0(e->get_arg(1 - i));
|
bool bv = bval0(sibling);
|
||||||
if (i == 0) {
|
if (ev) {
|
||||||
if (ev == (!av || bv))
|
|
||||||
return false;
|
if (i == 0 && (!av || bv))
|
||||||
}
|
return true;
|
||||||
else if (ev != (!bv || av))
|
if (i == 1 && (!bv || av))
|
||||||
|
return true;
|
||||||
|
if (i == 0) {
|
||||||
|
return set_value(child, false);
|
||||||
|
}
|
||||||
|
if (i == 1) {
|
||||||
|
return set_value(child, true);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
set_value(child, ev);
|
}
|
||||||
return true;
|
if (i == 0 && av && !bv)
|
||||||
|
return true;
|
||||||
|
if (i == 1 && bv && !av)
|
||||||
|
return true;
|
||||||
|
if (i == 0) {
|
||||||
|
return set_value(child, true) && set_value(sibling, false);
|
||||||
|
}
|
||||||
|
if (i == 1) {
|
||||||
|
return set_value(child, false) && set_value(sibling, true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_plugin::repair_up(expr* e) {
|
void basic_plugin::repair_up(app* e) {
|
||||||
if (!m.is_bool(e))
|
if (!m.is_bool(e) || e->get_family_id() != basic_family_id)
|
||||||
return false;
|
return;
|
||||||
auto b = bval1(to_app(e));
|
auto b = bval1(e);
|
||||||
|
if (bval0(e) == b)
|
||||||
|
return;
|
||||||
set_value(e, b);
|
set_value(e, b);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_plugin::repair_down(app* e) {
|
void basic_plugin::repair_down(app* e) {
|
||||||
SASSERT(m.is_bool(e));
|
SASSERT(m.is_bool(e));
|
||||||
unsigned n = e->get_num_args();
|
unsigned n = e->get_num_args();
|
||||||
if (n == 0 || e->get_family_id() != m.get_basic_family_id()) {
|
if (n == 0 || e->get_family_id() != m.get_basic_family_id())
|
||||||
for (auto p : ctx.parents(e))
|
|
||||||
m_repair_up.insert(p->get_id());
|
|
||||||
ctx.set_value(e, m.mk_bool_val(bval0(e)));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (bval0(e) == bval1(e))
|
if (bval0(e) == bval1(e))
|
||||||
return;
|
return;
|
||||||
unsigned s = ctx.rand(n);
|
unsigned s = ctx.rand(n);
|
||||||
for (unsigned i = 0; i < n; ++i) {
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
auto j = (i + s) % n;
|
auto j = (i + s) % n;
|
||||||
if (try_repair(e, j)) {
|
if (try_repair(e, j))
|
||||||
m_repair_down = e->get_arg(j)->get_id();
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_repair_up.insert(e->get_id());
|
set_value(e, bval1(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool basic_plugin::try_repair_distinct(app* e, unsigned i) {
|
||||||
void basic_plugin::repair_defs_and_updates() {
|
return false;
|
||||||
if (!m_repair_roots.empty() ||
|
|
||||||
!m_repair_up.empty() ||
|
|
||||||
m_repair_down != UINT_MAX) {
|
|
||||||
|
|
||||||
while (m_repair_down != UINT_MAX) {
|
|
||||||
auto e = ctx.term(m_repair_down);
|
|
||||||
repair_down(to_app(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!m_repair_up.empty()) {
|
|
||||||
auto id = m_repair_up.elem_at(rand() % m_repair_up.size());
|
|
||||||
auto e = ctx.term(id);
|
|
||||||
m_repair_up.remove(id);
|
|
||||||
repair_up(to_app(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_repair_roots.empty()) {
|
|
||||||
auto id = m_repair_roots.elem_at(rand() % m_repair_roots.size());
|
|
||||||
m_repair_roots.remove(id);
|
|
||||||
m_repair_down = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_plugin::set_value(expr* e, bool b) {
|
bool basic_plugin::set_value(expr* e, bool b) {
|
||||||
|
if (m.is_true(e) && !b)
|
||||||
|
return false;
|
||||||
|
if (m.is_false(e) && b)
|
||||||
|
return false;
|
||||||
sat::bool_var v = ctx.atom2bool_var(e);
|
sat::bool_var v = ctx.atom2bool_var(e);
|
||||||
if (v == sat::null_bool_var) {
|
if (v == sat::null_bool_var) {
|
||||||
if (m_values.get(e->get_id(), b) != b) {
|
if (m_values.get(e->get_id(), b) != b) {
|
||||||
m_values.set(e->get_id(), b);
|
m_values.set(e->get_id(), b);
|
||||||
ctx.set_value(e, m.mk_bool_val(b));
|
ctx.new_value_eh(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ctx.is_true(sat::literal(v, false)) != b) {
|
else if (ctx.is_true(v) != b) {
|
||||||
ctx.flip(v);
|
ctx.flip(v);
|
||||||
ctx.set_value(e, m.mk_bool_val(b));
|
ctx.new_value_eh(e);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_plugin::repair_literal(sat::literal lit) {
|
|
||||||
if (!ctx.is_true(lit))
|
|
||||||
return;
|
|
||||||
auto a = ctx.atom(lit.var());
|
|
||||||
if (!a || !is_app(a))
|
|
||||||
return;
|
|
||||||
if (to_app(a)->get_family_id() != basic_family_id)
|
|
||||||
return;
|
|
||||||
if (bval1(to_app(a)) != bval0(to_app(a)))
|
|
||||||
m_repair_roots.insert(a->get_id());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,20 +12,16 @@ Author:
|
||||||
--*/
|
--*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
class basic_plugin : public plugin {
|
class basic_plugin : public plugin {
|
||||||
bool_vector m_values;
|
bool_vector m_values;
|
||||||
indexed_uint_set m_repair_up, m_repair_roots;
|
|
||||||
unsigned m_repair_down = UINT_MAX;
|
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
|
|
||||||
void init();
|
|
||||||
bool bval1(app* e) const;
|
bool bval1(app* e) const;
|
||||||
bool bval0(expr* e) const;
|
bool bval0(expr* e) const;
|
||||||
bool repair_up(expr* e);
|
|
||||||
bool try_repair(app* e, unsigned i);
|
bool try_repair(app* e, unsigned i);
|
||||||
bool try_repair_and_or(app* e, unsigned i);
|
bool try_repair_and_or(app* e, unsigned i);
|
||||||
bool try_repair_not(app* e);
|
bool try_repair_not(app* e);
|
||||||
|
@ -33,28 +29,28 @@ namespace sls {
|
||||||
bool try_repair_xor(app* e, unsigned i);
|
bool try_repair_xor(app* e, unsigned i);
|
||||||
bool try_repair_ite(app* e, unsigned i);
|
bool try_repair_ite(app* e, unsigned i);
|
||||||
bool try_repair_implies(app* e, unsigned i);
|
bool try_repair_implies(app* e, unsigned i);
|
||||||
void set_value(expr* e, bool b);
|
bool try_repair_distinct(app* e, unsigned i);
|
||||||
|
bool set_value(expr* e, bool b);
|
||||||
void repair_down(app* e);
|
|
||||||
void repair_defs_and_updates();
|
|
||||||
void repair_literal(sat::literal lit);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
basic_plugin(context& ctx) :
|
basic_plugin(context& ctx) :
|
||||||
plugin(ctx) {
|
plugin(ctx) {
|
||||||
|
m_fid = basic_family_id;
|
||||||
}
|
}
|
||||||
~basic_plugin() override {}
|
~basic_plugin() override {}
|
||||||
void init_bool_var(sat::bool_var v) override {}
|
void register_term(expr* e) override;
|
||||||
void register_term(expr* e) override {}
|
|
||||||
expr_ref get_value(expr* e) override;
|
expr_ref get_value(expr* e) override;
|
||||||
lbool check() override;
|
void initialize() override;
|
||||||
|
void propagate_literal(sat::literal lit) override;
|
||||||
|
bool propagate() override { return false; }
|
||||||
|
void repair_down(app* e) override;
|
||||||
|
void repair_up(app* e) override;
|
||||||
bool is_sat() override;
|
bool is_sat() override;
|
||||||
|
|
||||||
void on_rescale() override {}
|
void on_rescale() override {}
|
||||||
void on_restart() override {}
|
void on_restart() override {}
|
||||||
std::ostream& display(std::ostream& out) const override;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
void mk_model(model& mdl) override {}
|
void mk_model(model& mdl) override {}
|
||||||
void set_shared(expr* e) override {}
|
|
||||||
void set_value(expr* e, expr* v) override;
|
void set_value(expr* e, expr* v) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,80 +23,44 @@ namespace sls {
|
||||||
plugin(ctx),
|
plugin(ctx),
|
||||||
bv(m),
|
bv(m),
|
||||||
m_terms(ctx),
|
m_terms(ctx),
|
||||||
m_eval(m_terms, ctx)
|
m_eval(m_terms, ctx) {
|
||||||
{}
|
m_fid = bv.get_family_id();
|
||||||
|
}
|
||||||
|
|
||||||
void bv_plugin::register_term(expr* e) {
|
void bv_plugin::register_term(expr* e) {
|
||||||
m_terms.register_term(e);
|
m_terms.register_term(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref bv_plugin::get_value(expr* e) {
|
expr_ref bv_plugin::get_value(expr* e) {
|
||||||
return expr_ref(m);
|
SASSERT(bv.is_bv(e));
|
||||||
|
auto const & val = m_eval.wval(e);
|
||||||
|
return expr_ref(bv.mk_numeral(val.get_value(), e->get_sort()), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool bv_plugin::check() {
|
|
||||||
|
|
||||||
if (!m_initialized) {
|
void bv_plugin::propagate_literal(sat::literal lit) {
|
||||||
auto eval = [&](expr* e, unsigned idx) { return false; };
|
SASSERT(ctx.is_true(lit));
|
||||||
m_eval.init_eval(eval);
|
auto a = ctx.atom(lit.var());
|
||||||
m_initialized = true;
|
if (!a || !is_app(a))
|
||||||
}
|
return;
|
||||||
|
if (!m_eval.eval_is_correct(to_app(a)))
|
||||||
|
ctx.new_value_eh(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bv_plugin::propagate() {
|
||||||
auto& axioms = m_terms.axioms();
|
auto& axioms = m_terms.axioms();
|
||||||
if (!axioms.empty()) {
|
if (!axioms.empty()) {
|
||||||
for (auto* e : axioms)
|
for (auto* e : axioms)
|
||||||
ctx.add_constraint(e);
|
ctx.add_constraint(e);
|
||||||
axioms.reset();
|
axioms.reset();
|
||||||
return l_undef;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
// repair each root literal
|
|
||||||
for (sat::literal lit : ctx.root_literals())
|
|
||||||
repair_literal(lit);
|
|
||||||
|
|
||||||
repair_defs_and_updates();
|
|
||||||
|
|
||||||
// update literal assignment based on current model
|
|
||||||
for (unsigned v = 0; v < ctx.num_bool_vars(); ++v)
|
|
||||||
init_bool_var_assignment(v);
|
|
||||||
|
|
||||||
return ctx.unsat().empty() ? l_true : l_undef;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bv_plugin::repair_literal(sat::literal lit) {
|
void bv_plugin::initialize() {
|
||||||
if (!ctx.is_true(lit))
|
if (!m_initialized) {
|
||||||
return;
|
// compute fixed ranges
|
||||||
auto a = ctx.atom(lit.var());
|
m_initialized = true;
|
||||||
if (!a || !is_app(a))
|
|
||||||
return;
|
|
||||||
if (to_app(a)->get_family_id() != bv.get_family_id())
|
|
||||||
return;
|
|
||||||
if (!m_eval.eval_is_correct(to_app(a)))
|
|
||||||
m_repair_roots.insert(a->get_id());
|
|
||||||
}
|
|
||||||
|
|
||||||
void bv_plugin::repair_defs_and_updates() {
|
|
||||||
if (!m_repair_roots.empty() ||
|
|
||||||
!m_repair_up.empty() ||
|
|
||||||
m_repair_down != UINT_MAX) {
|
|
||||||
|
|
||||||
while (m_repair_down != UINT_MAX) {
|
|
||||||
auto e = ctx.term(m_repair_down);
|
|
||||||
try_repair_down(to_app(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!m_repair_up.empty()) {
|
|
||||||
auto id = m_repair_up.elem_at(rand() % m_repair_up.size());
|
|
||||||
auto e = ctx.term(id);
|
|
||||||
m_repair_up.remove(id);
|
|
||||||
try_repair_up(to_app(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_repair_roots.empty()) {
|
|
||||||
auto id = m_repair_roots.elem_at(rand() % m_repair_roots.size());
|
|
||||||
m_repair_roots.remove(id);
|
|
||||||
m_repair_down = id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,38 +72,35 @@ namespace sls {
|
||||||
return;
|
return;
|
||||||
bool is_true = m_eval.bval1(to_app(a));
|
bool is_true = m_eval.bval1(to_app(a));
|
||||||
|
|
||||||
if (is_true != ctx.is_true(sat::literal(v, false)))
|
if (is_true != ctx.is_true(v))
|
||||||
ctx.flip(v);
|
ctx.flip(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bv_plugin::is_sat() {
|
bool bv_plugin::is_sat() {
|
||||||
return false;
|
for (auto t : ctx.subterms())
|
||||||
|
if (is_app(t) && bv.is_bv(t) && !m_eval.eval_is_correct(to_app(t)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& bv_plugin::display(std::ostream& out) const {
|
std::ostream& bv_plugin::display(std::ostream& out) const {
|
||||||
// m_eval.display(out);
|
return m_eval.display(out);
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bv_plugin::set_shared(expr* e) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bv_plugin::set_value(expr* e, expr* v) {
|
void bv_plugin::set_value(expr* e, expr* v) {
|
||||||
|
if (!bv.is_bv(e))
|
||||||
|
return;
|
||||||
|
rational val;
|
||||||
|
VERIFY(bv.is_numeral(v, val));
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
// set value of e to val,
|
||||||
}
|
}
|
||||||
|
|
||||||
void bv_plugin::try_repair_down(app* e) {
|
void bv_plugin::repair_down(app* e) {
|
||||||
|
|
||||||
unsigned n = e->get_num_args();
|
unsigned n = e->get_num_args();
|
||||||
if (n == 0 || m_eval.eval_is_correct(e)) {
|
if (n == 0 || m_eval.eval_is_correct(e)) {
|
||||||
m_eval.commit_eval(e);
|
m_eval.commit_eval(e);
|
||||||
if (!m.is_bool(e))
|
|
||||||
for (auto p : ctx.parents(e))
|
|
||||||
m_repair_up.insert(p->get_id());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m.is_bool(e)) {
|
|
||||||
NOT_IMPLEMENTED_YET();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,15 +109,15 @@ namespace sls {
|
||||||
auto d2 = get_depth(e->get_arg(1));
|
auto d2 = get_depth(e->get_arg(1));
|
||||||
unsigned s = ctx.rand(d1 + d2 + 2);
|
unsigned s = ctx.rand(d1 + d2 + 2);
|
||||||
if (s <= d1 && m_eval.try_repair(e, 0)) {
|
if (s <= d1 && m_eval.try_repair(e, 0)) {
|
||||||
set_repair_down(e->get_arg(0));
|
ctx.new_value_eh(e->get_arg(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_eval.try_repair(e, 1)) {
|
if (m_eval.try_repair(e, 1)) {
|
||||||
set_repair_down(e->get_arg(1));
|
ctx.new_value_eh(e->get_arg(1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_eval.try_repair(e, 0)) {
|
if (m_eval.try_repair(e, 0)) {
|
||||||
set_repair_down(e->get_arg(0));
|
ctx.new_value_eh(e->get_arg(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,18 +126,16 @@ namespace sls {
|
||||||
for (unsigned i = 0; i < n; ++i) {
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
auto j = (i + s) % n;
|
auto j = (i + s) % n;
|
||||||
if (m_eval.try_repair(e, j)) {
|
if (m_eval.try_repair(e, j)) {
|
||||||
set_repair_down(e->get_arg(j));
|
ctx.new_value_eh(e->get_arg(j));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IF_VERBOSE(3, verbose_stream() << "init-repair " << mk_bounded_pp(e, m) << "\n");
|
IF_VERBOSE(3, verbose_stream() << "init-repair " << mk_bounded_pp(e, m) << "\n");
|
||||||
// repair was not successful, so reset the state to find a different way to repair
|
|
||||||
m_repair_down = UINT_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bv_plugin::try_repair_up(app* e) {
|
void bv_plugin::repair_up(app* e) {
|
||||||
if (m.is_bool(e))
|
if (!bv.is_bv(e))
|
||||||
;
|
;
|
||||||
else if (m_eval.repair_up(e)) {
|
else if (m_eval.repair_up(e)) {
|
||||||
if (!m_eval.eval_is_correct(e)) {
|
if (!m_eval.eval_is_correct(e)) {
|
||||||
|
@ -184,12 +143,12 @@ namespace sls {
|
||||||
}
|
}
|
||||||
SASSERT(m_eval.eval_is_correct(e));
|
SASSERT(m_eval.eval_is_correct(e));
|
||||||
for (auto p : ctx.parents(e))
|
for (auto p : ctx.parents(e))
|
||||||
m_repair_up.insert(p->get_id());
|
ctx.new_value_eh(p);
|
||||||
}
|
}
|
||||||
else if (ctx.rand(10) != 0) {
|
else if (ctx.rand(10) != 0) {
|
||||||
IF_VERBOSE(2, verbose_stream() << "repair-up "; trace_repair(true, e));
|
IF_VERBOSE(2, verbose_stream() << "repair-up "; trace_repair(true, e));
|
||||||
m_eval.set_random(e);
|
m_eval.set_random(e);
|
||||||
m_repair_roots.insert(e->get_id());
|
ctx.new_value_eh(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,9 +161,7 @@ namespace sls {
|
||||||
|
|
||||||
void bv_plugin::trace() {
|
void bv_plugin::trace() {
|
||||||
IF_VERBOSE(2, verbose_stream()
|
IF_VERBOSE(2, verbose_stream()
|
||||||
<< "(bvsls :restarts " << m_stats.m_restarts
|
<< "(bvsls :restarts " << m_stats.m_restarts << ")\n");
|
||||||
<< " :repair-up " << m_repair_up.size()
|
|
||||||
<< " :repair-roots " << m_repair_roots.size() << ")\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ Author:
|
||||||
--*/
|
--*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
#include "ast/bv_decl_plugin.h"
|
#include "ast/bv_decl_plugin.h"
|
||||||
#include "ast/sls/bv_sls_terms.h"
|
#include "ast/sls/bv_sls_terms.h"
|
||||||
#include "ast/sls/bv_sls_eval.h"
|
#include "ast/sls/bv_sls_eval.h"
|
||||||
|
@ -28,38 +28,29 @@ namespace sls {
|
||||||
bv::sls_terms m_terms;
|
bv::sls_terms m_terms;
|
||||||
bv::sls_eval m_eval;
|
bv::sls_eval m_eval;
|
||||||
bv::sls_stats m_stats;
|
bv::sls_stats m_stats;
|
||||||
|
|
||||||
indexed_uint_set m_repair_up, m_repair_roots;
|
|
||||||
unsigned m_repair_down = UINT_MAX;
|
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
|
|
||||||
void repair_literal(sat::literal lit);
|
|
||||||
|
|
||||||
void repair_defs_and_updates();
|
|
||||||
|
|
||||||
void init_bool_var_assignment(sat::bool_var v);
|
void init_bool_var_assignment(sat::bool_var v);
|
||||||
|
std::ostream& trace_repair(bool down, expr* e);
|
||||||
void try_repair_down(app* e);
|
|
||||||
void set_repair_down(expr* e) { m_repair_down = e->get_id(); }
|
|
||||||
void try_repair_up(app* e);
|
|
||||||
|
|
||||||
std::ostream& bv_plugin::trace_repair(bool down, expr* e);
|
|
||||||
void trace();
|
void trace();
|
||||||
|
bool can_propagate();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bv_plugin(context& ctx);
|
bv_plugin(context& ctx);
|
||||||
~bv_plugin() override {}
|
~bv_plugin() override {}
|
||||||
void init_bool_var(sat::bool_var v) override {}
|
|
||||||
void register_term(expr* e) override;
|
void register_term(expr* e) override;
|
||||||
expr_ref get_value(expr* e) override;
|
expr_ref get_value(expr* e) override;
|
||||||
lbool check() override;
|
void initialize() override;
|
||||||
|
void propagate_literal(sat::literal lit) override;
|
||||||
|
bool propagate() override;
|
||||||
|
void repair_down(app* e) override;
|
||||||
|
void repair_up(app* e) override;
|
||||||
bool is_sat() override;
|
bool is_sat() override;
|
||||||
|
|
||||||
void on_rescale() override {}
|
void on_rescale() override {}
|
||||||
void on_restart() override {}
|
void on_restart() override {}
|
||||||
std::ostream& display(std::ostream& out) const override;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
void mk_model(model& mdl) override {}
|
void mk_model(model& mdl) override {}
|
||||||
void set_shared(expr* e) override;
|
|
||||||
void set_value(expr* e, expr* v) override;
|
void set_value(expr* e, expr* v) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace sls {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool cc_plugin::check() {
|
bool cc_plugin::propagate() {
|
||||||
bool new_constraint = false;
|
bool new_constraint = false;
|
||||||
for (auto & [f, ts] : m_app) {
|
for (auto & [f, ts] : m_app) {
|
||||||
if (ts.size() <= 1)
|
if (ts.size() <= 1)
|
||||||
|
@ -108,7 +108,7 @@ namespace sls {
|
||||||
m_values.insert(t);
|
m_values.insert(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new_constraint ? l_undef : l_true;
|
return new_constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& cc_plugin::display(std::ostream& out) const {
|
std::ostream& cc_plugin::display(std::ostream& out) const {
|
||||||
|
|
|
@ -17,7 +17,7 @@ Author:
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/hashtable.h"
|
#include "util/hashtable.h"
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
@ -39,14 +39,16 @@ namespace sls {
|
||||||
~cc_plugin() override;
|
~cc_plugin() override;
|
||||||
family_id fid() { return m_fid; }
|
family_id fid() { return m_fid; }
|
||||||
expr_ref get_value(expr* e) override;
|
expr_ref get_value(expr* e) override;
|
||||||
lbool check() override;
|
void initialize() override {}
|
||||||
|
void propagate_literal(sat::literal lit) override {}
|
||||||
|
bool propagate() override;
|
||||||
bool is_sat() override;
|
bool is_sat() override;
|
||||||
void register_term(expr* e) override;
|
void register_term(expr* e) override;
|
||||||
void init_bool_var(sat::bool_var v) override {}
|
|
||||||
std::ostream& display(std::ostream& out) const override;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
void mk_model(model& mdl) override;
|
void mk_model(model& mdl) override;
|
||||||
void set_value(expr* e, expr* v) override {}
|
void set_value(expr* e, expr* v) override {}
|
||||||
void set_shared(expr* e) override {}
|
void repair_up(app* e) override {}
|
||||||
|
void repair_down(app* e) override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,12 @@ Author:
|
||||||
--*/
|
--*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
#include "ast/sls/sls_cc.h"
|
#include "ast/sls/sls_cc.h"
|
||||||
#include "ast/sls/sls_arith_plugin.h"
|
#include "ast/sls/sls_arith_plugin.h"
|
||||||
#include "ast/sls/sls_bv_plugin.h"
|
#include "ast/sls/sls_bv_plugin.h"
|
||||||
#include "ast/sls/sls_basic_plugin.h"
|
#include "ast/sls/sls_basic_plugin.h"
|
||||||
|
#include "ast/ast_ll_pp.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
@ -30,7 +31,11 @@ namespace sls {
|
||||||
}
|
}
|
||||||
|
|
||||||
context::context(ast_manager& m, sat_solver_context& s) :
|
context::context(ast_manager& m, sat_solver_context& s) :
|
||||||
m(m), s(s), m_atoms(m), m_allterms(m) {
|
m(m), s(s), m_atoms(m), m_allterms(m),
|
||||||
|
m_gd(*this),
|
||||||
|
m_ld(*this),
|
||||||
|
m_repair_down(m.get_num_asts(), m_gd),
|
||||||
|
m_repair_up(m.get_num_asts(), m_ld) {
|
||||||
register_plugin(alloc(cc_plugin, *this));
|
register_plugin(alloc(cc_plugin, *this));
|
||||||
register_plugin(alloc(arith_plugin, *this));
|
register_plugin(alloc(arith_plugin, *this));
|
||||||
register_plugin(alloc(bv_plugin, *this));
|
register_plugin(alloc(bv_plugin, *this));
|
||||||
|
@ -56,14 +61,12 @@ namespace sls {
|
||||||
//
|
//
|
||||||
init();
|
init();
|
||||||
while (unsat().empty()) {
|
while (unsat().empty()) {
|
||||||
reinit_relevant();
|
|
||||||
for (auto p : m_plugins) {
|
propagate_boolean_assignment();
|
||||||
lbool r;
|
|
||||||
if (p && (r = p->check()) != l_true)
|
if (m_new_constraint || !unsat().empty())
|
||||||
return r;
|
|
||||||
}
|
|
||||||
if (m_new_constraint)
|
|
||||||
return l_undef;
|
return l_undef;
|
||||||
|
|
||||||
if (all_of(m_plugins, [&](auto* p) { return !p || p->is_sat(); })) {
|
if (all_of(m_plugins, [&](auto* p) { return !p || p->is_sat(); })) {
|
||||||
model_ref mdl = alloc(model, m);
|
model_ref mdl = alloc(model, m);
|
||||||
for (expr* e : subterms())
|
for (expr* e : subterms())
|
||||||
|
@ -74,17 +77,72 @@ namespace sls {
|
||||||
p->mk_model(*mdl);
|
p->mk_model(*mdl);
|
||||||
s.on_model(mdl);
|
s.on_model(mdl);
|
||||||
verbose_stream() << *mdl << "\n";
|
verbose_stream() << *mdl << "\n";
|
||||||
|
TRACE("sls", display(tout));
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void context::propagate_boolean_assignment() {
|
||||||
|
reinit_relevant();
|
||||||
|
|
||||||
|
for (sat::literal lit : root_literals()) {
|
||||||
|
if (m_new_constraint)
|
||||||
|
break;
|
||||||
|
propagate_literal(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!m_new_constraint && (!m_repair_up.empty() || !m_repair_down.empty())) {
|
||||||
|
while (!m_repair_down.empty() && !m_new_constraint) {
|
||||||
|
auto id = m_repair_down.erase_min();
|
||||||
|
expr* e = term(id);
|
||||||
|
if (is_app(e)) {
|
||||||
|
auto p = m_plugins.get(to_app(e)->get_family_id(), nullptr);
|
||||||
|
if (p)
|
||||||
|
p->repair_down(to_app(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!m_repair_up.empty() && !m_new_constraint) {
|
||||||
|
auto id = m_repair_up.erase_min();
|
||||||
|
expr* e = term(id);
|
||||||
|
if (is_app(e)) {
|
||||||
|
auto p = m_plugins.get(to_app(e)->get_family_id(), nullptr);
|
||||||
|
if (p)
|
||||||
|
p->repair_up(to_app(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// propagate "final checks"
|
||||||
|
bool propagated = true;
|
||||||
|
while (propagated && !m_new_constraint) {
|
||||||
|
propagated = false;
|
||||||
|
for (auto p : m_plugins)
|
||||||
|
propagated |= p && !m_new_constraint && p->propagate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void context::propagate_literal(sat::literal lit) {
|
||||||
|
if (!is_true(lit))
|
||||||
|
return;
|
||||||
|
auto a = atom(lit.var());
|
||||||
|
if (!a || !is_app(a))
|
||||||
|
return;
|
||||||
|
family_id fid = to_app(a)->get_family_id();
|
||||||
|
if (m.is_eq(a) || m.is_distinct(a))
|
||||||
|
fid = to_app(a)->get_arg(0)->get_sort()->get_family_id();
|
||||||
|
auto p = m_plugins.get(fid, nullptr);
|
||||||
|
if (p)
|
||||||
|
p->propagate_literal(lit);
|
||||||
|
}
|
||||||
|
|
||||||
bool context::is_true(expr* e) {
|
bool context::is_true(expr* e) {
|
||||||
SASSERT(m.is_bool(e));
|
SASSERT(m.is_bool(e));
|
||||||
auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var);
|
auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var);
|
||||||
SASSERT(v != sat::null_bool_var);
|
if (v != sat::null_bool_var)
|
||||||
return is_true(sat::literal(v, false));
|
return m.is_true(m_plugins[basic_family_id]->get_value(e));
|
||||||
|
else
|
||||||
|
return is_true(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool context::is_fixed(expr* e) {
|
bool context::is_fixed(expr* e) {
|
||||||
|
@ -101,11 +159,11 @@ namespace sls {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return expr_ref(e, m);
|
return expr_ref(e, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::set_value(expr* e, expr* v) {
|
void context::set_value(expr * e, expr * v) {
|
||||||
for (auto p : m_plugins)
|
for (auto p : m_plugins)
|
||||||
if (p)
|
if (p)
|
||||||
p->set_value(e, v);
|
p->set_value(e, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool context::is_relevant(expr* e) {
|
bool context::is_relevant(expr* e) {
|
||||||
|
@ -148,31 +206,21 @@ namespace sls {
|
||||||
v = s.add_var();
|
v = s.add_var();
|
||||||
register_terms(e);
|
register_terms(e);
|
||||||
register_atom(v, e);
|
register_atom(v, e);
|
||||||
init_bool_var(v);
|
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::init_bool_var(sat::bool_var v) {
|
|
||||||
for (auto p : m_plugins)
|
|
||||||
if (p)
|
|
||||||
p->init_bool_var(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void context::init() {
|
void context::init() {
|
||||||
m_new_constraint = false;
|
m_new_constraint = false;
|
||||||
if (m_initialized)
|
if (m_initialized)
|
||||||
return;
|
return;
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
register_terms();
|
|
||||||
for (sat::bool_var v = 0; v < num_bool_vars(); ++v)
|
|
||||||
init_bool_var(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void context::register_terms() {
|
|
||||||
for (auto a : m_atoms)
|
for (auto a : m_atoms)
|
||||||
if (a)
|
if (a)
|
||||||
register_terms(a);
|
register_terms(a);
|
||||||
|
for (auto p : m_plugins)
|
||||||
|
if (p)
|
||||||
|
p->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::register_terms(expr* e) {
|
void context::register_terms(expr* e) {
|
||||||
|
@ -213,6 +261,23 @@ namespace sls {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void context::new_value_eh(expr* e) {
|
||||||
|
DEBUG_CODE(
|
||||||
|
if (m.is_bool(e)) {
|
||||||
|
auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var);
|
||||||
|
if (v != sat::null_bool_var) {
|
||||||
|
SASSERT(m.is_true(get_value(e)) == is_true(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
m_repair_down.reserve(e->get_id() + 1);
|
||||||
|
m_repair_down.insert(e->get_id());
|
||||||
|
for (auto p : parents(e)) {
|
||||||
|
m_repair_up.reserve(p->get_id() + 1);
|
||||||
|
m_repair_up.insert(p->get_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void context::register_term(expr* e) {
|
void context::register_term(expr* e) {
|
||||||
for (auto p : m_plugins)
|
for (auto p : m_plugins)
|
||||||
if (p)
|
if (p)
|
||||||
|
@ -261,10 +326,14 @@ namespace sls {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& context::display(std::ostream& out) const {
|
std::ostream& context::display(std::ostream& out) const {
|
||||||
for (auto p : m_plugins) {
|
for (auto id : m_repair_down)
|
||||||
|
out << "d " << mk_bounded_pp(term(id), m) << "\n";
|
||||||
|
for (auto id : m_repair_up)
|
||||||
|
out << "u " << mk_bounded_pp(term(id), m) << "\n";
|
||||||
|
for (auto p : m_plugins)
|
||||||
if (p)
|
if (p)
|
||||||
p->display(out);
|
p->display(out);
|
||||||
}
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ Copyright (c) 2024 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
smt_sls.h
|
sls_context.h
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ Author:
|
||||||
#include "model/model.h"
|
#include "model/model.h"
|
||||||
#include "util/scoped_ptr_vector.h"
|
#include "util/scoped_ptr_vector.h"
|
||||||
#include "util/obj_hashtable.h"
|
#include "util/obj_hashtable.h"
|
||||||
|
#include "util/heap.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
@ -38,14 +39,16 @@ namespace sls {
|
||||||
virtual family_id fid() { return m_fid; }
|
virtual family_id fid() { return m_fid; }
|
||||||
virtual void register_term(expr* e) = 0;
|
virtual void register_term(expr* e) = 0;
|
||||||
virtual expr_ref get_value(expr* e) = 0;
|
virtual expr_ref get_value(expr* e) = 0;
|
||||||
virtual void init_bool_var(sat::bool_var v) = 0;
|
virtual void initialize() = 0;
|
||||||
virtual lbool check() = 0;
|
virtual bool propagate() = 0;
|
||||||
|
virtual void propagate_literal(sat::literal lit) = 0;
|
||||||
|
virtual void repair_down(app* e) = 0;
|
||||||
|
virtual void repair_up(app* e) = 0;
|
||||||
virtual bool is_sat() = 0;
|
virtual bool is_sat() = 0;
|
||||||
virtual void on_rescale() {};
|
virtual void on_rescale() {};
|
||||||
virtual void on_restart() {};
|
virtual void on_restart() {};
|
||||||
virtual std::ostream& display(std::ostream& out) const = 0;
|
virtual std::ostream& display(std::ostream& out) const = 0;
|
||||||
virtual void mk_model(model& mdl) = 0;
|
virtual void mk_model(model& mdl) = 0;
|
||||||
virtual void set_shared(expr* e) = 0;
|
|
||||||
virtual void set_value(expr* e, expr* v) = 0;
|
virtual void set_value(expr* e, expr* v) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,6 +71,22 @@ namespace sls {
|
||||||
};
|
};
|
||||||
|
|
||||||
class context {
|
class context {
|
||||||
|
struct greater_depth {
|
||||||
|
context& c;
|
||||||
|
greater_depth(context& c) : c(c) {}
|
||||||
|
bool operator()(unsigned x, unsigned y) const {
|
||||||
|
return get_depth(c.term(x)) > get_depth(c.term(y));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct less_depth {
|
||||||
|
context& c;
|
||||||
|
less_depth(context& c) : c(c) {}
|
||||||
|
bool operator()(unsigned x, unsigned y) const {
|
||||||
|
return get_depth(c.term(x)) < get_depth(c.term(y));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ast_manager& m;
|
ast_manager& m;
|
||||||
sat_solver_context& s;
|
sat_solver_context& s;
|
||||||
scoped_ptr_vector<plugin> m_plugins;
|
scoped_ptr_vector<plugin> m_plugins;
|
||||||
|
@ -81,23 +100,27 @@ namespace sls {
|
||||||
bool m_new_constraint = false;
|
bool m_new_constraint = false;
|
||||||
expr_ref_vector m_allterms;
|
expr_ref_vector m_allterms;
|
||||||
ptr_vector<expr> m_subterms;
|
ptr_vector<expr> m_subterms;
|
||||||
|
greater_depth m_gd;
|
||||||
|
less_depth m_ld;
|
||||||
|
heap<greater_depth> m_repair_down;
|
||||||
|
heap<less_depth> m_repair_up;
|
||||||
|
|
||||||
void register_plugin(plugin* p);
|
void register_plugin(plugin* p);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void init_bool_var(sat::bool_var v);
|
|
||||||
void register_terms();
|
|
||||||
ptr_vector<expr> m_todo;
|
ptr_vector<expr> m_todo;
|
||||||
void register_terms(expr* e);
|
void register_terms(expr* e);
|
||||||
void register_term(expr* e);
|
void register_term(expr* e);
|
||||||
sat::bool_var mk_atom(expr* e);
|
sat::bool_var mk_atom(expr* e);
|
||||||
|
|
||||||
|
void propagate_boolean_assignment();
|
||||||
|
void propagate_literal(sat::literal lit);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
context(ast_manager& m, sat_solver_context& s);
|
context(ast_manager& m, sat_solver_context& s);
|
||||||
|
|
||||||
// Between SAT/SMT solver and context.
|
// Between SAT/SMT solver and context.
|
||||||
void register_atom(sat::bool_var v, expr* e);
|
void register_atom(sat::bool_var v, expr* e);
|
||||||
// void reset();
|
|
||||||
lbool check();
|
lbool check();
|
||||||
|
|
||||||
// expose sat_solver to plugins
|
// expose sat_solver to plugins
|
||||||
|
@ -107,6 +130,7 @@ namespace sls {
|
||||||
double get_weight(unsigned clause_idx) { return s.get_weigth(clause_idx); }
|
double get_weight(unsigned clause_idx) { return s.get_weigth(clause_idx); }
|
||||||
unsigned num_bool_vars() const { return s.num_vars(); }
|
unsigned num_bool_vars() const { return s.num_vars(); }
|
||||||
bool is_true(sat::literal lit) { return s.is_true(lit); }
|
bool is_true(sat::literal lit) { return s.is_true(lit); }
|
||||||
|
bool is_true(sat::bool_var v) { return s.is_true(sat::literal(v, false)); }
|
||||||
expr* atom(sat::bool_var v) { return m_atoms.get(v, nullptr); }
|
expr* atom(sat::bool_var v) { return m_atoms.get(v, nullptr); }
|
||||||
expr* term(unsigned id) const { return m_allterms.get(id); }
|
expr* term(unsigned id) const { return m_allterms.get(id); }
|
||||||
sat::bool_var atom2bool_var(expr* e) const { return m_atom2bool_var.get(e->get_id(), sat::null_bool_var); }
|
sat::bool_var atom2bool_var(expr* e) const { return m_atom2bool_var.get(e->get_id(), sat::null_bool_var); }
|
||||||
|
@ -126,13 +150,15 @@ namespace sls {
|
||||||
|
|
||||||
// Between plugin solvers
|
// Between plugin solvers
|
||||||
expr_ref get_value(expr* e);
|
expr_ref get_value(expr* e);
|
||||||
bool is_true(expr* e);
|
|
||||||
bool is_fixed(expr* e);
|
|
||||||
void set_value(expr* e, expr* v);
|
void set_value(expr* e, expr* v);
|
||||||
|
void new_value_eh(expr* e);
|
||||||
|
bool is_true(expr* e);
|
||||||
|
bool is_fixed(expr* e);
|
||||||
bool is_relevant(expr* e);
|
bool is_relevant(expr* e);
|
||||||
void add_constraint(expr* e);
|
void add_constraint(expr* e);
|
||||||
ptr_vector<expr> const& subterms();
|
ptr_vector<expr> const& subterms();
|
||||||
ast_manager& get_manager() { return m; }
|
ast_manager& get_manager() { return m; }
|
||||||
std::ostream& display(std::ostream& out) const;
|
std::ostream& display(std::ostream& out) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ Author:
|
||||||
|
|
||||||
#include "sat/smt/sls_solver.h"
|
#include "sat/smt/sls_solver.h"
|
||||||
#include "sat/smt/euf_solver.h"
|
#include "sat/smt/euf_solver.h"
|
||||||
#include "ast/sls/sls_smt.h"
|
#include "ast/sls/sls_context.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,103 @@ Notes:
|
||||||
#include "tactic/sls/sls_tactic.h"
|
#include "tactic/sls/sls_tactic.h"
|
||||||
#include "params/sls_params.hpp"
|
#include "params/sls_params.hpp"
|
||||||
#include "ast/sls/sls_engine.h"
|
#include "ast/sls/sls_engine.h"
|
||||||
#include "ast/sls/bv_sls.h"
|
#include "ast/sls/sls_smt_solver.h"
|
||||||
|
|
||||||
|
class sls_smt_tactic : public tactic {
|
||||||
|
ast_manager& m;
|
||||||
|
params_ref m_params;
|
||||||
|
sls::smt_solver* m_sls;
|
||||||
|
statistics m_st;
|
||||||
|
|
||||||
|
public:
|
||||||
|
sls_smt_tactic(ast_manager& _m, params_ref const& p) :
|
||||||
|
m(_m),
|
||||||
|
m_params(p) {
|
||||||
|
m_sls = alloc(sls::smt_solver, m, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
tactic* translate(ast_manager& m) override {
|
||||||
|
return alloc(sls_smt_tactic, m, m_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
~sls_smt_tactic() override {
|
||||||
|
dealloc(m_sls);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* name() const override { return "sls-smt"; }
|
||||||
|
|
||||||
|
void updt_params(params_ref const& p) override {
|
||||||
|
m_params.append(p);
|
||||||
|
m_sls->updt_params(m_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void collect_param_descrs(param_descrs& r) override {
|
||||||
|
sls_params::collect_param_descrs(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(goal_ref const& g, model_converter_ref& mc) {
|
||||||
|
if (g->inconsistent()) {
|
||||||
|
mc = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < g->size(); i++)
|
||||||
|
m_sls->assert_expr(g->form(i));
|
||||||
|
|
||||||
|
|
||||||
|
lbool res = m_sls->check();
|
||||||
|
m_st.reset();
|
||||||
|
m_sls->collect_statistics(m_st);
|
||||||
|
// report_tactic_progress("Number of flips:", m_sls->get_num_moves());
|
||||||
|
IF_VERBOSE(10, verbose_stream() << res << "\n");
|
||||||
|
IF_VERBOSE(10, m_sls->display(verbose_stream()));
|
||||||
|
|
||||||
|
if (res == l_true) {
|
||||||
|
if (g->models_enabled()) {
|
||||||
|
model_ref mdl = m_sls->get_model();
|
||||||
|
mc = model2model_converter(mdl.get());
|
||||||
|
TRACE("sls_model", mc->display(tout););
|
||||||
|
}
|
||||||
|
g->reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mc = nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(goal_ref const& g,
|
||||||
|
goal_ref_buffer& result) override {
|
||||||
|
result.reset();
|
||||||
|
|
||||||
|
TRACE("sls", g->display(tout););
|
||||||
|
tactic_report report("sls", *g);
|
||||||
|
|
||||||
|
model_converter_ref mc;
|
||||||
|
run(g, mc);
|
||||||
|
g->add(mc.get());
|
||||||
|
g->inc_depth();
|
||||||
|
result.push_back(g.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup() override {
|
||||||
|
auto* d = alloc(sls::smt_solver, m, m_params);
|
||||||
|
std::swap(d, m_sls);
|
||||||
|
dealloc(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void collect_statistics(statistics& st) const override {
|
||||||
|
st.copy(m_st);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_statistics() override {
|
||||||
|
m_sls->reset_statistics();
|
||||||
|
m_st.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tactic* mk_sls_smt_tactic(ast_manager& m, params_ref const& p) {
|
||||||
|
return alloc(sls_smt_tactic, m, p);
|
||||||
|
}
|
||||||
|
|
||||||
class sls_tactic : public tactic {
|
class sls_tactic : public tactic {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
|
|
|
@ -23,9 +23,11 @@ class ast_manager;
|
||||||
class tactic;
|
class tactic;
|
||||||
|
|
||||||
tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p = params_ref());
|
tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||||
|
tactic * mk_sls_smt_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ADD_TACTIC("qfbv-sls", "(try to) solve using stochastic local search for QF_BV.", "mk_qfbv_sls_tactic(m, p)")
|
ADD_TACTIC("qfbv-sls", "(try to) solve using stochastic local search for QF_BV.", "mk_qfbv_sls_tactic(m, p)")
|
||||||
|
ADD_TACTIC("sls-smt", "(try to) solve SMT formulas using local search.", "mk_sls_smt_tactic(m, p)")
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue