mirror of
https://github.com/Z3Prover/z3
synced 2025-06-26 07:43:41 +00:00
perf improvements to solve-eqs and euf-completion
This commit is contained in:
parent
2c7799939e
commit
6662afdd26
4 changed files with 129 additions and 51 deletions
|
@ -58,31 +58,43 @@ namespace euf {
|
|||
}
|
||||
|
||||
void completion::reduce() {
|
||||
unsigned rounds = 0;
|
||||
do {
|
||||
++m_epoch;
|
||||
++rounds;
|
||||
m_has_new_eq = false;
|
||||
add_egraph();
|
||||
map_canonical();
|
||||
read_egraph();
|
||||
IF_VERBOSE(11, verbose_stream() << "(euf.completion :rounds " << rounds << ")\n");
|
||||
}
|
||||
while (m_has_new_eq);
|
||||
while (m_has_new_eq && rounds <= 3);
|
||||
}
|
||||
|
||||
void completion::add_egraph() {
|
||||
m_nodes.reset();
|
||||
m_nodes_to_canonize.reset();
|
||||
unsigned sz = m_fmls.size();
|
||||
auto add_children = [&](enode* n) {
|
||||
for (auto* ch : enode_args(n))
|
||||
m_nodes_to_canonize.push_back(ch);
|
||||
};
|
||||
|
||||
for (unsigned i = m_qhead; i < sz; ++i) {
|
||||
auto [f,d] = m_fmls[i]();
|
||||
auto* n = mk_enode(f);
|
||||
if (m.is_eq(f)) {
|
||||
m_egraph.merge(n->get_arg(0), n->get_arg(1), d);
|
||||
m_nodes.push_back(n->get_arg(0));
|
||||
m_nodes.push_back(n->get_arg(1));
|
||||
add_children(n->get_arg(0));
|
||||
add_children(n->get_arg(1));
|
||||
}
|
||||
if (m.is_not(f))
|
||||
if (m.is_not(f)) {
|
||||
m_egraph.merge(n->get_arg(0), m_ff, d);
|
||||
else
|
||||
add_children(n->get_arg(0));
|
||||
}
|
||||
else {
|
||||
m_egraph.merge(n, m_tt, d);
|
||||
add_children(n);
|
||||
}
|
||||
}
|
||||
m_egraph.propagate();
|
||||
}
|
||||
|
@ -106,15 +118,7 @@ namespace euf {
|
|||
m_fmls.update(i, dependent_expr(m, g, dep));
|
||||
m_stats.m_num_rewrites++;
|
||||
IF_VERBOSE(11, verbose_stream() << mk_bounded_pp(f, m, 3) << " -> " << mk_bounded_pp(g, m, 3) << "\n");
|
||||
expr* x, * y;
|
||||
if (m.is_eq(g, x, y) && new_eq(x, y))
|
||||
m_has_new_eq = true;
|
||||
if (m.is_and(g) && !m_has_new_eq)
|
||||
for (expr* arg : *to_app(g))
|
||||
if (m.is_eq(arg, x, y))
|
||||
m_has_new_eq |= new_eq(x, y);
|
||||
else if (!m.is_true(arg))
|
||||
m_has_new_eq = true;
|
||||
update_has_new_eq(g);
|
||||
}
|
||||
CTRACE("euf_completion", g != f, tout << mk_bounded_pp(f, m) << " -> " << mk_bounded_pp(g, m) << "\n");
|
||||
}
|
||||
|
@ -122,12 +126,34 @@ namespace euf {
|
|||
advance_qhead(m_fmls.size());
|
||||
}
|
||||
|
||||
bool completion::new_eq(expr* a, expr* b) {
|
||||
bool completion::is_new_eq(expr* a, expr* b) {
|
||||
enode* na = m_egraph.find(a);
|
||||
enode* nb = m_egraph.find(b);
|
||||
if (!na)
|
||||
IF_VERBOSE(11, verbose_stream() << "not internalied " << mk_bounded_pp(a, m) << "\n");
|
||||
if (!nb)
|
||||
IF_VERBOSE(11, verbose_stream() << "not internalied " << mk_bounded_pp(b, m) << "\n");
|
||||
if (na && nb && na->get_root() != nb->get_root())
|
||||
IF_VERBOSE(11, verbose_stream() << m_egraph.bpp(na) << " " << m_egraph.bpp(nb) << "\n");
|
||||
return !na || !nb || na->get_root() != nb->get_root();
|
||||
}
|
||||
|
||||
void completion::update_has_new_eq(expr* g) {
|
||||
expr* x, * y;
|
||||
if (m_has_new_eq)
|
||||
return;
|
||||
else if (m.is_eq(g, x, y))
|
||||
m_has_new_eq |= is_new_eq(x, y);
|
||||
else if (m.is_and(g)) {
|
||||
for (expr* arg : *to_app(g))
|
||||
update_has_new_eq(arg);
|
||||
}
|
||||
else if (m.is_not(g, g))
|
||||
m_has_new_eq |= is_new_eq(g, m.mk_false());
|
||||
else
|
||||
m_has_new_eq |= is_new_eq(g, m.mk_true());
|
||||
}
|
||||
|
||||
enode* completion::mk_enode(expr* e) {
|
||||
m_todo.push_back(e);
|
||||
enode* n;
|
||||
|
@ -138,7 +164,7 @@ namespace euf {
|
|||
continue;
|
||||
}
|
||||
if (!is_app(e)) {
|
||||
m_nodes.push_back(m_egraph.mk(e, 0, 0, nullptr));
|
||||
m_nodes_to_canonize.push_back(m_egraph.mk(e, 0, 0, nullptr));
|
||||
m_todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
@ -152,7 +178,7 @@ namespace euf {
|
|||
m_todo.push_back(arg);
|
||||
}
|
||||
if (sz == m_todo.size()) {
|
||||
m_nodes.push_back(m_egraph.mk(e, 0, m_args.size(), m_args.data()));
|
||||
m_nodes_to_canonize.push_back(m_egraph.mk(e, 0, m_args.size(), m_args.data()));
|
||||
m_todo.pop_back();
|
||||
}
|
||||
}
|
||||
|
@ -314,10 +340,10 @@ namespace euf {
|
|||
void completion::map_canonical() {
|
||||
m_todo.reset();
|
||||
enode_vector roots;
|
||||
if (m_nodes.empty())
|
||||
if (m_nodes_to_canonize.empty())
|
||||
return;
|
||||
for (unsigned i = 0; i < m_nodes.size(); ++i) {
|
||||
enode* n = m_nodes[i]->get_root();
|
||||
for (unsigned i = 0; i < m_nodes_to_canonize.size(); ++i) {
|
||||
enode* n = m_nodes_to_canonize[i]->get_root();
|
||||
if (n->is_marked1())
|
||||
continue;
|
||||
n->mark1();
|
||||
|
@ -334,7 +360,7 @@ namespace euf {
|
|||
for (enode* arg : enode_args(n)) {
|
||||
arg = arg->get_root();
|
||||
if (!arg->is_marked1())
|
||||
m_nodes.push_back(arg);
|
||||
m_nodes_to_canonize.push_back(arg);
|
||||
}
|
||||
}
|
||||
for (enode* r : roots)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue