mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 09:34:08 +00:00
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
9c3f0190f4
commit
cc8cd2cc2f
|
@ -2210,13 +2210,21 @@ br_status seq_rewriter::mk_eq_core(expr * l, expr * r, expr_ref & result) {
|
|||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
void seq_rewriter::remove_empty(expr_ref_vector& es) {
|
||||
void seq_rewriter::remove_empty_and_concats(expr_ref_vector& es) {
|
||||
unsigned j = 0;
|
||||
bool has_concat = false;
|
||||
for (expr* e : es) {
|
||||
has_concat |= m_util.str.is_concat(e);
|
||||
if (!m_util.str.is_empty(e))
|
||||
es[j++] = e;
|
||||
}
|
||||
es.shrink(j);
|
||||
if (has_concat) {
|
||||
expr_ref_vector fs(m());
|
||||
for (expr* e : es)
|
||||
m_util.str.get_concat(e, fs);
|
||||
es.swap(fs);
|
||||
}
|
||||
}
|
||||
|
||||
void seq_rewriter::remove_leading(unsigned n, expr_ref_vector& es) {
|
||||
|
@ -2229,7 +2237,7 @@ void seq_rewriter::remove_leading(unsigned n, expr_ref_vector& es) {
|
|||
es.shrink(es.size() - n);
|
||||
}
|
||||
|
||||
bool seq_rewriter::reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs, bool& change) {
|
||||
bool seq_rewriter::reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs) {
|
||||
expr* a, *b;
|
||||
zstring s, s1, s2;
|
||||
while (true) {
|
||||
|
@ -2237,7 +2245,7 @@ bool seq_rewriter::reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_re
|
|||
break;
|
||||
}
|
||||
expr* l = ls.back();
|
||||
expr* r = rs.back();
|
||||
expr* r = rs.back();
|
||||
if (m_util.str.is_unit(r) && m_util.str.is_string(l)) {
|
||||
std::swap(l, r);
|
||||
ls.swap(rs);
|
||||
|
@ -2289,12 +2297,11 @@ bool seq_rewriter::reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_re
|
|||
else {
|
||||
break;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool seq_rewriter::reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs, bool& change) {
|
||||
bool seq_rewriter::reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs) {
|
||||
expr* a, *b;
|
||||
zstring s, s1, s2;
|
||||
unsigned head1 = 0, head2 = 0;
|
||||
|
@ -2364,7 +2371,6 @@ bool seq_rewriter::reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_r
|
|||
else {
|
||||
break;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
remove_leading(head1, ls);
|
||||
remove_leading(head2, rs);
|
||||
|
@ -2376,17 +2382,24 @@ bool seq_rewriter::reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_r
|
|||
- New equalities are inserted into eqs.
|
||||
- Last remaining equalities that cannot be simplified further are kept in ls, rs
|
||||
- returns false if equality is unsatisfiable
|
||||
- sets change to true if some simplification occurred
|
||||
*/
|
||||
bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool& change) {
|
||||
TRACE("seq_verbose", tout << ls << "\n"; tout << rs << "\n";);
|
||||
remove_empty(ls);
|
||||
remove_empty(rs);
|
||||
unsigned hash_l = ls.hash();
|
||||
unsigned hash_r = rs.hash();
|
||||
unsigned sz_eqs = eqs.size();
|
||||
remove_empty_and_concats(ls);
|
||||
remove_empty_and_concats(rs);
|
||||
return
|
||||
reduce_back(ls, rs, eqs, change) &&
|
||||
reduce_front(ls, rs, eqs, change) &&
|
||||
reduce_itos(ls, rs, eqs, change) &&
|
||||
reduce_by_length(ls, rs, eqs, change) &&
|
||||
reduce_subsequence(ls, rs, eqs, change);
|
||||
reduce_back(ls, rs, eqs) &&
|
||||
reduce_front(ls, rs, eqs) &&
|
||||
reduce_itos(ls, rs, eqs) &&
|
||||
reduce_itos(rs, ls, eqs) &&
|
||||
reduce_by_length(ls, rs, eqs) &&
|
||||
reduce_subsequence(ls, rs, eqs) &&
|
||||
(change = (hash_l != ls.hash() || hash_r != rs.hash() || eqs.size() != sz_eqs),
|
||||
true);
|
||||
}
|
||||
|
||||
bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_pair_vector& new_eqs, bool& changed) {
|
||||
|
@ -2552,41 +2565,31 @@ bool seq_rewriter::is_string(unsigned n, expr* const* es, zstring& s) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool seq_rewriter::reduce_itos(expr_ref_vector& ls, expr_ref_vector& rs,
|
||||
expr_ref_pair_vector& eqs, bool& change) {
|
||||
expr* n = nullptr;
|
||||
if (ls.size() == 1 && m_util.str.is_itos(ls.get(0), n) &&
|
||||
solve_itos(n, rs, eqs)) {
|
||||
ls.reset(); rs.reset();
|
||||
change = true;
|
||||
}
|
||||
else if (rs.size() == 1 && m_util.str.is_itos(rs.get(0), n) &&
|
||||
solve_itos(n, ls, eqs)) {
|
||||
ls.reset(); rs.reset();
|
||||
change = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* itos(n) = <numeric string> -> n = numeric
|
||||
*/
|
||||
|
||||
bool seq_rewriter::solve_itos(expr* n, expr_ref_vector const& es, expr_ref_pair_vector& eqs) {
|
||||
bool seq_rewriter::reduce_itos(expr_ref_vector& ls, expr_ref_vector& rs,
|
||||
expr_ref_pair_vector& eqs) {
|
||||
expr* n = nullptr;
|
||||
zstring s;
|
||||
if (is_string(es.size(), es.c_ptr(), s)) {
|
||||
if (ls.size() == 1 &&
|
||||
m_util.str.is_itos(ls.get(0), n) &&
|
||||
is_string(rs.size(), rs.c_ptr(), s)) {
|
||||
std::string s1 = s.encode();
|
||||
rational r(s1.c_str());
|
||||
if (s1 == r.to_string()) {
|
||||
eqs.push_back(n, m_autil.mk_numeral(r, true));
|
||||
ls.reset();
|
||||
rs.reset();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool seq_rewriter::reduce_by_length(expr_ref_vector& ls, expr_ref_vector& rs,
|
||||
expr_ref_pair_vector& eqs, bool& change) {
|
||||
expr_ref_pair_vector& eqs) {
|
||||
|
||||
if (ls.empty() && rs.empty())
|
||||
return true;
|
||||
|
@ -2599,7 +2602,6 @@ bool seq_rewriter::reduce_by_length(expr_ref_vector& ls, expr_ref_vector& rs,
|
|||
if (bounded2 && len2 < len1)
|
||||
return false;
|
||||
if (bounded1 && len1 == len2 && len1 > 0) {
|
||||
change = true;
|
||||
if (!set_empty(rs.size(), rs.c_ptr(), false, eqs))
|
||||
return false;
|
||||
eqs.push_back(concat_non_empty(ls), concat_non_empty(rs));
|
||||
|
@ -2607,7 +2609,6 @@ bool seq_rewriter::reduce_by_length(expr_ref_vector& ls, expr_ref_vector& rs,
|
|||
rs.reset();
|
||||
}
|
||||
else if (bounded2 && len1 == len2 && len1 > 0) {
|
||||
change = true;
|
||||
if (!set_empty(ls.size(), ls.c_ptr(), false, eqs))
|
||||
return false;
|
||||
eqs.push_back(concat_non_empty(ls), concat_non_empty(rs));
|
||||
|
@ -2623,7 +2624,7 @@ bool seq_rewriter::is_epsilon(expr* e) const {
|
|||
return m_util.re.is_to_re(e, e1) && m_util.str.is_empty(e1);
|
||||
}
|
||||
|
||||
bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool& change) {
|
||||
bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
|
||||
|
||||
if (ls.size() > rs.size())
|
||||
ls.swap(rs);
|
||||
|
@ -2663,7 +2664,6 @@ bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs,
|
|||
if (j == rs.size()) {
|
||||
return true;
|
||||
}
|
||||
change = true;
|
||||
rs.shrink(j);
|
||||
SASSERT(ls.size() == rs.size());
|
||||
if (!ls.empty()) {
|
||||
|
|
|
@ -174,10 +174,9 @@ class seq_rewriter {
|
|||
bool sign_is_determined(expr* len, sign& s);
|
||||
|
||||
bool set_empty(unsigned sz, expr* const* es, bool all, expr_ref_pair_vector& eqs);
|
||||
bool reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool& change);
|
||||
bool reduce_by_length(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool& change);
|
||||
bool reduce_itos(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool& change);
|
||||
bool solve_itos(expr* n, expr_ref_vector const& es, expr_ref_pair_vector& eqs);
|
||||
bool reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs);
|
||||
bool reduce_by_length(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs);
|
||||
bool reduce_itos(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs);
|
||||
bool min_length(expr_ref_vector const& es, unsigned& len);
|
||||
expr* concat_non_empty(expr_ref_vector& es);
|
||||
|
||||
|
@ -188,9 +187,9 @@ class seq_rewriter {
|
|||
bool is_sequence(eautomaton& aut, expr_ref_vector& seq);
|
||||
bool is_epsilon(expr* e) const;
|
||||
bool get_lengths(expr* e, expr_ref_vector& lens, rational& pos);
|
||||
bool reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs, bool& change);
|
||||
bool reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs, bool& change);
|
||||
void remove_empty(expr_ref_vector& es);
|
||||
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);
|
||||
void remove_leading(unsigned n, expr_ref_vector& es);
|
||||
|
||||
public:
|
||||
|
|
|
@ -2288,7 +2288,6 @@ void theory_seq::validate_fmls(enode_pair_vector const& eqs, literal_vector cons
|
|||
for (expr* f : fmls) {
|
||||
k.assert_expr(f);
|
||||
}
|
||||
IF_VERBOSE(0, verbose_stream() << "validate: " << fmls << "\n";);
|
||||
lbool r = k.check();
|
||||
if (r != l_false && !m.limit().get_cancel_flag()) {
|
||||
model_ref mdl;
|
||||
|
|
|
@ -41,6 +41,11 @@ protected:
|
|||
dec_ref(*it);
|
||||
}
|
||||
|
||||
struct hash_proc {
|
||||
unsigned operator()(ref_vector_core const* v, unsigned idx) const {
|
||||
return (*v)[idx]->get_id();
|
||||
}
|
||||
};
|
||||
public:
|
||||
typedef T * data;
|
||||
|
||||
|
@ -129,6 +134,14 @@ public:
|
|||
|
||||
T ** c_ptr() { return m_nodes.begin(); }
|
||||
|
||||
unsigned hash() const {
|
||||
unsigned sz = size();
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
return get_composite_hash(this, sz, default_kind_hash_proc<ref_vector_core const*>(), hash_proc());
|
||||
}
|
||||
|
||||
iterator begin() const { return m_nodes.begin(); }
|
||||
iterator end() const { return begin() + size(); }
|
||||
|
||||
|
@ -400,21 +413,8 @@ struct ref_vector_ptr_hash {
|
|||
|
||||
typedef ref_vector<T,TM> RefV;
|
||||
|
||||
struct hash_proc {
|
||||
unsigned operator()(RefV* v, unsigned idx) const {
|
||||
return (*v)[idx]->get_id();
|
||||
}
|
||||
};
|
||||
|
||||
unsigned operator()(RefV* v) const {
|
||||
if (!v) {
|
||||
return 0;
|
||||
}
|
||||
unsigned sz = v->size();
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
return get_composite_hash(v, sz, default_kind_hash_proc<RefV*>(), hash_proc());
|
||||
return v ? v->hash() : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue