mirror of
https://github.com/Z3Prover/z3
synced 2026-05-09 11:52:21 +00:00
Use the minimum generation number among matching enodes (#9405)
* Compute term generations based on minimal match * Tidy up get_*_f_app * Update euf_mam to the minimum generation number among matches * Update euf_mam.cpp * Move the UNREACHABLE() test to smt_mam.cpp * Enforce stickiness of max-generation * Add current generation tracking to bind structure * Fix build error --------- Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
30c74fccee
commit
2c7b256db2
2 changed files with 47 additions and 21 deletions
|
|
@ -239,6 +239,7 @@ namespace euf {
|
|||
unsigned short m_num_args;
|
||||
unsigned m_ireg;
|
||||
unsigned m_oreg;
|
||||
unsigned m_curr_generation;
|
||||
};
|
||||
|
||||
struct get_cgr : public instruction {
|
||||
|
|
@ -1926,28 +1927,38 @@ namespace euf {
|
|||
m_max_generation = std::max(m_max_generation, n->generation());
|
||||
}
|
||||
|
||||
void get_f_app(func_decl* lbl, unsigned num_expected_args, enode* curr, enode*& matching_cgr, enode*& min_gen_match) {
|
||||
if (curr->get_decl() == lbl && curr->num_args() == num_expected_args) {
|
||||
if (curr->is_cgr() && !matching_cgr)
|
||||
matching_cgr = curr;
|
||||
if (!min_gen_match || min_gen_match->generation() > curr->generation())
|
||||
min_gen_match = curr;
|
||||
}
|
||||
}
|
||||
|
||||
// We have to provide the number of expected arguments because we have flat-assoc applications such as +.
|
||||
// Flat-assoc applications may have arbitrary number of arguments.
|
||||
enode * get_first_f_app(func_decl * lbl, unsigned num_expected_args, enode * first) {
|
||||
enode *matching_cgr = nullptr, *min_gen_match = nullptr;
|
||||
for (enode* curr : euf::enode_class(first)) {
|
||||
if (curr->get_decl() == lbl && curr->is_cgr() && curr->num_args() == num_expected_args) {
|
||||
update_max_generation(curr, first);
|
||||
return curr;
|
||||
}
|
||||
get_f_app(lbl, num_expected_args, curr, matching_cgr, min_gen_match);
|
||||
curr = curr->get_next();
|
||||
}
|
||||
return nullptr;
|
||||
if (matching_cgr)
|
||||
update_max_generation(min_gen_match, first);
|
||||
return matching_cgr;
|
||||
}
|
||||
|
||||
enode * get_next_f_app(func_decl * lbl, unsigned num_expected_args, enode * first, enode * curr) {
|
||||
curr = curr->get_next();
|
||||
enode *matching_cgr = nullptr, *min_gen_match = nullptr;
|
||||
while (curr != first) {
|
||||
if (curr->get_decl() == lbl && curr->is_cgr() && curr->num_args() == num_expected_args) {
|
||||
update_max_generation(curr, first);
|
||||
return curr;
|
||||
}
|
||||
get_f_app(lbl, num_expected_args, curr, matching_cgr, min_gen_match);
|
||||
curr = curr->get_next();
|
||||
}
|
||||
return nullptr;
|
||||
if (matching_cgr)
|
||||
update_max_generation(min_gen_match, first);
|
||||
return matching_cgr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2563,6 +2574,7 @@ namespace euf {
|
|||
m_backtrack_stack[m_top].m_instr = m_pc; \
|
||||
m_backtrack_stack[m_top].m_old_max_generation = m_curr_max_generation; \
|
||||
m_backtrack_stack[m_top].m_curr = m_app; \
|
||||
const_cast<bind*>(static_cast<bind const*>(m_pc))->m_curr_generation = m_max_generation; \
|
||||
m_top++;
|
||||
|
||||
BIND_COMMON();
|
||||
|
|
@ -2829,7 +2841,8 @@ namespace euf {
|
|||
goto backtrack; \
|
||||
} \
|
||||
bp.m_curr = m_app; \
|
||||
TRACE(mam_int, tout << "bind next candidate:\n" << mk_ll_pp(m_app->get_expr(), m);); \
|
||||
m_max_generation = m_b->m_curr_generation; \
|
||||
TRACE(mam_int, tout << "bind next candidate:\n" << mk_ll_pp(m_app->get_expr(), m);); \
|
||||
m_oreg = m_b->m_oreg
|
||||
|
||||
BBIND_COMMON();
|
||||
|
|
@ -4059,4 +4072,4 @@ void euf::mam::ground_subterms(expr* e, ptr_vector<app>& ground) {
|
|||
|
||||
euf::mam* euf::mam::mk(euf::mam_solver& ctx, euf::on_binding_callback& em) {
|
||||
return alloc(mam_impl, ctx, em, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@ namespace {
|
|||
unsigned short m_num_args;
|
||||
unsigned m_ireg;
|
||||
unsigned m_oreg;
|
||||
unsigned m_curr_max_generation = 0;
|
||||
};
|
||||
|
||||
struct get_cgr : public instruction {
|
||||
|
|
@ -1887,33 +1888,43 @@ namespace {
|
|||
m_used_enodes.push_back(std::make_tuple(prev, n));
|
||||
}
|
||||
|
||||
void get_f_app(func_decl* lbl, unsigned num_expected_args, enode* curr, enode*& matching_cgr, enode*& min_gen_match) {
|
||||
if (curr->get_decl() == lbl && curr->get_num_args() == num_expected_args) {
|
||||
if (curr->is_cgr() && !matching_cgr)
|
||||
matching_cgr = curr;
|
||||
|
||||
if (!min_gen_match || min_gen_match->get_generation() > curr->get_generation()) {
|
||||
min_gen_match = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have to provide the number of expected arguments because we have flat-assoc applications such as +.
|
||||
// Flat-assoc applications may have arbitrary number of arguments.
|
||||
enode * get_first_f_app(func_decl * lbl, unsigned num_expected_args, enode * curr) {
|
||||
enode * first = curr;
|
||||
enode *matching_cgr = nullptr, *min_gen_match = nullptr;
|
||||
do {
|
||||
if (curr->get_decl() == lbl && curr->is_cgr() && curr->get_num_args() == num_expected_args) {
|
||||
update_max_generation(curr, first);
|
||||
return curr;
|
||||
}
|
||||
get_f_app(lbl, num_expected_args, curr, matching_cgr, min_gen_match);
|
||||
curr = curr->get_next();
|
||||
}
|
||||
while (curr != first);
|
||||
return nullptr;
|
||||
if (matching_cgr)
|
||||
update_max_generation(min_gen_match, first);
|
||||
return matching_cgr;
|
||||
}
|
||||
|
||||
enode * get_next_f_app(func_decl * lbl, unsigned num_expected_args, enode * first, enode * curr) {
|
||||
curr = curr->get_next();
|
||||
while (curr != first) {
|
||||
if (curr->get_decl() == lbl && curr->is_cgr() && curr->get_num_args() == num_expected_args) {
|
||||
update_max_generation(curr, first);
|
||||
if (curr->get_decl() == lbl && curr->get_num_args() == num_expected_args && curr->is_cgr())
|
||||
return curr;
|
||||
}
|
||||
curr = curr->get_next();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Execute the is_cgr instruction.
|
||||
Return true if succeeded, and false if backtracking is needed.
|
||||
|
|
@ -2476,6 +2487,7 @@ namespace {
|
|||
m_backtrack_stack[m_top].m_old_max_generation = m_curr_max_generation; \
|
||||
m_backtrack_stack[m_top].m_old_used_enodes_size = m_curr_used_enodes_size; \
|
||||
m_backtrack_stack[m_top].m_curr = m_app; \
|
||||
const_cast<bind*>(static_cast<const bind*>(m_pc))->m_curr_max_generation = m_max_generation; \
|
||||
m_top++;
|
||||
|
||||
BIND_COMMON();
|
||||
|
|
@ -2743,7 +2755,8 @@ namespace {
|
|||
#define BBIND_COMMON() m_b = static_cast<const bind*>(bp.m_instr); \
|
||||
m_n1 = m_registers[m_b->m_ireg]; \
|
||||
m_app = get_next_f_app(m_b->m_label, m_b->m_num_args, m_n1, bp.m_curr); \
|
||||
if (m_app == 0) { \
|
||||
m_max_generation = m_b->m_curr_max_generation; \
|
||||
if (!m_app) { \
|
||||
m_top--; \
|
||||
goto backtrack; \
|
||||
} \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue