3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-04 10:20:23 +00:00

zero-length automaton solution fix

This commit is contained in:
Murphy Berzish 2018-01-18 17:52:55 -05:00
parent dbb15f65b5
commit 5727950a3c

View file

@ -9811,12 +9811,7 @@ namespace smt {
continue;
}
if (exact_length_value.is_zero()) {
// shortcut
expr_ref lhs(ctx.mk_eq_atom(mk_strlen(str), m_autil.mk_numeral(rational::zero(), true)), m);
expr_ref rhs(ctx.mk_eq_atom(str, mk_string("")), m);
assert_implication(lhs, rhs);
} else {
// find a consistent automaton for this term
bool found = false;
regex_automaton_under_assumptions assumption;
@ -9838,6 +9833,63 @@ namespace smt {
} // foreach(a in regex_automaton_assumptions)
}
if (found) {
if (exact_length_value.is_zero()) {
// check consistency of 0-length solution with automaton
eautomaton * aut = assumption.get_automaton();
bool zero_solution = false;
unsigned initial_state = aut->init();
if (aut->is_final_state(initial_state)) {
zero_solution = true;
} else {
unsigned_vector eps_states;
aut->get_epsilon_closure(initial_state, eps_states);
for (unsigned_vector::iterator it = eps_states.begin(); it != eps_states.end(); ++it) {
unsigned state = *it;
if (aut->is_final_state(state)) {
zero_solution = true;
break;
}
}
}
// now check polarity of automaton wrt. original term
if ( (current_assignment == l_true && !assumption.get_polarity())
|| (current_assignment == l_false && assumption.get_polarity())) {
// invert sense
NOT_IMPLEMENTED_YET();
}
if (zero_solution) {
TRACE("str", tout << "zero-length solution OK -- asserting empty path constraint" << std::endl;);
expr_ref_vector lhs_terms(m);
if (current_assignment == l_true) {
lhs_terms.push_back(str_in_re);
} else {
lhs_terms.push_back(m.mk_not(str_in_re));
}
lhs_terms.push_back(ctx.mk_eq_atom(mk_strlen(str), m_autil.mk_numeral(exact_length_value, true)));
expr_ref lhs(mk_and(lhs_terms), m);
expr_ref rhs(ctx.mk_eq_atom(str, mk_string("")), m);
assert_implication(lhs, rhs);
regex_terms_with_path_constraints.insert(str_in_re);
m_trail_stack.push(insert_obj_trail<theory_str, expr>(regex_terms_with_path_constraints, str_in_re));
} else {
TRACE("str", tout << "zero-length solution not admitted by this automaton -- asserting conflict clause" << std::endl;);
expr_ref_vector lhs_terms(m);
if (current_assignment == l_true) {
lhs_terms.push_back(str_in_re);
} else {
lhs_terms.push_back(m.mk_not(str_in_re));
}
lhs_terms.push_back(ctx.mk_eq_atom(mk_strlen(str), m_autil.mk_numeral(exact_length_value, true)));
expr_ref lhs(mk_and(lhs_terms), m);
expr_ref conflict(m.mk_not(lhs), m);
assert_axiom(conflict);
}
regex_axiom_add = true;
regex_inc_counter(regex_length_attempt_count, re);
continue;
} else {
expr_ref pathConstraint(m);
expr_ref characterConstraints(m);
pathConstraint = generate_regex_path_constraints(str, assumption.get_automaton(), exact_length_value, characterConstraints);
@ -9877,6 +9929,7 @@ namespace smt {
}
continue;
}
} else {
// no automata available, or else all bounds assumptions are invalid
unsigned expected_complexity = estimate_regex_complexity(re);
@ -9899,7 +9952,6 @@ namespace smt {
}
continue;
}
} // !length is zero
} // get_len_value()
expr_ref str_len(mk_strlen(str), m);
rational lower_bound_value;