File: Mathlib/Topology/Homotopy/Basic.lean

full_name: ContinuousMap.Homotopy.map_zero_left
code: /-- `ContinuousMap.Homotopy f₀ f₁` is the type of homotopies from `f₀` to `f₁`.

When possible, instead of parametrizing results over `(f : Homotopy f₀ f₁)`,
you should parametrize over `{F : Type*} [HomotopyLike F f₀ f₁] (f : F)`.

When you extend this structure, make sure to extend `ContinuousMap.HomotopyLike`. -/
structure Homotopy (f₀ f₁ : C(X, Y)) extends C(I × X, Y) where
  /-- value of the homotopy at 0 -/
  map_zero_left : ∀ x, toFun (0, x) = f₀ x
  /-- value of the homotopy at 1 -/
  map_one_left : ∀ x, toFun (1, x) = f₁ x
goal: self.toFun (0, x) = f₀ x

full_name: ContinuousMap.Homotopy.map_one_left
code: /-- `ContinuousMap.Homotopy f₀ f₁` is the type of homotopies from `f₀` to `f₁`.

When possible, instead of parametrizing results over `(f : Homotopy f₀ f₁)`,
you should parametrize over `{F : Type*} [HomotopyLike F f₀ f₁] (f : F)`.

When you extend this structure, make sure to extend `ContinuousMap.HomotopyLike`. -/
structure Homotopy (f₀ f₁ : C(X, Y)) extends C(I × X, Y) where
  /-- value of the homotopy at 0 -/
  map_zero_left : ∀ x, toFun (0, x) = f₀ x
  /-- value of the homotopy at 1 -/
  map_one_left : ∀ x, toFun (1, x) = f₁ x
goal: self.toFun (1, x) = f₁ x

full_name: ContinuousMap.Homotopy
code: /-- `ContinuousMap.Homotopy f₀ f₁` is the type of homotopies from `f₀` to `f₁`.

When possible, instead of parametrizing results over `(f : Homotopy f₀ f₁)`,
you should parametrize over `{F : Type*} [HomotopyLike F f₀ f₁] (f : F)`.

When you extend this structure, make sure to extend `ContinuousMap.HomotopyLike`. -/
structure Homotopy (f₀ f₁ : C(X, Y)) extends C(I × X, Y) where
  /-- value of the homotopy at 0 -/
  map_zero_left : ∀ x, toFun (0, x) = f₀ x
  /-- value of the homotopy at 1 -/
  map_one_left : ∀ x, toFun (1, x) = f₁ x
goal: Type (max u v)

full_name: ContinuousMap.HomotopyLike
code: /-- `ContinuousMap.HomotopyLike F f₀ f₁` states that `F` is a type of homotopies between `f₀` and
`f₁`.

You should extend this class when you extend `ContinuousMap.Homotopy`. -/
class HomotopyLike {X Y : outParam Type*} [TopologicalSpace X] [TopologicalSpace Y]
    (F : Type*) (f₀ f₁ : outParam <| C(X, Y)) [FunLike F (I × X) Y]
    extends ContinuousMapClass F (I × X) Y : Prop where
  /-- value of the homotopy at 0 -/
  map_zero_left (f : F) : ∀ x, f (0, x) = f₀ x
  /-- value of the homotopy at 1 -/
  map_one_left (f : F) : ∀ x, f (1, x) = f₁ x
goal: Prop

full_name: ContinuousMap.HomotopyLike.map_zero_left
code: /-- `ContinuousMap.HomotopyLike F f₀ f₁` states that `F` is a type of homotopies between `f₀` and
`f₁`.

You should extend this class when you extend `ContinuousMap.Homotopy`. -/
class HomotopyLike {X Y : outParam Type*} [TopologicalSpace X] [TopologicalSpace Y]
    (F : Type*) (f₀ f₁ : outParam <| C(X, Y)) [FunLike F (I × X) Y]
    extends ContinuousMapClass F (I × X) Y : Prop where
  /-- value of the homotopy at 0 -/
  map_zero_left (f : F) : ∀ x, f (0, x) = f₀ x
  /-- value of the homotopy at 1 -/
  map_one_left (f : F) : ∀ x, f (1, x) = f₁ x
goal: f (0, x) = f₀ x

full_name: ContinuousMap.HomotopyLike.map_one_left
code: /-- `ContinuousMap.HomotopyLike F f₀ f₁` states that `F` is a type of homotopies between `f₀` and
`f₁`.

You should extend this class when you extend `ContinuousMap.Homotopy`. -/
class HomotopyLike {X Y : outParam Type*} [TopologicalSpace X] [TopologicalSpace Y]
    (F : Type*) (f₀ f₁ : outParam <| C(X, Y)) [FunLike F (I × X) Y]
    extends ContinuousMapClass F (I × X) Y : Prop where
  /-- value of the homotopy at 0 -/
  map_zero_left (f : F) : ∀ x, f (0, x) = f₀ x
  /-- value of the homotopy at 1 -/
  map_one_left (f : F) : ∀ x, f (1, x) = f₁ x
goal: f (1, x) = f₁ x

full_name: ContinuousMap.Homotopy.instFunLike
code: instance instFunLike : FunLike (Homotopy f₀ f₁) (I × X) Y 
goal: FunLike (f₀.Homotopy f₁) (↑I × X) Y

full_name: ContinuousMap.Homotopy.instHomotopyLike
code: instance : HomotopyLike (Homotopy f₀ f₁) f₀ f₁ 
goal: ContinuousMap.HomotopyLike (f₀.Homotopy f₁) f₀ f₁

full_name: ContinuousMap.Homotopy.ext
code: @[ext]
theorem ext {F G : Homotopy f₀ f₁} (h : ∀ x, F x = G x) : F = G 
goal: F = G

full_name: ContinuousMap.Homotopy.Simps.apply
code: /-- See Note [custom simps projection]. We need to specify this projection explicitly in this case,
because it is a composition of multiple projections. -/
def Simps.apply (F : Homotopy f₀ f₁) : I × X → Y 
goal: ↑I × X → Y

full_name: ContinuousMap.Homotopy.continuous
code: /-- Deprecated. Use `map_continuous` instead. -/
protected theorem continuous (F : Homotopy f₀ f₁) : Continuous F 
goal: Continuous ⇑F

full_name: ContinuousMap.Homotopy.apply_zero
code: @[simp]
theorem apply_zero (F : Homotopy f₀ f₁) (x : X) : F (0, x) = f₀ x 
goal: F (0, x) = f₀ x

full_name: ContinuousMap.Homotopy.apply_one
code: @[simp]
theorem apply_one (F : Homotopy f₀ f₁) (x : X) : F (1, x) = f₁ x 
goal: F (1, x) = f₁ x

full_name: ContinuousMap.Homotopy.coe_toContinuousMap
code: @[simp]
theorem coe_toContinuousMap (F : Homotopy f₀ f₁) : ⇑F.toContinuousMap = F 
goal: ⇑F.toContinuousMap = ⇑F

full_name: ContinuousMap.Homotopy.curry
code: /-- Currying a homotopy to a continuous function from `I` to `C(X, Y)`.
-/
def curry (F : Homotopy f₀ f₁) : C(I, C(X, Y)) 
goal: C(↑I, C(X, Y))

full_name: ContinuousMap.Homotopy.curry_apply
code: @[simp]
theorem curry_apply (F : Homotopy f₀ f₁) (t : I) (x : X) : F.curry t x = F (t, x) 
goal: (F.curry t) x = F (t, x)

full_name: ContinuousMap.Homotopy.extend
code: /-- Continuously extending a curried homotopy to a function from `ℝ` to `C(X, Y)`.
-/
def extend (F : Homotopy f₀ f₁) : C(ℝ, C(X, Y)) 
goal: C(ℝ, C(X, Y))

full_name: ContinuousMap.Homotopy.extend_apply_of_le_zero
code: theorem extend_apply_of_le_zero (F : Homotopy f₀ f₁) {t : ℝ} (ht : t ≤ 0) (x : X) :
    F.extend t x = f₀ x 
goal: (F.extend t) x = f₀ x

full_name: ContinuousMap.Homotopy.extend_apply_of_one_le
code: theorem extend_apply_of_one_le (F : Homotopy f₀ f₁) {t : ℝ} (ht : 1 ≤ t) (x : X) :
    F.extend t x = f₁ x 
goal: (F.extend t) x = f₁ x

full_name: ContinuousMap.Homotopy.extend_apply_coe
code: @[simp]
theorem extend_apply_coe (F : Homotopy f₀ f₁) (t : I) (x : X) : F.extend t x = F (t, x) 
goal: (F.extend ↑t) x = F (t, x)

full_name: ContinuousMap.Homotopy.extend_apply_of_mem_I
code: @[simp]
theorem extend_apply_of_mem_I (F : Homotopy f₀ f₁) {t : ℝ} (ht : t ∈ I) (x : X) :
    F.extend t x = F (⟨t, ht⟩, x) 
goal: (F.extend t) x = F (⟨t, ht⟩, x)

full_name: ContinuousMap.Homotopy.congr_fun
code: protected theorem congr_fun {F G : Homotopy f₀ f₁} (h : F = G) (x : I × X) : F x = G x 
goal: F x = G x

full_name: ContinuousMap.Homotopy.congr_arg
code: protected theorem congr_arg (F : Homotopy f₀ f₁) {x y : I × X} (h : x = y) : F x = F y 
goal: F x = F y

full_name: ContinuousMap.Homotopy.refl_apply
code: /-- Given a continuous function `f`, we can define a `Homotopy f f` by `F (t, x) = f x`
-/
@[simps]
def refl (f : C(X, Y)) : Homotopy f f 
goal: (ContinuousMap.Homotopy.refl f) x = f x.2

full_name: ContinuousMap.Homotopy.refl
code: /-- Given a continuous function `f`, we can define a `Homotopy f f` by `F (t, x) = f x`
-/
@[simps]
def refl (f : C(X, Y)) : Homotopy f f 
goal: f.Homotopy f

full_name: ContinuousMap.Homotopy.instInhabitedId
code: instance : Inhabited (Homotopy (ContinuousMap.id X) (ContinuousMap.id X)) 
goal: Inhabited ((ContinuousMap.id X).Homotopy (ContinuousMap.id X))

full_name: ContinuousMap.Homotopy.symm_apply
code: /-- Given a `Homotopy f₀ f₁`, we can define a `Homotopy f₁ f₀` by reversing the homotopy.
-/
@[simps]
def symm {f₀ f₁ : C(X, Y)} (F : Homotopy f₀ f₁) : Homotopy f₁ f₀ 
goal: F.symm x = F (σ x.1, x.2)

full_name: ContinuousMap.Homotopy.symm
code: /-- Given a `Homotopy f₀ f₁`, we can define a `Homotopy f₁ f₀` by reversing the homotopy.
-/
@[simps]
def symm {f₀ f₁ : C(X, Y)} (F : Homotopy f₀ f₁) : Homotopy f₁ f₀ 
goal: f₁.Homotopy f₀

full_name: ContinuousMap.Homotopy.symm_symm
code: @[simp]
theorem symm_symm {f₀ f₁ : C(X, Y)} (F : Homotopy f₀ f₁) : F.symm.symm = F 
goal: F.symm.symm = F

full_name: ContinuousMap.Homotopy.symm_bijective
code: theorem symm_bijective {f₀ f₁ : C(X, Y)} :
    Function.Bijective (Homotopy.symm : Homotopy f₀ f₁ → Homotopy f₁ f₀) 
goal: Function.Bijective ContinuousMap.Homotopy.symm

full_name: ContinuousMap.Homotopy.trans
code: /--
Given `Homotopy f₀ f₁` and `Homotopy f₁ f₂`, we can define a `Homotopy f₀ f₂` by putting the first
homotopy on `[0, 1/2]` and the second on `[1/2, 1]`.
-/
def trans {f₀ f₁ f₂ : C(X, Y)} (F : Homotopy f₀ f₁) (G : Homotopy f₁ f₂) : Homotopy f₀ f₂ 
goal: f₀.Homotopy f₂

full_name: ContinuousMap.Homotopy.trans_apply
code: theorem trans_apply {f₀ f₁ f₂ : C(X, Y)} (F : Homotopy f₀ f₁) (G : Homotopy f₁ f₂) (x : I × X) :
    (F.trans G) x =
      if h : (x.1 : ℝ) ≤ 1 / 2 then
        F (⟨2 * x.1, (unitInterval.mul_pos_mem_iff zero_lt_two).2 ⟨x.1.2.1, h⟩⟩, x.2)
      else
        G (⟨2 * x.1 - 1, unitInterval.two_mul_sub_one_mem_iff.2 ⟨(not_le.1 h).le, x.1.2.2⟩⟩, x.2) 
goal: (F.trans G) x = if h : ↑x.1 ≤ 1 / 2 then F (⟨2 * ↑x.1, ⋯⟩, x.2) else G (⟨2 * ↑x.1 - 1, ⋯⟩, x.2)

full_name: ContinuousMap.Homotopy.symm_trans
code: theorem symm_trans {f₀ f₁ f₂ : C(X, Y)} (F : Homotopy f₀ f₁) (G : Homotopy f₁ f₂) :
    (F.trans G).symm = G.symm.trans F.symm 
goal: (F.trans G).symm = G.symm.trans F.symm

full_name: ContinuousMap.Homotopy.cast_apply
code: /-- Casting a `Homotopy f₀ f₁` to a `Homotopy g₀ g₁` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : Homotopy f₀ f₁) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    Homotopy g₀ g₁ 
goal: (F.cast h₀ h₁) a = F a

full_name: ContinuousMap.Homotopy.cast
code: /-- Casting a `Homotopy f₀ f₁` to a `Homotopy g₀ g₁` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : Homotopy f₀ f₁) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    Homotopy g₀ g₁ 
goal: g₀.Homotopy g₁

full_name: ContinuousMap.Homotopy.compContinuousMap
code: /-- Composition of a `Homotopy g₀ g₁` and `f : C(X, Y)` as a homotopy between `g₀.comp f` and
`g₁.comp f`. -/
@[simps!]
def compContinuousMap {g₀ g₁ : C(Y, Z)} (G : Homotopy g₀ g₁) (f : C(X, Y)) :
    Homotopy (g₀.comp f) (g₁.comp f) 
goal: (g₀.comp f).Homotopy (g₁.comp f)

full_name: ContinuousMap.Homotopy.compContinuousMap_apply
code: /-- Composition of a `Homotopy g₀ g₁` and `f : C(X, Y)` as a homotopy between `g₀.comp f` and
`g₁.comp f`. -/
@[simps!]
def compContinuousMap {g₀ g₁ : C(Y, Z)} (G : Homotopy g₀ g₁) (f : C(X, Y)) :
    Homotopy (g₀.comp f) (g₁.comp f) 
goal: ∀ (a : ↑I × X), (G.compContinuousMap f) a = G (Prod.map id (⇑f) a)

full_name: ContinuousMap.Homotopy.hcomp
code: /-- If we have a `Homotopy f₀ f₁` and a `Homotopy g₀ g₁`, then we can compose them and get a
`Homotopy (g₀.comp f₀) (g₁.comp f₁)`.
-/
@[simps]
def hcomp {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(Y, Z)} (F : Homotopy f₀ f₁) (G : Homotopy g₀ g₁) :
    Homotopy (g₀.comp f₀) (g₁.comp f₁) 
goal: (g₀.comp f₀).Homotopy (g₁.comp f₁)

full_name: ContinuousMap.Homotopy.hcomp_apply
code: /-- If we have a `Homotopy f₀ f₁` and a `Homotopy g₀ g₁`, then we can compose them and get a
`Homotopy (g₀.comp f₀) (g₁.comp f₁)`.
-/
@[simps]
def hcomp {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(Y, Z)} (F : Homotopy f₀ f₁) (G : Homotopy g₀ g₁) :
    Homotopy (g₀.comp f₀) (g₁.comp f₁) 
goal: (F.hcomp G) x = G (x.1, F x)

full_name: ContinuousMap.Homotopy.prodMk
code: /-- Let `F` be a homotopy between `f₀ : C(X, Y)` and `f₁ : C(X, Y)`. Let `G` be a homotopy between
`g₀ : C(X, Z)` and `g₁ : C(X, Z)`. Then `F.prodMk G` is the homotopy between `f₀.prodMk g₀` and
`f₁.prodMk g₁` that sends `p` to `(F p, G p)`. -/
nonrec def prodMk {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(X, Z)} (F : Homotopy f₀ f₁) (G : Homotopy g₀ g₁) :
    Homotopy (f₀.prodMk g₀) (f₁.prodMk g₁) 
goal: (f₀.prodMk g₀).Homotopy (f₁.prodMk g₁)

full_name: ContinuousMap.Homotopy.prodMap
code: /-- Let `F` be a homotopy between `f₀ : C(X, Y)` and `f₁ : C(X, Y)`. Let `G` be a homotopy between
`g₀ : C(Z, Z')` and `g₁ : C(Z, Z')`. Then `F.prodMap G` is the homotopy between `f₀.prodMap g₀` and
`f₁.prodMap g₁` that sends `(t, x, z)` to `(F (t, x), G (t, z))`. -/
def prodMap {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(Z, Z')} (F : Homotopy f₀ f₁) (G : Homotopy g₀ g₁) :
    Homotopy (f₀.prodMap g₀) (f₁.prodMap g₁) 
goal: (f₀.prodMap g₀).Homotopy (f₁.prodMap g₁)

full_name: ContinuousMap.Homotopy.pi
code: /-- Given a family of homotopies `F i` between `f₀ i : C(X, Y i)` and `f₁ i : C(X, Y i)`, returns a
homotopy between `ContinuousMap.pi f₀` and `ContinuousMap.pi f₁`. -/
protected def pi {Y : ι → Type*} [∀ i, TopologicalSpace (Y i)] {f₀ f₁ : ∀ i, C(X, Y i)}
    (F : ∀ i, Homotopy (f₀ i) (f₁ i)) :
    Homotopy (.pi f₀) (.pi f₁) 
goal: (ContinuousMap.pi f₀).Homotopy (ContinuousMap.pi f₁)

full_name: ContinuousMap.Homotopy.piMap
code: /-- Given a family of homotopies `F i` between `f₀ i : C(X i, Y i)` and `f₁ i : C(X i, Y i)`,
returns a homotopy between `ContinuousMap.piMap f₀` and `ContinuousMap.piMap f₁`. -/
protected def piMap {X Y : ι → Type*} [∀ i, TopologicalSpace (X i)] [∀ i, TopologicalSpace (Y i)]
    {f₀ f₁ : ∀ i, C(X i, Y i)} (F : ∀ i, Homotopy (f₀ i) (f₁ i)) :
    Homotopy (.piMap f₀) (.piMap f₁) 
goal: (ContinuousMap.piMap f₀).Homotopy (ContinuousMap.piMap f₁)

full_name: ContinuousMap.Homotopic
code: /-- Given continuous maps `f₀` and `f₁`, we say `f₀` and `f₁` are homotopic if there exists a
`Homotopy f₀ f₁`.
-/
def Homotopic (f₀ f₁ : C(X, Y)) : Prop 
goal: Prop

full_name: ContinuousMap.Homotopic.refl
code: @[refl]
theorem refl (f : C(X, Y)) : Homotopic f f 
goal: f.Homotopic f

full_name: ContinuousMap.Homotopic.symm
code: @[symm]
theorem symm ⦃f g : C(X, Y)⦄ (h : Homotopic f g) : Homotopic g f 
goal: g.Homotopic f

full_name: ContinuousMap.Homotopic.trans
code: @[trans]
theorem trans ⦃f g h : C(X, Y)⦄ (h₀ : Homotopic f g) (h₁ : Homotopic g h) : Homotopic f h 
goal: f.Homotopic h

full_name: ContinuousMap.Homotopic.hcomp
code: theorem hcomp {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(Y, Z)} (h₀ : Homotopic f₀ f₁) (h₁ : Homotopic g₀ g₁) :
    Homotopic (g₀.comp f₀) (g₁.comp f₁) 
goal: (g₀.comp f₀).Homotopic (g₁.comp f₁)

full_name: ContinuousMap.Homotopic.equivalence
code: theorem equivalence : Equivalence (@Homotopic X Y _ _) 
goal: Equivalence ContinuousMap.Homotopic

full_name: ContinuousMap.Homotopic.prodMk
code: nonrec theorem prodMk {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(X, Z)} :
    Homotopic f₀ f₁ → Homotopic g₀ g₁ → Homotopic (f₀.prodMk g₀) (f₁.prodMk g₁)
  
goal: f₀.Homotopic f₁ → g₀.Homotopic g₁ → (f₀.prodMk g₀).Homotopic (f₁.prodMk g₁)

full_name: ContinuousMap.Homotopic.prodMap
code: nonrec theorem prodMap {f₀ f₁ : C(X, Y)} {g₀ g₁ : C(Z, Z')} :
    Homotopic f₀ f₁ → Homotopic g₀ g₁ → Homotopic (f₀.prodMap g₀) (f₁.prodMap g₁)
  
goal: f₀.Homotopic f₁ → g₀.Homotopic g₁ → (f₀.prodMap g₀).Homotopic (f₁.prodMap g₁)

full_name: ContinuousMap.Homotopic.pi
code: /-- If each `f₀ i : C(X, Y i)` is homotopic to `f₁ i : C(X, Y i)`, then `ContinuousMap.pi f₀` is
homotopic to `ContinuousMap.pi f₁`. -/
protected theorem pi {Y : ι → Type*} [∀ i, TopologicalSpace (Y i)] {f₀ f₁ : ∀ i, C(X, Y i)}
    (F : ∀ i, Homotopic (f₀ i) (f₁ i)) :
    Homotopic (.pi f₀) (.pi f₁) 
goal: (ContinuousMap.pi f₀).Homotopic (ContinuousMap.pi f₁)

full_name: ContinuousMap.Homotopic.piMap
code: /-- If each `f₀ i : C(X, Y i)` is homotopic to `f₁ i : C(X, Y i)`, then `ContinuousMap.pi f₀` is
homotopic to `ContinuousMap.pi f₁`. -/
protected theorem piMap {X Y : ι → Type*} [∀ i, TopologicalSpace (X i)]
    [∀ i, TopologicalSpace (Y i)] {f₀ f₁ : ∀ i, C(X i, Y i)} (F : ∀ i, Homotopic (f₀ i) (f₁ i)) :
    Homotopic (.piMap f₀) (.piMap f₁) 
goal: (ContinuousMap.piMap f₀).Homotopic (ContinuousMap.piMap f₁)

full_name: ContinuousMap.HomotopyWith
code: /--
The type of homotopies between `f₀ f₁ : C(X, Y)`, where the intermediate maps satisfy the predicate
`P : C(X, Y) → Prop`
-/
structure HomotopyWith (f₀ f₁ : C(X, Y)) (P : C(X, Y) → Prop) extends Homotopy f₀ f₁ where
  -- Porting note (#11215): TODO: use `toHomotopy.curry t`
  /-- the intermediate maps of the homotopy satisfy the property -/
  prop' : ∀ t, P ⟨fun x => toFun (t, x),
    Continuous.comp continuous_toFun (continuous_const.prod_mk continuous_id')⟩
goal: Type (max u v)

full_name: ContinuousMap.HomotopyWith.prop'
code: /--
The type of homotopies between `f₀ f₁ : C(X, Y)`, where the intermediate maps satisfy the predicate
`P : C(X, Y) → Prop`
-/
structure HomotopyWith (f₀ f₁ : C(X, Y)) (P : C(X, Y) → Prop) extends Homotopy f₀ f₁ where
  -- Porting note (#11215): TODO: use `toHomotopy.curry t`
  /-- the intermediate maps of the homotopy satisfy the property -/
  prop' : ∀ t, P ⟨fun x => toFun (t, x),
    Continuous.comp continuous_toFun (continuous_const.prod_mk continuous_id')⟩
goal: P { toFun := fun x => self.toFun (t, x), continuous_toFun := ⋯ }

full_name: ContinuousMap.HomotopyWith.instFunLike
code: instance instFunLike : FunLike (HomotopyWith f₀ f₁ P) (I × X) Y 
goal: FunLike (f₀.HomotopyWith f₁ P) (↑I × X) Y

full_name: ContinuousMap.HomotopyWith.instHomotopyLike
code: instance : HomotopyLike (HomotopyWith f₀ f₁ P) f₀ f₁ 
goal: ContinuousMap.HomotopyLike (f₀.HomotopyWith f₁ P) f₀ f₁

full_name: ContinuousMap.HomotopyWith.coeFn_injective
code: theorem coeFn_injective : @Function.Injective (HomotopyWith f₀ f₁ P) (I × X → Y) (⇑) 
goal: Function.Injective DFunLike.coe

full_name: ContinuousMap.HomotopyWith.ext
code: @[ext]
theorem ext {F G : HomotopyWith f₀ f₁ P} (h : ∀ x, F x = G x) : F = G 
goal: F = G

full_name: ContinuousMap.HomotopyWith.Simps.apply
code: /-- See Note [custom simps projection]. We need to specify this projection explicitly in this case,
because it is a composition of multiple projections. -/
def Simps.apply (F : HomotopyWith f₀ f₁ P) : I × X → Y 
goal: ↑I × X → Y

full_name: ContinuousMap.HomotopyWith.continuous
code: @[continuity]
protected theorem continuous (F : HomotopyWith f₀ f₁ P) : Continuous F 
goal: Continuous ⇑F

full_name: ContinuousMap.HomotopyWith.apply_zero
code: @[simp]
theorem apply_zero (F : HomotopyWith f₀ f₁ P) (x : X) : F (0, x) = f₀ x 
goal: F (0, x) = f₀ x

full_name: ContinuousMap.HomotopyWith.apply_one
code: @[simp]
theorem apply_one (F : HomotopyWith f₀ f₁ P) (x : X) : F (1, x) = f₁ x 
goal: F (1, x) = f₁ x

full_name: ContinuousMap.HomotopyWith.coe_toContinuousMap
code: theorem coe_toContinuousMap (F : HomotopyWith f₀ f₁ P) : ⇑F.toContinuousMap = F 
goal: ⇑F.toContinuousMap = ⇑F

full_name: ContinuousMap.HomotopyWith.coe_toHomotopy
code: @[simp]
theorem coe_toHomotopy (F : HomotopyWith f₀ f₁ P) : ⇑F.toHomotopy = F 
goal: ⇑F.toHomotopy = ⇑F

full_name: ContinuousMap.HomotopyWith.prop
code: theorem prop (F : HomotopyWith f₀ f₁ P) (t : I) : P (F.toHomotopy.curry t) 
goal: P (F.curry t)

full_name: ContinuousMap.HomotopyWith.extendProp
code: theorem extendProp (F : HomotopyWith f₀ f₁ P) (t : ℝ) : P (F.toHomotopy.extend t) 
goal: P (F.extend t)

full_name: ContinuousMap.HomotopyWith.refl_toFun
code: /-- Given a continuous function `f`, and a proof `h : P f`, we can define a `HomotopyWith f f P` by
`F (t, x) = f x`
-/
@[simps!]
def refl (f : C(X, Y)) (hf : P f) : HomotopyWith f f P 
goal: (ContinuousMap.HomotopyWith.refl f hf) x = f x.2

full_name: ContinuousMap.HomotopyWith.refl_apply
code: /-- Given a continuous function `f`, and a proof `h : P f`, we can define a `HomotopyWith f f P` by
`F (t, x) = f x`
-/
@[simps!]
def refl (f : C(X, Y)) (hf : P f) : HomotopyWith f f P 
goal: (ContinuousMap.HomotopyWith.refl f hf) x = f x.2

full_name: ContinuousMap.HomotopyWith.refl
code: /-- Given a continuous function `f`, and a proof `h : P f`, we can define a `HomotopyWith f f P` by
`F (t, x) = f x`
-/
@[simps!]
def refl (f : C(X, Y)) (hf : P f) : HomotopyWith f f P 
goal: f.HomotopyWith f P

full_name: ContinuousMap.HomotopyWith.instInhabitedIdTrue
code: instance : Inhabited (HomotopyWith (ContinuousMap.id X) (ContinuousMap.id X) fun _ => True) 
goal: Inhabited ((ContinuousMap.id X).HomotopyWith (ContinuousMap.id X) fun x => True)

full_name: ContinuousMap.HomotopyWith.symm
code: /--
Given a `HomotopyWith f₀ f₁ P`, we can define a `HomotopyWith f₁ f₀ P` by reversing the homotopy.
-/
@[simps!]
def symm {f₀ f₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) : HomotopyWith f₁ f₀ P 
goal: f₁.HomotopyWith f₀ P

full_name: ContinuousMap.HomotopyWith.symm_apply
code: /--
Given a `HomotopyWith f₀ f₁ P`, we can define a `HomotopyWith f₁ f₀ P` by reversing the homotopy.
-/
@[simps!]
def symm {f₀ f₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) : HomotopyWith f₁ f₀ P 
goal: F.symm x = F (σ x.1, x.2)

full_name: ContinuousMap.HomotopyWith.symm_toFun
code: /--
Given a `HomotopyWith f₀ f₁ P`, we can define a `HomotopyWith f₁ f₀ P` by reversing the homotopy.
-/
@[simps!]
def symm {f₀ f₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) : HomotopyWith f₁ f₀ P 
goal: F.symm x = F (σ x.1, x.2)

full_name: ContinuousMap.HomotopyWith.symm_symm
code: @[simp]
theorem symm_symm {f₀ f₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) : F.symm.symm = F 
goal: F.symm.symm = F

full_name: ContinuousMap.HomotopyWith.symm_bijective
code: theorem symm_bijective {f₀ f₁ : C(X, Y)} :
    Function.Bijective (HomotopyWith.symm : HomotopyWith f₀ f₁ P → HomotopyWith f₁ f₀ P) 
goal: Function.Bijective ContinuousMap.HomotopyWith.symm

full_name: ContinuousMap.HomotopyWith.trans
code: /--
Given `HomotopyWith f₀ f₁ P` and `HomotopyWith f₁ f₂ P`, we can define a `HomotopyWith f₀ f₂ P`
by putting the first homotopy on `[0, 1/2]` and the second on `[1/2, 1]`.
-/
def trans {f₀ f₁ f₂ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) (G : HomotopyWith f₁ f₂ P) :
    HomotopyWith f₀ f₂ P 
goal: f₀.HomotopyWith f₂ P

full_name: ContinuousMap.HomotopyWith.trans_apply
code: theorem trans_apply {f₀ f₁ f₂ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) (G : HomotopyWith f₁ f₂ P)
    (x : I × X) :
    (F.trans G) x =
      if h : (x.1 : ℝ) ≤ 1 / 2 then
        F (⟨2 * x.1, (unitInterval.mul_pos_mem_iff zero_lt_two).2 ⟨x.1.2.1, h⟩⟩, x.2)
      else
        G (⟨2 * x.1 - 1, unitInterval.two_mul_sub_one_mem_iff.2 ⟨(not_le.1 h).le, x.1.2.2⟩⟩, x.2) 
goal: (F.trans G) x = if h : ↑x.1 ≤ 1 / 2 then F (⟨2 * ↑x.1, ⋯⟩, x.2) else G (⟨2 * ↑x.1 - 1, ⋯⟩, x.2)

full_name: ContinuousMap.HomotopyWith.symm_trans
code: theorem symm_trans {f₀ f₁ f₂ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) (G : HomotopyWith f₁ f₂ P) :
    (F.trans G).symm = G.symm.trans F.symm 
goal: (F.trans G).symm = G.symm.trans F.symm

full_name: ContinuousMap.HomotopyWith.cast_apply
code: /-- Casting a `HomotopyWith f₀ f₁ P` to a `HomotopyWith g₀ g₁ P` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps!]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    HomotopyWith g₀ g₁ P 
goal: (F.cast h₀ h₁) a = F a

full_name: ContinuousMap.HomotopyWith.cast
code: /-- Casting a `HomotopyWith f₀ f₁ P` to a `HomotopyWith g₀ g₁ P` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps!]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    HomotopyWith g₀ g₁ P 
goal: g₀.HomotopyWith g₁ P

full_name: ContinuousMap.HomotopyWith.cast_toFun
code: /-- Casting a `HomotopyWith f₀ f₁ P` to a `HomotopyWith g₀ g₁ P` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps!]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : HomotopyWith f₀ f₁ P) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    HomotopyWith g₀ g₁ P 
goal: (F.cast h₀ h₁) a = F a

full_name: ContinuousMap.HomotopicWith
code: /-- Given continuous maps `f₀` and `f₁`, we say `f₀` and `f₁` are homotopic with respect to the
predicate `P` if there exists a `HomotopyWith f₀ f₁ P`.
-/
def HomotopicWith (f₀ f₁ : C(X, Y)) (P : C(X, Y) → Prop) : Prop 
goal: Prop

full_name: ContinuousMap.HomotopicWith.refl
code: theorem refl (f : C(X, Y)) (hf : P f) : HomotopicWith f f P 
goal: f.HomotopicWith f P

full_name: ContinuousMap.HomotopicWith.symm
code: @[symm]
theorem symm ⦃f g : C(X, Y)⦄ (h : HomotopicWith f g P) : HomotopicWith g f P 
goal: g.HomotopicWith f P

full_name: ContinuousMap.HomotopicWith.trans
code: @[trans]
theorem trans ⦃f g h : C(X, Y)⦄ (h₀ : HomotopicWith f g P) (h₁ : HomotopicWith g h P) :
    HomotopicWith f h P 
goal: f.HomotopicWith h P

full_name: ContinuousMap.HomotopyRel
code: /--
A `HomotopyRel f₀ f₁ S` is a homotopy between `f₀` and `f₁` which is fixed on the points in `S`.
-/
abbrev HomotopyRel (f₀ f₁ : C(X, Y)) (S : Set X) 
goal: Type (max u v)

full_name: ContinuousMap.HomotopyRel.eq_fst
code: theorem eq_fst (F : HomotopyRel f₀ f₁ S) (t : I) {x : X} (hx : x ∈ S) : F (t, x) = f₀ x 
goal: F (t, x) = f₀ x

full_name: ContinuousMap.HomotopyRel.eq_snd
code: theorem eq_snd (F : HomotopyRel f₀ f₁ S) (t : I) {x : X} (hx : x ∈ S) : F (t, x) = f₁ x 
goal: F (t, x) = f₁ x

full_name: ContinuousMap.HomotopyRel.fst_eq_snd
code: theorem fst_eq_snd (F : HomotopyRel f₀ f₁ S) {x : X} (hx : x ∈ S) : f₀ x = f₁ x 
goal: f₀ x = f₁ x

full_name: ContinuousMap.HomotopyRel.refl_toFun
code: /-- Given a map `f : C(X, Y)` and a set `S`, we can define a `HomotopyRel f f S` by setting
`F (t, x) = f x` for all `t`. This is defined using `HomotopyWith.refl`, but with the proof
filled in.
-/
@[simps!]
def refl (f : C(X, Y)) (S : Set X) : HomotopyRel f f S 
goal: (ContinuousMap.HomotopyRel.refl f S) x = f x.2

full_name: ContinuousMap.HomotopyRel.refl_apply
code: /-- Given a map `f : C(X, Y)` and a set `S`, we can define a `HomotopyRel f f S` by setting
`F (t, x) = f x` for all `t`. This is defined using `HomotopyWith.refl`, but with the proof
filled in.
-/
@[simps!]
def refl (f : C(X, Y)) (S : Set X) : HomotopyRel f f S 
goal: (ContinuousMap.HomotopyRel.refl f S) x = f x.2

full_name: ContinuousMap.HomotopyRel.refl
code: /-- Given a map `f : C(X, Y)` and a set `S`, we can define a `HomotopyRel f f S` by setting
`F (t, x) = f x` for all `t`. This is defined using `HomotopyWith.refl`, but with the proof
filled in.
-/
@[simps!]
def refl (f : C(X, Y)) (S : Set X) : HomotopyRel f f S 
goal: f.HomotopyRel f S

full_name: ContinuousMap.HomotopyRel.symm_toFun
code: /--
Given a `HomotopyRel f₀ f₁ S`, we can define a `HomotopyRel f₁ f₀ S` by reversing the homotopy.
-/
@[simps!]
def symm (F : HomotopyRel f₀ f₁ S) : HomotopyRel f₁ f₀ S 
goal: F.symm x = F (σ x.1, x.2)

full_name: ContinuousMap.HomotopyRel.symm
code: /--
Given a `HomotopyRel f₀ f₁ S`, we can define a `HomotopyRel f₁ f₀ S` by reversing the homotopy.
-/
@[simps!]
def symm (F : HomotopyRel f₀ f₁ S) : HomotopyRel f₁ f₀ S 
goal: f₁.HomotopyRel f₀ S

full_name: ContinuousMap.HomotopyRel.symm_apply
code: /--
Given a `HomotopyRel f₀ f₁ S`, we can define a `HomotopyRel f₁ f₀ S` by reversing the homotopy.
-/
@[simps!]
def symm (F : HomotopyRel f₀ f₁ S) : HomotopyRel f₁ f₀ S 
goal: F.symm x = F (σ x.1, x.2)

full_name: ContinuousMap.HomotopyRel.symm_symm
code: @[simp]
theorem symm_symm (F : HomotopyRel f₀ f₁ S) : F.symm.symm = F 
goal: F.symm.symm = F

full_name: ContinuousMap.HomotopyRel.symm_bijective
code: theorem symm_bijective :
    Function.Bijective (HomotopyRel.symm : HomotopyRel f₀ f₁ S → HomotopyRel f₁ f₀ S) 
goal: Function.Bijective ContinuousMap.HomotopyRel.symm

full_name: ContinuousMap.HomotopyRel.trans
code: /-- Given `HomotopyRel f₀ f₁ S` and `HomotopyRel f₁ f₂ S`, we can define a `HomotopyRel f₀ f₂ S`
by putting the first homotopy on `[0, 1/2]` and the second on `[1/2, 1]`.
-/
def trans (F : HomotopyRel f₀ f₁ S) (G : HomotopyRel f₁ f₂ S) : HomotopyRel f₀ f₂ S 
goal: f₀.HomotopyRel f₂ S

full_name: ContinuousMap.HomotopyRel.trans_apply
code: theorem trans_apply (F : HomotopyRel f₀ f₁ S) (G : HomotopyRel f₁ f₂ S) (x : I × X) :
    (F.trans G) x =
      if h : (x.1 : ℝ) ≤ 1 / 2 then
        F (⟨2 * x.1, (unitInterval.mul_pos_mem_iff zero_lt_two).2 ⟨x.1.2.1, h⟩⟩, x.2)
      else
        G (⟨2 * x.1 - 1, unitInterval.two_mul_sub_one_mem_iff.2 ⟨(not_le.1 h).le, x.1.2.2⟩⟩, x.2) 
goal: (F.trans G) x = if h : ↑x.1 ≤ 1 / 2 then F (⟨2 * ↑x.1, ⋯⟩, x.2) else G (⟨2 * ↑x.1 - 1, ⋯⟩, x.2)

full_name: ContinuousMap.HomotopyRel.symm_trans
code: theorem symm_trans (F : HomotopyRel f₀ f₁ S) (G : HomotopyRel f₁ f₂ S) :
    (F.trans G).symm = G.symm.trans F.symm 
goal: (F.trans G).symm = G.symm.trans F.symm

full_name: ContinuousMap.HomotopyRel.cast
code: /-- Casting a `HomotopyRel f₀ f₁ S` to a `HomotopyRel g₀ g₁ S` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps!]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : HomotopyRel f₀ f₁ S) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    HomotopyRel g₀ g₁ S 
goal: g₀.HomotopyRel g₁ S

full_name: ContinuousMap.HomotopyRel.cast_toFun
code: /-- Casting a `HomotopyRel f₀ f₁ S` to a `HomotopyRel g₀ g₁ S` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps!]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : HomotopyRel f₀ f₁ S) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    HomotopyRel g₀ g₁ S 
goal: (F.cast h₀ h₁) a = F a

full_name: ContinuousMap.HomotopyRel.cast_apply
code: /-- Casting a `HomotopyRel f₀ f₁ S` to a `HomotopyRel g₀ g₁ S` where `f₀ = g₀` and `f₁ = g₁`.
-/
@[simps!]
def cast {f₀ f₁ g₀ g₁ : C(X, Y)} (F : HomotopyRel f₀ f₁ S) (h₀ : f₀ = g₀) (h₁ : f₁ = g₁) :
    HomotopyRel g₀ g₁ S 
goal: (F.cast h₀ h₁) a = F a

full_name: ContinuousMap.HomotopyRel.compContinuousMap
code: /-- Post-compose a homotopy relative to a set by a continuous function. -/
@[simps!] def compContinuousMap {f₀ f₁ : C(X, Y)} (F : f₀.HomotopyRel f₁ S) (g : C(Y, Z)) :
    (g.comp f₀).HomotopyRel (g.comp f₁) S 
goal: (g.comp f₀).HomotopyRel (g.comp f₁) S

full_name: ContinuousMap.HomotopyRel.compContinuousMap_apply
code: /-- Post-compose a homotopy relative to a set by a continuous function. -/
@[simps!] def compContinuousMap {f₀ f₁ : C(X, Y)} (F : f₀.HomotopyRel f₁ S) (g : C(Y, Z)) :
    (g.comp f₀).HomotopyRel (g.comp f₁) S 
goal: (F.compContinuousMap g) x = g (F x)

full_name: ContinuousMap.HomotopyRel.compContinuousMap_toFun
code: /-- Post-compose a homotopy relative to a set by a continuous function. -/
@[simps!] def compContinuousMap {f₀ f₁ : C(X, Y)} (F : f₀.HomotopyRel f₁ S) (g : C(Y, Z)) :
    (g.comp f₀).HomotopyRel (g.comp f₁) S 
goal: (F.compContinuousMap g) x = g (F x)

full_name: ContinuousMap.HomotopicRel
code: /-- Given continuous maps `f₀` and `f₁`, we say `f₀` and `f₁` are homotopic relative to a set `S` if
there exists a `HomotopyRel f₀ f₁ S`.
-/
def HomotopicRel (f₀ f₁ : C(X, Y)) (S : Set X) : Prop 
goal: Prop

full_name: ContinuousMap.HomotopicRel.homotopic
code: /-- If two maps are homotopic relative to a set, then they are homotopic. -/
protected theorem homotopic {f₀ f₁ : C(X, Y)} (h : HomotopicRel f₀ f₁ S) : Homotopic f₀ f₁ 
goal: f₀.Homotopic f₁

full_name: ContinuousMap.HomotopicRel.refl
code: theorem refl (f : C(X, Y)) : HomotopicRel f f S 
goal: f.HomotopicRel f S

full_name: ContinuousMap.HomotopicRel.symm
code: @[symm]
theorem symm ⦃f g : C(X, Y)⦄ (h : HomotopicRel f g S) : HomotopicRel g f S 
goal: g.HomotopicRel f S

full_name: ContinuousMap.HomotopicRel.trans
code: @[trans]
theorem trans ⦃f g h : C(X, Y)⦄ (h₀ : HomotopicRel f g S) (h₁ : HomotopicRel g h S) :
    HomotopicRel f h S 
goal: f.HomotopicRel h S

full_name: ContinuousMap.HomotopicRel.equivalence
code: theorem equivalence : Equivalence fun f g : C(X, Y) => HomotopicRel f g S 
goal: Equivalence fun f g => f.HomotopicRel g S

full_name: ContinuousMap.homotopicRel_empty
code: @[simp] theorem homotopicRel_empty {f₀ f₁ : C(X, Y)} : HomotopicRel f₀ f₁ ∅ ↔ Homotopic f₀ f₁ 
goal: f₀.HomotopicRel f₁ ∅ ↔ f₀.Homotopic f₁