mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
optimize for enumeration datatypes
This commit is contained in:
parent
caae0ba569
commit
f725989225
4 changed files with 125 additions and 82 deletions
|
@ -483,7 +483,7 @@ namespace smt {
|
|||
for (int v = 0; v < num_vars; v++) {
|
||||
if (v == static_cast<int>(m_find.find(v))) {
|
||||
enode * node = get_enode(v);
|
||||
if (!oc_cycle_free(node) && occurs_check(node)) {
|
||||
if (m_util.is_recursive(node->get_sort()) && !oc_cycle_free(node) && occurs_check(node)) {
|
||||
// conflict was detected...
|
||||
// return...
|
||||
return FC_CONTINUE;
|
||||
|
@ -956,6 +956,10 @@ namespace smt {
|
|||
v = m_find.find(v);
|
||||
enode * n = get_enode(v);
|
||||
sort * s = n->get_sort();
|
||||
if (m_util.is_enum_sort(s)) {
|
||||
mk_enum_split(v);
|
||||
return;
|
||||
}
|
||||
func_decl * non_rec_c = m_util.get_non_rec_constructor(s);
|
||||
unsigned non_rec_idx = m_util.get_constructor_idx(non_rec_c);
|
||||
var_data * d = m_var_data[v];
|
||||
|
@ -1015,4 +1019,55 @@ namespace smt {
|
|||
ctx.mark_as_relevant(bv);
|
||||
}
|
||||
|
||||
literal theory_datatype::mk_recognizer_constructor_literal(func_decl* c, enode* n) {
|
||||
func_decl* r = m_util.get_constructor_is(c);
|
||||
app_ref r_app(m.mk_app(r, n->get_expr()), m);
|
||||
bool_var bv = ctx.get_bool_var(r_app);
|
||||
ctx.set_true_first_flag(bv);
|
||||
ctx.mark_as_relevant(bv);
|
||||
return literal(bv, false);
|
||||
}
|
||||
|
||||
|
||||
void theory_datatype::mk_enum_split(theory_var v) {
|
||||
enode* n = get_enode(v);
|
||||
var_data* d = m_var_data[v];
|
||||
sort* srt = n->get_sort();
|
||||
auto const& constructors = *m_util.get_datatype_constructors(srt);
|
||||
unsigned sz = constructors.size();
|
||||
int start = ctx.get_random_value();
|
||||
m_lits.reset();
|
||||
literal lit;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned j = (i + start) % sz;
|
||||
func_decl* c = constructors[j];
|
||||
if (c->get_arity() > 0) {
|
||||
enode* curr = d->m_recognizers.get(j, nullptr);
|
||||
if (curr && ctx.get_assignment(curr) != l_false)
|
||||
return;
|
||||
lit = mk_recognizer_constructor_literal(c, n);
|
||||
if (!curr)
|
||||
return;
|
||||
if (ctx.get_assignment(lit) != l_false)
|
||||
return;
|
||||
m_lits.push_back(~lit);
|
||||
}
|
||||
else {
|
||||
lit = mk_eq(n->get_expr(), m.mk_const(c), false);
|
||||
switch (ctx.get_assignment(lit)) {
|
||||
case l_undef:
|
||||
ctx.set_true_first_flag(lit.var());
|
||||
return;
|
||||
case l_true:
|
||||
return;
|
||||
case l_false:
|
||||
m_lits.push_back(~lit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
region& reg = ctx.get_region();
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), reg, m_lits.size(), m_lits.c_ptr(), 0, nullptr)));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace smt {
|
|||
enode_pair_vector m_used_eqs; // conflict, if any
|
||||
parent_tbl m_parent; // parent explanation for occurs_check
|
||||
svector<stack_entry> m_stack; // stack for DFS for occurs_check
|
||||
literal_vector m_lits;
|
||||
|
||||
void clear_mark();
|
||||
|
||||
|
@ -108,6 +109,8 @@ namespace smt {
|
|||
void explain_is_child(enode* parent, enode* child);
|
||||
|
||||
void mk_split(theory_var v);
|
||||
literal mk_recognizer_constructor_literal(func_decl* c, enode* n);
|
||||
void mk_enum_split(theory_var v);
|
||||
|
||||
void display_var(std::ostream & out, theory_var v) const;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue