Skip to content

Commit 4d54b41

Browse files
1 parent e67112f commit 4d54b41

File tree

2 files changed

+90
-11
lines changed

2 files changed

+90
-11
lines changed

src/ast/rewriter/seq_rewriter.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,17 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
882882
if (offset == 0 && _pos > 0) {
883883
return BR_FAILED;
884884
}
885+
std::function<bool(expr*)> is_unit = [&](expr *e) { return m_util.str.is_unit(e); };
886+
887+
if (_pos == 0 && as.forall(is_unit)) {
888+
result = m_util.str.mk_empty(m().get_sort(a));
889+
for (unsigned i = 1; i <= as.size(); ++i) {
890+
result = m().mk_ite(m_autil.mk_ge(c, m_autil.mk_int(i)),
891+
m_util.str.mk_concat(i, as.c_ptr(), m().get_sort(a)),
892+
result);
893+
}
894+
return BR_REWRITE_FULL;
895+
}
885896
if (_pos == 0 && !constantLen) {
886897
return BR_FAILED;
887898
}
@@ -1736,6 +1747,50 @@ br_status seq_rewriter::mk_str_stoi(expr* a, expr_ref& result) {
17361747
result = m().mk_ite(m_autil.mk_ge(b, zero()), b, minus_one());
17371748
return BR_DONE;
17381749
}
1750+
expr* c = nullptr, *t = nullptr, *e = nullptr;
1751+
if (m().is_ite(a, c, t, e)) {
1752+
result = m().mk_ite(c, m_util.str.mk_stoi(t), m_util.str.mk_stoi(e));
1753+
return BR_REWRITE_FULL;
1754+
}
1755+
1756+
expr* u = nullptr;
1757+
unsigned ch = 0;
1758+
if (m_util.str.is_unit(a, u) && m_util.is_const_char(u, ch)) {
1759+
if ('0' <= ch && ch <= '9') {
1760+
result = m_autil.mk_int(ch - '0');
1761+
}
1762+
else {
1763+
result = m_autil.mk_int(-1);
1764+
}
1765+
return BR_DONE;
1766+
}
1767+
1768+
expr_ref_vector as(m());
1769+
m_util.str.get_concat_units(a, as);
1770+
if (as.empty()) {
1771+
result = m_autil.mk_int(-1);
1772+
return BR_DONE;
1773+
}
1774+
if (m_util.str.is_unit(as.back())) {
1775+
// if head = "" then tail else
1776+
// if tail < 0 then tail else
1777+
// if stoi(head) >= 0 and then stoi(head)*10+tail else -1
1778+
expr_ref tail(m_util.str.mk_stoi(as.back()), m());
1779+
expr_ref head(m_util.str.mk_concat(as.size() - 1, as.c_ptr(), m().get_sort(a)), m());
1780+
expr_ref stoi_head(m_util.str.mk_stoi(head), m());
1781+
result = m().mk_ite(m_autil.mk_ge(stoi_head, m_autil.mk_int(0)),
1782+
m_autil.mk_add(m_autil.mk_mul(m_autil.mk_int(10), stoi_head), tail),
1783+
m_autil.mk_int(-1));
1784+
1785+
result = m().mk_ite(m_autil.mk_ge(tail, m_autil.mk_int(0)),
1786+
result,
1787+
tail);
1788+
result = m().mk_ite(m_util.str.mk_is_empty(head),
1789+
tail,
1790+
result);
1791+
return BR_REWRITE_FULL;
1792+
}
1793+
17391794
return BR_FAILED;
17401795
}
17411796

src/smt/seq_axioms.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -563,21 +563,32 @@ void seq_axioms::add_itos_axiom(expr* e) {
563563
/**
564564
stoi(s) >= -1
565565
stoi("") = -1
566+
stoi(s) >= 0 => len(s) > 0
567+
stoi(s) >= 0 => is_digit(nth(s,0))
566568
*/
567569
void seq_axioms::add_stoi_axiom(expr* e) {
568570
TRACE("seq", tout << mk_pp(e, m) << "\n";);
569571
expr* s = nullptr;
570572
VERIFY (seq.str.is_stoi(e, s));
571-
add_axiom(mk_ge(e, -1));
572-
add_axiom(~mk_literal(seq.str.mk_is_empty(s)), mk_eq(seq.str.mk_stoi(s), a.mk_int(-1)));
573+
add_axiom(mk_ge(e, -1)); // stoi(s) >= -1
574+
add_axiom(~mk_eq_empty(s), mk_eq(e, a.mk_int(-1))); // s = "" => stoi(s) = -1
575+
literal ge0 = mk_ge(e, 0);
576+
add_axiom(~ge0, is_digit(mk_nth(s, 0))); // stoi(s) >= 0 => is_digit(nth(s,0))
577+
573578
}
574579

575580
/**
576581
577-
stoi(s) >= 0, len(s) <= k => stoi(s) = stoi(s, k)
578-
len(s) > 0 => stoi(s, 0) = digit(nth_i(s, 0))
582+
len(s) <= k => stoi(s) = stoi(s, k)
583+
len(s) > 0, is_digit(nth(s,0)) => stoi(s, 0) = digit(nth_i(s, 0))
584+
len(s) > 0, ~is_digit(nth(s,0)) => stoi(s, 0) = -1
585+
579586
0 < i, len(s) <= i => stoi(s, i) = stoi(s, i - 1)
580-
0 < i, len(s) > i => stoi(s, i) = 10*stoi(s, i - 1) + digit(nth_i(s, i - 1))
587+
0 < i, len(s) > i, stoi(s, i - 1) >= 0, is_digit(nth(s, i - 1)) => stoi(s, i) = 10*stoi(s, i - 1) + digit(nth_i(s, i - 1))
588+
0 < i, len(s) > i, stoi(s, i - 1) < 0 => stoi(s, i) = -1
589+
0 < i, len(s) > i, ~is_digit(nth(s, i - 1)) => stoi(s, i) = -1
590+
591+
581592
582593
Define auxiliary function with the property:
583594
for 0 <= i < k
@@ -599,17 +610,30 @@ void seq_axioms::add_stoi_axiom(expr* e, unsigned k) {
599610
m_rewrite(s);
600611
auto stoi2 = [&](unsigned j) { return m_sk.mk("seq.stoi", s, a.mk_int(j), a.mk_int()); };
601612
auto digit = [&](unsigned j) { return m_sk.mk_digit2int(mk_nth(s, j)); };
613+
auto is_digit_ = [&](unsigned j) { return is_digit(mk_nth(s, j)); };
602614
expr_ref len = mk_len(s);
603615
literal ge0 = mk_ge(e, 0);
604616
literal lek = mk_le(len, k);
605-
add_axiom(~ge0, ~mk_eq(len, a.mk_int(0)));
606-
add_axiom(~ge0, ~lek, mk_eq(e, stoi2(k-1)));
607-
add_axiom(mk_le(len, 0), mk_eq(stoi2(0), digit(0)));
608-
add_axiom(~ge0, is_digit(mk_nth(s, 0)));
617+
add_axiom(~lek, mk_eq(e, stoi2(k-1))); // len(s) <= k => stoi(s) = stoi(s, k-1)
618+
add_axiom(mk_le(len, 0), ~is_digit_(0), mk_eq(stoi2(0), digit(0))); // len(s) > 0, is_digit(nth(s, 0)) => stoi(s,0) = digit(s,0)
619+
add_axiom(mk_le(len, 0), is_digit_(0), mk_eq(stoi2(0), a.mk_int(-1))); // len(s) > 0, ~is_digit(nth(s, 0)) => stoi(s,0) = -1
609620
for (unsigned i = 1; i < k; ++i) {
610-
add_axiom(mk_le(len, i), mk_eq(stoi2(i), a.mk_add(a.mk_mul(a.mk_int(10), stoi2(i-1)), digit(i))));
621+
622+
// len(s) <= i => stoi(s, i) = stoi(s, i - 1)
623+
611624
add_axiom(~mk_le(len, i), mk_eq(stoi2(i), stoi2(i-1)));
612-
add_axiom(~ge0, mk_le(len, i), is_digit(mk_nth(s, i)));
625+
626+
// len(s) > i, stoi(s, i - 1) >= 0, is_digit(nth(s, i)) => stoi(s, i) = 10*stoi(s, i - 1) + digit(i)
627+
// len(s) > i, stoi(s, i - 1) < 0 => stoi(s, i) = -1
628+
// len(s) > i, ~is_digit(nth(s, i)) => stoi(s, i) = -1
629+
630+
add_axiom(mk_le(len, i), ~mk_ge(stoi2(i-1), 0), ~is_digit_(i), mk_eq(stoi2(i), a.mk_add(a.mk_mul(a.mk_int(10), stoi2(i-1)), digit(i))));
631+
add_axiom(mk_le(len, i), is_digit_(i), mk_eq(stoi2(i), a.mk_int(-1)));
632+
add_axiom(mk_le(len, i), mk_ge(stoi2(i-1), 0), mk_eq(stoi2(i), a.mk_int(-1)));
633+
634+
// stoi(s) >= 0, i < len(s) => is_digit(nth(s, i))
635+
636+
add_axiom(~ge0, mk_le(len, i), is_digit_(i));
613637
}
614638
}
615639

0 commit comments

Comments
 (0)