mirror of
https://github.com/Z3Prover/z3
synced 2025-06-05 21:53:23 +00:00
wip: term_graph::project and term_graph::solve
This commit is contained in:
parent
7714d05c1a
commit
771d3b1349
2 changed files with 136 additions and 41 deletions
|
@ -22,6 +22,7 @@ Notes:
|
||||||
#include "ast/ast_pp.h"
|
#include "ast/ast_pp.h"
|
||||||
#include "ast/ast_util.h"
|
#include "ast/ast_util.h"
|
||||||
#include "ast/for_each_expr.h"
|
#include "ast/for_each_expr.h"
|
||||||
|
#include "ast/occurs.h"
|
||||||
#include "qe/qe_term_graph.h"
|
#include "qe/qe_term_graph.h"
|
||||||
|
|
||||||
namespace qe {
|
namespace qe {
|
||||||
|
@ -630,7 +631,9 @@ namespace qe {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref_vector term_graph::project(func_decl_ref_vector const& decls, bool exclude) {
|
void term_graph::project_core(func_decl_ref_vector const& decls,
|
||||||
|
bool exclude,
|
||||||
|
expr_ref_vector &result) {
|
||||||
u_map<bool> _decls;
|
u_map<bool> _decls;
|
||||||
for (func_decl* f : decls) _decls.insert(f->get_id(), true);
|
for (func_decl* f : decls) _decls.insert(f->get_id(), true);
|
||||||
// - propagate representatives up over parents.
|
// - propagate representatives up over parents.
|
||||||
|
@ -639,10 +642,6 @@ namespace qe {
|
||||||
// - produce other literals over represented classes
|
// - produce other literals over represented classes
|
||||||
// (walk disequalities in m_lits and represent lhs/rhs over decls or excluding decls)
|
// (walk disequalities in m_lits and represent lhs/rhs over decls or excluding decls)
|
||||||
|
|
||||||
expr_ref_vector result(m);
|
|
||||||
m_term2app.reset();
|
|
||||||
m_pinned.reset();
|
|
||||||
|
|
||||||
obj_hashtable<expr> eqs;
|
obj_hashtable<expr> eqs;
|
||||||
expr_ref eq(m);
|
expr_ref eq(m);
|
||||||
ptr_vector<term> worklist;
|
ptr_vector<term> worklist;
|
||||||
|
@ -682,6 +681,9 @@ namespace qe {
|
||||||
}
|
}
|
||||||
bool update_rep = false;
|
bool update_rep = false;
|
||||||
|
|
||||||
|
// AG: can rep be null at this point?
|
||||||
|
// AG: why mk_pure(root) is guaranteed to return non-null?
|
||||||
|
|
||||||
// Add equations between pure and rep,
|
// Add equations between pure and rep,
|
||||||
// optionally swap the roles of rep and pure if
|
// optionally swap the roles of rep and pure if
|
||||||
// pure makes a better representative.
|
// pure makes a better representative.
|
||||||
|
@ -709,19 +711,107 @@ namespace qe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Here we could also walk equivalence classes that contain interpreted values by sort and
|
||||||
|
// extract disequalities bewteen non-unique value representatives.
|
||||||
|
// these disequalities are implied and can be mined using other means, such as
|
||||||
|
// theory aware core minimization
|
||||||
|
reset_marks();
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref_vector term_graph::project(func_decl_ref_vector const& decls, bool exclude) {
|
||||||
|
expr_ref_vector result(m);
|
||||||
|
m_term2app.reset();
|
||||||
|
m_pinned.reset();
|
||||||
|
project_core(decls, exclude, result);
|
||||||
// walk other predicates than equalities
|
// walk other predicates than equalities
|
||||||
for (expr* e : m_lits) {
|
for (expr* e : m_lits) {
|
||||||
if (!m.is_eq(e) && m_term2app.find(get_term(e)->get_root().get_id(), e)) {
|
if (!m.is_eq(e) && m_term2app.find(get_term(e)->get_root().get_id(), e)) {
|
||||||
result.push_back(e);
|
result.push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Here we could also walk equivalence classes that contain interpreted values by sort and
|
|
||||||
// extract disequalities bewteen non-unique value representatives.
|
|
||||||
// these disequalities are implied and can be mined using other means, such as
|
|
||||||
// theory aware core minimization
|
|
||||||
m_term2app.reset();
|
m_term2app.reset();
|
||||||
m_pinned.reset();
|
m_pinned.reset();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool term_graph::is_solved_eq(expr *_lhs, expr* _rhs) {
|
||||||
|
if (!is_app(_lhs) || !is_app(_rhs)) return false;
|
||||||
|
app *lhs, *rhs;
|
||||||
|
lhs = ::to_app(_lhs);
|
||||||
|
rhs = ::to_app(_rhs);
|
||||||
|
|
||||||
|
if (rhs->get_num_args() > 0) return false;
|
||||||
|
if (rhs->get_family_id() != null_family_id) return false;
|
||||||
|
|
||||||
|
return !occurs(rhs, lhs);
|
||||||
|
}
|
||||||
|
void term_graph::solve_core(func_decl_ref_vector const &decls, bool exclude,
|
||||||
|
expr_ref_vector &result) {
|
||||||
|
u_map<bool> _decls;
|
||||||
|
for (func_decl* f : decls) _decls.insert(f->get_id(), true);
|
||||||
|
obj_hashtable<expr> eqs;
|
||||||
|
expr_ref eq(m);
|
||||||
|
ptr_vector<term> worklist;
|
||||||
|
for (term * t : m_terms) {
|
||||||
|
worklist.push_back(t);
|
||||||
|
t->set_mark(true);
|
||||||
|
}
|
||||||
|
while (!worklist.empty()) {
|
||||||
|
term* t = worklist.back();
|
||||||
|
worklist.pop_back();
|
||||||
|
t->set_mark(false);
|
||||||
|
if (m_term2app.contains(t->get_id()))
|
||||||
|
continue;
|
||||||
|
term &root = t->get_root();
|
||||||
|
bool has_rep = m_term2app.contains(root.get_id());
|
||||||
|
expr *pure = mk_pure(*t);
|
||||||
|
if (!pure) continue;
|
||||||
|
|
||||||
|
if (has_rep) {
|
||||||
|
// add equality if needed
|
||||||
|
expr* rep = m_term2app.find(root.get_id());
|
||||||
|
if (exclude != _decls.contains(t->get_decl_id()) || !is_solved_eq(rep, pure)) {
|
||||||
|
eq = m.mk_eq(rep, pure);
|
||||||
|
if (!eqs.contains(eq)) {
|
||||||
|
eqs.insert(eq);
|
||||||
|
result.push_back(eq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// let pure be the representative
|
||||||
|
m_term2app.insert(root.get_id(), pure);
|
||||||
|
// schedule parents of root to be processed again
|
||||||
|
for (term * p : term::parents(root)) {
|
||||||
|
if (!p->is_marked()) {
|
||||||
|
p->set_mark(true);
|
||||||
|
worklist.push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SASSERT(false);
|
||||||
|
// TBD: deal with root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reset_marks();
|
reset_marks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
expr_ref_vector term_graph::solve(func_decl_ref_vector const &decls, bool exclude) {
|
||||||
|
expr_ref_vector result(m);
|
||||||
|
m_term2app.reset();
|
||||||
|
m_pinned.reset();
|
||||||
|
project_core(decls, exclude, result);
|
||||||
|
solve_core(decls, exclude, result);
|
||||||
|
// walk other predicates than equalities
|
||||||
|
for (expr* e : m_lits) {
|
||||||
|
if (!m.is_eq(e) && m_term2app.find(get_term(e)->get_root().get_id(), e)) {
|
||||||
|
result.push_back(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_term2app.reset();
|
||||||
|
m_pinned.reset();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,9 @@ namespace qe {
|
||||||
void mk_equalities(term const &t, expr_ref_vector &out);
|
void mk_equalities(term const &t, expr_ref_vector &out);
|
||||||
void mk_all_equalities(term const &t, expr_ref_vector &out);
|
void mk_all_equalities(term const &t, expr_ref_vector &out);
|
||||||
void display(std::ostream &out);
|
void display(std::ostream &out);
|
||||||
|
void project_core(func_decl_ref_vector const &decls, bool exclude, expr_ref_vector &result);
|
||||||
|
void solve_core(func_decl_ref_vector const &decls, bool exclude, expr_ref_vector &result);
|
||||||
|
bool is_solved_eq(expr *lhs, expr *rhs);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
term_graph(ast_manager &m);
|
term_graph(ast_manager &m);
|
||||||
|
@ -100,6 +103,8 @@ namespace qe {
|
||||||
* vocabulary of decls (if exclude is true).
|
* vocabulary of decls (if exclude is true).
|
||||||
*/
|
*/
|
||||||
expr_ref_vector project(func_decl_ref_vector const& decls, bool exclude);
|
expr_ref_vector project(func_decl_ref_vector const& decls, bool exclude);
|
||||||
|
expr_ref_vector solve(func_decl_ref_vector const& decls, bool exclude);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue