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

add unconstrained elimination for sequences

This commit is contained in:
Nikolaj Bjorner 2023-03-14 09:23:13 +01:00
parent a0f3727e90
commit d1c7ff1a36
12 changed files with 148 additions and 16 deletions

View file

@ -19,6 +19,7 @@ Author:
#include "ast/ast_ll_pp.h"
#include "ast/ast_util.h"
#include "ast/arith_decl_plugin.h"
#include "ast/seq_decl_plugin.h"
#include "ast/converters/expr_inverter.h"
class basic_expr_inverter : public iexpr_inverter {
@ -742,6 +743,53 @@ public:
};
class seq_expr_inverter : public iexpr_inverter {
seq_util seq;
public:
seq_expr_inverter(ast_manager& m) : iexpr_inverter(m), seq(m) {}
family_id get_fid() const override { return seq.get_family_id(); }
bool operator()(func_decl* f, unsigned num, expr* const* args, expr_ref& r) override {
switch (f->get_decl_kind()) {
case _OP_STRING_CONCAT:
case OP_SEQ_CONCAT: {
expr* x, *y;
if (uncnstr(args[0]) && num == 2 &&
seq.str.is_concat(args[1], x, y) &&
uncnstr(x)) {
mk_fresh_uncnstr_var_for(f, r);
if (m_mc) {
add_def(args[0], seq.str.mk_empty(args[0]->get_sort()));
add_def(x, r);
}
r = seq.str.mk_concat(r, y);
return true;
}
if (!uncnstr(num, args))
return false;
mk_fresh_uncnstr_var_for(f, r);
if (m_mc) {
add_def(args[0], r);
for (unsigned i = 1; i < num; ++i)
add_def(args[i], seq.str.mk_empty(args[0]->get_sort()));
}
return true;
}
default:
return false;
}
}
bool mk_diff(expr* t, expr_ref& r) override {
return false;
}
};
expr_inverter::~expr_inverter() {
for (auto* v : m_inverters)
@ -796,6 +844,7 @@ expr_inverter::expr_inverter(ast_manager& m): iexpr_inverter(m) {
add(alloc(array_expr_inverter, m, *this));
add(alloc(dt_expr_inverter, m));
add(alloc(basic_expr_inverter, m, *this));
add(alloc(seq_expr_inverter, m));
}

View file

@ -67,6 +67,8 @@ namespace euf {
}
enode_bool_pair egraph::insert_table(enode* p) {
TRACE("euf", tout << bpp(p) << "\n");
//SASSERT(!m_table.contains_ptr(p));
auto rc = m_table.insert(p);
p->m_cg = rc.first;
return rc;
@ -280,6 +282,7 @@ namespace euf {
if (!m.is_bool(n->get_sort()))
return;
if (enable_merge_tf != n->merge_tf()) {
TRACE("euf", tout << "set tf " << enable_merge_tf << " " << bpp(n) << "\n");
n->set_merge_tf(enable_merge_tf);
m_updates.push_back(update_record(n, update_record::toggle_merge_tf()));
}
@ -487,6 +490,7 @@ namespace euf {
}
void egraph::remove_parents(enode* r) {
TRACE("euf", tout << bpp(r) << "\n");
for (enode* p : enode_parents(r)) {
if (p->is_marked1())
continue;
@ -496,6 +500,7 @@ namespace euf {
SASSERT(m_table.contains_ptr(p));
p->mark1();
erase_from_table(p);
CTRACE("euf", m_table.contains_ptr(p), tout << bpp(p) << "\n"; display(tout));
SASSERT(!m_table.contains_ptr(p));
}
else if (p->is_equality())

View file

@ -5518,6 +5518,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
reduce_front(ls, rs, eqs) &&
reduce_itos(ls, rs, eqs) &&
reduce_itos(rs, ls, eqs) &&
reduce_value_clash(ls, rs, eqs) &&
reduce_by_length(ls, rs, eqs) &&
reduce_subsequence(ls, rs, eqs) &&
reduce_non_overlap(ls, rs, eqs) &&
@ -5943,6 +5944,41 @@ bool seq_rewriter::reduce_non_overlap(expr_ref_vector& ls, expr_ref_vector& rs,
return true;
}
/**
* partial check for value clash.
* checks that elements that do not occur in
* other sequence are non-values.
* The check could be extended to take non-value
* characters (units) into account.
*/
bool seq_rewriter::reduce_value_clash(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
ptr_buffer<expr> es;
if (ls.empty() || rs.empty())
return true;
es.append(ls.size(), ls.data());
auto remove = [&](expr* r) {
for (unsigned i = 0; i < es.size(); ++i) {
if (r == es[i]) {
es[i] = es.back();
es.pop_back();
return true;
}
}
return false;
};
auto is_unit_value = [&](expr* r) {
return m().is_value(r) && str().is_unit(r);
};
for (expr* r : rs) {
if (remove(r))
continue;
if (!is_unit_value(r))
return true;
}
return any_of(es, [&](expr* e) { return is_unit_value(e); });
}
bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
if (ls.size() > rs.size())

View file

@ -340,6 +340,7 @@ class seq_rewriter {
bool is_sequence(expr* e, expr_ref_vector& seq);
bool is_sequence(eautomaton& aut, expr_ref_vector& seq);
bool get_lengths(expr* e, expr_ref_vector& lens, rational& pos);
bool reduce_value_clash(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
bool reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
bool reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
void remove_empty_and_concats(expr_ref_vector& es);

View file

@ -73,7 +73,7 @@ void elim_unconstrained::eliminate() {
node& n = get_node(v);
if (n.m_refcount == 0)
continue;
if (n.m_refcount > 1)
if (n.m_refcount > 1)
return;
if (n.m_parents.empty()) {
@ -90,10 +90,10 @@ void elim_unconstrained::eliminate() {
unsigned sz = m_args.size();
for (expr* arg : *to_app(t))
m_args.push_back(reconstruct_term(get_node(arg)));
bool inverted = m_inverter(t->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz, r);
bool inverted = m_inverter(t->get_decl(), t->get_num_args(), m_args.data() + sz, r);
proof_ref pr(m);
if (inverted && m_enable_proofs) {
expr * s = m.mk_app(t->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz);
expr * s = m.mk_app(t->get_decl(), t->get_num_args(), m_args.data() + sz);
expr * eq = m.mk_eq(s, r);
proof * pr1 = m.mk_def_intro(eq);
proof * pr = m.mk_apply_def(s, r, pr1);

View file

@ -3,7 +3,7 @@ Copyright (c) 2022 Microsoft Corporation
Module Name:
seq_simplifier.h
then_simplifier.h
Abstract:
@ -21,7 +21,7 @@ Author:
#include "ast/simplifiers/dependent_expr_state.h"
class seq_simplifier : public dependent_expr_simplifier {
class then_simplifier : public dependent_expr_simplifier {
scoped_ptr_vector<dependent_expr_simplifier> m_simplifiers;
struct collect_stats {
@ -53,7 +53,7 @@ class seq_simplifier : public dependent_expr_simplifier {
public:
seq_simplifier(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
then_simplifier(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
dependent_expr_simplifier(m, fmls) {
}