l3lab/ntp-mathlib huggingface dataset:
theorem eq_singleton_or_nontrivial (ha : a ∈ s) : s = {a} ∨ s.Nontrivial := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s : Finset α
a b : α
ha : a ∈ s
⊢ s = {a} ∨ Finset.Nontrivial s

Next tactic:
rw [← coe_eq_singleton]
theorem eq_singleton_or_nontrivial (ha : a ∈ s) : s = {a} ∨ s.Nontrivial := by
  rw [← coe_eq_singleton]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s : Finset α
a b : α
ha : a ∈ s
⊢ ↑s = {a} ∨ Finset.Nontrivial s

Next tactic:
exact Set.eq_singleton_or_nontrivial ha
theorem forall_mem_cons (h : a ∉ s) (p : α → Prop) :
    (∀ x, x ∈ cons a s h → p x) ↔ p a ∧ ∀ x, x ∈ s → p x := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b : α
h : a ∉ s
p : α → Prop
⊢ (∀ x ∈ cons a s h, p x) ↔ p a ∧ ∀ x ∈ s, p x

Next tactic:
simp only [mem_cons, or_imp, forall_and, forall_eq]
@[simp]
theorem nonempty_mk {m : Multiset α} {hm} : (⟨m, hm⟩ : Finset α).Nonempty ↔ m ≠ 0 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b : α
m : Multiset α
hm : Nodup m
⊢ Finset.Nonempty { val := m, nodup := hm } ↔ m ≠ 0

Next tactic:
induction m using Multiset.induction_on
@[simp]
theorem nonempty_mk {m : Multiset α} {hm} : (⟨m, hm⟩ : Finset α).Nonempty ↔ m ≠ 0 := by
  induction m using Multiset.induction_on <;> 

Proof state:
case empty
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b : α
hm : Nodup 0
⊢ Finset.Nonempty { val := 0, nodup := hm } ↔ 0 ≠ 0

Next tactic:
simp
@[simp]
theorem nonempty_mk {m : Multiset α} {hm} : (⟨m, hm⟩ : Finset α).Nonempty ↔ m ≠ 0 := by
  induction m using Multiset.induction_on <;> 

Proof state:
case cons
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b a✝¹ : α
s✝ : Multiset α
a✝ : ∀ {hm : Nodup s✝}, Finset.Nonempty { val := s✝, nodup := hm } ↔ s✝ ≠ 0
hm : Nodup (a✝¹ ::ₘ s✝)
⊢ Finset.Nonempty { val := a✝¹ ::ₘ s✝, nodup := hm } ↔ a✝¹ ::ₘ s✝ ≠ 0

Next tactic:
simp
@[simp]
theorem coe_cons {a s h} : (@cons α a s h : Set α) = insert a (s : Set α) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ t : Finset α
a✝ b a : α
s : Finset α
h : a ∉ s
⊢ ↑(cons a s h) = insert a ↑s

Next tactic:
ext
@[simp]
theorem coe_cons {a s h} : (@cons α a s h : Set α) = insert a (s : Set α) := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ t : Finset α
a✝ b a : α
s : Finset α
h : a ∉ s
x✝ : α
⊢ x✝ ∈ ↑(cons a s h) ↔ x✝ ∈ insert a ↑s

Next tactic:
simp
@[simp]
theorem cons_subset_cons {hs ht} : s.cons a hs ⊆ t.cons a ht ↔ s ⊆ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b : α
hs : a ∉ s
ht : a ∉ t
⊢ cons a s hs ⊆ cons a t ht ↔ s ⊆ t

Next tactic:
rwa [← coe_subset, coe_cons, coe_cons, Set.insert_subset_insert_iff, coe_subset]
theorem ssubset_iff_exists_cons_subset : s ⊂ t ↔ ∃ (a : _) (h : a ∉ s), s.cons a h ⊆ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b : α
⊢ s ⊂ t ↔ ∃ a, ∃ (h : a ∉ s), cons a s h ⊆ t

Next tactic:
refine' ⟨fun h => _, fun ⟨a, ha, h⟩ => ssubset_of_ssubset_of_subset (ssubset_cons _) h⟩
theorem ssubset_iff_exists_cons_subset : s ⊂ t ↔ ∃ (a : _) (h : a ∉ s), s.cons a h ⊆ t := by
  refine' ⟨fun h => _, fun ⟨a, ha, h⟩ => ssubset_of_ssubset_of_subset (ssubset_cons _) h⟩
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a b : α
h : s ⊂ t
⊢ ∃ a, ∃ (h : a ∉ s), cons a s h ⊆ t

Next tactic:
obtain ⟨a, hs, ht⟩ := not_subset.1 h.2
theorem ssubset_iff_exists_cons_subset : s ⊂ t ↔ ∃ (a : _) (h : a ∉ s), s.cons a h ⊆ t := by
  refine' ⟨fun h => _, fun ⟨a, ha, h⟩ => ssubset_of_ssubset_of_subset (ssubset_cons _) h⟩
  obtain ⟨a, hs, ht⟩ := not_subset.1 h.2
  

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
a✝ b : α
h : s ⊂ t
a : α
hs : a ∈ t
ht : a ∉ s
⊢ ∃ a, ∃ (h : a ∉ s), cons a s h ⊆ t

Next tactic:
exact ⟨a, ht, cons_subset.2 ⟨hs, h.subset⟩⟩
theorem disjoint_right : Disjoint s t ↔ ∀ ⦃a⦄, a ∈ t → a ∉ s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s t u : Finset α
a b : α
⊢ _root_.Disjoint s t ↔ ∀ ⦃a : α⦄, a ∈ t → a ∉ s

Next tactic:
rw [_root_.disjoint_comm, disjoint_left]
theorem disjoint_iff_ne : Disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s t u : Finset α
a b : α
⊢ _root_.Disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b

Next tactic:
simp only [disjoint_left, imp_not_comm, forall_eq']
theorem not_disjoint_iff : ¬Disjoint s t ↔ ∃ a, a ∈ s ∧ a ∈ t :=
  disjoint_left.not.trans <| not_forall.trans <| exists_congr fun _ => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s t u : Finset α
a b x✝ : α
⊢ ¬(x✝ ∈ s → x✝ ∉ t) ↔ x✝ ∈ s ∧ x✝ ∈ t

Next tactic:
rw [not_imp, not_not]
@[simp]
theorem disjoint_singleton_left : Disjoint (singleton a) s ↔ a ∉ s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s t u : Finset α
a b : α
⊢ _root_.Disjoint {a} s ↔ a ∉ s

Next tactic:
simp only [disjoint_left, mem_singleton, forall_eq]
theorem disjoint_singleton : Disjoint ({a} : Finset α) {b} ↔ a ≠ b := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s t u : Finset α
a b : α
⊢ _root_.Disjoint {a} {b} ↔ a ≠ b

Next tactic:
rw [disjoint_singleton_left, mem_singleton]
@[simp, norm_cast]
theorem disjoint_coe : Disjoint (s : Set α) t ↔ Disjoint s t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s t u : Finset α
a b : α
⊢ _root_.Disjoint ↑s ↑t ↔ _root_.Disjoint s t

Next tactic:
simp only [Finset.disjoint_left, Set.disjoint_left, mem_coe]
@[simp]
theorem mem_disjUnion {α s t h a} : a ∈ @disjUnion α s t h ↔ a ∈ s ∨ a ∈ t := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
s t : Finset α
h : _root_.Disjoint s t
a : α
⊢ a ∈ disjUnion s t h ↔ a ∈ s ∨ a ∈ t

Next tactic:
rcases s with ⟨⟨s⟩⟩
@[simp]
theorem mem_disjUnion {α s t h a} : a ∈ @disjUnion α s t h ↔ a ∈ s ∨ a ∈ t := by
  rcases s with ⟨⟨s⟩⟩; 

Proof state:
case mk.mk
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
t : Finset α
a : α
val✝ : Multiset α
s : List α
nodup✝ : Nodup (Quot.mk Setoid.r s)
h : _root_.Disjoint { val := Quot.mk Setoid.r s, nodup := nodup✝ } t
⊢ a ∈ disjUnion { val := Quot.mk Setoid.r s, nodup := nodup✝ } t h ↔
    a ∈ { val := Quot.mk Setoid.r s, nodup := nodup✝ } ∨ a ∈ t

Next tactic:
rcases t with ⟨⟨t⟩⟩
@[simp]
theorem mem_disjUnion {α s t h a} : a ∈ @disjUnion α s t h ↔ a ∈ s ∨ a ∈ t := by
  rcases s with ⟨⟨s⟩⟩; rcases t with ⟨⟨t⟩⟩; 

Proof state:
case mk.mk.mk.mk
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
a : α
val✝¹ : Multiset α
s : List α
nodup✝¹ : Nodup (Quot.mk Setoid.r s)
val✝ : Multiset α
t : List α
nodup✝ : Nodup (Quot.mk Setoid.r t)
h : _root_.Disjoint { val := Quot.mk Setoid.r s, nodup := nodup✝¹ } { val := Quot.mk Setoid.r t, nodup := nodup✝ }
⊢ a ∈ disjUnion { val := Quot.mk Setoid.r s, nodup := nodup✝¹ } { val := Quot.mk Setoid.r t, nodup := nodup✝ } h ↔
    a ∈ { val := Quot.mk Setoid.r s, nodup := nodup✝¹ } ∨ a ∈ { val := Quot.mk Setoid.r t, nodup := nodup✝ }

Next tactic:
apply List.mem_append
@[simp, norm_cast]
theorem coe_disjUnion {s t : Finset α} (h : Disjoint s t) :
    (disjUnion s t h : Set α) = (s : Set α) ∪ t :=
  Set.ext <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Finset α
h : _root_.Disjoint s t
⊢ ∀ (x : α), x ∈ ↑(disjUnion s t h) ↔ x ∈ ↑s ∪ ↑t

Next tactic:
simp
theorem disjUnion_singleton (s : Finset α) (a : α) (h : Disjoint s {a}) :
    disjUnion s {a} h = cons a s (disjoint_singleton_right.mp h) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s : Finset α
a : α
h : _root_.Disjoint s {a}
⊢ disjUnion s {a} h = cons a s (_ : a ∉ s)

Next tactic:
rw [disjUnion_comm, singleton_disjUnion]
theorem insert_val' (a : α) (s : Finset α) : (insert a s).1 = dedup (a ::ₘ s.1) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b a : α
s : Finset α
⊢ (insert a s).val = dedup (a ::ₘ s.val)

Next tactic:
rw [dedup_cons, dedup_eq_self]
theorem insert_val' (a : α) (s : Finset α) : (insert a s).1 = dedup (a ::ₘ s.1) := by
  rw [dedup_cons, dedup_eq_self]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b a : α
s : Finset α
⊢ (insert a s).val = ndinsert a s.val

Next tactic:
rfl
theorem insert_val_of_not_mem {a : α} {s : Finset α} (h : a ∉ s) : (insert a s).1 = a ::ₘ s.1 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b a : α
s : Finset α
h : a ∉ s
⊢ (insert a s).val = a ::ₘ s.val

Next tactic:
rw [insert_val, ndinsert_of_not_mem h]
@[simp]
theorem cons_eq_insert (a s h) : @cons α a s h = insert a s :=
  ext fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝¹ b a✝ : α
s : Finset α
h : a✝ ∉ s
a : α
⊢ a ∈ cons a✝ s h ↔ a ∈ insert a✝ s

Next tactic:
simp
@[simp, norm_cast]
theorem coe_insert (a : α) (s : Finset α) : ↑(insert a s) = (insert a s : Set α) :=
  Set.ext fun x => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b a : α
s : Finset α
x : α
⊢ x ∈ ↑(insert a s) ↔ x ∈ insert a ↑s

Next tactic:
simp only [mem_coe, mem_insert, Set.mem_insert_iff]
theorem mem_insert_coe {s : Finset α} {x y : α} : x ∈ insert y s ↔ x ∈ insert y (s : Set α) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a b : α
s : Finset α
x y : α
⊢ x ∈ insert y s ↔ x ∈ insert y ↑s

Next tactic:
simp
instance : IsLawfulSingleton α (Finset α) :=
  ⟨fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a✝ b a : α
⊢ insert a ∅ = {a}

Next tactic:
ext
instance : IsLawfulSingleton α (Finset α) :=
  ⟨fun a => by ext; 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a✝¹ b a a✝ : α
⊢ a✝ ∈ insert a ∅ ↔ a✝ ∈ {a}

Next tactic:
simp
theorem Insert.comm (a b : α) (s : Finset α) : insert a (insert b s) = insert b (insert a s) :=
  ext fun x => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b✝ a b : α
s : Finset α
x : α
⊢ x ∈ insert a (insert b s) ↔ x ∈ insert b (insert a s)

Next tactic:
simp only [mem_insert, or_left_comm]
@[norm_cast]
theorem coe_pair {a b : α} : (({a, b} : Finset α) : Set α) = {a, b} := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a✝ b✝ a b : α
⊢ ↑{a, b} = {a, b}

Next tactic:
ext
@[norm_cast]
theorem coe_pair {a b : α} : (({a, b} : Finset α) : Set α) = {a, b} := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a✝ b✝ a b x✝ : α
⊢ x✝ ∈ ↑{a, b} ↔ x✝ ∈ {a, b}

Next tactic:
simp
@[simp, norm_cast]
theorem coe_eq_pair {s : Finset α} {a b : α} : (s : Set α) = {a, b} ↔ s = {a, b} := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b✝ : α
s : Finset α
a b : α
⊢ ↑s = {a, b} ↔ s = {a, b}

Next tactic:
rw [← coe_pair, coe_inj]
theorem insert_idem (a : α) (s : Finset α) : insert a (insert a s) = insert a s :=
  ext fun x => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t u v : Finset α
a✝ b a : α
s : Finset α
x : α
⊢ x ∈ insert a (insert a s) ↔ x ∈ insert a s

Next tactic:
simp only [mem_insert, ← or_assoc, or_self_iff]
theorem ne_insert_of_not_mem (s t : Finset α) {a : α} (h : a ∉ s) : s ≠ insert a t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t✝ u v : Finset α
a✝ b : α
s t : Finset α
a : α
h : a ∉ s
⊢ s ≠ insert a t

Next tactic:
contrapose! h
theorem ne_insert_of_not_mem (s t : Finset α) {a : α} (h : a ∉ s) : s ≠ insert a t := by
  contrapose! h
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s✝ t✝ u v : Finset α
a✝ b : α
s t : Finset α
a : α
h : s = insert a t
⊢ a ∈ s

Next tactic:
simp [h]
theorem insert_subset_iff : insert a s ⊆ t ↔ a ∈ t ∧ s ⊆ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a b : α
⊢ insert a s ⊆ t ↔ a ∈ t ∧ s ⊆ t

Next tactic:
simp only [subset_iff, mem_insert, forall_eq, or_imp, forall_and]
@[simp] lemma insert_subset_insert_iff (ha : a ∉ s) : insert a s ⊆ insert a t ↔ s ⊆ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a b : α
ha : a ∉ s
⊢ insert a s ⊆ insert a t ↔ s ⊆ t

Next tactic:
simp_rw [← coe_subset]
@[simp] lemma insert_subset_insert_iff (ha : a ∉ s) : insert a s ⊆ insert a t ↔ s ⊆ t := by
  simp_rw [← coe_subset]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α
s t u v : Finset α
a b : α
ha : a ∉ s
⊢ ↑(insert a s) ⊆ ↑(insert a t) ↔ ↑s ⊆ ↑t

Next tactic:
simp [-coe_subset, ha]
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
s : Multiset α
nd : Nodup s
⊢ p { val := s, nodup := nd }

Next tactic:
induction s using Multiset.induction with
    | empty => exact empty
    | @cons a s IH =>
      cases' nodup_cons.1 nd with m nd'
      rw [← (eq_of_veq _ : Finset.cons a ⟨s, _⟩ m = ⟨a ::ₘ s, nd⟩)]
      · exact cons m (IH nd')
      · rw [cons_val]
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    

Proof state:
case empty
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s t u v : Finset α✝
a b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
nd : Nodup 0
⊢ p { val := 0, nodup := nd }

Next tactic:
| empty => exact empty
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    | empty => 

Proof state:
case empty
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s t u v : Finset α✝
a b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
nd : Nodup 0
⊢ p { val := 0, nodup := nd }

Next tactic:
exact empty
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    | empty => exact empty
    

Proof state:
case cons
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
a : α
s : Multiset α
IH : ∀ (nd : Nodup s), p { val := s, nodup := nd }
nd : Nodup (a ::ₘ s)
⊢ p { val := a ::ₘ s, nodup := nd }

Next tactic:
| @cons a s IH =>
      cases' nodup_cons.1 nd with m nd'
      rw [← (eq_of_veq _ : Finset.cons a ⟨s, _⟩ m = ⟨a ::ₘ s, nd⟩)]
      · exact cons m (IH nd')
      · rw [cons_val]
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    | empty => exact empty
    | @cons a s IH =>
      

Proof state:
case cons
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
a : α
s : Multiset α
IH : ∀ (nd : Nodup s), p { val := s, nodup := nd }
nd : Nodup (a ::ₘ s)
⊢ p { val := a ::ₘ s, nodup := nd }

Next tactic:
cases' nodup_cons.1 nd with m nd'
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    | empty => exact empty
    | @cons a s IH =>
      cases' nodup_cons.1 nd with m nd'
      

Proof state:
case cons.intro
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
a : α
s : Multiset α
IH : ∀ (nd : Nodup s), p { val := s, nodup := nd }
nd : Nodup (a ::ₘ s)
m : a ∉ s
nd' : Nodup s
⊢ p { val := a ::ₘ s, nodup := nd }

Next tactic:
rw [← (eq_of_veq _ : Finset.cons a ⟨s, _⟩ m = ⟨a ::ₘ s, nd⟩)]
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    | empty => exact empty
    | @cons a s IH =>
      cases' nodup_cons.1 nd with m nd'
      rw [← (eq_of_veq _ : Finset.cons a ⟨s, _⟩ m = ⟨a ::ₘ s, nd⟩)]
      · 

Proof state:
case cons.intro
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
a : α
s : Multiset α
IH : ∀ (nd : Nodup s), p { val := s, nodup := nd }
nd : Nodup (a ::ₘ s)
m : a ∉ s
nd' : Nodup s
⊢ p (Finset.cons a { val := s, nodup := ?m.130014 } m)

Next tactic:
exact cons m (IH nd')
@[elab_as_elim]
theorem cons_induction {α : Type*} {p : Finset α → Prop} (empty : p ∅)
    (cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (cons a s h)) : ∀ s, p s
  | ⟨s, nd⟩ => by
    induction s using Multiset.induction with
    | empty => exact empty
    | @cons a s IH =>
      cases' nodup_cons.1 nd with m nd'
      rw [← (eq_of_veq _ : Finset.cons a ⟨s, _⟩ m = ⟨a ::ₘ s, nd⟩)]
      · exact cons m (IH nd')
      · 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : Finset α → Prop
empty : p ∅
cons : ∀ ⦃a : α⦄ {s : Finset α} (h : a ∉ s), p s → p (Finset.cons a s h)
a : α
s : Multiset α
IH : ∀ (nd : Nodup s), p { val := s, nodup := nd }
nd : Nodup (a ::ₘ s)
m : a ∉ s
nd' : Nodup s
⊢ (Finset.cons a { val := s, nodup := nd' } m).val = { val := a ::ₘ s, nodup := nd }.val

Next tactic:
rw [cons_val]
/-- To prove a proposition about a nonempty `s : Finset α`, it suffices to show it holds for all
singletons and that if it holds for nonempty `t : Finset α`, then it also holds for the `Finset`
obtained by inserting an element in `t`. -/
@[elab_as_elim]
theorem Nonempty.cons_induction {α : Type*} {p : ∀ s : Finset α, s.Nonempty → Prop}
    (h₀ : ∀ a, p {a} (singleton_nonempty _))
    (h₁ : ∀ ⦃a⦄ (s) (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (nonempty_cons h))
    {s : Finset α} (hs : s.Nonempty) : p s hs := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s✝ t u v : Finset α✝
a b : α✝
α : Type u_4
p : (s : Finset α) → Finset.Nonempty s → Prop
h₀ : ∀ (a : α), p {a} (_ : Finset.Nonempty {a})
h₁ :
  ∀ ⦃a : α⦄ (s : Finset α) (h : a ∉ s) (hs : Finset.Nonempty s),
    p s hs → p (cons a s h) (_ : Finset.Nonempty (cons a s h))
s : Finset α
hs : Finset.Nonempty s
⊢ p s hs

Next tactic:
induction' s using Finset.cons_induction with a t ha h
/-- To prove a proposition about a nonempty `s : Finset α`, it suffices to show it holds for all
singletons and that if it holds for nonempty `t : Finset α`, then it also holds for the `Finset`
obtained by inserting an element in `t`. -/
@[elab_as_elim]
theorem Nonempty.cons_induction {α : Type*} {p : ∀ s : Finset α, s.Nonempty → Prop}
    (h₀ : ∀ a, p {a} (singleton_nonempty _))
    (h₁ : ∀ ⦃a⦄ (s) (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (nonempty_cons h))
    {s : Finset α} (hs : s.Nonempty) : p s hs := by
  induction' s using Finset.cons_induction with a t ha h
  · 

Proof state:
case empty
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s t u v : Finset α✝
a b : α✝
α : Type u_4
p : (s : Finset α) → Finset.Nonempty s → Prop
h₀ : ∀ (a : α), p {a} (_ : Finset.Nonempty {a})
h₁ :
  ∀ ⦃a : α⦄ (s : Finset α) (h : a ∉ s) (hs : Finset.Nonempty s),
    p s hs → p (cons a s h) (_ : Finset.Nonempty (cons a s h))
hs : Finset.Nonempty ∅
⊢ p ∅ hs

Next tactic:
exact (not_nonempty_empty hs).elim
/-- To prove a proposition about a nonempty `s : Finset α`, it suffices to show it holds for all
singletons and that if it holds for nonempty `t : Finset α`, then it also holds for the `Finset`
obtained by inserting an element in `t`. -/
@[elab_as_elim]
theorem Nonempty.cons_induction {α : Type*} {p : ∀ s : Finset α, s.Nonempty → Prop}
    (h₀ : ∀ a, p {a} (singleton_nonempty _))
    (h₁ : ∀ ⦃a⦄ (s) (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (nonempty_cons h))
    {s : Finset α} (hs : s.Nonempty) : p s hs := by
  induction' s using Finset.cons_induction with a t ha h
  · exact (not_nonempty_empty hs).elim
  

Proof state:
case cons
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s t✝ u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : (s : Finset α) → Finset.Nonempty s → Prop
h₀ : ∀ (a : α), p {a} (_ : Finset.Nonempty {a})
h₁ :
  ∀ ⦃a : α⦄ (s : Finset α) (h : a ∉ s) (hs : Finset.Nonempty s),
    p s hs → p (cons a s h) (_ : Finset.Nonempty (cons a s h))
a : α
t : Finset α
ha : a ∉ t
h : ∀ (hs : Finset.Nonempty t), p t hs
hs : Finset.Nonempty (cons a t ha)
⊢ p (cons a t ha) hs

Next tactic:
obtain rfl | ht := t.eq_empty_or_nonempty
/-- To prove a proposition about a nonempty `s : Finset α`, it suffices to show it holds for all
singletons and that if it holds for nonempty `t : Finset α`, then it also holds for the `Finset`
obtained by inserting an element in `t`. -/
@[elab_as_elim]
theorem Nonempty.cons_induction {α : Type*} {p : ∀ s : Finset α, s.Nonempty → Prop}
    (h₀ : ∀ a, p {a} (singleton_nonempty _))
    (h₁ : ∀ ⦃a⦄ (s) (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (nonempty_cons h))
    {s : Finset α} (hs : s.Nonempty) : p s hs := by
  induction' s using Finset.cons_induction with a t ha h
  · exact (not_nonempty_empty hs).elim
  obtain rfl | ht := t.eq_empty_or_nonempty
  · 

Proof state:
case cons.inl
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s t u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : (s : Finset α) → Finset.Nonempty s → Prop
h₀ : ∀ (a : α), p {a} (_ : Finset.Nonempty {a})
h₁ :
  ∀ ⦃a : α⦄ (s : Finset α) (h : a ∉ s) (hs : Finset.Nonempty s),
    p s hs → p (cons a s h) (_ : Finset.Nonempty (cons a s h))
a : α
ha : a ∉ ∅
h : ∀ (hs : Finset.Nonempty ∅), p ∅ hs
hs : Finset.Nonempty (cons a ∅ ha)
⊢ p (cons a ∅ ha) hs

Next tactic:
exact h₀ a
/-- To prove a proposition about a nonempty `s : Finset α`, it suffices to show it holds for all
singletons and that if it holds for nonempty `t : Finset α`, then it also holds for the `Finset`
obtained by inserting an element in `t`. -/
@[elab_as_elim]
theorem Nonempty.cons_induction {α : Type*} {p : ∀ s : Finset α, s.Nonempty → Prop}
    (h₀ : ∀ a, p {a} (singleton_nonempty _))
    (h₁ : ∀ ⦃a⦄ (s) (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (nonempty_cons h))
    {s : Finset α} (hs : s.Nonempty) : p s hs := by
  induction' s using Finset.cons_induction with a t ha h
  · exact (not_nonempty_empty hs).elim
  obtain rfl | ht := t.eq_empty_or_nonempty
  · exact h₀ a
  · 

Proof state:
case cons.inr
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : DecidableEq α✝
s t✝ u v : Finset α✝
a✝ b : α✝
α : Type u_4
p : (s : Finset α) → Finset.Nonempty s → Prop
h₀ : ∀ (a : α), p {a} (_ : Finset.Nonempty {a})
h₁ :
  ∀ ⦃a : α⦄ (s : Finset α) (h : a ∉ s) (hs : Finset.Nonempty s),
    p s hs → p (cons a s h) (_ : Finset.Nonempty (cons a s h))
a : α
t : Finset α
ha : a ∉ t
h : ∀ (hs : Finset.Nonempty t), p t hs
hs : Finset.Nonempty (cons a t ha)
ht : Finset.Nonempty t
⊢ p (cons a t ha) hs

Next tactic:
exact h₁ t ha ht (h ht)