chore(library/tactic/simplify): remove subsingleton support

It is left over from the blast tactic.
Moreover, it is incomplete.
This commit is contained in:
Leonardo de Moura 2016-10-16 22:11:12 -07:00
parent 835c888936
commit 7b806755d9
4 changed files with 3 additions and 229 deletions

View file

@ -1259,7 +1259,6 @@ class add_nested_inductive_decl_fn {
opts = opts.update(get_simplify_lift_eq_name(), false);
opts = opts.update(get_simplify_canonize_instances_fixed_point_name(), false);
opts = opts.update(get_simplify_canonize_proofs_fixed_point_name(), false);
opts = opts.update(get_simplify_canonize_subsingletons_name(), false);
return opts;
}

View file

@ -56,9 +56,6 @@ Author: Daniel Selsam
#ifndef LEAN_DEFAULT_SIMPLIFY_DEFEQ_CANONIZE_PROOFS_FIXED_POINT
#define LEAN_DEFAULT_SIMPLIFY_DEFEQ_CANONIZE_PROOFS_FIXED_POINT false
#endif
#ifndef LEAN_DEFAULT_SIMPLIFY_CANONIZE_SUBSINGLETONS
#define LEAN_DEFAULT_SIMPLIFY_CANONIZE_SUBSINGLETONS true
#endif
namespace lean {
@ -73,7 +70,6 @@ static name * g_simplify_rewrite = nullptr;
static name * g_simplify_lift_eq = nullptr;
static name * g_simplify_canonize_instances_fixed_point = nullptr;
static name * g_simplify_canonize_proofs_fixed_point = nullptr;
static name * g_simplify_canonize_subsingletons = nullptr;
name get_simplify_max_steps_name() { return *g_simplify_max_steps; }
name get_simplify_contextual_name() { return *g_simplify_contextual; }
@ -81,7 +77,6 @@ name get_simplify_rewrite_name() { return *g_simplify_rewrite; }
name get_simplify_lift_eq_name() { return *g_simplify_lift_eq; }
name get_simplify_canonize_instances_fixed_point_name() { return *g_simplify_canonize_instances_fixed_point; }
name get_simplify_canonize_proofs_fixed_point_name() { return *g_simplify_canonize_proofs_fixed_point; }
name get_simplify_canonize_subsingletons_name() { return *g_simplify_canonize_subsingletons; }
static unsigned get_simplify_max_steps(options const & o) {
return o.get_unsigned(*g_simplify_max_steps, LEAN_DEFAULT_SIMPLIFY_MAX_STEPS);
@ -107,10 +102,6 @@ static bool get_simplify_canonize_proofs_fixed_point(options const & o) {
return o.get_bool(*g_simplify_canonize_proofs_fixed_point, LEAN_DEFAULT_SIMPLIFY_DEFEQ_CANONIZE_PROOFS_FIXED_POINT);
}
static bool get_simplify_canonize_subsingletons(options const & o) {
return o.get_bool(*g_simplify_canonize_subsingletons, LEAN_DEFAULT_SIMPLIFY_CANONIZE_SUBSINGLETONS);
}
#define lean_simp_trace(tctx, n, code) lean_trace(n, scope_trace_env _scope1(tctx.env(), tctx); code)
/* Main simplifier class */
@ -136,7 +127,6 @@ class simplifier {
bool m_lift_eq;
bool m_canonize_instances_fixed_point;
bool m_canonize_proofs_fixed_point;
bool m_canonize_subsingletons;
typedef expr_struct_map<simp_result> simplify_cache;
simplify_cache m_cache;
@ -368,12 +358,9 @@ class simplifier {
/* Proving */
optional<expr> prove(expr const & thm);
/* Canonicalize */
/* Canonize */
expr defeq_canonize_args_step(expr const & e);
expr_struct_map<expr> m_subsingleton_elem_map;
simp_result canonize_subsingleton_args(expr const & e);
/* Congruence */
simp_result congr_fun_arg(simp_result const & r_f, simp_result const & r_arg);
simp_result congr(simp_result const & r_f, simp_result const & r_arg);
@ -404,9 +391,8 @@ public:
m_rewrite(get_simplify_rewrite(tctx.get_options())),
m_lift_eq(get_simplify_lift_eq(tctx.get_options())),
m_canonize_instances_fixed_point(get_simplify_canonize_instances_fixed_point(tctx.get_options())),
m_canonize_proofs_fixed_point(get_simplify_canonize_proofs_fixed_point(tctx.get_options())),
m_canonize_subsingletons(get_simplify_canonize_subsingletons(tctx.get_options()))
{ }
m_canonize_proofs_fixed_point(get_simplify_canonize_proofs_fixed_point(tctx.get_options()))
{}
simp_result operator()(expr const & e) {
scope_trace_env scope(env(), m_tctx.get_options(), m_tctx);
@ -471,21 +457,6 @@ simp_result simplifier::simplify_subterms_lambda(expr const & old_e) {
simp_result r = simplify(e);
expr new_e = r.get_new();
expr new_e_type = m_tctx.infer(new_e);
if (auto inst = m_tctx.mk_subsingleton_instance(new_e_type)) {
auto it = m_subsingleton_elem_map.find(new_e_type);
if (it != m_subsingleton_elem_map.end()) {
// We do not canonize when there is an unfavourable locals mismatch
// TODO(dhs): maintain a list of canonical elements as we do in the defeq-canonizer
if (it->second != new_e && locals_subset(it->second, new_e)) {
expr proof = mk_ss_elim(m_tctx, new_e_type, *inst, new_e, it->second);
r = join(r, simp_result(it->second, proof));
lean_trace_d(name({"simplifier", "subsingleton"}), tout() << new_e << " ==> " << it->second << "\n";);
}
} else {
m_subsingleton_elem_map.insert(mk_pair(new_e_type, new_e));
}
}
if (r.get_new() == e)
return old_e;
@ -740,8 +711,6 @@ simp_result simplifier::try_congr(expr const & e, simp_lemma const & cl) {
expr pf = tmp_tctx.instantiate_mvars(cl.get_proof());
simp_result r(e_s, pf);
if (is_app(e_s))
r = join(r, canonize_subsingleton_args(r.get_new()));
lean_simp_trace(tmp_tctx, name({"simplifier", "congruence"}),
tout() << "(" << cl.get_id() << ") "
@ -845,15 +814,11 @@ optional<simp_result> simplifier::synth_congr(expr const & e) {
if (!has_simplified) {
simp_result r = simp_result(e);
if (has_cast)
r = join(r, canonize_subsingleton_args(r.get_new()));
return optional<simp_result>(r);
}
if (!has_proof) {
simp_result r = simp_result(mk_app(f, new_args));
if (has_cast)
r = join(r, canonize_subsingleton_args(r.get_new()));
return optional<simp_result>(r);
}
@ -903,78 +868,11 @@ optional<simp_result> simplifier::synth_congr(expr const & e) {
if (has_cast) {
r.update(remove_unnecessary_casts(r.get_new()));
r = join(r, canonize_subsingleton_args(r.get_new()));
}
return optional<simp_result>(r);
}
// Given a function application \c e, replace arguments that are subsingletons with a
// representative
simp_result simplifier::canonize_subsingleton_args(expr const & e) {
// TODO(dhs): flag to skip this step
buffer<expr> args;
get_app_args(e, args);
auto congr_lemma = mk_specialized_congr(m_tctx, e);
if (!congr_lemma)
return simp_result(e);
expr proof = congr_lemma->get_proof();
expr type = congr_lemma->get_type();
unsigned i = 0;
bool modified = false;
for_each(congr_lemma->get_arg_kinds(), [&](congr_arg_kind const & ckind) {
expr rfl;
switch (ckind) {
case congr_arg_kind::HEq:
lean_unreachable();
case congr_arg_kind::Fixed:
proof = mk_app(proof, args[i]);
type = instantiate(binding_body(type), args[i]);
break;
case congr_arg_kind::FixedNoParam:
break;
case congr_arg_kind::Eq:
proof = mk_app(proof, args[i]);
type = instantiate(binding_body(type), args[i]);
rfl = mk_eq_refl(m_tctx, args[i]);
proof = mk_app(proof, args[i], rfl);
type = instantiate(binding_body(type), args[i]);
type = instantiate(binding_body(type), rfl);
break;
case congr_arg_kind::Cast:
proof = mk_app(proof, args[i]);
type = instantiate(binding_body(type), args[i]);
expr const & arg_type = binding_domain(type);
expr new_arg;
if (!m_tctx.is_prop(arg_type)) {
auto it = m_subsingleton_elem_map.find(arg_type);
if (it != m_subsingleton_elem_map.end()) {
modified = (it->second != args[i]);
new_arg = it->second;
lean_trace_d(name({"simplifier", "subsingleton"}), tout() << args[i] << " ==> " << new_arg << "\n";);
} else {
new_arg = args[i];
m_subsingleton_elem_map.insert(mk_pair(arg_type, args[i]));
}
} else {
new_arg = args[i];
}
proof = mk_app(proof, new_arg);
type = instantiate(binding_body(type), new_arg);
break;
}
i++;
});
if (!modified)
return simp_result(e);
lean_assert(is_eq(type));
buffer<expr> type_args;
get_app_args(type, type_args);
expr e_new = type_args[2];
return simp_result(e_new, proof);
}
expr simplifier::remove_unnecessary_casts(expr const & e) {
buffer<expr> args;
expr f = get_app_args(e, args);
@ -1043,7 +941,6 @@ void initialize_simplify() {
register_trace_class(name({"simplifier", "context"}));
register_trace_class(name({"simplifier", "prove"}));
register_trace_class(name({"simplifier", "rewrite"}));
register_trace_class(name({"simplifier", "subsingleton"}));
register_trace_class(name({"debug", "simplifier", "try_rewrite"}));
register_trace_class(name({"debug", "simplifier", "try_congruence"}));
register_trace_class(name({"debug", "simplifier", "remove_casts"}));
@ -1056,7 +953,6 @@ void initialize_simplify() {
g_simplify_lift_eq = new name{*g_simplify_prefix, "lift_eq"};
g_simplify_canonize_instances_fixed_point = new name{*g_simplify_prefix, "canonize_instances_fixed_point"};
g_simplify_canonize_proofs_fixed_point = new name{*g_simplify_prefix, "canonize_proofs_fixed_point"};
g_simplify_canonize_subsingletons = new name{*g_simplify_prefix, "canonize_subsingletons"};
register_unsigned_option(*g_simplify_max_steps, LEAN_DEFAULT_SIMPLIFY_MAX_STEPS,
"(simplify) max number of (large) steps in simplification");
@ -1070,14 +966,11 @@ void initialize_simplify() {
"(simplify) canonize instances, replacing with the smallest seen so far until reaching a fixed point");
register_bool_option(*g_simplify_canonize_proofs_fixed_point, LEAN_DEFAULT_SIMPLIFY_CANONIZE_PROOFS_FIXED_POINT,
"(simplify) canonize proofs, replacing with the smallest seen so far until reaching a fixed point. ");
register_bool_option(*g_simplify_canonize_subsingletons, LEAN_DEFAULT_SIMPLIFY_CANONIZE_SUBSINGLETONS,
"(simplify) canonize_subsingletons");
DECLARE_VM_BUILTIN(name({"simp_lemmas", "simplify_core"}), simp_lemmas_simplify_core);
}
void finalize_simplify() {
delete g_simplify_canonize_subsingletons;
delete g_simplify_canonize_instances_fixed_point;
delete g_simplify_canonize_proofs_fixed_point;
delete g_simplify_lift_eq;

View file

@ -1,87 +0,0 @@
open tactic
namespace synth_congr
universe variable l
constants (ss : Π {A : Type.{l}}, A → Type.{l})
[ss_ss : ∀ T (t : T), subsingleton (ss t)]
(A : Type.{l})
(a₁ a₁' : A) (H₁ : a₁ = a₁')
(ss₁ : ss a₁)
(ss₁' : ss a₁')
(f : Π (X : Type.{l}) (x₁ : X) (ss_x₁ : ss x₁), Type.{l})
attribute [instance] ss_ss
attribute [simp] H₁
set_option trace.simplifier.subsingleton true
example : f A a₁ ss₁ = f A a₁' ss₁' := by simp
end synth_congr
namespace user_congr
universe variable l
constants (ss : Π {A : Type.{l}}, A → Type.{l})
[ss_ss : ∀ T (t : T), subsingleton (ss t)]
(A : Type.{l})
(a₁ a₁' : A) (H₁ : a₁ = a₁')
(ss₁ : ss a₁)
(ss₁' : ss a₁')
(f : Π (X : Type.{l}) (x₁ : X) (ss_x₁ : ss x₁), Type.{l})
(f_congr : Π (X : Type.{l}) (x₁ x₂ : X) (Hx : x₁ = x₂) (ss₁ : ss x₁), f X x₁ ss₁ = f X x₂ (eq.rec ss₁ Hx))
attribute [instance] ss_ss
attribute [simp] H₁
attribute [congr] f_congr
set_option trace.simplifier.subsingleton true
example : f A a₁ ss₁ = f A a₁' ss₁' := by simp
end user_congr
namespace lambda
universe variable l
constants (ss : Π {A : Type.{l}}, A → Type.{l})
[ss_ss : ∀ (T : Type*) (t : T), subsingleton (ss t)]
(A : Type.{l}) (a : A)
(ss₁ ss₂ : ss a)
attribute [instance] ss_ss
set_option trace.simplifier.subsingleton true
example : ss₁ = ss₂ := by simp
example : (λ p : Prop, ss₁) = (λ p : Prop, ss₂) := by simp
example : (λ (A : Type) (a : A), ss₁) = (λ (A : Type) (a : A), ss₂) := by simp
end lambda
namespace dont_crash_when_locals_incompatible
universe variables l
constants (ss : Π {A : Type.{l}}, A → Type.{l})
[ss_ss : ∀ (T : Type l) (t : T), subsingleton (ss t)]
(A : Type.{l}) (a : A)
(ss₁ ss₂ : ss a)
attribute [instance] ss_ss
-- This example works by accident. The first (_ : ss a) it encounters
-- has no locals, and is compatible with the second it finds so it
-- replaces the second with the first.
example : (λ (s : ss a), ss₁) = (λ (s : ss a), s) := by simp
-- This example fails because it finds the (_ : ss a) with the local
-- first. We do however avoid the error of replacing ss₁ with the local s.
-- TODO(dhs): the more robust solution is to maintain a set of canonical (_ : ss a)
-- for each subsingleton type, analogous to the defeq_canonizer.
lemma ex : (λ (s : ss a.{1}), s) = (λ (s : ss a.{1}), ss₁) :=
by do try simp,
f ← mk_const `funext,
apply f,
intro `s,
simp
end dont_crash_when_locals_incompatible

View file

@ -1,31 +0,0 @@
open tactic
universe variable l
constants (ss₁ : Type.{l} → Type.{l})
(ss₂ : Π {A : Type.{l}}, A → Type.{l})
[sss₁ : ∀ T, subsingleton (ss₁ T)]
[sss₂ : ∀ T (t : T), subsingleton (ss₂ t)]
(A B : Type.{l}) (HAB : A = B)
(ss_A : ss₁ A) (ss_B : ss₁ B)
(a₁ a₁' a₂ a₂' : A)
(H₁ : a₁ = a₁') (H₂ : a₂ = a₂')
(ss_a₁ : ss₂ a₁)
(ss_a₁' : ss₂ a₁')
(ss_a₂ : ss₂ a₂)
(ss_a₂' : ss₂ a₂')
(f : Π (X : Type.{l}) (ss_X : ss₁ X) (x₁ x₂ : X) (ss_x₁ : ss₂ x₁) (ss_x₂ : ss₂ x₂), Type.{l})
attribute [instance] sss₁
attribute [instance] sss₂
attribute [simp] HAB
attribute [simp] H₁
attribute [simp] H₂
example : f A ss_A a₁ a₂ ss_a₁ ss_a₂ = f A ss_A a₁' a₂' ss_a₁' ss_a₂' := by simp
attribute [reducible] noncomputable definition c₁' := a₁'
attribute [reducible] noncomputable definition c₂' := a₂'
example : f A ss_A a₁' a₂' ss_a₁' ss_a₂' = f A ss_A c₁' c₂' ss_a₁' ss_a₂' := by simp
example : f A ss_A a₁ a₂ ss_a₁ ss_a₂ = f A ss_A c₁' c₂' ss_a₁' ss_a₂' := by simp