3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-15 23:35:26 +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

@ -1382,7 +1382,8 @@ namespace smt {
bool_var v = l.var();
bool_var_data & d = get_bdata(v);
lbool val = get_assignment(v);
TRACE("propagate_atoms", tout << "propagating atom, #" << bool_var2expr(v)->get_id() << ", is_enode(): " << d.is_enode() << " " << l << "\n";);
TRACE("propagate_atoms", tout << "propagating atom, #" << bool_var2expr(v)->get_id() << ", is_enode(): " << d.is_enode()
<< " tag: " << (d.is_eq()?"eq":"") << (d.is_theory_atom()?"th":"") << (d.is_quantifier()?"q":"") << " " << l << "\n";);
SASSERT(val != l_undef);
if (d.is_enode())
propagate_bool_var_enode(v);
@ -1404,6 +1405,7 @@ namespace smt {
else if (d.is_theory_atom()) {
theory * th = m_theories.get_plugin(d.get_theory());
SASSERT(th);
TRACE("seq", tout << d.get_theory() << "\n";);
th->assign_eh(v, val == l_true);
}
else if (d.is_quantifier()) {

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;
}
}
}

View file

@ -251,6 +251,7 @@ namespace smt {
seq_factory* m_factory; // value factory
expr_ref_vector m_ineqs; // inequalities to check solution against
expr_ref_vector m_in_re; // regular expression membership
exclusion_table m_exclude; // set of asserted disequalities.
expr_ref_vector m_axioms; // list of axioms to add.
unsigned m_axioms_head; // index of first axiom to add.
@ -277,7 +278,7 @@ namespace smt {
virtual void internalize_eq_eh(app * atom, bool_var v);
virtual void new_eq_eh(theory_var, theory_var);
virtual void new_diseq_eh(theory_var, theory_var);
virtual void assign_eq(bool_var v, bool is_true);
virtual void assign_eh(bool_var v, bool is_true);
virtual bool can_propagate();
virtual void propagate();
virtual void push_scope_eh();