diff --git a/src/ast/sls/CMakeLists.txt b/src/ast/sls/CMakeLists.txt index 3306ea216..35f936e01 100644 --- a/src/ast/sls/CMakeLists.txt +++ b/src/ast/sls/CMakeLists.txt @@ -9,9 +9,9 @@ z3_add_component(ast_sls sls_arith_plugin.cpp sls_basic_plugin.cpp sls_bv_plugin.cpp - sls_cc.cpp sls_context.cpp sls_engine.cpp + sls_euf_plugin.cpp sls_smt_solver.cpp sls_valuation.cpp COMPONENT_DEPENDENCIES diff --git a/src/ast/sls/bv_sls_eval.cpp b/src/ast/sls/bv_sls_eval.cpp index 4abd4beab..e1350b6a0 100644 --- a/src/ast/sls/bv_sls_eval.cpp +++ b/src/ast/sls/bv_sls_eval.cpp @@ -590,7 +590,7 @@ namespace bv { rw(v); rational r; VERIFY(bv.is_numeral(v, r)); - val.set_value(m_tmp, r); + val.set_value(val.eval, r); break; } case OP_BREDAND: @@ -630,14 +630,18 @@ namespace bv { digit_t sls_eval::random_bits() { return sls_valuation::random_bits(m_rand); } - + bool sls_eval::repair_down(app* e, unsigned i) { if (e->get_family_id() == bv.get_family_id() && try_repair_bv(e, i)) { + commit_eval(to_app(e->get_arg(i))); ctx.new_value_eh(e->get_arg(i)); - if (eval_is_correct(e)) - commit_eval(e); - else - ctx.new_value_eh(e); // re-queue repair + if (bv.is_bv(e)) { + auto& val = eval(e); + if (val.eval != val.bits()) { + commit_eval(e); + ctx.new_value_eh(e); + } + } return true; } return false; @@ -648,45 +652,45 @@ namespace bv { case OP_BAND: SASSERT(e->get_num_args() >= 2); if (e->get_num_args() == 2) - return try_repair_band(eval_value(e), wval(e, i), wval(e, 1 - i)); + return try_repair_band(assign_value(e), wval(e, i), wval(e, 1 - i)); else return try_repair_band(e, i); case OP_BOR: SASSERT(e->get_num_args() >= 2); if (e->get_num_args() == 2) - return try_repair_bor(eval_value(e), wval(e, i), wval(e, 1 - i)); + return try_repair_bor(assign_value(e), wval(e, i), wval(e, 1 - i)); else return try_repair_bor(e, i); case OP_BXOR: SASSERT(e->get_num_args() >= 2); if (e->get_num_args() == 2) - return try_repair_bxor(eval_value(e), wval(e, i), wval(e, 1 - i)); + return try_repair_bxor(assign_value(e), wval(e, i), wval(e, 1 - i)); else return try_repair_bxor(e, i); case OP_BADD: SASSERT(e->get_num_args() >= 2); if (e->get_num_args() == 2) - return try_repair_add(eval_value(e), wval(e, i), wval(e, 1 - i)); + return try_repair_add(assign_value(e), wval(e, i), wval(e, 1 - i)); else return try_repair_add(e, i); case OP_BSUB: - return try_repair_sub(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_sub(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_BMUL: SASSERT(e->get_num_args() >= 2); if (e->get_num_args() == 2) - return try_repair_mul(eval_value(e), wval(e, i), eval_value(to_app(e->get_arg(1 - i)))); + return try_repair_mul(assign_value(e), wval(e, i), assign_value(to_app(e->get_arg(1 - i)))); else { auto const& a = wval(e, 0); auto f = [&](bvect& out, bvval const& c) { a.set_mul(out, out, c.bits()); }; fold_oper(m_mul_tmp, e, i, f); - return try_repair_mul(eval_value(e), wval(e, i), m_mul_tmp); + return try_repair_mul(assign_value(e), wval(e, i), m_mul_tmp); } case OP_BNOT: - return try_repair_bnot(eval_value(e), wval(e, i)); + return try_repair_bnot(assign_value(e), wval(e, i)); case OP_BNEG: - return try_repair_bneg(eval_value(e), wval(e, i)); + return try_repair_bneg(assign_value(e), wval(e, i)); case OP_BIT0: return false; case OP_BIT1: @@ -694,7 +698,7 @@ namespace bv { case OP_BV2INT: return false; case OP_INT2BV: - return try_repair_int2bv(eval_value(e), e->get_arg(0)); + return try_repair_int2bv(assign_value(e), e->get_arg(0)); case OP_ULEQ: if (i == 0) return try_repair_ule(bval0(e), wval(e, i), wval(e, 1 - i)); @@ -736,11 +740,11 @@ namespace bv { else return try_repair_sle(!bval0(e), wval(e, i), wval(e, 1 - i)); case OP_BASHR: - return try_repair_ashr(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_ashr(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_BLSHR: - return try_repair_lshr(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_lshr(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_BSHL: - return try_repair_shl(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_shl(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_BIT2BOOL: { unsigned idx; expr* arg; @@ -751,37 +755,37 @@ namespace bv { case OP_BUDIV: case OP_BUDIV_I: case OP_BUDIV0: - return try_repair_udiv(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_udiv(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_BUREM: case OP_BUREM_I: case OP_BUREM0: - return try_repair_urem(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_urem(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_ROTATE_LEFT: - return try_repair_rotate_left(eval_value(e), wval(e, 0), e->get_parameter(0).get_int()); + return try_repair_rotate_left(assign_value(e), wval(e, 0), e->get_parameter(0).get_int()); case OP_ROTATE_RIGHT: - return try_repair_rotate_left(eval_value(e), wval(e, 0), wval(e).bw - e->get_parameter(0).get_int()); + return try_repair_rotate_left(assign_value(e), wval(e, 0), wval(e).bw - e->get_parameter(0).get_int()); case OP_EXT_ROTATE_LEFT: - return try_repair_rotate_left(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_rotate_left(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_EXT_ROTATE_RIGHT: - return try_repair_rotate_right(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_rotate_right(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_ZERO_EXT: - return try_repair_zero_ext(eval_value(e), wval(e, 0)); + return try_repair_zero_ext(assign_value(e), wval(e, 0)); case OP_SIGN_EXT: - return try_repair_sign_ext(eval_value(e), wval(e, 0)); + return try_repair_sign_ext(assign_value(e), wval(e, 0)); case OP_CONCAT: - return try_repair_concat(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_concat(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_EXTRACT: { unsigned hi, lo; expr* arg; VERIFY(bv.is_extract(e, lo, hi, arg)); - return try_repair_extract(eval_value(e), wval(arg), lo); + return try_repair_extract(assign_value(e), wval(arg), lo); } case OP_BUMUL_NO_OVFL: return try_repair_umul_ovfl(!bval0(e), wval(e, 0), wval(e, 1), i); case OP_BUMUL_OVFL: return try_repair_umul_ovfl(bval0(e), wval(e, 0), wval(e, 1), i); case OP_BCOMP: - return try_repair_comp(eval_value(e), wval(e, 0), wval(e, 1), i); + return try_repair_comp(assign_value(e), wval(e, 0), wval(e, 1), i); case OP_BUADD_OVFL: case OP_BNAND: @@ -887,7 +891,7 @@ namespace bv { } bool sls_eval::try_repair_band(app* t, unsigned i) { - bvect const& e = eval_value(t); + bvect const& e = assign_value(t); auto f = [&](bvect& out, bvval const& c) { for (unsigned j = 0; j < c.nw; ++j) out[j] &= c.bits()[j]; @@ -913,7 +917,7 @@ namespace bv { } bool sls_eval::try_repair_bor(app* t, unsigned i) { - bvect const& e = eval_value(t); + bvect const& e = assign_value(t); auto f = [&](bvect& out, bvval const& c) { for (unsigned j = 0; j < c.nw; ++j) out[j] |= c.bits()[j]; @@ -935,7 +939,7 @@ namespace bv { bool sls_eval::try_repair_bxor(app* t, unsigned i) { - bvect const& e = eval_value(t); + bvect const& e = assign_value(t); auto f = [&](bvect& out, bvval const& c) { for (unsigned j = 0; j < c.nw; ++j) out[j] ^= c.bits()[j]; @@ -965,7 +969,7 @@ namespace bv { bool sls_eval::try_repair_add(app* t, unsigned i) { bvval& a = wval(t, i); - bvect const& e = eval_value(t); + bvect const& e = assign_value(t); if (m_rand(20) != 0) { auto f = [&](bvect& out, bvval const& c) { a.set_add(m_tmp2, m_tmp2, c.bits()); @@ -1827,11 +1831,9 @@ namespace bv { } 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"; + rational r = e.get_value(e.nw); + arith_util a(m); + expr_ref intval(a.mk_int(r), m); ctx.set_value(arg, intval); return true; } @@ -1906,8 +1908,8 @@ namespace bv { return false; if (m.is_bool(e)) return bval0(e) == bval1(e); - if (bv.is_bv(e)) { - auto const& v = wval(e); + if (bv.is_bv(e)) { + auto const& v = eval(e); return v.eval == v.bits(); } UNREACHABLE(); diff --git a/src/ast/sls/bv_sls_eval.h b/src/ast/sls/bv_sls_eval.h index 02b4104fa..de1a1cb56 100644 --- a/src/ast/sls/bv_sls_eval.h +++ b/src/ast/sls/bv_sls_eval.h @@ -123,7 +123,7 @@ namespace bv { void eval(app* e, sls_valuation& val) const; - bvect const& eval_value(app* e) const { return wval(e).eval; } + bvect const& assign_value(app* e) const { return wval(e).bits(); } bool bval0(expr* e) const { return ctx.is_true(e); } diff --git a/src/ast/sls/sls_arith_base.cpp b/src/ast/sls/sls_arith_base.cpp index 383c63b8f..7285bd89b 100644 --- a/src/ast/sls/sls_arith_base.cpp +++ b/src/ast/sls/sls_arith_base.cpp @@ -558,7 +558,7 @@ namespace sls { if (m_bool_vars.get(bv, nullptr)) return; 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) return; expr* x, * y; @@ -1048,7 +1048,7 @@ namespace sls { num_t n; if (!is_num(v, n)) return; - verbose_stream() << "set value " << w << " " << mk_bounded_pp(e, m) << " " << n << " " << value(w) << "\n"; + // verbose_stream() << "set value " << w << " " << mk_bounded_pp(e, m) << " " << n << " " << value(w) << "\n"; if (n == value(w)) return; update(w, n); diff --git a/src/ast/sls/sls_basic_plugin.cpp b/src/ast/sls/sls_basic_plugin.cpp index 7e571637e..d98ea2652 100644 --- a/src/ast/sls/sls_basic_plugin.cpp +++ b/src/ast/sls/sls_basic_plugin.cpp @@ -56,7 +56,7 @@ namespace sls { 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) - out << mk_bounded_pp(t, m) << " " << bval0(t) << " ~ " << bval1(to_app(t)) << "\n"; + out << mk_bounded_pp(t, m) << " := " << (bval0(t)?"T":"F") << " eval: " << (bval1(to_app(t))?"T":"F") << "\n"; return out; } diff --git a/src/ast/sls/sls_bv_plugin.cpp b/src/ast/sls/sls_bv_plugin.cpp index 25c5eea30..8e5fd94a8 100644 --- a/src/ast/sls/sls_bv_plugin.cpp +++ b/src/ast/sls/sls_bv_plugin.cpp @@ -16,6 +16,7 @@ Author: --*/ #include "ast/sls/sls_bv_plugin.h" #include "ast/ast_ll_pp.h" +#include "ast/ast_pp.h" namespace sls { @@ -124,7 +125,7 @@ namespace sls { return; } } - IF_VERBOSE(3, verbose_stream() << "revert repair: " << mk_bounded_pp(e, m) << "\n"); + IF_VERBOSE(0, verbose_stream() << "revert repair: " << mk_bounded_pp(e, m) << "\n"); repair_up(e); } diff --git a/src/ast/sls/sls_context.cpp b/src/ast/sls/sls_context.cpp index 0270c18a5..11e5f2e2a 100644 --- a/src/ast/sls/sls_context.cpp +++ b/src/ast/sls/sls_context.cpp @@ -14,10 +14,9 @@ Author: Nikolaj Bjorner (nbjorner) 2024-06-24 --*/ -#pragma once #include "ast/sls/sls_context.h" -#include "ast/sls/sls_cc.h" +#include "ast/sls/sls_euf_plugin.h" #include "ast/sls/sls_arith_plugin.h" #include "ast/sls/sls_bv_plugin.h" #include "ast/sls/sls_basic_plugin.h" @@ -36,7 +35,7 @@ namespace sls { 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(euf_plugin, *this)); register_plugin(alloc(arith_plugin, *this)); register_plugin(alloc(bv_plugin, *this)); register_plugin(alloc(basic_plugin, *this)); @@ -64,6 +63,8 @@ namespace sls { propagate_boolean_assignment(); + // display(verbose_stream()); + if (m_new_constraint || !unsat().empty()) return l_undef; @@ -96,7 +97,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); + expr* e = term(id); + // verbose_stream() << "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) @@ -106,6 +108,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"; if (is_app(e)) { auto p = m_plugins.get(to_app(e)->get_family_id(), nullptr); if (p) @@ -205,8 +208,8 @@ 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_terms(e); register_atom(v, e); + register_terms(e); } return v; } @@ -271,11 +274,14 @@ namespace sls { } } ); + // verbose_stream() << "new value " << mk_bounded_pp(e, m) << " " << mk_bounded_pp(get_value(e), m) << "\n"; m_repair_down.reserve(e->get_id() + 1); - m_repair_down.insert(e->get_id()); + if (!m_repair_down.contains(e->get_id())) + 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()); + if (!m_repair_up.contains(p->get_id())) + m_repair_up.insert(p->get_id()); } } diff --git a/src/ast/sls/sls_cc.cpp b/src/ast/sls/sls_euf_plugin.cpp similarity index 77% rename from src/ast/sls/sls_cc.cpp rename to src/ast/sls/sls_euf_plugin.cpp index 609e0bb29..61e2d747b 100644 --- a/src/ast/sls/sls_cc.cpp +++ b/src/ast/sls/sls_euf_plugin.cpp @@ -3,7 +3,7 @@ Copyright (c) 2024 Microsoft Corporation Module Name: - sls_cc.cpp + sls_euf_plugin.cpp Abstract: @@ -15,27 +15,27 @@ Author: --*/ -#include "ast/sls/sls_cc.h" +#include "ast/sls/sls_euf_plugin.h" #include "ast/ast_ll_pp.h" #include "ast/ast_pp.h" namespace sls { - cc_plugin::cc_plugin(context& c): + euf_plugin::euf_plugin(context& c): plugin(c), m_values(8U, value_hash(*this), value_eq(*this)) { m_fid = m.mk_family_id("cc"); } - cc_plugin::~cc_plugin() {} + euf_plugin::~euf_plugin() {} - expr_ref cc_plugin::get_value(expr* e) { + expr_ref euf_plugin::get_value(expr* e) { UNREACHABLE(); return expr_ref(m); } - void cc_plugin::register_term(expr* e) { + void euf_plugin::register_term(expr* e) { if (!is_app(e)) return; if (!is_uninterp(e)) @@ -49,14 +49,14 @@ namespace sls { m_app[f].push_back(a); } - unsigned cc_plugin::value_hash::operator()(app* t) const { + unsigned euf_plugin::value_hash::operator()(app* t) const { unsigned r = 0; for (auto arg : *t) r *= 3, r += cc.ctx.get_value(arg)->hash(); return r; } - bool cc_plugin::value_eq::operator()(app* a, app* b) const { + bool euf_plugin::value_eq::operator()(app* a, app* b) const { SASSERT(a->get_num_args() == b->get_num_args()); for (unsigned i = a->get_num_args(); i-- > 0; ) if (cc.ctx.get_value(a->get_arg(i)) != cc.ctx.get_value(b->get_arg(i))) @@ -64,7 +64,7 @@ namespace sls { return true; } - bool cc_plugin::is_sat() { + bool euf_plugin::is_sat() { for (auto& [f, ts] : m_app) { if (ts.size() <= 1) continue; @@ -84,7 +84,7 @@ namespace sls { return true; } - bool cc_plugin::propagate() { + bool euf_plugin::propagate() { bool new_constraint = false; for (auto & [f, ts] : m_app) { if (ts.size() <= 1) @@ -101,6 +101,12 @@ namespace sls { for (unsigned i = t->get_num_args(); i-- > 0; ) ors.push_back(m.mk_not(m.mk_eq(t->get_arg(i), u->get_arg(i)))); ors.push_back(m.mk_eq(t, u)); +#if 0 + verbose_stream() << "conflict: " << mk_bounded_pp(t, m) << " != " << mk_bounded_pp(u, m) << "\n"; + verbose_stream() << "value " << ctx.get_value(t) << " != " << ctx.get_value(u) << "\n"; + for (unsigned i = t->get_num_args(); i-- > 0; ) + verbose_stream() << ctx.get_value(t->get_arg(i)) << " == " << ctx.get_value(u->get_arg(i)) << "\n"; +#endif ctx.add_constraint(m.mk_or(ors)); new_constraint = true; } @@ -111,7 +117,7 @@ namespace sls { return new_constraint; } - std::ostream& cc_plugin::display(std::ostream& out) const { + std::ostream& euf_plugin::display(std::ostream& out) const { for (auto& [f, ts] : m_app) { for (auto* t : ts) out << mk_bounded_pp(t, m) << "\n"; @@ -120,7 +126,7 @@ namespace sls { return out; } - void cc_plugin::mk_model(model& mdl) { + void euf_plugin::mk_model(model& mdl) { expr_ref_vector args(m); for (auto& [f, ts] : m_app) { func_interp* fi = alloc(func_interp, m, f->get_arity()); diff --git a/src/ast/sls/sls_cc.h b/src/ast/sls/sls_euf_plugin.h similarity index 80% rename from src/ast/sls/sls_cc.h rename to src/ast/sls/sls_euf_plugin.h index dd2f82829..60504212f 100644 --- a/src/ast/sls/sls_cc.h +++ b/src/ast/sls/sls_euf_plugin.h @@ -3,7 +3,7 @@ Copyright (c) 2024 Microsoft Corporation Module Name: - cc_sls.h + sls_euf_plugin.h Abstract: @@ -21,22 +21,22 @@ Author: namespace sls { - class cc_plugin : public plugin { + class euf_plugin : public plugin { obj_map> m_app; struct value_hash { - cc_plugin& cc; - value_hash(cc_plugin& cc) : cc(cc) {} + euf_plugin& cc; + value_hash(euf_plugin& cc) : cc(cc) {} unsigned operator()(app* t) const; }; struct value_eq { - cc_plugin& cc; - value_eq(cc_plugin& cc) : cc(cc) {} + euf_plugin& cc; + value_eq(euf_plugin& cc) : cc(cc) {} bool operator()(app* a, app* b) const; }; hashtable m_values; public: - cc_plugin(context& c); - ~cc_plugin() override; + euf_plugin(context& c); + ~euf_plugin() override; family_id fid() { return m_fid; } expr_ref get_value(expr* e) override; void initialize() override {} diff --git a/src/ast/sls/sls_smt_solver.cpp b/src/ast/sls/sls_smt_solver.cpp index bd79245e8..88ec5dc00 100644 --- a/src/ast/sls/sls_smt_solver.cpp +++ b/src/ast/sls/sls_smt_solver.cpp @@ -51,6 +51,7 @@ namespace sls { m_context.check(); if (!m_new_clause_added) break; + TRACE("sls", display(tout)); m_ddfw.reinit(); m_new_clause_added = false; }