feat(library/tactic/congruence/congruence_closure): add new configuration options for minimizing the number of entries and occurrences
This commit is contained in:
parent
95882c14cd
commit
6eb81d2472
2 changed files with 39 additions and 19 deletions
|
|
@ -620,12 +620,31 @@ void congruence_closure::internalize_core(expr const & e, bool toplevel, bool to
|
|||
add_symm_congruence_table(e);
|
||||
} else if (auto lemma = mk_ext_congr_lemma(e)) {
|
||||
bool symm_table = false;
|
||||
if (m_state.m_config.m_ignore_instances) {
|
||||
buffer<expr> apps;
|
||||
expr const & fn = get_app_apps(e, apps);
|
||||
buffer<expr> apps;
|
||||
expr const & fn = get_app_apps(e, apps);
|
||||
lean_assert(is_app(apps.back(), e));
|
||||
list<param_info> pinfos;
|
||||
if (m_state.m_config.m_ignore_instances)
|
||||
pinfos = get_fun_info(m_ctx, fn, apps.size()).get_params_info();
|
||||
if (!m_state.m_config.m_all_ho && is_constant(fn) && !m_state.m_ho_fns.contains(const_name(fn))) {
|
||||
for (unsigned i = 0; i < apps.size(); i++) {
|
||||
expr const & arg = app_arg(apps[i]);
|
||||
add_occurrence(e, arg, symm_table);
|
||||
if (pinfos && head(pinfos).is_inst_implicit()) {
|
||||
/* We do not recurse on instances when m_state.m_config.m_ignore_instances is true. */
|
||||
mk_entry_core(arg, to_propagate);
|
||||
} else {
|
||||
internalize_core(arg, toplevel, to_propagate);
|
||||
}
|
||||
if (pinfos) pinfos = tail(pinfos);
|
||||
}
|
||||
internalize_core(fn, toplevel, to_propagate);
|
||||
add_occurrence(e, fn, symm_table);
|
||||
add_congruence_table(e);
|
||||
} else {
|
||||
/* Expensive case where we store a quadratic number of occurrences,
|
||||
as described in the paper "Congruence Closure in Internsional Type Theory" */
|
||||
lean_assert(is_app(apps.back(), e));
|
||||
fun_info info = get_fun_info(m_ctx, fn, apps.size());
|
||||
auto it = info.get_params_info();
|
||||
for (unsigned i = 0; i < apps.size(); i++) {
|
||||
expr const & curr = apps[i];
|
||||
lean_assert(is_app(curr));
|
||||
|
|
@ -635,7 +654,7 @@ void congruence_closure::internalize_core(expr const & e, bool toplevel, bool to
|
|||
add_occurrence(apps[j], curr_arg, symm_table);
|
||||
add_occurrence(apps[j], curr_fn, symm_table);
|
||||
}
|
||||
if (it && head(it).is_inst_implicit()) {
|
||||
if (pinfos && head(pinfos).is_inst_implicit()) {
|
||||
/* We do not recurse on instances when m_state.m_config.m_ignore_instances is true. */
|
||||
mk_entry_core(curr_arg, to_propagate);
|
||||
mk_entry_core(curr_fn, to_propagate);
|
||||
|
|
@ -643,19 +662,9 @@ void congruence_closure::internalize_core(expr const & e, bool toplevel, bool to
|
|||
internalize_core(curr_arg, toplevel, to_propagate);
|
||||
mk_entry_core(curr_fn, to_propagate);
|
||||
}
|
||||
if (it) it = tail(it);
|
||||
if (pinfos) pinfos = tail(pinfos);
|
||||
add_congruence_table(curr);
|
||||
}
|
||||
} else {
|
||||
internalize_core(app_fn(e), toplevel, to_propagate);
|
||||
internalize_core(app_arg(e), toplevel, to_propagate);
|
||||
expr it = e;
|
||||
while (is_app(it)) {
|
||||
add_occurrence(e, app_fn(it), symm_table);
|
||||
add_occurrence(e, app_arg(it), symm_table);
|
||||
it = app_fn(it);
|
||||
}
|
||||
add_congruence_table(e);
|
||||
}
|
||||
}
|
||||
apply_simple_eqvs(e);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ public:
|
|||
struct config {
|
||||
unsigned m_ignore_instances:1;
|
||||
unsigned m_values:1;
|
||||
config() { m_ignore_instances = true; m_values = true; }
|
||||
unsigned m_all_ho:1;
|
||||
config() { m_ignore_instances = true; m_values = true; m_all_ho = false; }
|
||||
};
|
||||
|
||||
class state {
|
||||
|
|
@ -112,11 +113,21 @@ public:
|
|||
short m_froze_partitions{false};
|
||||
short m_inconsistent{false};
|
||||
unsigned m_gmt{0};
|
||||
/** Only for constant functions in m_ho_fns, we add the extra occurrences discussed in
|
||||
the paper "Congruence Closure in Intensional Type Theory". The idea is to avoid
|
||||
the quadratic number of entries in the parent occurrences data-structures,
|
||||
and avoid the creation of entries for partial applications. For example, given
|
||||
(@add nat nat_has_add a b), it seems wasteful to create entries for
|
||||
(@add nat), (@add nat nat_has_add) and (@nat nat_has_add a).
|
||||
This set is ignore if m_config.m_all_ho is true. */
|
||||
name_set m_ho_fns;
|
||||
config m_config;
|
||||
friend class congruence_closure;
|
||||
bool check_eqc(expr const & e) const;
|
||||
public:
|
||||
state(config const & cfg = config()):m_config(cfg) {}
|
||||
state(name_set const & ho_fns = name_set(), config const & cfg = config()):
|
||||
m_ho_fns(ho_fns),
|
||||
m_config(cfg) {}
|
||||
void get_roots(buffer<expr> & roots) const;
|
||||
expr get_root(expr const & e) const;
|
||||
expr get_next(expr const & e) const;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue