l3lab/ntp-mathlib huggingface dataset:
instance instIsLowerProd [Preorder α] [TopologicalSpace α] [IsLower α]
    [OrderBot α] [Preorder β] [TopologicalSpace β] [IsLower β] [OrderBot β] :
    IsLower (α × β) where
  topology_eq_lowerTopology := by
    refine' le_antisymm (le_generateFrom _) _
    · rintro _ ⟨x, rfl⟩
      exact (isClosed_Ici.prod isClosed_Ici).isOpen_compl
    rw [(IsLower.isTopologicalBasis.prod
      IsLower.isTopologicalBasis).eq_generateFrom, le_generateFrom_iff_subset_isOpen,
      image2_subset_iff]
    rintro _ ⟨s, hs, rfl⟩ _ ⟨t, ht, rfl⟩
    dsimp
    simp_rw [coe_upperClosure, compl_iUnion, prod_eq, preimage_iInter, preimage_compl]
    -- without `let`, `refine` tries to use the product topology and fails
    let _ : TopologicalSpace (α × β) := lower (α × β)
    refine (hs.isOpen_biInter fun a _ => ?_).inter (ht.isOpen_biInter fun b _ => ?_)
    · exact GenerateOpen.basic _ ⟨(a, ⊥), by 

Proof state:
α : Type ?u.17620
β : Type ?u.17649
inst✝⁷ : Preorder α
inst✝⁶ : TopologicalSpace α
inst✝⁵ : IsLower α
inst✝⁴ : OrderBot α
inst✝³ : Preorder β
inst✝² : TopologicalSpace β
inst✝¹ : IsLower β
inst✝ : OrderBot β
s : Set α
hs : Set.Finite s
t : Set β
ht : Set.Finite t
x✝¹ : TopologicalSpace (α × β) := lower (α × β)
a : α
x✝ : a ∈ s
⊢ (Ici (a, ⊥))ᶜ = (Prod.fst ⁻¹' Ici a)ᶜ

Next tactic:
simp [Ici_prod_eq, prod_univ]
instance instIsLowerProd [Preorder α] [TopologicalSpace α] [IsLower α]
    [OrderBot α] [Preorder β] [TopologicalSpace β] [IsLower β] [OrderBot β] :
    IsLower (α × β) where
  topology_eq_lowerTopology := by
    refine' le_antisymm (le_generateFrom _) _
    · rintro _ ⟨x, rfl⟩
      exact (isClosed_Ici.prod isClosed_Ici).isOpen_compl
    rw [(IsLower.isTopologicalBasis.prod
      IsLower.isTopologicalBasis).eq_generateFrom, le_generateFrom_iff_subset_isOpen,
      image2_subset_iff]
    rintro _ ⟨s, hs, rfl⟩ _ ⟨t, ht, rfl⟩
    dsimp
    simp_rw [coe_upperClosure, compl_iUnion, prod_eq, preimage_iInter, preimage_compl]
    -- without `let`, `refine` tries to use the product topology and fails
    let _ : TopologicalSpace (α × β) := lower (α × β)
    refine (hs.isOpen_biInter fun a _ => ?_).inter (ht.isOpen_biInter fun b _ => ?_)
    · exact GenerateOpen.basic _ ⟨(a, ⊥), by simp [Ici_prod_eq, prod_univ]⟩
    · 

Proof state:
case refine'_2.intro.intro.intro.intro.refine_2
α : Type ?u.17620
β : Type ?u.17649
inst✝⁷ : Preorder α
inst✝⁶ : TopologicalSpace α
inst✝⁵ : IsLower α
inst✝⁴ : OrderBot α
inst✝³ : Preorder β
inst✝² : TopologicalSpace β
inst✝¹ : IsLower β
inst✝ : OrderBot β
s : Set α
hs : Set.Finite s
t : Set β
ht : Set.Finite t
x✝¹ : TopologicalSpace (α × β) := lower (α × β)
b : β
x✝ : b ∈ t
⊢ IsOpen (Prod.snd ⁻¹' Ici b)ᶜ

Next tactic:
exact GenerateOpen.basic _ ⟨(⊥, b), by simp [Ici_prod_eq, univ_prod]⟩
instance instIsLowerProd [Preorder α] [TopologicalSpace α] [IsLower α]
    [OrderBot α] [Preorder β] [TopologicalSpace β] [IsLower β] [OrderBot β] :
    IsLower (α × β) where
  topology_eq_lowerTopology := by
    refine' le_antisymm (le_generateFrom _) _
    · rintro _ ⟨x, rfl⟩
      exact (isClosed_Ici.prod isClosed_Ici).isOpen_compl
    rw [(IsLower.isTopologicalBasis.prod
      IsLower.isTopologicalBasis).eq_generateFrom, le_generateFrom_iff_subset_isOpen,
      image2_subset_iff]
    rintro _ ⟨s, hs, rfl⟩ _ ⟨t, ht, rfl⟩
    dsimp
    simp_rw [coe_upperClosure, compl_iUnion, prod_eq, preimage_iInter, preimage_compl]
    -- without `let`, `refine` tries to use the product topology and fails
    let _ : TopologicalSpace (α × β) := lower (α × β)
    refine (hs.isOpen_biInter fun a _ => ?_).inter (ht.isOpen_biInter fun b _ => ?_)
    · exact GenerateOpen.basic _ ⟨(a, ⊥), by simp [Ici_prod_eq, prod_univ]⟩
    · exact GenerateOpen.basic _ ⟨(⊥, b), by 

Proof state:
α : Type ?u.17620
β : Type ?u.17649
inst✝⁷ : Preorder α
inst✝⁶ : TopologicalSpace α
inst✝⁵ : IsLower α
inst✝⁴ : OrderBot α
inst✝³ : Preorder β
inst✝² : TopologicalSpace β
inst✝¹ : IsLower β
inst✝ : OrderBot β
s : Set α
hs : Set.Finite s
t : Set β
ht : Set.Finite t
x✝¹ : TopologicalSpace (α × β) := lower (α × β)
b : β
x✝ : b ∈ t
⊢ (Ici (⊥, b))ᶜ = (Prod.snd ⁻¹' Ici b)ᶜ

Next tactic:
simp [Ici_prod_eq, univ_prod]
instance instIsUpperProd [Preorder α] [TopologicalSpace α] [IsUpper α]
    [OrderTop α] [Preorder β] [TopologicalSpace β] [IsUpper β] [OrderTop β] :
    IsUpper (α × β) where
  topology_eq_upperTopology := by
    

Proof state:
α : Type ?u.23072
β : Type ?u.23101
inst✝⁷ : Preorder α
inst✝⁶ : TopologicalSpace α
inst✝⁵ : IsUpper α
inst✝⁴ : OrderTop α
inst✝³ : Preorder β
inst✝² : TopologicalSpace β
inst✝¹ : IsUpper β
inst✝ : OrderTop β
⊢ instTopologicalSpaceProd = upper (α × β)

Next tactic:
suffices : IsLower (α × β)ᵒᵈ
instance instIsUpperProd [Preorder α] [TopologicalSpace α] [IsUpper α]
    [OrderTop α] [Preorder β] [TopologicalSpace β] [IsUpper β] [OrderTop β] :
    IsUpper (α × β) where
  topology_eq_upperTopology := by
    suffices : IsLower (α × β)ᵒᵈ
    · 

Proof state:
α : Type ?u.23072
β : Type ?u.23101
inst✝⁷ : Preorder α
inst✝⁶ : TopologicalSpace α
inst✝⁵ : IsUpper α
inst✝⁴ : OrderTop α
inst✝³ : Preorder β
inst✝² : TopologicalSpace β
inst✝¹ : IsUpper β
inst✝ : OrderTop β
this : IsLower (α × β)ᵒᵈ
⊢ instTopologicalSpaceProd = upper (α × β)

Next tactic:
exact IsLower.topology_eq_lowerTopology (α := (α × β)ᵒᵈ)
instance instIsUpperProd [Preorder α] [TopologicalSpace α] [IsUpper α]
    [OrderTop α] [Preorder β] [TopologicalSpace β] [IsUpper β] [OrderTop β] :
    IsUpper (α × β) where
  topology_eq_upperTopology := by
    suffices : IsLower (α × β)ᵒᵈ
    · exact IsLower.topology_eq_lowerTopology (α := (α × β)ᵒᵈ)
    

Proof state:
case this
α : Type ?u.23072
β : Type ?u.23101
inst✝⁷ : Preorder α
inst✝⁶ : TopologicalSpace α
inst✝⁵ : IsUpper α
inst✝⁴ : OrderTop α
inst✝³ : Preorder β
inst✝² : TopologicalSpace β
inst✝¹ : IsUpper β
inst✝ : OrderTop β
⊢ IsLower (α × β)ᵒᵈ

Next tactic:
exact instIsLowerProd (α := αᵒᵈ) (β := βᵒᵈ)
protected lemma _root_.sInfHom.continuous (f : sInfHom α β) : Continuous f := by
  

Proof state:
α : Type u_2
β : Type u_1
inst✝⁵ : CompleteLattice α
inst✝⁴ : CompleteLattice β
inst✝³ : TopologicalSpace α
inst✝² : IsLower α
inst✝¹ : TopologicalSpace β
inst✝ : IsLower β
f : sInfHom α β
⊢ Continuous ⇑f

Next tactic:
refine IsLower.continuous_of_Ici fun b => ?_
protected lemma _root_.sInfHom.continuous (f : sInfHom α β) : Continuous f := by
  refine IsLower.continuous_of_Ici fun b => ?_
  

Proof state:
α : Type u_2
β : Type u_1
inst✝⁵ : CompleteLattice α
inst✝⁴ : CompleteLattice β
inst✝³ : TopologicalSpace α
inst✝² : IsLower α
inst✝¹ : TopologicalSpace β
inst✝ : IsLower β
f : sInfHom α β
b : β
⊢ IsClosed (⇑f ⁻¹' Ici b)

Next tactic:
convert isClosed_Ici (a := sInf <| f ⁻¹' Ici b)
protected lemma _root_.sInfHom.continuous (f : sInfHom α β) : Continuous f := by
  refine IsLower.continuous_of_Ici fun b => ?_
  convert isClosed_Ici (a := sInf <| f ⁻¹' Ici b)
  

Proof state:
case h.e'_3
α : Type u_2
β : Type u_1
inst✝⁵ : CompleteLattice α
inst✝⁴ : CompleteLattice β
inst✝³ : TopologicalSpace α
inst✝² : IsLower α
inst✝¹ : TopologicalSpace β
inst✝ : IsLower β
f : sInfHom α β
b : β
⊢ ⇑f ⁻¹' Ici b = Ici (sInf (⇑f ⁻¹' Ici b))

Next tactic:
refine' Subset.antisymm (fun a => sInf_le) fun a ha => le_trans _ <|
    OrderHomClass.mono (f : α →o β) ha
protected lemma _root_.sInfHom.continuous (f : sInfHom α β) : Continuous f := by
  refine IsLower.continuous_of_Ici fun b => ?_
  convert isClosed_Ici (a := sInf <| f ⁻¹' Ici b)
  refine' Subset.antisymm (fun a => sInf_le) fun a ha => le_trans _ <|
    OrderHomClass.mono (f : α →o β) ha
  

Proof state:
case h.e'_3
α : Type u_2
β : Type u_1
inst✝⁵ : CompleteLattice α
inst✝⁴ : CompleteLattice β
inst✝³ : TopologicalSpace α
inst✝² : IsLower α
inst✝¹ : TopologicalSpace β
inst✝ : IsLower β
f : sInfHom α β
b : β
a : α
ha : a ∈ Ici (sInf (⇑f ⁻¹' Ici b))
⊢ b ≤ ↑f (sInf (⇑f ⁻¹' Ici b))

Next tactic:
refine' LE.le.trans _ (map_sInf f _).ge
protected lemma _root_.sInfHom.continuous (f : sInfHom α β) : Continuous f := by
  refine IsLower.continuous_of_Ici fun b => ?_
  convert isClosed_Ici (a := sInf <| f ⁻¹' Ici b)
  refine' Subset.antisymm (fun a => sInf_le) fun a ha => le_trans _ <|
    OrderHomClass.mono (f : α →o β) ha
  refine' LE.le.trans _ (map_sInf f _).ge
  

Proof state:
case h.e'_3
α : Type u_2
β : Type u_1
inst✝⁵ : CompleteLattice α
inst✝⁴ : CompleteLattice β
inst✝³ : TopologicalSpace α
inst✝² : IsLower α
inst✝¹ : TopologicalSpace β
inst✝ : IsLower β
f : sInfHom α β
b : β
a : α
ha : a ∈ Ici (sInf (⇑f ⁻¹' Ici b))
⊢ b ≤ sInf (⇑f '' (⇑f ⁻¹' Ici b))

Next tactic:
simp
lemma isUpper_orderDual [Preorder α] [TopologicalSpace α] : IsUpper αᵒᵈ ↔ IsLower α := by
  

Proof state:
α : Type u_1
β : ?m.43147
inst✝¹ : Preorder α
inst✝ : TopologicalSpace α
⊢ IsUpper αᵒᵈ ↔ IsLower α

Next tactic:
constructor
lemma isUpper_orderDual [Preorder α] [TopologicalSpace α] : IsUpper αᵒᵈ ↔ IsLower α := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : ?m.43147
inst✝¹ : Preorder α
inst✝ : TopologicalSpace α
⊢ IsUpper αᵒᵈ → IsLower α

Next tactic:
apply OrderDual.instIsLower
lemma isUpper_orderDual [Preorder α] [TopologicalSpace α] : IsUpper αᵒᵈ ↔ IsLower α := by
  constructor
  · apply OrderDual.instIsLower
  · 

Proof state:
case mpr
α : Type u_1
β : ?m.43147
inst✝¹ : Preorder α
inst✝ : TopologicalSpace α
⊢ IsLower α → IsUpper αᵒᵈ

Next tactic:
apply OrderDual.instIsUpper
@[simp]
theorem braiding_naturality {X₁ X₂ Y₁ Y₂ : ModuleCat.{u} R} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
    (f ⊗ g) ≫ (Y₁.braiding Y₂).hom = (X₁.braiding X₂).hom ≫ (g ⊗ f) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
X₁ X₂ Y₁ Y₂ : ModuleCat R
f : X₁ ⟶ Y₁
g : X₂ ⟶ Y₂
⊢ (f ⊗ g) ≫ (braiding Y₁ Y₂).hom = (braiding X₁ X₂).hom ≫ (g ⊗ f)

Next tactic:
apply TensorProduct.ext'
@[simp]
theorem braiding_naturality {X₁ X₂ Y₁ Y₂ : ModuleCat.{u} R} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
    (f ⊗ g) ≫ (Y₁.braiding Y₂).hom = (X₁.braiding X₂).hom ≫ (g ⊗ f) := by
  apply TensorProduct.ext'
  

Proof state:
case H
R : Type u
inst✝ : CommRing R
X₁ X₂ Y₁ Y₂ : ModuleCat R
f : X₁ ⟶ Y₁
g : X₂ ⟶ Y₂
⊢ ∀ (x : ↑X₁) (y : ↑X₂), ((f ⊗ g) ≫ (braiding Y₁ Y₂).hom) (x ⊗ₜ[R] y) = ((braiding X₁ X₂).hom ≫ (g ⊗ f)) (x ⊗ₜ[R] y)

Next tactic:
intro x y
@[simp]
theorem braiding_naturality {X₁ X₂ Y₁ Y₂ : ModuleCat.{u} R} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
    (f ⊗ g) ≫ (Y₁.braiding Y₂).hom = (X₁.braiding X₂).hom ≫ (g ⊗ f) := by
  apply TensorProduct.ext'
  intro x y
  

Proof state:
case H
R : Type u
inst✝ : CommRing R
X₁ X₂ Y₁ Y₂ : ModuleCat R
f : X₁ ⟶ Y₁
g : X₂ ⟶ Y₂
x : ↑X₁
y : ↑X₂
⊢ ((f ⊗ g) ≫ (braiding Y₁ Y₂).hom) (x ⊗ₜ[R] y) = ((braiding X₁ X₂).hom ≫ (g ⊗ f)) (x ⊗ₜ[R] y)

Next tactic:
rfl
@[simp]
theorem braiding_naturality_left {X Y : ModuleCat R} (f : X ⟶ Y) (Z : ModuleCat R) :
    f ▷ Z ≫ (braiding Y Z).hom = (braiding X Z).hom ≫ Z ◁ f := by
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y : ModuleCat R
f : X ⟶ Y
Z : ModuleCat R
⊢ f ▷ Z ≫ (braiding Y Z).hom = (braiding X Z).hom ≫ Z ◁ f

Next tactic:
simp_rw [← id_tensorHom]
@[simp]
theorem braiding_naturality_left {X Y : ModuleCat R} (f : X ⟶ Y) (Z : ModuleCat R) :
    f ▷ Z ≫ (braiding Y Z).hom = (braiding X Z).hom ≫ Z ◁ f := by
  simp_rw [← id_tensorHom]
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y : ModuleCat R
f : X ⟶ Y
Z : ModuleCat R
⊢ f ▷ Z ≫ (braiding Y Z).hom = (braiding X Z).hom ≫ (𝟙 Z ⊗ f)

Next tactic:
apply braiding_naturality
@[simp]
theorem braiding_naturality_right (X : ModuleCat R) {Y Z : ModuleCat R} (f : Y ⟶ Z) :
    X ◁ f ≫ (braiding X Z).hom = (braiding X Y).hom ≫ f ▷ X := by
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
f : Y ⟶ Z
⊢ X ◁ f ≫ (braiding X Z).hom = (braiding X Y).hom ≫ f ▷ X

Next tactic:
simp_rw [← id_tensorHom]
@[simp]
theorem braiding_naturality_right (X : ModuleCat R) {Y Z : ModuleCat R} (f : Y ⟶ Z) :
    X ◁ f ≫ (braiding X Z).hom = (braiding X Y).hom ≫ f ▷ X := by
  simp_rw [← id_tensorHom]
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
f : Y ⟶ Z
⊢ (𝟙 X ⊗ f) ≫ (braiding X Z).hom = (braiding X Y).hom ≫ f ▷ X

Next tactic:
apply braiding_naturality
@[simp]
theorem hexagon_forward (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).hom ≫ (braiding X _).hom ≫ (α_ Y Z X).hom =
      ((braiding X Y).hom ⊗ 𝟙 Z) ≫ (α_ Y X Z).hom ≫ (𝟙 Y ⊗ (braiding X Z).hom) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
⊢ (α_ X Y Z).hom ≫ (braiding X (Y ⊗ Z)).hom ≫ (α_ Y Z X).hom =
    ((braiding X Y).hom ⊗ 𝟙 Z) ≫ (α_ Y X Z).hom ≫ (𝟙 Y ⊗ (braiding X Z).hom)

Next tactic:
apply TensorProduct.ext_threefold
@[simp]
theorem hexagon_forward (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).hom ≫ (braiding X _).hom ≫ (α_ Y Z X).hom =
      ((braiding X Y).hom ⊗ 𝟙 Z) ≫ (α_ Y X Z).hom ≫ (𝟙 Y ⊗ (braiding X Z).hom) := by
  apply TensorProduct.ext_threefold
  

Proof state:
case H
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
⊢ ∀ (x : ↑X) (y : ↑Y) (z : ↑Z),
    ((α_ X Y Z).hom ≫ (braiding X (Y ⊗ Z)).hom ≫ (α_ Y Z X).hom) ((x ⊗ₜ[R] y) ⊗ₜ[R] z) =
      (((braiding X Y).hom ⊗ 𝟙 Z) ≫ (α_ Y X Z).hom ≫ (𝟙 Y ⊗ (braiding X Z).hom)) ((x ⊗ₜ[R] y) ⊗ₜ[R] z)

Next tactic:
intro x y z
@[simp]
theorem hexagon_forward (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).hom ≫ (braiding X _).hom ≫ (α_ Y Z X).hom =
      ((braiding X Y).hom ⊗ 𝟙 Z) ≫ (α_ Y X Z).hom ≫ (𝟙 Y ⊗ (braiding X Z).hom) := by
  apply TensorProduct.ext_threefold
  intro x y z
  

Proof state:
case H
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
x : ↑X
y : ↑Y
z : ↑Z
⊢ ((α_ X Y Z).hom ≫ (braiding X (Y ⊗ Z)).hom ≫ (α_ Y Z X).hom) ((x ⊗ₜ[R] y) ⊗ₜ[R] z) =
    (((braiding X Y).hom ⊗ 𝟙 Z) ≫ (α_ Y X Z).hom ≫ (𝟙 Y ⊗ (braiding X Z).hom)) ((x ⊗ₜ[R] y) ⊗ₜ[R] z)

Next tactic:
rfl
@[simp]
theorem hexagon_reverse (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).inv ≫ (braiding _ Z).hom ≫ (α_ Z X Y).inv =
      (𝟙 X ⊗ (Y.braiding Z).hom) ≫ (α_ X Z Y).inv ≫ ((X.braiding Z).hom ⊗ 𝟙 Y) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
⊢ (α_ X Y Z).inv ≫ (braiding (X ⊗ Y) Z).hom ≫ (α_ Z X Y).inv =
    (𝟙 X ⊗ (braiding Y Z).hom) ≫ (α_ X Z Y).inv ≫ ((braiding X Z).hom ⊗ 𝟙 Y)

Next tactic:
apply (cancel_epi (α_ X Y Z).hom).1
@[simp]
theorem hexagon_reverse (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).inv ≫ (braiding _ Z).hom ≫ (α_ Z X Y).inv =
      (𝟙 X ⊗ (Y.braiding Z).hom) ≫ (α_ X Z Y).inv ≫ ((X.braiding Z).hom ⊗ 𝟙 Y) := by
  apply (cancel_epi (α_ X Y Z).hom).1
  

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
⊢ (α_ X Y Z).hom ≫ (α_ X Y Z).inv ≫ (braiding (X ⊗ Y) Z).hom ≫ (α_ Z X Y).inv =
    (α_ X Y Z).hom ≫ (𝟙 X ⊗ (braiding Y Z).hom) ≫ (α_ X Z Y).inv ≫ ((braiding X Z).hom ⊗ 𝟙 Y)

Next tactic:
apply TensorProduct.ext_threefold
@[simp]
theorem hexagon_reverse (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).inv ≫ (braiding _ Z).hom ≫ (α_ Z X Y).inv =
      (𝟙 X ⊗ (Y.braiding Z).hom) ≫ (α_ X Z Y).inv ≫ ((X.braiding Z).hom ⊗ 𝟙 Y) := by
  apply (cancel_epi (α_ X Y Z).hom).1
  apply TensorProduct.ext_threefold
  

Proof state:
case H
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
⊢ ∀ (x : ↑X) (y : ↑Y) (z : ↑Z),
    ((α_ X Y Z).hom ≫ (α_ X Y Z).inv ≫ (braiding (X ⊗ Y) Z).hom ≫ (α_ Z X Y).inv) ((x ⊗ₜ[R] y) ⊗ₜ[R] z) =
      ((α_ X Y Z).hom ≫ (𝟙 X ⊗ (braiding Y Z).hom) ≫ (α_ X Z Y).inv ≫ ((braiding X Z).hom ⊗ 𝟙 Y)) ((x ⊗ₜ[R] y) ⊗ₜ[R] z)

Next tactic:
intro x y z
@[simp]
theorem hexagon_reverse (X Y Z : ModuleCat.{u} R) :
    (α_ X Y Z).inv ≫ (braiding _ Z).hom ≫ (α_ Z X Y).inv =
      (𝟙 X ⊗ (Y.braiding Z).hom) ≫ (α_ X Z Y).inv ≫ ((X.braiding Z).hom ⊗ 𝟙 Y) := by
  apply (cancel_epi (α_ X Y Z).hom).1
  apply TensorProduct.ext_threefold
  intro x y z
  

Proof state:
case H
R : Type u
inst✝ : CommRing R
X Y Z : ModuleCat R
x : ↑X
y : ↑Y
z : ↑Z
⊢ ((α_ X Y Z).hom ≫ (α_ X Y Z).inv ≫ (braiding (X ⊗ Y) Z).hom ≫ (α_ Z X Y).inv) ((x ⊗ₜ[R] y) ⊗ₜ[R] z) =
    ((α_ X Y Z).hom ≫ (𝟙 X ⊗ (braiding Y Z).hom) ≫ (α_ X Z Y).inv ≫ ((braiding X Z).hom ⊗ 𝟙 Y)) ((x ⊗ₜ[R] y) ⊗ₜ[R] z)

Next tactic:
rfl
/-- The symmetric monoidal structure on `Module R`. -/
instance symmetricCategory : SymmetricCategory (ModuleCat.{u} R) where
  braiding := braiding
  braiding_naturality f g := braiding_naturality f g
  hexagon_forward := hexagon_forward
  hexagon_reverse := hexagon_reverse
  -- porting note: this proof was automatic in Lean3
  -- now `aesop` is applying `ModuleCat.ext` in favour of `TensorProduct.ext`.
  symmetry _ _ := by
    

Proof state:
R : Type u
inst✝ : CommRing R
x✝¹ x✝ : ModuleCat R
⊢ (β_ x✝¹ x✝).hom ≫ (β_ x✝ x✝¹).hom = 𝟙 (x✝¹ ⊗ x✝)

Next tactic:
apply TensorProduct.ext'
/-- The symmetric monoidal structure on `Module R`. -/
instance symmetricCategory : SymmetricCategory (ModuleCat.{u} R) where
  braiding := braiding
  braiding_naturality f g := braiding_naturality f g
  hexagon_forward := hexagon_forward
  hexagon_reverse := hexagon_reverse
  -- porting note: this proof was automatic in Lean3
  -- now `aesop` is applying `ModuleCat.ext` in favour of `TensorProduct.ext`.
  symmetry _ _ := by
    apply TensorProduct.ext'
    

Proof state:
case H
R : Type u
inst✝ : CommRing R
x✝¹ x✝ : ModuleCat R
⊢ ∀ (x : ↑x✝¹) (y : ↑x✝), ((β_ x✝¹ x✝).hom ≫ (β_ x✝ x✝¹).hom) (x ⊗ₜ[R] y) = (𝟙 (x✝¹ ⊗ x✝)) (x ⊗ₜ[R] y)

Next tactic:
aesop_cat
/-- **Fermat's theorem on the sum of two squares**. Every prime not congruent to 3 mod 4 is the sum
of two squares. Also known as **Fermat's Christmas theorem**. -/
theorem Nat.Prime.sq_add_sq {p : ℕ} [Fact p.Prime] (hp : p % 4 ≠ 3) :
    ∃ a b : ℕ, a ^ 2 + b ^ 2 = p := by
  

Proof state:
p : ℕ
inst✝ : Fact (Prime p)
hp : p % 4 ≠ 3
⊢ ∃ a b, a ^ 2 + b ^ 2 = p

Next tactic:
apply sq_add_sq_of_nat_prime_of_not_irreducible p
/-- **Fermat's theorem on the sum of two squares**. Every prime not congruent to 3 mod 4 is the sum
of two squares. Also known as **Fermat's Christmas theorem**. -/
theorem Nat.Prime.sq_add_sq {p : ℕ} [Fact p.Prime] (hp : p % 4 ≠ 3) :
    ∃ a b : ℕ, a ^ 2 + b ^ 2 = p := by
  apply sq_add_sq_of_nat_prime_of_not_irreducible p
  

Proof state:
p : ℕ
inst✝ : Fact (Prime p)
hp : p % 4 ≠ 3
⊢ ¬Irreducible ↑p

Next tactic:
rwa [PrincipalIdealRing.irreducible_iff_prime, prime_iff_mod_four_eq_three_of_nat_prime p]
/-- The set of sums of two squares is closed under multiplication in any commutative ring.
See also `sq_add_sq_mul_sq_add_sq`. -/
theorem sq_add_sq_mul {R} [CommRing R] {a b x y u v : R} (ha : a = x ^ 2 + y ^ 2)
    (hb : b = u ^ 2 + v ^ 2) : ∃ r s : R, a * b = r ^ 2 + s ^ 2 :=
  ⟨x * u - y * v, x * v + y * u, by 

Proof state:
R : Type u_1
inst✝ : CommRing R
a b x y u v : R
ha : a = x ^ 2 + y ^ 2
hb : b = u ^ 2 + v ^ 2
⊢ a * b = (x * u - y * v) ^ 2 + (x * v + y * u) ^ 2

Next tactic:
rw [ha, hb]
/-- The set of sums of two squares is closed under multiplication in any commutative ring.
See also `sq_add_sq_mul_sq_add_sq`. -/
theorem sq_add_sq_mul {R} [CommRing R] {a b x y u v : R} (ha : a = x ^ 2 + y ^ 2)
    (hb : b = u ^ 2 + v ^ 2) : ∃ r s : R, a * b = r ^ 2 + s ^ 2 :=
  ⟨x * u - y * v, x * v + y * u, by rw [ha, hb]; 

Proof state:
R : Type u_1
inst✝ : CommRing R
a b x y u v : R
ha : a = x ^ 2 + y ^ 2
hb : b = u ^ 2 + v ^ 2
⊢ (x ^ 2 + y ^ 2) * (u ^ 2 + v ^ 2) = (x * u - y * v) ^ 2 + (x * v + y * u) ^ 2

Next tactic:
ring
/-- The set of natural numbers that are sums of two squares is closed under multiplication. -/
theorem Nat.sq_add_sq_mul {a b x y u v : ℕ} (ha : a = x ^ 2 + y ^ 2) (hb : b = u ^ 2 + v ^ 2) :
    ∃ r s : ℕ, a * b = r ^ 2 + s ^ 2 := by
  

Proof state:
a b x y u v : ℕ
ha : a = x ^ 2 + y ^ 2
hb : b = u ^ 2 + v ^ 2
⊢ ∃ r s, a * b = r ^ 2 + s ^ 2

Next tactic:
zify at ha hb ⊢
/-- The set of natural numbers that are sums of two squares is closed under multiplication. -/
theorem Nat.sq_add_sq_mul {a b x y u v : ℕ} (ha : a = x ^ 2 + y ^ 2) (hb : b = u ^ 2 + v ^ 2) :
    ∃ r s : ℕ, a * b = r ^ 2 + s ^ 2 := by
  zify at ha hb ⊢
  

Proof state:
a b x y u v : ℕ
ha : ↑a = ↑x ^ 2 + ↑y ^ 2
hb : ↑b = ↑u ^ 2 + ↑v ^ 2
⊢ ∃ r s, ↑a * ↑b = ↑r ^ 2 + ↑s ^ 2

Next tactic:
obtain ⟨r, s, h⟩ := _root_.sq_add_sq_mul ha hb
/-- The set of natural numbers that are sums of two squares is closed under multiplication. -/
theorem Nat.sq_add_sq_mul {a b x y u v : ℕ} (ha : a = x ^ 2 + y ^ 2) (hb : b = u ^ 2 + v ^ 2) :
    ∃ r s : ℕ, a * b = r ^ 2 + s ^ 2 := by
  zify at ha hb ⊢
  obtain ⟨r, s, h⟩ := _root_.sq_add_sq_mul ha hb
  

Proof state:
case intro.intro
a b x y u v : ℕ
ha : ↑a = ↑x ^ 2 + ↑y ^ 2
hb : ↑b = ↑u ^ 2 + ↑v ^ 2
r s : ℤ
h : ↑a * ↑b = r ^ 2 + s ^ 2
⊢ ∃ r s, ↑a * ↑b = ↑r ^ 2 + ↑s ^ 2

Next tactic:
refine' ⟨r.natAbs, s.natAbs, _⟩
/-- The set of natural numbers that are sums of two squares is closed under multiplication. -/
theorem Nat.sq_add_sq_mul {a b x y u v : ℕ} (ha : a = x ^ 2 + y ^ 2) (hb : b = u ^ 2 + v ^ 2) :
    ∃ r s : ℕ, a * b = r ^ 2 + s ^ 2 := by
  zify at ha hb ⊢
  obtain ⟨r, s, h⟩ := _root_.sq_add_sq_mul ha hb
  refine' ⟨r.natAbs, s.natAbs, _⟩
  

Proof state:
case intro.intro
a b x y u v : ℕ
ha : ↑a = ↑x ^ 2 + ↑y ^ 2
hb : ↑b = ↑u ^ 2 + ↑v ^ 2
r s : ℤ
h : ↑a * ↑b = r ^ 2 + s ^ 2
⊢ ↑a * ↑b = ↑(Int.natAbs r) ^ 2 + ↑(Int.natAbs s) ^ 2

Next tactic:
simpa only [Int.coe_natAbs, sq_abs]
/-- If `-1` is a square modulo `n` and `m` divides `n`, then `-1` is also a square modulo `m`. -/
theorem ZMod.isSquare_neg_one_of_dvd {m n : ℕ} (hd : m ∣ n) (hs : IsSquare (-1 : ZMod n)) :
    IsSquare (-1 : ZMod m) := by
  

Proof state:
m n : ℕ
hd : m ∣ n
hs : IsSquare (-1)
⊢ IsSquare (-1)

Next tactic:
let f : ZMod n →+* ZMod m := ZMod.castHom hd _
/-- If `-1` is a square modulo `n` and `m` divides `n`, then `-1` is also a square modulo `m`. -/
theorem ZMod.isSquare_neg_one_of_dvd {m n : ℕ} (hd : m ∣ n) (hs : IsSquare (-1 : ZMod n)) :
    IsSquare (-1 : ZMod m) := by
  let f : ZMod n →+* ZMod m := ZMod.castHom hd _
  

Proof state:
m n : ℕ
hd : m ∣ n
hs : IsSquare (-1)
f : ZMod n →+* ZMod m := castHom hd (ZMod m)
⊢ IsSquare (-1)

Next tactic:
rw [← RingHom.map_one f, ← RingHom.map_neg]
/-- If `-1` is a square modulo `n` and `m` divides `n`, then `-1` is also a square modulo `m`. -/
theorem ZMod.isSquare_neg_one_of_dvd {m n : ℕ} (hd : m ∣ n) (hs : IsSquare (-1 : ZMod n)) :
    IsSquare (-1 : ZMod m) := by
  let f : ZMod n →+* ZMod m := ZMod.castHom hd _
  rw [← RingHom.map_one f, ← RingHom.map_neg]
  

Proof state:
m n : ℕ
hd : m ∣ n
hs : IsSquare (-1)
f : ZMod n →+* ZMod m := castHom hd (ZMod m)
⊢ IsSquare (f (-1))

Next tactic:
exact hs.map f
/-- If `-1` is a square modulo coprime natural numbers `m` and `n`, then `-1` is also
a square modulo `m*n`. -/
theorem ZMod.isSquare_neg_one_mul {m n : ℕ} (hc : m.Coprime n) (hm : IsSquare (-1 : ZMod m))
    (hn : IsSquare (-1 : ZMod n)) : IsSquare (-1 : ZMod (m * n)) := by
  

Proof state:
m n : ℕ
hc : Nat.Coprime m n
hm : IsSquare (-1)
hn : IsSquare (-1)
⊢ IsSquare (-1)

Next tactic:
have : IsSquare (-1 : ZMod m × ZMod n) := by
    rw [show (-1 : ZMod m × ZMod n) = ((-1 : ZMod m), (-1 : ZMod n)) from rfl]
    obtain ⟨x, hx⟩ := hm
    obtain ⟨y, hy⟩ := hn
    rw [hx, hy]
    exact ⟨(x, y), rfl⟩
/-- If `-1` is a square modulo coprime natural numbers `m` and `n`, then `-1` is also
a square modulo `m*n`. -/
theorem ZMod.isSquare_neg_one_mul {m n : ℕ} (hc : m.Coprime n) (hm : IsSquare (-1 : ZMod m))
    (hn : IsSquare (-1 : ZMod n)) : IsSquare (-1 : ZMod (m * n)) := by
  have : IsSquare (-1 : ZMod m × ZMod n) := by
    

Proof state:
m n : ℕ
hc : Nat.Coprime m n
hm : IsSquare (-1)
hn : IsSquare (-1)
⊢ IsSquare (-1)

Next tactic:
rw [show (-1 : ZMod m × ZMod n) = ((-1 : ZMod m), (-1 : ZMod n)) from rfl]
/-- If `-1` is a square modulo coprime natural numbers `m` and `n`, then `-1` is also
a square modulo `m*n`. -/
theorem ZMod.isSquare_neg_one_mul {m n : ℕ} (hc : m.Coprime n) (hm : IsSquare (-1 : ZMod m))
    (hn : IsSquare (-1 : ZMod n)) : IsSquare (-1 : ZMod (m * n)) := by
  have : IsSquare (-1 : ZMod m × ZMod n) := by
    rw [show (-1 : ZMod m × ZMod n) = ((-1 : ZMod m), (-1 : ZMod n)) from rfl]
    

Proof state:
m n : ℕ
hc : Nat.Coprime m n
hm : IsSquare (-1)
hn : IsSquare (-1)
⊢ IsSquare (-1, -1)

Next tactic:
obtain ⟨x, hx⟩ := hm