mirror of
https://github.com/Z3Prover/z3
synced 2025-06-23 06:13:40 +00:00
call m_egraph.merge() at a single point
This commit is contained in:
parent
d36262d731
commit
036a3f31ca
2 changed files with 27 additions and 20 deletions
|
@ -211,7 +211,8 @@ namespace polysat {
|
||||||
case trail_item::mk_concat:
|
case trail_item::mk_concat:
|
||||||
num_replay_concat++;
|
num_replay_concat++;
|
||||||
break;
|
break;
|
||||||
default: UNREACHABLE();
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_egraph.pop(num_scopes);
|
m_egraph.pop(num_scopes);
|
||||||
|
@ -247,9 +248,9 @@ namespace polysat {
|
||||||
replay_concat(ci.num_args, &m_concat_args[ci.args_idx], ci.v);
|
replay_concat(ci.num_args, &m_concat_args[ci.args_idx], ci.v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
m_concat_trail.shrink(m_concat_trail.size() - num_replay_concat);
|
m_concat_trail.shrink(m_concat_trail.size() - num_replay_concat);
|
||||||
m_concat_args.shrink(m_concat_trail.empty() ? 0 : m_concat_trail.back().next_args_idx());
|
m_concat_args.shrink(m_concat_trail.empty() ? 0 : m_concat_trail.back().next_args_idx());
|
||||||
|
@ -319,7 +320,7 @@ namespace polysat {
|
||||||
slice_info& concat_info = m_info[concat->get_id()];
|
slice_info& concat_info = m_info[concat->get_id()];
|
||||||
SASSERT(!concat_info.slice); // not yet set
|
SASSERT(!concat_info.slice); // not yet set
|
||||||
concat_info.slice = s;
|
concat_info.slice = s;
|
||||||
m_egraph.merge(s, concat, dep_t().encode());
|
egraph_merge(s, concat, dep_t());
|
||||||
}
|
}
|
||||||
|
|
||||||
void slicing::add_var_congruence(pvar v) {
|
void slicing::add_var_congruence(pvar v) {
|
||||||
|
@ -342,6 +343,8 @@ namespace polysat {
|
||||||
void slicing::update_var_congruences() {
|
void slicing::update_var_congruences() {
|
||||||
if (!use_var_congruences())
|
if (!use_var_congruences())
|
||||||
return;
|
return;
|
||||||
|
// TODO: this is only needed once per equivalence class
|
||||||
|
// (mark root of var2slice to detect duplicates?)
|
||||||
for (pvar v : m_needs_congruence)
|
for (pvar v : m_needs_congruence)
|
||||||
add_var_congruence(v);
|
add_var_congruence(v);
|
||||||
m_needs_congruence.reset();
|
m_needs_congruence.reset();
|
||||||
|
@ -410,24 +413,17 @@ namespace polysat {
|
||||||
// split all slices in the equivalence class
|
// split all slices in the equivalence class
|
||||||
for (enode* n : euf::enode_class(s))
|
for (enode* n : euf::enode_class(s))
|
||||||
split_core(n, cut);
|
split_core(n, cut);
|
||||||
// propagate the proper equivalences
|
// propagate equivalences to subslices
|
||||||
for (enode* n : euf::enode_class(s)) {
|
for (enode* n : euf::enode_class(s)) {
|
||||||
enode* target = n->get_target();
|
enode* target = n->get_target();
|
||||||
if (!target)
|
if (!target)
|
||||||
continue;
|
continue;
|
||||||
|
SASSERT(!is_value(n)); // values are always roots, and target always points towards the root.
|
||||||
euf::justification const j = n->get_justification();
|
euf::justification const j = n->get_justification();
|
||||||
SASSERT(j.is_external()); // cannot be a congruence since the slice wasn't split before.
|
SASSERT(j.is_external()); // cannot be a congruence since the slice wasn't split before.
|
||||||
void* j_hi = j.ext<void>();
|
dep_t const d = dep_t::decode(j.ext<void>());
|
||||||
void* j_lo = j.ext<void>();
|
egraph_merge(sub_hi(n), sub_hi(target), d);
|
||||||
dep_t d = dep_t::decode(j.ext<void>());
|
egraph_merge(sub_lo(n), sub_lo(target), d);
|
||||||
if (d.is_value()) {
|
|
||||||
enode* ds = get_dep_slice(d);
|
|
||||||
SASSERT(ds == n || ds == target);
|
|
||||||
j_hi = mk_var_dep(get_dep_var(d), sub_hi(ds), get_dep_lit(d)).encode();
|
|
||||||
j_lo = mk_var_dep(get_dep_var(d), sub_lo(ds), get_dep_lit(d)).encode();
|
|
||||||
}
|
|
||||||
m_egraph.merge(sub_hi(n), sub_hi(target), j_hi);
|
|
||||||
m_egraph.merge(sub_lo(n), sub_lo(target), j_lo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,18 +833,26 @@ namespace polysat {
|
||||||
m_egraph.propagate();
|
m_egraph.propagate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool slicing::merge_base(enode* s1, enode* s2, dep_t dep) {
|
bool slicing::egraph_merge(enode* s1, enode* s2, dep_t dep) {
|
||||||
SASSERT_EQ(width(s1), width(s2));
|
SASSERT_EQ(width(s1), width(s2));
|
||||||
SASSERT(!has_sub(s1));
|
|
||||||
SASSERT(!has_sub(s2));
|
|
||||||
if (dep.is_value()) {
|
if (dep.is_value()) {
|
||||||
|
if (is_value(s1))
|
||||||
|
std::swap(s1, s2);
|
||||||
SASSERT(is_value(s2));
|
SASSERT(is_value(s2));
|
||||||
|
SASSERT(!is_value(s1)); // we never merge two value slices directly
|
||||||
|
if (get_dep_slice(dep) != s1)
|
||||||
dep = mk_var_dep(get_dep_var(dep), s1, get_dep_lit(dep));
|
dep = mk_var_dep(get_dep_var(dep), s1, get_dep_lit(dep));
|
||||||
}
|
}
|
||||||
m_egraph.merge(s1, s2, dep.encode());
|
m_egraph.merge(s1, s2, dep.encode());
|
||||||
return !is_conflict();
|
return !is_conflict();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool slicing::merge_base(enode* s1, enode* s2, dep_t dep) {
|
||||||
|
SASSERT(!has_sub(s1));
|
||||||
|
SASSERT(!has_sub(s2));
|
||||||
|
return egraph_merge(s1, s2, dep);
|
||||||
|
}
|
||||||
|
|
||||||
bool slicing::merge(enode_vector& xs, enode_vector& ys, dep_t dep) {
|
bool slicing::merge(enode_vector& xs, enode_vector& ys, dep_t dep) {
|
||||||
while (!xs.empty()) {
|
while (!xs.empty()) {
|
||||||
SASSERT(!ys.empty());
|
SASSERT(!ys.empty());
|
||||||
|
|
|
@ -192,6 +192,9 @@ namespace polysat {
|
||||||
void egraph_on_merge(enode* root, enode* other);
|
void egraph_on_merge(enode* root, enode* other);
|
||||||
void egraph_on_propagate(enode* lit, enode* ante);
|
void egraph_on_propagate(enode* lit, enode* ante);
|
||||||
|
|
||||||
|
// Merge slices in the e-graph.
|
||||||
|
bool egraph_merge(enode* s1, enode* s2, dep_t dep);
|
||||||
|
|
||||||
// Merge equivalence classes of two base slices.
|
// Merge equivalence classes of two base slices.
|
||||||
// Returns true if merge succeeded without conflict.
|
// Returns true if merge succeeded without conflict.
|
||||||
[[nodiscard]] bool merge_base(enode* s1, enode* s2, dep_t dep);
|
[[nodiscard]] bool merge_base(enode* s1, enode* s2, dep_t dep);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue