3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

moved obj_equiv_class to ast

This commit is contained in:
Arie Gurfinkel 2017-08-01 14:17:27 -04:00
parent 4d07fa5db3
commit 88a35119b9
12 changed files with 164 additions and 128 deletions

View file

@ -1,250 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
obj_equiv_class.h
Abstract:
"Equivalence class structure" for objs. Uses a union_find structure internally.
Operations are :
-Declare a new equivalence class with a single element
-Merge two equivalence classes
-Retrieve whether two elements are in the same equivalence class
-Iterate on all the elements of the equivalence class of a given element
-Iterate on all equivalence classes (and then within them)
Author:
Julien Braine
Revision History:
*/
#ifndef OBJ_EQUIV_CLASS_H_
#define OBJ_EQUIV_CLASS_H_
#include "util/union_find.h"
#include "ast/ast_util.h"
namespace spacer {
//All functions naturally add their parameters to the union_find class
template<typename OBJ, typename Manager>
class obj_equiv_class {
basic_union_find m_uf;
obj_map<OBJ, unsigned> m_to_int;
ref_vector<OBJ, Manager> m_to_obj;
unsigned add_elem_impl(OBJ*o) {
unsigned id = m_to_obj.size();
m_to_int.insert(o, id);
m_to_obj.push_back(o);
return id;
}
unsigned add_if_not_there(OBJ*o) {
unsigned id;
if(!m_to_int.find(o, id)) {
id = add_elem_impl(o);
}
return id;
}
public:
class iterator;
class equiv_iterator;
friend class iterator;
friend class equiv_iterator;
obj_equiv_class(Manager& m) : m_to_obj(m) {}
void add_elem(OBJ*o) {
SASSERT(!m_to_int.find(o));
add_elem_impl(o);
}
//Invalidates all iterators
void merge(OBJ* a, OBJ* b) {
unsigned v1 = add_if_not_there(a);
unsigned v2 = add_if_not_there(b);
unsigned tmp1 = m_uf.find(v1);
unsigned tmp2 = m_uf.find(v2);
m_uf.merge(tmp1, tmp2);
}
void reset() {
m_uf.reset();
m_to_int.reset();
m_to_obj.reset();
}
bool are_equiv(OBJ*a, OBJ*b) {
unsigned id1 = add_if_not_there(a);
unsigned id2 = add_if_not_there(b);
return m_uf.find(id1) == m_uf.find(id2);
}
class iterator {
friend class obj_equiv_class;
private :
const obj_equiv_class& m_ouf;
unsigned m_curr_id;
bool m_first;
iterator(const obj_equiv_class& uf, unsigned id, bool f) :
m_ouf(uf), m_curr_id(id), m_first(f) {}
public :
OBJ*operator*() {return m_ouf.m_to_obj[m_curr_id];}
iterator& operator++() {
m_curr_id = m_ouf.m_uf.next(m_curr_id);
m_first = false;
return *this;
}
bool operator==(const iterator& o) {
SASSERT(&m_ouf == &o.m_ouf);
return m_first == o.m_first && m_curr_id == o.m_curr_id;
}
bool operator!=(const iterator& o) {return !(*this == o);}
};
iterator begin(OBJ*o) {
unsigned id = add_if_not_there(o);
return iterator(*this, id, true);
}
iterator end(OBJ*o) {
unsigned id = add_if_not_there(o);
return iterator(*this, id, false);
}
class eq_class {
private :
iterator m_begin;
iterator m_end;
public :
eq_class(const iterator& a, const iterator& b) : m_begin(a), m_end(b) {}
iterator begin() {return m_begin;}
iterator end() {return m_end;}
};
class equiv_iterator {
friend class obj_equiv_class;
private :
const obj_equiv_class& m_ouf;
unsigned m_rootnb;
equiv_iterator(const obj_equiv_class& uf, unsigned nb) :
m_ouf(uf), m_rootnb(nb) {
while(m_rootnb != m_ouf.m_to_obj.size() &&
m_ouf.m_uf.is_root(m_rootnb) != true)
{ m_rootnb++; }
}
public :
eq_class operator*() {
return eq_class(iterator(m_ouf, m_rootnb, true),
iterator(m_ouf, m_rootnb, false));
}
equiv_iterator& operator++() {
do {
m_rootnb++;
} while(m_rootnb != m_ouf.m_to_obj.size() &&
m_ouf.m_uf.is_root(m_rootnb) != true);
return *this;
}
bool operator==(const equiv_iterator& o) {
SASSERT(&m_ouf == &o.m_ouf);
return m_rootnb == o.m_rootnb;
}
bool operator!=(const equiv_iterator& o) {return !(*this == o);}
};
equiv_iterator begin() {return equiv_iterator(*this, 0);}
equiv_iterator end() {return equiv_iterator(*this, m_to_obj.size());}
};
typedef obj_equiv_class<expr, ast_manager> expr_equiv_class;
/**
Factors input vector v into equivalence classes and the rest
*/
inline void factor_eqs(expr_ref_vector &v, expr_equiv_class &equiv) {
ast_manager &m = v.get_manager();
arith_util arith(m);
expr *e1, *e2;
flatten_and(v);
unsigned j = 0;
for (unsigned i = 0; i < v.size(); ++i) {
if (m.is_eq(v.get(i), e1, e2)) {
if (arith.is_zero(e1)) {
expr* t;
t = e1; e1 = e2; e2 = t;
}
// y + -1*x == 0
if (arith.is_zero(e2) && arith.is_add(e1) &&
to_app(e1)->get_num_args() == 2) {
expr *a0, *a1, *x;
a0 = to_app(e1)->get_arg(0);
a1 = to_app(e1)->get_arg(1);
if (arith.is_times_minus_one(a1, x)) {
e1 = a0;
e2 = x;
}
else if (arith.is_times_minus_one(a0, x)) {
e1 = a1;
e2 = x;
}
}
equiv.merge(e1, e2);
}
else {
if (j < i) {v[j] = v.get(i);}
j++;
}
}
v.shrink(j);
}
/**
* converts equivalence classes to equalities
*/
inline void equiv_to_expr(expr_equiv_class &equiv, expr_ref_vector &out) {
ast_manager &m = out.get_manager();
for (auto eq_class : equiv) {
expr *rep = nullptr;
for (expr *elem : eq_class) {
if (!m.is_value (elem)) {
rep = elem;
break;
}
}
SASSERT(rep);
for (expr *elem : eq_class) {
if (rep != elem) {out.push_back (m.mk_eq (rep, elem));}
}
}
}
/**
* expands equivalence classes to all derivable equalities
*/
inline bool equiv_to_expr_full(expr_equiv_class &equiv, expr_ref_vector &out) {
ast_manager &m = out.get_manager();
bool dirty = false;
for (auto eq_class : equiv) {
for (auto a = eq_class.begin(), end = eq_class.end(); a != end; ++a) {
expr_equiv_class::iterator b(a);
for (++b; b != end; ++b) {
out.push_back(m.mk_eq(*a, *b));
dirty = true;
}
}
}
return dirty;
}
}
#endif

View file

@ -50,7 +50,6 @@ Notes:
#include "util/luby.h"
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/expr_abstract.h"
#include "muz/spacer/obj_equiv_class.h"
namespace spacer {
@ -1123,7 +1122,7 @@ lemma::lemma(pob_ref const &p) :
m_pob(p), m_new_pob(m_pob) {SASSERT(m_pob);}
lemma::lemma(pob_ref const &p, expr_ref_vector &cube, unsigned lvl) :
m_ref_count(0),
m_ref_count(0),
m(p->get_ast_manager()),
m_body(m), m_cube(m),
m_bindings(m), m_lvl(p->level()),

View file

@ -24,7 +24,7 @@ Revision History:
#include "ast/expr_abstract.h"
#include "ast/rewriter/var_subst.h"
#include "ast/for_each_expr.h"
#include "muz/spacer/obj_equiv_class.h"
#include "ast/factor_equivs.h"
namespace spacer {

View file

@ -34,7 +34,7 @@
#include "util/luby.h"
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/expr_abstract.h"
#include "muz/spacer/obj_equiv_class.h"
#include "ast/factor_equivs.h"
namespace spacer {

View file

@ -63,7 +63,7 @@ Notes:
#include "tactic/arith/propagate_ineqs_tactic.h"
#include "tactic/arith/arith_bounds_tactic.h"
#include "muz/spacer/obj_equiv_class.h"
#include "ast/factor_equivs.h"
namespace spacer {

View file

@ -22,11 +22,7 @@ Revision History:
#include "muz/base/dl_context.h"
#include "muz/base/fixedpoint_params.hpp"
#include "muz/transforms/dl_mk_array_eq_rewrite.h"
#include "../spacer/obj_equiv_class.h"
// NSB code review: avoid dependency on spacer inside this directory.
// The python build system will rightfully complain if you include
// "muz/spacer/obj_equiv_class.h".
#include "ast/factor_equivs.h"
namespace datalog {
@ -65,7 +61,7 @@ namespace datalog {
new_tail.push_back(r.get_tail(i));
}
spacer::expr_equiv_class array_eq_classes(m);
expr_equiv_class array_eq_classes(m);
for(unsigned i = nb_predicates; i < tail_size; i++) {
expr* cond = r.get_tail(i);
expr* e1, *e2;

View file

@ -11,16 +11,14 @@ Author:
Julien Braine
Revision History:
Revision History:
--*/
#ifndef DL_MK_ARRAY_EQ_REWRITE_H_
#define DL_MK_ARRAY_EQ_REWRITE_H_
#include "muz/base/dl_rule_transformer.h"
#include "../spacer/obj_equiv_class.h"
namespace datalog {
@ -30,7 +28,7 @@ namespace datalog {
ast_manager& m;
context& m_ctx;
array_util m_a;
//Rule set context
const rule_set* m_src_set;
rule_set* m_dst;
@ -51,4 +49,3 @@ namespace datalog {
};
#endif /* DL_MK_ARRAY_EQ_REWRITE_H_ */

View file

@ -24,7 +24,6 @@ Revision History:
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/expr_abstract.h"
#include "muz/base/fixedpoint_params.hpp"
#include "../spacer/obj_equiv_class.h"
namespace datalog {
@ -244,7 +243,7 @@ namespace datalog {
expr_ref_vector mk_array_instantiation::retrieve_all_selects(expr*array)
{
expr_ref_vector all_selects(m);
for(spacer::expr_equiv_class::iterator it = eq_classes.begin(array);
for(expr_equiv_class::iterator it = eq_classes.begin(array);
it != eq_classes.end(array); ++it)
{
selects.insert_if_not_there(*it, ptr_vector<expr>());

View file

@ -70,8 +70,8 @@ Revision History:
#define DL_MK_ARRAY_INSTANTIATION_H_
#include "ast/factor_equivs.h"
#include "muz/base/dl_rule_transformer.h"
#include "../spacer/obj_equiv_class.h"
namespace datalog {
@ -89,7 +89,7 @@ namespace datalog {
//Rule context
obj_map<expr, ptr_vector<expr> > selects;
spacer::expr_equiv_class eq_classes;
expr_equiv_class eq_classes;
unsigned cnt;//Index for new variables
obj_map<expr, var*> done_selects;
expr_ref_vector ownership;