3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 20:05:51 +00:00

add symbolic automaton

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2015-12-23 19:46:10 -08:00
parent 386399472d
commit f414869456
8 changed files with 428 additions and 32 deletions

View file

@ -125,6 +125,7 @@ theory_seq::theory_seq(ast_manager& m):
m_rep(m, m_dm),
m_factory(0),
m_ineqs(m),
m_in_re(m),
m_exclude(m),
m_axioms(m),
m_axioms_head(0),
@ -379,6 +380,9 @@ bool theory_seq::is_solved() {
if (!check_ineq_coherence()) {
return false;
}
if (!m_in_re.empty()) {
return false;
}
SASSERT(check_length_coherence());
@ -572,7 +576,6 @@ bool theory_seq::solve_nqs() {
bool change = false;
context & ctx = get_context();
for (unsigned i = 0; !ctx.inconsistent() && i < m_nqs.size(); ++i) {
TRACE("seq", tout << i << " " << m_nqs.size() << "\n";);
if (!m_nqs[i].is_solved()) {
change = solve_ne(i) || change;
}
@ -637,6 +640,16 @@ bool theory_seq::solve_ne(unsigned idx) {
literal lit(mk_eq(nl, nr, false));
m_trail_stack.push(push_lit(*this, idx, lit));
ctx.mark_as_relevant(lit);
switch (ctx.get_assignment(lit)) {
case l_false:
mark_solved(idx);
return false;
case l_true:
break;
case l_undef:
++num_undef_lits;
break;
}
}
}
m_trail_stack.push(push_dep(*this, idx, deps));
@ -696,6 +709,8 @@ bool theory_seq::internalize_term(app* term) {
if (m.is_bool(term)) {
bool_var bv = ctx.mk_bool_var(term);
ctx.set_var_theory(bv, get_id());
ctx.mark_as_relevant(bv);
TRACE("seq", tout << mk_pp(term, m) << ": " << bv << "\n";);
}
else {
enode* e = 0;
@ -751,6 +766,12 @@ void theory_seq::display(std::ostream & out) const {
out << mk_pp(m_ineqs[i], m) << "\n";
}
}
if (!m_in_re.empty()) {
out << "Regex\n";
for (unsigned i = 0; i < m_in_re.size(); ++i) {
out << mk_pp(m_in_re[i], m) << "\n";
}
}
if (!m_rep.empty()) {
out << "Solved equations:\n";
m_rep.display(out);
@ -917,7 +938,12 @@ expr_ref theory_seq::expand(expr* e0, enode_pair_dependency*& eqs) {
enode* n = get_context().get_enode(e)->get_root();
result = n->get_owner();
if (!m.is_model_value(result)) {
result = m_mg->get_some_value(m.get_sort(result));
if (m_util.is_char(result)) {
result = m_util.str.mk_char('#');
}
else {
result = m_mg->get_some_value(m.get_sort(result));
}
}
m_rep.update(e, result, 0);
TRACE("seq", tout << mk_pp(e, m) << " |-> " << result << "\n";);
@ -1288,13 +1314,16 @@ expr_ref theory_seq::mk_skolem(symbol const& name, expr* e1,
void theory_seq::propagate_eq(bool_var v, expr* e1, expr* e2) {
context& ctx = get_context();
TRACE("seq",
tout << mk_pp(ctx.bool_var2enode(v)->get_owner(), m) << " => "
<< mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
SASSERT(ctx.e_internalized(e2));
enode* n1 = ensure_enode(e1);
enode* n2 = ensure_enode(e2);
if (n1->get_root() == n2->get_root()) {
return;
}
TRACE("seq",
tout << mk_pp(ctx.bool_var2enode(v)->get_owner(), m) << " => "
<< mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
literal lit(v);
justification* js =
ctx.mk_justification(
@ -1304,10 +1333,9 @@ void theory_seq::propagate_eq(bool_var v, expr* e1, expr* e2) {
ctx.assign_eq(n1, n2, eq_justification(js));
}
void theory_seq::assign_eq(bool_var v, bool is_true) {
void theory_seq::assign_eh(bool_var v, bool is_true) {
context & ctx = get_context();
enode* n = ctx.bool_var2enode(v);
app* e = n->get_owner();
expr* e = ctx.bool_var2expr(v);
if (is_true) {
expr* e1, *e2;
expr_ref f(m);
@ -1327,8 +1355,10 @@ void theory_seq::assign_eq(bool_var v, bool is_true) {
f = m_util.str.mk_concat(m_util.str.mk_concat(f1, e2), f2);
propagate_eq(v, f, e1);
}
else if (m_util.str.is_in_re(e, e1, e2)) {
// TBD
else if (m_util.str.is_in_re(e)) {
TRACE("seq", tout << "in re: " << mk_pp(e, m) << "\n";);
m_trail_stack.push(push_back_vector<theory_seq, expr_ref_vector>(m_in_re));
m_in_re.push_back(e);
}
else {
UNREACHABLE();
@ -1403,4 +1433,22 @@ void theory_seq::relevant_eh(app* n) {
m_util.str.is_string(n)) {
enque_axiom(n);
}
if (m_util.str.is_in_re(n) ||
m_util.str.is_contains(n) ||
m_util.str.is_suffix(n) ||
m_util.str.is_prefix(n)) {
context& ctx = get_context();
TRACE("seq", tout << mk_pp(n, m) << "\n";);
bool_var bv = ctx.get_bool_var(n);
switch (ctx.get_assignment(bv)) {
case l_false:
assign_eh(bv, false);
break;
case l_true:
assign_eh(bv, true);
break;
case l_undef:
break;
}
}
}