I have a new puzzle for simp debugging lovers. I tried to minimize but it's a very shy bug which very quickly disappear.
import Mathlib.Analysis.InnerProductSpace.Projection
lemma Prod.snd_mk { α β : Type * } ( a : α ) ( b : β ) : ( a , b ) . 2 = b := rfl
example { E : Type * } [ NormedAddCommGroup E ] [ InnerProductSpace ℝ E ] ( v : E ) ( t : ℝ ) :
orthogonalProjection ( Submodule.span ℝ {( t , v ) . snd }) = 0 := by
simp only [ Prod.snd_mk ] -- fails to make progress and to report it didn't make progress
-- dsimp only [Prod.snd_mk] -- works
sorry
The goal here is to get simp to transform (t, v).snd
into v
.
If you do it twice it doesn't make progress the second time
I think we're missing a congruence lemma for docs#orthogonalProjection , as it takes a dependently-typed argument
Or the auto-generated ones are broken
In 4 places of the expression, the following
| | | | |-' Prod.snd' -- app
| | | | | |-' Real' ' [] ' -- const
| | | | | |-' _uniq.2901' -- fvar
| | | | | |-' Prod.mk' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' _uniq.2905' -- fvar
| | | | | | |-' _uniq.2904' -- fvar
was replaced by
| | | | |-' _uniq.2904' -- fvar
inspect : ' orthogonalProjection ( Submodule.span ℝ {( t , v ) . snd }) = 0 '
' Eq' -- app
|-' ContinuousLinearMap' -- app
| |-' Real' ' [] ' -- const
| |-' Real' ' [] ' -- const
| |-' DivisionSemiring.toSemiring' -- app
| | |-' Real' ' [] ' -- const
| | |-' Semifield.toDivisionSemiring' -- app
| | | |-' Real' ' [] ' -- const
| | | |-' Field.toSemifield' -- app
| | | | |-' Real' ' [] ' -- const
| | | | |-' NormedField.toField' -- app
| | | | | |-' Real' ' [] ' -- const
| | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' Real.isROrC' ' [] ' -- const
| |-' DivisionSemiring.toSemiring' -- app
| | |-' Real' ' [] ' -- const
| | |-' Semifield.toDivisionSemiring' -- app
| | | |-' Real' ' [] ' -- const
| | | |-' Field.toSemifield' -- app
| | | | |-' Real' ' [] ' -- const
| | | | |-' NormedField.toField' -- app
| | | | | |-' Real' ' [] ' -- const
| | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' Real.isROrC' ' [] ' -- const
| |-' RingHom.id' -- app
| | |-' Real' ' [] ' -- const
| | |-' Semiring.toNonAssocSemiring' -- app
| | | |-' Real' ' [] ' -- const
| | | |-' DivisionSemiring.toSemiring' -- app
| | | | |-' Real' ' [] ' -- const
| | | | |-' Semifield.toDivisionSemiring' -- app
| | | | | |-' Real' ' [] ' -- const
| | | | | |-' Field.toSemifield' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' NormedField.toField' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | |-' Real.isROrC' ' [] ' -- const
| |-' _uniq.2901' -- fvar
| |-' UniformSpace.toTopologicalSpace' -- app
| | |-' _uniq.2901' -- fvar
| | |-' PseudoMetricSpace.toUniformSpace' -- app
| | | |-' _uniq.2901' -- fvar
| | | |-' SeminormedAddCommGroup.toPseudoMetricSpace' -- app
| | | | |-' _uniq.2901' -- fvar
| | | | |-' NormedAddCommGroup.toSeminormedAddCommGroup' -- app
| | | | | |-' _uniq.2901' -- fvar
| | | | | |-' _uniq.2902' -- fvar
| |-' AddCommGroup.toAddCommMonoid' -- app
| | |-' _uniq.2901' -- fvar
| | |-' NormedAddCommGroup.toAddCommGroup' -- app
| | | |-' _uniq.2901' -- fvar
| | | |-' _uniq.2902' -- fvar
| |-' Subtype' -- app
| | |-' _uniq.2901' -- fvar
| | |- ( 'x' ) -- lam
| | | |-' _uniq.2901' -- fvar
| | | |-' Membership.mem' -- app
| | | | |-' _uniq.2901' -- fvar
| | | | |-' Submodule' -- app
| | | | | |-' Real' ' [] ' -- const
| | | | | |-' _uniq.2901' -- fvar
| | | | | |-' DivisionSemiring.toSemiring' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' Semifield.toDivisionSemiring' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' Field.toSemifield' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' NormedField.toField' -- app
| | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | |-' AddCommGroup.toAddCommMonoid' -- app
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' NormedAddCommGroup.toAddCommGroup' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' _uniq.2902' -- fvar
| | | | | |-' NormedSpace.toModule' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | |-' NormedAddCommGroup.toSeminormedAddCommGroup' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' _uniq.2902' -- fvar
| | | | | | |-' InnerProductSpace.toNormedSpace' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | | |-' _uniq.2902' -- fvar
| | | | | | | |-' _uniq.2903' -- fvar
| | | | |-' SetLike.instMembership' -- app
| | | | | |-' Submodule' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' DivisionSemiring.toSemiring' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' Semifield.toDivisionSemiring' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' Field.toSemifield' -- app
| | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | |-' NormedField.toField' -- app
| | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | |-' AddCommGroup.toAddCommMonoid' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' NormedAddCommGroup.toAddCommGroup' -- app
| | | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | | |-' _uniq.2902' -- fvar
| | | | | | |-' NormedSpace.toModule' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | | |-' NormedAddCommGroup.toSeminormedAddCommGroup' -- app
| | | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | | |-' _uniq.2902' -- fvar
| | | | | | | |-' InnerProductSpace.toNormedSpace' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | | | |-' _uniq.2902' -- fvar
| | | | | | | | |-' _uniq.2903' -- fvar
| | | | | |-' _uniq.2901' -- fvar
| | | | | |-' Submodule.setLike' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' DivisionSemiring.toSemiring' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' Semifield.toDivisionSemiring' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' Field.toSemifield' -- app
| | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | |-' NormedField.toField' -- app
| | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | |-' AddCommGroup.toAddCommMonoid' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' NormedAddCommGroup.toAddCommGroup' -- app
| | | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | | |-' _uniq.2902' -- fvar
| | | | | | |-' NormedSpace.toModule' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | | |-' NormedAddCommGroup.toSeminormedAddCommGroup' -- app
| | | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | | |-' _uniq.2902' -- fvar
| | | | | | | |-' InnerProductSpace.toNormedSpace' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | | | |-' _uniq.2902' -- fvar
| | | | | | | | |-' _uniq.2903' -- fvar
| | | | |- '0' -- bvar
| | | | |-' Submodule.span' -- app
| | | | | |-' Real' ' [] ' -- const
| | | | | |-' _uniq.2901' -- fvar
| | | | | |-' Real.semiring' ' [] ' -- const
| | | | | |-' AddCommGroup.toAddCommMonoid' -- app
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' NormedAddCommGroup.toAddCommGroup' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' _uniq.2902' -- fvar
| | | | | |-' NormedSpace.toModule' -- app
| | | | | | |-' Real' ' [] ' -- const
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' DenselyNormedField.toNormedField' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' IsROrC.toDenselyNormedField' -- app
| | | | | | | | |-' Real' ' [] ' -- const
| | | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | |-' NormedAddCommGroup.toSeminormedAddCommGroup' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' _uniq.2902' -- fvar
| | | | | | |-' InnerProductSpace.toNormedSpace' -- app
| | | | | | | |-' Real' ' [] ' -- const
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | | |-' Real.isROrC' ' [] ' -- const
| | | | | | | |-' _uniq.2902' -- fvar
| | | | | | | |-' _uniq.2903' -- fvar
| | | | | |-' Singleton.singleton' -- app
| | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' Set' -- app
| | | | | | | |-' _uniq.2901' -- fvar
| | | | | | |-' Set.instSingletonSet' -- app
| | | | | | | |-' _uniq.2901' -- fvar
Interesting. So indeed simp
does something, but no what we expected.
Here's a hint, the congruence lemma for orthogonalProjection
needs to be a HEq
def orthogonalProjection.congr { 𝕜 E : Type * } [ IsROrC 𝕜 ] [ NormedAddCommGroup E ]
[ InnerProductSpace 𝕜 E ] ( K K' : Submodule 𝕜 E ) ( h : K = K' ) [ HasOrthogonalProjection K ] :
haveI : HasOrthogonalProjection K' := by cases h ; assumption
HEq ( orthogonalProjection K ) ( orthogonalProjection K' ) := by
congr !
Rewriting K
in orthogonalProjection K
changes the type
dsimp
can make progress because it's allowed to change K
to something that's defeq
Upon better inspection, it seems that simp
simplified the product inside the type of the left-hand side of the equality, but failed to enter the lhs and perform the substitution there.
Of the probably 22 places where the expression could change, simp
seems to only "see" 4, all inside the type and none in the actual terms.
Here you can see the locations where the relevant mvar appears, the end of the implicit argument to Eq.
and the beginning of the LHS.
image.png
Again this does not explain why the Lean 3 simplifier was happy to do its job and the Lean 4 simplifier isn't.
The diff highlights how the expression became, only the first 4 occurrences were rewritten.
No, this is just a text based description!
Sorry, it is bed-time! Have fun with this puzzle!
@Damiano Testa When simp
comes across "fixed" variables it will usually dsimp
them, but I'm not sure it will always do so.
(@Patrick Massot It doesn't help simp make progress, but I noticed that Prod.snd_mk
is specialized to Type
instead of Type*
!)
Oops, that's a copy-paste mistake.
I'll fix it in my post above to avoid confusion.
Last updated: Dec 20 2023 at 11:08 UTC