mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
be4bc6caed
26 changed files with 309 additions and 111 deletions
|
@ -129,7 +129,7 @@ namespace euf {
|
|||
return n;
|
||||
}
|
||||
|
||||
egraph::egraph(ast_manager& m) : m(m), m_table(m), m_tmp_app(2), m_exprs(m) {
|
||||
egraph::egraph(ast_manager& m) : m(m), m_table(m), m_tmp_app(2), m_exprs(m), m_eq_decls(m) {
|
||||
m_tmp_eq = enode::mk_tmp(m_region, 2);
|
||||
}
|
||||
|
||||
|
@ -592,7 +592,7 @@ namespace euf {
|
|||
SASSERT(!n1->get_root()->m_target);
|
||||
}
|
||||
|
||||
bool egraph::are_diseq(enode* a, enode* b) const {
|
||||
bool egraph::are_diseq(enode* a, enode* b) {
|
||||
enode* ra = a->get_root(), * rb = b->get_root();
|
||||
if (ra == rb)
|
||||
return false;
|
||||
|
@ -600,12 +600,7 @@ namespace euf {
|
|||
return true;
|
||||
if (ra->get_sort() != rb->get_sort())
|
||||
return true;
|
||||
expr_ref eq(m.mk_eq(a->get_expr(), b->get_expr()), m);
|
||||
m_tmp_eq->m_args[0] = a;
|
||||
m_tmp_eq->m_args[1] = b;
|
||||
m_tmp_eq->m_expr = eq;
|
||||
SASSERT(m_tmp_eq->num_args() == 2);
|
||||
enode* r = m_table.find(m_tmp_eq);
|
||||
enode* r = tmp_eq(ra, rb);
|
||||
if (r && r->get_root()->value() == l_false)
|
||||
return true;
|
||||
return false;
|
||||
|
@ -617,6 +612,18 @@ namespace euf {
|
|||
return find(m_tmp_app.get_app(), num_args, args);
|
||||
}
|
||||
|
||||
enode* egraph::tmp_eq(enode* a, enode* b) {
|
||||
SASSERT(a->is_root());
|
||||
SASSERT(b->is_root());
|
||||
if (a->num_parents() > b->num_parents())
|
||||
std::swap(a, b);
|
||||
for (enode* p : enode_parents(a))
|
||||
if (p->is_equality() &&
|
||||
(b == p->get_arg(0)->get_root() || b == p->get_arg(1)->get_root()))
|
||||
return p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief generate an explanation for a congruence.
|
||||
Each pair of children under a congruence have the same roots
|
||||
|
@ -714,12 +721,7 @@ namespace euf {
|
|||
explain_eq(justifications, b, rb);
|
||||
return sat::null_bool_var;
|
||||
}
|
||||
expr_ref eq(m.mk_eq(a->get_expr(), b->get_expr()), m);
|
||||
m_tmp_eq->m_args[0] = a;
|
||||
m_tmp_eq->m_args[1] = b;
|
||||
m_tmp_eq->m_expr = eq;
|
||||
SASSERT(m_tmp_eq->num_args() == 2);
|
||||
enode* r = m_table.find(m_tmp_eq);
|
||||
enode* r = tmp_eq(ra, rb);
|
||||
SASSERT(r && r->get_root()->value() == l_false);
|
||||
explain_eq(justifications, r, r->get_root());
|
||||
return r->get_root()->bool_var();
|
||||
|
@ -818,9 +820,13 @@ namespace euf {
|
|||
args.push_back(old_expr2new_enode[n1->get_arg(j)->get_expr_id()]);
|
||||
expr* e2 = tr(e1);
|
||||
enode* n2 = mk(e2, n1->generation(), args.size(), args.data());
|
||||
|
||||
old_expr2new_enode.setx(e1->get_id(), n2, nullptr);
|
||||
n2->set_value(n2->value());
|
||||
n2->set_value(n1->value());
|
||||
n2->m_bool_var = n1->m_bool_var;
|
||||
n2->m_commutative = n1->m_commutative;
|
||||
n2->m_merge_enabled = n1->m_merge_enabled;
|
||||
n2->m_is_equality = n1->m_is_equality;
|
||||
}
|
||||
for (unsigned i = 0; i < src.m_nodes.size(); ++i) {
|
||||
enode* n1 = src.m_nodes[i];
|
||||
|
|
|
@ -165,6 +165,7 @@ namespace euf {
|
|||
tmp_app m_tmp_app;
|
||||
enode_vector m_nodes;
|
||||
expr_ref_vector m_exprs;
|
||||
func_decl_ref_vector m_eq_decls;
|
||||
vector<enode_vector> m_decl2enodes;
|
||||
enode_vector m_empty_enodes;
|
||||
unsigned m_num_scopes = 0;
|
||||
|
@ -263,10 +264,12 @@ namespace euf {
|
|||
/**
|
||||
* \brief check if two nodes are known to be disequal.
|
||||
*/
|
||||
bool are_diseq(enode* a, enode* b) const;
|
||||
bool are_diseq(enode* a, enode* b);
|
||||
|
||||
enode* get_enode_eq_to(func_decl* f, unsigned num_args, enode* const* args);
|
||||
|
||||
enode* tmp_eq(enode* a, enode* b);
|
||||
|
||||
/**
|
||||
\brief Maintain and update cursor into propagated consequences.
|
||||
The result of get_literal() is a pair (n, is_eq)
|
||||
|
|
|
@ -55,17 +55,17 @@ namespace euf {
|
|||
unsigned m_table_id = UINT_MAX;
|
||||
unsigned m_generation = 0; // Tracks how many quantifier instantiation rounds were needed to generate this enode.
|
||||
enode_vector m_parents;
|
||||
enode* m_next = nullptr;
|
||||
enode* m_root = nullptr;
|
||||
enode* m_target = nullptr;
|
||||
enode* m_cg = nullptr;
|
||||
enode* m_next = nullptr;
|
||||
enode* m_root = nullptr;
|
||||
enode* m_target = nullptr;
|
||||
enode* m_cg = nullptr;
|
||||
th_var_list m_th_vars;
|
||||
justification m_justification;
|
||||
unsigned m_num_args = 0;
|
||||
signed char m_lbl_hash = -1; // It is different from -1, if enode is used in a pattern
|
||||
approx_set m_lbls;
|
||||
approx_set m_plbls;
|
||||
enode* m_args[0];
|
||||
signed char m_lbl_hash = -1; // It is different from -1, if enode is used in a pattern
|
||||
approx_set m_lbls;
|
||||
approx_set m_plbls;
|
||||
enode* m_args[0];
|
||||
|
||||
friend class enode_args;
|
||||
friend class enode_parents;
|
||||
|
|
|
@ -18,9 +18,10 @@ Revision History:
|
|||
--*/
|
||||
#include "ast/ast.h"
|
||||
#include "ast/expr_delta_pair.h"
|
||||
#include "ast/has_free_vars.h"
|
||||
#include "util/hashtable.h"
|
||||
|
||||
class contains_vars {
|
||||
class contains_vars::imp {
|
||||
typedef hashtable<expr_delta_pair, obj_hash<expr_delta_pair>, default_eq<expr_delta_pair> > cache;
|
||||
cache m_cache;
|
||||
svector<expr_delta_pair> m_todo;
|
||||
|
@ -86,6 +87,18 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
contains_vars::contains_vars() {
|
||||
m_imp = alloc(imp);
|
||||
}
|
||||
|
||||
contains_vars::~contains_vars() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
bool contains_vars::operator()(expr* e) {
|
||||
return (*m_imp)(e);
|
||||
}
|
||||
|
||||
bool has_free_vars(expr * n) {
|
||||
contains_vars p;
|
||||
return p(n);
|
||||
|
|
|
@ -20,6 +20,15 @@ Revision History:
|
|||
|
||||
class expr;
|
||||
|
||||
class contains_vars {
|
||||
class imp;
|
||||
imp* m_imp;
|
||||
public:
|
||||
contains_vars();
|
||||
~contains_vars();
|
||||
bool operator()(expr* n);
|
||||
};
|
||||
|
||||
bool has_free_vars(expr * n);
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
struct pull_quant::imp {
|
||||
|
||||
|
@ -50,7 +51,7 @@ struct pull_quant::imp {
|
|||
quantifier * q = to_quantifier(child);
|
||||
expr * body = q->get_expr();
|
||||
quantifier_kind k = q->get_kind() == forall_k ? exists_k : forall_k;
|
||||
result = m.update_quantifier(q, k, m.mk_not(body));
|
||||
result = m.update_quantifier(q, k, mk_not(m, body));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -78,9 +79,8 @@ struct pull_quant::imp {
|
|||
qid = nested_q->get_qid();
|
||||
}
|
||||
w = std::min(w, nested_q->get_weight());
|
||||
unsigned j = nested_q->get_num_decls();
|
||||
while (j > 0) {
|
||||
--j;
|
||||
|
||||
for (unsigned j = nested_q->get_num_decls(); j-- > 0; ) {
|
||||
var_sorts.push_back(nested_q->get_decl_sort(j));
|
||||
symbol s = nested_q->get_decl_name(j);
|
||||
if (std::find(var_names.begin(), var_names.end(), s) != var_names.end())
|
||||
|
@ -254,6 +254,10 @@ struct pull_quant::imp {
|
|||
}
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
if (m.is_not(f) && m.is_not(args[0])) {
|
||||
result = to_app(args[0])->get_arg(0);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
if (!m.is_or(f) && !m.is_and(f) && !m.is_not(f))
|
||||
return BR_FAILED;
|
||||
|
||||
|
@ -275,7 +279,7 @@ struct pull_quant::imp {
|
|||
proof_ref & result_pr) {
|
||||
|
||||
if (is_exists(old_q)) {
|
||||
result = m.mk_not(new_body);
|
||||
result = mk_not(m, new_body);
|
||||
result = m.mk_not(m.update_quantifier(old_q, forall_k, result));
|
||||
if (m.proofs_enabled())
|
||||
m.mk_rewrite(old_q, result);
|
||||
|
|
|
@ -905,6 +905,24 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
expr* t1, *t2;
|
||||
// (ite c (not (= t1 t2)) t1) ==> (not (= t1 (and c t2)))
|
||||
if (m().is_not(t, t1) && m().is_eq(t1, t1, t2) && e == t1) {
|
||||
expr_ref a(m());
|
||||
mk_and(c, t2, a);
|
||||
result = m().mk_not(m().mk_eq(t1, a));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_not(t, t1) && m().is_eq(t1, t2, t1) && e == t1) {
|
||||
expr_ref a(m());
|
||||
mk_and(c, t2, a);
|
||||
result = m().mk_eq(t1, a);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (m().is_ite(t) && m_ite_extra_rules && m_elim_ite) {
|
||||
// (ite c1 (ite c2 t1 t2) t1) ==> (ite (and c1 (not c2)) t2 t1)
|
||||
if (e == to_app(t)->get_arg(1)) {
|
||||
|
@ -923,6 +941,7 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
return BR_REWRITE1;
|
||||
}
|
||||
|
||||
|
||||
if (m().is_ite(e)) {
|
||||
// (ite c1 (ite c2 t1 t2) (ite c3 t1 t2)) ==> (ite (or (and c1 c2) (and (not c1) c3)) t1 t2)
|
||||
if (to_app(t)->get_arg(1) == to_app(e)->get_arg(1) &&
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue