Skip to content

Commit 0e883f0

Browse files
Sebi-Kumarjcommelin
andcommitted
feat(Topology): add definition for subpaths (leanprover-community#27261)
Define subpaths as restrictions of paths to subintervals, reparameterized to have domain `[0, 1]` and possibly with a reverse of direction. Prove their basic properties. This serves as an alternative to `Path.truncate` which is useful for the explicit construction of certain homotopies, in particular regarding the concatenation of subpaths. Co-authored-by: Johan Commelin <johan@commelin.net>
1 parent 6ec3a4c commit 0e883f0

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7379,6 +7379,7 @@ public import Mathlib.Topology.Specialization
73797379
public import Mathlib.Topology.Spectral.Basic
73807380
public import Mathlib.Topology.Spectral.Hom
73817381
public import Mathlib.Topology.Spectral.Prespectral
7382+
public import Mathlib.Topology.Subpath
73827383
public import Mathlib.Topology.TietzeExtension
73837384
public import Mathlib.Topology.Ultrafilter
73847385
public import Mathlib.Topology.UniformSpace.AbsoluteValue

Mathlib/Topology/Subpath.lean

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/-
2+
Copyright (c) 2025 Sebastian Kumar. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Sebastian Kumar
5+
-/
6+
module
7+
8+
public import Mathlib.AlgebraicTopology.FundamentalGroupoid.Basic
9+
10+
/-!
11+
# Subpaths
12+
13+
This file defines `Path.subpath` as a restriction of a path to a subinterval,
14+
reparameterized to have domain `[0, 1]` and possibly with a reverse of direction.
15+
16+
The main result `Path.Homotopy.subpathTransSubpath` shows that subpaths concatenate nicely.
17+
In particular: following the subpath of `γ` from `t₀` to `t₁`, and then that from `t₁` to `t₂`,
18+
is in natural homotopy with following the subpath of `γ` from `t₀` to `t₂`.
19+
20+
`Path.subpath` is similar in behavior to `Path.truncate`. When t₀ ≤ t₁, they are reparameterizations
21+
of each other (not yet proven). However, `Path.subpath` works without assuming an order on `t₀` and
22+
`t₁`, and is convenient for concrete manipulations (e.g., `Path.Homotopy.subpathTransSubpath`).
23+
24+
## TODO
25+
26+
Prove that `Path.truncateOfLE` and `Path.subpath` are reparameterizations of each other.
27+
-/
28+
29+
@[expose] public noncomputable section
30+
31+
open unitInterval Set Function
32+
33+
universe u
34+
35+
variable {X : Type u} [TopologicalSpace X] {a b : X}
36+
37+
namespace Path
38+
39+
/-- Auxillary function for defining subpaths. -/
40+
@[simp]
41+
def subpathAux (t₀ t₁ s : I) : I := ⟨(1 - s) * t₀ + s * t₁,
42+
(convex_Icc 0 1) t₀.prop t₁.prop (one_minus_nonneg s) s.prop.left (sub_add_cancel 1 _)⟩
43+
44+
lemma subpathAux_zero (t₀ t₁ : I) : subpathAux t₀ t₁ 0 = t₀ := by simp
45+
46+
lemma subpathAux_one (t₀ t₁ : I) : subpathAux t₀ t₁ 1 = t₁ := by simp
47+
48+
/-- `subpathAux` is continuous as an uncurried function `I × I × I → I`. -/
49+
@[continuity, fun_prop]
50+
lemma subpathAux_continuous : Continuous (fun x ↦ subpathAux x.1 x.2.1 x.2.2 : I × I × I → I) := by
51+
unfold subpathAux
52+
fun_prop
53+
54+
/-- The subpath of `γ` from `t₀` to `t₁`. -/
55+
def subpath (γ : Path a b) (t₀ t₁ : I) : Path (γ t₀) (γ t₁) where
56+
toFun := γ ∘ (subpathAux t₀ t₁)
57+
source' := by rw [comp_apply, subpathAux_zero]
58+
target' := by rw [comp_apply, subpathAux_one]
59+
continuous_toFun := by fun_prop
60+
61+
/-- Reversing `γ.subpath t₀ t₁` results in `γ.subpath t₁ t₀`. -/
62+
@[simp]
63+
theorem symm_subpath (γ : Path a b) (t₀ t₁ : I) : symm (γ.subpath t₀ t₁) = γ.subpath t₁ t₀ := by
64+
ext s
65+
simp [subpath, add_comm]
66+
67+
lemma range_subpathAux (t₀ t₁ : I) : range (subpathAux t₀ t₁) = uIcc t₀ t₁ := by
68+
rw [range_eq_iff]
69+
constructor
70+
· intro s
71+
exact convex_uIcc (t₀ : ℝ) t₁ left_mem_uIcc right_mem_uIcc
72+
(one_minus_nonneg s) (nonneg s) (sub_add_cancel _ _)
73+
· intro t (ht : (t : ℝ) ∈ uIcc (t₀ : ℝ) (t₁ : ℝ))
74+
rw [← segment_eq_uIcc, segment_eq_image] at ht
75+
obtain ⟨s, hs, hst⟩ := ht
76+
use ⟨s, hs⟩
77+
ext
78+
exact hst
79+
80+
/-- The range of a subpath is the image of the original path on the relevant interval. -/
81+
@[simp]
82+
theorem range_subpath (γ : Path a b) (t₀ t₁ : I) :
83+
range (γ.subpath t₀ t₁) = γ '' (uIcc t₀ t₁) := by
84+
rw [← range_subpathAux, ← range_comp]
85+
rfl
86+
87+
lemma range_subpath_of_le (γ : Path a b) (t₀ t₁ : I) (h : t₀ ≤ t₁) :
88+
range (γ.subpath t₀ t₁) = γ '' (Icc t₀ t₁) := by
89+
simp [h]
90+
91+
lemma range_subpath_of_ge (γ : Path a b) (t₀ t₁ : I) (h : t₁ ≤ t₀) :
92+
range (γ.subpath t₀ t₁) = γ '' (Icc t₁ t₀) := by
93+
simp [h]
94+
95+
/-- The subpath of `γ` from `t` to `t` is just the constant path at `γ t`. -/
96+
@[simp]
97+
theorem subpath_self (γ : Path a b) (t : I) : γ.subpath t t = Path.refl (γ t) := by
98+
ext s
99+
simp [subpath, ← add_mul, sub_add_cancel, one_mul]
100+
101+
/-- The subpath of `γ` from `0` to `1` is just `γ`, with a slightly different type. -/
102+
@[simp]
103+
theorem subpath_zero_one (γ : Path a b) : γ.subpath 0 1 = γ.cast γ.source γ.target := by
104+
ext s
105+
simp [subpath]
106+
107+
/-- For a path `γ`, `γ.subpath` gives a "continuous family of paths", by which we mean
108+
the uncurried function which maps `(t₀, t₁, s)` to `γ.subpath t₀ t₁ s` is continuous. -/
109+
@[continuity]
110+
theorem subpath_continuous_family (γ : Path a b) :
111+
Continuous (fun x => γ.subpath x.1 x.2.1 x.2.2 : I × I × I → X) :=
112+
Continuous.comp' (map_continuous γ) subpathAux_continuous
113+
114+
namespace Homotopy
115+
116+
/-- Auxillary homotopy for `Path.Homotopy.subpathTransSubpath` which includes an unnecessary
117+
copy of `Path.refl`. -/
118+
def subpathTransSubpathRefl (γ : Path a b) (t₀ t₁ t₂ : I) : Homotopy
119+
((γ.subpath t₀ t₁).trans (γ.subpath t₁ t₂)) ((γ.subpath t₀ t₂).trans (Path.refl _)) where
120+
toFun x := ((γ.subpath t₀ (subpathAux t₁ t₂ x.1)).trans (γ.subpath _ t₂)) x.2
121+
continuous_toFun := by
122+
let γ₁ (t : I) := γ.subpath t₀ (subpathAux t₁ t₂ t)
123+
let γ₂ (t : I) := γ.subpath (subpathAux t₁ t₂ t) t₂
124+
refine Path.trans_continuous_family γ₁ ?_ γ₂ ?_ <;>
125+
refine γ.subpath_continuous_family.comp (.prodMk ?_ <| .prodMk ?_ ?_) <;>
126+
fun_prop
127+
map_zero_left := by
128+
intro _
129+
rw [subpathAux_zero]
130+
rfl
131+
map_one_left := by
132+
intro _
133+
rw [subpathAux_one, subpath_self]
134+
rfl
135+
prop' := by
136+
intro _ _ hx
137+
rcases hx with rfl | rfl <;>
138+
simp
139+
140+
/-- Following the subpath of `γ` from `t₀` to `t₁`, and then that from `t₁` to `t₂`,
141+
is in natural homotopy with following the subpath of `γ` from `t₀` to `t₂`. -/
142+
def subpathTransSubpath (γ : Path a b) (t₀ t₁ t₂ : I) : Homotopy
143+
((γ.subpath t₀ t₁).trans (γ.subpath t₁ t₂)) (γ.subpath t₀ t₂) :=
144+
trans (subpathTransSubpathRefl γ t₀ t₁ t₂) (transRefl _)
145+
146+
end Path.Homotopy
147+
end

0 commit comments

Comments
 (0)