l3lab/ntp-mathlib huggingface dataset:
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
          rfl
        _ = (∫ x, f 0 x) *  ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x := by
          rw [← n_ih, ← integral_prod_mul, volume_eq_prod]
        _ =  ∏ i, ∫ x, f i x := by 

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ (∫ (x : E 0), f 0 x) * ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x =
    ∏ i : Fin (Nat.succ n), ∫ (x : E i), f i x

Next tactic:
rw [Fin.prod_univ_succ]
/-- A version of **Fubini's theorem** with the variables indexed by a general finite type. -/
theorem MeasureTheory.integral_fintype_prod_eq_prod (ι : Type*) [Fintype ι] {E : ι → Type*}
    (f : (i : ι) → E i → 𝕜) [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))] :
    ∫ x : (i : ι) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  

Proof state:
𝕜 : Type u_1
inst✝³ : IsROrC 𝕜
ι : Type u_2
inst✝² : Fintype ι
E : ι → Type u_3
f : (i : ι) → E i → 𝕜
inst✝¹ : (i : ι) → MeasureSpace (E i)
inst✝ : ∀ (i : ι), SigmaFinite volume
⊢ ∫ (x : (i : ι) → E i), ∏ i : ι, f i (x i) = ∏ i : ι, ∫ (x : E i), f i x

Next tactic:
let e := (equivFin ι).symm
/-- A version of **Fubini's theorem** with the variables indexed by a general finite type. -/
theorem MeasureTheory.integral_fintype_prod_eq_prod (ι : Type*) [Fintype ι] {E : ι → Type*}
    (f : (i : ι) → E i → 𝕜) [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))] :
    ∫ x : (i : ι) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  let e := (equivFin ι).symm
  

Proof state:
𝕜 : Type u_1
inst✝³ : IsROrC 𝕜
ι : Type u_2
inst✝² : Fintype ι
E : ι → Type u_3
f : (i : ι) → E i → 𝕜
inst✝¹ : (i : ι) → MeasureSpace (E i)
inst✝ : ∀ (i : ι), SigmaFinite volume
e : Fin (card ι) ≃ ι := (equivFin ι).symm
⊢ ∫ (x : (i : ι) → E i), ∏ i : ι, f i (x i) = ∏ i : ι, ∫ (x : E i), f i x

Next tactic:
rw [← (volume_measurePreserving_piCongrLeft _ e).integral_comp']
/-- A version of **Fubini's theorem** with the variables indexed by a general finite type. -/
theorem MeasureTheory.integral_fintype_prod_eq_prod (ι : Type*) [Fintype ι] {E : ι → Type*}
    (f : (i : ι) → E i → 𝕜) [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))] :
    ∫ x : (i : ι) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  let e := (equivFin ι).symm
  rw [← (volume_measurePreserving_piCongrLeft _ e).integral_comp']
  

Proof state:
𝕜 : Type u_1
inst✝³ : IsROrC 𝕜
ι : Type u_2
inst✝² : Fintype ι
E : ι → Type u_3
f : (i : ι) → E i → 𝕜
inst✝¹ : (i : ι) → MeasureSpace (E i)
inst✝ : ∀ (i : ι), SigmaFinite volume
e : Fin (card ι) ≃ ι := (equivFin ι).symm
⊢ ∫ (x : (b : Fin (card ι)) → E (e b)), ∏ i : ι, f i ((MeasurableEquiv.piCongrLeft (fun i => E i) e) x i) =
    ∏ i : ι, ∫ (x : E i), f i x

Next tactic:
simp_rw [← e.prod_comp, MeasurableEquiv.coe_piCongrLeft, Equiv.piCongrLeft_apply_apply,
    MeasureTheory.integral_fin_nat_prod_eq_prod]
theorem MeasureTheory.integral_fintype_prod_eq_pow {E : Type*} (ι : Type*) [Fintype ι] (f : E → 𝕜)
    [MeasureSpace E] [SigmaFinite (volume : Measure E)] :
    ∫ x : ι → E, ∏ i, f (x i) = (∫ x, f x) ^ (card ι) := by
  

Proof state:
𝕜 : Type u_1
inst✝³ : IsROrC 𝕜
E : Type u_2
ι : Type u_3
inst✝² : Fintype ι
f : E → 𝕜
inst✝¹ : MeasureSpace E
inst✝ : SigmaFinite volume
⊢ ∫ (x : ι → E), ∏ i : ι, f (x i) = (∫ (x : E), f x) ^ card ι

Next tactic:
rw [integral_fintype_prod_eq_prod, Finset.prod_const, card]
theorem exists_prod_set {p : α × β → Prop} : (∃ x ∈ s ×ˢ t, p x) ↔ ∃ x ∈ s, ∃ y ∈ t, p (x, y) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
p : α × β → Prop
⊢ (∃ x ∈ s ×ˢ t, p x) ↔ ∃ x ∈ s, ∃ y ∈ t, p (x, y)

Next tactic:
simp [and_assoc]
@[simp]
theorem prod_empty : s ×ˢ (∅ : Set β) = ∅ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ s ×ˢ ∅ = ∅

Next tactic:
ext
@[simp]
theorem prod_empty : s ×ˢ (∅ : Set β) = ∅ := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x✝ : α × β
⊢ x✝ ∈ s ×ˢ ∅ ↔ x✝ ∈ ∅

Next tactic:
exact and_false_iff _
@[simp]
theorem empty_prod : (∅ : Set α) ×ˢ t = ∅ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ ∅ ×ˢ t = ∅

Next tactic:
ext
@[simp]
theorem empty_prod : (∅ : Set α) ×ˢ t = ∅ := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x✝ : α × β
⊢ x✝ ∈ ∅ ×ˢ t ↔ x✝ ∈ ∅

Next tactic:
exact false_and_iff _
@[simp, mfld_simps]
theorem univ_prod_univ : @univ α ×ˢ @univ β = univ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ univ ×ˢ univ = univ

Next tactic:
ext
@[simp, mfld_simps]
theorem univ_prod_univ : @univ α ×ˢ @univ β = univ := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x✝ : α × β
⊢ x✝ ∈ univ ×ˢ univ ↔ x✝ ∈ univ

Next tactic:
exact true_and_iff _
theorem univ_prod {t : Set β} : (univ : Set α) ×ˢ t = Prod.snd ⁻¹' t := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t✝ t₁ t₂ : Set β
a : α
b : β
t : Set β
⊢ univ ×ˢ t = Prod.snd ⁻¹' t

Next tactic:
simp [prod_eq]
theorem prod_univ {s : Set α} : s ×ˢ (univ : Set β) = Prod.fst ⁻¹' s := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
s : Set α
⊢ s ×ˢ univ = Prod.fst ⁻¹' s

Next tactic:
simp [prod_eq]
@[simp] lemma prod_eq_univ [Nonempty α] [Nonempty β] : s ×ˢ t = univ ↔ s = univ ∧ t = univ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
inst✝¹ : Nonempty α
inst✝ : Nonempty β
⊢ s ×ˢ t = univ ↔ s = univ ∧ t = univ

Next tactic:
simp [eq_univ_iff_forall, forall_and]
@[simp]
theorem singleton_prod : ({a} : Set α) ×ˢ t = Prod.mk a '' t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ {a} ×ˢ t = Prod.mk a '' t

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem singleton_prod : ({a} : Set α) ×ˢ t = Prod.mk a '' t := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ {a} ×ˢ t ↔ (x, y) ∈ Prod.mk a '' t

Next tactic:
simp [and_left_comm, eq_comm]
@[simp]
theorem prod_singleton : s ×ˢ ({b} : Set β) = (fun a => (a, b)) '' s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ s ×ˢ {b} = (fun a => (a, b)) '' s

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem prod_singleton : s ×ˢ ({b} : Set β) = (fun a => (a, b)) '' s := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ s ×ˢ {b} ↔ (x, y) ∈ (fun a => (a, b)) '' s

Next tactic:
simp [and_left_comm, eq_comm]
theorem singleton_prod_singleton : ({a} : Set α) ×ˢ ({b} : Set β) = {(a, b)} := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ {a} ×ˢ {b} = {(a, b)}

Next tactic:
simp
@[simp]
theorem union_prod : (s₁ ∪ s₂) ×ˢ t = s₁ ×ˢ t ∪ s₂ ×ˢ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ (s₁ ∪ s₂) ×ˢ t = s₁ ×ˢ t ∪ s₂ ×ˢ t

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem union_prod : (s₁ ∪ s₂) ×ˢ t = s₁ ×ˢ t ∪ s₂ ×ˢ t := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ (s₁ ∪ s₂) ×ˢ t ↔ (x, y) ∈ s₁ ×ˢ t ∪ s₂ ×ˢ t

Next tactic:
simp [or_and_right]
@[simp]
theorem prod_union : s ×ˢ (t₁ ∪ t₂) = s ×ˢ t₁ ∪ s ×ˢ t₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ s ×ˢ (t₁ ∪ t₂) = s ×ˢ t₁ ∪ s ×ˢ t₂

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem prod_union : s ×ˢ (t₁ ∪ t₂) = s ×ˢ t₁ ∪ s ×ˢ t₂ := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ s ×ˢ (t₁ ∪ t₂) ↔ (x, y) ∈ s ×ˢ t₁ ∪ s ×ˢ t₂

Next tactic:
simp [and_or_left]
theorem inter_prod : (s₁ ∩ s₂) ×ˢ t = s₁ ×ˢ t ∩ s₂ ×ˢ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ (s₁ ∩ s₂) ×ˢ t = s₁ ×ˢ t ∩ s₂ ×ˢ t

Next tactic:
ext ⟨x, y⟩
theorem inter_prod : (s₁ ∩ s₂) ×ˢ t = s₁ ×ˢ t ∩ s₂ ×ˢ t := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ (s₁ ∩ s₂) ×ˢ t ↔ (x, y) ∈ s₁ ×ˢ t ∩ s₂ ×ˢ t

Next tactic:
simp only [← and_and_right, mem_inter_iff, mem_prod]
theorem prod_inter : s ×ˢ (t₁ ∩ t₂) = s ×ˢ t₁ ∩ s ×ˢ t₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ s ×ˢ (t₁ ∩ t₂) = s ×ˢ t₁ ∩ s ×ˢ t₂

Next tactic:
ext ⟨x, y⟩
theorem prod_inter : s ×ˢ (t₁ ∩ t₂) = s ×ˢ t₁ ∩ s ×ˢ t₂ := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ s ×ˢ (t₁ ∩ t₂) ↔ (x, y) ∈ s ×ˢ t₁ ∩ s ×ˢ t₂

Next tactic:
simp only [← and_and_left, mem_inter_iff, mem_prod]
@[mfld_simps]
theorem prod_inter_prod : s₁ ×ˢ t₁ ∩ s₂ ×ˢ t₂ = (s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ s₁ ×ˢ t₁ ∩ s₂ ×ˢ t₂ = (s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂)

Next tactic:
ext ⟨x, y⟩
@[mfld_simps]
theorem prod_inter_prod : s₁ ×ˢ t₁ ∩ s₂ ×ˢ t₂ = (s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂) := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ s₁ ×ˢ t₁ ∩ s₂ ×ˢ t₂ ↔ (x, y) ∈ (s₁ ∩ s₂) ×ˢ (t₁ ∩ t₂)

Next tactic:
simp [and_assoc, and_left_comm]
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
⊢ (s ×ˢ t)ᶜ = sᶜ ×ˢ univ ∪ univ ×ˢ tᶜ

Next tactic:
ext p
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  

Proof state:
case h
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
⊢ p ∈ (s ×ˢ t)ᶜ ↔ p ∈ sᶜ ×ˢ univ ∪ univ ×ˢ tᶜ

Next tactic:
simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  

Proof state:
case h
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
⊢ p.1 ∈ s → p.2 ∉ t ↔ p.1 ∉ s ∨ p.2 ∉ t

Next tactic:
constructor
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> 

Proof state:
case h.mp
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
⊢ (p.1 ∈ s → p.2 ∉ t) → p.1 ∉ s ∨ p.2 ∉ t

Next tactic:
intro h
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> 

Proof state:
case h.mpr
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
⊢ p.1 ∉ s ∨ p.2 ∉ t → p.1 ∈ s → p.2 ∉ t

Next tactic:
intro h
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> intro h
  · 

Proof state:
case h.mp
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
h : p.1 ∈ s → p.2 ∉ t
⊢ p.1 ∉ s ∨ p.2 ∉ t

Next tactic:
by_cases fst_in_s : p.fst ∈ s
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> intro h
  · by_cases fst_in_s : p.fst ∈ s
    · 

Proof state:
case pos
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
h : p.1 ∈ s → p.2 ∉ t
fst_in_s : p.1 ∈ s
⊢ p.1 ∉ s ∨ p.2 ∉ t

Next tactic:
exact Or.inr (h fst_in_s)
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> intro h
  · by_cases fst_in_s : p.fst ∈ s
    · exact Or.inr (h fst_in_s)
    · 

Proof state:
case neg
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
h : p.1 ∈ s → p.2 ∉ t
fst_in_s : p.1 ∉ s
⊢ p.1 ∉ s ∨ p.2 ∉ t

Next tactic:
exact Or.inl fst_in_s
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> intro h
  · by_cases fst_in_s : p.fst ∈ s
    · exact Or.inr (h fst_in_s)
    · exact Or.inl fst_in_s
  · 

Proof state:
case h.mpr
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
h : p.1 ∉ s ∨ p.2 ∉ t
⊢ p.1 ∈ s → p.2 ∉ t

Next tactic:
intro fst_in_s
lemma compl_prod_eq_union {α β : Type*} (s : Set α) (t : Set β) :
    (s ×ˢ t)ᶜ = (sᶜ ×ˢ univ) ∪ (univ ×ˢ tᶜ) := by
  ext p
  simp only [mem_compl_iff, mem_prod, not_and, mem_union, mem_univ, and_true, true_and]
  constructor <;> intro h
  · by_cases fst_in_s : p.fst ∈ s
    · exact Or.inr (h fst_in_s)
    · exact Or.inl fst_in_s
  · intro fst_in_s
    

Proof state:
case h.mpr
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α✝
t✝ t₁ t₂ : Set β✝
a : α✝
b : β✝
α : Type u_5
β : Type u_6
s : Set α
t : Set β
p : α × β
h : p.1 ∉ s ∨ p.2 ∉ t
fst_in_s : p.1 ∈ s
⊢ p.2 ∉ t

Next tactic:
simpa only [fst_in_s, not_true, false_or] using h
@[simp]
theorem disjoint_prod : Disjoint (s₁ ×ˢ t₁) (s₂ ×ˢ t₂) ↔ Disjoint s₁ s₂ ∨ Disjoint t₁ t₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ Disjoint (s₁ ×ˢ t₁) (s₂ ×ˢ t₂) ↔ Disjoint s₁ s₂ ∨ Disjoint t₁ t₂

Next tactic:
simp_rw [disjoint_left, mem_prod, not_and_or, Prod.forall, and_imp, ← @forall_or_right α, ←
    @forall_or_left β, ← @forall_or_right (_ ∈ s₁), ← @forall_or_left (_ ∈ t₁)]
theorem insert_prod : insert a s ×ˢ t = Prod.mk a '' t ∪ s ×ˢ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ insert a s ×ˢ t = Prod.mk a '' t ∪ s ×ˢ t

Next tactic:
ext ⟨x, y⟩
theorem insert_prod : insert a s ×ˢ t = Prod.mk a '' t ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ insert a s ×ˢ t ↔ (x, y) ∈ Prod.mk a '' t ∪ s ×ˢ t

Next tactic:
simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
⊢ s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t

Next tactic:
ext ⟨x, y⟩
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ (x, y) ∈ s ×ˢ insert b t ↔ (x, y) ∈ (fun a => (a, b)) '' s ∪ s ×ˢ t

Next tactic:
simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
⊢ x ∈ s ∧ (y = b ∨ y ∈ t) ↔ (∃ a ∈ s, a = x ∧ b = y) ∨ x ∈ s ∧ y ∈ t

Next tactic:
refine ⟨fun h => ?_, fun h => ?_⟩
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  refine ⟨fun h => ?_, fun h => ?_⟩
  · 

Proof state:
case h.mk.refine_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
h : x ∈ s ∧ (y = b ∨ y ∈ t)
⊢ (∃ a ∈ s, a = x ∧ b = y) ∨ x ∈ s ∧ y ∈ t

Next tactic:
obtain ⟨hx, rfl|hy⟩ := h
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  refine ⟨fun h => ?_, fun h => ?_⟩
  · obtain ⟨hx, rfl|hy⟩ := h
    · 

Proof state:
case h.mk.refine_1.intro.inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a x : α
y : β
hx : x ∈ s
⊢ (∃ a ∈ s, a = x ∧ y = y) ∨ x ∈ s ∧ y ∈ t

Next tactic:
exact Or.inl ⟨x, hx, rfl, rfl⟩
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  refine ⟨fun h => ?_, fun h => ?_⟩
  · obtain ⟨hx, rfl|hy⟩ := h
    · exact Or.inl ⟨x, hx, rfl, rfl⟩
    · 

Proof state:
case h.mk.refine_1.intro.inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
hx : x ∈ s
hy : y ∈ t
⊢ (∃ a ∈ s, a = x ∧ b = y) ∨ x ∈ s ∧ y ∈ t

Next tactic:
exact Or.inr ⟨hx, hy⟩
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  refine ⟨fun h => ?_, fun h => ?_⟩
  · obtain ⟨hx, rfl|hy⟩ := h
    · exact Or.inl ⟨x, hx, rfl, rfl⟩
    · exact Or.inr ⟨hx, hy⟩
  · 

Proof state:
case h.mk.refine_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
h : (∃ a ∈ s, a = x ∧ b = y) ∨ x ∈ s ∧ y ∈ t
⊢ x ∈ s ∧ (y = b ∨ y ∈ t)

Next tactic:
obtain ⟨x, hx, rfl, rfl⟩|⟨hx, hy⟩ := h
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  refine ⟨fun h => ?_, fun h => ?_⟩
  · obtain ⟨hx, rfl|hy⟩ := h
    · exact Or.inl ⟨x, hx, rfl, rfl⟩
    · exact Or.inr ⟨hx, hy⟩
  · obtain ⟨x, hx, rfl, rfl⟩|⟨hx, hy⟩ := h
    · 

Proof state:
case h.mk.refine_2.inl.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
hx : x ∈ s
⊢ x ∈ s ∧ (b = b ∨ b ∈ t)

Next tactic:
exact ⟨hx, Or.inl rfl⟩
theorem prod_insert : s ×ˢ insert b t = (fun a => (a, b)) '' s ∪ s ×ˢ t := by
  ext ⟨x, y⟩
  -- Porting note: was `simp (config := { contextual := true }) [image, iff_def, or_imp, Imp.swap]`
  simp only [mem_prod, mem_insert_iff, image, mem_union, mem_setOf_eq, Prod.mk.injEq]
  refine ⟨fun h => ?_, fun h => ?_⟩
  · obtain ⟨hx, rfl|hy⟩ := h
    · exact Or.inl ⟨x, hx, rfl, rfl⟩
    · exact Or.inr ⟨hx, hy⟩
  · obtain ⟨x, hx, rfl, rfl⟩|⟨hx, hy⟩ := h
    · exact ⟨hx, Or.inl rfl⟩
    · 

Proof state:
case h.mk.refine_2.inr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
x : α
y : β
hx : x ∈ s
hy : y ∈ t
⊢ x ∈ s ∧ (y = b ∨ y ∈ t)

Next tactic:
exact ⟨hx, Or.inr hy⟩
@[simp]
theorem mk_preimage_prod_left (hb : b ∈ t) : (fun a => (a, b)) ⁻¹' s ×ˢ t = s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
hb : b ∈ t
⊢ (fun a => (a, b)) ⁻¹' s ×ˢ t = s

Next tactic:
ext a
@[simp]
theorem mk_preimage_prod_left (hb : b ∈ t) : (fun a => (a, b)) ⁻¹' s ×ˢ t = s := by
  ext a
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a✝ : α
b : β
hb : b ∈ t
a : α
⊢ a ∈ (fun a => (a, b)) ⁻¹' s ×ˢ t ↔ a ∈ s

Next tactic:
simp [hb]
@[simp]
theorem mk_preimage_prod_right (ha : a ∈ s) : Prod.mk a ⁻¹' s ×ˢ t = t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
ha : a ∈ s
⊢ Prod.mk a ⁻¹' s ×ˢ t = t

Next tactic:
ext b
@[simp]
theorem mk_preimage_prod_right (ha : a ∈ s) : Prod.mk a ⁻¹' s ×ˢ t = t := by
  ext b
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b✝ : β
ha : a ∈ s
b : β
⊢ b ∈ Prod.mk a ⁻¹' s ×ˢ t ↔ b ∈ t

Next tactic:
simp [ha]
@[simp]
theorem mk_preimage_prod_left_eq_empty (hb : b ∉ t) : (fun a => (a, b)) ⁻¹' s ×ˢ t = ∅ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
hb : b ∉ t
⊢ (fun a => (a, b)) ⁻¹' s ×ˢ t = ∅

Next tactic:
ext a