3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-02 09:20:22 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-08-24 01:55:13 -07:00
parent 96587bf708
commit 65e6d942ac
23 changed files with 1338 additions and 39 deletions

109
src/ast/euf/euf_egraph.h Normal file
View file

@ -0,0 +1,109 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_egraph.h
Abstract:
E-graph layer
Author:
Nikolaj Bjorner (nbjorner) 2020-08-23
Notes:
It relies on
- data structures form the (legacy) SMT solver.
- it still uses eager path compression.
- delayed congruence table reconstruction from egg.
- it does not deduplicate parents.
--*/
#pragma once
#include "ast/euf/euf_enode.h"
#include "ast/euf/euf_etable.h"
namespace euf {
struct add_eq_record {
enode* r1;
enode* n1;
unsigned r2_num_parents;
add_eq_record(enode* r1, enode* n1, unsigned r2_num_parents):
r1(r1), n1(n1), r2_num_parents(r2_num_parents) {}
};
class egraph {
struct scope {
bool m_inconsistent;
unsigned m_num_eqs;
unsigned m_num_nodes;
};
ast_manager& m;
region m_region;
enode_vector m_worklist;
etable m_table;
svector<add_eq_record> m_eqs;
svector<scope> m_scopes;
enode_vector m_expr2enode;
enode_vector m_nodes;
expr_ref_vector m_exprs;
unsigned m_num_scopes { 0 };
bool m_inconsistent { false };
enode *m_n1 { nullptr };
enode *m_n2 { nullptr };
justification m_justification;
enode_vector m_new_eqs;
enode_vector m_todo;
void push_eq(enode* r1, enode* n1, unsigned r2_num_parents) {
m_eqs.push_back(add_eq_record(r1, n1, r2_num_parents));
}
void undo_eq(enode* r1, enode* n1, unsigned r2_num_parents);
enode* mk_enode(expr* f, enode * const* args);
void reinsert(enode* n);
void force_push();
void set_conflict(enode* n1, enode* n2, justification j);
void merge(enode* n1, enode* n2, justification j);
void merge_justification(enode* n1, enode* n2, justification j);
void unmerge_justification(enode* n1);
void dedup_equalities();
bool is_equality(enode* n) const;
void reinsert_equality(enode* p);
void update_children(enode* n);
public:
egraph(ast_manager& m): m(m), m_table(m), m_exprs(m) {}
enode* find(expr* f) { return m_expr2enode.get(f->get_id(), nullptr); }
enode* mk(expr* f, enode *const* args);
void push() { ++m_num_scopes; }
void pop(unsigned num_scopes);
/**
\brief merge nodes, all effects are deferred to the propagation step.
*/
void merge(enode* n1, enode* n2, void* reason) { merge(n1, n2, justification::external(reason)); }
/**
\brief propagate set of merges.
This call may detect an inconsistency. Then inconsistent() is true.
Use then explain() to extract an explanation for the conflict.
It may also infer new implied equalities, when the roots of the
equated nodes are merged. Use then new_eqs() to extract the vector
of new equalities.
*/
void propagate();
bool inconsistent() const { return m_inconsistent; }
enode_vector const& new_eqs() const { return m_new_eqs; }
template <typename T>
void explain(ptr_vector<T>& justifications);
void invariant();
std::ostream& display(std::ostream& out) const;
};
inline std::ostream& operator<<(std::ostream& out, egraph const& g) { return g.display(out); }
}