3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00
This commit is contained in:
Nils Becker 2019-05-02 20:09:06 +02:00
commit 2c40da23a2
33 changed files with 424 additions and 401 deletions

View file

@ -30,13 +30,14 @@ array_decl_plugin::array_decl_plugin():
m_default_sym("default"),
m_map_sym("map"),
m_set_union_sym("union"),
m_set_intersect_sym("intersect"),
m_set_difference_sym("difference"),
m_set_intersect_sym("intersection"),
m_set_difference_sym("setminus"),
m_set_complement_sym("complement"),
m_set_subset_sym("subset"),
m_array_ext_sym("array-ext"),
m_as_array_sym("as-array"),
m_set_has_size_sym("set-has-size") {
m_set_has_size_sym("set-has-size"),
m_set_card_sym("card") {
}
#define ARRAY_SORT_STR "Array"
@ -440,6 +441,21 @@ func_decl * array_decl_plugin::mk_set_subset(unsigned arity, sort * const * doma
func_decl_info(m_family_id, OP_SET_SUBSET));
}
func_decl * array_decl_plugin::mk_set_card(unsigned arity, sort * const* domain) {
if (arity != 1) {
m_manager->raise_exception("card takes only one argument");
return nullptr;
}
arith_util arith(*m_manager);
if (!is_array_sort(domain[0]) || !m_manager->is_bool(get_array_range(domain[0]))) {
m_manager->raise_exception("card expects an array of Booleans");
}
sort * int_sort = arith.mk_int();
return m_manager->mk_func_decl(m_set_card_sym, arity, domain, int_sort,
func_decl_info(m_family_id, OP_SET_CARD));
}
func_decl * array_decl_plugin::mk_set_has_size(unsigned arity, sort * const* domain) {
if (arity != 2) {
m_manager->raise_exception("set-has-size takes two arguments");
@ -525,6 +541,8 @@ func_decl * array_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
return mk_set_subset(arity, domain);
case OP_SET_HAS_SIZE:
return mk_set_has_size(arity, domain);
case OP_SET_CARD:
return mk_set_card(arity, domain);
case OP_AS_ARRAY: {
if (num_parameters != 1 ||
!parameters[0].is_ast() ||
@ -548,8 +566,10 @@ func_decl * array_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
void array_decl_plugin::get_sort_names(svector<builtin_name>& sort_names, symbol const & logic) {
sort_names.push_back(builtin_name(ARRAY_SORT_STR, ARRAY_SORT));
sort_names.push_back(builtin_name("=>", ARRAY_SORT));
// TBD: this could easily break users even though it is already used in CVC4:
// sort_names.push_back(builtin_name("Set", _SET_SORT));
if (logic == symbol::null || logic == symbol("HORN") || logic == symbol("ALL")) {
// this could easily break users even though it is already used in CVC4:
sort_names.push_back(builtin_name("Set", _SET_SORT));
}
}
void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol const & logic) {
@ -561,13 +581,14 @@ void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
op_names.push_back(builtin_name("map",OP_ARRAY_MAP));
op_names.push_back(builtin_name("default",OP_ARRAY_DEFAULT));
op_names.push_back(builtin_name("union",OP_SET_UNION));
op_names.push_back(builtin_name("intersect",OP_SET_INTERSECT));
op_names.push_back(builtin_name("difference",OP_SET_DIFFERENCE));
op_names.push_back(builtin_name("intersection",OP_SET_INTERSECT));
op_names.push_back(builtin_name("setminus",OP_SET_DIFFERENCE));
op_names.push_back(builtin_name("complement",OP_SET_COMPLEMENT));
op_names.push_back(builtin_name("subset",OP_SET_SUBSET));
op_names.push_back(builtin_name("as-array", OP_AS_ARRAY));
op_names.push_back(builtin_name("array-ext", OP_ARRAY_EXT));
op_names.push_back(builtin_name("set-has-size", OP_SET_HAS_SIZE));
op_names.push_back(builtin_name("card", OP_SET_CARD));
}
}
@ -595,6 +616,13 @@ func_decl * array_recognizers::get_as_array_func_decl(expr * n) const {
return to_func_decl(to_app(n)->get_decl()->get_parameter(0).get_ast());
}
func_decl * array_recognizers::get_map_func_decl(func_decl* f) const {
SASSERT(f->get_num_parameters() == 1);
SASSERT(f->get_parameter(0).is_ast());
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
return to_func_decl(f->get_parameter(0).get_ast());
}
func_decl * array_recognizers::get_as_array_func_decl(func_decl * f) const {
SASSERT(is_as_array(f));
return to_func_decl(f->get_parameter(0).get_ast());

View file

@ -52,6 +52,7 @@ enum array_op_kind {
OP_SET_COMPLEMENT,
OP_SET_SUBSET,
OP_SET_HAS_SIZE,
OP_SET_CARD,
OP_AS_ARRAY, // used for model construction
LAST_ARRAY_OP
};
@ -70,6 +71,7 @@ class array_decl_plugin : public decl_plugin {
symbol m_array_ext_sym;
symbol m_as_array_sym;
symbol m_set_has_size_sym;
symbol m_set_card_sym;
bool check_set_arguments(unsigned arity, sort * const * domain);
@ -99,6 +101,8 @@ class array_decl_plugin : public decl_plugin {
func_decl* mk_set_has_size(unsigned arity, sort * const* domain);
func_decl* mk_set_card(unsigned arity, sort * const* domain);
bool is_array_sort(sort* s) const;
public:
array_decl_plugin();
@ -149,15 +153,19 @@ public:
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
bool is_set_has_size(expr* e) const { return is_app_of(e, m_fid, OP_SET_HAS_SIZE); }
bool is_set_card(expr* e) const { return is_app_of(e, m_fid, OP_SET_CARD); }
bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); }
bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
bool is_map(func_decl* f) const { return is_decl_of(f, m_fid, OP_ARRAY_MAP); }
bool is_as_array(func_decl* f) const { return is_decl_of(f, m_fid, OP_AS_ARRAY); }
bool is_set_has_size(func_decl* f) const { return is_decl_of(f, m_fid, OP_SET_HAS_SIZE); }
bool is_set_card(func_decl* f) const { return is_decl_of(f, m_fid, OP_SET_CARD); }
bool is_as_array(func_decl* f, func_decl*& g) const { return is_decl_of(f, m_fid, OP_AS_ARRAY) && (g = get_as_array_func_decl(f), true); }
func_decl * get_as_array_func_decl(expr * n) const;
func_decl * get_as_array_func_decl(func_decl* f) const;
func_decl * get_map_func_decl(func_decl* f) const;
func_decl * get_map_func_decl(expr* e) const { return get_map_func_decl(to_app(e)->get_decl()); }
bool is_const(expr* e, expr*& v) const;
@ -184,6 +192,16 @@ public:
parameter p(f);
return m_manager.mk_app(m_fid, OP_ARRAY_MAP, 1, &p, num_args, args);
}
expr * mk_map_assoc(func_decl * f, unsigned num_args, expr * const * args) {
expr* r = args[0];
for (unsigned i = 1; i < num_args; ++i) {
expr* es[2] = { r, args[i] };
r = mk_map(f, 2, es);
}
return r;
}
app * mk_const_array(sort * s, expr * v) {
parameter param(s);
return m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, &param, 1, &v);
@ -195,6 +213,18 @@ public:
return mk_const_array(s, m_manager.mk_true());
}
app * mk_setminus(expr* s1, expr* s2) {
return m_manager.mk_app(m_fid, OP_SET_DIFFERENCE, s1, s2);
}
app * mk_intersection(expr* s1, expr* s2) {
return m_manager.mk_app(m_fid, OP_SET_INTERSECT, s1, s2);
}
app * mk_union(expr* s1, expr* s2) {
return m_manager.mk_app(m_fid, OP_SET_UNION, s1, s2);
}
app* mk_has_size(expr* set, expr* n) {
return m_manager.mk_app(m_fid, OP_SET_HAS_SIZE, set, n);
}

View file

@ -924,11 +924,11 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
decl_collector decls(m);
smt_renaming rn;
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
decls.visit(m_assumptions[i].get());
for (expr* a : m_assumptions) {
decls.visit(a);
}
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
decls.visit(m_assumptions_star[i].get());
for (expr* a : m_assumptions_star) {
decls.visit(a);
}
decls.visit(n);
@ -959,8 +959,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
#else
decls.order_deps();
ast_mark sort_mark;
for (unsigned i = 0; i < decls.get_num_sorts(); ++i) {
sort* s = decls.get_sorts()[i];
for (sort* s : decls.get_sorts()) {
if (!(*m_is_declared)(s)) {
smt_printer p(strm, m, ql, rn, m_logic, true, true, m_simplify_implies, 0);
p.pp_sort_decl(sort_mark, s);

View file

@ -57,8 +57,8 @@ public:
unsigned get_num_sorts() const { return m_sorts.size(); }
unsigned get_num_decls() const { return m_decls.size(); }
sort * const * get_sorts() const { return m_sorts.c_ptr(); }
func_decl * const * get_func_decls() const { return m_decls.c_ptr(); }
ptr_vector<sort> const& get_sorts() const { return m_sorts; }
ptr_vector<func_decl> const& get_func_decls() const { return m_decls; }
};
#endif

View file

@ -45,10 +45,7 @@ br_status array_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
st = mk_store_core(num_args, args, result);
break;
case OP_ARRAY_MAP:
SASSERT(f->get_num_parameters() == 1);
SASSERT(f->get_parameter(0).is_ast());
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
st = mk_map_core(to_func_decl(f->get_parameter(0).get_ast()), num_args, args, result);
st = mk_map_core(m_util.get_map_func_decl(f), num_args, args, result);
break;
case OP_SET_UNION:
st = mk_set_union(num_args, args, result);
@ -69,14 +66,15 @@ br_status array_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
st = mk_set_difference(args[0], args[1], result);
break;
default:
return BR_FAILED;
st = BR_FAILED;
break;
}
TRACE("array_rewriter", tout << mk_pp(f, m()) << "\n";
for (unsigned i = 0; i < num_args; ++i) {
tout << mk_pp(args[i], m()) << "\n";
}
tout << "\n --> " << result << "\n";
);
CTRACE("array_rewriter", st != BR_FAILED,
tout << mk_pp(f, m()) << "\n";
for (unsigned i = 0; i < num_args; ++i) {
tout << mk_pp(args[i], m()) << "\n";
}
tout << "\n --> " << result << "\n";);
return st;
}
@ -241,6 +239,14 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
return BR_FAILED;
}
sort_ref array_rewriter::get_map_array_sort(func_decl* f, unsigned num_args, expr* const* args) {
sort* s0 = m().get_sort(args[0]);
unsigned sz = get_array_arity(s0);
ptr_vector<sort> domain;
for (unsigned i = 0; i < sz; ++i) domain.push_back(get_array_domain(s0, i));
return sort_ref(m_util.mk_array_sort(sz, domain.c_ptr(), f->get_range()), m());
}
br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
app* store_expr = nullptr;
@ -291,11 +297,7 @@ br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * c
}
else {
expr_ref value(m().mk_app(f, values.size(), values.c_ptr()), m());
sort* s0 = m().get_sort(args[0]);
unsigned sz = get_array_arity(s0);
ptr_vector<sort> domain;
for (unsigned i = 0; i < sz; ++i) domain.push_back(get_array_domain(s0, i));
sort_ref s(m_util.mk_array_sort(sz, domain.c_ptr(), m().get_sort(value)), m());
sort_ref s = get_map_array_sort(f, num_args, args);
result = m_util.mk_const_array(s, value);
}
return BR_REWRITE2;
@ -336,6 +338,75 @@ br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * c
return BR_REWRITE3;
}
if (m().is_and(f)) {
ast_mark mark;
ptr_buffer<expr> es;
bool change = false;
unsigned j = 0;
es.append(num_args, args);
for (unsigned i = 0; i < es.size(); ++i) {
expr* e = es[i];
if (mark.is_marked(e)) {
change = true;
}
else if (m_util.is_map(e) && m().is_and(m_util.get_map_func_decl(e))) {
mark.mark(e, true);
es.append(to_app(e)->get_num_args(), to_app(e)->get_args());
}
else {
mark.mark(e, true);
es[j++] = es[i];
}
}
es.shrink(j);
for (expr* e : es) {
if (m().is_not(e, e) && mark.is_marked(e)) {
sort_ref s = get_map_array_sort(f, num_args, args);
result = m_util.mk_const_array(s, m().mk_false());
return BR_DONE;
}
}
if (change) {
result = m_util.mk_map_assoc(f, es.size(), es.c_ptr());
return BR_DONE;
}
}
if (m().is_or(f)) {
ast_mark mark;
ptr_buffer<expr> es;
es.append(num_args, args);
unsigned j = 0;
bool change = false;
for (unsigned i = 0; i < es.size(); ++i) {
expr* e = es[i];
if (mark.is_marked(e)) {
change = true;
}
else if (m_util.is_map(e) && m().is_or(m_util.get_map_func_decl(e))) {
mark.mark(e, true);
es.append(to_app(e)->get_num_args(), to_app(e)->get_args());
}
else {
mark.mark(e, true);
es[j++] = es[i];
}
}
es.shrink(j);
for (expr* e : es) {
if (m().is_not(e, e) && mark.is_marked(e)) {
sort_ref s = get_map_array_sort(f, num_args, args);
result = m_util.mk_const_array(s, m().mk_true());
return BR_DONE;
}
}
if (change) {
result = m_util.mk_map_assoc(f, es.size(), es.c_ptr());
return BR_DONE;
}
}
return BR_FAILED;
}

View file

@ -37,6 +37,9 @@ class array_rewriter {
lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
bool has_index_set(expr* e, expr_ref& e0, vector<expr_ref_vector>& indices);
void mk_eq(expr* e, expr* lhs, expr* rhs, expr_ref_vector& fmls);
sort_ref get_map_array_sort(func_decl* f, unsigned num_args, expr* const* args);
public:
array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
m_util(m) {