l3lab/ntp-mathlib huggingface dataset:
instance forgetReflectIsos : ReflectsIsomorphisms (forget CommSemiRingCat) where
  reflects {X Y} f _ := by
    let i := asIso ((forget CommSemiRingCat).map f)
    

Proof state:
X Y : CommSemiRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommSemiRingCat).map f)
i : (forget CommSemiRingCat).obj X ≅ (forget CommSemiRingCat).obj Y := asIso ((forget CommSemiRingCat).map f)
⊢ IsIso f

Next tactic:
let ff : X →+* Y := f
instance forgetReflectIsos : ReflectsIsomorphisms (forget CommSemiRingCat) where
  reflects {X Y} f _ := by
    let i := asIso ((forget CommSemiRingCat).map f)
    let ff : X →+* Y := f
    

Proof state:
X Y : CommSemiRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommSemiRingCat).map f)
i : (forget CommSemiRingCat).obj X ≅ (forget CommSemiRingCat).obj Y := asIso ((forget CommSemiRingCat).map f)
ff : ↑X →+* ↑Y := f
⊢ IsIso f

Next tactic:
let e : X ≃+* Y := { ff, i.toEquiv with }
instance forgetReflectIsos : ReflectsIsomorphisms (forget CommSemiRingCat) where
  reflects {X Y} f _ := by
    let i := asIso ((forget CommSemiRingCat).map f)
    let ff : X →+* Y := f
    let e : X ≃+* Y := { ff, i.toEquiv with }
    

Proof state:
X Y : CommSemiRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommSemiRingCat).map f)
i : (forget CommSemiRingCat).obj X ≅ (forget CommSemiRingCat).obj Y := asIso ((forget CommSemiRingCat).map f)
ff : ↑X →+* ↑Y := f
e : ↑X ≃+* ↑Y :=
  let src := i.toEquiv;
  {
    toEquiv :=
      { toFun := ff.toFun, invFun := src.invFun, left_inv := (_ : Function.LeftInverse src.invFun src.toFun),
        right_inv := (_ : Function.RightInverse src.invFun src.toFun) },
    map_mul' := (_ : ∀ (x y : ↑X), OneHom.toFun (↑↑ff) (x * y) = OneHom.toFun (↑↑ff) x * OneHom.toFun (↑↑ff) y),
    map_add' := (_ : ∀ (x y : ↑X), OneHom.toFun (↑↑ff) (x + y) = OneHom.toFun (↑↑ff) x + OneHom.toFun (↑↑ff) y) }
⊢ IsIso f

Next tactic:
exact ⟨(IsIso.of_iso e.toSemiRingCatIso).1⟩
instance : ConcreteCategory CommRingCat := by
  

Proof state:
⊢ ConcreteCategory CommRingCat

Next tactic:
dsimp [CommRingCat]
instance : ConcreteCategory CommRingCat := by
  dsimp [CommRingCat]
  

Proof state:
⊢ ConcreteCategory (Bundled CommRing)

Next tactic:
infer_instance
/-- The forgetful functor from commutative rings to (multiplicative) commutative monoids. -/
instance hasForgetToCommSemiRingCat : HasForget₂ CommRingCat CommSemiRingCat :=
  HasForget₂.mk' (fun R : CommRingCat => CommSemiRingCat.of R) (fun R => rfl)
    (fun {R₁ R₂} f => f) (by 

Proof state:
⊢ ∀ {X Y : CommRingCat} {f : X ⟶ Y},
    HEq ((forget CommSemiRingCat).map ((fun {R₁ R₂} f => f) f)) ((forget CommRingCat).map f)

Next tactic:
rfl
example {R S : CommRingCat} (i : R ⟶ S) (r : R) (h : r = 0) : i r = 0 := by 

Proof state:
R S : CommRingCat
i : R ⟶ S
r : ↑R
h : r = 0
⊢ i r = 0

Next tactic:
simp [h]
/-- Build a `RingEquiv` from an isomorphism in the category `RingCat`. -/
def ringCatIsoToRingEquiv {X Y : RingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by 

Proof state:
X Y : RingCat
i : X ≅ Y
x : ↑X
⊢ (i.hom ≫ i.inv) x = x

Next tactic:
rw [i.hom_inv_id]
/-- Build a `RingEquiv` from an isomorphism in the category `RingCat`. -/
def ringCatIsoToRingEquiv {X Y : RingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by rw [i.hom_inv_id]; 

Proof state:
X Y : RingCat
i : X ≅ Y
x : ↑X
⊢ (𝟙 X) x = x

Next tactic:
rfl
/-- Build a `RingEquiv` from an isomorphism in the category `RingCat`. -/
def ringCatIsoToRingEquiv {X Y : RingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by rw [i.hom_inv_id]; rfl
  right_inv := fun x => show (i.inv ≫ i.hom) x = x by 

Proof state:
X Y : RingCat
i : X ≅ Y
x : ↑Y
⊢ (i.inv ≫ i.hom) x = x

Next tactic:
rw [i.inv_hom_id]
/-- Build a `RingEquiv` from an isomorphism in the category `RingCat`. -/
def ringCatIsoToRingEquiv {X Y : RingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by rw [i.hom_inv_id]; rfl
  right_inv := fun x => show (i.inv ≫ i.hom) x = x by rw [i.inv_hom_id]; 

Proof state:
X Y : RingCat
i : X ≅ Y
x : ↑Y
⊢ (𝟙 Y) x = x

Next tactic:
rfl
/-- Build a `RingEquiv` from an isomorphism in the category `CommRingCat`. -/
def commRingCatIsoToRingEquiv {X Y : CommRingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by 

Proof state:
X Y : CommRingCat
i : X ≅ Y
x : ↑X
⊢ (i.hom ≫ i.inv) x = x

Next tactic:
rw [i.hom_inv_id]
/-- Build a `RingEquiv` from an isomorphism in the category `CommRingCat`. -/
def commRingCatIsoToRingEquiv {X Y : CommRingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by rw [i.hom_inv_id]; 

Proof state:
X Y : CommRingCat
i : X ≅ Y
x : ↑X
⊢ (𝟙 X) x = x

Next tactic:
rfl
/-- Build a `RingEquiv` from an isomorphism in the category `CommRingCat`. -/
def commRingCatIsoToRingEquiv {X Y : CommRingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by rw [i.hom_inv_id]; rfl
  right_inv := fun x => show (i.inv ≫ i.hom) x = x by 

Proof state:
X Y : CommRingCat
i : X ≅ Y
x : ↑Y
⊢ (i.inv ≫ i.hom) x = x

Next tactic:
rw [i.inv_hom_id]
/-- Build a `RingEquiv` from an isomorphism in the category `CommRingCat`. -/
def commRingCatIsoToRingEquiv {X Y : CommRingCat} (i : X ≅ Y) : X ≃+* Y
    where
  toFun := i.hom
  invFun := i.inv
  -- Porting note: All these proofs were much easier in lean3.
  left_inv := fun x => show (i.hom ≫ i.inv) x = x by rw [i.hom_inv_id]; rfl
  right_inv := fun x => show (i.inv ≫ i.hom) x = x by rw [i.inv_hom_id]; 

Proof state:
X Y : CommRingCat
i : X ≅ Y
x : ↑Y
⊢ (𝟙 Y) x = x

Next tactic:
rfl
@[simp (high)]
theorem commRingIsoToRingEquiv_toRingHom {X Y : CommRingCat} (i : X ≅ Y) :
    i.commRingCatIsoToRingEquiv.toRingHom = i.hom := by
  

Proof state:
X Y : CommRingCat
i : X ≅ Y
⊢ RingEquiv.toRingHom (commRingCatIsoToRingEquiv i) = i.hom

Next tactic:
ext
@[simp (high)]
theorem commRingIsoToRingEquiv_toRingHom {X Y : CommRingCat} (i : X ≅ Y) :
    i.commRingCatIsoToRingEquiv.toRingHom = i.hom := by
  ext
  

Proof state:
case a
X Y : CommRingCat
i : X ≅ Y
x✝ : ↑X
⊢ (RingEquiv.toRingHom (commRingCatIsoToRingEquiv i)) x✝ = i.hom x✝

Next tactic:
rfl
@[simp (high)]
theorem commRingIsoToRingEquiv_symm_toRingHom {X Y : CommRingCat} (i : X ≅ Y) :
    i.commRingCatIsoToRingEquiv.symm.toRingHom = i.inv := by
  

Proof state:
X Y : CommRingCat
i : X ≅ Y
⊢ RingEquiv.toRingHom (RingEquiv.symm (commRingCatIsoToRingEquiv i)) = i.inv

Next tactic:
ext
@[simp (high)]
theorem commRingIsoToRingEquiv_symm_toRingHom {X Y : CommRingCat} (i : X ≅ Y) :
    i.commRingCatIsoToRingEquiv.symm.toRingHom = i.inv := by
  ext
  

Proof state:
case a
X Y : CommRingCat
i : X ≅ Y
x✝ : ↑Y
⊢ (RingEquiv.toRingHom (RingEquiv.symm (commRingCatIsoToRingEquiv i))) x✝ = i.inv x✝

Next tactic:
rfl
instance RingCat.forget_reflects_isos : ReflectsIsomorphisms (forget RingCat.{u}) where
  reflects {X Y} f _ := by
    

Proof state:
X Y : RingCat
f : X ⟶ Y
x✝ : IsIso ((forget RingCat).map f)
⊢ IsIso f

Next tactic:
let i := asIso ((forget RingCat).map f)
instance RingCat.forget_reflects_isos : ReflectsIsomorphisms (forget RingCat.{u}) where
  reflects {X Y} f _ := by
    let i := asIso ((forget RingCat).map f)
    

Proof state:
X Y : RingCat
f : X ⟶ Y
x✝ : IsIso ((forget RingCat).map f)
i : (forget RingCat).obj X ≅ (forget RingCat).obj Y := asIso ((forget RingCat).map f)
⊢ IsIso f

Next tactic:
let ff : X →+* Y := f
instance RingCat.forget_reflects_isos : ReflectsIsomorphisms (forget RingCat.{u}) where
  reflects {X Y} f _ := by
    let i := asIso ((forget RingCat).map f)
    let ff : X →+* Y := f
    

Proof state:
X Y : RingCat
f : X ⟶ Y
x✝ : IsIso ((forget RingCat).map f)
i : (forget RingCat).obj X ≅ (forget RingCat).obj Y := asIso ((forget RingCat).map f)
ff : ↑X →+* ↑Y := f
⊢ IsIso f

Next tactic:
let e : X ≃+* Y := { ff, i.toEquiv with }
instance RingCat.forget_reflects_isos : ReflectsIsomorphisms (forget RingCat.{u}) where
  reflects {X Y} f _ := by
    let i := asIso ((forget RingCat).map f)
    let ff : X →+* Y := f
    let e : X ≃+* Y := { ff, i.toEquiv with }
    

Proof state:
X Y : RingCat
f : X ⟶ Y
x✝ : IsIso ((forget RingCat).map f)
i : (forget RingCat).obj X ≅ (forget RingCat).obj Y := asIso ((forget RingCat).map f)
ff : ↑X →+* ↑Y := f
e : ↑X ≃+* ↑Y :=
  let src := i.toEquiv;
  {
    toEquiv :=
      { toFun := ff.toFun, invFun := src.invFun, left_inv := (_ : Function.LeftInverse src.invFun src.toFun),
        right_inv := (_ : Function.RightInverse src.invFun src.toFun) },
    map_mul' := (_ : ∀ (x y : ↑X), OneHom.toFun (↑↑ff) (x * y) = OneHom.toFun (↑↑ff) x * OneHom.toFun (↑↑ff) y),
    map_add' := (_ : ∀ (x y : ↑X), OneHom.toFun (↑↑ff) (x + y) = OneHom.toFun (↑↑ff) x + OneHom.toFun (↑↑ff) y) }
⊢ IsIso f

Next tactic:
exact ⟨(IsIso.of_iso e.toRingCatIso).1⟩
instance CommRingCat.forget_reflects_isos : ReflectsIsomorphisms (forget CommRingCat.{u}) where
  reflects {X Y} f _ := by
    

Proof state:
X Y : CommRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommRingCat).map f)
⊢ IsIso f

Next tactic:
let i := asIso ((forget CommRingCat).map f)
instance CommRingCat.forget_reflects_isos : ReflectsIsomorphisms (forget CommRingCat.{u}) where
  reflects {X Y} f _ := by
    let i := asIso ((forget CommRingCat).map f)
    

Proof state:
X Y : CommRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommRingCat).map f)
i : (forget CommRingCat).obj X ≅ (forget CommRingCat).obj Y := asIso ((forget CommRingCat).map f)
⊢ IsIso f

Next tactic:
let ff : X →+* Y := f
instance CommRingCat.forget_reflects_isos : ReflectsIsomorphisms (forget CommRingCat.{u}) where
  reflects {X Y} f _ := by
    let i := asIso ((forget CommRingCat).map f)
    let ff : X →+* Y := f
    

Proof state:
X Y : CommRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommRingCat).map f)
i : (forget CommRingCat).obj X ≅ (forget CommRingCat).obj Y := asIso ((forget CommRingCat).map f)
ff : ↑X →+* ↑Y := f
⊢ IsIso f

Next tactic:
let e : X ≃+* Y := { ff, i.toEquiv with }
instance CommRingCat.forget_reflects_isos : ReflectsIsomorphisms (forget CommRingCat.{u}) where
  reflects {X Y} f _ := by
    let i := asIso ((forget CommRingCat).map f)
    let ff : X →+* Y := f
    let e : X ≃+* Y := { ff, i.toEquiv with }
    

Proof state:
X Y : CommRingCat
f : X ⟶ Y
x✝ : IsIso ((forget CommRingCat).map f)
i : (forget CommRingCat).obj X ≅ (forget CommRingCat).obj Y := asIso ((forget CommRingCat).map f)
ff : ↑X →+* ↑Y := f
e : ↑X ≃+* ↑Y :=
  let src := i.toEquiv;
  {
    toEquiv :=
      { toFun := ff.toFun, invFun := src.invFun, left_inv := (_ : Function.LeftInverse src.invFun src.toFun),
        right_inv := (_ : Function.RightInverse src.invFun src.toFun) },
    map_mul' := (_ : ∀ (x y : ↑X), OneHom.toFun (↑↑ff) (x * y) = OneHom.toFun (↑↑ff) x * OneHom.toFun (↑↑ff) y),
    map_add' := (_ : ∀ (x y : ↑X), OneHom.toFun (↑↑ff) (x + y) = OneHom.toFun (↑↑ff) x + OneHom.toFun (↑↑ff) y) }
⊢ IsIso f

Next tactic:
exact ⟨(IsIso.of_iso e.toCommRingCatIso).1⟩
example : ReflectsIsomorphisms (forget₂ RingCat AddCommGroupCat) := by 

Proof state:
⊢ ReflectsIsomorphisms (forget₂ RingCat AddCommGroupCat)

Next tactic:
infer_instance
/-- Rectangles formed by π-systems form a π-system. -/
theorem IsPiSystem.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsPiSystem C)
    (hD : IsPiSystem D) : IsPiSystem (image2 (· ×ˢ ·) C D) := by
  

Proof state:
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
hC : IsPiSystem C
hD : IsPiSystem D
⊢ IsPiSystem (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
rintro _ ⟨s₁, t₁, hs₁, ht₁, rfl⟩ _ ⟨s₂, t₂, hs₂, ht₂, rfl⟩ hst
/-- Rectangles formed by π-systems form a π-system. -/
theorem IsPiSystem.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsPiSystem C)
    (hD : IsPiSystem D) : IsPiSystem (image2 (· ×ˢ ·) C D) := by
  rintro _ ⟨s₁, t₁, hs₁, ht₁, rfl⟩ _ ⟨s₂, t₂, hs₂, ht₂, rfl⟩ hst
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
hC : IsPiSystem C
hD : IsPiSystem D
s₁ : Set α
t₁ : Set β
hs₁ : s₁ ∈ C
ht₁ : t₁ ∈ D
s₂ : Set α
t₂ : Set β
hs₂ : s₂ ∈ C
ht₂ : t₂ ∈ D
hst : Set.Nonempty ((fun x x_1 => x ×ˢ x_1) s₁ t₁ ∩ (fun x x_1 => x ×ˢ x_1) s₂ t₂)
⊢ (fun x x_1 => x ×ˢ x_1) s₁ t₁ ∩ (fun x x_1 => x ×ˢ x_1) s₂ t₂ ∈ image2 (fun x x_1 => x ×ˢ x_1) C D

Next tactic:
rw [prod_inter_prod] at hst ⊢
/-- Rectangles formed by π-systems form a π-system. -/
theorem IsPiSystem.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsPiSystem C)
    (hD : IsPiSystem D) : IsPiSystem (image2 (· ×ˢ ·) C D) := by
  rintro _ ⟨s₁, t₁, hs₁, ht₁, rfl⟩ _ ⟨s₂, t₂, hs₂, ht₂, rfl⟩ hst
  rw [prod_inter_prod] at hst ⊢; 

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
hC : IsPiSystem C
hD : IsPiSystem D
s₁ : Set α
t₁ : Set β
hs₁ : s₁ ∈ C
ht₁ : t₁ ∈ D
s₂ : Set α
t₂ : Set β
hs₂ : s₂ ∈ C
ht₂ : t₂ ∈ D
hst : Set.Nonempty ((s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂))
⊢ (s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂) ∈ image2 (fun x x_1 => x ×ˢ x_1) C D

Next tactic:
rw [prod_nonempty_iff] at hst
/-- Rectangles formed by π-systems form a π-system. -/
theorem IsPiSystem.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsPiSystem C)
    (hD : IsPiSystem D) : IsPiSystem (image2 (· ×ˢ ·) C D) := by
  rintro _ ⟨s₁, t₁, hs₁, ht₁, rfl⟩ _ ⟨s₂, t₂, hs₂, ht₂, rfl⟩ hst
  rw [prod_inter_prod] at hst ⊢; rw [prod_nonempty_iff] at hst
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
hC : IsPiSystem C
hD : IsPiSystem D
s₁ : Set α
t₁ : Set β
hs₁ : s₁ ∈ C
ht₁ : t₁ ∈ D
s₂ : Set α
t₂ : Set β
hs₂ : s₂ ∈ C
ht₂ : t₂ ∈ D
hst : Set.Nonempty (s₁ ∩ s₂) ∧ Set.Nonempty (t₁ ∩ t₂)
⊢ (s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂) ∈ image2 (fun x x_1 => x ×ˢ x_1) C D

Next tactic:
exact mem_image2_of_mem (hC _ hs₁ _ hs₂ hst.1) (hD _ ht₁ _ ht₂ hst.2)
/-- Rectangles of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) : IsCountablySpanning (image2 (· ×ˢ ·) C D) := by
  

Proof state:
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ IsCountablySpanning (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
rcases hC, hD with ⟨⟨s, h1s, h2s⟩, t, h1t, h2t⟩
/-- Rectangles of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) : IsCountablySpanning (image2 (· ×ˢ ·) C D) := by
  rcases hC, hD with ⟨⟨s, h1s, h2s⟩, t, h1t, h2t⟩
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
s : ℕ → Set α
h1s : ∀ (n : ℕ), s n ∈ C
h2s : ⋃ n, s n = univ
t : ℕ → Set β
h1t : ∀ (n : ℕ), t n ∈ D
h2t : ⋃ n, t n = univ
⊢ IsCountablySpanning (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
refine' ⟨fun n => s n.unpair.1 ×ˢ t n.unpair.2, fun n => mem_image2_of_mem (h1s _) (h1t _), _⟩
/-- Rectangles of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.prod {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) : IsCountablySpanning (image2 (· ×ˢ ·) C D) := by
  rcases hC, hD with ⟨⟨s, h1s, h2s⟩, t, h1t, h2t⟩
  refine' ⟨fun n => s n.unpair.1 ×ˢ t n.unpair.2, fun n => mem_image2_of_mem (h1s _) (h1t _), _⟩
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
α' : Type u_2
β : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
C : Set (Set α)
D : Set (Set β)
s : ℕ → Set α
h1s : ∀ (n : ℕ), s n ∈ C
h2s : ⋃ n, s n = univ
t : ℕ → Set β
h1t : ∀ (n : ℕ), t n ∈ D
h2t : ⋃ n, t n = univ
⊢ ⋃ n, (fun n => s (Nat.unpair n).1 ×ˢ t (Nat.unpair n).2) n = univ

Next tactic:
rw [iUnion_unpair_prod, h2s, h2t, univ_prod_univ]
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  

Proof state:
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ Prod.instMeasurableSpace = generateFrom (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
apply le_antisymm
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  apply le_antisymm
  · 

Proof state:
case a
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ Prod.instMeasurableSpace ≤ generateFrom (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
refine' sup_le _ _
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  apply le_antisymm
  · refine' sup_le _ _ <;> 

Proof state:
case a.refine'_1
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ MeasurableSpace.comap Prod.fst (generateFrom C) ≤ generateFrom (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
rw [comap_generateFrom]
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  apply le_antisymm
  · refine' sup_le _ _ <;> 

Proof state:
case a.refine'_2
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ MeasurableSpace.comap Prod.snd (generateFrom D) ≤ generateFrom (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
rw [comap_generateFrom]
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  apply le_antisymm
  · refine' sup_le _ _ <;> rw [comap_generateFrom] <;> 

Proof state:
case a.refine'_1
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ generateFrom (preimage Prod.fst '' C) ≤ generateFrom (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
apply generateFrom_le
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  apply le_antisymm
  · refine' sup_le _ _ <;> rw [comap_generateFrom] <;> 

Proof state:
case a.refine'_2
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ generateFrom (preimage Prod.snd '' D) ≤ generateFrom (image2 (fun x x_1 => x ×ˢ x_1) C D)

Next tactic:
apply generateFrom_le
/-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets
  are countably spanning. -/
theorem generateFrom_prod_eq {α β} {C : Set (Set α)} {D : Set (Set β)} (hC : IsCountablySpanning C)
    (hD : IsCountablySpanning D) :
    @Prod.instMeasurableSpace _ _ (generateFrom C) (generateFrom D) =
      generateFrom (image2 (· ×ˢ ·) C D) := by
  apply le_antisymm
  · refine' sup_le _ _ <;> rw [comap_generateFrom] <;> apply generateFrom_le <;>
      

Proof state:
case a.refine'_1.h
α✝ : Type u_1
α' : Type u_2
β✝ : Type u_3
β' : Type u_4
γ : Type u_5
E : Type u_6
inst✝⁵ : MeasurableSpace α✝
inst✝⁴ : MeasurableSpace α'
inst✝³ : MeasurableSpace β✝
inst✝² : MeasurableSpace β'
inst✝¹ : MeasurableSpace γ
μ μ' : Measure α✝
ν ν' : Measure β✝
τ : Measure γ
inst✝ : NormedAddCommGroup E
α : Type u_7
β : Type u_8
C : Set (Set α)
D : Set (Set β)
hC : IsCountablySpanning C
hD : IsCountablySpanning D
⊢ ∀ t ∈ preimage Prod.fst '' C, MeasurableSet t

Next tactic:
rintro _ ⟨s, hs, rfl⟩