l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem mk_preimage_prod_left_eq_empty (hb : b ∉ t) : (fun a => (a, b)) ⁻¹' s ×ˢ t = ∅ := 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 ∈ ∅

Next tactic:
simp [hb]
@[simp]
theorem mk_preimage_prod_right_eq_empty (ha : a ∉ s) : Prod.mk a ⁻¹' 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 : β
ha : a ∉ s
⊢ Prod.mk a ⁻¹' s ×ˢ t = ∅

Next tactic:
ext b
@[simp]
theorem mk_preimage_prod_right_eq_empty (ha : a ∉ s) : Prod.mk a ⁻¹' s ×ˢ 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 ∈ ∅

Next tactic:
simp [ha]
theorem mk_preimage_prod_left_eq_if [DecidablePred (· ∈ t)] :
    (fun a => (a, b)) ⁻¹' s ×ˢ t = if b ∈ t then s else ∅ := 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✝ : DecidablePred fun x => x ∈ t
⊢ (fun a => (a, b)) ⁻¹' s ×ˢ t = if b ∈ t then s else ∅

Next tactic:
split_ifs with h
theorem mk_preimage_prod_left_eq_if [DecidablePred (· ∈ t)] :
    (fun a => (a, b)) ⁻¹' s ×ˢ t = if b ∈ t then s else ∅ := by split_ifs with h <;> 

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 : β
inst✝ : DecidablePred fun x => x ∈ t
h : b ∈ t
⊢ (fun a => (a, b)) ⁻¹' s ×ˢ t = s

Next tactic:
simp [h]
theorem mk_preimage_prod_left_eq_if [DecidablePred (· ∈ t)] :
    (fun a => (a, b)) ⁻¹' s ×ˢ t = if b ∈ t then s else ∅ := by split_ifs with h <;> 

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 : β
inst✝ : DecidablePred fun x => x ∈ t
h : b ∉ t
⊢ (fun a => (a, b)) ⁻¹' s ×ˢ t = ∅

Next tactic:
simp [h]
theorem mk_preimage_prod_right_eq_if [DecidablePred (· ∈ s)] :
    Prod.mk a ⁻¹' s ×ˢ t = if a ∈ s then t else ∅ := 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✝ : DecidablePred fun x => x ∈ s
⊢ Prod.mk a ⁻¹' s ×ˢ t = if a ∈ s then t else ∅

Next tactic:
split_ifs with h
theorem mk_preimage_prod_right_eq_if [DecidablePred (· ∈ s)] :
    Prod.mk a ⁻¹' s ×ˢ t = if a ∈ s then t else ∅ := by split_ifs with h <;> 

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 : β
inst✝ : DecidablePred fun x => x ∈ s
h : a ∈ s
⊢ Prod.mk a ⁻¹' s ×ˢ t = t

Next tactic:
simp [h]
theorem mk_preimage_prod_right_eq_if [DecidablePred (· ∈ s)] :
    Prod.mk a ⁻¹' s ×ˢ t = if a ∈ s then t else ∅ := by split_ifs with h <;> 

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 : β
inst✝ : DecidablePred fun x => x ∈ s
h : a ∉ s
⊢ Prod.mk a ⁻¹' s ×ˢ t = ∅

Next tactic:
simp [h]
theorem mk_preimage_prod_left_fn_eq_if [DecidablePred (· ∈ t)] (f : γ → α) :
    (fun a => (f a, b)) ⁻¹' s ×ˢ t = if b ∈ t then f ⁻¹' s else ∅ := 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✝ : DecidablePred fun x => x ∈ t
f : γ → α
⊢ (fun a => (f a, b)) ⁻¹' s ×ˢ t = if b ∈ t then f ⁻¹' s else ∅

Next tactic:
rw [← mk_preimage_prod_left_eq_if, prod_preimage_left, preimage_preimage]
theorem mk_preimage_prod_right_fn_eq_if [DecidablePred (· ∈ s)] (g : δ → β) :
    (fun b => (a, g b)) ⁻¹' s ×ˢ t = if a ∈ s then g ⁻¹' t else ∅ := 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✝ : DecidablePred fun x => x ∈ s
g : δ → β
⊢ (fun b => (a, g b)) ⁻¹' s ×ˢ t = if a ∈ s then g ⁻¹' t else ∅

Next tactic:
rw [← mk_preimage_prod_right_eq_if, prod_preimage_right, preimage_preimage]
@[simp]
theorem preimage_swap_prod (s : Set α) (t : Set β) : Prod.swap ⁻¹' s ×ˢ t = 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 : β
s : Set α
t : Set β
⊢ Prod.swap ⁻¹' s ×ˢ t = t ×ˢ s

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem preimage_swap_prod (s : Set α) (t : Set β) : Prod.swap ⁻¹' s ×ˢ t = t ×ˢ 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 : β
s : Set α
t : Set β
x : β
y : α
⊢ (x, y) ∈ Prod.swap ⁻¹' s ×ˢ t ↔ (x, y) ∈ t ×ˢ s

Next tactic:
simp [and_comm]
@[simp]
theorem image_swap_prod (s : Set α) (t : Set β) : Prod.swap '' s ×ˢ t = 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 : β
s : Set α
t : Set β
⊢ Prod.swap '' s ×ˢ t = t ×ˢ s

Next tactic:
rw [image_swap_eq_preimage_swap, preimage_swap_prod]
theorem prod_image_image_eq {m₁ : α → γ} {m₂ : β → δ} :
    (m₁ '' s) ×ˢ (m₂ '' t) = (fun p : α × β => (m₁ p.1, m₂ p.2)) '' s ×ˢ t :=
  ext <| 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 : β
m₁ : α → γ
m₂ : β → δ
⊢ ∀ (x : γ × δ), x ∈ (m₁ '' s) ×ˢ (m₂ '' t) ↔ x ∈ (fun p => (m₁ p.1, m₂ p.2)) '' s ×ˢ t

Next tactic:
simp [-exists_and_right, exists_and_right.symm, and_left_comm, and_assoc, and_comm]
theorem prod_range_range_eq {m₁ : α → γ} {m₂ : β → δ} :
    range m₁ ×ˢ range m₂ = range fun p : α × β => (m₁ p.1, m₂ p.2) :=
  ext <| 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 : β
m₁ : α → γ
m₂ : β → δ
⊢ ∀ (x : γ × δ), x ∈ range m₁ ×ˢ range m₂ ↔ x ∈ range fun p => (m₁ p.1, m₂ p.2)

Next tactic:
simp [range]
theorem prod_range_univ_eq {m₁ : α → γ} :
    range m₁ ×ˢ (univ : Set β) = range fun p : α × β => (m₁ p.1, p.2) :=
  ext <| 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 : β
m₁ : α → γ
⊢ ∀ (x : γ × β), x ∈ range m₁ ×ˢ univ ↔ x ∈ range fun p => (m₁ p.1, p.2)

Next tactic:
simp [range]
theorem prod_univ_range_eq {m₂ : β → δ} :
    (univ : Set α) ×ˢ range m₂ = range fun p : α × β => (p.1, m₂ p.2) :=
  ext <| 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 : β
m₂ : β → δ
⊢ ∀ (x : α × δ), x ∈ univ ×ˢ range m₂ ↔ x ∈ range fun p => (p.1, m₂ p.2)

Next tactic:
simp [range]
theorem range_pair_subset (f : α → β) (g : α → γ) :
    (range fun x => (f x, g x)) ⊆ range f ×ˢ range g := 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 : β
f : α → β
g : α → γ
⊢ (range fun x => (f x, g x)) ⊆ range f ×ˢ range g

Next tactic:
have : (fun x => (f x, g x)) = Prod.map f g ∘ fun x => (x, x) := funext fun x => rfl
theorem range_pair_subset (f : α → β) (g : α → γ) :
    (range fun x => (f x, g x)) ⊆ range f ×ˢ range g := by
  have : (fun x => (f x, g x)) = Prod.map f g ∘ fun x => (x, x) := funext fun x => rfl
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
f : α → β
g : α → γ
this : (fun x => (f x, g x)) = Prod.map f g ∘ fun x => (x, x)
⊢ (range fun x => (f x, g x)) ⊆ range f ×ˢ range g

Next tactic:
rw [this, ← range_prod_map]
theorem range_pair_subset (f : α → β) (g : α → γ) :
    (range fun x => (f x, g x)) ⊆ range f ×ˢ range g := by
  have : (fun x => (f x, g x)) = Prod.map f g ∘ fun x => (x, x) := funext fun x => rfl
  rw [this, ← range_prod_map]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
f : α → β
g : α → γ
this : (fun x => (f x, g x)) = Prod.map f g ∘ fun x => (x, x)
⊢ range (Prod.map f g ∘ fun x => (x, x)) ⊆ range (Prod.map f g)

Next tactic:
apply range_comp_subset_range
@[simp]
theorem prod_eq_empty_iff : 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 = ∅ ↔ s = ∅ ∨ t = ∅

Next tactic:
simp only [not_nonempty_iff_eq_empty.symm, prod_nonempty_iff, not_and_or]
theorem prod_sub_preimage_iff {W : Set γ} {f : α × β → γ} :
    s ×ˢ t ⊆ f ⁻¹' W ↔ ∀ a b, a ∈ s → b ∈ t → f (a, b) ∈ W := 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 : β
W : Set γ
f : α × β → γ
⊢ s ×ˢ t ⊆ f ⁻¹' W ↔ ∀ (a : α) (b : β), a ∈ s → b ∈ t → f (a, b) ∈ W

Next tactic:
simp [subset_def]
theorem image_prod_mk_subset_prod {f : α → β} {g : α → γ} {s : Set α} :
    (fun x => (f x, g x)) '' s ⊆ (f '' s) ×ˢ (g '' 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 : β
f : α → β
g : α → γ
s : Set α
⊢ (fun x => (f x, g x)) '' s ⊆ (f '' s) ×ˢ (g '' s)

Next tactic:
rintro _ ⟨x, hx, rfl⟩
theorem image_prod_mk_subset_prod {f : α → β} {g : α → γ} {s : Set α} :
    (fun x => (f x, g x)) '' s ⊆ (f '' s) ×ˢ (g '' s) := by
  rintro _ ⟨x, hx, rfl⟩
  

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s✝ s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
f : α → β
g : α → γ
s : Set α
x : α
hx : x ∈ s
⊢ (fun x => (f x, g x)) x ∈ (f '' s) ×ˢ (g '' s)

Next tactic:
exact mk_mem_prod (mem_image_of_mem f hx) (mem_image_of_mem g hx)
theorem image_prod_mk_subset_prod_left (hb : 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 : β
hb : b ∈ t
⊢ (fun a => (a, b)) '' s ⊆ s ×ˢ t

Next tactic:
rintro _ ⟨a, ha, rfl⟩
theorem image_prod_mk_subset_prod_left (hb : b ∈ t) : (fun a => (a, b)) '' s ⊆ s ×ˢ t := by
  rintro _ ⟨a, ha, rfl⟩
  

Proof state:
case intro.intro
α : 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 : α
ha : a ∈ s
⊢ (fun a => (a, b)) a ∈ s ×ˢ t

Next tactic:
exact ⟨ha, hb⟩
theorem image_prod_mk_subset_prod_right (ha : a ∈ s) : 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 : β
ha : a ∈ s
⊢ Prod.mk a '' t ⊆ s ×ˢ t

Next tactic:
rintro _ ⟨b, hb, rfl⟩
theorem image_prod_mk_subset_prod_right (ha : a ∈ s) : Prod.mk a '' t ⊆ s ×ˢ t := by
  rintro _ ⟨b, hb, rfl⟩
  

Proof state:
case intro.intro
α : 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 : β
hb : b ∈ t
⊢ (a, b) ∈ s ×ˢ t

Next tactic:
exact ⟨ha, hb⟩
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (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 ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
ext x
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  

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 ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
by_cases h₁ : x.1 ∈ s₁
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  by_cases h₁ : x.1 ∈ 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 : β
x : α × β
h₁ : x.1 ∈ s₁
⊢ x ∈ s ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
by_cases h₂ : x.2 ∈ t₁
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  by_cases h₁ : x.1 ∈ 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 : β
x : α × β
h₁ : x.1 ∉ s₁
⊢ x ∈ s ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
by_cases h₂ : x.2 ∈ t₁
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  by_cases h₁ : x.1 ∈ s₁ <;> by_cases h₂ : x.2 ∈ t₁ <;> 

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 : β
x : α × β
h₁ : x.1 ∈ s₁
h₂ : x.2 ∈ t₁
⊢ x ∈ s ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
simp [*]
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  by_cases h₁ : x.1 ∈ s₁ <;> by_cases h₂ : x.2 ∈ t₁ <;> 

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 : β
x : α × β
h₁ : x.1 ∈ s₁
h₂ : x.2 ∉ t₁
⊢ x ∈ s ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
simp [*]
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  by_cases h₁ : x.1 ∈ s₁ <;> by_cases h₂ : x.2 ∈ t₁ <;> 

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 : β
x : α × β
h₁ : x.1 ∉ s₁
h₂ : x.2 ∈ t₁
⊢ x ∈ s ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
simp [*]
theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by
  ext x
  by_cases h₁ : x.1 ∈ s₁ <;> by_cases h₂ : x.2 ∈ t₁ <;> 

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 : β
x : α × β
h₁ : x.1 ∉ s₁
h₂ : x.2 ∉ t₁
⊢ x ∈ s ×ˢ t \ s₁ ×ˢ t₁ ↔ x ∈ s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t

Next tactic:
simp [*]
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ 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 ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅

Next tactic:
rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : s ×ˢ t = ∅
⊢ s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅

Next tactic:
simp [h, prod_eq_empty_iff.1 h]
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
⊢ s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅

Next tactic:
have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := 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 : β
h : Set.Nonempty (s ×ˢ t)
⊢ Set.Nonempty s ∧ Set.Nonempty t

Next tactic:
rwa [prod_nonempty_iff] at h
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
⊢ s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅

Next tactic:
refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · 

Proof state:
case inr.refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
H : s ×ˢ t ⊆ s₁ ×ˢ t₁
⊢ s ⊆ s₁

Next tactic:
have := image_subset (Prod.fst : α × β → α) H
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · have := image_subset (Prod.fst : α × β → α) H
    

Proof state:
case inr.refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
H : s ×ˢ t ⊆ s₁ ×ˢ t₁
this : Prod.fst '' s ×ˢ t ⊆ Prod.fst '' s₁ ×ˢ t₁
⊢ s ⊆ s₁

Next tactic:
rwa [fst_image_prod _ st.2, fst_image_prod _ (h.mono H).snd] at this
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · have := image_subset (Prod.fst : α × β → α) H
    rwa [fst_image_prod _ st.2, fst_image_prod _ (h.mono H).snd] at this
  · 

Proof state:
case inr.refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
H : s ×ˢ t ⊆ s₁ ×ˢ t₁
⊢ t ⊆ t₁

Next tactic:
have := image_subset (Prod.snd : α × β → β) H
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · have := image_subset (Prod.fst : α × β → α) H
    rwa [fst_image_prod _ st.2, fst_image_prod _ (h.mono H).snd] at this
  · have := image_subset (Prod.snd : α × β → β) H
    

Proof state:
case inr.refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
H : s ×ˢ t ⊆ s₁ ×ˢ t₁
this : Prod.snd '' s ×ˢ t ⊆ Prod.snd '' s₁ ×ˢ t₁
⊢ t ⊆ t₁

Next tactic:
rwa [snd_image_prod st.1, snd_image_prod (h.mono H).fst] at this
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · have := image_subset (Prod.fst : α × β → α) H
    rwa [fst_image_prod _ st.2, fst_image_prod _ (h.mono H).snd] at this
  · have := image_subset (Prod.snd : α × β → β) H
    rwa [snd_image_prod st.1, snd_image_prod (h.mono H).fst] at this
  · 

Proof state:
case inr.refine'_3
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
⊢ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ → s ×ˢ t ⊆ s₁ ×ˢ t₁

Next tactic:
intro H
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · have := image_subset (Prod.fst : α × β → α) H
    rwa [fst_image_prod _ st.2, fst_image_prod _ (h.mono H).snd] at this
  · have := image_subset (Prod.snd : α × β → β) H
    rwa [snd_image_prod st.1, snd_image_prod (h.mono H).fst] at this
  · intro H
    

Proof state:
case inr.refine'_3
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
H : s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅
⊢ s ×ˢ t ⊆ s₁ ×ˢ t₁

Next tactic:
simp only [st.1.ne_empty, st.2.ne_empty, or_false_iff] at H
/-- A product set is included in a product set if and only factors are included, or a factor of the
first set is empty. -/
theorem prod_subset_prod_iff : s ×ˢ t ⊆ s₁ ×ˢ t₁ ↔ s ⊆ s₁ ∧ t ⊆ t₁ ∨ s = ∅ ∨ t = ∅ := by
  rcases (s ×ˢ t).eq_empty_or_nonempty with h | h
  · simp [h, prod_eq_empty_iff.1 h]
  have st : s.Nonempty ∧ t.Nonempty := by rwa [prod_nonempty_iff] at h
  refine' ⟨fun H => Or.inl ⟨_, _⟩, _⟩
  · have := image_subset (Prod.fst : α × β → α) H
    rwa [fst_image_prod _ st.2, fst_image_prod _ (h.mono H).snd] at this
  · have := image_subset (Prod.snd : α × β → β) H
    rwa [snd_image_prod st.1, snd_image_prod (h.mono H).fst] at this
  · intro H
    simp only [st.1.ne_empty, st.2.ne_empty, or_false_iff] at H
    

Proof state:
case inr.refine'_3
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
st : Set.Nonempty s ∧ Set.Nonempty t
H : s ⊆ s₁ ∧ t ⊆ t₁
⊢ s ×ˢ t ⊆ s₁ ×ˢ t₁

Next tactic:
exact prod_mono H.1 H.2
theorem prod_eq_prod_iff_of_nonempty (h : (s ×ˢ t).Nonempty) :
    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 : β
h : Set.Nonempty (s ×ˢ t)
⊢ s ×ˢ t = s₁ ×ˢ t₁ ↔ s = s₁ ∧ t = t₁

Next tactic:
constructor
theorem prod_eq_prod_iff_of_nonempty (h : (s ×ˢ t).Nonempty) :
    s ×ˢ t = s₁ ×ˢ t₁ ↔ s = s₁ ∧ t = t₁ := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
⊢ s ×ˢ t = s₁ ×ˢ t₁ → s = s₁ ∧ t = t₁

Next tactic:
intro heq
theorem prod_eq_prod_iff_of_nonempty (h : (s ×ˢ t).Nonempty) :
    s ×ˢ t = s₁ ×ˢ t₁ ↔ s = s₁ ∧ t = t₁ := by
  constructor
  · intro heq
    

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
heq : s ×ˢ t = s₁ ×ˢ t₁
⊢ s = s₁ ∧ t = t₁

Next tactic:
have h₁ : (s₁ ×ˢ t₁ : Set _).Nonempty := by rwa [← heq]
theorem prod_eq_prod_iff_of_nonempty (h : (s ×ˢ t).Nonempty) :
    s ×ˢ t = s₁ ×ˢ t₁ ↔ s = s₁ ∧ t = t₁ := by
  constructor
  · intro heq
    have h₁ : (s₁ ×ˢ t₁ : Set _).Nonempty := 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 : β
h : Set.Nonempty (s ×ˢ t)
heq : s ×ˢ t = s₁ ×ˢ t₁
⊢ Set.Nonempty (s₁ ×ˢ t₁)

Next tactic:
rwa [← heq]
theorem prod_eq_prod_iff_of_nonempty (h : (s ×ˢ t).Nonempty) :
    s ×ˢ t = s₁ ×ˢ t₁ ↔ s = s₁ ∧ t = t₁ := by
  constructor
  · intro heq
    have h₁ : (s₁ ×ˢ t₁ : Set _).Nonempty := by rwa [← heq]
    

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
s s₁ s₂ : Set α
t t₁ t₂ : Set β
a : α
b : β
h : Set.Nonempty (s ×ˢ t)
heq : s ×ˢ t = s₁ ×ˢ t₁
h₁ : Set.Nonempty (s₁ ×ˢ t₁)
⊢ s = s₁ ∧ t = t₁

Next tactic:
rw [prod_nonempty_iff] at h h₁