l3lab/ntp-mathlib huggingface dataset:
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
⊢ Continuous fun p =>
    {
        toContinuousMap :=
          ContinuousMap.mk fun x => if ↑x ≤ 1 / 2 then extend (γ₁ p.1) (2 * ↑x) else extend (γ₂ p.1) (2 * ↑x - 1),
        source' :=
          (_ :
            ContinuousMap.toFun
                (ContinuousMap.mk fun x =>
                  if ↑x ≤ 1 / 2 then extend (γ₁ p.1) (2 * ↑x) else extend (γ₂ p.1) (2 * ↑x - 1))
                0 =
              a p.1),
        target' :=
          (_ :
            ContinuousMap.toFun
                (ContinuousMap.mk fun x =>
                  if ↑x ≤ 1 / 2 then extend (γ₁ p.1) (2 * ↑x) else extend (γ₂ p.1) (2 * ↑x - 1))
                1 =
              c p.1) }
      p.2

Next tactic:
refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
  · 

Proof state:
case refine'_1
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
⊢ Continuous fun p => extend (γ₁ p.1) (2 * ↑p.2)

Next tactic:
change
      Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ))
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
  · change
      Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ))
    

Proof state:
case refine'_1
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
⊢ Continuous ((fun p => extend (γ₁ p.1) p.2) ∘ Prod.map id fun x => 2 * ↑x)

Next tactic:
exact h₁'.comp (continuous_id.prod_map <| continuous_const.mul continuous_subtype_val)
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
  · change
      Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ))
    exact h₁'.comp (continuous_id.prod_map <| continuous_const.mul continuous_subtype_val)
  · 

Proof state:
case refine'_2
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
⊢ Continuous fun p => extend (γ₂ p.1) (2 * ↑p.2 - 1)

Next tactic:
change
      Continuous ((fun p : ι × ℝ => (γ₂ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x - 1 : I → ℝ))
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
  · change
      Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ))
    exact h₁'.comp (continuous_id.prod_map <| continuous_const.mul continuous_subtype_val)
  · change
      Continuous ((fun p : ι × ℝ => (γ₂ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x - 1 : I → ℝ))
    

Proof state:
case refine'_2
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
⊢ Continuous ((fun p => extend (γ₂ p.1) p.2) ∘ Prod.map id fun x => 2 * ↑x - 1)

Next tactic:
exact
      h₂'.comp
        (continuous_id.prod_map <|
          (continuous_const.mul continuous_subtype_val).sub continuous_const)
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
  · change
      Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ))
    exact h₁'.comp (continuous_id.prod_map <| continuous_const.mul continuous_subtype_val)
  · change
      Continuous ((fun p : ι × ℝ => (γ₂ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x - 1 : I → ℝ))
    exact
      h₂'.comp
        (continuous_id.prod_map <|
          (continuous_const.mul continuous_subtype_val).sub continuous_const)
  · 

Proof state:
case refine'_3
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
⊢ ∀ (x : ι × ↑I), ↑x.2 = 1 / 2 → extend (γ₁ x.1) (2 * ↑x.2) = extend (γ₂ x.1) (2 * ↑x.2 - 1)

Next tactic:
rintro st hst
@[continuity]
theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι]
    {a b c : ι → X} (γ₁ : ∀ t : ι, Path (a t) (b t)) (h₁ : Continuous ↿γ₁)
    (γ₂ : ∀ t : ι, Path (b t) (c t)) (h₂ : Continuous ↿γ₂) :
    Continuous ↿fun t => (γ₁ t).trans (γ₂ t) := by
  have h₁' := Path.continuous_uncurry_extend_of_continuous_family γ₁ h₁
  have h₂' := Path.continuous_uncurry_extend_of_continuous_family γ₂ h₂
  simp only [HasUncurry.uncurry, CoeFun.coe, Path.trans, (· ∘ ·)]
  refine' Continuous.if_le _ _ (continuous_subtype_val.comp continuous_snd) continuous_const _
  · change
      Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ))
    exact h₁'.comp (continuous_id.prod_map <| continuous_const.mul continuous_subtype_val)
  · change
      Continuous ((fun p : ι × ℝ => (γ₂ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x - 1 : I → ℝ))
    exact
      h₂'.comp
        (continuous_id.prod_map <|
          (continuous_const.mul continuous_subtype_val).sub continuous_const)
  · rintro st hst
    

Proof state:
case refine'_3
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι✝ : Type u_3
γ : Path x y
ι : Type u_4
inst✝ : TopologicalSpace ι
a b c : ι → X
γ₁ : (t : ι) → Path (a t) (b t)
h₁ : Continuous ↿γ₁
γ₂ : (t : ι) → Path (b t) (c t)
h₂ : Continuous ↿γ₂
h₁' : Continuous ↿fun t => extend (γ₁ t)
h₂' : Continuous ↿fun t => extend (γ₂ t)
st : ι × ↑I
hst : ↑st.2 = 1 / 2
⊢ extend (γ₁ st.1) (2 * ↑st.2) = extend (γ₂ st.1) (2 * ↑st.2 - 1)

Next tactic:
simp [hst, mul_inv_cancel (two_ne_zero' ℝ)]
@[continuity]
theorem _root_.Continuous.path_trans {f : Y → Path x y} {g : Y → Path y z} :
    Continuous f → Continuous g → Continuous fun t => (f t).trans (g t) := by
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
f : Y → Path x y
g : Y → Path y z
⊢ Continuous f → Continuous g → Continuous fun t => trans (f t) (g t)

Next tactic:
intro hf hg
@[continuity]
theorem _root_.Continuous.path_trans {f : Y → Path x y} {g : Y → Path y z} :
    Continuous f → Continuous g → Continuous fun t => (f t).trans (g t) := by
  intro hf hg
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
f : Y → Path x y
g : Y → Path y z
hf : Continuous f
hg : Continuous g
⊢ Continuous fun t => trans (f t) (g t)

Next tactic:
apply continuous_uncurry_iff.mp
@[continuity]
theorem _root_.Continuous.path_trans {f : Y → Path x y} {g : Y → Path y z} :
    Continuous f → Continuous g → Continuous fun t => (f t).trans (g t) := by
  intro hf hg
  apply continuous_uncurry_iff.mp
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
f : Y → Path x y
g : Y → Path y z
hf : Continuous f
hg : Continuous g
⊢ Continuous ↿fun t => trans (f t) (g t)

Next tactic:
exact trans_continuous_family _ (continuous_uncurry_iff.mpr hf) _ (continuous_uncurry_iff.mpr hg)
/-- Given a path in `X` and a path in `Y`, we can take their pointwise product to get a path in
`X × Y`. -/
protected def prod (γ₁ : Path a₁ a₂) (γ₂ : Path b₁ b₂) : Path (a₁, b₁) (a₂, b₂) where
  toContinuousMap := ContinuousMap.prodMk γ₁.toContinuousMap γ₂.toContinuousMap
  source' := by 

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
γ₂ : Path b₁ b₂
⊢ ContinuousMap.toFun (prodMk γ₁.toContinuousMap γ₂.toContinuousMap) 0 = (a₁, b₁)

Next tactic:
simp
/-- Given a path in `X` and a path in `Y`, we can take their pointwise product to get a path in
`X × Y`. -/
protected def prod (γ₁ : Path a₁ a₂) (γ₂ : Path b₁ b₂) : Path (a₁, b₁) (a₂, b₂) where
  toContinuousMap := ContinuousMap.prodMk γ₁.toContinuousMap γ₂.toContinuousMap
  source' := by simp
  target' := by 

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
γ₂ : Path b₁ b₂
⊢ ContinuousMap.toFun (prodMk γ₁.toContinuousMap γ₂.toContinuousMap) 1 = (a₂, b₂)

Next tactic:
simp
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
⊢ trans (Path.prod γ₁ γ₂) (Path.prod δ₁ δ₂) = Path.prod (trans γ₁ δ₁) (trans γ₂ δ₂)

Next tactic:
ext t
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  

Proof state:
case a.h.a
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
⊢ ((trans (Path.prod γ₁ γ₂) (Path.prod δ₁ δ₂)) t).1 = ((Path.prod (trans γ₁ δ₁) (trans γ₂ δ₂)) t).1

Next tactic:
unfold Path.trans
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  

Proof state:
case a.h.a
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
⊢ ((trans (Path.prod γ₁ γ₂) (Path.prod δ₁ δ₂)) t).2 = ((Path.prod (trans γ₁ δ₁) (trans γ₂ δ₂)) t).2

Next tactic:
unfold Path.trans
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  

Proof state:
case a.h.a
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
⊢ ({
          toContinuousMap :=
            ContinuousMap.mk
              ((fun t => if t ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * t) else extend (Path.prod δ₁ δ₂) (2 * t - 1)) ∘
                Subtype.val),
          source' :=
            (_ :
              ((fun x => if x ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * x) else extend (Path.prod δ₁ δ₂) (2 * x - 1)) ∘
                    Subtype.val)
                  0 =
                (a₁, b₁)),
          target' :=
            (_ :
              ((fun x => if x ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * x) else extend (Path.prod δ₁ δ₂) (2 * x - 1)) ∘
                    Subtype.val)
                  1 =
                (a₃, b₃)) }
        t).1 =
    ((Path.prod
          {
            toContinuousMap :=
              ContinuousMap.mk
                ((fun t => if t ≤ 1 / 2 then extend γ₁ (2 * t) else extend δ₁ (2 * t - 1)) ∘ Subtype.val),
            source' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₁ (2 * x) else extend δ₁ (2 * x - 1)) ∘ Subtype.val) 0 = a₁),
            target' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₁ (2 * x) else extend δ₁ (2 * x - 1)) ∘ Subtype.val) 1 = a₃) }
          {
            toContinuousMap :=
              ContinuousMap.mk
                ((fun t => if t ≤ 1 / 2 then extend γ₂ (2 * t) else extend δ₂ (2 * t - 1)) ∘ Subtype.val),
            source' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₂ (2 * x) else extend δ₂ (2 * x - 1)) ∘ Subtype.val) 0 = b₁),
            target' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₂ (2 * x) else extend δ₂ (2 * x - 1)) ∘ Subtype.val) 1 = b₃) })
        t).1

Next tactic:
simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply]
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  

Proof state:
case a.h.a
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
⊢ ({
          toContinuousMap :=
            ContinuousMap.mk
              ((fun t => if t ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * t) else extend (Path.prod δ₁ δ₂) (2 * t - 1)) ∘
                Subtype.val),
          source' :=
            (_ :
              ((fun x => if x ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * x) else extend (Path.prod δ₁ δ₂) (2 * x - 1)) ∘
                    Subtype.val)
                  0 =
                (a₁, b₁)),
          target' :=
            (_ :
              ((fun x => if x ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * x) else extend (Path.prod δ₁ δ₂) (2 * x - 1)) ∘
                    Subtype.val)
                  1 =
                (a₃, b₃)) }
        t).2 =
    ((Path.prod
          {
            toContinuousMap :=
              ContinuousMap.mk
                ((fun t => if t ≤ 1 / 2 then extend γ₁ (2 * t) else extend δ₁ (2 * t - 1)) ∘ Subtype.val),
            source' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₁ (2 * x) else extend δ₁ (2 * x - 1)) ∘ Subtype.val) 0 = a₁),
            target' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₁ (2 * x) else extend δ₁ (2 * x - 1)) ∘ Subtype.val) 1 = a₃) }
          {
            toContinuousMap :=
              ContinuousMap.mk
                ((fun t => if t ≤ 1 / 2 then extend γ₂ (2 * t) else extend δ₂ (2 * t - 1)) ∘ Subtype.val),
            source' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₂ (2 * x) else extend δ₂ (2 * x - 1)) ∘ Subtype.val) 0 = b₁),
            target' :=
              (_ : ((fun x => if x ≤ 1 / 2 then extend γ₂ (2 * x) else extend δ₂ (2 * x - 1)) ∘ Subtype.val) 1 = b₃) })
        t).2

Next tactic:
simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply]
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
  

Proof state:
case a.h.a
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
⊢ (if ↑t ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * ↑t) else extend (Path.prod δ₁ δ₂) (2 * ↑t - 1)).1 =
    if ↑t ≤ 1 / 2 then extend γ₁ (2 * ↑t) else extend δ₁ (2 * ↑t - 1)

Next tactic:
split_ifs
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
  

Proof state:
case a.h.a
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
⊢ (if ↑t ≤ 1 / 2 then extend (Path.prod γ₁ γ₂) (2 * ↑t) else extend (Path.prod δ₁ δ₂) (2 * ↑t - 1)).2 =
    if ↑t ≤ 1 / 2 then extend γ₂ (2 * ↑t) else extend δ₂ (2 * ↑t - 1)

Next tactic:
split_ifs
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
  split_ifs <;>
  

Proof state:
case pos
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
h✝ : ↑t ≤ 1 / 2
⊢ (extend (Path.prod γ₁ γ₂) (2 * ↑t)).1 = extend γ₁ (2 * ↑t)

Next tactic:
rfl
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
  split_ifs <;>
  

Proof state:
case neg
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
h✝ : ¬↑t ≤ 1 / 2
⊢ (extend (Path.prod δ₁ δ₂) (2 * ↑t - 1)).1 = extend δ₁ (2 * ↑t - 1)

Next tactic:
rfl
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
  split_ifs <;>
  

Proof state:
case pos
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
h✝ : ↑t ≤ 1 / 2
⊢ (extend (Path.prod γ₁ γ₂) (2 * ↑t)).2 = extend γ₂ (2 * ↑t)

Next tactic:
rfl
/-- Path composition commutes with products -/
theorem trans_prod_eq_prod_trans (γ₁ : Path a₁ a₂) (δ₁ : Path a₂ a₃) (γ₂ : Path b₁ b₂)
    (δ₂ : Path b₂ b₃) : (γ₁.prod γ₂).trans (δ₁.prod δ₂) = (γ₁.trans δ₁).prod (γ₂.trans δ₂) := by
  ext t <;>
  unfold Path.trans <;>
  simp only [Path.coe_mk_mk, Path.prod_coe, Function.comp_apply] <;>
  split_ifs <;>
  

Proof state:
case neg
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ : Path x y
a₁ a₂ a₃ : X
b₁ b₂ b₃ : Y
γ₁ : Path a₁ a₂
δ₁ : Path a₂ a₃
γ₂ : Path b₁ b₂
δ₂ : Path b₂ b₃
t : ↑I
h✝ : ¬↑t ≤ 1 / 2
⊢ (extend (Path.prod δ₁ δ₂) (2 * ↑t - 1)).2 = extend δ₂ (2 * ↑t - 1)

Next tactic:
rfl
/-- Given a family of paths, one in each Xᵢ, we take their pointwise product to get a path in
Π i, Xᵢ. -/
protected def pi (γ : ∀ i, Path (as i) (bs i)) : Path as bs where
  toContinuousMap := ContinuousMap.pi fun i => (γ i).toContinuousMap
  source' := by 

Proof state:
X : Type u_1
Y : Type u_2
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
x y z : X
ι : Type u_3
γ✝ : Path x y
χ : ι → Type u_4
inst✝ : (i : ι) → TopologicalSpace (χ i)
as bs cs : (i : ι) → χ i
γ : (i : ι) → Path (as i) (bs i)
⊢ ContinuousMap.toFun (ContinuousMap.pi fun i => (γ i).toContinuousMap) 0 = as

Next tactic:
simp