l3lab/ntp-mathlib huggingface dataset:
/-- The equivalence, given by swapping factors, between `C × D` and `D × C`.
-/
@[simps!]
def braiding : C × D ≌ D × C :=
  Equivalence.mk (swap C D) (swap D C)
    (NatIso.ofComponents fun X => eqToIso (by simp))
    (NatIso.ofComponents fun X => eqToIso (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : D × C
⊢ (swap D C ⋙ swap C D).obj X = (𝟭 (D × C)).obj X

Next tactic:
simp
instance swapIsEquivalence : IsEquivalence (swap C D) :=
  (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
⊢ IsEquivalence (braiding C D).functor

Next tactic:
infer_instance
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C × (C ⥤ D)
f : X ⟶ Y
g : Y ⟶ Z
⊢ { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (f ≫ g) =
    { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map f ≫
      { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map g

Next tactic:
cases g
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    cases g; 

Proof state:
case mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C × (C ⥤ D)
f : X ⟶ Y
fst✝ : Y.1 ⟶ Z.1
snd✝ : Y.2 ⟶ Z.2
⊢ { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (f ≫ (fst✝, snd✝)) =
    { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map f ≫
      { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝, snd✝)

Next tactic:
cases f
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    cases g; cases f; 

Proof state:
case mk.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y Z : C × (C ⥤ D)
fst✝¹ : Y.1 ⟶ Z.1
snd✝¹ : Y.2 ⟶ Z.2
fst✝ : X.1 ⟶ Y.1
snd✝ : X.2 ⟶ Y.2
⊢ { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map ((fst✝, snd✝) ≫ (fst✝¹, snd✝¹)) =
    { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝, snd✝) ≫
      { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝¹, snd✝¹)

Next tactic:
cases Z
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    cases g; cases f; cases Z; 

Proof state:
case mk.mk.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C × (C ⥤ D)
fst✝² : X.1 ⟶ Y.1
snd✝² : X.2 ⟶ Y.2
fst✝¹ : C
snd✝¹ : C ⥤ D
fst✝ : Y.1 ⟶ (fst✝¹, snd✝¹).1
snd✝ : Y.2 ⟶ (fst✝¹, snd✝¹).2
⊢ { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map ((fst✝², snd✝²) ≫ (fst✝, snd✝)) =
    { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝², snd✝²) ≫
      { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝, snd✝)

Next tactic:
cases Y
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    cases g; cases f; cases Z; cases Y; 

Proof state:
case mk.mk.mk.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C × (C ⥤ D)
fst✝³ : C
snd✝³ : C ⥤ D
fst✝² : C
snd✝² : C ⥤ D
fst✝¹ : X.1 ⟶ (fst✝², snd✝²).1
snd✝¹ : X.2 ⟶ (fst✝², snd✝²).2
fst✝ : (fst✝², snd✝²).1 ⟶ (fst✝³, snd✝³).1
snd✝ : (fst✝², snd✝²).2 ⟶ (fst✝³, snd✝³).2
⊢ { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map ((fst✝¹, snd✝¹) ≫ (fst✝, snd✝)) =
    { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝¹, snd✝¹) ≫
      { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝, snd✝)

Next tactic:
cases X
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    cases g; cases f; cases Z; cases Y; cases X
    

Proof state:
case mk.mk.mk.mk.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
fst✝⁴ : C
snd✝⁴ : C ⥤ D
fst✝³ : C
snd✝³ : C ⥤ D
fst✝² : (fst✝³, snd✝³).1 ⟶ (fst✝⁴, snd✝⁴).1
snd✝² : (fst✝³, snd✝³).2 ⟶ (fst✝⁴, snd✝⁴).2
fst✝¹ : C
snd✝¹ : C ⥤ D
fst✝ : (fst✝¹, snd✝¹).1 ⟶ (fst✝³, snd✝³).1
snd✝ : (fst✝¹, snd✝¹).2 ⟶ (fst✝³, snd✝³).2
⊢ { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map ((fst✝, snd✝) ≫ (fst✝², snd✝²)) =
    { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝, snd✝) ≫
      { obj := fun p => p.2.obj p.1, map := fun {x y} f => x.2.map f.1 ≫ f.2.app y.1 }.map (fst✝², snd✝²)

Next tactic:
simp only [prod_comp, NatTrans.comp_app, Functor.map_comp, Category.assoc]
/-- The "evaluation of `F` at `X`" functor,
as a functor `C × (C ⥤ D) ⥤ D`.
-/
@[simps]
def evaluationUncurried : C × (C ⥤ D) ⥤ D where
  obj p := p.2.obj p.1
  map := fun {x} {y} f => x.2.map f.1 ≫ f.2.app y.1
  map_comp := fun {X} {Y} {Z} f g => by
    cases g; cases f; cases Z; cases Y; cases X
    simp only [prod_comp, NatTrans.comp_app, Functor.map_comp, Category.assoc]
    

Proof state:
case mk.mk.mk.mk.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
fst✝⁴ : C
snd✝⁴ : C ⥤ D
fst✝³ : C
snd✝³ : C ⥤ D
fst✝² : (fst✝³, snd✝³).1 ⟶ (fst✝⁴, snd✝⁴).1
snd✝² : (fst✝³, snd✝³).2 ⟶ (fst✝⁴, snd✝⁴).2
fst✝¹ : C
snd✝¹ : C ⥤ D
fst✝ : (fst✝¹, snd✝¹).1 ⟶ (fst✝³, snd✝³).1
snd✝ : (fst✝¹, snd✝¹).2 ⟶ (fst✝³, snd✝³).2
⊢ snd✝¹.map fst✝ ≫ snd✝¹.map fst✝² ≫ snd✝.app fst✝⁴ ≫ snd✝².app fst✝⁴ =
    snd✝¹.map fst✝ ≫ snd✝.app fst✝³ ≫ snd✝³.map fst✝² ≫ snd✝².app fst✝⁴

Next tactic:
rw [← NatTrans.comp_app, NatTrans.naturality, NatTrans.comp_app, Category.assoc,
      NatTrans.naturality]
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
X Y : A × C
f : X ⟶ Y
⊢ (Functor.prod F H).map f ≫ (fun X => (α.app X.1, β.app X.2)) Y =
    (fun X => (α.app X.1, β.app X.2)) X ≫ (Functor.prod G I).map f

Next tactic:
cases X
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; 

Proof state:
case mk
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
Y : A × C
fst✝ : A
snd✝ : C
f : (fst✝, snd✝) ⟶ Y
⊢ (Functor.prod F H).map f ≫ (fun X => (α.app X.1, β.app X.2)) Y =
    (fun X => (α.app X.1, β.app X.2)) (fst✝, snd✝) ≫ (Functor.prod G I).map f

Next tactic:
cases Y
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    

Proof state:
case mk.mk
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ (Functor.prod F H).map f ≫ (fun X => (α.app X.1, β.app X.2)) (fst✝, snd✝) =
    (fun X => (α.app X.1, β.app X.2)) (fst✝¹, snd✝¹) ≫ (Functor.prod G I).map f

Next tactic:
simp only [Functor.prod_map, prod_comp]
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    

Proof state:
case mk.mk
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ (F.map f.1 ≫ α.app fst✝, H.map f.2 ≫ β.app snd✝) = (α.app fst✝¹ ≫ G.map f.1, β.app snd✝¹ ≫ I.map f.2)

Next tactic:
rw [Prod.mk.inj_iff]
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    

Proof state:
case mk.mk
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ F.map f.1 ≫ α.app fst✝ = α.app fst✝¹ ≫ G.map f.1 ∧ H.map f.2 ≫ β.app snd✝ = β.app snd✝¹ ≫ I.map f.2

Next tactic:
constructor
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    constructor
    

Proof state:
case mk.mk.left
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ F.map f.1 ≫ α.app fst✝ = α.app fst✝¹ ≫ G.map f.1
case mk.mk.right
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ H.map f.2 ≫ β.app snd✝ = β.app snd✝¹ ≫ I.map f.2

Next tactic:
repeat {rw [naturality]}
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    constructor
    repeat 

Proof state:
case mk.mk.left
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ F.map f.1 ≫ α.app fst✝ = α.app fst✝¹ ≫ G.map f.1
case mk.mk.right
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ H.map f.2 ≫ β.app snd✝ = β.app snd✝¹ ≫ I.map f.2

Next tactic:
{rw [naturality]}
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    constructor
    repeat {

Proof state:
case mk.mk.left
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ F.map f.1 ≫ α.app fst✝ = α.app fst✝¹ ≫ G.map f.1

Next tactic:
rw [naturality]
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    constructor
    repeat 

Proof state:
case mk.mk.right
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ H.map f.2 ≫ β.app snd✝ = β.app snd✝¹ ≫ I.map f.2

Next tactic:
{rw [naturality]}
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    constructor
    repeat {

Proof state:
case mk.mk.right
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
fst✝¹ : A
snd✝¹ : C
fst✝ : A
snd✝ : C
f : (fst✝¹, snd✝¹) ⟶ (fst✝, snd✝)
⊢ H.map f.2 ≫ β.app snd✝ = β.app snd✝¹ ≫ I.map f.2

Next tactic:
rw [naturality]
/-- The cartesian product of two natural transformations. -/
@[simps]
def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod H ⟶ G.prod I
    where
  app X := (α.app X.1, β.app X.2)
  naturality {X} {Y} f := by
    cases X; cases Y
    simp only [Functor.prod_map, prod_comp]
    rw [Prod.mk.inj_iff]
    constructor
    repeat 

Proof state:

Next tactic:
{rw [naturality]}
/-- The backward direction for `functorProdFunctorEquiv` -/
@[simps]
def functorProdToProdFunctor : (A ⥤ B × C) ⥤ (A ⥤ B) × (A ⥤ C)
    where
  obj F := ⟨F ⋙ CategoryTheory.Prod.fst B C, F ⋙ CategoryTheory.Prod.snd B C⟩
  map α :=
    ⟨{  app := fun X => (α.app X).1
        naturality := fun X Y f => by
          

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
X✝ Y✝ : A ⥤ B × C
α : X✝ ⟶ Y✝
X Y : A
f : X ⟶ Y
⊢ ((fun F => (F ⋙ Prod.fst B C, F ⋙ Prod.snd B C)) X✝).1.map f ≫ (fun X => (α.app X).1) Y =
    (fun X => (α.app X).1) X ≫ ((fun F => (F ⋙ Prod.fst B C, F ⋙ Prod.snd B C)) Y✝).1.map f

Next tactic:
simp only [Functor.comp_map, Prod.fst_map, ← prod_comp_fst, α.naturality]
/-- The backward direction for `functorProdFunctorEquiv` -/
@[simps]
def functorProdToProdFunctor : (A ⥤ B × C) ⥤ (A ⥤ B) × (A ⥤ C)
    where
  obj F := ⟨F ⋙ CategoryTheory.Prod.fst B C, F ⋙ CategoryTheory.Prod.snd B C⟩
  map α :=
    ⟨{  app := fun X => (α.app X).1
        naturality := fun X Y f => by
          simp only [Functor.comp_map, Prod.fst_map, ← prod_comp_fst, α.naturality] },
      { app := fun X => (α.app X).2
        naturality := fun X Y f => by
          

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
X✝ Y✝ : A ⥤ B × C
α : X✝ ⟶ Y✝
X Y : A
f : X ⟶ Y
⊢ ((fun F => (F ⋙ Prod.fst B C, F ⋙ Prod.snd B C)) X✝).2.map f ≫ (fun X => (α.app X).2) Y =
    (fun X => (α.app X).2) X ≫ ((fun F => (F ⋙ Prod.fst B C, F ⋙ Prod.snd B C)) Y✝).2.map f

Next tactic:
simp only [Functor.comp_map, Prod.snd_map, ← prod_comp_snd, α.naturality]
/-- The equivalence between the opposite of a product and the product of the opposites. -/
@[simps]
def prodOpEquiv : (C × D)ᵒᵖ ≌ Cᵒᵖ × Dᵒᵖ where
  functor :=
    { obj := λ X => ⟨op X.unop.1, op X.unop.2⟩,
      map := λ f => ⟨f.unop.1.op, f.unop.2.op⟩ }
  inverse :=
    { obj := λ ⟨X,Y⟩ => op ⟨X.unop, Y.unop⟩,
      map := λ ⟨f,g⟩ => op ⟨f.unop, g.unop⟩ }
  unitIso := Iso.refl _
  counitIso := Iso.refl _
  functor_unitIso_comp := fun ⟨X, Y⟩ => by
    

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
x✝ : (C × D)ᵒᵖ
X : C
Y : D
⊢ (Functor.mk { obj := fun X => (op X.unop.1, op X.unop.2), map := fun {X Y} f => (f.unop.1.op, f.unop.2.op) }).map
        ((Iso.refl (𝟭 (C × D)ᵒᵖ)).hom.app { unop := (X, Y) }) ≫
      (Iso.refl
              (Functor.mk
                  {
                    obj := fun x =>
                      match x with
                      | (X, Y) => op (X.unop, Y.unop),
                    map := fun {X Y} x =>
                      match x with
                      | (f, g) => op (f.unop, g.unop) } ⋙
                Functor.mk
                  { obj := fun X => (op X.unop.1, op X.unop.2),
                    map := fun {X Y} f => (f.unop.1.op, f.unop.2.op) })).hom.app
        ((Functor.mk
              { obj := fun X => (op X.unop.1, op X.unop.2), map := fun {X Y} f => (f.unop.1.op, f.unop.2.op) }).obj
          { unop := (X, Y) }) =
    𝟙
      ((Functor.mk { obj := fun X => (op X.unop.1, op X.unop.2), map := fun {X Y} f => (f.unop.1.op, f.unop.2.op) }).obj
        { unop := (X, Y) })

Next tactic:
dsimp
/-- The equivalence between the opposite of a product and the product of the opposites. -/
@[simps]
def prodOpEquiv : (C × D)ᵒᵖ ≌ Cᵒᵖ × Dᵒᵖ where
  functor :=
    { obj := λ X => ⟨op X.unop.1, op X.unop.2⟩,
      map := λ f => ⟨f.unop.1.op, f.unop.2.op⟩ }
  inverse :=
    { obj := λ ⟨X,Y⟩ => op ⟨X.unop, Y.unop⟩,
      map := λ ⟨f,g⟩ => op ⟨f.unop, g.unop⟩ }
  unitIso := Iso.refl _
  counitIso := Iso.refl _
  functor_unitIso_comp := fun ⟨X, Y⟩ => by
    dsimp
    

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
x✝ : (C × D)ᵒᵖ
X : C
Y : D
⊢ (𝟙 (op X) ≫ 𝟙 (op X), 𝟙 (op Y) ≫ 𝟙 (op Y)) = (𝟙 (op X), 𝟙 (op Y))

Next tactic:
ext
/-- The equivalence between the opposite of a product and the product of the opposites. -/
@[simps]
def prodOpEquiv : (C × D)ᵒᵖ ≌ Cᵒᵖ × Dᵒᵖ where
  functor :=
    { obj := λ X => ⟨op X.unop.1, op X.unop.2⟩,
      map := λ f => ⟨f.unop.1.op, f.unop.2.op⟩ }
  inverse :=
    { obj := λ ⟨X,Y⟩ => op ⟨X.unop, Y.unop⟩,
      map := λ ⟨f,g⟩ => op ⟨f.unop, g.unop⟩ }
  unitIso := Iso.refl _
  counitIso := Iso.refl _
  functor_unitIso_comp := fun ⟨X, Y⟩ => by
    dsimp
    ext <;> 

Proof state:
case a
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
x✝ : (C × D)ᵒᵖ
X : C
Y : D
⊢ (𝟙 (op X) ≫ 𝟙 (op X), 𝟙 (op Y) ≫ 𝟙 (op Y)).1 = (𝟙 (op X), 𝟙 (op Y)).1

Next tactic:
simpa using Category.id_comp _
/-- The equivalence between the opposite of a product and the product of the opposites. -/
@[simps]
def prodOpEquiv : (C × D)ᵒᵖ ≌ Cᵒᵖ × Dᵒᵖ where
  functor :=
    { obj := λ X => ⟨op X.unop.1, op X.unop.2⟩,
      map := λ f => ⟨f.unop.1.op, f.unop.2.op⟩ }
  inverse :=
    { obj := λ ⟨X,Y⟩ => op ⟨X.unop, Y.unop⟩,
      map := λ ⟨f,g⟩ => op ⟨f.unop, g.unop⟩ }
  unitIso := Iso.refl _
  counitIso := Iso.refl _
  functor_unitIso_comp := fun ⟨X, Y⟩ => by
    dsimp
    ext <;> 

Proof state:
case a
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₂
inst✝² : Category.{v₂, u₂} B
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
x✝ : (C × D)ᵒᵖ
X : C
Y : D
⊢ (𝟙 (op X) ≫ 𝟙 (op X), 𝟙 (op Y) ≫ 𝟙 (op Y)).2 = (𝟙 (op X), 𝟙 (op Y)).2

Next tactic:
simpa using Category.id_comp _
theorem one_lt_rOut_div_rIn {c : E} (f : ContDiffBump c) : 1 < f.rOut / f.rIn := by
  

Proof state:
E : Type u_1
X : Type u_2
c : E
f : ContDiffBump c
⊢ 1 < f.rOut / f.rIn

Next tactic:
rw [one_lt_div f.rIn_pos]
theorem one_lt_rOut_div_rIn {c : E} (f : ContDiffBump c) : 1 < f.rOut / f.rIn := by
  rw [one_lt_div f.rIn_pos]
  

Proof state:
E : Type u_1
X : Type u_2
c : E
f : ContDiffBump c
⊢ f.rIn < f.rOut

Next tactic:
exact f.rIn_lt_rOut
protected theorem sub (x : E) : f (c - x) = f (c + x) := by
  

Proof state:
E : Type u_1
X : Type u_2
inst✝⁴ : NormedAddCommGroup E
inst✝³ : NormedSpace ℝ E
inst✝² : NormedAddCommGroup X
inst✝¹ : NormedSpace ℝ X
inst✝ : HasContDiffBump E
c : E
f : ContDiffBump c
x✝ : E
n : ℕ∞
x : E
⊢ ↑f (c - x) = ↑f (c + x)

Next tactic:
simp [f.apply, ContDiffBumpBase.symmetric]
protected theorem neg (f : ContDiffBump (0 : E)) (x : E) : f (-x) = f x := by
  

Proof state:
E : Type u_1
X : Type u_2
inst✝⁴ : NormedAddCommGroup E
inst✝³ : NormedSpace ℝ E
inst✝² : NormedAddCommGroup X
inst✝¹ : NormedSpace ℝ X
inst✝ : HasContDiffBump E
c : E
f✝ : ContDiffBump c
x✝ : E
n : ℕ∞
f : ContDiffBump 0
x : E
⊢ ↑f (-x) = ↑f x

Next tactic:
simp_rw [← zero_sub, f.sub, zero_add]
theorem one_of_mem_closedBall (hx : x ∈ closedBall c f.rIn) : f x = 1 := by
  

Proof state:
E : Type u_1
X : Type u_2
inst✝⁴ : NormedAddCommGroup E
inst✝³ : NormedSpace ℝ E
inst✝² : NormedAddCommGroup X
inst✝¹ : NormedSpace ℝ X
inst✝ : HasContDiffBump E
c : E
f : ContDiffBump c
x : E
n : ℕ∞
hx : x ∈ closedBall c f.rIn
⊢ ↑f x = 1

Next tactic:
apply ContDiffBumpBase.eq_one _ _ f.one_lt_rOut_div_rIn
theorem one_of_mem_closedBall (hx : x ∈ closedBall c f.rIn) : f x = 1 := by
  apply ContDiffBumpBase.eq_one _ _ f.one_lt_rOut_div_rIn
  

Proof state:
case a
E : Type u_1
X : Type u_2
inst✝⁴ : NormedAddCommGroup E
inst✝³ : NormedSpace ℝ E
inst✝² : NormedAddCommGroup X
inst✝¹ : NormedSpace ℝ X
inst✝ : HasContDiffBump E
c : E
f : ContDiffBump c
x : E
n : ℕ∞
hx : x ∈ closedBall c f.rIn
⊢ ‖(fun x => f.rIn⁻¹ • (x - c)) x‖ ≤ 1

Next tactic:
simpa only [norm_smul, Real.norm_eq_abs, abs_inv, abs_of_nonneg f.rIn_pos.le, ← div_eq_inv_mul,
    div_le_one f.rIn_pos] using mem_closedBall_iff_norm.1 hx
theorem support_eq : Function.support f = Metric.ball c f.rOut := by
  

Proof state:
E : Type u_1
X : Type u_2
inst✝⁴ : NormedAddCommGroup E
inst✝³ : NormedSpace ℝ E
inst✝² : NormedAddCommGroup X
inst✝¹ : NormedSpace ℝ X
inst✝ : HasContDiffBump E
c : E
f : ContDiffBump c
x : E
n : ℕ∞
⊢ support ↑f = ball c f.rOut

Next tactic:
simp only [toFun, support_comp_eq_preimage, ContDiffBumpBase.support _ _ f.one_lt_rOut_div_rIn]
theorem support_eq : Function.support f = Metric.ball c f.rOut := by
  simp only [toFun, support_comp_eq_preimage, ContDiffBumpBase.support _ _ f.one_lt_rOut_div_rIn]
  

Proof state:
E : Type u_1
X : Type u_2
inst✝⁴ : NormedAddCommGroup E
inst✝³ : NormedSpace ℝ E
inst✝² : NormedAddCommGroup X
inst✝¹ : NormedSpace ℝ X
inst✝ : HasContDiffBump E
c : E
f : ContDiffBump c
x : E
n : ℕ∞
⊢ (fun x => f.rIn⁻¹ • (x - c)) ⁻¹' ball 0 (f.rOut / f.rIn) = ball c f.rOut

Next tactic:
ext x