mirror of
https://github.com/Z3Prover/z3
synced 2025-08-02 01:13:18 +00:00
add EUF plugin framework.
plugin setting allows adding equality saturation within the E-graph propagation without involving externalizing theory solver dispatch. It makes equality saturation independent of SAT integration. Add a special relation operator to support ad-hoc AC symbols.
This commit is contained in:
parent
5784c2da79
commit
b52fd8d954
28 changed files with 3063 additions and 68 deletions
|
@ -29,8 +29,10 @@ Notes:
|
|||
#include "util/statistics.h"
|
||||
#include "util/trail.h"
|
||||
#include "util/lbool.h"
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "ast/euf/euf_enode.h"
|
||||
#include "ast/euf/euf_etable.h"
|
||||
#include "ast/euf/euf_plugin.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include <vector>
|
||||
|
||||
|
@ -82,14 +84,18 @@ namespace euf {
|
|||
|
||||
class egraph {
|
||||
|
||||
friend class plugin;
|
||||
|
||||
typedef ptr_vector<trail> trail_stack;
|
||||
|
||||
enum to_merge_t { to_merge_plain, to_merge_comm, to_add_literal };
|
||||
enum to_merge_t { to_merge_plain, to_merge_comm, to_justified, to_add_literal };
|
||||
struct to_merge {
|
||||
enode* a, * b;
|
||||
to_merge_t t;
|
||||
justification j;
|
||||
bool commutativity() const { return t == to_merge_comm; }
|
||||
to_merge(enode* a, enode* b, bool c) : a(a), b(b), t(c ? to_merge_comm : to_merge_plain) {}
|
||||
to_merge(enode* a, enode* b, justification j): a(a), b(b), t(to_justified), j(j) {}
|
||||
to_merge(enode* p, enode* ante): a(p), b(ante), t(to_add_literal) {}
|
||||
};
|
||||
|
||||
|
@ -116,10 +122,12 @@ namespace euf {
|
|||
struct lbl_set {};
|
||||
struct update_children {};
|
||||
struct set_relevant {};
|
||||
struct plugin_undo {};
|
||||
enum class tag_t { is_set_parent, is_add_node, is_toggle_cgc, is_toggle_merge_tf, is_update_children,
|
||||
is_add_th_var, is_replace_th_var, is_new_th_eq,
|
||||
is_lbl_hash, is_new_th_eq_qhead,
|
||||
is_inconsistent, is_value_assignment, is_lbl_set, is_set_relevant };
|
||||
is_inconsistent, is_value_assignment, is_lbl_set, is_set_relevant,
|
||||
is_plugin_undo };
|
||||
tag_t tag;
|
||||
enode* r1;
|
||||
enode* n1;
|
||||
|
@ -162,11 +170,14 @@ namespace euf {
|
|||
tag(tag_t::is_update_children), r1(n), n1(nullptr), r2_num_parents(UINT_MAX) {}
|
||||
update_record(enode* n, set_relevant) :
|
||||
tag(tag_t::is_set_relevant), r1(n), n1(nullptr), r2_num_parents(UINT_MAX) {}
|
||||
update_record(unsigned th_id, plugin_undo) :
|
||||
tag(tag_t::is_plugin_undo), r1(nullptr), n1(nullptr), m_th_id(th_id) {}
|
||||
};
|
||||
ast_manager& m;
|
||||
svector<to_merge> m_to_merge;
|
||||
etable m_table;
|
||||
region m_region;
|
||||
scoped_ptr_vector<plugin> m_plugins;
|
||||
svector<update_record> m_updates;
|
||||
unsigned_vector m_scopes;
|
||||
enode_vector m_expr2enode;
|
||||
|
@ -205,6 +216,12 @@ namespace euf {
|
|||
}
|
||||
void push_node(enode* n) { m_updates.push_back(update_record(n)); }
|
||||
|
||||
// plugin related methods
|
||||
void push_plugin_undo(unsigned th_id) { m_updates.push_back(update_record(th_id, update_record::plugin_undo())); }
|
||||
void push_merge(enode* a, enode* b, justification j) { m_to_merge.push_back({ a, b, j }); }
|
||||
void push_merge(enode* a, enode* b, bool comm) { m_to_merge.push_back({ a, b, comm }); }
|
||||
void propagate_plugins();
|
||||
|
||||
void add_th_eq(theory_id id, theory_var v1, theory_var v2, enode* c, enode* r);
|
||||
|
||||
void add_th_diseqs(theory_id id, theory_var v1, enode* r);
|
||||
|
@ -245,11 +262,15 @@ namespace euf {
|
|||
public:
|
||||
egraph(ast_manager& m);
|
||||
~egraph();
|
||||
|
||||
void add_plugin(plugin* p);
|
||||
plugin* get_plugin(family_id fid) const { return m_plugins.get(fid, nullptr); }
|
||||
|
||||
enode* find(expr* f) const { return m_expr2enode.get(f->get_id(), nullptr); }
|
||||
enode* find(expr* f, unsigned n, enode* const* args);
|
||||
enode* mk(expr* f, unsigned generation, unsigned n, enode *const* args);
|
||||
enode_vector const& enodes_of(func_decl* f);
|
||||
void push() { if (!m_to_merge.empty()) propagate(); ++m_num_scopes; }
|
||||
void push() { if (can_propagate()) propagate(); ++m_num_scopes; }
|
||||
void pop(unsigned num_scopes);
|
||||
|
||||
/**
|
||||
|
@ -269,6 +290,7 @@ namespace euf {
|
|||
of new equalities.
|
||||
*/
|
||||
bool propagate();
|
||||
bool can_propagate() const { return !m_to_merge.empty(); }
|
||||
bool inconsistent() const { return m_inconsistent; }
|
||||
|
||||
/**
|
||||
|
@ -286,7 +308,7 @@ namespace euf {
|
|||
where \c n is an enode and \c is_eq indicates whether the enode
|
||||
is an equality consequence.
|
||||
*/
|
||||
void add_th_diseq(theory_id id, theory_var v1, theory_var v2, expr* eq);
|
||||
void add_th_diseq(theory_id id, theory_var v1, theory_var v2, enode* eq);
|
||||
bool has_th_eq() const { return m_new_th_eqs_qhead < m_new_th_eqs.size(); }
|
||||
th_eq get_th_eq() const { return m_new_th_eqs[m_new_th_eqs_qhead]; }
|
||||
void next_th_eq() { force_push(); SASSERT(m_new_th_eqs_qhead < m_new_th_eqs.size()); m_new_th_eqs_qhead++; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue