l3lab/ntp-mathlib huggingface dataset:
/--
Suppose `p` is a path, then we have a homotopy from `p` to `p.reparam f` by the convexity of `I`.
-/
def reparam (p : Path x₀ x₁) (f : I → I) (hf : Continuous f) (hf₀ : f 0 = 0) (hf₁ : f 1 = 1) :
    Homotopy p (p.reparam f hf hf₀ hf₁) where
  toFun x := p ⟨σ x.1 * x.2 + x.1 * f x.2,
    show (σ x.1 : ℝ) • (x.2 : ℝ) + (x.1 : ℝ) • (f x.2 : ℝ) ∈ I from
      convex_Icc _ _ x.2.2 (f x.2).2 (by unit_interval) (by unit_interval) (by simp)⟩
  map_zero_left x := by norm_num
  map_one_left x := by norm_num
  prop' t x hx := by
    cases' hx with hx hx
    · rw [hx]
      simp [hf₀]
    · rw [Set.mem_singleton_iff] at hx
      

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p : Path x₀ x₁
f : ↑I → ↑I
hf : Continuous f
hf₀ : f 0 = 0
hf₁ : f 1 = 1
t x : ↑I
hx : x = 1
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          {
              toContinuousMap :=
                ContinuousMap.mk fun x =>
                  p
                    { val := ↑(σ x.1) * ↑x.2 + ↑x.1 * ↑(f x.2),
                      property := (_ : ↑(σ x.1) • ↑x.2 + ↑x.1 • ↑(f x.2) ∈ I) },
              map_zero_left :=
                (_ :
                  ∀ (x : ↑I),
                    p
                        { val := ↑(σ (0, x).1) * ↑(0, x).2 + ↑(0, x).1 * ↑(f (0, x).2),
                          property := (_ : ↑(σ (0, x).1) • ↑(0, x).2 + ↑(0, x).1 • ↑(f (0, x).2) ∈ I) } =
                      p x),
              map_one_left :=
                (_ :
                  ∀ (x : ↑I),
                    p
                        { val := ↑(σ (1, x).1) * ↑(1, x).2 + ↑(1, x).1 * ↑(f (1, x).2),
                          property := (_ : ↑(σ (1, x).1) • ↑(1, x).2 + ↑(1, x).1 • ↑(f (1, x).2) ∈ I) } =
                      p (f x)) }.toContinuousMap
          (t, x))
      x =
    p.toContinuousMap x

Next tactic:
rw [hx]
/--
Suppose `p` is a path, then we have a homotopy from `p` to `p.reparam f` by the convexity of `I`.
-/
def reparam (p : Path x₀ x₁) (f : I → I) (hf : Continuous f) (hf₀ : f 0 = 0) (hf₁ : f 1 = 1) :
    Homotopy p (p.reparam f hf hf₀ hf₁) where
  toFun x := p ⟨σ x.1 * x.2 + x.1 * f x.2,
    show (σ x.1 : ℝ) • (x.2 : ℝ) + (x.1 : ℝ) • (f x.2 : ℝ) ∈ I from
      convex_Icc _ _ x.2.2 (f x.2).2 (by unit_interval) (by unit_interval) (by simp)⟩
  map_zero_left x := by norm_num
  map_one_left x := by norm_num
  prop' t x hx := by
    cases' hx with hx hx
    · rw [hx]
      simp [hf₀]
    · rw [Set.mem_singleton_iff] at hx
      rw [hx]
      

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p : Path x₀ x₁
f : ↑I → ↑I
hf : Continuous f
hf₀ : f 0 = 0
hf₁ : f 1 = 1
t x : ↑I
hx : x = 1
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          {
              toContinuousMap :=
                ContinuousMap.mk fun x =>
                  p
                    { val := ↑(σ x.1) * ↑x.2 + ↑x.1 * ↑(f x.2),
                      property := (_ : ↑(σ x.1) • ↑x.2 + ↑x.1 • ↑(f x.2) ∈ I) },
              map_zero_left :=
                (_ :
                  ∀ (x : ↑I),
                    p
                        { val := ↑(σ (0, x).1) * ↑(0, x).2 + ↑(0, x).1 * ↑(f (0, x).2),
                          property := (_ : ↑(σ (0, x).1) • ↑(0, x).2 + ↑(0, x).1 • ↑(f (0, x).2) ∈ I) } =
                      p x),
              map_one_left :=
                (_ :
                  ∀ (x : ↑I),
                    p
                        { val := ↑(σ (1, x).1) * ↑(1, x).2 + ↑(1, x).1 * ↑(f (1, x).2),
                          property := (_ : ↑(σ (1, x).1) • ↑(1, x).2 + ↑(1, x).1 • ↑(f (1, x).2) ∈ I) } =
                      p (f x)) }.toContinuousMap
          (t, x))
      1 =
    p.toContinuousMap 1

Next tactic:
simp [hf₁]
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
⊢ ∀ (x : ↑I), ContinuousMap.toFun (ContinuousMap.mk fun x => F (x.1, σ x.2)) (0, x) = (Path.symm p).toContinuousMap x

Next tactic:
simp [Path.symm]
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
⊢ ∀ (x : ↑I), ContinuousMap.toFun (ContinuousMap.mk fun x => F (x.1, σ x.2)) (1, x) = (Path.symm q).toContinuousMap x

Next tactic:
simp [Path.symm]
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by simp [Path.symm]
  prop' t x hx := by
    

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
t x : ↑I
hx : x ∈ {0, 1}
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk fun x => F (x.1, σ x.2),
              map_zero_left := (_ : ∀ (a : ↑I), F (0, σ a) = p (σ a)),
              map_one_left := (_ : ∀ (a : ↑I), F (1, σ a) = q (σ a)) }.toContinuousMap
          (t, x))
      x =
    (Path.symm p).toContinuousMap x

Next tactic:
cases' hx with hx hx
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by simp [Path.symm]
  prop' t x hx := by
    cases' hx with hx hx
    · 

Proof state:
case inl
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
t x : ↑I
hx : x = 0
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk fun x => F (x.1, σ x.2),
              map_zero_left := (_ : ∀ (a : ↑I), F (0, σ a) = p (σ a)),
              map_one_left := (_ : ∀ (a : ↑I), F (1, σ a) = q (σ a)) }.toContinuousMap
          (t, x))
      x =
    (Path.symm p).toContinuousMap x

Next tactic:
rw [hx]
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by simp [Path.symm]
  prop' t x hx := by
    cases' hx with hx hx
    · rw [hx]
      

Proof state:
case inl
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
t x : ↑I
hx : x = 0
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk fun x => F (x.1, σ x.2),
              map_zero_left := (_ : ∀ (a : ↑I), F (0, σ a) = p (σ a)),
              map_one_left := (_ : ∀ (a : ↑I), F (1, σ a) = q (σ a)) }.toContinuousMap
          (t, x))
      0 =
    (Path.symm p).toContinuousMap 0

Next tactic:
simp
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by simp [Path.symm]
  prop' t x hx := by
    cases' hx with hx hx
    · rw [hx]
      simp
    · 

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
t x : ↑I
hx : x ∈ {1}
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk fun x => F (x.1, σ x.2),
              map_zero_left := (_ : ∀ (a : ↑I), F (0, σ a) = p (σ a)),
              map_one_left := (_ : ∀ (a : ↑I), F (1, σ a) = q (σ a)) }.toContinuousMap
          (t, x))
      x =
    (Path.symm p).toContinuousMap x

Next tactic:
rw [Set.mem_singleton_iff] at hx
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by simp [Path.symm]
  prop' t x hx := by
    cases' hx with hx hx
    · rw [hx]
      simp
    · rw [Set.mem_singleton_iff] at hx
      

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
t x : ↑I
hx : x = 1
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk fun x => F (x.1, σ x.2),
              map_zero_left := (_ : ∀ (a : ↑I), F (0, σ a) = p (σ a)),
              map_one_left := (_ : ∀ (a : ↑I), F (1, σ a) = q (σ a)) }.toContinuousMap
          (t, x))
      x =
    (Path.symm p).toContinuousMap x

Next tactic:
rw [hx]
/-- Suppose `F : Homotopy p q`. Then we have a `Homotopy p.symm q.symm` by reversing the second
argument.
-/
@[simps]
def symm₂ {p q : Path x₀ x₁} (F : p.Homotopy q) : p.symm.Homotopy q.symm where
  toFun x := F ⟨x.1, σ x.2⟩
  map_zero_left := by simp [Path.symm]
  map_one_left := by simp [Path.symm]
  prop' t x hx := by
    cases' hx with hx hx
    · rw [hx]
      simp
    · rw [Set.mem_singleton_iff] at hx
      rw [hx]
      

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
t x : ↑I
hx : x = 1
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk fun x => F (x.1, σ x.2),
              map_zero_left := (_ : ∀ (a : ↑I), F (0, σ a) = p (σ a)),
              map_one_left := (_ : ∀ (a : ↑I), F (1, σ a) = q (σ a)) }.toContinuousMap
          (t, x))
      1 =
    (Path.symm p).toContinuousMap 1

Next tactic:
simp
/--
Given `F : Homotopy p q`, and `f : C(X, Y)`, we can define a homotopy from `p.map f.continuous` to
`q.map f.continuous`.
-/
@[simps]
def map {p q : Path x₀ x₁} (F : p.Homotopy q) (f : C(X, Y)) :
    Homotopy (p.map f.continuous) (q.map f.continuous) where
  toFun := f ∘ F
  map_zero_left := by 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
f : C(X, Y)
⊢ ∀ (x : ↑I),
    ContinuousMap.toFun (ContinuousMap.mk (⇑f ∘ ⇑F)) (0, x) = (Path.map p (_ : Continuous ⇑f)).toContinuousMap x

Next tactic:
simp
/--
Given `F : Homotopy p q`, and `f : C(X, Y)`, we can define a homotopy from `p.map f.continuous` to
`q.map f.continuous`.
-/
@[simps]
def map {p q : Path x₀ x₁} (F : p.Homotopy q) (f : C(X, Y)) :
    Homotopy (p.map f.continuous) (q.map f.continuous) where
  toFun := f ∘ F
  map_zero_left := by simp
  map_one_left := by 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
f : C(X, Y)
⊢ ∀ (x : ↑I),
    ContinuousMap.toFun (ContinuousMap.mk (⇑f ∘ ⇑F)) (1, x) = (Path.map q (_ : Continuous ⇑f)).toContinuousMap x

Next tactic:
simp
/--
Given `F : Homotopy p q`, and `f : C(X, Y)`, we can define a homotopy from `p.map f.continuous` to
`q.map f.continuous`.
-/
@[simps]
def map {p q : Path x₀ x₁} (F : p.Homotopy q) (f : C(X, Y)) :
    Homotopy (p.map f.continuous) (q.map f.continuous) where
  toFun := f ∘ F
  map_zero_left := by simp
  map_one_left := by simp
  prop' t x hx := by
    

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
f : C(X, Y)
t x : ↑I
hx : x ∈ {0, 1}
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk (⇑f ∘ ⇑F),
              map_zero_left := (_ : ∀ (a : ↑I), f (F (0, a)) = (Path.map p (_ : Continuous ⇑f)) a),
              map_one_left := (_ : ∀ (a : ↑I), f (F (1, a)) = (Path.map q (_ : Continuous ⇑f)) a) }.toContinuousMap
          (t, x))
      x =
    (Path.map p (_ : Continuous ⇑f)).toContinuousMap x

Next tactic:
cases' hx with hx hx
/--
Given `F : Homotopy p q`, and `f : C(X, Y)`, we can define a homotopy from `p.map f.continuous` to
`q.map f.continuous`.
-/
@[simps]
def map {p q : Path x₀ x₁} (F : p.Homotopy q) (f : C(X, Y)) :
    Homotopy (p.map f.continuous) (q.map f.continuous) where
  toFun := f ∘ F
  map_zero_left := by simp
  map_one_left := by simp
  prop' t x hx := by
    cases' hx with hx hx
    · 

Proof state:
case inl
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
f : C(X, Y)
t x : ↑I
hx : x = 0
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk (⇑f ∘ ⇑F),
              map_zero_left := (_ : ∀ (a : ↑I), f (F (0, a)) = (Path.map p (_ : Continuous ⇑f)) a),
              map_one_left := (_ : ∀ (a : ↑I), f (F (1, a)) = (Path.map q (_ : Continuous ⇑f)) a) }.toContinuousMap
          (t, x))
      x =
    (Path.map p (_ : Continuous ⇑f)).toContinuousMap x

Next tactic:
simp [hx]
/--
Given `F : Homotopy p q`, and `f : C(X, Y)`, we can define a homotopy from `p.map f.continuous` to
`q.map f.continuous`.
-/
@[simps]
def map {p q : Path x₀ x₁} (F : p.Homotopy q) (f : C(X, Y)) :
    Homotopy (p.map f.continuous) (q.map f.continuous) where
  toFun := f ∘ F
  map_zero_left := by simp
  map_one_left := by simp
  prop' t x hx := by
    cases' hx with hx hx
    · simp [hx]
    · 

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
f : C(X, Y)
t x : ↑I
hx : x ∈ {1}
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk (⇑f ∘ ⇑F),
              map_zero_left := (_ : ∀ (a : ↑I), f (F (0, a)) = (Path.map p (_ : Continuous ⇑f)) a),
              map_one_left := (_ : ∀ (a : ↑I), f (F (1, a)) = (Path.map q (_ : Continuous ⇑f)) a) }.toContinuousMap
          (t, x))
      x =
    (Path.map p (_ : Continuous ⇑f)).toContinuousMap x

Next tactic:
rw [Set.mem_singleton_iff] at hx
/--
Given `F : Homotopy p q`, and `f : C(X, Y)`, we can define a homotopy from `p.map f.continuous` to
`q.map f.continuous`.
-/
@[simps]
def map {p q : Path x₀ x₁} (F : p.Homotopy q) (f : C(X, Y)) :
    Homotopy (p.map f.continuous) (q.map f.continuous) where
  toFun := f ∘ F
  map_zero_left := by simp
  map_one_left := by simp
  prop' t x hx := by
    cases' hx with hx hx
    · simp [hx]
    · rw [Set.mem_singleton_iff] at hx
      

Proof state:
case inr
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p q : Path x₀ x₁
F : Homotopy p q
f : C(X, Y)
t x : ↑I
hx : x = 1
⊢ (ContinuousMap.mk fun x =>
        ContinuousMap.toFun
          { toContinuousMap := ContinuousMap.mk (⇑f ∘ ⇑F),
              map_zero_left := (_ : ∀ (a : ↑I), f (F (0, a)) = (Path.map p (_ : Continuous ⇑f)) a),
              map_one_left := (_ : ∀ (a : ↑I), f (F (1, a)) = (Path.map q (_ : Continuous ⇑f)) a) }.toContinuousMap
          (t, x))
      x =
    (Path.map p (_ : Continuous ⇑f)).toContinuousMap x

Next tactic:
simp [hx]
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₂ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ HEq ⟦p₁⟧ ⟦p₂⟧

Next tactic:
obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₂ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ x₀ = x₂

Next tactic:
convert hp 0
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> 

Proof state:
case h.e'_2
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₂ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ x₀ = p₁ 0

Next tactic:
simp
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> 

Proof state:
case h.e'_3
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₂ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ x₂ = p₂ 0

Next tactic:
simp
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₀ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ HEq ⟦p₁⟧ ⟦p₂⟧

Next tactic:
obtain rfl : x₁ = x₃ := by convert hp 1 <;> simp
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₀ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ x₁ = x₃

Next tactic:
convert hp 1
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by convert hp 1 <;> 

Proof state:
case h.e'_2
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₀ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ x₁ = p₁ 1

Next tactic:
simp
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by convert hp 1 <;> 

Proof state:
case h.e'_3
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ x₃ : X
p₁ : Path x₀ x₁
p₂ : Path x₀ x₃
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ x₃ = p₂ 1

Next tactic:
simp
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by convert hp 1 <;> simp
  

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ : X
p₁ p₂ : Path x₀ x₁
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ HEq ⟦p₁⟧ ⟦p₂⟧

Next tactic:
rw [heq_iff_eq]
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by convert hp 1 <;> simp
  rw [heq_iff_eq]; 

Proof state:
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ : X
p₁ p₂ : Path x₀ x₁
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ ⟦p₁⟧ = ⟦p₂⟧

Next tactic:
congr
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by convert hp 1 <;> simp
  rw [heq_iff_eq]; congr; 

Proof state:
case e_a
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ : X
p₁ p₂ : Path x₀ x₁
hp : ∀ (t : ↑I), p₁ t = p₂ t
⊢ p₁ = p₂

Next tactic:
ext t
theorem hpath_hext {p₁ : Path x₀ x₁} {p₂ : Path x₂ x₃} (hp : ∀ t, p₁ t = p₂ t) :
    @HEq (Path.Homotopic.Quotient _ _) ⟦p₁⟧ (Path.Homotopic.Quotient _ _) ⟦p₂⟧ := by
  obtain rfl : x₀ = x₂ := by convert hp 0 <;> simp
  obtain rfl : x₁ = x₃ := by convert hp 1 <;> simp
  rw [heq_iff_eq]; congr; ext t; 

Proof state:
case e_a.a.h
X : Type u
Y : Type v
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x₀ x₁ : X
p₁ p₂ : Path x₀ x₁
hp : ∀ (t : ↑I), p₁ t = p₂ t
t : ↑I
⊢ p₁ t = p₂ t

Next tactic:
exact hp t
/-- Two constant continuous maps with nonempty domain are homotopic if and only if their values are
joined by a path in the codomain. -/
@[simp]
theorem ContinuousMap.homotopic_const_iff [Nonempty Y] :
    (ContinuousMap.const Y x₀).Homotopic (ContinuousMap.const Y x₁) ↔ Joined x₀ x₁ := by
  

Proof state:
X : Type u
Y : Type v
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
inst✝ : Nonempty Y
⊢ Homotopic (const Y x₀) (const Y x₁) ↔ Joined x₀ x₁

Next tactic:
inhabit Y
/-- Two constant continuous maps with nonempty domain are homotopic if and only if their values are
joined by a path in the codomain. -/
@[simp]
theorem ContinuousMap.homotopic_const_iff [Nonempty Y] :
    (ContinuousMap.const Y x₀).Homotopic (ContinuousMap.const Y x₁) ↔ Joined x₀ x₁ := by
  inhabit Y
  

Proof state:
X : Type u
Y : Type v
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
inst✝ : Nonempty Y
inhabited_h : Inhabited Y
⊢ Homotopic (const Y x₀) (const Y x₁) ↔ Joined x₀ x₁

Next tactic:
refine ⟨fun ⟨H⟩ ↦ ⟨⟨(H.toContinuousMap.comp .prodSwap).curry default, ?_, ?_⟩⟩,
    fun ⟨p⟩ ↦ ⟨p.toHomotopyConst⟩⟩
/-- Two constant continuous maps with nonempty domain are homotopic if and only if their values are
joined by a path in the codomain. -/
@[simp]
theorem ContinuousMap.homotopic_const_iff [Nonempty Y] :
    (ContinuousMap.const Y x₀).Homotopic (ContinuousMap.const Y x₁) ↔ Joined x₀ x₁ := by
  inhabit Y
  refine ⟨fun ⟨H⟩ ↦ ⟨⟨(H.toContinuousMap.comp .prodSwap).curry default, ?_, ?_⟩⟩,
    fun ⟨p⟩ ↦ ⟨p.toHomotopyConst⟩⟩ <;> 

Proof state:
case refine_1
X : Type u
Y : Type v
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
inst✝ : Nonempty Y
inhabited_h : Inhabited Y
x✝ : Homotopic (const Y x₀) (const Y x₁)
H : Homotopy (const Y x₀) (const Y x₁)
⊢ ContinuousMap.toFun ((curry (comp H.toContinuousMap prodSwap)) default) 0 = x₀

Next tactic:
simp
/-- Two constant continuous maps with nonempty domain are homotopic if and only if their values are
joined by a path in the codomain. -/
@[simp]
theorem ContinuousMap.homotopic_const_iff [Nonempty Y] :
    (ContinuousMap.const Y x₀).Homotopic (ContinuousMap.const Y x₁) ↔ Joined x₀ x₁ := by
  inhabit Y
  refine ⟨fun ⟨H⟩ ↦ ⟨⟨(H.toContinuousMap.comp .prodSwap).curry default, ?_, ?_⟩⟩,
    fun ⟨p⟩ ↦ ⟨p.toHomotopyConst⟩⟩ <;> 

Proof state:
case refine_2
X : Type u
Y : Type v
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x₀ x₁ x₂ x₃ : X
inst✝ : Nonempty Y
inhabited_h : Inhabited Y
x✝ : Homotopic (const Y x₀) (const Y x₁)
H : Homotopy (const Y x₀) (const Y x₁)
⊢ ContinuousMap.toFun ((curry (comp H.toContinuousMap prodSwap)) default) 1 = x₁

Next tactic:
simp
/-- Inducts on the base `b` expansion of an ordinal. -/
@[elab_as_elim]
noncomputable def CNFRec (b : Ordinal) {C : Ordinal → Sort*} (H0 : C 0)
    (H : ∀ o, o ≠ 0 → C (o % b ^ log b o) → C o) : ∀ o, C o := fun o ↦ by
    

Proof state:
b : Ordinal.{?u.2}
C : Ordinal.{?u.2} → Sort u_1
H0 : C 0
H : (o : Ordinal.{?u.2}) → o ≠ 0 → C (o % b ^ log b o) → C o
o : Ordinal.{?u.2}
⊢ C o

Next tactic:
by_cases h : o = 0