3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-10-09 01:11:55 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-11-26 21:12:47 -08:00
parent e026f96ed4
commit 503bedbc7a
3 changed files with 99 additions and 84 deletions

View file

@ -1487,8 +1487,7 @@ bool theory_seq::enforce_length(expr_ref_vector const& es, vector<rational> & le
bool all_have_length = true;
rational val;
zstring s;
for (unsigned i = 0; i < es.size(); ++i) {
expr* e = es[i];
for (expr* e : es) {
if (m_util.str.is_unit(e)) {
len.push_back(rational(1));
}
@ -3397,6 +3396,7 @@ bool theory_seq::check_int_string() {
bool theory_seq::check_int_string(expr* e) {
return
get_context().inconsistent() ||
(m_util.str.is_itos(e) && add_itos_val_axiom(e)) ||
(m_util.str.is_stoi(e) && add_stoi_val_axiom(e));
}
@ -3410,9 +3410,33 @@ void theory_seq::add_stoi_axiom(expr* e) {
// stoi(s) >= -1
literal l = mk_simplified_literal(m_autil.mk_ge(e, m_autil.mk_int(-1)));
add_axiom(l);
// stoi("") = -1
add_axiom(mk_eq(m_util.str.mk_stoi(m_util.str.mk_empty(m.get_sort(s))), m_autil.mk_int(-1), false));
}
void theory_seq::add_itos_axiom(expr* e) {
rational val;
expr* n = nullptr;
TRACE("seq", tout << mk_pp(e, m) << "\n";);
VERIFY(m_util.str.is_itos(e, n));
// itos(n) = "" <=> n < 0
expr_ref zero(m_autil.mk_int(0), m);
literal eq1 = mk_literal(m_util.str.mk_is_empty(e));
literal ge0 = mk_literal(m_autil.mk_ge(n, zero));
// n >= 0 => itos(n) != ""
// itos(n) = "" or n >= 0
add_axiom(~eq1, ~ge0);
add_axiom(eq1, ge0);
// n >= 0 => stoi(itos(n)) = n
app_ref stoi(m_util.str.mk_stoi(e), m);
add_axiom(~ge0, mk_preferred_eq(stoi, n));
}
void theory_seq::ensure_digit_axiom() {
if (m_si_axioms.empty()) {
@ -3425,7 +3449,7 @@ void theory_seq::ensure_digit_axiom() {
}
bool theory_seq::add_itos_val_axiom(expr* e) {
rational val;
rational val, val2;
expr* n = nullptr;
TRACE("seq", tout << mk_pp(e, m) << "\n";);
VERIFY(m_util.str.is_itos(e, n));
@ -3435,11 +3459,11 @@ bool theory_seq::add_itos_val_axiom(expr* e) {
}
enforce_length(e);
if (get_length(e, val) && val.is_pos() && val.is_unsigned() && !m_si_axioms.contains(e)) {
if (get_length(e, val) && val.is_pos() && val.is_unsigned() && (!m_si_axioms.find(e, val2) || val != val2)) {
add_si_axiom(e, n, val.get_unsigned());
m_si_axioms.insert(e);
m_si_axioms.insert(e, val);
m_trail_stack.push(push_replay(alloc(replay_is_axiom, m, e)));
m_trail_stack.push(insert_map<theory_seq, obj_hashtable<expr>, expr*>(m_si_axioms, e));
m_trail_stack.push(insert_map<theory_seq, obj_map<expr, rational>, expr*>(m_si_axioms, e));
return true;
}
@ -3449,20 +3473,21 @@ bool theory_seq::add_itos_val_axiom(expr* e) {
bool theory_seq::add_stoi_val_axiom(expr* e) {
context& ctx = get_context();
expr* n = nullptr;
rational val;
TRACE("seq", tout << mk_pp(e, m) << " " << ctx.get_scope_level () << "\n";);
rational val, val2;
VERIFY(m_util.str.is_stoi(e, n));
TRACE("seq", tout << mk_pp(e, m) << " " << ctx.get_scope_level () << " " << get_length(n, val) << " " << val << "\n";);
if (m_util.str.is_itos(n)) {
return false;
}
enforce_length(n);
if (get_length(n, val) && val.is_pos() && val.is_unsigned() && !m_si_axioms.contains(e)) {
if (get_length(n, val) && val.is_pos() && val.is_unsigned() && (!m_si_axioms.find(e, val2) || val2 != val)) {
add_si_axiom(n, e, val.get_unsigned());
m_si_axioms.insert(e);
m_si_axioms.insert(e, val);
m_trail_stack.push(push_replay(alloc(replay_is_axiom, m, e)));
m_trail_stack.push(insert_map<theory_seq, obj_hashtable<expr>, expr*>(m_si_axioms, e));
m_trail_stack.push(insert_map<theory_seq, obj_map<expr, rational>, expr*>(m_si_axioms, e));
return true;
}
@ -3487,26 +3512,6 @@ expr_ref theory_seq::digit2int(expr* ch) {
return expr_ref(mk_skolem(symbol("seq.digit2int"), ch, nullptr, nullptr, nullptr, m_autil.mk_int()), m);
}
void theory_seq::add_itos_axiom(expr* e) {
rational val;
expr* n = nullptr;
TRACE("seq", tout << mk_pp(e, m) << "\n";);
VERIFY(m_util.str.is_itos(e, n));
// itos(n) = "" <=> n < 0
expr_ref zero(arith_util(m).mk_int(0), m);
literal eq1 = mk_literal(m_util.str.mk_is_empty(e));
literal ge0 = mk_literal(m_autil.mk_ge(n, zero));
// n >= 0 => itos(n) != ""
// itos(n) = "" or n >= 0
add_axiom(~eq1, ~ge0);
add_axiom(eq1, ge0);
// n >= 0 => stoi(itos(n)) = n
app_ref stoi(m_util.str.mk_stoi(e), m);
add_axiom(~ge0, mk_preferred_eq(stoi, n));
}
// n >= 0 & len(e) = k => is_digit(e_i) for i = 0..k-1
@ -3550,7 +3555,7 @@ void theory_seq::add_si_axiom(expr* e, expr* n, unsigned k) {
SASSERT(k > 0);
rational lb = power(rational(10), k - 1);
rational ub = power(rational(10), k) - 1;
arith_util a (m);
arith_util& a = m_autil;
literal lbl = mk_literal(a.mk_ge(n, a.mk_int(lb)));
literal ubl = mk_literal(a.mk_le(n, a.mk_int(ub)));
literal ge_k = mk_literal(a.mk_ge(len, a.mk_int(k)));