3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-14 04:41:48 +00:00

sls fixes for ABV. Axiomatization required as saturation can produce conflicts by congruence closure

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2025-01-27 15:16:04 -08:00
parent 2050fc3b35
commit fe1622b592
4 changed files with 110 additions and 40 deletions

View file

@ -22,6 +22,8 @@ Author:
namespace sls {
class euf_plugin;
class array_plugin : public plugin {
struct select_args {
euf::enode* sel = nullptr;
@ -29,15 +31,15 @@ namespace sls {
select_args() {}
};
struct select_args_hash {
unsigned operator()(select_args const& a) const {
unsigned operator()(select_args const& a) const {
unsigned h = 0;
for (unsigned i = 1; i < a.sel->num_args(); ++i)
h ^= a.sel->get_arg(i)->get_root()->hash();
h ^= a.sel->get_arg(i)->get_root()->hash();
return h;
};
};
struct select_args_eq {
bool operator()(select_args const& a, select_args const& b) const {
bool operator()(select_args const& a, select_args const& b) const {
SASSERT(a.sel->num_args() == b.sel->num_args());
for (unsigned i = 1; i < a.sel->num_args(); ++i)
if (a.sel->get_arg(i)->get_root() != b.sel->get_arg(i)->get_root())
@ -47,12 +49,37 @@ namespace sls {
};
typedef map<select_args, euf::enode*, select_args_hash, select_args_eq> select2value;
typedef obj_map<euf::enode, select2value> kv;
struct stats {
unsigned m_num_conflicts = 0;
unsigned m_num_axioms = 0;
void reset() { memset(this, 0, sizeof(*this)); }
};
euf_plugin& euf;
array_util a;
scoped_ptr<euf::egraph> m_g;
scoped_ptr<kv> m_kv;
bool m_add_conflicts = true;
bool m_has_arrays = false;
scoped_ptr<kv> m_kv;
bool m_add_conflicts = true;
bool m_has_arrays = false;
stats m_stats;
enum axiom_t { store_axiom1, store_axiom2_down, store_axiom2_up, map_axiom, const_axiom };
struct axiom_instance {
axiom_t t;
euf::enode* sto; euf::enode* sel;
};
svector<axiom_instance> m_delayed_axioms;
unsigned store_axiom1_index(euf::enode* n) { m_delayed_axioms.push_back({ store_axiom1, n, nullptr }); return m_delayed_axioms.size() - 1; }
unsigned store_axiom2_down_index(euf::enode* sto, euf::enode* sel) { m_delayed_axioms.push_back({ store_axiom2_down, sto, sel }); return m_delayed_axioms.size() - 1; }
unsigned store_axiom2_up_index(euf::enode* sto, euf::enode* sel) { m_delayed_axioms.push_back({ store_axiom2_up, sto, sel }); return m_delayed_axioms.size() - 1; }
unsigned map_axiom_index(euf::enode* sto, euf::enode* sel) { m_delayed_axioms.push_back({ map_axiom, sto, sel }); return m_delayed_axioms.size() - 1; }
unsigned const_axiom_index(euf::enode* val, euf::enode* sel) { m_delayed_axioms.push_back({ const_axiom, val, sel }); return m_delayed_axioms.size() - 1; }
void add_eq_axiom(euf::enode* x, euf::enode* y) {
++m_stats.m_num_axioms;
expr_ref eq(m.mk_eq(x->get_expr(), y->get_expr()), m);
ctx.add_theory_axiom(eq);
}
void init_egraph(euf::egraph& g);
void init_kv(euf::egraph& g, kv& kv);
@ -73,10 +100,14 @@ namespace sls {
void resolve_conflict();
size_t* to_ptr(sat::literal l) { return reinterpret_cast<size_t*>((size_t)(l.index() << 4)); };
size_t* to_ptr(expr* t) { return reinterpret_cast<size_t*>((reinterpret_cast<size_t>(t) << 4) + 1); }
bool is_literal(size_t* p) { return (reinterpret_cast<size_t>(p) & 1) == 0; }
size_t* to_ptr(euf::enode* t) { return reinterpret_cast<size_t*>((reinterpret_cast<size_t>(t) << 4) + 1); }
size_t* to_ptr(unsigned n) { return reinterpret_cast<size_t*>((size_t)(n << 4) + 3); }
bool is_literal(size_t* p) { return (reinterpret_cast<size_t>(p) & 3) == 0; }
bool is_index(size_t* p) { return (reinterpret_cast<size_t>(p) & 3) == 3; }
bool is_enode(size_t* p) { return (reinterpret_cast<size_t>(p) & 3) == 1; }
sat::literal to_literal(size_t* p) { return sat::to_literal(static_cast<unsigned>(reinterpret_cast<size_t>(p) >> 4)); };
expr* to_expr(size_t* p) { return reinterpret_cast<expr*>(reinterpret_cast<size_t>(p) >> 4); }
euf::enode* to_enode(size_t* p) { return reinterpret_cast<euf::enode*>(reinterpret_cast<size_t>(p) >> 4); }
unsigned to_index(size_t* p) { return static_cast<unsigned>(reinterpret_cast<size_t>(p) >> 4); }
public:
array_plugin(context& ctx);
@ -95,8 +126,8 @@ namespace sls {
void on_restart() override {}
std::ostream& display(std::ostream& out) const override;
bool set_value(expr* e, expr* v) override { return false; }
void collect_statistics(statistics& st) const override {}
void reset_statistics() override {}
void collect_statistics(statistics& st) const override;
void reset_statistics() override { m_stats.reset(); }
};
}