l3lab/ntp-mathlib huggingface dataset:
@[simp]
protected theorem Finite.insert (a : α) {s : Set α} (hs : s.Finite) : (insert a s).Finite := by
  cases hs
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
a : α
s : Set α
a✝ : Fintype ↑s
⊢ Set.Finite (insert a s)

Next tactic:
apply toFinite
theorem Finite.image {s : Set α} (f : α → β) (hs : s.Finite) : (f '' s).Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → β
hs : Set.Finite s
⊢ Set.Finite (f '' s)

Next tactic:
cases hs
theorem Finite.image {s : Set α} (f : α → β) (hs : s.Finite) : (f '' s).Finite := by
  cases hs
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → β
a✝ : Fintype ↑s
⊢ Set.Finite (f '' s)

Next tactic:
apply toFinite
theorem Finite.dependent_image {s : Set α} (hs : s.Finite) (F : ∀ i ∈ s, β) :
    { y : β | ∃ (x : _) (hx : x ∈ s), y = F x hx }.Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
hs : Set.Finite s
F : (i : α) → i ∈ s → β
⊢ Set.Finite {y | ∃ x, ∃ (hx : x ∈ s), y = F x hx}

Next tactic:
cases hs
theorem Finite.dependent_image {s : Set α} (hs : s.Finite) (F : ∀ i ∈ s, β) :
    { y : β | ∃ (x : _) (hx : x ∈ s), y = F x hx }.Finite := by
  cases hs
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
F : (i : α) → i ∈ s → β
a✝ : Fintype ↑s
⊢ Set.Finite {y | ∃ x, ∃ (hx : x ∈ s), y = F x hx}

Next tactic:
simpa [range, eq_comm] using finite_range fun x : s => F x x.2
theorem Finite.of_finite_image {s : Set α} {f : α → β} (h : (f '' s).Finite) (hi : Set.InjOn f s) :
    s.Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → β
h : Set.Finite (f '' s)
hi : InjOn f s
⊢ Set.Finite s

Next tactic:
cases h
theorem Finite.of_finite_image {s : Set α} {f : α → β} (h : (f '' s).Finite) (hi : Set.InjOn f s) :
    s.Finite := by
  cases h
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → β
hi : InjOn f s
a✝ : Fintype ↑(f '' s)
⊢ Set.Finite s

Next tactic:
exact
    ⟨Fintype.ofInjective (fun a => (⟨f a.1, mem_image_of_mem f a.2⟩ : f '' s)) fun a b eq =>
        Subtype.eq <| hi a.2 b.2 <| Subtype.ext_iff_val.1 eq⟩
theorem finite_of_finite_preimage (h : (f ⁻¹' s).Finite) (hs : s ⊆ range f) : s.Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : α → β
s : Set β
h : Set.Finite (f ⁻¹' s)
hs : s ⊆ range f
⊢ Set.Finite s

Next tactic:
rw [← image_preimage_eq_of_subset hs]
theorem finite_of_finite_preimage (h : (f ⁻¹' s).Finite) (hs : s ⊆ range f) : s.Finite := by
  rw [← image_preimage_eq_of_subset hs]
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : α → β
s : Set β
h : Set.Finite (f ⁻¹' s)
hs : s ⊆ range f
⊢ Set.Finite (f '' (f ⁻¹' s))

Next tactic:
exact Finite.image f h
theorem Finite.surjOn_iff_bijOn_of_mapsTo : SurjOn f s s ↔ BijOn f s s := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → α
hs : Set.Finite s
hm : MapsTo f s s
⊢ SurjOn f s s ↔ BijOn f s s

Next tactic:
refine ⟨fun h ↦ ⟨hm, ?_, h⟩, BijOn.surjOn⟩
theorem Finite.surjOn_iff_bijOn_of_mapsTo : SurjOn f s s ↔ BijOn f s s := by
  refine ⟨fun h ↦ ⟨hm, ?_, h⟩, BijOn.surjOn⟩
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → α
hs : Set.Finite s
hm : MapsTo f s s
h : SurjOn f s s
⊢ InjOn f s

Next tactic:
have : Finite s := finite_coe_iff.mpr hs
theorem Finite.surjOn_iff_bijOn_of_mapsTo : SurjOn f s s ↔ BijOn f s s := by
  refine ⟨fun h ↦ ⟨hm, ?_, h⟩, BijOn.surjOn⟩
  have : Finite s := finite_coe_iff.mpr hs
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → α
hs : Set.Finite s
hm : MapsTo f s s
h : SurjOn f s s
this : Finite ↑s
⊢ InjOn f s

Next tactic:
exact hm.restrict_inj.mp (Finite.injective_iff_surjective.mpr <| hm.restrict_surjective_iff.mpr h)
theorem Finite.injOn_iff_bijOn_of_mapsTo : InjOn f s ↔ BijOn f s s := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → α
hs : Set.Finite s
hm : MapsTo f s s
⊢ InjOn f s ↔ BijOn f s s

Next tactic:
refine ⟨fun h ↦ ⟨hm, h, ?_⟩, BijOn.injOn⟩
theorem Finite.injOn_iff_bijOn_of_mapsTo : InjOn f s ↔ BijOn f s s := by
  refine ⟨fun h ↦ ⟨hm, h, ?_⟩, BijOn.injOn⟩
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → α
hs : Set.Finite s
hm : MapsTo f s s
h : InjOn f s
⊢ SurjOn f s s

Next tactic:
have : Finite s := finite_coe_iff.mpr hs
theorem Finite.injOn_iff_bijOn_of_mapsTo : InjOn f s ↔ BijOn f s s := by
  refine ⟨fun h ↦ ⟨hm, h, ?_⟩, BijOn.injOn⟩
  have : Finite s := finite_coe_iff.mpr hs
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
f : α → α
hs : Set.Finite s
hm : MapsTo f s s
h : InjOn f s
this : Finite ↑s
⊢ SurjOn f s s

Next tactic:
exact hm.restrict_surjective_iff.mp (Finite.injective_iff_surjective.mp <| hm.restrict_inj.mpr h)
protected theorem Finite.prod (hs : s.Finite) (ht : t.Finite) : (s ×ˢ t : Set (α × β)).Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
hs : Set.Finite s
ht : Set.Finite t
⊢ Set.Finite (s ×ˢ t)

Next tactic:
cases hs
protected theorem Finite.prod (hs : s.Finite) (ht : t.Finite) : (s ×ˢ t : Set (α × β)).Finite := by
  cases hs
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
ht : Set.Finite t
a✝ : Fintype ↑s
⊢ Set.Finite (s ×ˢ t)

Next tactic:
cases ht
protected theorem Finite.prod (hs : s.Finite) (ht : t.Finite) : (s ×ˢ t : Set (α × β)).Finite := by
  cases hs
  cases ht
  

Proof state:
case intro.intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
a✝¹ : Fintype ↑s
a✝ : Fintype ↑t
⊢ Set.Finite (s ×ˢ t)

Next tactic:
apply toFinite
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
⊢ Set.Infinite (s ×ˢ t) ↔ Set.Infinite s ∧ Set.Nonempty t ∨ Set.Infinite t ∧ Set.Nonempty s

Next tactic:
refine' ⟨fun h => _, _⟩
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  refine' ⟨fun h => _, _⟩
  · 

Proof state:
case refine'_1
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
h : Set.Infinite (s ×ˢ t)
⊢ Set.Infinite s ∧ Set.Nonempty t ∨ Set.Infinite t ∧ Set.Nonempty s

Next tactic:
simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp]
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  refine' ⟨fun h => _, _⟩
  · simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp]
    

Proof state:
case refine'_1
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
h : Set.Infinite (s ×ˢ t)
⊢ ¬(Set.Nonempty t → Set.Finite s) ∨ ¬(Set.Nonempty s → Set.Finite t)

Next tactic:
by_contra!
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  refine' ⟨fun h => _, _⟩
  · simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp]
    by_contra!
    

Proof state:
case refine'_1
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
h : Set.Infinite (s ×ˢ t)
this : (Set.Nonempty t → Set.Finite s) ∧ (Set.Nonempty s → Set.Finite t)
⊢ False

Next tactic:
exact h ((this.1 h.nonempty.snd).prod $ this.2 h.nonempty.fst)
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  refine' ⟨fun h => _, _⟩
  · simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp]
    by_contra!
    exact h ((this.1 h.nonempty.snd).prod $ this.2 h.nonempty.fst)
  · 

Proof state:
case refine'_2
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
⊢ Set.Infinite s ∧ Set.Nonempty t ∨ Set.Infinite t ∧ Set.Nonempty s → Set.Infinite (s ×ˢ t)

Next tactic:
rintro (h | h)
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  refine' ⟨fun h => _, _⟩
  · simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp]
    by_contra!
    exact h ((this.1 h.nonempty.snd).prod $ this.2 h.nonempty.fst)
  · rintro (h | h)
    · 

Proof state:
case refine'_2.inl
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
h : Set.Infinite s ∧ Set.Nonempty t
⊢ Set.Infinite (s ×ˢ t)

Next tactic:
exact h.1.prod_left h.2
protected theorem infinite_prod :
    (s ×ˢ t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := by
  refine' ⟨fun h => _, _⟩
  · simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp]
    by_contra!
    exact h ((this.1 h.nonempty.snd).prod $ this.2 h.nonempty.fst)
  · rintro (h | h)
    · exact h.1.prod_left h.2
    · 

Proof state:
case refine'_2.inr
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
h : Set.Infinite t ∧ Set.Nonempty s
⊢ Set.Infinite (s ×ˢ t)

Next tactic:
exact h.1.prod_right h.2
theorem finite_prod : (s ×ˢ t).Finite ↔ (s.Finite ∨ t = ∅) ∧ (t.Finite ∨ s = ∅) := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
⊢ Set.Finite (s ×ˢ t) ↔ (Set.Finite s ∨ t = ∅) ∧ (Set.Finite t ∨ s = ∅)

Next tactic:
simp only [← not_infinite, Set.infinite_prod, not_or, not_and_or, not_nonempty_iff_eq_empty]
protected theorem Finite.offDiag {s : Set α} (hs : s.Finite) : s.offDiag.Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s✝ : Set α
t : Set β
s : Set α
hs : Set.Finite s
⊢ Set.Finite (offDiag s)

Next tactic:
classical
    cases hs
    apply Set.toFinite
protected theorem Finite.offDiag {s : Set α} (hs : s.Finite) : s.offDiag.Finite := by
  classical
    

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s✝ : Set α
t : Set β
s : Set α
hs : Set.Finite s
⊢ Set.Finite (offDiag s)

Next tactic:
cases hs
protected theorem Finite.offDiag {s : Set α} (hs : s.Finite) : s.offDiag.Finite := by
  classical
    cases hs
    

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s✝ : Set α
t : Set β
s : Set α
a✝ : Fintype ↑s
⊢ Set.Finite (offDiag s)

Next tactic:
apply Set.toFinite
protected theorem Finite.image2 (f : α → β → γ) (hs : s.Finite) (ht : t.Finite) :
    (image2 f s t).Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
f : α → β → γ
hs : Set.Finite s
ht : Set.Finite t
⊢ Set.Finite (image2 f s t)

Next tactic:
cases hs
protected theorem Finite.image2 (f : α → β → γ) (hs : s.Finite) (ht : t.Finite) :
    (image2 f s t).Finite := by
  cases hs
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
f : α → β → γ
ht : Set.Finite t
a✝ : Fintype ↑s
⊢ Set.Finite (image2 f s t)

Next tactic:
cases ht
protected theorem Finite.image2 (f : α → β → γ) (hs : s.Finite) (ht : t.Finite) :
    (image2 f s t).Finite := by
  cases hs
  cases ht
  

Proof state:
case intro.intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
f : α → β → γ
a✝¹ : Fintype ↑s
a✝ : Fintype ↑t
⊢ Set.Finite (image2 f s t)

Next tactic:
apply toFinite
theorem Finite.seq {f : Set (α → β)} {s : Set α} (hf : f.Finite) (hs : s.Finite) :
    (f.seq s).Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : Set (α → β)
s : Set α
hf : Set.Finite f
hs : Set.Finite s
⊢ Set.Finite (Set.seq f s)

Next tactic:
classical
    cases hf
    cases hs
    apply toFinite
theorem Finite.seq {f : Set (α → β)} {s : Set α} (hf : f.Finite) (hs : s.Finite) :
    (f.seq s).Finite := by
  classical
    

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : Set (α → β)
s : Set α
hf : Set.Finite f
hs : Set.Finite s
⊢ Set.Finite (Set.seq f s)

Next tactic:
cases hf
theorem Finite.seq {f : Set (α → β)} {s : Set α} (hf : f.Finite) (hs : s.Finite) :
    (f.seq s).Finite := by
  classical
    cases hf
    

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : Set (α → β)
s : Set α
hs : Set.Finite s
a✝ : Fintype ↑f
⊢ Set.Finite (Set.seq f s)

Next tactic:
cases hs
theorem Finite.seq {f : Set (α → β)} {s : Set α} (hf : f.Finite) (hs : s.Finite) :
    (f.seq s).Finite := by
  classical
    cases hf
    cases hs
    

Proof state:
case intro.intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : Set (α → β)
s : Set α
a✝¹ : Fintype ↑f
a✝ : Fintype ↑s
⊢ Set.Finite (Set.seq f s)

Next tactic:
apply toFinite
/-- There are finitely many subsets of a given finite set -/
theorem Finite.finite_subsets {α : Type u} {a : Set α} (h : a.Finite) : { b | b ⊆ a }.Finite :=
  ⟨Fintype.ofFinset ((Finset.powerset h.toFinset).map Finset.coeEmb.1) fun s => by
      

Proof state:
α✝ : Type u
β : Type v
ι : Sort w
γ : Type x
α : Type u
a : Set α
h : Set.Finite a
s : Set α
⊢ s ∈ Finset.map Finset.coeEmb.toEmbedding (Finset.powerset (Finite.toFinset h)) ↔ s ∈ {b | b ⊆ a}

Next tactic:
simpa [← @exists_finite_iff_finset α fun t => t ⊆ a ∧ t = s, Finite.subset_toFinset, ←
        and_assoc, Finset.coeEmb] using h.subset
/-- Finite product of finite sets is finite -/
theorem Finite.pi {δ : Type*} [Finite δ] {κ : δ → Type*} {t : ∀ d, Set (κ d)}
    (ht : ∀ d, (t d).Finite) : (pi univ t).Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
δ : Type u_1
inst✝ : Finite δ
κ : δ → Type u_2
t : (d : δ) → Set (κ d)
ht : ∀ (d : δ), Set.Finite (t d)
⊢ Set.Finite (Set.pi univ t)

Next tactic:
cases _root_.nonempty_fintype δ
/-- Finite product of finite sets is finite -/
theorem Finite.pi {δ : Type*} [Finite δ] {κ : δ → Type*} {t : ∀ d, Set (κ d)}
    (ht : ∀ d, (t d).Finite) : (pi univ t).Finite := by
  cases _root_.nonempty_fintype δ
  

Proof state:
case intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
δ : Type u_1
inst✝ : Finite δ
κ : δ → Type u_2
t : (d : δ) → Set (κ d)
ht : ∀ (d : δ), Set.Finite (t d)
val✝ : Fintype δ
⊢ Set.Finite (Set.pi univ t)

Next tactic:
lift t to ∀ d, Finset (κ d) using ht
/-- Finite product of finite sets is finite -/
theorem Finite.pi {δ : Type*} [Finite δ] {κ : δ → Type*} {t : ∀ d, Set (κ d)}
    (ht : ∀ d, (t d).Finite) : (pi univ t).Finite := by
  cases _root_.nonempty_fintype δ
  lift t to ∀ d, Finset (κ d) using ht
  

Proof state:
case intro.intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
δ : Type u_1
inst✝ : Finite δ
κ : δ → Type u_2
val✝ : Fintype δ
t : (i : δ) → Finset (κ i)
⊢ Set.Finite (Set.pi univ fun i => ↑(t i))

Next tactic:
classical
    rw [← Fintype.coe_piFinset]
    apply Finset.finite_toSet
/-- Finite product of finite sets is finite -/
theorem Finite.pi {δ : Type*} [Finite δ] {κ : δ → Type*} {t : ∀ d, Set (κ d)}
    (ht : ∀ d, (t d).Finite) : (pi univ t).Finite := by
  cases _root_.nonempty_fintype δ
  lift t to ∀ d, Finset (κ d) using ht
  classical
    

Proof state:
case intro.intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
δ : Type u_1
inst✝ : Finite δ
κ : δ → Type u_2
val✝ : Fintype δ
t : (i : δ) → Finset (κ i)
⊢ Set.Finite (Set.pi univ fun i => ↑(t i))

Next tactic:
rw [← Fintype.coe_piFinset]
/-- Finite product of finite sets is finite -/
theorem Finite.pi {δ : Type*} [Finite δ] {κ : δ → Type*} {t : ∀ d, Set (κ d)}
    (ht : ∀ d, (t d).Finite) : (pi univ t).Finite := by
  cases _root_.nonempty_fintype δ
  lift t to ∀ d, Finset (κ d) using ht
  classical
    rw [← Fintype.coe_piFinset]
    

Proof state:
case intro.intro
α : Type u
β : Type v
ι : Sort w
γ : Type x
δ : Type u_1
inst✝ : Finite δ
κ : δ → Type u_2
val✝ : Fintype δ
t : (i : δ) → Finset (κ i)
⊢ Set.Finite ↑(Fintype.piFinset fun i => t i)

Next tactic:
apply Finset.finite_toSet
/-- A finite union of finsets is finite. -/
theorem union_finset_finite_of_range_finite (f : α → Finset β) (h : (range f).Finite) :
    (⋃ a, (f a : Set β)).Finite := by
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : α → Finset β
h : Set.Finite (range f)
⊢ Set.Finite (⋃ a, ↑(f a))

Next tactic:
rw [← biUnion_range]
/-- A finite union of finsets is finite. -/
theorem union_finset_finite_of_range_finite (f : α → Finset β) (h : (range f).Finite) :
    (⋃ a, (f a : Set β)).Finite := by
  rw [← biUnion_range]
  

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
f : α → Finset β
h : Set.Finite (range f)
⊢ Set.Finite (⋃ x ∈ range fun a => f a, ↑x)

Next tactic:
exact h.biUnion fun y _ => y.finite_toSet
@[simp]
theorem Finite.toFinset_insert [DecidableEq α] {s : Set α} {a : α} (hs : (insert a s).Finite) :
    hs.toFinset = insert a (hs.subset <| subset_insert _ _).toFinset :=
  Finset.ext <| by 

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
inst✝ : DecidableEq α
s : Set α
a : α
hs : Set.Finite (insert a s)
⊢ ∀ (a_1 : α), a_1 ∈ Finite.toFinset hs ↔ a_1 ∈ insert a (Finite.toFinset (_ : Set.Finite s))

Next tactic:
simp
theorem Finite.toFinset_prod {s : Set α} {t : Set β} (hs : s.Finite) (ht : t.Finite) :
    hs.toFinset ×ˢ ht.toFinset = (hs.prod ht).toFinset :=
  Finset.ext <| by 

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
t : Set β
hs : Set.Finite s
ht : Set.Finite t
⊢ ∀ (a : α × β), a ∈ Finite.toFinset hs ×ˢ Finite.toFinset ht ↔ a ∈ Finite.toFinset (_ : Set.Finite (s ×ˢ t))

Next tactic:
simp
theorem Finite.toFinset_offDiag {s : Set α} [DecidableEq α] (hs : s.Finite) :
    hs.offDiag.toFinset = hs.toFinset.offDiag :=
  Finset.ext <| by 

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
inst✝ : DecidableEq α
hs : Set.Finite s
⊢ ∀ (a : α × α), a ∈ Finite.toFinset (_ : Set.Finite (offDiag s)) ↔ a ∈ Finset.offDiag (Finite.toFinset hs)

Next tactic:
simp
theorem Finite.fin_embedding {s : Set α} (h : s.Finite) :
    ∃ (n : ℕ) (f : Fin n ↪ α), range f = s :=
  ⟨_, (Fintype.equivFin (h.toFinset : Set α)).symm.asEmbedding, by
    

Proof state:
α : Type u
β : Type v
ι : Sort w
γ : Type x
s : Set α
h : Set.Finite s
⊢ range ⇑(Equiv.asEmbedding (Fintype.equivFin ↑↑(Finite.toFinset h)).symm) = s

Next tactic:
simp only [Finset.coe_sort_coe, Equiv.asEmbedding_range, Finite.coe_toFinset, setOf_mem_eq]
theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) :
    ∃ I : Set ι, I.Finite ∧ s ⊆ ⋃ i ∈ I, t i := by
  

Proof state:
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
s : Set α
hs : Set.Finite s
ι : Type u_1
t : ι → Set α
h : s ⊆ ⋃ i, t i
⊢ ∃ I, Set.Finite I ∧ s ⊆ ⋃ i ∈ I, t i

Next tactic:
cases hs
theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) :
    ∃ I : Set ι, I.Finite ∧ s ⊆ ⋃ i ∈ I, t i := by
  cases hs
  

Proof state:
case intro
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
s : Set α
ι : Type u_1
t : ι → Set α
h : s ⊆ ⋃ i, t i
a✝ : Fintype ↑s
⊢ ∃ I, Set.Finite I ∧ s ⊆ ⋃ i ∈ I, t i

Next tactic:
choose f hf using show ∀ x : s, ∃ i, x.1 ∈ t i by simpa [subset_def] using h
theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) :
    ∃ I : Set ι, I.Finite ∧ s ⊆ ⋃ i ∈ I, t i := by
  cases hs
  choose f hf using show ∀ x : s, ∃ i, x.1 ∈ t i by 

Proof state:
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
s : Set α
ι : Type u_1
t : ι → Set α
h : s ⊆ ⋃ i, t i
a✝ : Fintype ↑s
⊢ ∀ (x : ↑s), ∃ i, ↑x ∈ t i

Next tactic:
simpa [subset_def] using h
theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) :
    ∃ I : Set ι, I.Finite ∧ s ⊆ ⋃ i ∈ I, t i := by
  cases hs
  choose f hf using show ∀ x : s, ∃ i, x.1 ∈ t i by simpa [subset_def] using h
  

Proof state:
case intro
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
s : Set α
ι : Type u_1
t : ι → Set α
h : s ⊆ ⋃ i, t i
a✝ : Fintype ↑s
f : ↑s → ι
hf : ∀ (x : ↑s), ↑x ∈ t (f x)
⊢ ∃ I, Set.Finite I ∧ s ⊆ ⋃ i ∈ I, t i

Next tactic:
refine' ⟨range f, finite_range f, fun x hx => _⟩
theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) :
    ∃ I : Set ι, I.Finite ∧ s ⊆ ⋃ i ∈ I, t i := by
  cases hs
  choose f hf using show ∀ x : s, ∃ i, x.1 ∈ t i by simpa [subset_def] using h
  refine' ⟨range f, finite_range f, fun x hx => _⟩
  

Proof state:
case intro
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
s : Set α
ι : Type u_1
t : ι → Set α
h : s ⊆ ⋃ i, t i
a✝ : Fintype ↑s
f : ↑s → ι
hf : ∀ (x : ↑s), ↑x ∈ t (f x)
x : α
hx : x ∈ s
⊢ x ∈ ⋃ i ∈ range f, t i

Next tactic:
rw [biUnion_range, mem_iUnion]
theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) :
    ∃ I : Set ι, I.Finite ∧ s ⊆ ⋃ i ∈ I, t i := by
  cases hs
  choose f hf using show ∀ x : s, ∃ i, x.1 ∈ t i by simpa [subset_def] using h
  refine' ⟨range f, finite_range f, fun x hx => _⟩
  rw [biUnion_range, mem_iUnion]
  

Proof state:
case intro
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
s : Set α
ι : Type u_1
t : ι → Set α
h : s ⊆ ⋃ i, t i
a✝ : Fintype ↑s
f : ↑s → ι
hf : ∀ (x : ↑s), ↑x ∈ t (f x)
x : α
hx : x ∈ s
⊢ ∃ i, x ∈ t (f i)

Next tactic:
exact ⟨⟨x, hx⟩, hf _⟩
theorem eq_finite_iUnion_of_finite_subset_iUnion {ι} {s : ι → Set α} {t : Set α} (tfin : t.Finite)
    (h : t ⊆ ⋃ i, s i) :
    ∃ I : Set ι,
      I.Finite ∧
        ∃ σ : { i | i ∈ I } → Set α, (∀ i, (σ i).Finite) ∧ (∀ i, σ i ⊆ s i) ∧ t = ⋃ i, σ i :=
  let ⟨I, Ifin, hI⟩ := finite_subset_iUnion tfin h
  ⟨I, Ifin, fun x => s x ∩ t, fun i => tfin.subset (inter_subset_right _ _), fun i =>
    inter_subset_left _ _, by
    

Proof state:
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
ι : Type u_1
s : ι → Set α
t : Set α
tfin : Set.Finite t
h : t ⊆ ⋃ i, s i
I : Set ι
Ifin : Set.Finite I
hI : t ⊆ ⋃ i ∈ I, s i
⊢ t = ⋃ i, (fun x => s ↑x ∩ t) i

Next tactic:
ext x
theorem eq_finite_iUnion_of_finite_subset_iUnion {ι} {s : ι → Set α} {t : Set α} (tfin : t.Finite)
    (h : t ⊆ ⋃ i, s i) :
    ∃ I : Set ι,
      I.Finite ∧
        ∃ σ : { i | i ∈ I } → Set α, (∀ i, (σ i).Finite) ∧ (∀ i, σ i ⊆ s i) ∧ t = ⋃ i, σ i :=
  let ⟨I, Ifin, hI⟩ := finite_subset_iUnion tfin h
  ⟨I, Ifin, fun x => s x ∩ t, fun i => tfin.subset (inter_subset_right _ _), fun i =>
    inter_subset_left _ _, by
    ext x
    

Proof state:
case h
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
ι : Type u_1
s : ι → Set α
t : Set α
tfin : Set.Finite t
h : t ⊆ ⋃ i, s i
I : Set ι
Ifin : Set.Finite I
hI : t ⊆ ⋃ i ∈ I, s i
x : α
⊢ x ∈ t ↔ x ∈ ⋃ i, (fun x => s ↑x ∩ t) i

Next tactic:
rw [mem_iUnion]
theorem eq_finite_iUnion_of_finite_subset_iUnion {ι} {s : ι → Set α} {t : Set α} (tfin : t.Finite)
    (h : t ⊆ ⋃ i, s i) :
    ∃ I : Set ι,
      I.Finite ∧
        ∃ σ : { i | i ∈ I } → Set α, (∀ i, (σ i).Finite) ∧ (∀ i, σ i ⊆ s i) ∧ t = ⋃ i, σ i :=
  let ⟨I, Ifin, hI⟩ := finite_subset_iUnion tfin h
  ⟨I, Ifin, fun x => s x ∩ t, fun i => tfin.subset (inter_subset_right _ _), fun i =>
    inter_subset_left _ _, by
    ext x
    rw [mem_iUnion]
    

Proof state:
case h
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
ι : Type u_1
s : ι → Set α
t : Set α
tfin : Set.Finite t
h : t ⊆ ⋃ i, s i
I : Set ι
Ifin : Set.Finite I
hI : t ⊆ ⋃ i ∈ I, s i
x : α
⊢ x ∈ t ↔ ∃ i, x ∈ (fun x => s ↑x ∩ t) i

Next tactic:
constructor
theorem eq_finite_iUnion_of_finite_subset_iUnion {ι} {s : ι → Set α} {t : Set α} (tfin : t.Finite)
    (h : t ⊆ ⋃ i, s i) :
    ∃ I : Set ι,
      I.Finite ∧
        ∃ σ : { i | i ∈ I } → Set α, (∀ i, (σ i).Finite) ∧ (∀ i, σ i ⊆ s i) ∧ t = ⋃ i, σ i :=
  let ⟨I, Ifin, hI⟩ := finite_subset_iUnion tfin h
  ⟨I, Ifin, fun x => s x ∩ t, fun i => tfin.subset (inter_subset_right _ _), fun i =>
    inter_subset_left _ _, by
    ext x
    rw [mem_iUnion]
    constructor
    · 

Proof state:
case h.mp
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
ι : Type u_1
s : ι → Set α
t : Set α
tfin : Set.Finite t
h : t ⊆ ⋃ i, s i
I : Set ι
Ifin : Set.Finite I
hI : t ⊆ ⋃ i ∈ I, s i
x : α
⊢ x ∈ t → ∃ i, x ∈ (fun x => s ↑x ∩ t) i

Next tactic:
intro x_in
theorem eq_finite_iUnion_of_finite_subset_iUnion {ι} {s : ι → Set α} {t : Set α} (tfin : t.Finite)
    (h : t ⊆ ⋃ i, s i) :
    ∃ I : Set ι,
      I.Finite ∧
        ∃ σ : { i | i ∈ I } → Set α, (∀ i, (σ i).Finite) ∧ (∀ i, σ i ⊆ s i) ∧ t = ⋃ i, σ i :=
  let ⟨I, Ifin, hI⟩ := finite_subset_iUnion tfin h
  ⟨I, Ifin, fun x => s x ∩ t, fun i => tfin.subset (inter_subset_right _ _), fun i =>
    inter_subset_left _ _, by
    ext x
    rw [mem_iUnion]
    constructor
    · intro x_in
      

Proof state:
case h.mp
α : Type u
β : Type v
ι✝ : Sort w
γ : Type x
ι : Type u_1
s : ι → Set α
t : Set α
tfin : Set.Finite t
h : t ⊆ ⋃ i, s i
I : Set ι
Ifin : Set.Finite I
hI : t ⊆ ⋃ i ∈ I, s i
x : α
x_in : x ∈ t
⊢ ∃ i, x ∈ (fun x => s ↑x ∩ t) i

Next tactic:
rcases mem_iUnion.mp (hI x_in) with ⟨i, _, ⟨hi, rfl⟩, H⟩