Zulip Chat Archive
Stream: mathlib4
Topic: simp not using a simp lemma
Winston Yin (Nov 21 2022 at 07:21):
In the following example, why isn't simp
using map_one
?
import Mathlib.Data.FunLike.Basic
variable {M N P F : Type _} [MulOneClass M] [MulOneClass N]
structure OneHom (M : Type _) (N : Type _) [One M] [One N] where
toFun : M → N
map_one' : toFun 1 = 1
class OneHomClass (F : Type _) (M N : outParam <| Type _)
[outParam <| One M] [outParam <| One N] extends FunLike F M fun _ => N where
map_one : ∀ f : F, f 1 = 1
instance OneHom.oneHomClass : OneHomClass (OneHom M N) M N where
coe := OneHom.toFun
coe_injective' f g h := by cases f; cases g; congr
map_one := OneHom.map_one'
@[simp]
theorem map_one [OneHomClass F M N] (f : F) : f 1 = 1 :=
OneHomClass.map_one f
structure MulHom (M : Type _) (N : Type _) [Mul M] [Mul N] where
toFun : M → N
map_mul' : ∀ x y, toFun (x * y) = toFun x * toFun y
infixr:25 " →ₙ* " => MulHom
class MulHomClass (F : Type _) (M N : outParam <| Type _)
[outParam <| Mul M] [outParam <| Mul N] extends FunLike F M fun _ => N where
map_mul : ∀ (f : F) (x y : M), f (x * y) = f x * f y
@[simp]
theorem map_mul [MulHomClass F M N] (f : F) (x y : M) : f (x * y) = f x * f y :=
MulHomClass.map_mul f x y
structure MonoidHom (M : Type _) (N : Type _) [MulOneClass M] [MulOneClass N] extends
OneHom M N, M →ₙ* N
class MonoidHomClass (F : Type _) (M N : outParam <| Type _)
[outParam <| MulOneClass M] [outParam <| MulOneClass N] extends
MulHomClass F M N, OneHomClass F M N
infixr:25 " →* " => MonoidHom
instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where
coe f := f.toFun
coe_injective' f g h := by
cases f
cases g
congr
apply OneHom.oneHomClass.coe_injective'
exact h
map_mul := MonoidHom.map_mul'
map_one f := f.toOneHom.map_one'
def MonoidHom.comp [MulOneClass M] [MulOneClass N] [MulOneClass P] (hnp : N →* P) (hmn : M →* N) : M →* P where
toFun := hnp ∘ hmn
map_one' := by simp [-FunLike.coe_eq_coe_fn]; rw [map_one, map_one] -- map_one can be applied manually
-- fails to complete goal: by simp [-FunLike.coe_eq_coe_fn]
map_mul' := by simp [-FunLike.coe_eq_coe_fn]
Eric Rodriguez (Nov 21 2022 at 11:22):
I wonder if this is the same issue as I'm having with EmbeddingLike, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/EmbeddingLike
Eric Rodriguez (Nov 21 2022 at 11:23):
I think this is likely a serious problem
Andrew Yang (Nov 21 2022 at 11:31):
Is this related to the head symbol simp optimization thingy?
Mario Carneiro (Nov 21 2022 at 11:36):
I can't replicate misread the issue
Scott Morrison (Nov 23 2022 at 19:28):
I wonder if this is the same as https://github.com/leanprover/lean4/issues/1869.
Winston Yin (Nov 24 2022 at 02:20):
Hmm that issue seems to be about simp
attribute applied to Prop
fields of structures. In my case, map_one
is defined as a standalone simp
theorem.
Reid Barton (Dec 22 2022 at 17:43):
Is this the same issue?
import Mathlib.Order.Hom.Basic
theorem ex {α : Type} [PartialOrder α] {x : α} : (OrderHom.id.comp OrderHom.id) x = x := by
dsimp only [OrderHom.comp_coe] -- no change
simp only [OrderHom.comp_coe] -- no change
rw [OrderHom.comp_coe] -- better!
rfl
Reid Barton (Dec 24 2022 at 17:52):
MWE
structure THom (a b : Type) : Type where
toFun : a → b
def THom.comp {a b c : Type} : THom a b → THom b c → THom a c :=
fun f g => ⟨g.1 ∘ f.1⟩
@[simp] theorem THom.comp_toFun {a b c : Type} (f : THom a b) (g : THom b c)
: (f.comp g).toFun = g.toFun ∘ f.toFun :=
rfl
def THom.id {a : Type} : THom a a := ⟨@_root_.id a⟩
theorem ex2 {a : Type} (x : a) : (THom.id.comp THom.id).toFun x = x :=
by
simp only [THom.comp_toFun] -- does nothing
rw [THom.comp_toFun] -- works
rfl
Reid Barton (Dec 24 2022 at 17:55):
Maybe simp
somehow can't simplify function applications properly?
Meta.Tactic.simp.unify] @THom.comp_toFun:1000, failed to unify
(THom.comp ?f ?g).toFun
with
THom.toFun (THom.comp THom.id THom.id) x
Reid Barton (Dec 24 2022 at 17:55):
Of course they don't unify, because of the x
Reid Barton (Dec 24 2022 at 17:57):
Looks like this is https://github.com/leanprover/lean4/issues/1937
Kevin Buzzard (Dec 24 2022 at 19:29):
Reid Barton said:
Of course they don't unify, because of the
x
I don't understand this. Why don't they unify? This works in Lean 3:
-- lean 3
structure THom (a b : Type) : Type :=
(toFun : a → b)
def THom.comp {a b c : Type} : THom a b → THom b c → THom a c :=
fun f g, ⟨g.1 ∘ f.1⟩
@[simp] theorem THom.comp_toFun {a b c : Type} (f : THom a b) (g : THom b c)
: (f.comp g).toFun = g.toFun ∘ f.toFun :=
rfl
def THom.id {a : Type} : THom a a := ⟨@_root_.id a⟩
theorem ex2 {a : Type} (x : a) : (THom.id.comp THom.id).toFun x = x :=
begin
simp only [THom.comp_toFun], -- does something
refl,
end
Kevin Buzzard (Dec 24 2022 at 19:30):
-- lean 4
example (f g : α → β) (h : f = g) (a : α) (b : β) : f a = b := by
simp only [h] -- does something
sorry
That unifies fine.
Reid Barton (Dec 24 2022 at 19:31):
Right, simp should work. But for some reason it tries to unify the LHS of comp_toFun
with the entire LHS of the goal--maybe because it counted some arguments wrong or something.
Reid Barton (Dec 24 2022 at 19:31):
Yeah, it is something more specific than "simp a function application, with a lemma about the function".
Reid Barton (Dec 24 2022 at 19:32):
On the lean4 issue linked above, @Anne Baanen says it happens when there is a structure field projection involved
Kevin Buzzard (Dec 24 2022 at 19:38):
Aah I see, I had not properly grokked the trace output.
Kevin Buzzard (Apr 28 2023 at 15:44):
Is this issue
import Mathlib.CategoryTheory.StructuredArrow
open CategoryTheory Limits
variable (C: Type _) [Category C] (D : Type _) [Category D]
(J : Type _) [SmallCategory J]
(F: C ⥤ D)
(K: J ⥤ C)
(c: Cone K)
(s: Cone (K ⋙ F))
(j₁ j₂: J) (φ: j₁ ⟶ j₂)
(f₁ f₂: s.pt ⟶ F.obj c.pt)
(foo : (StructuredArrow.mk (f₁ ≫ F.map (c.π.app j₂)) : StructuredArrow s.pt (K ⋙ F)) =
StructuredArrow.mk (s.π.app j₂))
(bar : (StructuredArrow.mk (f₁ ≫ F.map (c.π.app j₁)) : StructuredArrow s.pt (K ⋙ F)) =
StructuredArrow.mk (s.π.app j₁))
example: φ ≫ (eqToHom foo).right = (eqToHom bar).right ≫ φ := by
simp -- does nothing
rw [Comma.eqToHom_right] -- a `simp` lemma
simp -- small progress
rw [Comma.eqToHom_right] -- a `simp` lemma
simp
done
related to the discussion above or is this an unrelated problem?
Eric Wieser (May 08 2023 at 20:20):
This is about !4#3703, right?
Kevin Buzzard (May 08 2023 at 20:33):
I've left a porting note. It's here and again a few lines later.
Eric Wieser (May 08 2023 at 20:46):
Making StructuredArrow
reducible solves everything here
Eric Wieser (May 08 2023 at 20:49):
The problem is that eqToHom_right
is about Comma (Functor.fromPUnit S) T
, but our goal contains StructuredArrow S T
.
For whatever reason, simp
isn't happy to unfold things, but rw
is.
I suspect this is like #mathlib4 > LinearAlgebra.Dual, where making things reducible is the right call.
Sebastian Ullrich (May 08 2023 at 20:53):
A note on simp
debugging: you should always start with trace.Meta.Tactic.simp
. If, like here, it doesn't even say that it tried to apply the lemma and failed, then it's not a problem with TC synth or unification, but with simp lemma indexing (the discrimination tree)
Sebastian Ullrich (May 08 2023 at 22:01):
Eric Wieser said:
For whatever reason,
simp
isn't happy to unfold things, butrw
is.
Since StructuredArrow
is an implicit parameter to eqToHom
, it might be the case that rw
succeeds because the unifier always unfolds non-irreducible defs when visiting implicit parameters, while the discrimination tree does not have such a special case. In the end it is expected that simp lemma indexing trades some accuracy for performance.
Eric Wieser (May 08 2023 at 22:01):
In this particular case I don't think we're getting any advantage by not making the definition reducible
Eric Wieser (May 08 2023 at 22:02):
I will try it out in Mathlib3 to find out... (edit: #18973)
Sebastian Ullrich (May 08 2023 at 22:03):
That sounds like the right call, but just to further illustrate the issue: using
(eqToHom (C := no_index _) H).right = ...
in eqToHom_right
also fixes the proof
Kevin Buzzard (May 08 2023 at 22:26):
So should this change be made to mathlib?
Eric Wieser (May 08 2023 at 22:26):
Which change? Mine (#18973) or Sebastian's?
Kevin Buzzard (May 08 2023 at 22:34):
I was asking about Sebastian's but anything is fine. I just wanted to make progress with !4#3703
Eric Wieser (May 08 2023 at 22:37):
My preference would be to try these reducibility changes and see if that allows us to remove most of the workarounds from the file, rather than just merge things with the workaround and clean up later; but I've no feel for how important doing this file quickly is. The argument for sorting out the workarounds first is that it may make downstream files easier too.
Eric Wieser (May 08 2023 at 22:38):
I don't think @Sebastian Ullrich's solution scales very well here; we don't really want to tell lean that every lemma about Comma
should be no-indexed to allow it to work for semireducible aliases
Kevin Buzzard (May 08 2023 at 22:38):
I've just checked that Sebastian's suggested change lets me remove three workarounds in !4#3703; I'll now check that yours does too.
Eric Wieser (May 08 2023 at 22:40):
(To be clear sebastian's comment is very helpful here, especially for debugging; I just don't think it's something mathlib can exploit much)
Kevin Buzzard (May 08 2023 at 22:52):
Yeah your change also lets me remove the workarounds, although it breaks mathlib a bit more than Sebastian's suggestion (I also had to edit CategoryTheory.Elements
(I had to add two rfl
s after simp
s) and CategoryTheory.Comma
(a new goal appeared which simp
closed))
Last updated: Dec 20 2023 at 11:08 UTC