fix(library/tactic/simplify): fixes #1685

This commit is contained in:
Leonardo de Moura 2017-06-20 12:27:46 -07:00
parent ce3387b246
commit b25291c5c9
4 changed files with 67 additions and 12 deletions

View file

@ -8,7 +8,7 @@ Author: Leonardo de Moura
#include "library/expr_lt.h"
namespace lean {
bool is_lt(expr const & a, expr const & b, bool use_hash) {
bool is_lt(expr const & a, expr const & b, bool use_hash, local_context const * lctx) {
if (is_eqp(a, b)) return false;
unsigned wa = get_weight(a);
unsigned wb = get_weight(b);
@ -30,28 +30,33 @@ bool is_lt(expr const & a, expr const & b, bool use_hash) {
return is_lt(const_levels(a), const_levels(b), use_hash);
case expr_kind::App:
if (app_fn(a) != app_fn(b))
return is_lt(app_fn(a), app_fn(b), use_hash);
return is_lt(app_fn(a), app_fn(b), use_hash, lctx);
else
return is_lt(app_arg(a), app_arg(b), use_hash);
return is_lt(app_arg(a), app_arg(b), use_hash, lctx);
case expr_kind::Lambda: case expr_kind::Pi:
if (binding_domain(a) != binding_domain(b))
return is_lt(binding_domain(a), binding_domain(b), use_hash);
return is_lt(binding_domain(a), binding_domain(b), use_hash, lctx);
else
return is_lt(binding_body(a), binding_body(b), use_hash);
return is_lt(binding_body(a), binding_body(b), use_hash, lctx);
case expr_kind::Let:
if (let_type(a) != let_type(b))
return is_lt(let_type(a), let_type(b), use_hash);
return is_lt(let_type(a), let_type(b), use_hash, lctx);
else if (let_value(a) != let_value(b))
return is_lt(let_value(a), let_value(b), use_hash);
return is_lt(let_value(a), let_value(b), use_hash, lctx);
else
return is_lt(let_body(a), let_body(b), use_hash);
return is_lt(let_body(a), let_body(b), use_hash, lctx);
case expr_kind::Sort:
return is_lt(sort_level(a), sort_level(b), use_hash);
case expr_kind::Local: case expr_kind::Meta:
if (lctx) {
if (auto d1 = lctx->find_local_decl(a))
if (auto d2 = lctx->find_local_decl(b))
return d1->get_idx() < d2->get_idx();
}
if (mlocal_name(a) != mlocal_name(b))
return mlocal_name(a) < mlocal_name(b);
else
return is_lt(mlocal_type(a), mlocal_type(b), use_hash);
return is_lt(mlocal_type(a), mlocal_type(b), use_hash, lctx);
case expr_kind::Macro:
if (macro_def(a) != macro_def(b))
return macro_def(a) < macro_def(b);
@ -59,7 +64,7 @@ bool is_lt(expr const & a, expr const & b, bool use_hash) {
return macro_num_args(a) < macro_num_args(b);
for (unsigned i = 0; i < macro_num_args(a); i++) {
if (macro_arg(a, i) != macro_arg(b, i))
return is_lt(macro_arg(a, i), macro_arg(b, i), use_hash);
return is_lt(macro_arg(a, i), macro_arg(b, i), use_hash, lctx);
}
return false;
}

View file

@ -7,6 +7,7 @@ Author: Leonardo de Moura
#pragma once
#include "kernel/expr.h"
#include "util/rb_map.h"
#include "library/local_context.h"
namespace lean {
/** \brief Total order on expressions.
@ -14,8 +15,10 @@ namespace lean {
\remark If \c use_hash is true, then we use the hash_code to
partially order expressions. Setting use_hash to false is useful
for testing the code.
\remark If lctx is not nullptr, then we use the local_decl index to compare local constants.
*/
bool is_lt(expr const & a, expr const & b, bool use_hash);
bool is_lt(expr const & a, expr const & b, bool use_hash, local_context const * lctx = nullptr);
/** \brief Similar to is_lt, but universe level parameter names are ignored. */
bool is_lt_no_level_params(expr const & a, expr const & b);
inline bool is_hash_lt(expr const & a, expr const & b) { return is_lt(a, b, true); }

View file

@ -584,7 +584,7 @@ simp_result simplify_core_fn::rewrite_core(expr const & e, simp_lemma const & sl
}
if (sl.is_permutation()) {
if (!is_lt(new_rhs, new_lhs, false)) {
if (!is_lt(new_rhs, new_lhs, false, &m_ctx.lctx())) {
lean_simp_trace(tmp_ctx, name({"simplify", "perm"}),
tout() << "perm rejected: " << new_rhs << " !< " << new_lhs << "\n";);
return simp_result(e);

47
tests/lean/run/1685.lean Normal file
View file

@ -0,0 +1,47 @@
/- This test assumes the total order on terms used by simp compares local constants
using the order they appear in the local context. -/
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, m + n = k → n + m = k := by intros; simp; assumption
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end
example (m : ) : ∀ n k, n + m = k → n + m = k :=
begin intros, simp, fail_if_success {assumption}, admit end