3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-10-08 17:01:55 +00:00

delay digit axioms until solving itos succeeds

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-04-20 00:32:48 -07:00
parent e3e6959b70
commit dd064a5554
4 changed files with 179 additions and 180 deletions

View file

@ -980,6 +980,7 @@ bool theory_seq::solve_itos(expr* n, expr_ref_vector const& rs, dependency* dep)
propagate_lit(dep, 0, nullptr, lit);
return true;
}
expr_ref num(m), digit(m);
expr* u = nullptr;
for (expr* r : rs) {
@ -992,8 +993,12 @@ bool theory_seq::solve_itos(expr* n, expr_ref_vector const& rs, dependency* dep)
else {
num = m_autil.mk_add(m_autil.mk_mul(m_autil.mk_int(10), num), digit);
}
}
for (expr* r : rs) {
VERIFY(m_util.str.is_unit(r, u));
propagate_lit(dep, 0, nullptr, m_ax.is_digit(u));
}
propagate_lit(dep, 0, nullptr, mk_simplified_literal(m.mk_eq(n, num)));
if (rs.size() > 1) {
VERIFY (m_util.str.is_unit(rs[0], u));
@ -1017,55 +1022,6 @@ bool theory_seq::reduce_length(expr* l, expr* r, literal_vector& lits) {
}
}
bool theory_seq::solve_unit_eq(expr* l, expr* r, dependency* deps) {
if (l == r) {
return true;
}
if (is_var(l) && !occurs(l, r) && add_solution(l, r, deps)) {
return true;
}
if (is_var(r) && !occurs(r, l) && add_solution(r, l, deps)) {
return true;
}
return false;
}
bool theory_seq::occurs(expr* a, expr_ref_vector const& b) {
for (auto const& elem : b) {
if (a == elem || m.is_ite(elem)) return true;
}
return false;
}
bool theory_seq::occurs(expr* a, expr* b) {
// true if a occurs under an interpreted function or under left/right selector.
SASSERT(is_var(a));
SASSERT(m_todo.empty());
expr* e1 = nullptr, *e2 = nullptr;
m_todo.push_back(b);
while (!m_todo.empty()) {
b = m_todo.back();
if (a == b || m.is_ite(b)) {
m_todo.reset();
return true;
}
m_todo.pop_back();
if (m_util.str.is_concat(b, e1, e2)) {
m_todo.push_back(e1);
m_todo.push_back(e2);
}
else if (m_util.str.is_unit(b, e1)) {
m_todo.push_back(e1);
}
else if (m_util.str.is_nth_i(b, e1, e2)) {
m_todo.push_back(e1);
}
}
return false;
}
bool theory_seq::is_var(expr* a) const {
return
@ -1234,64 +1190,6 @@ bool theory_seq::reduce_length(unsigned i, unsigned j, bool front, expr_ref_vect
}
}
bool theory_seq::solve_binary_eq(expr_ref_vector const& ls, expr_ref_vector const& rs, dependency* dep) {
context& ctx = get_context();
ptr_vector<expr> xs, ys;
expr_ref x(m), y(m);
bool is_binary = is_binary_eq(ls, rs, x, xs, ys, y);
if (!is_binary) {
is_binary = is_binary_eq(rs, ls, x, xs, ys, y);
}
if (!is_binary) {
return false;
}
// Equation is of the form x ++ xs = ys ++ y
// where xs, ys are units.
if (x != y) {
return false;
}
if (xs.size() != ys.size()) {
TRACE("seq", tout << "binary conflict\n";);
set_conflict(dep);
return false;
}
if (xs.empty()) {
// this should have been solved already
UNREACHABLE();
return false;
}
// Equation is of the form x ++ xs = ys ++ x
// where |xs| = |ys| are units of same length
// then xs is a wrap-around of ys
// x ++ ab = ba ++ x
//
if (xs.size() == 1) {
enode* n1 = ensure_enode(xs[0]);
enode* n2 = ensure_enode(ys[0]);
if (n1->get_root() == n2->get_root()) {
return false;
}
literal eq = mk_eq(xs[0], ys[0], false);
switch (ctx.get_assignment(eq)) {
case l_false: {
literal_vector conflict;
conflict.push_back(~eq);
TRACE("seq", tout << conflict << "\n";);
set_conflict(dep, conflict);
break;
}
case l_true:
break;
case l_undef:
ctx.mark_as_relevant(eq);
propagate_lit(dep, 0, nullptr, eq);
m_new_propagation = true;
break;
}
}
return false;
}
bool theory_seq::get_length(expr* e, expr_ref& len, literal_vector& lits) {
context& ctx = get_context();