l3lab/ntp-mathlib huggingface dataset:
theorem sUnion_lem {α β : Type u} (A : α → PSet) (B : β → PSet) (αβ : ∀ a, ∃ b, Equiv (A a) (B b)) :
    ∀ a, ∃ b, Equiv ((sUnion ⟨α, A⟩).Func a) ((sUnion ⟨β, B⟩).Func b)
  | ⟨a, c⟩ => by
    let ⟨b, hb⟩ := αβ a
    induction' ea : A a with γ Γ
    induction' eb : B b with δ Δ
    rw [ea, eb] at hb
    cases' hb with γδ δγ
    let c : (A a).Type := c
    let ⟨d, hd⟩ := γδ (by rwa [ea] at c)
    use ⟨b, Eq.ndrec d (Eq.symm eb)⟩
    change PSet.Equiv ((A a).Func c) ((B b).Func (Eq.ndrec d eb.symm))
    

Proof state:
case h
α β : Type u
A : α → PSet
B : β → PSet
αβ : ∀ (a : α), ∃ b, PSet.Equiv (A a) (B b)
a : Type (PSet.mk α A)
c✝ : Type (Func (PSet.mk α A) a)
b : β
γ : Type u
Γ : γ → PSet
A_ih✝¹ :
  ∀ (a_1 : γ), A a = Γ a_1 → ∃ b, PSet.Equiv (Func (⋃₀ PSet.mk α A) { fst := a, snd := c✝ }) (Func (⋃₀ PSet.mk β B) b)
ea : A a = PSet.mk γ Γ
δ : Type u
Δ : δ → PSet
A_ih✝ :
  ∀ (a_1 : δ), B b = Δ a_1 → ∃ b, PSet.Equiv (Func (⋃₀ PSet.mk α A) { fst := a, snd := c✝ }) (Func (⋃₀ PSet.mk β B) b)
eb : B b = PSet.mk δ Δ
γδ : ∀ (a : γ), ∃ b, PSet.Equiv (Γ a) (Δ b)
δγ : ∀ (b : δ), ∃ a, PSet.Equiv (Γ a) (Δ b)
c : Type (A a) := c✝
d : δ
hd : PSet.Equiv (Γ (Eq.mp (_ : Type (A a) = Type (PSet.mk γ Γ)) c)) (Δ d)
⊢ PSet.Equiv (Func (A a) c) (Func (B b) ((_ : PSet.mk δ Δ = B b) ▸ d))

Next tactic:
match A a, B b, ea, eb, c, d, hd with
    | _, _, rfl, rfl, _, _, hd => exact hd
theorem sUnion_lem {α β : Type u} (A : α → PSet) (B : β → PSet) (αβ : ∀ a, ∃ b, Equiv (A a) (B b)) :
    ∀ a, ∃ b, Equiv ((sUnion ⟨α, A⟩).Func a) ((sUnion ⟨β, B⟩).Func b)
  | ⟨a, c⟩ => by
    let ⟨b, hb⟩ := αβ a
    induction' ea : A a with γ Γ
    induction' eb : B b with δ Δ
    rw [ea, eb] at hb
    cases' hb with γδ δγ
    let c : (A a).Type := c
    let ⟨d, hd⟩ := γδ (by rwa [ea] at c)
    use ⟨b, Eq.ndrec d (Eq.symm eb)⟩
    change PSet.Equiv ((A a).Func c) ((B b).Func (Eq.ndrec d eb.symm))
    match A a, B b, ea, eb, c, d, hd with
    | _, _, rfl, rfl, _, _, hd => 

Proof state:
α β : Type u
A : α → PSet
B : β → PSet
αβ : ∀ (a : α), ∃ b, PSet.Equiv (A a) (B b)
a : Type (PSet.mk α A)
c✝ : Type (Func (PSet.mk α A) a)
b : β
γ : Type u
Γ : γ → PSet
A_ih✝¹ :
  ∀ (a_1 : γ), A a = Γ a_1 → ∃ b, PSet.Equiv (Func (⋃₀ PSet.mk α A) { fst := a, snd := c✝ }) (Func (⋃₀ PSet.mk β B) b)
ea : A a = PSet.mk γ Γ
δ : Type u
Δ : δ → PSet
A_ih✝ :
  ∀ (a_1 : δ), B b = Δ a_1 → ∃ b, PSet.Equiv (Func (⋃₀ PSet.mk α A) { fst := a, snd := c✝ }) (Func (⋃₀ PSet.mk β B) b)
eb : B b = PSet.mk δ Δ
γδ : ∀ (a : γ), ∃ b, PSet.Equiv (Γ a) (Δ b)
δγ : ∀ (b : δ), ∃ a, PSet.Equiv (Γ a) (Δ b)
c : Type (A a) := c✝
d : δ
hd✝ : PSet.Equiv (Γ (Eq.mp (_ : Type (A a) = Type (PSet.mk γ Γ)) c)) (Δ d)
x✝¹ : Type (PSet.mk γ Γ)
x✝ : δ
hd : PSet.Equiv (Γ (Eq.mp (_ : Type (PSet.mk γ Γ) = Type (PSet.mk γ Γ)) x✝¹)) (Δ x✝)
⊢ PSet.Equiv (Func (PSet.mk γ Γ) x✝¹) (Func (PSet.mk δ Δ) ((_ : PSet.mk δ Δ = PSet.mk δ Δ) ▸ x✝))

Next tactic:
exact hd
/-- The intersection operator, the collection of elements in all of the elements of a ZFC set. We
special-case `⋂₀ ∅ = ∅`. -/
noncomputable def sInter (x : ZFSet) : ZFSet := by
   

Proof state:
x : ZFSet
⊢ ZFSet

Next tactic:
classical exact if h : x.Nonempty then ZFSet.sep (fun y => ∀ z ∈ x, y ∈ z) h.some else ∅
/-- The intersection operator, the collection of elements in all of the elements of a ZFC set. We
special-case `⋂₀ ∅ = ∅`. -/
noncomputable def sInter (x : ZFSet) : ZFSet := by
   classical 

Proof state:
x : ZFSet
⊢ ZFSet

Next tactic:
exact if h : x.Nonempty then ZFSet.sep (fun y => ∀ z ∈ x, y ∈ z) h.some else ∅
theorem mem_sInter {x y : ZFSet} (h : x.Nonempty) : y ∈ ⋂₀ x ↔ ∀ z ∈ x, y ∈ z := by
  

Proof state:
x y : ZFSet
h : ZFSet.Nonempty x
⊢ y ∈ ⋂₀ x ↔ ∀ z ∈ x, y ∈ z

Next tactic:
rw [sInter, dif_pos h]
theorem mem_sInter {x y : ZFSet} (h : x.Nonempty) : y ∈ ⋂₀ x ↔ ∀ z ∈ x, y ∈ z := by
  rw [sInter, dif_pos h]
  

Proof state:
x y : ZFSet
h : ZFSet.Nonempty x
⊢ y ∈ ZFSet.sep (fun y => ∀ z ∈ x, y ∈ z) (Set.Nonempty.some h) ↔ ∀ z ∈ x, y ∈ z

Next tactic:
simp only [mem_toSet, mem_sep, and_iff_right_iff_imp]
theorem mem_sInter {x y : ZFSet} (h : x.Nonempty) : y ∈ ⋂₀ x ↔ ∀ z ∈ x, y ∈ z := by
  rw [sInter, dif_pos h]
  simp only [mem_toSet, mem_sep, and_iff_right_iff_imp]
  

Proof state:
x y : ZFSet
h : ZFSet.Nonempty x
⊢ (∀ z ∈ x, y ∈ z) → y ∈ Set.Nonempty.some h

Next tactic:
exact fun H => H _ h.some_mem
@[simp]
theorem sUnion_empty : ⋃₀ (∅ : ZFSet.{u}) = ∅ := by
  

Proof state:
⊢ ⋃₀ ∅ = ∅

Next tactic:
ext
@[simp]
theorem sUnion_empty : ⋃₀ (∅ : ZFSet.{u}) = ∅ := by
  ext
  

Proof state:
case a
z✝ : ZFSet
⊢ z✝ ∈ ⋃₀ ∅ ↔ z✝ ∈ ∅

Next tactic:
simp
@[simp]
theorem sInter_empty : ⋂₀ (∅ : ZFSet) = ∅ := dif_neg <| by 

Proof state:
⊢ ¬ZFSet.Nonempty ∅

Next tactic:
simp
theorem mem_of_mem_sInter {x y z : ZFSet} (hy : y ∈ ⋂₀ x) (hz : z ∈ x) : y ∈ z := by
  

Proof state:
x y z : ZFSet
hy : y ∈ ⋂₀ x
hz : z ∈ x
⊢ y ∈ z

Next tactic:
rcases eq_empty_or_nonempty x with (rfl | hx)
theorem mem_of_mem_sInter {x y z : ZFSet} (hy : y ∈ ⋂₀ x) (hz : z ∈ x) : y ∈ z := by
  rcases eq_empty_or_nonempty x with (rfl | hx)
  · 

Proof state:
case inl
y z : ZFSet
hy : y ∈ ⋂₀ ∅
hz : z ∈ ∅
⊢ y ∈ z

Next tactic:
exact (not_mem_empty z hz).elim
theorem mem_of_mem_sInter {x y z : ZFSet} (hy : y ∈ ⋂₀ x) (hz : z ∈ x) : y ∈ z := by
  rcases eq_empty_or_nonempty x with (rfl | hx)
  · exact (not_mem_empty z hz).elim
  · 

Proof state:
case inr
x y z : ZFSet
hy : y ∈ ⋂₀ x
hz : z ∈ x
hx : ZFSet.Nonempty x
⊢ y ∈ z

Next tactic:
exact (mem_sInter hx).1 hy z hz
@[simp]
theorem sUnion_singleton {x : ZFSet.{u}} : ⋃₀ ({x} : ZFSet) = x :=
  ext fun y => by 

Proof state:
x y : ZFSet
⊢ y ∈ ⋃₀ {x} ↔ y ∈ x

Next tactic:
simp_rw [mem_sUnion, mem_singleton, exists_eq_left]
@[simp]
theorem sInter_singleton {x : ZFSet.{u}} : ⋂₀ ({x} : ZFSet) = x :=
  ext fun y => by 

Proof state:
x y : ZFSet
⊢ y ∈ ⋂₀ {x} ↔ y ∈ x

Next tactic:
simp_rw [mem_sInter (singleton_nonempty x), mem_singleton, forall_eq]
@[simp]
theorem toSet_sUnion (x : ZFSet.{u}) : (⋃₀ x).toSet = ⋃₀ (toSet '' x.toSet) := by
  

Proof state:
x : ZFSet
⊢ toSet (⋃₀ x) = ⋃₀ (toSet '' toSet x)

Next tactic:
ext
@[simp]
theorem toSet_sUnion (x : ZFSet.{u}) : (⋃₀ x).toSet = ⋃₀ (toSet '' x.toSet) := by
  ext
  

Proof state:
case h
x x✝ : ZFSet
⊢ x✝ ∈ toSet (⋃₀ x) ↔ x✝ ∈ ⋃₀ (toSet '' toSet x)

Next tactic:
simp
theorem toSet_sInter {x : ZFSet.{u}} (h : x.Nonempty) : (⋂₀ x).toSet = ⋂₀ (toSet '' x.toSet) := by
  

Proof state:
x : ZFSet
h : ZFSet.Nonempty x
⊢ toSet (⋂₀ x) = ⋂₀ (toSet '' toSet x)

Next tactic:
ext
theorem toSet_sInter {x : ZFSet.{u}} (h : x.Nonempty) : (⋂₀ x).toSet = ⋂₀ (toSet '' x.toSet) := by
  ext
  

Proof state:
case h
x : ZFSet
h : ZFSet.Nonempty x
x✝ : ZFSet
⊢ x✝ ∈ toSet (⋂₀ x) ↔ x✝ ∈ ⋂₀ (toSet '' toSet x)

Next tactic:
simp [mem_sInter h]
theorem singleton_injective : Function.Injective (@singleton ZFSet ZFSet _) := fun x y H => by
  

Proof state:
x y : ZFSet
H : {x} = {y}
⊢ x = y

Next tactic:
let this := congr_arg sUnion H
theorem singleton_injective : Function.Injective (@singleton ZFSet ZFSet _) := fun x y H => by
  let this := congr_arg sUnion H
  

Proof state:
x y : ZFSet
H : {x} = {y}
this : ⋃₀ {x} = ⋃₀ {y} := congr_arg sUnion H
⊢ x = y

Next tactic:
rwa [sUnion_singleton, sUnion_singleton] at this
@[simp]
theorem toSet_union (x y : ZFSet.{u}) : (x ∪ y).toSet = x.toSet ∪ y.toSet := by
  

Proof state:
x y : ZFSet
⊢ toSet (x ∪ y) = toSet x ∪ toSet y

Next tactic:
change (⋃₀ {x, y}).toSet = _
@[simp]
theorem toSet_union (x y : ZFSet.{u}) : (x ∪ y).toSet = x.toSet ∪ y.toSet := by
  change (⋃₀ {x, y}).toSet = _
  

Proof state:
x y : ZFSet
⊢ toSet (⋃₀ {x, y}) = toSet x ∪ toSet y

Next tactic:
simp
@[simp]
theorem toSet_inter (x y : ZFSet.{u}) : (x ∩ y).toSet = x.toSet ∩ y.toSet := by
  

Proof state:
x y : ZFSet
⊢ toSet (x ∩ y) = toSet x ∩ toSet y

Next tactic:
change (ZFSet.sep (fun z => z ∈ y) x).toSet = _
@[simp]
theorem toSet_inter (x y : ZFSet.{u}) : (x ∩ y).toSet = x.toSet ∩ y.toSet := by
  change (ZFSet.sep (fun z => z ∈ y) x).toSet = _
  

Proof state:
x y : ZFSet
⊢ toSet (ZFSet.sep (fun z => z ∈ y) x) = toSet x ∩ toSet y

Next tactic:
ext
@[simp]
theorem toSet_inter (x y : ZFSet.{u}) : (x ∩ y).toSet = x.toSet ∩ y.toSet := by
  change (ZFSet.sep (fun z => z ∈ y) x).toSet = _
  ext
  

Proof state:
case h
x y x✝ : ZFSet
⊢ x✝ ∈ toSet (ZFSet.sep (fun z => z ∈ y) x) ↔ x✝ ∈ toSet x ∩ toSet y

Next tactic:
simp
@[simp]
theorem toSet_sdiff (x y : ZFSet.{u}) : (x \ y).toSet = x.toSet \ y.toSet := by
  

Proof state:
x y : ZFSet
⊢ toSet (x \ y) = toSet x \ toSet y

Next tactic:
change (ZFSet.sep (fun z => z ∉ y) x).toSet = _
@[simp]
theorem toSet_sdiff (x y : ZFSet.{u}) : (x \ y).toSet = x.toSet \ y.toSet := by
  change (ZFSet.sep (fun z => z ∉ y) x).toSet = _
  

Proof state:
x y : ZFSet
⊢ toSet (ZFSet.sep (fun z => z ∉ y) x) = toSet x \ toSet y

Next tactic:
ext
@[simp]
theorem toSet_sdiff (x y : ZFSet.{u}) : (x \ y).toSet = x.toSet \ y.toSet := by
  change (ZFSet.sep (fun z => z ∉ y) x).toSet = _
  ext
  

Proof state:
case h
x y x✝ : ZFSet
⊢ x✝ ∈ toSet (ZFSet.sep (fun z => z ∉ y) x) ↔ x✝ ∈ toSet x \ toSet y

Next tactic:
simp
@[simp]
theorem mem_union {x y z : ZFSet.{u}} : z ∈ x ∪ y ↔ z ∈ x ∨ z ∈ y := by
  

Proof state:
x y z : ZFSet
⊢ z ∈ x ∪ y ↔ z ∈ x ∨ z ∈ y

Next tactic:
rw [← mem_toSet]
@[simp]
theorem mem_union {x y z : ZFSet.{u}} : z ∈ x ∪ y ↔ z ∈ x ∨ z ∈ y := by
  rw [← mem_toSet]
  

Proof state:
x y z : ZFSet
⊢ z ∈ toSet (x ∪ y) ↔ z ∈ x ∨ z ∈ y

Next tactic:
simp
@[simp]
theorem toSet_image (f : ZFSet → ZFSet) [H : Definable 1 f] (x : ZFSet) :
    (image f x).toSet = f '' x.toSet := by
  

Proof state:
f : ZFSet → ZFSet
H : Definable 1 f
x : ZFSet
⊢ toSet (image f x) = f '' toSet x

Next tactic:
ext
@[simp]
theorem toSet_image (f : ZFSet → ZFSet) [H : Definable 1 f] (x : ZFSet) :
    (image f x).toSet = f '' x.toSet := by
  ext
  

Proof state:
case h
f : ZFSet → ZFSet
H : Definable 1 f
x x✝ : ZFSet
⊢ x✝ ∈ toSet (image f x) ↔ x✝ ∈ f '' toSet x

Next tactic:
simp
@[simp]
theorem mem_range {α : Type u} {f : α → ZFSet.{max u v}} {x : ZFSet.{max u v}} :
    x ∈ range.{u, v} f ↔ x ∈ Set.range f :=
  Quotient.inductionOn x fun y => by
    

Proof state:
α : Type u
f : α → ZFSet
x : ZFSet
y : PSet
⊢ ⟦y⟧ ∈ range f ↔ ⟦y⟧ ∈ Set.range f

Next tactic:
constructor
@[simp]
theorem mem_range {α : Type u} {f : α → ZFSet.{max u v}} {x : ZFSet.{max u v}} :
    x ∈ range.{u, v} f ↔ x ∈ Set.range f :=
  Quotient.inductionOn x fun y => by
    constructor
    · 

Proof state:
case mp
α : Type u
f : α → ZFSet
x : ZFSet
y : PSet
⊢ ⟦y⟧ ∈ range f → ⟦y⟧ ∈ Set.range f

Next tactic:
rintro ⟨z, hz⟩
@[simp]
theorem mem_range {α : Type u} {f : α → ZFSet.{max u v}} {x : ZFSet.{max u v}} :
    x ∈ range.{u, v} f ↔ x ∈ Set.range f :=
  Quotient.inductionOn x fun y => by
    constructor
    · rintro ⟨z, hz⟩
      

Proof state:
case mp.intro
α : Type u
f : α → ZFSet
x : ZFSet
y : PSet
z : Type (PSet.mk (ULift.{v, u} α) (Quotient.out ∘ f ∘ ULift.down))
hz : PSet.Equiv y (Func (PSet.mk (ULift.{v, u} α) (Quotient.out ∘ f ∘ ULift.down)) z)
⊢ ⟦y⟧ ∈ Set.range f

Next tactic:
exact ⟨z.down, Quotient.eq_mk_iff_out.2 hz.symm⟩
@[simp]
theorem mem_range {α : Type u} {f : α → ZFSet.{max u v}} {x : ZFSet.{max u v}} :
    x ∈ range.{u, v} f ↔ x ∈ Set.range f :=
  Quotient.inductionOn x fun y => by
    constructor
    · rintro ⟨z, hz⟩
      exact ⟨z.down, Quotient.eq_mk_iff_out.2 hz.symm⟩
    · 

Proof state:
case mpr
α : Type u
f : α → ZFSet
x : ZFSet
y : PSet
⊢ ⟦y⟧ ∈ Set.range f → ⟦y⟧ ∈ range f

Next tactic:
rintro ⟨z, hz⟩
@[simp]
theorem mem_range {α : Type u} {f : α → ZFSet.{max u v}} {x : ZFSet.{max u v}} :
    x ∈ range.{u, v} f ↔ x ∈ Set.range f :=
  Quotient.inductionOn x fun y => by
    constructor
    · rintro ⟨z, hz⟩
      exact ⟨z.down, Quotient.eq_mk_iff_out.2 hz.symm⟩
    · rintro ⟨z, hz⟩
      

Proof state:
case mpr.intro
α : Type u
f : α → ZFSet
x : ZFSet
y : PSet
z : α
hz : f z = ⟦y⟧
⊢ ⟦y⟧ ∈ range f

Next tactic:
use ULift.up z
@[simp]
theorem mem_range {α : Type u} {f : α → ZFSet.{max u v}} {x : ZFSet.{max u v}} :
    x ∈ range.{u, v} f ↔ x ∈ Set.range f :=
  Quotient.inductionOn x fun y => by
    constructor
    · rintro ⟨z, hz⟩
      exact ⟨z.down, Quotient.eq_mk_iff_out.2 hz.symm⟩
    · rintro ⟨z, hz⟩
      use ULift.up z
      

Proof state:
case h
α : Type u
f : α → ZFSet
x : ZFSet
y : PSet
z : α
hz : f z = ⟦y⟧
⊢ PSet.Equiv y (Func (PSet.mk (ULift.{v, u} α) (Quotient.out ∘ f ∘ ULift.down)) { down := z })

Next tactic:
simpa [hz] using PSet.Equiv.symm (Quotient.mk_out y)
@[simp]
theorem toSet_range {α : Type u} (f : α → ZFSet.{max u v}) :
    (range.{u, v} f).toSet = Set.range f := by
  

Proof state:
α : Type u
f : α → ZFSet
⊢ toSet (range f) = Set.range f

Next tactic:
ext
@[simp]
theorem toSet_range {α : Type u} (f : α → ZFSet.{max u v}) :
    (range.{u, v} f).toSet = Set.range f := by
  ext
  

Proof state:
case h
α : Type u
f : α → ZFSet
x✝ : ZFSet
⊢ x✝ ∈ toSet (range f) ↔ x✝ ∈ Set.range f

Next tactic:
simp
@[simp]
theorem toSet_pair (x y : ZFSet.{u}) : (pair x y).toSet = {{x}, {x, y}} := by 

Proof state:
x y : ZFSet
⊢ toSet (pair x y) = {{x}, {x, y}}

Next tactic:
simp [pair]
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  

Proof state:
p : ZFSet → ZFSet → Prop
x y z : ZFSet
⊢ z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b

Next tactic:
refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  

Proof state:
p : ZFSet → ZFSet → Prop
x y z : ZFSet
e : ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b
⊢ z ∈ powerset (powerset (x ∪ y))

Next tactic:
rcases e with ⟨a, ax, b, bY, rfl, pab⟩
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  

Proof state:
case intro.intro.intro.intro.intro
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
⊢ pair a b ∈ powerset (powerset (x ∪ y))

Next tactic:
simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  

Proof state:
case intro.intro.intro.intro.intro
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
⊢ ∀ ⦃z : ZFSet⦄, z = {a} ∨ z = {a, b} → ∀ ⦃z_1 : ZFSet⦄, z_1 ∈ z → z_1 ∈ x ∨ z_1 ∈ y

Next tactic:
rintro u (rfl | rfl) v
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> 

Proof state:
case intro.intro.intro.intro.intro.inl
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
v : ZFSet
⊢ v ∈ {a} → v ∈ x ∨ v ∈ y

Next tactic:
simp only [mem_singleton, mem_pair]
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> 

Proof state:
case intro.intro.intro.intro.intro.inr
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
v : ZFSet
⊢ v ∈ {a, b} → v ∈ x ∨ v ∈ y

Next tactic:
simp only [mem_singleton, mem_pair]
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · 

Proof state:
case intro.intro.intro.intro.intro.inl
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
v : ZFSet
⊢ v = a → v ∈ x ∨ v ∈ y

Next tactic:
rintro rfl
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    

Proof state:
case intro.intro.intro.intro.intro.inl
p : ZFSet → ZFSet → Prop
x y b : ZFSet
bY : b ∈ y
v : ZFSet
ax : v ∈ x
pab : p v b
⊢ v ∈ x ∨ v ∈ y

Next tactic:
exact Or.inl ax
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    exact Or.inl ax
  · 

Proof state:
case intro.intro.intro.intro.intro.inr
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
v : ZFSet
⊢ v = a ∨ v = b → v ∈ x ∨ v ∈ y

Next tactic:
rintro (rfl | rfl) <;> [left; right]
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    exact Or.inl ax
  · 

Proof state:
case intro.intro.intro.intro.intro.inr
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
b : ZFSet
bY : b ∈ y
pab : p a b
v : ZFSet
⊢ v = a ∨ v = b → v ∈ x ∨ v ∈ y

Next tactic:
rintro (rfl | rfl)
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    exact Or.inl ax
  · rintro (rfl | rfl) <;> [

Proof state:
case intro.intro.intro.intro.intro.inr.inl
p : ZFSet → ZFSet → Prop
x y b : ZFSet
bY : b ∈ y
v : ZFSet
ax : v ∈ x
pab : p v b
⊢ v ∈ x ∨ v ∈ y

Next tactic:
left
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    exact Or.inl ax
  · rintro (rfl | rfl) <;> [left; 

Proof state:
case intro.intro.intro.intro.intro.inr.inr
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
v : ZFSet
bY : v ∈ y
pab : p a v
⊢ v ∈ x ∨ v ∈ y

Next tactic:
right
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    exact Or.inl ax
  · rintro (rfl | rfl) <;> [left; right] <;> 

Proof state:
case intro.intro.intro.intro.intro.inr.inl.h
p : ZFSet → ZFSet → Prop
x y b : ZFSet
bY : b ∈ y
v : ZFSet
ax : v ∈ x
pab : p v b
⊢ v ∈ x

Next tactic:
assumption
@[simp]
theorem mem_pairSep {p} {x y z : ZFSet.{u}} :
    z ∈ pairSep p x y ↔ ∃ a ∈ x, ∃ b ∈ y, z = pair a b ∧ p a b := by
  refine' mem_sep.trans ⟨And.right, fun e => ⟨_, e⟩⟩
  rcases e with ⟨a, ax, b, bY, rfl, pab⟩
  simp only [mem_powerset, subset_def, mem_union, pair, mem_pair]
  rintro u (rfl | rfl) v <;> simp only [mem_singleton, mem_pair]
  · rintro rfl
    exact Or.inl ax
  · rintro (rfl | rfl) <;> [left; right] <;> 

Proof state:
case intro.intro.intro.intro.intro.inr.inr.h
p : ZFSet → ZFSet → Prop
x y a : ZFSet
ax : a ∈ x
v : ZFSet
bY : v ∈ y
pab : p a v
⊢ v ∈ y

Next tactic:
assumption
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  

Proof state:
x x' y y' : ZFSet
H : pair x y = pair x' y'
⊢ x = x' ∧ y = y'

Next tactic:
have ae := ext_iff.1 H
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  

Proof state:
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z ∈ pair x y ↔ z ∈ pair x' y'
⊢ x = x' ∧ y = y'

Next tactic:
simp only [pair, mem_pair] at ae
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  

Proof state:
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
⊢ x = x' ∧ y = y'

Next tactic:
obtain rfl : x = x' := by
    cases' (ae {x}).1 (by simp) with h h
    · exact singleton_injective h
    · have m : x' ∈ ({x} : ZFSet) := by simp [h]
      rw [mem_singleton.mp m]
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  obtain rfl : x = x' := by
    

Proof state:
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
⊢ x = x'

Next tactic:
cases' (ae {x}).1 (by simp) with h h
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  obtain rfl : x = x' := by
    cases' (ae {x}).1 (by 

Proof state:
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
⊢ {x} = {x} ∨ {x} = {x, y}

Next tactic:
simp
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  obtain rfl : x = x' := by
    cases' (ae {x}).1 (by simp) with h h
    · 

Proof state:
case inl
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
h : {x} = {x'}
⊢ x = x'

Next tactic:
exact singleton_injective h
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  obtain rfl : x = x' := by
    cases' (ae {x}).1 (by simp) with h h
    · exact singleton_injective h
    · 

Proof state:
case inr
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
h : {x} = {x', y'}
⊢ x = x'

Next tactic:
have m : x' ∈ ({x} : ZFSet) := by simp [h]
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  obtain rfl : x = x' := by
    cases' (ae {x}).1 (by simp) with h h
    · exact singleton_injective h
    · have m : x' ∈ ({x} : ZFSet) := by 

Proof state:
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
h : {x} = {x', y'}
⊢ x' ∈ {x}

Next tactic:
simp [h]
theorem pair_injective : Function.Injective2 pair := fun x x' y y' H => by
  have ae := ext_iff.1 H
  simp only [pair, mem_pair] at ae
  obtain rfl : x = x' := by
    cases' (ae {x}).1 (by simp) with h h
    · exact singleton_injective h
    · have m : x' ∈ ({x} : ZFSet) := by simp [h]
      

Proof state:
case inr
x x' y y' : ZFSet
H : pair x y = pair x' y'
ae : ∀ (z : ZFSet), z = {x} ∨ z = {x, y} ↔ z = {x'} ∨ z = {x', y'}
h : {x} = {x', y'}
m : x' ∈ {x}
⊢ x = x'

Next tactic:
rw [mem_singleton.mp m]