mirror of
https://github.com/Z3Prover/z3
synced 2025-04-30 04:15:51 +00:00
#5641 add handlers for basic set operations to euf=true
This commit is contained in:
parent
9d3c8a6a2f
commit
8245935d41
5 changed files with 69 additions and 21 deletions
|
@ -84,7 +84,7 @@ namespace array {
|
|||
return assert_default_const_axiom(to_app(child));
|
||||
else if (a.is_store(child))
|
||||
return assert_default_store_axiom(to_app(child));
|
||||
else if (a.is_map(child))
|
||||
else if (is_map_combinator(child))
|
||||
return assert_default_map_axiom(to_app(child));
|
||||
else
|
||||
return false;
|
||||
|
@ -115,7 +115,7 @@ namespace array {
|
|||
return assert_select_as_array_axiom(select, to_app(child));
|
||||
else if (a.is_store(child))
|
||||
return assert_select_store_axiom(select, to_app(child));
|
||||
else if (a.is_map(child))
|
||||
else if (is_map_combinator(child))
|
||||
return assert_select_map_axiom(select, to_app(child));
|
||||
else if (is_lambda(child))
|
||||
return assert_select_lambda_axiom(select, child);
|
||||
|
@ -273,16 +273,19 @@ namespace array {
|
|||
return add_clause(lit1, ~lit2);
|
||||
}
|
||||
|
||||
bool solver::is_map_combinator(expr* map) const {
|
||||
return a.is_map(map) || a.is_union(map) || a.is_intersect(map) || a.is_difference(map) || a.is_complement(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert axiom:
|
||||
* select(map[f](a, ... d), i) = f(select(a,i),...,select(d,i))
|
||||
*/
|
||||
bool solver::assert_select_map_axiom(app* select, app* map) {
|
||||
++m_stats.m_num_select_map_axiom;
|
||||
SASSERT(a.is_map(map));
|
||||
SASSERT(a.is_select(select));
|
||||
SASSERT(is_map_combinator(map));
|
||||
SASSERT(map->get_num_args() > 0);
|
||||
func_decl* f = a.get_map_func_decl(map);
|
||||
unsigned num_args = select->get_num_args();
|
||||
ptr_buffer<expr> args1, args2;
|
||||
vector<ptr_vector<expr> > args2l;
|
||||
|
@ -303,7 +306,8 @@ namespace array {
|
|||
|
||||
expr_ref sel1(m), sel2(m);
|
||||
sel1 = a.mk_select(args1);
|
||||
sel2 = m.mk_app(f, args2);
|
||||
sel2 = apply_map(map, args2.size(), args2.data());
|
||||
|
||||
rewrite(sel2);
|
||||
euf::enode* n1 = e_internalize(sel1);
|
||||
euf::enode* n2 = e_internalize(sel2);
|
||||
|
@ -330,21 +334,44 @@ namespace array {
|
|||
return ctx.propagate(n1, n2, array_axiom());
|
||||
}
|
||||
|
||||
expr_ref solver::apply_map(app* map, unsigned n, expr* const* args) {
|
||||
expr_ref result(m);
|
||||
if (a.is_map(map))
|
||||
result = m.mk_app(a.get_map_func_decl(map), n, args);
|
||||
else if (a.is_union(map))
|
||||
result = m.mk_or(n, args);
|
||||
else if (a.is_intersect(map))
|
||||
result = m.mk_and(n, args);
|
||||
else if (a.is_difference(map)) {
|
||||
SASSERT(n > 0);
|
||||
result = args[0];
|
||||
for (unsigned i = 1; i < n; ++i)
|
||||
result = m.mk_and(result, m.mk_not(args[i]));
|
||||
}
|
||||
else if (a.is_complement(map)) {
|
||||
SASSERT(n == 1);
|
||||
result = m.mk_not(args[0]);
|
||||
}
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
rewrite(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert:
|
||||
* default(map[f](a,..,d)) = f(default(a),..,default(d))
|
||||
*/
|
||||
bool solver::assert_default_map_axiom(app* map) {
|
||||
++m_stats.m_num_default_map_axiom;
|
||||
SASSERT(a.is_map(map));
|
||||
func_decl* f = a.get_map_func_decl(map);
|
||||
SASSERT(map->get_num_args() == f->get_arity());
|
||||
SASSERT(is_map_combinator(map));
|
||||
expr_ref_vector args2(m);
|
||||
for (expr* arg : *map)
|
||||
args2.push_back(a.mk_default(arg));
|
||||
expr_ref def1(a.mk_default(map), m);
|
||||
expr_ref def2(m.mk_app(f, args2), m);
|
||||
rewrite(def2);
|
||||
expr_ref def2 = apply_map(map, args2.size(), args2.data());
|
||||
return ctx.propagate(e_internalize(def1), e_internalize(def2), array_axiom());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue