fix(library/abstract_expr_manager): instantiate before calling mk_congr

This commit is contained in:
Daniel Selsam 2015-12-03 16:25:10 -08:00 committed by Leonardo de Moura
parent d729302718
commit 9689085834
4 changed files with 33 additions and 6 deletions

View file

@ -4,12 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Daniel Selsam Author: Daniel Selsam
*/ */
#include "library/abstract_expr_manager.h" #include "library/abstract_expr_manager.h"
#include "kernel/instantiate.h"
#include "util/safe_arith.h" #include "util/safe_arith.h"
#include "util/list_fn.h" #include "util/list_fn.h"
namespace lean { namespace lean {
unsigned abstract_expr_manager::hash(expr const & e) { unsigned abstract_expr_manager::hash(expr const & e) {
unsigned h;
switch (e.kind()) { switch (e.kind()) {
case expr_kind::Constant: case expr_kind::Constant:
case expr_kind::Local: case expr_kind::Local:
@ -20,12 +22,16 @@ unsigned abstract_expr_manager::hash(expr const & e) {
return e.hash(); return e.hash();
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Pi:
return ::lean::hash(hash(binding_domain(e)), hash(binding_body(e))); h = hash(binding_domain(e));
m_locals.push_back(m_tctx.mk_tmp_local(binding_domain(e)));
h = ::lean::hash(h, hash(binding_body(e)));
m_locals.pop_back();
return h;
case expr_kind::App: case expr_kind::App:
buffer<expr> args; buffer<expr> args;
expr f = get_app_args(e, args); expr f = instantiate_rev(get_app_args(e, args), m_locals.size(), m_locals.data());
optional<congr_lemma> f_congr = m_congr_lemma_manager.mk_congr(f, args.size()); optional<congr_lemma> f_congr = m_congr_lemma_manager.mk_congr(f, args.size());
unsigned h = hash(f); h = hash(f);
if (!f_congr) { if (!f_congr) {
for (expr const & arg : args) h = ::lean::hash(h, hash(arg)); for (expr const & arg : args) h = ::lean::hash(h, hash(arg));
} else { } else {
@ -46,6 +52,7 @@ bool abstract_expr_manager::is_equal(expr const & a, expr const & b) {
if (hash(a) != hash(b)) return false; if (hash(a) != hash(b)) return false;
if (a.kind() != b.kind()) return false; if (a.kind() != b.kind()) return false;
if (is_var(a)) return var_idx(a) == var_idx(b); if (is_var(a)) return var_idx(a) == var_idx(b);
bool is_eq;
switch (a.kind()) { switch (a.kind()) {
case expr_kind::Var: case expr_kind::Var:
lean_unreachable(); // LCOV_EXCL_LINE lean_unreachable(); // LCOV_EXCL_LINE
@ -54,7 +61,11 @@ bool abstract_expr_manager::is_equal(expr const & a, expr const & b) {
case expr_kind::Meta: case expr_kind::Local: case expr_kind::Meta: case expr_kind::Local:
return mlocal_name(a) == mlocal_name(b) && is_equal(mlocal_type(a), mlocal_type(b)); return mlocal_name(a) == mlocal_name(b) && is_equal(mlocal_type(a), mlocal_type(b));
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi:
return is_equal(binding_domain(a), binding_domain(b)) && is_equal(binding_body(a), binding_body(b)); if (!is_equal(binding_domain(a), binding_domain(b))) return false;
m_locals.push_back(m_tctx.mk_tmp_local(binding_domain(a)));
is_eq = is_equal(binding_body(a), binding_body(b));
m_locals.pop_back();
return is_eq;
case expr_kind::Macro: case expr_kind::Macro:
if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b))
return false; return false;
@ -69,7 +80,8 @@ bool abstract_expr_manager::is_equal(expr const & a, expr const & b) {
expr f_b = get_app_args(b, b_args); expr f_b = get_app_args(b, b_args);
if (!is_equal(f_a, f_b)) return false; if (!is_equal(f_a, f_b)) return false;
if (a_args.size() != b_args.size()) return false; if (a_args.size() != b_args.size()) return false;
optional<congr_lemma> f_congr = m_congr_lemma_manager.mk_congr(f_a, a_args.size()); expr f = instantiate_rev(f_a, m_locals.size(), m_locals.data());
optional<congr_lemma> f_congr = m_congr_lemma_manager.mk_congr(f, a_args.size());
bool not_equal = false; bool not_equal = false;
if (!f_congr) { if (!f_congr) {
for (unsigned i = 0; i < a_args.size(); ++i) { for (unsigned i = 0; i < a_args.size(); ++i) {

View file

@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Daniel Selsam Author: Daniel Selsam
*/ */
#pragma once #pragma once
#include <vector>
#include "kernel/expr.h" #include "kernel/expr.h"
#include "library/type_context.h"
#include "library/congr_lemma_manager.h" #include "library/congr_lemma_manager.h"
namespace lean { namespace lean {
@ -12,9 +14,16 @@ namespace lean {
/** \brief Abstract expression manager, to allow comparing expressions while ignoring subsingletons. */ /** \brief Abstract expression manager, to allow comparing expressions while ignoring subsingletons. */
class abstract_expr_manager { class abstract_expr_manager {
/* The [congr_lemma_manager] cannot handle [Var]s since it needs to infer types, and we do not
want to instantiate eagerly for performance reasons. Therefore we track the context ourselves,
and only instantiate on the expressions we pass to the [congr_lemma_manager], which we
expect to be very small in general. */
std::vector<expr> m_locals;
type_context & m_tctx;
congr_lemma_manager & m_congr_lemma_manager; congr_lemma_manager & m_congr_lemma_manager;
public: public:
abstract_expr_manager(congr_lemma_manager & c_lemma_manager): m_congr_lemma_manager(c_lemma_manager) {} abstract_expr_manager(congr_lemma_manager & c_lemma_manager):
m_tctx(c_lemma_manager.ctx()), m_congr_lemma_manager(c_lemma_manager) {}
unsigned hash(expr const & e); unsigned hash(expr const & e);
bool is_equal(expr const & a, expr const & b); bool is_equal(expr const & a, expr const & b);
}; };

View file

@ -301,6 +301,8 @@ public:
m_builder(b), m_fmanager(fm), m_ctx(fm.ctx()), m_builder(b), m_fmanager(fm), m_ctx(fm.ctx()),
m_relation_info_getter(mk_relation_info_getter(fm.ctx().env())) {} m_relation_info_getter(mk_relation_info_getter(fm.ctx().env())) {}
type_context & ctx() { return m_ctx; }
optional<result> mk_congr_simp(expr const & fn) { optional<result> mk_congr_simp(expr const & fn) {
fun_info finfo = m_fmanager.get(fn); fun_info finfo = m_fmanager.get(fn);
return mk_congr_simp(fn, finfo.get_arity()); return mk_congr_simp(fn, finfo.get_arity());
@ -493,6 +495,8 @@ congr_lemma_manager::congr_lemma_manager(app_builder & b, fun_info_manager & fm)
congr_lemma_manager::~congr_lemma_manager() { congr_lemma_manager::~congr_lemma_manager() {
} }
type_context & congr_lemma_manager::ctx() { return m_ptr->ctx(); }
auto congr_lemma_manager::mk_congr_simp(expr const & fn) -> optional<result> { auto congr_lemma_manager::mk_congr_simp(expr const & fn) -> optional<result> {
return m_ptr->mk_congr_simp(fn); return m_ptr->mk_congr_simp(fn);
} }

View file

@ -33,6 +33,8 @@ public:
~congr_lemma_manager(); ~congr_lemma_manager();
typedef congr_lemma result; typedef congr_lemma result;
type_context & ctx();
optional<result> mk_congr_simp(expr const & fn); optional<result> mk_congr_simp(expr const & fn);
optional<result> mk_congr_simp(expr const & fn, unsigned nargs); optional<result> mk_congr_simp(expr const & fn, unsigned nargs);