l3lab/ntp-mathlib huggingface dataset:
/-- An element admitting a right inverse is right-regular. -/
@[to_additive "An element admitting a right additive opposite is add-right-regular."]
theorem isRightRegular_of_mul_eq_one (h : a * b = 1) : IsRightRegular a :=
  IsRightRegular.of_mul (by 

Proof state:
R : Type u_1
inst✝ : Monoid R
a b : R
h : a * b = 1
⊢ IsRightRegular (a * ?m.13703 h)

Next tactic:
rw [h]
/-- An element admitting a right inverse is right-regular. -/
@[to_additive "An element admitting a right additive opposite is add-right-regular."]
theorem isRightRegular_of_mul_eq_one (h : a * b = 1) : IsRightRegular a :=
  IsRightRegular.of_mul (by rw [h]; 

Proof state:
R : Type u_1
inst✝ : Monoid R
a b : R
h : a * b = 1
⊢ IsRightRegular 1

Next tactic:
exact isRegular_one.right
/-- A unit in a monoid is regular. -/
@[to_additive "An additive unit in an additive monoid is add-regular."]
theorem IsUnit.isRegular (ua : IsUnit a) : IsRegular a := by
  

Proof state:
R : Type u_1
inst✝ : Monoid R
a b : R
ua : IsUnit a
⊢ IsRegular a

Next tactic:
rcases ua with ⟨a, rfl⟩
/-- A unit in a monoid is regular. -/
@[to_additive "An additive unit in an additive monoid is add-regular."]
theorem IsUnit.isRegular (ua : IsUnit a) : IsRegular a := by
  rcases ua with ⟨a, rfl⟩
  

Proof state:
case intro
R : Type u_1
inst✝ : Monoid R
b : R
a : Rˣ
⊢ IsRegular ↑a

Next tactic:
exact Units.isRegular a
theorem insertAt_boundary (i : N) {t₀ : I} {t}
    (H : (t₀ = 0 ∨ t₀ = 1) ∨ t ∈ boundary { j // j ≠ i }) : insertAt i ⟨t₀, t⟩ ∈ boundary N := by
  

Proof state:
N : Type u_1
inst✝ : DecidableEq N
i : N
t₀ : ↑I
t : { j // j ≠ i } → ↑I
H : (t₀ = 0 ∨ t₀ = 1) ∨ t ∈ boundary { j // j ≠ i }
⊢ (insertAt i) (t₀, t) ∈ boundary N

Next tactic:
obtain H | ⟨j, H⟩ := H
theorem insertAt_boundary (i : N) {t₀ : I} {t}
    (H : (t₀ = 0 ∨ t₀ = 1) ∨ t ∈ boundary { j // j ≠ i }) : insertAt i ⟨t₀, t⟩ ∈ boundary N := by
  obtain H | ⟨j, H⟩ := H
  · 

Proof state:
case inl
N : Type u_1
inst✝ : DecidableEq N
i : N
t₀ : ↑I
t : { j // j ≠ i } → ↑I
H : t₀ = 0 ∨ t₀ = 1
⊢ (insertAt i) (t₀, t) ∈ boundary N

Next tactic:
use i
theorem insertAt_boundary (i : N) {t₀ : I} {t}
    (H : (t₀ = 0 ∨ t₀ = 1) ∨ t ∈ boundary { j // j ≠ i }) : insertAt i ⟨t₀, t⟩ ∈ boundary N := by
  obtain H | ⟨j, H⟩ := H
  · use i; 

Proof state:
case h
N : Type u_1
inst✝ : DecidableEq N
i : N
t₀ : ↑I
t : { j // j ≠ i } → ↑I
H : t₀ = 0 ∨ t₀ = 1
⊢ (insertAt i) (t₀, t) i = 0 ∨ (insertAt i) (t₀, t) i = 1

Next tactic:
rwa [funSplitAt_symm_apply, dif_pos rfl]
theorem insertAt_boundary (i : N) {t₀ : I} {t}
    (H : (t₀ = 0 ∨ t₀ = 1) ∨ t ∈ boundary { j // j ≠ i }) : insertAt i ⟨t₀, t⟩ ∈ boundary N := by
  obtain H | ⟨j, H⟩ := H
  · use i; rwa [funSplitAt_symm_apply, dif_pos rfl]
  · 

Proof state:
case inr.intro
N : Type u_1
inst✝ : DecidableEq N
i : N
t₀ : ↑I
t : { j // j ≠ i } → ↑I
j : { j // j ≠ i }
H : t j = 0 ∨ t j = 1
⊢ (insertAt i) (t₀, t) ∈ boundary N

Next tactic:
use j
theorem insertAt_boundary (i : N) {t₀ : I} {t}
    (H : (t₀ = 0 ∨ t₀ = 1) ∨ t ∈ boundary { j // j ≠ i }) : insertAt i ⟨t₀, t⟩ ∈ boundary N := by
  obtain H | ⟨j, H⟩ := H
  · use i; rwa [funSplitAt_symm_apply, dif_pos rfl]
  · use j; 

Proof state:
case h
N : Type u_1
inst✝ : DecidableEq N
i : N
t₀ : ↑I
t : { j // j ≠ i } → ↑I
j : { j // j ≠ i }
H : t j = 0 ∨ t j = 1
⊢ (insertAt i) (t₀, t) ↑j = 0 ∨ (insertAt i) (t₀, t) ↑j = 1

Next tactic:
rwa [funSplitAt_symm_apply, dif_neg j.prop, Subtype.coe_eta]
instance funLike : FunLike (Ω^ N X x) (I^N) fun _ => X where
  coe f := f.1
  coe_injective' := fun ⟨⟨f, _⟩, _⟩ ⟨⟨g, _⟩, _⟩ _ => by 

Proof state:
N : Type u_1
X : Type u_2
inst✝ : TopologicalSpace X
x : X
x✝² x✝¹ : ↑(Ω^ N X x)
f : (N → ↑I) → X
continuous_toFun✝¹ : Continuous f
property✝¹ : ContinuousMap.mk f ∈ Ω^ N X x
g : (N → ↑I) → X
continuous_toFun✝ : Continuous g
property✝ : ContinuousMap.mk g ∈ Ω^ N X x
x✝ :
  (fun f => ⇑↑f) { val := ContinuousMap.mk f, property := property✝¹ } =
    (fun f => ⇑↑f) { val := ContinuousMap.mk g, property := property✝ }
⊢ { val := ContinuousMap.mk f, property := property✝¹ } = { val := ContinuousMap.mk g, property := property✝ }

Next tactic:
congr
/-- Copy of a `GenLoop` with a new map from the unit cube equal to the old one.
  Useful to fix definitional equalities. -/
def copy (f : Ω^ N X x) (g : (I^N) → X) (h : g = f) : Ω^ N X x :=
  ⟨⟨g, h.symm ▸ f.1.2⟩, by 

Proof state:
N : Type u_1
X : Type u_2
inst✝ : TopologicalSpace X
x : X
f : ↑(Ω^ N X x)
g : (N → ↑I) → X
h : g = ⇑f
⊢ ContinuousMap.mk g ∈ Ω^ N X x

Next tactic:
convert f.2
theorem copy_eq (f : Ω^ N X x) {g : (I^N) → X} (h : g = f) : copy f g h = f := by
  

Proof state:
N : Type u_1
X : Type u_2
inst✝ : TopologicalSpace X
x : X
f : ↑(Ω^ N X x)
g : (N → ↑I) → X
h : g = ⇑f
⊢ copy f g h = f

Next tactic:
ext x
theorem copy_eq (f : Ω^ N X x) {g : (I^N) → X} (h : g = f) : copy f g h = f := by
  ext x
  

Proof state:
case H
N : Type u_1
X : Type u_2
inst✝ : TopologicalSpace X
x✝ : X
f : ↑(Ω^ N X x✝)
g : (N → ↑I) → X
h : g = ⇑f
x : N → ↑I
⊢ (copy f g h) x = f x

Next tactic:
exact congr_fun h x
/-- Loop from a generalized loop by currying $I^N → X$ into $I → (I^{N\setminus\{j\}} → X)$. -/
@[simps]
def toLoop (i : N) (p : Ω^ N X x) : Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun t :=
    ⟨(p.val.comp (Cube.insertAt i).toContinuousMap).curry t, fun y yH =>
      p.property (Cube.insertAt i (t, y)) (Cube.insertAt_boundary i <| Or.inr yH)⟩
  source' := by 

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
⊢ ContinuousMap.toFun
      (ContinuousMap.mk fun t =>
        { val := (ContinuousMap.curry (ContinuousMap.comp (↑p) (Homeomorph.toContinuousMap (Cube.insertAt i)))) t,
          property := (_ : ∀ y ∈ Cube.boundary { j // j ≠ i }, ↑p ((Cube.insertAt i) (t, y)) = x) })
      0 =
    const

Next tactic:
ext t
/-- Loop from a generalized loop by currying $I^N → X$ into $I → (I^{N\setminus\{j\}} → X)$. -/
@[simps]
def toLoop (i : N) (p : Ω^ N X x) : Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun t :=
    ⟨(p.val.comp (Cube.insertAt i).toContinuousMap).curry t, fun y yH =>
      p.property (Cube.insertAt i (t, y)) (Cube.insertAt_boundary i <| Or.inr yH)⟩
  source' := by ext t; 

Proof state:
case H
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
t : { j // j ≠ i } → ↑I
⊢ (ContinuousMap.toFun
        (ContinuousMap.mk fun t =>
          { val := (ContinuousMap.curry (ContinuousMap.comp (↑p) (Homeomorph.toContinuousMap (Cube.insertAt i)))) t,
            property := (_ : ∀ y ∈ Cube.boundary { j // j ≠ i }, ↑p ((Cube.insertAt i) (t, y)) = x) })
        0)
      t =
    const t

Next tactic:
refine' p.property (Cube.insertAt i (0, t)) ⟨i, Or.inl _⟩
/-- Loop from a generalized loop by currying $I^N → X$ into $I → (I^{N\setminus\{j\}} → X)$. -/
@[simps]
def toLoop (i : N) (p : Ω^ N X x) : Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun t :=
    ⟨(p.val.comp (Cube.insertAt i).toContinuousMap).curry t, fun y yH =>
      p.property (Cube.insertAt i (t, y)) (Cube.insertAt_boundary i <| Or.inr yH)⟩
  source' := by ext t; refine' p.property (Cube.insertAt i (0, t)) ⟨i, Or.inl _⟩; 

Proof state:
case H
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
t : { j // j ≠ i } → ↑I
⊢ (Cube.insertAt i) (0, t) i = 0

Next tactic:
simp
/-- Loop from a generalized loop by currying $I^N → X$ into $I → (I^{N\setminus\{j\}} → X)$. -/
@[simps]
def toLoop (i : N) (p : Ω^ N X x) : Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun t :=
    ⟨(p.val.comp (Cube.insertAt i).toContinuousMap).curry t, fun y yH =>
      p.property (Cube.insertAt i (t, y)) (Cube.insertAt_boundary i <| Or.inr yH)⟩
  source' := by ext t; refine' p.property (Cube.insertAt i (0, t)) ⟨i, Or.inl _⟩; simp
  target' := by 

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
⊢ ContinuousMap.toFun
      (ContinuousMap.mk fun t =>
        { val := (ContinuousMap.curry (ContinuousMap.comp (↑p) (Homeomorph.toContinuousMap (Cube.insertAt i)))) t,
          property := (_ : ∀ y ∈ Cube.boundary { j // j ≠ i }, ↑p ((Cube.insertAt i) (t, y)) = x) })
      1 =
    const

Next tactic:
ext t
/-- Loop from a generalized loop by currying $I^N → X$ into $I → (I^{N\setminus\{j\}} → X)$. -/
@[simps]
def toLoop (i : N) (p : Ω^ N X x) : Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun t :=
    ⟨(p.val.comp (Cube.insertAt i).toContinuousMap).curry t, fun y yH =>
      p.property (Cube.insertAt i (t, y)) (Cube.insertAt_boundary i <| Or.inr yH)⟩
  source' := by ext t; refine' p.property (Cube.insertAt i (0, t)) ⟨i, Or.inl _⟩; simp
  target' := by ext t; 

Proof state:
case H
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
t : { j // j ≠ i } → ↑I
⊢ (ContinuousMap.toFun
        (ContinuousMap.mk fun t =>
          { val := (ContinuousMap.curry (ContinuousMap.comp (↑p) (Homeomorph.toContinuousMap (Cube.insertAt i)))) t,
            property := (_ : ∀ y ∈ Cube.boundary { j // j ≠ i }, ↑p ((Cube.insertAt i) (t, y)) = x) })
        1)
      t =
    const t

Next tactic:
refine' p.property (Cube.insertAt i (1, t)) ⟨i, Or.inr _⟩
/-- Loop from a generalized loop by currying $I^N → X$ into $I → (I^{N\setminus\{j\}} → X)$. -/
@[simps]
def toLoop (i : N) (p : Ω^ N X x) : Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun t :=
    ⟨(p.val.comp (Cube.insertAt i).toContinuousMap).curry t, fun y yH =>
      p.property (Cube.insertAt i (t, y)) (Cube.insertAt_boundary i <| Or.inr yH)⟩
  source' := by ext t; refine' p.property (Cube.insertAt i (0, t)) ⟨i, Or.inl _⟩; simp
  target' := by ext t; refine' p.property (Cube.insertAt i (1, t)) ⟨i, Or.inr _⟩; 

Proof state:
case H
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
t : { j // j ≠ i } → ↑I
⊢ (Cube.insertAt i) (1, t) i = 1

Next tactic:
simp
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by 

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
⊢ Continuous Subtype.val

Next tactic:
continuity
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
⊢ ContinuousMap.comp (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap))
      (Homeomorph.toContinuousMap (Cube.splitAt i)) ∈
    Ω^ N X x

Next tactic:
rintro y ⟨j, Hj⟩
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    

Proof state:
case intro
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
y : N → ↑I
j : N
Hj : y j = 0 ∨ y j = 1
⊢ (ContinuousMap.comp (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap))
        (Homeomorph.toContinuousMap (Cube.splitAt i)))
      y =
    x

Next tactic:
simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    

Proof state:
case intro
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
y : N → ↑I
j : N
Hj : y j = 0 ∨ y j = 1
⊢ (↑(p.toContinuousMap (y i)) fun j => y ↑j) = x

Next tactic:
obtain rfl | Hne := eq_or_ne j i
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    obtain rfl | Hne := eq_or_ne j i
    · 

Proof state:
case intro.inl
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
y : N → ↑I
j : N
Hj : y j = 0 ∨ y j = 1
p : Ω (↑(Ω^ { j_1 // j_1 ≠ j } X x)) const
⊢ (↑(p.toContinuousMap (y j)) fun j_1 => y ↑j_1) = x

Next tactic:
cases' Hj with Hj Hj
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    obtain rfl | Hne := eq_or_ne j i
    · cases' Hj with Hj Hj <;> 

Proof state:
case intro.inl.inl
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
y : N → ↑I
j : N
p : Ω (↑(Ω^ { j_1 // j_1 ≠ j } X x)) const
Hj : y j = 0
⊢ (↑(p.toContinuousMap (y j)) fun j_1 => y ↑j_1) = x

Next tactic:
simp only [Hj, p.coe_toContinuousMap, p.source, p.target]
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    obtain rfl | Hne := eq_or_ne j i
    · cases' Hj with Hj Hj <;> 

Proof state:
case intro.inl.inr
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
y : N → ↑I
j : N
p : Ω (↑(Ω^ { j_1 // j_1 ≠ j } X x)) const
Hj : y j = 1
⊢ (↑(p.toContinuousMap (y j)) fun j_1 => y ↑j_1) = x

Next tactic:
simp only [Hj, p.coe_toContinuousMap, p.source, p.target]
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    obtain rfl | Hne := eq_or_ne j i
    · cases' Hj with Hj Hj <;> simp only [Hj, p.coe_toContinuousMap, p.source, p.target] <;> 

Proof state:
case intro.inl.inl
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
y : N → ↑I
j : N
p : Ω (↑(Ω^ { j_1 // j_1 ≠ j } X x)) const
Hj : y j = 0
⊢ (↑const fun j_1 => y ↑j_1) = x

Next tactic:
rfl
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    obtain rfl | Hne := eq_or_ne j i
    · cases' Hj with Hj Hj <;> simp only [Hj, p.coe_toContinuousMap, p.source, p.target] <;> 

Proof state:
case intro.inl.inr
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
y : N → ↑I
j : N
p : Ω (↑(Ω^ { j_1 // j_1 ≠ j } X x)) const
Hj : y j = 1
⊢ (↑const fun j_1 => y ↑j_1) = x

Next tactic:
rfl
/-- Generalized loop from a loop by uncurrying $I → (I^{N\setminus\{j\}} → X)$ into $I^N → X$. -/
@[simps]
def fromLoop (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : Ω^ N X x :=
  ⟨(ContinuousMap.comp ⟨Subtype.val, by continuity⟩ p.toContinuousMap).uncurry.comp
    (Cube.splitAt i).toContinuousMap,
    by
    rintro y ⟨j, Hj⟩
    simp only [ContinuousMap.comp_apply, toContinuousMap_apply,
      funSplitAt_apply, ContinuousMap.uncurry_apply, ContinuousMap.coe_mk,
      Function.uncurry_apply_pair]
    obtain rfl | Hne := eq_or_ne j i
    · cases' Hj with Hj Hj <;> simp only [Hj, p.coe_toContinuousMap, p.source, p.target] <;> rfl
    · 

Proof state:
case intro.inr
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
y : N → ↑I
j : N
Hj : y j = 0 ∨ y j = 1
Hne : j ≠ i
⊢ (↑(p.toContinuousMap (y i)) fun j => y ↑j) = x

Next tactic:
exact GenLoop.boundary _ _ ⟨⟨j, Hne⟩, Hj⟩
theorem to_from (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : toLoop i (fromLoop i p) = p := by
  

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
⊢ toLoop i (fromLoop i p) = p

Next tactic:
simp_rw [toLoop, fromLoop, ContinuousMap.comp_assoc,
    toContinuousMap_comp_symm, ContinuousMap.comp_id]
theorem to_from (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : toLoop i (fromLoop i p) = p := by
  simp_rw [toLoop, fromLoop, ContinuousMap.comp_assoc,
    toContinuousMap_comp_symm, ContinuousMap.comp_id]
  

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
⊢ {
      toContinuousMap :=
        ContinuousMap.mk fun t =>
          {
            val :=
              (ContinuousMap.curry
                  (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                t,
            property :=
              (_ :
                (fun x_1 => x_1 ∈ Ω^ { j // j ≠ i } X x)
                  ((ContinuousMap.curry
                      (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                    t)) },
      source' :=
        (_ :
          ContinuousMap.toFun
              (ContinuousMap.mk fun t =>
                {
                  val :=
                    (ContinuousMap.curry
                        (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                      t,
                  property :=
                    (_ :
                      (fun x_1 => x_1 ∈ Ω^ { j // j ≠ i } X x)
                        ((ContinuousMap.curry
                            (ContinuousMap.uncurry
                              (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                          t)) })
              0 =
            const),
      target' :=
        (_ :
          ContinuousMap.toFun
              (ContinuousMap.mk fun t =>
                {
                  val :=
                    (ContinuousMap.curry
                        (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                      t,
                  property :=
                    (_ :
                      (fun x_1 => x_1 ∈ Ω^ { j // j ≠ i } X x)
                        ((ContinuousMap.curry
                            (ContinuousMap.uncurry
                              (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                          t)) })
              1 =
            const) } =
    p

Next tactic:
ext
theorem to_from (i : N) (p : Ω (Ω^ { j // j ≠ i } X x) const) : toLoop i (fromLoop i p) = p := by
  simp_rw [toLoop, fromLoop, ContinuousMap.comp_assoc,
    toContinuousMap_comp_symm, ContinuousMap.comp_id]
  ext; 

Proof state:
case a.h.H
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : Ω (↑(Ω^ { j // j ≠ i } X x)) const
x✝ : ↑I
y✝ : { j // j ≠ i } → ↑I
⊢ ({
          toContinuousMap :=
            ContinuousMap.mk fun t =>
              {
                val :=
                  (ContinuousMap.curry
                      (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                    t,
                property :=
                  (_ :
                    (fun x_1 => x_1 ∈ Ω^ { j // j ≠ i } X x)
                      ((ContinuousMap.curry
                          (ContinuousMap.uncurry (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                        t)) },
          source' :=
            (_ :
              ContinuousMap.toFun
                  (ContinuousMap.mk fun t =>
                    {
                      val :=
                        (ContinuousMap.curry
                            (ContinuousMap.uncurry
                              (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                          t,
                      property :=
                        (_ :
                          (fun x_1 => x_1 ∈ Ω^ { j // j ≠ i } X x)
                            ((ContinuousMap.curry
                                (ContinuousMap.uncurry
                                  (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                              t)) })
                  0 =
                const),
          target' :=
            (_ :
              ContinuousMap.toFun
                  (ContinuousMap.mk fun t =>
                    {
                      val :=
                        (ContinuousMap.curry
                            (ContinuousMap.uncurry
                              (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                          t,
                      property :=
                        (_ :
                          (fun x_1 => x_1 ∈ Ω^ { j // j ≠ i } X x)
                            ((ContinuousMap.curry
                                (ContinuousMap.uncurry
                                  (ContinuousMap.comp (ContinuousMap.mk Subtype.val) p.toContinuousMap)))
                              t)) })
                  1 =
                const) }
        x✝)
      y✝ =
    (p x✝) y✝

Next tactic:
rfl
/-- The `n+1`-dimensional loops are in bijection with the loops in the space of
  `n`-dimensional loops with base point `const`.
  We allow an arbitrary indexing type `N` in place of `Fin n` here. -/
@[simps]
def loopHomeo (i : N) : Ω^ N X x ≃ₜ Ω (Ω^ { j // j ≠ i } X x) const
    where
  toFun := toLoop i
  invFun := fromLoop i
  left_inv p := by 

Proof state:
N : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace X
x : X
inst✝ : DecidableEq N
i : N
p : ↑(Ω^ N X x)
⊢ fromLoop i (toLoop i p) = p

Next tactic:
ext