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:
parent
386399472d
commit
f414869456
8 changed files with 428 additions and 32 deletions
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue