Skip to content

Commit f9532ff

Browse files
committed
feat: grind golfing in Topology/Path (#31305)
This is not as exhaustive as I would have liked; there's plenty more cleanup to do here. But I need to pause on this for now and I think it's an improvement.
1 parent 1c10ceb commit f9532ff

File tree

5 files changed

+61
-91
lines changed

5 files changed

+61
-91
lines changed

Mathlib/Algebra/Order/Interval/Set/Instances.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ theorem coe_zero : ↑(0 : Icc (0 : R) 1) = (0 : R) :=
6464
theorem coe_one : ↑(1 : Icc (0 : R) 1) = (1 : R) :=
6565
rfl
6666

67-
@[simp]
67+
@[simp, grind =]
6868
theorem mk_zero (h : (0 : R) ∈ Icc (0 : R) 1) : (⟨0, h⟩ : Icc (0 : R) 1) = 0 :=
6969
rfl
7070

71-
@[simp]
71+
@[simp, grind =]
7272
theorem mk_one (h : (1 : R) ∈ Icc (0 : R) 1) : (⟨1, h⟩ : Icc (0 : R) 1) = 1 :=
7373
rfl
7474

@@ -169,7 +169,7 @@ instance instZero [Nontrivial R] : Zero (Ico (0 : R) 1) where zero := ⟨0, by s
169169
theorem coe_zero [Nontrivial R] : ↑(0 : Ico (0 : R) 1) = (0 : R) :=
170170
rfl
171171

172-
@[simp]
172+
@[simp, grind =]
173173
theorem mk_zero [Nontrivial R] (h : (0 : R) ∈ Ico (0 : R) 1) : (⟨0, h⟩ : Ico (0 : R) 1) = 0 :=
174174
rfl
175175

@@ -225,7 +225,7 @@ instance instOne : One (Ioc (0 : R) 1) where one := ⟨1, ⟨zero_lt_one, le_ref
225225
theorem coe_one : ↑(1 : Ioc (0 : R) 1) = (1 : R) :=
226226
rfl
227227

228-
@[simp]
228+
@[simp, grind =]
229229
theorem mk_one (h : (1 : R) ∈ Ioc (0 : R) 1) : (⟨1, h⟩ : Ioc (0 : R) 1) = 1 :=
230230
rfl
231231

Mathlib/AlgebraicTopology/FundamentalGroupoid/Basic.lean

Lines changed: 22 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -38,36 +38,19 @@ def reflTransSymmAux (x : I × I) : ℝ :=
3838
if (x.2 : ℝ) ≤ 1 / 2 then x.1 * 2 * x.2 else x.1 * (2 - 2 * x.2)
3939

4040
@[continuity, fun_prop]
41-
theorem continuous_reflTransSymmAux : Continuous reflTransSymmAux := by
42-
refine continuous_if_le ?_ ?_ (Continuous.continuousOn ?_) (Continuous.continuousOn ?_) ?_
43-
iterate 4 fun_prop
44-
intro x hx
45-
norm_num [hx, mul_assoc]
41+
theorem continuous_reflTransSymmAux : Continuous reflTransSymmAux :=
42+
continuous_if_le (by fun_prop) (by fun_prop) (by fun_prop) (by fun_prop) (by grind)
4643

4744
theorem reflTransSymmAux_mem_I (x : I × I) : reflTransSymmAux x ∈ I := by
4845
dsimp only [reflTransSymmAux]
4946
split_ifs
5047
· constructor
51-
· apply mul_nonneg
52-
· apply mul_nonneg
53-
· unit_interval
54-
· simp
55-
· unit_interval
48+
· apply mul_nonneg <;> grind
5649
· rw [mul_assoc]
57-
apply mul_le_one₀
58-
· unit_interval
59-
· apply mul_nonneg
60-
· simp
61-
· unit_interval
62-
· linarith
50+
apply mul_le_one₀ <;> grind
6351
· constructor
64-
· apply mul_nonneg
65-
· unit_interval
66-
linarith [unitInterval.nonneg x.2, unitInterval.le_one x.2]
67-
· apply mul_le_one₀
68-
· unit_interval
69-
· linarith [unitInterval.nonneg x.2, unitInterval.le_one x.2]
70-
· linarith [unitInterval.nonneg x.2, unitInterval.le_one x.2]
52+
· apply mul_nonneg <;> grind
53+
· apply mul_le_one₀ <;> grind
7154

7255
/-- For any path `p` from `x₀` to `x₁`, we have a homotopy from the constant path based at `x₀` to
7356
`p.trans p.symm`. -/
@@ -78,10 +61,10 @@ def reflTransSymm (p : Path x₀ x₁) : Homotopy (Path.refl x₀) (p.trans p.sy
7861
map_one_left x := by
7962
simp only [reflTransSymmAux, Path.trans]
8063
cases le_or_gt (x : ℝ) 2⁻¹ with
81-
| inl hx => simp [hx, ← extend_extends]
64+
| inl hx => simp [hx, ← extend_apply]
8265
| inr hx =>
8366
have : p.extend (2 - 2 * ↑x) = p.extend (1 - (2 * ↑x - 1)) := by ring_nf
84-
simpa [hx.not_ge, ← extend_extends]
67+
simpa [hx.not_ge, ← extend_apply]
8568
prop' t := by norm_num [reflTransSymmAux]
8669

8770
/-- For any path `p` from `x₀` to `x₁`, we have a homotopy from the constant path based at `x₁` to
@@ -98,11 +81,8 @@ def transReflReparamAux (t : I) : ℝ :=
9881
if (t : ℝ) ≤ 1 / 2 then 2 * t else 1
9982

10083
@[continuity, fun_prop]
101-
theorem continuous_transReflReparamAux : Continuous transReflReparamAux := by
102-
refine continuous_if_le ?_ ?_ (Continuous.continuousOn ?_) (Continuous.continuousOn ?_) ?_ <;>
103-
[fun_prop; fun_prop; fun_prop; fun_prop; skip]
104-
intro x hx
105-
simp [hx]
84+
theorem continuous_transReflReparamAux : Continuous transReflReparamAux :=
85+
continuous_if_le (by fun_prop) (by fun_prop) (by fun_prop) (by fun_prop) (by grind)
10686

10787
theorem transReflReparamAux_mem_I (t : I) : transReflReparamAux t ∈ I := by
10888
unfold transReflReparamAux
@@ -120,12 +100,8 @@ theorem trans_refl_reparam (p : Path x₀ x₁) :
120100
(Subtype.ext transReflReparamAux_zero) (Subtype.ext transReflReparamAux_one) := by
121101
ext
122102
unfold transReflReparamAux
123-
simp only [Path.trans_apply, coe_reparam, Function.comp_apply, one_div, Path.refl_apply]
124-
split_ifs
125-
· rfl
126-
· rfl
127-
· simp
128-
· simp
103+
simp only [coe_reparam]
104+
grind
129105

130106
/-- For any path `p` from `x₀` to `x₁`, we have a homotopy from `p.trans (Path.refl x₁)` to `p`. -/
131107
def transRefl (p : Path x₀ x₁) : Homotopy (p.trans (Path.refl x₁)) p :=
@@ -147,15 +123,10 @@ def transAssocReparamAux (t : I) : ℝ :=
147123
if (t : ℝ) ≤ 1 / 4 then 2 * t else if (t : ℝ) ≤ 1 / 2 then t + 1 / 4 else 1 / 2 * (t + 1)
148124

149125
@[continuity, fun_prop]
150-
theorem continuous_transAssocReparamAux : Continuous transAssocReparamAux := by
151-
refine continuous_if_le ?_ ?_ (Continuous.continuousOn ?_)
152-
(continuous_if_le ?_ ?_
153-
(Continuous.continuousOn ?_) (Continuous.continuousOn ?_) ?_).continuousOn
154-
?_ <;>
155-
[fun_prop; fun_prop; fun_prop; fun_prop; fun_prop; fun_prop; fun_prop; skip;
156-
skip] <;>
157-
· intro x hx
158-
norm_num [hx]
126+
theorem continuous_transAssocReparamAux : Continuous transAssocReparamAux :=
127+
continuous_if_le (by fun_prop) (by fun_prop) (by fun_prop)
128+
(continuous_if_le (by fun_prop) (by fun_prop) (by fun_prop) (by fun_prop)
129+
(by grind)).continuousOn (by grind)
159130

160131
theorem transAssocReparamAux_mem_I (t : I) : transAssocReparamAux t ∈ I := by
161132
unfold transAssocReparamAux
@@ -173,16 +144,12 @@ theorem trans_assoc_reparam {x₀ x₁ x₂ x₃ : X} (p : Path x₀ x₁) (q :
173144
(fun t => ⟨transAssocReparamAux t, transAssocReparamAux_mem_I t⟩) (by fun_prop)
174145
(Subtype.ext transAssocReparamAux_zero) (Subtype.ext transAssocReparamAux_one) := by
175146
ext x
176-
simp only [transAssocReparamAux, Path.trans_apply, Function.comp_apply, mul_ite, Path.coe_reparam]
177-
-- TODO: why does split_ifs not reduce the ifs??????
178-
split_ifs with h₁ h₂ h₃ h₄ h₅
179-
· rfl
180-
iterate 6 exfalso; linarith
181-
· have h : 2 * (2 * (x : ℝ)) - 1 = 2 * (2 * (↑x + 1 / 4) - 1) := by linarith
182-
simp [h]
183-
iterate 6 exfalso; linarith
184-
· congr
185-
ring
147+
simp only [transAssocReparamAux, Path.trans_apply, Function.comp_apply, Path.coe_reparam]
148+
split_ifs
149+
iterate 12 grind
150+
· linarith
151+
· linarith
152+
· grind
186153

187154
/-- For paths `p q r`, we have a homotopy from `(p.trans q).trans r` to `p.trans (q.trans r)`. -/
188155
def transAssoc {x₀ x₁ x₂ x₃ : X} (p : Path x₀ x₁) (q : Path x₁ x₂) (r : Path x₂ x₃) :

Mathlib/Topology/Homotopy/Path.lean

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ theorem target (F : Homotopy p₀ p₁) (t : I) : F (t, 1) = x₁ :=
6767

6868
/-- Evaluating a path homotopy at an intermediate point, giving us a `Path`.
6969
-/
70+
@[simps]
7071
def eval (F : Homotopy p₀ p₁) (t : I) : Path x₀ x₁ where
7172
toFun := F.toHomotopy.curry t
7273
source' := by simp
@@ -75,12 +76,12 @@ def eval (F : Homotopy p₀ p₁) (t : I) : Path x₀ x₁ where
7576
@[simp]
7677
theorem eval_zero (F : Homotopy p₀ p₁) : F.eval 0 = p₀ := by
7778
ext t
78-
simp [eval]
79+
simp
7980

8081
@[simp]
8182
theorem eval_one (F : Homotopy p₀ p₁) : F.eval 1 = p₁ := by
8283
ext t
83-
simp [eval]
84+
simp
8485

8586
end
8687

@@ -163,7 +164,7 @@ theorem hcomp_apply (F : Homotopy p₀ q₀) (G : Homotopy p₁ q₁) (x : I ×
163164
else
164165
G.eval x.1
165166
2 * x.2 - 1, unitInterval.two_mul_sub_one_mem_iff.2 ⟨(not_le.1 h).le, x.2.2.2⟩⟩ :=
166-
show ite _ _ _ = _ by split_ifs <;> exact Path.extend_extends _ _
167+
show ite _ _ _ = _ by split_ifs <;> exact Path.extend_apply _ _
167168

168169
theorem hcomp_half (F : Homotopy p₀ q₀) (G : Homotopy p₁ q₁) (t : I) :
169170
F.hcomp G (t, ⟨1 / 2, by norm_num, by norm_num⟩) = x₁ :=

Mathlib/Topology/Path.lean

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ instance Path.instFunLike : FunLike (Path x y) I X where
6666
instance Path.continuousMapClass : ContinuousMapClass (Path x y) I X where
6767
map_continuous γ := show Continuous γ.toContinuousMap by fun_prop
6868

69-
@[ext]
69+
@[ext, grind ext]
7070
protected theorem Path.ext : ∀ {γ₁ γ₂ : Path x y}, (γ₁ : I → X) = γ₂ → γ₁ = γ₂ := by
7171
rintro ⟨⟨x, h11⟩, h12, h13⟩ ⟨⟨x, h21⟩, h22, h23⟩ rfl
7272
rfl
@@ -87,11 +87,11 @@ variable (γ : Path x y)
8787
protected theorem continuous : Continuous γ :=
8888
γ.continuous_toFun
8989

90-
@[simp]
90+
@[simp, grind =]
9191
protected theorem source : γ 0 = x :=
9292
γ.source'
9393

94-
@[simp]
94+
@[simp, grind =]
9595
protected theorem target : γ 1 = y :=
9696
γ.target'
9797

@@ -123,16 +123,16 @@ instance instHasUncurryPath {α : Type*} {x y : α → X} :
123123
HasUncurry (∀ a : α, Path (x a) (y a)) (α × I) X :=
124124
fun φ p => φ p.1 p.2
125125

126-
@[simp high]
126+
@[simp high, grind! .]
127127
lemma source_mem_range (γ : Path x y) : x ∈ range ⇑γ :=
128128
0, Path.source γ⟩
129129

130-
@[simp high]
130+
@[simp high, grind! .]
131131
lemma target_mem_range (γ : Path x y) : y ∈ range ⇑γ :=
132132
1, Path.target γ⟩
133133

134134
/-- The constant path from a point to itself -/
135-
@[refl, simps!]
135+
@[refl, simps! (attr := grind =)]
136136
def refl (x : X) : Path x x where
137137
toContinuousMap := .const I x
138138
source' := rfl
@@ -142,18 +142,15 @@ def refl (x : X) : Path x x where
142142
theorem refl_range {a : X} : range (Path.refl a) = {a} := range_const
143143

144144
/-- The reverse of a path from `x` to `y`, as a path from `y` to `x` -/
145-
@[symm, simps]
145+
@[symm, simps (attr := grind =)]
146146
def symm (γ : Path x y) : Path y x where
147147
toFun := γ ∘ σ
148148
continuous_toFun := by fun_prop
149149
source' := by simp
150150
target' := by simp
151151

152152
@[simp]
153-
theorem symm_symm (γ : Path x y) : γ.symm.symm = γ := by
154-
ext t
155-
change γ (σ (σ t)) = γ t
156-
rw [unitInterval.symm_symm]
153+
theorem symm_symm (γ : Path x y) : γ.symm.symm = γ := by grind
157154

158155
theorem symm_bijective : Function.Bijective (Path.symm : Path x y → Path y x) :=
159156
Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩
@@ -218,11 +215,14 @@ theorem _root_.ContinuousAt.pathExtend {g : Y → ℝ} {l r : Y → X} (γ : ∀
218215
@[deprecated (since := "2025-05-02")]
219216
alias _root_.ContinuousAt.path_extend := ContinuousAt.pathExtend
220217

221-
@[simp]
222-
theorem extend_extends {a b : X} (γ : Path a b) {t : ℝ}
218+
@[simp, grind =]
219+
theorem extend_apply {a b : X} (γ : Path a b) {t : ℝ}
223220
(ht : t ∈ (Icc 0 1 : Set ℝ)) : γ.extend t = γ ⟨t, ht⟩ :=
224221
IccExtend_of_mem _ γ ht
225222

223+
@[deprecated (since := "2025-11-05")]
224+
alias extend_extends := extend_apply
225+
226226
theorem extend_zero : γ.extend 0 = x := by simp
227227

228228
theorem extend_one : γ.extend 1 = y := by simp
@@ -289,11 +289,12 @@ def trans (γ : Path x y) (γ' : Path y z) : Path x z where
289289
source' := by simp
290290
target' := by norm_num
291291

292+
@[grind =]
292293
theorem trans_apply (γ : Path x y) (γ' : Path y z) (t : I) :
293294
(γ.trans γ') t =
294295
if h : (t : ℝ) ≤ 1 / 2 then γ ⟨2 * t, (mul_pos_mem_iff zero_lt_two).2 ⟨t.2.1, h⟩⟩
295296
else γ' ⟨2 * t - 1, two_mul_sub_one_mem_iff.2 ⟨(not_le.1 h).le, t.2.2⟩⟩ :=
296-
show ite _ _ _ = _ by split_ifs <;> rw [extend_extends]
297+
show ite _ _ _ = _ by split_ifs <;> rw [extend_apply]
297298

298299
@[simp]
299300
theorem trans_symm (γ : Path x y) (γ' : Path y z) : (γ.trans γ').symm = γ'.symm.trans γ.symm := by
@@ -314,7 +315,7 @@ theorem extend_trans_of_le_half (γ₁ : Path x y) (γ₂ : Path y z) {t : ℝ}
314315
(γ₁.trans γ₂).extend t = γ₁.extend (2 * t) := by
315316
obtain _ | ht₀ := le_total t 0
316317
· repeat rw [extend_of_le_zero _ (by linarith)]
317-
· rwa [extend_extends _ ⟨ht₀, by linarith⟩, trans_apply, dif_pos, extend_extends]
318+
· rwa [extend_apply _ ⟨ht₀, by linarith⟩, trans_apply, dif_pos, extend_apply]
318319

319320
theorem extend_trans_of_half_le (γ₁ : Path x y) (γ₂ : Path y z) {t : ℝ} (ht : 1 / 2 ≤ t) :
320321
(γ₁.trans γ₂).extend t = γ₂.extend (2 * t - 1) := by
@@ -349,7 +350,7 @@ def map' (γ : Path x y) {f : X → Y} (h : ContinuousOn f (range γ)) : Path (f
349350
def map (γ : Path x y) {f : X → Y} (h : Continuous f) :
350351
Path (f x) (f y) := γ.map' h.continuousOn
351352

352-
@[simp]
353+
@[simp, grind =]
353354
theorem map_coe (γ : Path x y) {f : X → Y} (h : Continuous f) :
354355
(γ.map h : I → Y) = f ∘ γ := by
355356
ext t
@@ -364,8 +365,8 @@ theorem map_symm (γ : Path x y) {f : X → Y} (h : Continuous f) :
364365
theorem map_trans (γ : Path x y) (γ' : Path y z) {f : X → Y}
365366
(h : Continuous f) : (γ.trans γ').map h = (γ.map h).trans (γ'.map h) := by
366367
ext t
367-
rw [trans_apply, map_coe, Function.comp_apply, trans_apply]
368-
split_ifs <;> rfl
368+
rw [trans_apply, map_coe, Function.comp_apply, trans_apply, map_coe, map_coe]
369+
grind
369370

370371
@[simp]
371372
theorem map_id (γ : Path x y) : γ.map continuous_id = γ := by
@@ -478,19 +479,18 @@ protected def prod (γ₁ : Path a₁ a₂) (γ₂ : Path b₁ b₂) : Path (a
478479
source' := by simp
479480
target' := by simp
480481

481-
@[simp]
482+
@[simp, grind =]
482483
theorem prod_coe (γ₁ : Path a₁ a₂) (γ₂ : Path b₁ b₂) :
483484
⇑(γ₁.prod γ₂) = fun t => (γ₁ t, γ₂ t) :=
484485
rfl
485486

486487
/-- Path composition commutes with products -/
487488
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
488489
(δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
490+
unfold Path.trans
489491
ext t <;>
490-
unfold Path.trans <;>
491-
simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
492-
split_ifs <;>
493-
rfl
492+
· simp only [Path.coe_mk_mk, Path.prod_coe]
493+
grind
494494

495495
end Prod
496496

@@ -505,7 +505,7 @@ protected def pi (γ : ∀ i, Path (as i) (bs i)) : Path as bs where
505505
source' := by simp
506506
target' := by simp
507507

508-
@[simp]
508+
@[simp, grind =]
509509
theorem pi_coe (γ : ∀ i, Path (as i) (bs i)) : ⇑(Path.pi γ) = fun t i => γ i t :=
510510
rfl
511511

@@ -515,7 +515,9 @@ theorem trans_pi_eq_pi_trans (γ₀ : ∀ i, Path (as i) (bs i)) (γ₁ : ∀ i,
515515
ext t i
516516
unfold Path.trans
517517
simp only [Path.coe_mk_mk, Function.comp_apply, pi_coe]
518-
split_ifs <;> rfl
518+
split_ifs
519+
· rfl
520+
· rfl
519521

520522
end Pi
521523

Mathlib/Topology/UnitInterval.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,23 @@ def symm : I → I := fun t => ⟨1 - t, Icc.mem_iff_one_sub_mem.mp t.prop⟩
6969
@[inherit_doc]
7070
scoped notation "σ" => unitInterval.symm
7171

72-
@[simp]
72+
@[simp, grind =]
7373
theorem symm_zero : σ 0 = 1 :=
7474
Subtype.ext <| by simp [symm]
7575

76-
@[simp]
76+
@[simp, grind =]
7777
theorem symm_one : σ 1 = 0 :=
7878
Subtype.ext <| by simp [symm]
7979

80-
@[simp]
80+
@[simp, grind =]
8181
theorem symm_symm (x : I) : σ (σ x) = x :=
8282
Subtype.ext <| by simp [symm]
8383

8484
theorem symm_involutive : Function.Involutive (symm : I → I) := symm_symm
8585

8686
theorem symm_bijective : Function.Bijective (symm : I → I) := symm_involutive.bijective
8787

88-
@[simp]
88+
@[simp, grind =]
8989
theorem coe_symm_eq (x : I) : (σ x : ℝ) = 1 - x :=
9090
rfl
9191

0 commit comments

Comments
 (0)