Inserting return paths: a chain of paths is homotopic to the concatenation of the loops it splices, whenever the two outer return paths are nullhomotopic
ProvedPathCover.homotopic_concat_insertLet be a topological space and a basepoint. Fix and points of . Suppose given
- for each , a path from to ;
- for each , a path from to ;
and suppose and , and that and , read as loops at by means of those two equalities, are nullhomotopic.
Then, reading the concatenation as a loop at in the same way, it is homotopic rel endpoints to the concatenation of the loops
each of which is a loop at . Here denotes the reverse path.
Nothing at all is required of the intermediate paths beyond their endpoints: they need not come from any coherent system of choices, need not be related to the , and need not be distinct. The conclusion holds for every choice of them, which is stronger than a reader might expect.
The point is that the inserted return paths cancel: consecutive terms meet in , which is nullhomotopic, so the whole product telescopes back to — and the two outer factors are nullhomotopic by hypothesis.
Two conventions are worth stating. The bracketing of both sides is fixed by Path.concat, which folds from the left starting at the constant path, so a family of paths yields pieces, the first of them constant; homotopy rel endpoints absorbs the difference between any two bracketings, and the leading constant piece appears on both sides. And the hypothesis on and is nullhomotopy rather than equality to the constant path — the weakest form the argument supports. A caller who happens to hold literal equality gets the hypothesis in one line.
The conclusion is homotopy of the actual paths, not merely equality of their classes in the fundamental groupoid.
import Mathlib open scoped unitInterval
namespace PathCover
theorem homotopic_concat_insert {X : Type*} [TopologicalSpace X] (x0 : X) {n : ℕ}
(p : Fin (n + 1) → X)
(f : (k : Fin n) → Path (p k.castSucc) (p k.succ)) (g : (k : Fin (n + 1)) → Path x0 (p k))
(h0 : p 0 = x0) (hn : p (Fin.last n) = x0)
(hg0 : ((g 0).cast rfl h0.symm).Homotopic (Path.refl x0))
(hgn : ((g (Fin.last n)).cast rfl hn.symm).Homotopic (Path.refl x0)) :
((Path.concat p f).cast h0.symm hn.symm).Homotopic
(Path.concat (fun _ : Fin (n + 1) => x0)
(fun k => (g k.castSucc).trans ((f k).trans (g k.succ).symm))) := by
sorry
end PathCover