Zulip Chat Archive

Stream: mathlib4

Topic: simp lemmas with side conditions


Scott Morrison (Jun 15 2023 at 01:00):

I am confused about something. Why is a lemma like src4#LieHom.idealRange_eq_top_of_surjective marked as @[simp]? It has the side condition h : Function.Surjective f. I think simp would never be able to use this lemma.

Scott Morrison (Jun 15 2023 at 01:05):

Oh!!! My confusion is that this is a simp regression.

Scott Morrison (Jun 15 2023 at 01:07):

In Lean3:

@[simp] lemma ideal_range_eq_top_of_surjective (h : function.surjective f) : f.ideal_range =  :=
begin
  rw  f.range_eq_top at h,
  rw [ideal_range_eq_lie_span_range, h,  lie_subalgebra.coe_to_submodule,
     lie_submodule.coe_to_submodule_eq_iff, lie_submodule.top_coe_submodule,
      lie_subalgebra.top_coe_submodule, lie_submodule.coe_lie_span_submodule_eq_iff],
  use ,
  exact lie_submodule.top_coe_submodule,
end

example (h : function.surjective f) : f.ideal_range =  :=
by simp only [ideal_range_eq_top_of_surjective, h] -- works fine

while in Lean4

@[simp]
theorem idealRange_eq_top_of_surjective (h : Function.Surjective f) : f.idealRange =  := by
  rw [ f.range_eq_top] at h
  rw [idealRange_eq_lieSpan_range, h,  LieSubalgebra.coe_to_submodule, 
    LieSubmodule.coe_toSubmodule_eq_iff, LieSubmodule.top_coeSubmodule,
    LieSubalgebra.top_coe_submodule, LieSubmodule.coe_lieSpan_submodule_eq_iff]
  use 
  exact LieSubmodule.top_coeSubmodule
#align lie_hom.ideal_range_eq_top_of_surjective LieHom.idealRange_eq_top_of_surjective

example (h : Function.Surjective f) : f.idealRange =  := by
  simp only [idealRange_eq_top_of_surjective, h] -- doesn't do anything, so `by` fails with unsolved goals.

Scott Morrison (Jun 15 2023 at 01:10):

which minimises straightforwardly as oops.

Scott Morrison (Jun 15 2023 at 01:10):

Am I missing something!? How did we miss this?

Scott Morrison (Jun 15 2023 at 01:19):

The Lean4 failure, under set_option trace.Meta.Tactic.simp true, gives:

[Meta.Tactic.simp.discharge] >> discharge?: Function.Surjective f

[Meta.Tactic.simp.discharge] @LieHom.idealRange_eq_top_of_surjective, failed to discharge hypotheses
      Function.Surjective f

[Meta.Tactic.simp.unify] @eq_self:1000, failed to unify
      ?a = ?a
    with
      LieHom.idealRange f = 

Scott Morrison (Jun 15 2023 at 01:23):

even though h : Function.Surjective f is right there in the simp set.

Scott Morrison (Jun 15 2023 at 01:24):

and it's not that discharging side goals is completely broken:

def P : Prop := True
@[simp] theorem foo (h : P) : Nat = Int := by sorry
example (h : P) : Nat = Int := by simp only [foo, h]   -- works fine

Scott Morrison (Jun 15 2023 at 01:25):

I'm not sure in what direction I should be trying to minimize this.

Scott Morrison (Jun 15 2023 at 01:35):

Okay, partial minimisation:

-- Lean 3, works fine
import algebra.hom.group

variables {M N : Type*} [monoid M] [monoid N] (f : M →* N)
theorem foo (h : function.surjective f) : f 1 = 1 := by simp

example (h : function.surjective f) : f 1 = 1 := by simp only [foo, h]
-- Lean 4, fails
import Mathlib.Algebra.Hom.Group

variable [Monoid M] [Monoid N] (f : M →* N)
theorem foo (h : Function.Surjective f) : f 1 = 1 := by simp

example (h : Function.Surjective f) : f 1 = 1 := by simp only [foo, h]

Scott Morrison (Jun 15 2023 at 01:46):

And a mathlib-free minimization:

-- Lean 3, works fine
class one (α : Type _) :=
(one : α)

structure OneHom (M : Type _) (N : Type _) [one M] [one N] :=
(to_fun : M  N)
(map_one : to_fun one.one = one.one)

variables {M N : Type _} [one M] [one N] (f : OneHom M N)

theorem foo (h : function.surjective f.to_fun) : f.to_fun one.one = one.one := f.map_one

example (h : function.surjective f.to_fun) : f.to_fun one.one = one.one := by simp only [foo, h]
-- Lean 4, fails
@[reducible] def Function.Surjective (f : α  β) : Prop :=  b,  a, f a = b

class One (α : Type u) where
  one : α

structure OneHom (M : Type _) (N : Type _) [One M] [One N] where
  to_fun : M  N
  map_one : to_fun One.one = One.one

variable {M N : Type _} [One M] [One N] (f : OneHom M N)

theorem foo (h : Function.Surjective f.to_fun) : f.to_fun One.one = One.one := f.map_one

example (h : Function.Surjective f.to_fun) : f.to_fun One.one = One.one := by simp only [foo, h]

Scott Morrison (Jun 15 2023 at 01:47):

@Gabriel Ebner, @Mario Carneiro, do either of you recognise this, or see what I'm doing wrong here? It seems Lean 4 is having great difficulty discharging side goals of simp lemmas. :-(

Mario Carneiro (Jun 15 2023 at 01:50):

minimized some more:

-- Lean 4, fails
@[reducible] def Function.Surjective (f : α  β) : Prop :=  b,  a, f a = b

example (h : Function.Surjective f) : Function.Surjective f := by simp only [h]

Mario Carneiro (Jun 15 2023 at 01:51):

TBH it's not that surprising to me that this fails, the hypothesis has a lot of internal structure and simp is getting lost in the weeds, necessitating some additional theorems like (A -> True) = True to simplify it

Scott Morrison (Jun 15 2023 at 01:51):

Haha, nice :-) That's terrible. Just double checking:

-- Lean 3, works fine
example {α β : Type} {f : α  β} (h : function.surjective f) : function.surjective f := by simp only [h]

Mario Carneiro (Jun 15 2023 at 01:52):

which is why simp only doesn't work

Scott Morrison (Jun 15 2023 at 01:53):

It hadn't occurred to me until now that the @[reducible] was implicated here!

Mario Carneiro (Jun 15 2023 at 01:56):

I think it's not the full story however, the last two cases here have different behavior even though I only unfolded reducibles:

@[reducible] def Function.Surjective (f : α  β) : Prop :=  b,  a, f a = b

variable {f : α  β}
example (h :  b,  a, f a = b) :  b,  a, f a = b := by
  simp only [h] -- fails
example (h :  b,  a, f a = b) :  b,  a, f a = b := by
  simp only [h, implies_true] -- ok
example (h : Function.Surjective f) :  b,  a, f a = b := by
  simp only [h, implies_true] -- ok
example (h : Function.Surjective f) : Function.Surjective f := by
  simp only [h, implies_true] -- fails

Mario Carneiro (Jun 15 2023 at 01:57):

example (h :  b,  a, f a = b) : Function.Surjective f := by
  simp only [h, implies_true] -- fails

Scott Morrison (Jun 15 2023 at 01:58):

Curiously (at least) the first 1/3 of mathlib4 compiles just fine without @[reducible] on Function.Surjective.

Scott Morrison (Jun 15 2023 at 02:30):

!4#5063 removes @[reducible] from Function.Surjective.

Scott Morrison (Jun 15 2023 at 02:30):

and !4#5064 adds some simp lemmas that were missing, but become useful after this fix. (and which I needed for something else).

Gabriel Ebner (Jun 15 2023 at 02:41):

See also !4#375 which removed @[reducible] on Function.Injective.


Last updated: Dec 20 2023 at 11:08 UTC