mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
testing / debugging arithmetic
This commit is contained in:
parent
ae55d30961
commit
5b0d49cd76
10 changed files with 269 additions and 139 deletions
|
@ -61,13 +61,20 @@ namespace sat {
|
|||
m_steps_since_progress = 0;
|
||||
unsigned steps = 0;
|
||||
save_best_values();
|
||||
while (m_min_sz != 0 && m_steps_since_progress++ <= 1500000) {
|
||||
if (should_reinit_weights()) do_reinit_weights();
|
||||
else if (steps % 5000 == 0) shift_weights(), m_plugin->on_rescale();
|
||||
else if (should_restart()) do_restart(), m_plugin->on_restart();
|
||||
else if (do_flip<true>());
|
||||
else shift_weights(), m_plugin->on_rescale();
|
||||
++steps;
|
||||
try {
|
||||
while (m_min_sz != 0 && m_steps_since_progress++ <= 1500000) {
|
||||
if (should_reinit_weights()) do_reinit_weights();
|
||||
else if (steps % 5000 == 0) shift_weights(), m_plugin->on_rescale();
|
||||
else if (should_restart()) do_restart(), m_plugin->on_restart();
|
||||
else if (do_flip<true>());
|
||||
else shift_weights(), m_plugin->on_rescale();
|
||||
verbose_stream() << "steps: " << steps << " min_sz: " << m_min_sz << " unsat: " << m_unsat.size() << "\n";
|
||||
++steps;
|
||||
}
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
IF_VERBOSE(0, verbose_stream() << "Exception: " << ex.msg() << "\n");
|
||||
throw;
|
||||
}
|
||||
m_plugin->finish_search();
|
||||
}
|
||||
|
|
|
@ -214,19 +214,20 @@ namespace sls {
|
|||
// or flip on first non-negative score
|
||||
template<typename num_t>
|
||||
void arith_base<num_t>::repair(sat::literal lit, ineq const& ineq) {
|
||||
num_t new_value;
|
||||
num_t new_value, old_value;
|
||||
if (UINT_MAX == ineq.m_var_to_flip)
|
||||
dtt_reward(lit);
|
||||
auto v = ineq.m_var_to_flip;
|
||||
|
||||
if (v == UINT_MAX) {
|
||||
IF_VERBOSE(1, verbose_stream() << "no var to flip\n");
|
||||
IF_VERBOSE(0, verbose_stream() << "no var to flip\n");
|
||||
return;
|
||||
}
|
||||
// verbose_stream() << "var to flip " << v << "\n";
|
||||
if (!cm(ineq, v, new_value)) {
|
||||
IF_VERBOSE(1, verbose_stream() << "no critical move for " << v << "\n");
|
||||
IF_VERBOSE(0, verbose_stream() << "no critical move for " << v << "\n");
|
||||
return;
|
||||
}
|
||||
verbose_stream() << "repair " << lit << ": " << ineq << " var: v" << v << " := " << value(v) << " -> " << new_value << "\n";
|
||||
update(v, new_value);
|
||||
}
|
||||
|
||||
|
@ -331,9 +332,11 @@ namespace sls {
|
|||
template<typename num_t>
|
||||
void arith_base<num_t>::update(var_t v, num_t const& new_value) {
|
||||
auto& vi = m_vars[v];
|
||||
expr* e = vi.m_expr;
|
||||
auto old_value = vi.m_value;
|
||||
if (old_value == new_value)
|
||||
return;
|
||||
verbose_stream() << mk_bounded_pp(e, m) << " := " << new_value << "\n";
|
||||
for (auto const& [coeff, bv] : vi.m_bool_vars) {
|
||||
auto& ineq = *atom(bv);
|
||||
bool old_sign = sign(bv);
|
||||
|
@ -354,7 +357,8 @@ namespace sls {
|
|||
auto const& ad = m_adds[idx];
|
||||
ctx.new_value_eh(m_vars[ad.m_var].m_expr);
|
||||
}
|
||||
expr* e = vi.m_expr;
|
||||
|
||||
SASSERT(!m.is_value(e));
|
||||
ctx.new_value_eh(e);
|
||||
}
|
||||
|
||||
|
@ -374,7 +378,7 @@ namespace sls {
|
|||
template<>
|
||||
bool arith_base<checked_int64<true>>::is_num(expr* e, checked_int64<true>& i) {
|
||||
rational r;
|
||||
if (a.is_numeral(e, r)) {
|
||||
if (a.is_extended_numeral(e, r)) {
|
||||
if (!r.is_int64())
|
||||
throw overflow_exception();
|
||||
i = r.get_int64();
|
||||
|
@ -385,7 +389,7 @@ namespace sls {
|
|||
|
||||
template<>
|
||||
bool arith_base<rational>::is_num(expr* e, rational& i) {
|
||||
return a.is_numeral(e, i);
|
||||
return a.is_extended_numeral(e, i);
|
||||
}
|
||||
|
||||
template<typename num_t>
|
||||
|
@ -431,7 +435,7 @@ namespace sls {
|
|||
unsigned_vector m;
|
||||
num_t c = coeff;
|
||||
for (expr* arg : *to_app(e))
|
||||
if (is_num(x, i))
|
||||
if (is_num(arg, i))
|
||||
c *= i;
|
||||
else
|
||||
m.push_back(mk_term(arg));
|
||||
|
@ -620,16 +624,14 @@ namespace sls {
|
|||
}
|
||||
|
||||
template<typename num_t>
|
||||
void arith_base<num_t>::propagate_literal(sat::literal lit) {
|
||||
TRACE("sls", tout << "repair is-true: " << ctx.is_true(lit) << " lit: " << lit << "\n");
|
||||
void arith_base<num_t>::propagate_literal(sat::literal lit) {
|
||||
if (!ctx.is_true(lit))
|
||||
return;
|
||||
auto const* ineq = atom(lit.var());
|
||||
if (!ineq)
|
||||
return;
|
||||
TRACE("sls", tout << "repair lit: " << lit << " ineq-is-true: " << ineq->is_true() << "\n");
|
||||
return;
|
||||
if (ineq->is_true() != lit.sign())
|
||||
return;
|
||||
return;
|
||||
repair(lit, *ineq);
|
||||
}
|
||||
|
||||
|
@ -750,6 +752,9 @@ namespace sls {
|
|||
auto const& coeffs = ad.m_args;
|
||||
num_t sum(ad.m_coeff);
|
||||
num_t val = value(v);
|
||||
|
||||
verbose_stream() << mk_bounded_pp(m_vars[v].m_expr, m) << " := " << value(v) << "\n";
|
||||
|
||||
for (auto const& [c, w] : coeffs)
|
||||
sum += c * value(w);
|
||||
if (val == sum)
|
||||
|
@ -771,13 +776,14 @@ namespace sls {
|
|||
auto const& [v, coeff, monomial] = md;
|
||||
num_t product(coeff);
|
||||
num_t val = value(v);
|
||||
num_t new_value;
|
||||
for (auto v : monomial)
|
||||
product *= value(v);
|
||||
if (product == val)
|
||||
return;
|
||||
if (rand() % 20 == 0) {
|
||||
update(v, product);
|
||||
}
|
||||
verbose_stream() << "repair mul " << mk_bounded_pp(m_vars[v].m_expr, m) << " := " << val << "(" << product << ")\n";
|
||||
if (rand() % 20 == 0)
|
||||
update(v, product);
|
||||
else if (val == 0) {
|
||||
auto v = monomial[ctx.rand(monomial.size())];
|
||||
num_t zero(0);
|
||||
|
@ -801,28 +807,30 @@ namespace sls {
|
|||
// value1(v) * product / value(v) = val
|
||||
// value1(v) = value(v) * val / product
|
||||
auto w = monomial[ctx.rand(monomial.size())];
|
||||
auto old_value = value(w);
|
||||
num_t new_value;
|
||||
if (m_vars[w].m_sort == var_sort::REAL)
|
||||
new_value = old_value * val / product;
|
||||
else
|
||||
new_value = divide(w, old_value * val, product);
|
||||
auto old_value = value(w);
|
||||
new_value = divide(w, old_value * val, product);
|
||||
update(w, new_value);
|
||||
}
|
||||
else {
|
||||
product = coeff;
|
||||
auto w = monomial[ctx.rand(monomial.size())];
|
||||
num_t prod(coeff);
|
||||
for (auto v : monomial) {
|
||||
num_t new_value{ 1 };
|
||||
if (v == w)
|
||||
continue;
|
||||
num_t new_value(1);
|
||||
if (rand() % 2 == 0)
|
||||
new_value = -1;
|
||||
product *= new_value;
|
||||
prod *= new_value;
|
||||
update(v, new_value);
|
||||
}
|
||||
auto v = monomial[ctx.rand(monomial.size())];
|
||||
if ((product < 0 && 0 < val) || (val < 0 && 0 < product))
|
||||
update(v, -val * value(v));
|
||||
|
||||
verbose_stream() << "select random " << coeff << " " << val << " v" << w << "\n";
|
||||
new_value = divide(w, val * value(w), coeff);
|
||||
|
||||
if ((product < 0 && 0 < new_value) || (new_value < 0 && 0 < product))
|
||||
update(w, -new_value);
|
||||
else
|
||||
update(v, val * value(v));
|
||||
update(w, new_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1076,6 +1084,19 @@ namespace sls {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (sat)
|
||||
continue;
|
||||
verbose_stream() << clause << "\n";
|
||||
for (auto lit : clause.m_clause) {
|
||||
verbose_stream() << lit << " (" << ctx.is_true(lit) << ") ";
|
||||
auto ineq = atom(lit.var());
|
||||
if (!ineq)
|
||||
continue;
|
||||
verbose_stream() << *ineq << "\n";
|
||||
for (auto const& [coeff, v] : ineq->m_args)
|
||||
verbose_stream() << coeff << " " << v << " " << mk_bounded_pp(m_vars[v].m_expr, m) << " := " << value(v) << "\n";
|
||||
}
|
||||
exit(0);
|
||||
if (!sat)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,34 +21,35 @@ Author:
|
|||
|
||||
namespace sls {
|
||||
|
||||
#define WITH_FALLBACK(_fn_) \
|
||||
if (!m_arith) { \
|
||||
try {\
|
||||
return m_arith64->_fn_;\
|
||||
}\
|
||||
catch (overflow_exception&) {\
|
||||
init_backup();\
|
||||
}\
|
||||
}\
|
||||
return m_arith->_fn_; \
|
||||
|
||||
arith_plugin::arith_plugin(context& ctx) :
|
||||
plugin(ctx), m_shared(ctx.get_manager()) {
|
||||
m_arith64 = alloc(arith_base<checked_int64<true>>, ctx);
|
||||
m_fid = m_arith64->fid();
|
||||
init_backup();
|
||||
}
|
||||
|
||||
void arith_plugin::init_backup() {
|
||||
m_arith = alloc(arith_base<rational>, ctx);
|
||||
m_arith->initialize();
|
||||
}
|
||||
|
||||
void arith_plugin::register_term(expr* e) {
|
||||
if (!m_arith) {
|
||||
try {
|
||||
m_arith64->register_term(e);
|
||||
return;
|
||||
}
|
||||
catch (overflow_exception&) {
|
||||
init_backup();
|
||||
}
|
||||
}
|
||||
m_arith->register_term(e);
|
||||
WITH_FALLBACK(register_term(e));
|
||||
}
|
||||
|
||||
expr_ref arith_plugin::get_value(expr* e) {
|
||||
if (!m_arith) {
|
||||
try {
|
||||
return m_arith64->get_value(e);
|
||||
}
|
||||
catch (overflow_exception&) {
|
||||
init_backup();
|
||||
}
|
||||
}
|
||||
return m_arith->get_value(e);
|
||||
WITH_FALLBACK(get_value(e));
|
||||
}
|
||||
|
||||
void arith_plugin::initialize() {
|
||||
|
@ -59,28 +60,11 @@ namespace sls {
|
|||
}
|
||||
|
||||
void arith_plugin::propagate_literal(sat::literal lit) {
|
||||
if (!m_arith) {
|
||||
try {
|
||||
m_arith64->propagate_literal(lit);
|
||||
return;
|
||||
}
|
||||
catch (overflow_exception&) {
|
||||
init_backup();
|
||||
}
|
||||
}
|
||||
m_arith->propagate_literal(lit);
|
||||
WITH_FALLBACK(propagate_literal(lit));
|
||||
}
|
||||
|
||||
bool arith_plugin::propagate() {
|
||||
if (!m_arith) {
|
||||
try {
|
||||
return m_arith64->propagate();
|
||||
}
|
||||
catch (overflow_exception&) {
|
||||
init_backup();
|
||||
}
|
||||
}
|
||||
return m_arith->propagate();
|
||||
WITH_FALLBACK(propagate());
|
||||
}
|
||||
|
||||
bool arith_plugin::is_sat() {
|
||||
|
@ -119,29 +103,14 @@ namespace sls {
|
|||
}
|
||||
|
||||
void arith_plugin::repair_down(app* e) {
|
||||
if (m_arith)
|
||||
m_arith->repair_down(e);
|
||||
else
|
||||
m_arith64->repair_down(e);
|
||||
WITH_FALLBACK(repair_down(e));
|
||||
}
|
||||
|
||||
void arith_plugin::repair_up(app* e) {
|
||||
if (m_arith)
|
||||
m_arith->repair_up(e);
|
||||
else
|
||||
m_arith64->repair_up(e);
|
||||
WITH_FALLBACK(repair_up(e));
|
||||
}
|
||||
|
||||
void arith_plugin::set_value(expr* e, expr* v) {
|
||||
if (!m_arith) {
|
||||
try {
|
||||
m_arith64->set_value(e, v);
|
||||
return;
|
||||
}
|
||||
catch (overflow_exception&) {
|
||||
init_backup();
|
||||
}
|
||||
}
|
||||
m_arith->set_value(e, v);
|
||||
WITH_FALLBACK(set_value(e, v));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,7 @@ namespace sls {
|
|||
|
||||
void init_backup();
|
||||
public:
|
||||
arith_plugin(context& ctx) :
|
||||
plugin(ctx), m_shared(ctx.get_manager()) {
|
||||
m_arith64 = alloc(arith_base<checked_int64<true>>,ctx);
|
||||
m_fid = m_arith64->fid();
|
||||
}
|
||||
arith_plugin(context& ctx);
|
||||
~arith_plugin() override {}
|
||||
void register_term(expr* e) override;
|
||||
expr_ref get_value(expr* e) override;
|
||||
|
|
|
@ -17,6 +17,8 @@ Author:
|
|||
|
||||
#include "ast/sls/sls_basic_plugin.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
namespace sls {
|
||||
|
||||
|
@ -24,50 +26,76 @@ namespace sls {
|
|||
return expr_ref(m.mk_bool_val(bval0(e)), m);
|
||||
}
|
||||
|
||||
bool basic_plugin::is_basic(expr* e) const {
|
||||
if (!e || !is_app(e))
|
||||
return false;
|
||||
if (to_app(e)->get_family_id() != basic_family_id)
|
||||
return false;
|
||||
if (!m.is_bool(e))
|
||||
return false;
|
||||
expr* x, * y;
|
||||
if (m.is_eq(e, x, y) && !m.is_bool(x))
|
||||
return false;
|
||||
if (m.is_distinct(e) && !m.is_bool(to_app(e)->get_arg(0)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void basic_plugin::propagate_literal(sat::literal lit) {
|
||||
auto a = ctx.atom(lit.var());
|
||||
if (!a || !is_app(a))
|
||||
return;
|
||||
if (to_app(a)->get_family_id() != basic_family_id)
|
||||
if (!is_basic(a))
|
||||
return;
|
||||
if (bval1(to_app(a)) != bval0(to_app(a)))
|
||||
ctx.new_value_eh(a);
|
||||
}
|
||||
|
||||
void basic_plugin::register_term(expr* e) {
|
||||
if (is_app(e) && m.is_bool(e) && to_app(e)->get_family_id() == basic_family_id)
|
||||
if (is_basic(e))
|
||||
m_values.setx(e->get_id(), bval1(to_app(e)), false);
|
||||
}
|
||||
|
||||
void basic_plugin::initialize() {
|
||||
}
|
||||
|
||||
bool basic_plugin::propagate() {
|
||||
for (auto t : ctx.subterms())
|
||||
if (is_basic(t) && !m.is_not(t) &&
|
||||
bval0(t) != bval1(to_app(t))) {
|
||||
add_clause(to_app(t));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool basic_plugin::is_sat() {
|
||||
for (auto t : ctx.subterms())
|
||||
if (is_app(t) &&
|
||||
m.is_bool(t) &&
|
||||
to_app(t)->get_family_id() == basic_family_id &&
|
||||
bval0(t) != bval1(to_app(t)))
|
||||
return false;
|
||||
if (is_basic(t) && !m.is_not(t) &&
|
||||
bval0(t) != bval1(to_app(t))) {
|
||||
verbose_stream() << mk_bounded_pp(t, m) << " := " << (bval0(t) ? "T" : "F") << " eval: " << (bval1(to_app(t)) ? "T" : "F") << "\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& basic_plugin::display(std::ostream& out) const {
|
||||
for (auto t : ctx.subterms())
|
||||
if (is_app(t) && m.is_bool(t) && to_app(t)->get_family_id() == basic_family_id)
|
||||
if (is_basic(t))
|
||||
out << mk_bounded_pp(t, m) << " := " << (bval0(t)?"T":"F") << " eval: " << (bval1(to_app(t))?"T":"F") << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
void basic_plugin::set_value(expr* e, expr* v) {
|
||||
if (!m.is_bool(e))
|
||||
if (!is_basic(e))
|
||||
return;
|
||||
SASSERT(m.is_true(v) || m.is_false(v));
|
||||
set_value(e, m.is_true(v));
|
||||
}
|
||||
|
||||
bool basic_plugin::bval1(app* e) const {
|
||||
if (m.is_not(e))
|
||||
return bval1(to_app(e->get_arg(0)));
|
||||
SASSERT(m.is_bool(e));
|
||||
SASSERT(e->get_family_id() == basic_family_id);
|
||||
|
||||
|
@ -103,6 +131,7 @@ namespace sls {
|
|||
auto b = e->get_arg(1);
|
||||
if (m.is_bool(a))
|
||||
return bval0(a) == bval0(b);
|
||||
verbose_stream() << mk_bounded_pp(e, m) << " " << ctx.get_value(a) << " " << ctx.get_value(b) << "\n";
|
||||
return ctx.get_value(a) == ctx.get_value(b);
|
||||
}
|
||||
case OP_DISTINCT: {
|
||||
|
@ -123,11 +152,14 @@ namespace sls {
|
|||
|
||||
bool basic_plugin::bval0(expr* e) const {
|
||||
SASSERT(m.is_bool(e));
|
||||
bool b = true;
|
||||
while (m.is_not(e, e))
|
||||
b = !b;
|
||||
sat::bool_var v = ctx.atom2bool_var(e);
|
||||
if (v == sat::null_bool_var)
|
||||
return m_values.get(e->get_id(), false);
|
||||
return b == m_values.get(e->get_id(), false);
|
||||
else
|
||||
return ctx.is_true(v);
|
||||
return b == ctx.is_true(v);
|
||||
}
|
||||
|
||||
bool basic_plugin::try_repair(app* e, unsigned i) {
|
||||
|
@ -158,6 +190,56 @@ namespace sls {
|
|||
}
|
||||
}
|
||||
|
||||
void basic_plugin::add_clause(app* e) {
|
||||
expr_ref_vector es(m);
|
||||
expr_ref fml(m);
|
||||
expr* x, *y;
|
||||
switch (e->get_decl_kind()) {
|
||||
case OP_AND:
|
||||
for (expr* arg : *e) {
|
||||
ctx.add_constraint(m.mk_or(m.mk_not(e), arg));
|
||||
es.push_back(mk_not(m, arg));
|
||||
}
|
||||
es.push_back(e);
|
||||
ctx.add_constraint(m.mk_or(es));
|
||||
break;
|
||||
case OP_OR:
|
||||
for (expr* arg : *e) {
|
||||
ctx.add_constraint(m.mk_or(mk_not(m, arg), e));
|
||||
es.push_back(arg);
|
||||
}
|
||||
es.push_back(m.mk_not(e));
|
||||
ctx.add_constraint(m.mk_or(es));
|
||||
break;
|
||||
case OP_NOT:
|
||||
break;
|
||||
case OP_FALSE:
|
||||
break;
|
||||
case OP_TRUE:
|
||||
break;
|
||||
case OP_EQ:
|
||||
VERIFY(m.is_eq(e, x, y));
|
||||
ctx.add_constraint(m.mk_or(m.mk_not(e), mk_not(m, x), y));
|
||||
ctx.add_constraint(m.mk_or(m.mk_not(e), mk_not(m, y), x));
|
||||
ctx.add_constraint(m.mk_or(e, y, x));
|
||||
ctx.add_constraint(m.mk_or(e, mk_not(m, x), mk_not(m, y)));
|
||||
break;
|
||||
case OP_IMPLIES:
|
||||
NOT_IMPLEMENTED_YET();
|
||||
case OP_XOR:
|
||||
NOT_IMPLEMENTED_YET();
|
||||
case OP_ITE:
|
||||
NOT_IMPLEMENTED_YET();
|
||||
case OP_DISTINCT:
|
||||
NOT_IMPLEMENTED_YET();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool basic_plugin::try_repair_and_or(app* e, unsigned i) {
|
||||
auto b = bval0(e);
|
||||
if ((b && m.is_and(e)) || (!b && m.is_or(e))) {
|
||||
|
@ -245,7 +327,7 @@ namespace sls {
|
|||
}
|
||||
|
||||
void basic_plugin::repair_up(app* e) {
|
||||
if (!m.is_bool(e) || e->get_family_id() != basic_family_id)
|
||||
if (!is_basic(e))
|
||||
return;
|
||||
auto b = bval1(e);
|
||||
if (bval0(e) == b)
|
||||
|
@ -256,7 +338,7 @@ namespace sls {
|
|||
void basic_plugin::repair_down(app* e) {
|
||||
SASSERT(m.is_bool(e));
|
||||
unsigned n = e->get_num_args();
|
||||
if (n == 0 || e->get_family_id() != m.get_basic_family_id())
|
||||
if (n == 0 || !is_basic(e))
|
||||
return;
|
||||
|
||||
if (bval0(e) == bval1(e))
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace sls {
|
|||
class basic_plugin : public plugin {
|
||||
bool_vector m_values;
|
||||
bool m_initialized = false;
|
||||
|
||||
|
||||
bool is_basic(expr* e) const;
|
||||
bool bval1(app* e) const;
|
||||
bool bval0(expr* e) const;
|
||||
bool try_repair(app* e, unsigned i);
|
||||
|
@ -32,6 +33,8 @@ namespace sls {
|
|||
bool try_repair_distinct(app* e, unsigned i);
|
||||
bool set_value(expr* e, bool b);
|
||||
|
||||
void add_clause(app* e);
|
||||
|
||||
public:
|
||||
basic_plugin(context& ctx) :
|
||||
plugin(ctx) {
|
||||
|
@ -42,7 +45,7 @@ namespace sls {
|
|||
expr_ref get_value(expr* e) override;
|
||||
void initialize() override;
|
||||
void propagate_literal(sat::literal lit) override;
|
||||
bool propagate() override { return false; }
|
||||
bool propagate() override;
|
||||
void repair_down(app* e) override;
|
||||
void repair_up(app* e) override;
|
||||
bool is_sat() override;
|
||||
|
|
|
@ -59,15 +59,19 @@ namespace sls {
|
|||
// Use timestamps to make it incremental.
|
||||
//
|
||||
init();
|
||||
verbose_stream() << "check " << unsat().size() << "\n";
|
||||
while (unsat().empty()) {
|
||||
|
||||
propagate_boolean_assignment();
|
||||
|
||||
verbose_stream() << "propagate " << unsat().size() << " " << m_new_constraint << "\n";
|
||||
// display(verbose_stream());
|
||||
|
||||
if (m_new_constraint || !unsat().empty())
|
||||
return l_undef;
|
||||
|
||||
verbose_stream() << unsat().size() << " " << m_new_constraint << "\n";
|
||||
|
||||
if (all_of(m_plugins, [&](auto* p) { return !p || p->is_sat(); })) {
|
||||
model_ref mdl = alloc(model, m);
|
||||
for (expr* e : subterms())
|
||||
|
@ -97,8 +101,8 @@ namespace sls {
|
|||
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);
|
||||
// verbose_stream() << "repair down " << mk_bounded_pp(e, m) << "\n";
|
||||
expr* e = term(id);
|
||||
TRACE("sls", tout << "repair down " << mk_bounded_pp(e, m) << "\n");
|
||||
if (is_app(e)) {
|
||||
auto p = m_plugins.get(to_app(e)->get_family_id(), nullptr);
|
||||
if (p)
|
||||
|
@ -108,7 +112,7 @@ namespace sls {
|
|||
while (!m_repair_up.empty() && !m_new_constraint) {
|
||||
auto id = m_repair_up.erase_min();
|
||||
expr* e = term(id);
|
||||
// verbose_stream() << "repair up " << mk_bounded_pp(e, m) << "\n";
|
||||
TRACE("sls", tout << "repair up " << mk_bounded_pp(e, m) << "\n");
|
||||
if (is_app(e)) {
|
||||
auto p = m_plugins.get(to_app(e)->get_family_id(), nullptr);
|
||||
if (p)
|
||||
|
|
|
@ -108,32 +108,73 @@ namespace sls {
|
|||
// send clauses to ddfw
|
||||
// send expression mapping to m_solver_ctx
|
||||
|
||||
sat::literal_vector clause;
|
||||
for (auto f : m_assertions) {
|
||||
if (m.is_or(f)) {
|
||||
clause.reset();
|
||||
for (auto arg : *to_app(f))
|
||||
clause.push_back(mk_literal(arg));
|
||||
m_solver_ctx->add_clause(clause.size(), clause.data());
|
||||
}
|
||||
else {
|
||||
sat::literal lit = mk_literal(f);
|
||||
m_solver_ctx->add_clause(1, &lit);
|
||||
}
|
||||
}
|
||||
for (auto f : m_assertions)
|
||||
add_clause(f);
|
||||
|
||||
IF_VERBOSE(10, m_solver_ctx->display(verbose_stream()));
|
||||
return m_ddfw.check(0, nullptr);
|
||||
}
|
||||
|
||||
sat::literal smt_solver::mk_literal(expr* e) {
|
||||
bool neg = m.is_not(e, e);
|
||||
sat::bool_var v;
|
||||
if (!m_expr2var.find(e, v)) {
|
||||
v = m_expr2var.size();
|
||||
m_expr2var.insert(e, v);
|
||||
m_solver_ctx->register_atom(v, e);
|
||||
void smt_solver::add_clause(expr* f) {
|
||||
sat::literal_vector clause;
|
||||
if (m.is_or(f)) {
|
||||
clause.reset();
|
||||
for (auto arg : *to_app(f))
|
||||
clause.push_back(mk_literal(arg));
|
||||
m_solver_ctx->add_clause(clause.size(), clause.data());
|
||||
}
|
||||
return sat::literal(v, neg);
|
||||
else if (m.is_and(f)) {
|
||||
for (auto arg : *to_app(f))
|
||||
add_clause(arg);
|
||||
}
|
||||
else {
|
||||
sat::literal lit = mk_literal(f);
|
||||
m_solver_ctx->add_clause(1, &lit);
|
||||
}
|
||||
}
|
||||
|
||||
sat::literal smt_solver::mk_literal(expr* e) {
|
||||
sat::literal lit;
|
||||
bool neg = false;
|
||||
while (m.is_not(e,e))
|
||||
neg = !neg;
|
||||
if (m_expr2lit.find(e, lit))
|
||||
return neg ? ~lit : lit;
|
||||
sat::literal_vector clause;
|
||||
if (m.is_and(e)) {
|
||||
lit = mk_literal();
|
||||
for (expr* arg : *to_app(e)) {
|
||||
auto lit2 = mk_literal(arg);
|
||||
clause.push_back(~lit2);
|
||||
sat::literal lits[2] = { ~lit, lit2 };
|
||||
m_solver_ctx->add_clause(2, lits);
|
||||
}
|
||||
clause.push_back(lit);
|
||||
m_solver_ctx->add_clause(clause.size(), clause.data());
|
||||
}
|
||||
else if (m.is_or(e)) {
|
||||
lit = mk_literal();
|
||||
for (expr* arg : *to_app(e)) {
|
||||
auto lit2 = mk_literal(arg);
|
||||
clause.push_back(lit2);
|
||||
sat::literal lits[2] = { lit, ~lit2 };
|
||||
m_solver_ctx->add_clause(2, lits);
|
||||
}
|
||||
clause.push_back(~lit);
|
||||
m_solver_ctx->add_clause(clause.size(), clause.data());
|
||||
}
|
||||
else {
|
||||
sat::bool_var v = m_num_vars++;
|
||||
lit = sat::literal(v, false);
|
||||
m_solver_ctx->register_atom(lit.var(), e);
|
||||
}
|
||||
m_expr2lit.insert(e, lit);
|
||||
return neg ? ~lit : lit;
|
||||
}
|
||||
|
||||
sat::literal smt_solver::mk_literal() {
|
||||
sat::bool_var v = m_num_vars++;
|
||||
return sat::literal(v, false);
|
||||
}
|
||||
|
||||
model_ref smt_solver::get_model() {
|
||||
|
|
|
@ -29,9 +29,12 @@ namespace sls {
|
|||
solver_ctx* m_solver_ctx = nullptr;
|
||||
expr_ref_vector m_assertions;
|
||||
statistics m_st;
|
||||
obj_map<expr, sat::bool_var> m_expr2var;
|
||||
obj_map<expr, sat::literal> m_expr2lit;
|
||||
unsigned m_num_vars = 0;
|
||||
|
||||
sat::literal mk_literal(expr* e);
|
||||
sat::literal mk_literal();
|
||||
void add_clause(expr* f);
|
||||
public:
|
||||
smt_solver(ast_manager& m, params_ref const& p);
|
||||
~smt_solver();
|
||||
|
|
|
@ -32,6 +32,10 @@ namespace sat {
|
|||
void add(literal lit) { ++m_num_trues; m_trues += lit.index(); }
|
||||
void del(literal lit) { SASSERT(m_num_trues > 0); --m_num_trues; m_trues -= lit.index(); }
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, clause_info const& ci) {
|
||||
return out << ci.m_clause << " w: " << ci.m_weight << " nt: " << ci.m_num_trues;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue