3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

porting bv-sls

This commit is contained in:
Nikolaj Bjorner 2024-07-08 13:16:28 -07:00
parent e7104ebb93
commit ef54feec3d
18 changed files with 264 additions and 811 deletions

View file

@ -222,7 +222,7 @@ public:
#define MK_BV_BINARY(OP) \
expr_ref OP(expr* a, expr* b) { \
expr_ref result(m); \
expr_ref result(m); \
if (BR_FAILED == OP(a, b, result)) \
result = m_util.OP(a, b); \
return result; \
@ -237,6 +237,7 @@ public:
MK_BV_BINARY(mk_bv_urem);
MK_BV_BINARY(mk_ule);
MK_BV_BINARY(mk_sle);
MK_BV_BINARY(mk_bv_add);
MK_BV_BINARY(mk_bv_mul);
MK_BV_BINARY(mk_bv_sub);
@ -249,6 +250,13 @@ public:
return result;
}
expr_ref mk_bv_neg(expr* a) {
expr_ref result(a, m);
if (BR_FAILED == mk_uminus(a, result))
result = m_util.mk_bv_neg(a);
return result;
}
};

View file

@ -1,7 +1,6 @@
z3_add_component(ast_sls
SOURCES
bvsls_opt_engine.cpp
bv_sls.cpp
bv_sls_eval.cpp
bv_sls_fixed.cpp
bv_sls_terms.cpp

View file

@ -23,14 +23,13 @@ Author:
#include "ast/ast_ll_pp.h"
#include "params/sls_params.hpp"
namespace bv {
namespace bvu {
sls::sls(ast_manager& m, params_ref const& p):
m(m),
bv(m),
m_terms(m),
m_eval(m),
m_engine(m, p)
m_eval(m)
{
updt_params(p);
}
@ -100,55 +99,12 @@ namespace bv {
void sls::reinit_eval() {
init_repair_candidates();
if (m_to_repair.empty())
return;
// refresh the best model so far to a callback
set_model();
// add fresh units, if any
bool new_assertion = false;
while (m_get_unit) {
auto e = m_get_unit();
if (!e)
break;
new_assertion = true;
assert_expr(e);
}
if (new_assertion)
init();
std::function<bool(expr*, unsigned)> eval = [&](expr* e, unsigned i) {
unsigned id = e->get_id();
bool keep = !m_to_repair.contains(id);
if (m.is_bool(e)) {
if (m_eval.is_fixed0(e) || keep)
return m_eval.bval0(e);
if (m_engine_init) {
auto const& z = m_engine.get_value(e);
return rational(z).get_bit(0);
}
}
else if (bv.is_bv(e)) {
auto& w = m_eval.wval(e);
if (w.fixed.get(i) || keep)
return w.get_bit(i);
if (m_engine_init) {
auto const& z = m_engine.get_value(e);
return rational(z).get_bit(i);
}
}
return m_rand() % 2 == 0;
};
m_eval.init_eval(m_terms.assertions(), eval);
init_repair();
// m_engine_init = false;
}
std::pair<bool, app*> sls::next_to_repair() {
#if 0
app* e = nullptr;
if (m_repair_down != UINT_MAX) {
e = m_terms.term(m_repair_down);
@ -176,7 +132,7 @@ namespace bv {
}
m_repair_roots.remove(index);
}
#endif
return { false, nullptr };
}
@ -199,35 +155,17 @@ namespace bv {
return l_undef;
}
lbool sls::search2() {
lbool res = l_undef;
if (m_stats.m_restarts == 0)
res = m_engine(),
m_engine_init = true;
else if (m_stats.m_restarts % 1000 == 0)
res = m_engine.search_loop(),
m_engine_init = true;
if (res != l_undef)
m_engine_model = true;
return res;
}
lbool sls::operator()() {
lbool res = l_undef;
m_stats.reset();
m_stats.m_restarts = 0;
m_engine_model = false;
m_engine_init = false;
do {
res = search1();
if (res != l_undef)
break;
trace();
//res = search2();
if (res != l_undef)
break;
reinit_eval();
}
while (m.inc() && m_stats.m_restarts++ < m_config.m_max_restarts);
@ -300,26 +238,8 @@ namespace bv {
}
}
model_ref sls::get_model() {
if (m_engine_model)
return m_engine.get_model();
model_ref mdl = alloc(model, m);
auto& terms = m_eval.sort_assertions(m_terms.assertions());
for (expr* e : terms) {
if (!is_uninterp_const(e))
continue;
auto f = to_app(e)->get_decl();
auto v = m_eval.get_value(to_app(e));
if (v)
mdl->register_decl(f, v);
}
terms.reset();
return mdl;
}
std::ostream& sls::display(std::ostream& out) {
#if 0
auto& terms = m_eval.sort_assertions(m_terms.assertions());
for (expr* e : terms) {
out << e->get_id() << ": " << mk_bounded_pp(e, m, 1) << " ";
@ -333,6 +253,7 @@ namespace bv {
out << "\n";
}
terms.reset();
#endif
return out;
}
@ -344,7 +265,6 @@ namespace bv {
m_terms.updt_params(_p);
params_ref q = _p;
q.set_uint("max_restarts", 10);
m_engine.updt_params(q);
}
std::ostream& sls::trace_repair(bool down, expr* e) {

View file

@ -26,11 +26,10 @@ Author:
#include "ast/sls/sls_valuation.h"
#include "ast/sls/bv_sls_terms.h"
#include "ast/sls/bv_sls_eval.h"
#include "ast/sls/sls_engine.h"
#include "ast/bv_decl_plugin.h"
#include "model/model.h"
namespace bv {
namespace bvu {
class sls {
@ -42,15 +41,14 @@ namespace bv {
ast_manager& m;
bv_util bv;
sls_terms m_terms;
sls_eval m_eval;
sls_stats m_stats;
bv::sls_terms m_terms;
bv::sls_eval m_eval;
bv::sls_stats m_stats;
indexed_uint_set m_repair_up, m_repair_roots;
unsigned m_repair_down = UINT_MAX;
ptr_vector<expr> m_todo;
random_gen m_rand;
config m_config;
sls_engine m_engine;
bool m_engine_model = false;
bool m_engine_init = false;
std::function<expr_ref()> m_get_unit;
@ -78,11 +76,6 @@ namespace bv {
public:
sls(ast_manager& m, params_ref const& p);
/**
* Add constraints
*/
void assert_expr(expr* e) { m_terms.assert_expr(e); m_engine.assert_expr(e); }
/*
* Invoke init after all expressions are asserted.
*/
@ -110,17 +103,17 @@ namespace bv {
lbool operator()();
void updt_params(params_ref const& p);
void collect_statistics(statistics& st) const { m_stats.collect_statistics(st); m_engine.collect_statistics(st); }
void reset_statistics() { m_stats.reset(); m_engine.reset_statistics(); }
void collect_statistics(statistics& st) const { m_stats.collect_statistics(st); }
void reset_statistics() { m_stats.reset(); }
unsigned get_num_moves() { return m_stats.m_moves + m_engine.get_stats().m_moves; }
unsigned get_num_moves() { return m_stats.m_moves; }
std::ostream& display(std::ostream& out);
/**
* Retrieve valuation
*/
sls_valuation const& wval(expr* e) const { return m_eval.wval(e); }
bv::sls_valuation const& wval(expr* e) const { return m_eval.wval(e); }
model_ref get_model();

View file

@ -17,65 +17,31 @@ Author:
namespace bv {
sls_eval::sls_eval(ast_manager& m):
m(m),
sls_eval::sls_eval(sls_terms& terms, sls::context& ctx):
m(ctx.get_manager()),
ctx(ctx),
terms(terms),
bv(m),
m_fix(*this)
m_fix(*this, terms, ctx)
{}
void sls_eval::init_eval(expr_ref_vector const& es, std::function<bool(expr*, unsigned)> const& eval) {
auto& terms = sort_assertions(es);
for (expr* e : terms) {
void sls_eval::init_eval(std::function<bool(expr*, unsigned)> const& eval) {
for (expr* e : terms.subterms()) {
if (!is_app(e))
continue;
app* a = to_app(e);
if (bv.is_bv(e))
add_bit_vector(a);
if (a->get_family_id() == basic_family_id)
init_eval_basic(a);
else if (a->get_family_id() == bv.get_family_id())
if (!bv.is_bv(e))
continue;
add_bit_vector(a);
if (a->get_family_id() == bv.get_family_id())
init_eval_bv(a);
else if (is_uninterp(e)) {
if (bv.is_bv(e)) {
auto& v = wval(e);
for (unsigned i = 0; i < v.bw; ++i)
m_tmp.set(i, eval(e, i));
v.set_repair(random_bool(), m_tmp);
}
else if (m.is_bool(e))
m_eval.setx(e->get_id(), eval(e, 0), false);
}
else {
TRACE("sls", tout << "Unhandled expression " << mk_pp(e, m) << "\n");
auto& v = wval(e);
for (unsigned i = 0; i < v.bw; ++i)
m_tmp.set(i, eval(e, i));
v.set_repair(random_bool(), m_tmp);
}
}
terms.reset();
}
/**
* Sort all sub-expressions by depth, smallest first.
*/
ptr_vector<expr>& sls_eval::sort_assertions(expr_ref_vector const& es) {
expr_fast_mark1 mark;
for (expr* e : es) {
if (!mark.is_marked(e)) {
mark.mark(e);
m_todo.push_back(e);
}
}
for (unsigned i = 0; i < m_todo.size(); ++i) {
auto e = m_todo[i];
if (!is_app(e))
continue;
for (expr* arg : *to_app(e)) {
if (!mark.is_marked(arg)) {
mark.mark(arg);
m_todo.push_back(arg);
}
}
}
std::stable_sort(m_todo.begin(), m_todo.end(), [&](expr* a, expr* b) { return get_depth(a) < get_depth(b); });
return m_todo;
}
bool sls_eval::add_bit_vector(app* e) {
@ -115,83 +81,10 @@ namespace bv {
return r;
}
void sls_eval::init_eval_basic(app* e) {
auto id = e->get_id();
if (m.is_bool(e))
m_eval.setx(id, bval1(e), false);
else if (m.is_ite(e)) {
SASSERT(bv.is_bv(e->get_arg(1)));
auto& val = wval(e);
auto& val_th = wval(e->get_arg(1));
auto& val_el = wval(e->get_arg(2));
if (bval0(e->get_arg(0)))
val.set(val_th.bits());
else
val.set(val_el.bits());
}
else {
UNREACHABLE();
}
}
void sls_eval::init_eval_bv(app* e) {
if (bv.is_bv(e))
eval(e).commit_eval();
else if (m.is_bool(e))
m_eval.setx(e->get_id(), bval1_bv(e), false);
}
bool sls_eval::bval1_basic(app* e) const {
SASSERT(m.is_bool(e));
SASSERT(e->get_family_id() == basic_family_id);
auto id = e->get_id();
switch (e->get_decl_kind()) {
case OP_TRUE:
return true;
case OP_FALSE:
return false;
case OP_AND:
return all_of(*to_app(e), [&](expr* arg) { return bval0(arg); });
case OP_OR:
return any_of(*to_app(e), [&](expr* arg) { return bval0(arg); });
case OP_NOT:
return !bval0(e->get_arg(0));
case OP_XOR: {
bool r = false;
for (auto* arg : *to_app(e))
r ^= bval0(arg);
return r;
}
case OP_IMPLIES: {
auto a = e->get_arg(0);
auto b = e->get_arg(1);
return !bval0(a) || bval0(b);
}
case OP_ITE: {
auto c = bval0(e->get_arg(0));
return bval0(c ? e->get_arg(1) : e->get_arg(2));
}
case OP_EQ: {
auto a = e->get_arg(0);
auto b = e->get_arg(1);
if (m.is_bool(a))
return bval0(a) == bval0(b);
else if (bv.is_bv(a)) {
auto const& va = wval(a);
auto const& vb = wval(b);
return va.eq(vb);
}
return m.are_equal(a, b);
}
case OP_DISTINCT:
default:
verbose_stream() << mk_bounded_pp(e, m) << "\n";
UNREACHABLE();
break;
}
UNREACHABLE();
return false;
eval(e).commit_eval();
}
bool sls_eval::can_eval1(app* e) const {
@ -296,12 +189,10 @@ namespace bv {
}
bool sls_eval::bval1(app* e) const {
if (e->get_family_id() == basic_family_id)
return bval1_basic(e);
if (e->get_family_id() == bv.get_fid())
return bval1_bv(e);
SASSERT(is_uninterp_const(e));
return bval0(e);
UNREACHABLE();
return false;
}
sls_valuation& sls_eval::eval(app* e) const {
@ -701,41 +592,11 @@ namespace bv {
}
bool sls_eval::try_repair(app* e, unsigned i) {
if (is_fixed0(e->get_arg(i)))
return false;
else if (e->get_family_id() == basic_family_id)
return try_repair_basic(e, i);
if (e->get_family_id() == bv.get_family_id())
return try_repair_bv(e, i);
return false;
}
bool sls_eval::try_repair_basic(app* e, unsigned i) {
switch (e->get_decl_kind()) {
case OP_AND:
return try_repair_and_or(e, i);
case OP_OR:
return try_repair_and_or(e, i);
case OP_NOT:
return try_repair_not(e);
case OP_FALSE:
return false;
case OP_TRUE:
return false;
case OP_EQ:
return try_repair_eq(e, i);
case OP_IMPLIES:
return try_repair_implies(e, i);
case OP_XOR:
return try_repair_xor(e, i);
case OP_ITE:
return try_repair_ite(e, i);
default:
UNREACHABLE();
return false;
}
}
bool sls_eval::try_repair_bv(app* e, unsigned i) {
switch (e->get_decl_kind()) {
case OP_BAND:
@ -880,21 +741,7 @@ namespace bv {
}
}
bool sls_eval::try_repair_and_or(app* e, unsigned i) {
auto b = bval0(e);
auto child = e->get_arg(i);
if (b == bval0(child))
return false;
m_eval[child->get_id()] = b;
return true;
}
bool sls_eval::try_repair_not(app* e) {
auto child = e->get_arg(0);
m_eval[child->get_id()] = !bval0(e);
return true;
}
#if 0
bool sls_eval::try_repair_eq(app* e, unsigned i) {
auto child = e->get_arg(i);
auto is_true = bval0(e);
@ -911,6 +758,7 @@ namespace bv {
}
return false;
}
#endif
bool sls_eval::try_repair_eq(bool is_true, bvval& a, bvval const& b) {
if (is_true) {
@ -939,47 +787,6 @@ namespace bv {
}
}
bool sls_eval::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);
m_eval[child->get_id()] = ev != bv;
return true;
}
bool sls_eval::try_repair_ite(app* e, unsigned i) {
auto child = e->get_arg(i);
bool c = bval0(e->get_arg(0));
if (i == 0) {
m_eval[child->get_id()] = !c;
return true;
}
if (c != (i == 1))
return false;
if (m.is_bool(e)) {
m_eval[child->get_id()] = bval0(e);
return true;
}
if (bv.is_bv(e))
return wval(child).try_set(wval(e).bits());
return false;
}
bool sls_eval::try_repair_implies(app* e, unsigned i) {
auto child = e->get_arg(i);
bool ev = bval0(e);
bool av = bval0(child);
bool bv = bval0(e->get_arg(1 - i));
if (i == 0) {
if (ev == (!av || bv))
return false;
}
else if (ev != (!bv || av))
return false;
m_eval[child->get_id()] = ev;
return true;
}
//
// e = a & b
// e[i] = 1 -> a[i] = 1
@ -1892,28 +1699,18 @@ namespace bv {
}
bool sls_eval::repair_up(expr* e) {
if (!is_app(e))
if (!bv.is_bv(e) || !is_app(e))
return false;
if (m.is_bool(e)) {
auto b = bval1(to_app(e));
if (is_fixed0(e))
return b == bval0(e);
m_eval[e->get_id()] = b;
auto& v = eval(to_app(e));
for (unsigned i = 0; i < v.nw; ++i) {
if (0 != (v.fixed[i] & (v.bits()[i] ^ v.eval[i]))) {
v.bits().copy_to(v.nw, v.eval);
return false;
}
}
if (v.commit_eval())
return true;
}
if (bv.is_bv(e)) {
auto& v = eval(to_app(e));
for (unsigned i = 0; i < v.nw; ++i)
if (0 != (v.fixed[i] & (v.bits()[i] ^ v.eval[i]))) {
v.bits().copy_to(v.nw, v.eval);
return false;
}
if (v.commit_eval())
return true;
v.bits().copy_to(v.nw, v.eval);
return false;
}
v.bits().copy_to(v.nw, v.eval);
return false;
}
@ -1923,21 +1720,15 @@ namespace bv {
}
void sls_eval::init_eval(app* t) {
if (m.is_bool(t))
set(t, bval1(t));
else if (bv.is_bv(t)) {
if (bv.is_bv(t)) {
auto& v = wval(t);
v.bits().copy_to(v.nw, v.eval);
}
}
void sls_eval::commit_eval(app* e) {
if (m.is_bool(e)) {
set(e, bval1(e));
}
else {
VERIFY(wval(e).commit_eval());
}
if (bv.is_bv(e))
VERIFY(wval(e).commit_eval());
}
void sls_eval::set_random(app* e) {
@ -1983,6 +1774,7 @@ namespace bv {
}
std::ostream& sls_eval::display(std::ostream& out, expr_ref_vector const& es) {
#if 0
auto& terms = sort_assertions(es);
for (expr* e : terms) {
out << e->get_id() << ": " << mk_bounded_pp(e, m, 1) << " ";
@ -1991,14 +1783,13 @@ namespace bv {
display_value(out, e) << "\n";
}
terms.reset();
#endif
return out;
}
std::ostream& sls_eval::display_value(std::ostream& out, expr* e) {
if (bv.is_bv(e))
return out << wval(e);
if (m.is_bool(e))
return out << (bval0(e)?"T":"F");
return out << "?";
}
}

View file

@ -19,17 +19,12 @@ Author:
#include "ast/ast.h"
#include "ast/sls/sls_valuation.h"
#include "ast/sls/bv_sls_fixed.h"
#include "ast/sls/sls_smt.h"
#include "ast/bv_decl_plugin.h"
namespace bv {
class sls_fixed;
class sls_eval_plugin {
public:
virtual ~sls_eval_plugin() {}
};
class sls_terms;
class sls_eval {
struct config {
@ -39,28 +34,24 @@ namespace bv {
friend class sls_fixed;
friend class sls_test;
ast_manager& m;
sls::context& ctx;
sls_terms& terms;
bv_util bv;
sls_fixed m_fix;
mutable mpn_manager mpn;
ptr_vector<expr> m_todo;
random_gen m_rand;
config m_config;
scoped_ptr_vector<sls_eval_plugin> m_plugins;
bool_vector m_fixed;
scoped_ptr_vector<sls_valuation> m_values; // expr-id -> bv valuation
bool_vector m_eval; // expr-id -> boolean valuation
bool_vector m_fixed; // expr-id -> is Boolean fixed
mutable bvect m_tmp, m_tmp2, m_tmp3, m_tmp4, m_zero, m_one, m_minus_one;
bvect m_a, m_b, m_nextb, m_nexta, m_aux;
using bvval = sls_valuation;
void init_eval_basic(app* e);
void init_eval_bv(app* e);
/**
@ -70,20 +61,13 @@ namespace bv {
bool add_bit_vector(app* e);
sls_valuation* alloc_valuation(app* e);
bool bval1_basic(app* e) const;
//bool bval1_basic(app* e) const;
bool bval1_bv(app* e) const;
/**
* Repair operations
*/
bool try_repair_basic(app* e, unsigned i);
bool try_repair_bv(app * e, unsigned i);
bool try_repair_and_or(app* e, unsigned i);
bool try_repair_not(app* e);
bool try_repair_eq(app* e, unsigned i);
bool try_repair_xor(app* e, unsigned i);
bool try_repair_ite(app* e, unsigned i);
bool try_repair_implies(app* e, unsigned i);
bool try_repair_band(bvect const& e, bvval& a, bvval const& b);
bool try_repair_bor(bvect const& e, bvval& a, bvval const& b);
bool try_repair_add(bvect const& e, bvval& a, bvval const& b);
@ -136,32 +120,30 @@ namespace bv {
bvect const& eval_value(app* e) const { return wval(e).eval; }
bool bval0(expr* e) const { return ctx.is_true(e); }
/**
* Retrieve evaluation based on immediate children.
*/
bool bval1(app* e) const;
bool can_eval1(app* e) const;
public:
sls_eval(ast_manager& m);
sls_eval(sls_terms& terms, sls::context& ctx);
void init_eval(expr_ref_vector const& es, std::function<bool(expr*, unsigned)> const& eval);
void init_eval(std::function<bool(expr*, unsigned)> const& eval);
void tighten_range(expr_ref_vector const& es) { m_fix.init(es); }
ptr_vector<expr>& sort_assertions(expr_ref_vector const& es);
void tighten_range() { m_fix.init(); }
/**
* Retrieve evaluation based on cache.
* bval - Boolean values
* wval - Word (bit-vector) values
*/
bool bval0(expr* e) const { return m_eval[e->get_id()]; }
*/
sls_valuation& wval(expr* e) const;
bool is_fixed0(expr* e) const { return m_fixed.get(e->get_id(), false); }
/**
* Retrieve evaluation based on immediate children.
*/
bool bval1(app* e) const;
bool can_eval1(app* e) const;
sls_valuation& eval(app* e) const;
@ -176,18 +158,10 @@ namespace bv {
bool re_eval_is_correct(app* e);
expr_ref get_value(app* e);
/**
* Override evaluaton.
*/
void set(expr* e, bool b) {
m_eval[e->get_id()] = b;
}
/*
* Try to invert value of child to repair value assignment of parent.
*/
* Try to invert value of child to repair value assignment of parent.
*/
bool try_repair(app* e, unsigned i);

View file

@ -14,55 +14,48 @@ Author:
#include "ast/ast_pp.h"
#include "ast/ast_ll_pp.h"
#include "ast/sls/bv_sls_fixed.h"
#include "ast/sls/bv_sls_terms.h"
#include "ast/sls/bv_sls_eval.h"
namespace bv {
sls_fixed::sls_fixed(sls_eval& ev):
sls_fixed::sls_fixed(sls_eval& ev, sls_terms& terms, sls::context& ctx):
ev(ev),
terms(terms),
m(ev.m),
bv(ev.bv)
bv(ev.bv),
ctx(ctx)
{}
void sls_fixed::init(expr_ref_vector const& es) {
ev.sort_assertions(es);
for (expr* e : ev.m_todo) {
if (!is_app(e))
continue;
app* a = to_app(e);
ev.m_fixed.setx(a->get_id(), is_fixed1(a), false);
if (a->get_family_id() == basic_family_id)
init_fixed_basic(a);
else if (a->get_family_id() == bv.get_family_id())
init_fixed_bv(a);
else
;
}
init_ranges(es);
ev.m_todo.reset();
}
void sls_fixed::init() {
for (auto e : terms.subterms())
set_fixed(e);
void sls_fixed::init_ranges(expr_ref_vector const& es) {
for (expr* e : es) {
bool sign = m.is_not(e, e);
if (is_app(e))
init_range(to_app(e), sign);
for (auto const& c : ctx.clauses()) {
if (c.m_clause.size() == 1) {
auto lit = c.m_clause[0];
auto a = ctx.atom(lit.var());
if (!a)
continue;
a = terms.translated(a);
if (is_app(a))
init_range(to_app(a), lit.sign());
ev.m_fixed.setx(a->get_id(), true, false);
}
}
for (expr* e : ev.m_todo)
propagate_range_up(e);
for (auto e : terms.subterms())
propagate_range_up(e);
}
void sls_fixed::propagate_range_up(expr* e) {
expr* t, * s;
rational v;
if (bv.is_concat(e, t, s)) {
auto& vals = wval(s);
auto& vals = ev.wval(s);
if (vals.lo() != vals.hi() && (vals.lo() < vals.hi() || vals.hi() == 0))
// lo <= e
add_range(e, vals.lo(), rational::zero(), false);
auto valt = wval(t);
auto valt = ev.wval(t);
if (valt.lo() != valt.hi() && (valt.lo() < valt.hi() || valt.hi() == 0)) {
// (2^|s|) * lo <= e < (2^|s|) * hi
auto p = rational::power_of_two(bv.get_bv_size(s));
@ -70,12 +63,12 @@ namespace bv {
}
}
else if (bv.is_bv_add(e, s, t) && bv.is_numeral(s, v)) {
auto& val = wval(t);
auto& val = ev.wval(t);
if (val.lo() != val.hi())
add_range(e, v + val.lo(), v + val.hi(), false);
}
else if (bv.is_bv_add(e, t, s) && bv.is_numeral(s, v)) {
auto& val = wval(t);
auto& val = ev.wval(t);
if (val.lo() != val.hi())
add_range(e, v + val.lo(), v + val.hi(), false);
}
@ -83,7 +76,7 @@ namespace bv {
// x in [lo, hi[ => -x in [-hi + 1, -lo + 1[
else if (bv.is_bv_mul(e, s, t) && bv.is_numeral(s, v) &&
v + 1 == rational::power_of_two(bv.get_bv_size(e))) {
auto& val = wval(t);
auto& val = ev.wval(t);
if (val.lo() != val.hi())
add_range(e, -val.hi() + 1, - val.lo() + 1, false);
}
@ -149,7 +142,7 @@ namespace bv {
return true;
}
else if (bv.is_bit2bool(e, s, idx)) {
auto& val = wval(s);
auto& val = ev.wval(s);
val.try_set_bit(idx, !sign);
val.fixed.set(idx, true);
val.tighten_range();
@ -188,13 +181,13 @@ namespace bv {
if (bv.is_extract(t, lo, hi, s)) {
if (hi == lo) {
sign = sign ? a == 1 : a == 0;
auto& val = wval(s);
auto& val = ev.wval(s);
if (val.try_set_bit(lo, !sign))
val.fixed.set(lo, true);
val.tighten_range();
}
else if (!sign) {
auto& val = wval(s);
auto& val = ev.wval(s);
for (unsigned i = lo; i <= hi; ++i)
if (val.try_set_bit(i, a.get_bit(i - lo)))
val.fixed.set(i, true);
@ -236,7 +229,7 @@ namespace bv {
}
bool sls_fixed::add_range(expr* e, rational lo, rational hi, bool sign) {
auto& v = wval(e);
auto& v = ev.wval(e);
lo = mod(lo, rational::power_of_two(bv.get_bv_size(e)));
hi = mod(hi, rational::power_of_two(bv.get_bv_size(e)));
if (lo == hi)
@ -285,50 +278,19 @@ namespace bv {
x = nullptr;
}
sls_valuation& sls_fixed::wval(expr* e) {
return ev.wval(e);
}
void sls_fixed::init_fixed_basic(app* e) {
if (bv.is_bv(e) && m.is_ite(e)) {
auto& val = wval(e);
auto& val_th = wval(e->get_arg(1));
auto& val_el = wval(e->get_arg(2));
for (unsigned i = 0; i < val.nw; ++i)
val.fixed[i] = val_el.fixed[i] & val_th.fixed[i] & ~(val_el.bits(i) ^ val_th.bits(i));
}
}
void sls_fixed::init_fixed_bv(app* e) {
if (bv.is_bv(e))
set_fixed_bw(e);
}
bool sls_fixed::is_fixed1(app* e) const {
if (is_uninterp(e))
return false;
if (e->get_family_id() == basic_family_id)
return is_fixed1_basic(e);
return all_of(*e, [&](expr* arg) { return ev.is_fixed0(arg); });
}
bool sls_fixed::is_fixed1_basic(app* e) const {
switch (e->get_decl_kind()) {
case OP_TRUE:
case OP_FALSE:
return true;
case OP_AND:
return any_of(*e, [&](expr* arg) { return ev.is_fixed0(arg) && !ev.bval0(e); });
case OP_OR:
return any_of(*e, [&](expr* arg) { return ev.is_fixed0(arg) && ev.bval0(e); });
default:
return all_of(*e, [&](expr* arg) { return ev.is_fixed0(arg); });
}
}
void sls_fixed::set_fixed_bw(app* e) {
SASSERT(bv.is_bv(e));
SASSERT(e->get_family_id() == bv.get_fid());
void sls_fixed::set_fixed(expr* _e) {
if (!is_app(_e))
return;
auto e = to_app(_e);
if (!bv.is_bv(e))
return;
auto& v = ev.wval(e);
if (all_of(*e, [&](expr* arg) { return ev.is_fixed0(arg); })) {
for (unsigned i = 0; i < v.bw; ++i)
@ -336,39 +298,54 @@ namespace bv {
ev.m_fixed.setx(e->get_id(), true, false);
return;
}
if (m.is_ite(e)) {
auto& val_th = ev.wval(e->get_arg(1));
auto& val_el = ev.wval(e->get_arg(2));
for (unsigned i = 0; i < v.nw; ++i)
v.fixed[i] = val_el.fixed[i] & val_th.fixed[i] & ~(val_el.bits(i) ^ val_th.bits(i));
return;
}
if (e->get_family_id() != bv.get_fid())
return;
switch (e->get_decl_kind()) {
case OP_BAND: {
auto& a = wval(e->get_arg(0));
auto& b = wval(e->get_arg(1));
SASSERT(e->get_num_args() == 2);
auto& a = ev.wval(e->get_arg(0));
auto& b = ev.wval(e->get_arg(1));
// (a.fixed & b.fixed) | (a.fixed & ~a.bits) | (b.fixed & ~b.bits)
for (unsigned i = 0; i < a.nw; ++i)
v.fixed[i] = (a.fixed[i] & b.fixed[i]) | (a.fixed[i] & ~a.bits(i)) | (b.fixed[i] & ~b.bits(i));
break;
}
case OP_BOR: {
auto& a = wval(e->get_arg(0));
auto& b = wval(e->get_arg(1));
SASSERT(e->get_num_args() == 2);
auto& a = ev.wval(e->get_arg(0));
auto& b = ev.wval(e->get_arg(1));
// (a.fixed & b.fixed) | (a.fixed & a.bits) | (b.fixed & b.bits)
for (unsigned i = 0; i < a.nw; ++i)
v.fixed[i] = (a.fixed[i] & b.fixed[i]) | (a.fixed[i] & a.bits(i)) | (b.fixed[i] & b.bits(i));
break;
}
case OP_BXOR: {
auto& a = wval(e->get_arg(0));
auto& b = wval(e->get_arg(1));
SASSERT(e->get_num_args() == 2);
auto& a = ev.wval(e->get_arg(0));
auto& b = ev.wval(e->get_arg(1));
for (unsigned i = 0; i < a.nw; ++i)
v.fixed[i] = a.fixed[i] & b.fixed[i];
break;
}
case OP_BNOT: {
auto& a = wval(e->get_arg(0));
auto& a = ev.wval(e->get_arg(0));
for (unsigned i = 0; i < a.nw; ++i)
v.fixed[i] = a.fixed[i];
break;
}
case OP_BADD: {
auto& a = wval(e->get_arg(0));
auto& b = wval(e->get_arg(1));
SASSERT(e->get_num_args() == 2);
auto& a = ev.wval(e->get_arg(0));
auto& b = ev.wval(e->get_arg(1));
bool pfixed = true;
for (unsigned i = 0; i < v.bw; ++i) {
if (pfixed && a.fixed.get(i) && b.fixed.get(i))
@ -386,8 +363,9 @@ namespace bv {
break;
}
case OP_BMUL: {
auto& a = wval(e->get_arg(0));
auto& b = wval(e->get_arg(1));
SASSERT(e->get_num_args() == 2);
auto& a = ev.wval(e->get_arg(0));
auto& b = ev.wval(e->get_arg(1));
unsigned j = 0, k = 0, zj = 0, zk = 0, hzj = 0, hzk = 0;
// i'th bit depends on bits j + k = i
// if the first j, resp k bits are 0, the bits j + k are 0
@ -437,8 +415,9 @@ namespace bv {
break;
}
case OP_CONCAT: {
auto& a = wval(e->get_arg(0));
auto& b = wval(e->get_arg(1));
SASSERT(e->get_num_args() == 2);
auto& a = ev.wval(e->get_arg(0));
auto& b = ev.wval(e->get_arg(1));
for (unsigned i = 0; i < b.bw; ++i)
v.fixed.set(i, b.fixed.get(i));
for (unsigned i = 0; i < a.bw; ++i)
@ -449,13 +428,13 @@ namespace bv {
expr* child;
unsigned lo, hi;
VERIFY(bv.is_extract(e, lo, hi, child));
auto& a = wval(child);
auto& a = ev.wval(child);
for (unsigned i = lo; i <= hi; ++i)
v.fixed.set(i - lo, a.fixed.get(i));
break;
}
case OP_BNEG: {
auto& a = wval(e->get_arg(0));
auto& a = ev.wval(e->get_arg(0));
bool pfixed = true;
for (unsigned i = 0; i < v.bw; ++i) {
if (pfixed && a.fixed.get(i))

View file

@ -18,18 +18,21 @@ Author:
#include "ast/ast.h"
#include "ast/sls/sls_valuation.h"
#include "ast/sls/sls_smt.h"
#include "ast/bv_decl_plugin.h"
namespace bv {
class sls_eval;
class sls_terms;
class sls_fixed {
sls_eval& ev;
sls_terms& terms;
ast_manager& m;
bv_util& bv;
sls::context& ctx;
void init_ranges(expr_ref_vector const& es);
bool init_range(app* e, bool sign);
void propagate_range_up(expr* e);
bool init_range(expr* x, rational const& a, expr* y, rational const& b, bool sign);
@ -37,19 +40,11 @@ namespace bv {
bool init_eq(expr* e, rational const& v, bool sign);
bool add_range(expr* e, rational lo, rational hi, bool sign);
void init_fixed_basic(app* e);
void init_fixed_bv(app* e);
bool is_fixed1(app* e) const;
bool is_fixed1_basic(app* e) const;
void set_fixed_bw(app* e);
sls_valuation& wval(expr* e);
void set_fixed(expr* e);
public:
sls_fixed(sls_eval& ev);
void init(expr_ref_vector const& es);
sls_fixed(sls_eval& ev, sls_terms& terms, sls::context& ctx);
void init();
};
}

View file

@ -20,57 +20,50 @@ Author:
#include "ast/ast_ll_pp.h"
#include "ast/sls/bv_sls.h"
#include "ast/rewriter/th_rewriter.h"
#include "ast/rewriter/bool_rewriter.h"
#include "ast/rewriter/bv_rewriter.h"
namespace bv {
sls_terms::sls_terms(ast_manager& m):
m(m),
sls_terms::sls_terms(sls::context& ctx):
ctx(ctx),
m(ctx.get_manager()),
bv(m),
m_rewriter(m),
m_assertions(m),
m_pinned(m),
m_translated(m),
m_terms(m){}
m_translated(m) {}
void sls_terms::init() {
for (auto t : ctx.subterms())
ensure_binary(t);
void sls_terms::assert_expr(expr* e) {
m_assertions.push_back(ensure_binary(e));
}
expr* sls_terms::ensure_binary(expr* e) {
expr* top = e;
m_pinned.push_back(e);
m_todo.push_back(e);
{
expr_fast_mark1 mark;
for (unsigned i = 0; i < m_todo.size(); ++i) {
expr* e = m_todo[i];
if (!is_app(e))
m_subterms.reset();
expr_fast_mark1 visited;
for (auto t : ctx.subterms())
m_subterms.push_back(translated(t));
for (auto t : m_subterms)
visited.mark(t, true);
for (unsigned i = 0; i < m_subterms.size(); ++i) {
auto t = m_subterms[i];
if (!is_app(t))
continue;
app* a = to_app(t);
for (expr* arg : *a) {
if (visited.is_marked(arg))
continue;
if (m_translated.get(e->get_id(), nullptr))
continue;
if (mark.is_marked(e))
continue;
mark.mark(e);
for (auto arg : *to_app(e))
m_todo.push_back(arg);
visited.mark(arg, true);
m_subterms.push_back(arg);
}
}
std::stable_sort(m_todo.begin(), m_todo.end(), [&](expr* a, expr* b) { return get_depth(a) < get_depth(b); });
for (expr* e : m_todo)
ensure_binary_core(e);
m_todo.reset();
return m_translated.get(top->get_id());
std::stable_sort(m_subterms.begin(), m_subterms.end(),
[](expr* a, expr* b) { return a->get_id() < b->get_id(); });
}
void sls_terms::ensure_binary_core(expr* e) {
void sls_terms::ensure_binary(expr* e) {
if (m_translated.get(e->get_id(), nullptr))
return;
app* a = to_app(e);
auto arg = [&](unsigned i) {
return m_translated.get(a->get_arg(i)->get_id());
return a->get_arg(i);
};
unsigned num_args = a->get_num_args();
expr_ref r(m);
@ -79,16 +72,7 @@ namespace bv {
for (unsigned i = 1; i < num_args; ++i)\
r = oper(r, arg(i)); \
if (m.is_and(e)) {
FOLD_OP(m.mk_and);
}
else if (m.is_or(e)) {
FOLD_OP(m.mk_or);
}
else if (m.is_xor(e)) {
FOLD_OP(m.mk_xor);
}
else if (bv.is_bv_and(e)) {
if (bv.is_bv_and(e)) {
FOLD_OP(bv.mk_bv_and);
}
else if (bv.is_bv_or(e)) {
@ -106,13 +90,6 @@ namespace bv {
else if (bv.is_concat(e)) {
FOLD_OP(bv.mk_concat);
}
else if (m.is_distinct(e)) {
expr_ref_vector es(m);
for (unsigned i = 0; i < num_args; ++i)
for (unsigned j = i + 1; j < num_args; ++j)
es.push_back(m.mk_not(m.mk_eq(arg(i), arg(j))));
r = m.mk_and(es);
}
else if (bv.is_bv_sdiv(e) || bv.is_bv_sdiv0(e) || bv.is_bv_sdivi(e)) {
r = mk_sdiv(arg(0), arg(1));
}
@ -122,12 +99,8 @@ namespace bv {
else if (bv.is_bv_srem(e) || bv.is_bv_srem0(e) || bv.is_bv_sremi(e)) {
r = mk_srem(arg(0), arg(1));
}
else {
for (unsigned i = 0; i < num_args; ++i)
m_args.push_back(arg(i));
r = m.mk_app(a->get_decl(), num_args, m_args.data());
m_args.reset();
}
else
r = e;
m_translated.setx(e->get_id(), r);
}
@ -140,19 +113,20 @@ namespace bv {
// x < 0, y > 0 -> -d
// x > 0, y > 0 -> d
// x < 0, y < 0 -> d
bool_rewriter br(m);
bv_rewriter bvr(m);
unsigned sz = bv.get_bv_size(x);
rational N = rational::power_of_two(sz);
expr_ref z(bv.mk_zero(sz), m);
expr* signx = bv.mk_ule(bv.mk_numeral(N / 2, sz), x);
expr* signy = bv.mk_ule(bv.mk_numeral(N / 2, sz), y);
expr* absx = m.mk_ite(signx, bv.mk_bv_neg(x), x);
expr* absy = m.mk_ite(signy, bv.mk_bv_neg(y), y);
expr* signx = bvr.mk_ule(bv.mk_numeral(N / 2, sz), x);
expr* signy = bvr.mk_ule(bv.mk_numeral(N / 2, sz), y);
expr* absx = br.mk_ite(signx, bvr.mk_bv_neg(x), x);
expr* absy = br.mk_ite(signy, bvr.mk_bv_neg(y), y);
expr* d = bv.mk_bv_udiv(absx, absy);
expr_ref r(m.mk_ite(m.mk_eq(signx, signy), d, bv.mk_bv_neg(d)), m);
r = m.mk_ite(m.mk_eq(z, y),
m.mk_ite(signx, bv.mk_one(sz), bv.mk_numeral(N - 1, sz)),
m.mk_ite(m.mk_eq(x, z), z, r));
m_rewriter(r);
expr_ref r(br.mk_ite(br.mk_eq(signx, signy), d, bvr.mk_bv_neg(d)), m);
r = br.mk_ite(br.mk_eq(z, y),
br.mk_ite(signx, bv.mk_one(sz), bv.mk_numeral(N - 1, sz)),
br.mk_ite(br.mk_eq(x, z), z, r));
return r;
}
@ -164,18 +138,19 @@ namespace bv {
// x < 0, y >= 0 -> y - u
// x >= 0, y < 0 -> y + u
// x >= 0, y >= 0 -> u
bool_rewriter br(m);
bv_rewriter bvr(m);
unsigned sz = bv.get_bv_size(x);
expr_ref z(bv.mk_zero(sz), m);
expr_ref abs_x(m.mk_ite(bv.mk_sle(z, x), x, bv.mk_bv_neg(x)), m);
expr_ref abs_y(m.mk_ite(bv.mk_sle(z, y), y, bv.mk_bv_neg(y)), m);
expr_ref u(bv.mk_bv_urem(abs_x, abs_y), m);
expr_ref abs_x(br.mk_ite(bvr.mk_sle(z, x), x, bvr.mk_bv_neg(x)), m);
expr_ref abs_y(br.mk_ite(bvr.mk_sle(z, y), y, bvr.mk_bv_neg(y)), m);
expr_ref u(bvr.mk_bv_urem(abs_x, abs_y), m);
expr_ref r(m);
r = m.mk_ite(m.mk_eq(u, z), z,
m.mk_ite(m.mk_eq(y, z), x,
m.mk_ite(m.mk_and(bv.mk_sle(z, x), bv.mk_sle(z, x)), u,
m.mk_ite(bv.mk_sle(z, x), bv.mk_bv_add(y, u),
m.mk_ite(bv.mk_sle(z, y), bv.mk_bv_sub(y, u), bv.mk_bv_neg(u))))));
m_rewriter(r);
r = br.mk_ite(br.mk_eq(u, z), z,
br.mk_ite(br.mk_eq(y, z), x,
br.mk_ite(br.mk_and(bvr.mk_sle(z, x), bvr.mk_sle(z, x)), u,
br.mk_ite(bvr.mk_sle(z, x), bvr.mk_bv_add(y, u),
br.mk_ite(bv.mk_sle(z, y), bvr.mk_bv_sub(y, u), bvr.mk_bv_neg(u))))));
return r;
}
@ -183,47 +158,11 @@ namespace bv {
// y = 0 -> x
// else x - sdiv(x, y) * y
expr_ref r(m);
r = m.mk_ite(m.mk_eq(y, bv.mk_zero(bv.get_bv_size(x))),
x, bv.mk_bv_sub(x, bv.mk_bv_mul(y, mk_sdiv(x, y))));
m_rewriter(r);
bool_rewriter br(m);
bv_rewriter bvr(m);
expr_ref z(bv.mk_zero(bv.get_bv_size(x)), m);
r = br.mk_ite(br.mk_eq(y, z), x, bvr.mk_bv_sub(x, bvr.mk_bv_mul(y, mk_sdiv(x, y))));
return r;
}
void sls_terms::init() {
// populate terms
expr_fast_mark1 mark;
for (expr* e : m_assertions)
m_todo.push_back(e);
while (!m_todo.empty()) {
expr* e = m_todo.back();
m_todo.pop_back();
if (mark.is_marked(e) || !is_app(e))
continue;
mark.mark(e);
m_terms.setx(e->get_id(), to_app(e));
for (expr* arg : *to_app(e))
m_todo.push_back(arg);
}
// populate parents
m_parents.reset();
m_parents.reserve(m_terms.size());
for (expr* e : m_terms) {
if (!e || !is_app(e))
continue;
for (expr* arg : *to_app(e))
m_parents[arg->get_id()].push_back(e);
}
m_assertion_set.reset();
for (auto a : m_assertions)
m_assertion_set.insert(a->get_id());
}
void sls_terms::updt_params(params_ref const& p) {
params_ref q = p;
q.set_bool("flat", false);
m_rewriter.updt_params(q);
}
}

View file

@ -17,63 +17,41 @@ Author:
#pragma once
#include "util/lbool.h"
#include "util/params.h"
#include "util/scoped_ptr_vector.h"
#include "util/uint_set.h"
#include "ast/ast.h"
#include "ast/rewriter/th_rewriter.h"
#include "ast/bv_decl_plugin.h"
#include "ast/sls/sls_stats.h"
#include "ast/sls/sls_powers.h"
#include "ast/sls/sls_valuation.h"
#include "ast/bv_decl_plugin.h"
#include "ast/sls/sls_smt.h"
namespace bv {
class sls_terms {
sls::context& ctx;
ast_manager& m;
bv_util bv;
th_rewriter m_rewriter;
ptr_vector<expr> m_todo, m_args;
expr_ref_vector m_assertions, m_pinned, m_translated;
app_ref_vector m_terms;
vector<ptr_vector<expr>> m_parents;
tracked_uint_set m_assertion_set;
expr_ref_vector m_translated;
ptr_vector<expr> m_subterms;
expr* ensure_binary(expr* e);
void ensure_binary_core(expr* e);
void ensure_binary(expr* e);
expr_ref mk_sdiv(expr* x, expr* y);
expr_ref mk_smod(expr* x, expr* y);
expr_ref mk_srem(expr* x, expr* y);
public:
sls_terms(ast_manager& m);
void updt_params(params_ref const& p);
/**
* Add constraints
*/
void assert_expr(expr* e);
sls_terms(sls::context& ctx);
/**
* Initialize structures: assertions, parents, terms
*/
void init();
/**
* Accessors.
*/
ptr_vector<expr> const& parents(expr* e) const { return m_parents[e->get_id()]; }
expr* translated(expr* e) const { return m_translated.get(e->get_id(), nullptr); }
expr_ref_vector const& assertions() const { return m_assertions; }
app* term(unsigned id) const { return m_terms.get(id); }
app_ref_vector const& terms() const { return m_terms; }
bool is_assertion(expr* e) const { return m_assertion_set.contains(e->get_id()); }
ptr_vector<expr> const& subterms() const { return m_subterms; }
};
}

View file

@ -11,8 +11,7 @@
Author:
Nikolaj Bjorner, Marijn Heule 2019-4-23
Nikolaj Bjorner, Marijn Heule 2019-4-23
Notes:

View file

@ -6,8 +6,8 @@ namespace sls {
bv_plugin::bv_plugin(context& ctx):
plugin(ctx),
bv(m),
m_terms(m),
m_eval(m)
m_terms(ctx),
m_eval(m_terms, ctx)
{}
void bv_plugin::init_bool_var(sat::bool_var v) {
@ -55,39 +55,9 @@ namespace sls {
}
std::pair<bool, app*> bv_plugin::next_to_repair() {
app* e = nullptr;
if (m_repair_down != UINT_MAX) {
e = m_terms.term(m_repair_down);
m_repair_down = UINT_MAX;
return { true, e };
}
if (!m_repair_up.empty()) {
unsigned index = m_repair_up.elem_at(ctx.rand(m_repair_up.size()));
m_repair_up.remove(index);
e = m_terms.term(index);
return { false, e };
}
while (!m_repair_roots.empty()) {
unsigned index = m_repair_roots.elem_at(ctx.rand(m_repair_roots.size()));
e = m_terms.term(index);
if (m_terms.is_assertion(e) && !m_eval.bval1(e)) {
SASSERT(m_eval.bval0(e));
return { true, e };
}
if (!m_eval.re_eval_is_correct(e)) {
init_repair_goal(e);
return { true, e };
}
m_repair_roots.remove(index);
}
return { false, nullptr };
}
void bv_plugin::init_repair_goal(app* e) {
m_eval.init_eval(e);
}
}

View file

@ -33,7 +33,7 @@ namespace sls {
unsigned m_repair_down = UINT_MAX;
std::pair<bool, app*> next_to_repair();
void init_repair_goal(app* e);
public:
bv_plugin(context& ctx);
~bv_plugin() override {}

View file

@ -29,7 +29,7 @@ namespace sls {
}
context::context(ast_manager& m, sat_solver_context& s) :
m(m), s(s), m_atoms(m), m_subterms(m) {
m(m), s(s), m_atoms(m), m_allterms(m) {
reset();
}
@ -40,7 +40,7 @@ namespace sls {
void context::register_atom(sat::bool_var v, expr* e) {
m_atoms.setx(v, e);
m_atom2bool_var.setx(e->get_id(), v, UINT_MAX);
m_atom2bool_var.setx(e->get_id(), v, sat::null_bool_var);
}
void context::reset() {
@ -51,7 +51,7 @@ namespace sls {
m_parents.reset();
m_relevant.reset();
m_visited.reset();
m_subterms.reset();
m_allterms.reset();
register_plugin(alloc(cc_plugin, *this));
register_plugin(alloc(arith_plugin, *this));
}
@ -86,6 +86,18 @@ namespace sls {
return l_undef;
}
bool context::is_true(expr* e) {
SASSERT(m.is_bool(e));
auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var);
SASSERT(v != sat::null_bool_var);
return is_true(sat::literal(v, false));
}
bool context::is_fixed(expr* e) {
// is this a Boolean literal that is a unit?
return false;
}
expr_ref context::get_value(expr* e) {
if (m.is_bool(e)) {
auto v = m_atom2bool_var[e->get_id()];
@ -144,7 +156,7 @@ namespace sls {
auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var);
if (v == sat::null_bool_var) {
v = s.add_var();
register_subterms(e);
register_terms(e);
register_atom(v, e);
init_bool_var(v);
}
@ -170,18 +182,19 @@ namespace sls {
void context::register_terms() {
for (auto a : m_atoms)
if (a)
register_subterms(a);
register_terms(a);
}
void context::register_subterms(expr* e) {
void context::register_terms(expr* e) {
auto is_visited = [&](expr* e) {
return nullptr != m_subterms.get(e->get_id(), nullptr);
return nullptr != m_allterms.get(e->get_id(), nullptr);
};
auto visit = [&](expr* e) {
m_subterms.setx(e->get_id(), e);
m_allterms.setx(e->get_id(), e);
};
if (is_visited(e))
return;
m_subterms.reset();
m_todo.push_back(e);
while (!m_todo.empty()) {
expr* e = m_todo.back();
@ -216,6 +229,17 @@ namespace sls {
p->register_term(e);
}
ptr_vector<expr> const& context::subterms() {
if (!m_subterms.empty())
return m_subterms;
for (auto e : m_allterms)
if (e)
m_subterms.push_back(e);
std::stable_sort(m_subterms.begin(), m_subterms.end(),
[](expr* a, expr* b) { return a->get_id() < b->get_id(); });
return m_subterms;
}
void context::reinit_relevant() {
m_relevant.reset();
m_visited.reset();

View file

@ -80,7 +80,8 @@ namespace sls {
random_gen m_rand;
bool m_initialized = false;
bool m_new_constraint = false;
expr_ref_vector m_subterms;
expr_ref_vector m_allterms;
ptr_vector<expr> m_subterms;
void register_plugin(plugin* p);
@ -88,7 +89,7 @@ namespace sls {
void init_bool_var(sat::bool_var v);
void register_terms();
ptr_vector<expr> m_todo;
void register_subterms(expr* e);
void register_terms(expr* e);
void register_term(expr* e);
sat::bool_var mk_atom(expr* e);
@ -119,9 +120,12 @@ namespace sls {
// Between plugin solvers
expr_ref get_value(expr* e);
bool is_true(expr* e);
bool is_fixed(expr* e);
void set_value(expr* e, expr* v);
bool is_relevant(expr* e);
void add_constraint(expr* e);
ptr_vector<expr> const& subterms();
ast_manager& get_manager() { return m; }
std::ostream& display(std::ostream& out) const;
};