l3lab/ntp-mathlib huggingface dataset:
/-- Cuts `s` along the finsets in `F`: Two elements of `s` will be in the same part if they are
in the same finsets of `F`. -/
def atomise (s : Finset α) (F : Finset (Finset α)) : Finpartition s :=
  ofErase (F.powerset.image fun Q ↦ s.filter fun i ↦ ∀ t ∈ F, t ∈ Q ↔ i ∈ t)
    (Set.PairwiseDisjoint.supIndep fun x hx y hy h ↦
      disjoint_left.mpr fun z hz1 hz2 ↦
        h (by
            rw [mem_coe, mem_image] at hx hy
            obtain ⟨Q, hQ, rfl⟩ := hx
            obtain ⟨R, hR, rfl⟩ := hy
            suffices h' : Q = R
            · subst h'
              exact of_eq_true (eq_self (
                filter (fun i ↦ ∀ (t : Finset α), t ∈ F → (t ∈ Q ↔ i ∈ t)) s))
            rw [id, mem_filter] at hz1 hz2
            rw [mem_powerset] at hQ hR
            ext i
            refine' ⟨fun hi ↦ _, fun hi ↦ _⟩
            · rwa [hz2.2 _ (hQ hi), ← hz1.2 _ (hQ hi)]
            · rwa [hz1.2 _ (hR hi), ← hz2.2 _ (hR hi)]))
    (by
      refine' (Finset.sup_le fun t ht ↦ _).antisymm fun a ha ↦ _
      · rw [mem_image] at ht
        obtain ⟨A, _, rfl⟩ := ht
        

Proof state:
case refine'_1.intro.intro
α : Type u_1
inst✝ : DecidableEq α
s✝ t u : Finset α
P : Finpartition s✝
a : α
s : Finset α
F A : Finset (Finset α)
left✝ : A ∈ powerset F
⊢ id (filter (fun i => ∀ t ∈ F, t ∈ A ↔ i ∈ t) s) ≤ s

Next tactic:
exact s.filter_subset _
/-- Cuts `s` along the finsets in `F`: Two elements of `s` will be in the same part if they are
in the same finsets of `F`. -/
def atomise (s : Finset α) (F : Finset (Finset α)) : Finpartition s :=
  ofErase (F.powerset.image fun Q ↦ s.filter fun i ↦ ∀ t ∈ F, t ∈ Q ↔ i ∈ t)
    (Set.PairwiseDisjoint.supIndep fun x hx y hy h ↦
      disjoint_left.mpr fun z hz1 hz2 ↦
        h (by
            rw [mem_coe, mem_image] at hx hy
            obtain ⟨Q, hQ, rfl⟩ := hx
            obtain ⟨R, hR, rfl⟩ := hy
            suffices h' : Q = R
            · subst h'
              exact of_eq_true (eq_self (
                filter (fun i ↦ ∀ (t : Finset α), t ∈ F → (t ∈ Q ↔ i ∈ t)) s))
            rw [id, mem_filter] at hz1 hz2
            rw [mem_powerset] at hQ hR
            ext i
            refine' ⟨fun hi ↦ _, fun hi ↦ _⟩
            · rwa [hz2.2 _ (hQ hi), ← hz1.2 _ (hQ hi)]
            · rwa [hz1.2 _ (hR hi), ← hz2.2 _ (hR hi)]))
    (by
      refine' (Finset.sup_le fun t ht ↦ _).antisymm fun a ha ↦ _
      · rw [mem_image] at ht
        obtain ⟨A, _, rfl⟩ := ht
        exact s.filter_subset _
      · 

Proof state:
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s✝ t u : Finset α
P : Finpartition s✝
a✝ : α
s : Finset α
F : Finset (Finset α)
a : α
ha : a ∈ s
⊢ a ∈ sup (image (fun Q => filter (fun i => ∀ t ∈ F, t ∈ Q ↔ i ∈ t) s) (powerset F)) id

Next tactic:
rw [mem_sup]
/-- Cuts `s` along the finsets in `F`: Two elements of `s` will be in the same part if they are
in the same finsets of `F`. -/
def atomise (s : Finset α) (F : Finset (Finset α)) : Finpartition s :=
  ofErase (F.powerset.image fun Q ↦ s.filter fun i ↦ ∀ t ∈ F, t ∈ Q ↔ i ∈ t)
    (Set.PairwiseDisjoint.supIndep fun x hx y hy h ↦
      disjoint_left.mpr fun z hz1 hz2 ↦
        h (by
            rw [mem_coe, mem_image] at hx hy
            obtain ⟨Q, hQ, rfl⟩ := hx
            obtain ⟨R, hR, rfl⟩ := hy
            suffices h' : Q = R
            · subst h'
              exact of_eq_true (eq_self (
                filter (fun i ↦ ∀ (t : Finset α), t ∈ F → (t ∈ Q ↔ i ∈ t)) s))
            rw [id, mem_filter] at hz1 hz2
            rw [mem_powerset] at hQ hR
            ext i
            refine' ⟨fun hi ↦ _, fun hi ↦ _⟩
            · rwa [hz2.2 _ (hQ hi), ← hz1.2 _ (hQ hi)]
            · rwa [hz1.2 _ (hR hi), ← hz2.2 _ (hR hi)]))
    (by
      refine' (Finset.sup_le fun t ht ↦ _).antisymm fun a ha ↦ _
      · rw [mem_image] at ht
        obtain ⟨A, _, rfl⟩ := ht
        exact s.filter_subset _
      · rw [mem_sup]
        

Proof state:
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s✝ t u : Finset α
P : Finpartition s✝
a✝ : α
s : Finset α
F : Finset (Finset α)
a : α
ha : a ∈ s
⊢ ∃ v ∈ image (fun Q => filter (fun i => ∀ t ∈ F, t ∈ Q ↔ i ∈ t) s) (powerset F), a ∈ id v

Next tactic:
refine'
          ⟨s.filter fun i ↦ ∀ t, t ∈ F → ((t ∈ F.filter fun u ↦ a ∈ u) ↔ i ∈ t),
            mem_image_of_mem _ (mem_powerset.2 <| filter_subset _ _),
            mem_filter.2 ⟨ha, fun t ht ↦ _⟩⟩
/-- Cuts `s` along the finsets in `F`: Two elements of `s` will be in the same part if they are
in the same finsets of `F`. -/
def atomise (s : Finset α) (F : Finset (Finset α)) : Finpartition s :=
  ofErase (F.powerset.image fun Q ↦ s.filter fun i ↦ ∀ t ∈ F, t ∈ Q ↔ i ∈ t)
    (Set.PairwiseDisjoint.supIndep fun x hx y hy h ↦
      disjoint_left.mpr fun z hz1 hz2 ↦
        h (by
            rw [mem_coe, mem_image] at hx hy
            obtain ⟨Q, hQ, rfl⟩ := hx
            obtain ⟨R, hR, rfl⟩ := hy
            suffices h' : Q = R
            · subst h'
              exact of_eq_true (eq_self (
                filter (fun i ↦ ∀ (t : Finset α), t ∈ F → (t ∈ Q ↔ i ∈ t)) s))
            rw [id, mem_filter] at hz1 hz2
            rw [mem_powerset] at hQ hR
            ext i
            refine' ⟨fun hi ↦ _, fun hi ↦ _⟩
            · rwa [hz2.2 _ (hQ hi), ← hz1.2 _ (hQ hi)]
            · rwa [hz1.2 _ (hR hi), ← hz2.2 _ (hR hi)]))
    (by
      refine' (Finset.sup_le fun t ht ↦ _).antisymm fun a ha ↦ _
      · rw [mem_image] at ht
        obtain ⟨A, _, rfl⟩ := ht
        exact s.filter_subset _
      · rw [mem_sup]
        refine'
          ⟨s.filter fun i ↦ ∀ t, t ∈ F → ((t ∈ F.filter fun u ↦ a ∈ u) ↔ i ∈ t),
            mem_image_of_mem _ (mem_powerset.2 <| filter_subset _ _),
            mem_filter.2 ⟨ha, fun t ht ↦ _⟩⟩
        

Proof state:
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s✝ t✝ u : Finset α
P : Finpartition s✝
a✝ : α
s : Finset α
F : Finset (Finset α)
a : α
ha : a ∈ s
t : Finset α
ht : t ∈ F
⊢ t ∈ filter (fun u => a ∈ u) F ↔ a ∈ t

Next tactic:
rw [mem_filter]
/-- Cuts `s` along the finsets in `F`: Two elements of `s` will be in the same part if they are
in the same finsets of `F`. -/
def atomise (s : Finset α) (F : Finset (Finset α)) : Finpartition s :=
  ofErase (F.powerset.image fun Q ↦ s.filter fun i ↦ ∀ t ∈ F, t ∈ Q ↔ i ∈ t)
    (Set.PairwiseDisjoint.supIndep fun x hx y hy h ↦
      disjoint_left.mpr fun z hz1 hz2 ↦
        h (by
            rw [mem_coe, mem_image] at hx hy
            obtain ⟨Q, hQ, rfl⟩ := hx
            obtain ⟨R, hR, rfl⟩ := hy
            suffices h' : Q = R
            · subst h'
              exact of_eq_true (eq_self (
                filter (fun i ↦ ∀ (t : Finset α), t ∈ F → (t ∈ Q ↔ i ∈ t)) s))
            rw [id, mem_filter] at hz1 hz2
            rw [mem_powerset] at hQ hR
            ext i
            refine' ⟨fun hi ↦ _, fun hi ↦ _⟩
            · rwa [hz2.2 _ (hQ hi), ← hz1.2 _ (hQ hi)]
            · rwa [hz1.2 _ (hR hi), ← hz2.2 _ (hR hi)]))
    (by
      refine' (Finset.sup_le fun t ht ↦ _).antisymm fun a ha ↦ _
      · rw [mem_image] at ht
        obtain ⟨A, _, rfl⟩ := ht
        exact s.filter_subset _
      · rw [mem_sup]
        refine'
          ⟨s.filter fun i ↦ ∀ t, t ∈ F → ((t ∈ F.filter fun u ↦ a ∈ u) ↔ i ∈ t),
            mem_image_of_mem _ (mem_powerset.2 <| filter_subset _ _),
            mem_filter.2 ⟨ha, fun t ht ↦ _⟩⟩
        rw [mem_filter]
        

Proof state:
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s✝ t✝ u : Finset α
P : Finpartition s✝
a✝ : α
s : Finset α
F : Finset (Finset α)
a : α
ha : a ∈ s
t : Finset α
ht : t ∈ F
⊢ t ∈ F ∧ a ∈ t ↔ a ∈ t

Next tactic:
exact and_iff_right ht
theorem mem_atomise :
    t ∈ (atomise s F).parts ↔
      t.Nonempty ∧ ∃ (Q : _) (_ : Q ⊆ F), (s.filter fun i ↦ ∀ u ∈ F, u ∈ Q ↔ i ∈ u) = t := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
⊢ t ∈ (atomise s F).parts ↔ Finset.Nonempty t ∧ ∃ Q, ∃ (_ : Q ⊆ F), filter (fun i => ∀ u ∈ F, u ∈ Q ↔ i ∈ u) s = t

Next tactic:
simp only [atomise, ofErase, bot_eq_empty, mem_erase, mem_image, nonempty_iff_ne_empty,
    mem_singleton, and_comm, mem_powerset, exists_prop]
theorem atomise_empty (hs : s.Nonempty) : (atomise s ∅).parts = {s} := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
hs : Finset.Nonempty s
⊢ (atomise s ∅).parts = {s}

Next tactic:
simp only [atomise, powerset_empty, image_singleton, not_mem_empty, IsEmpty.forall_iff,
    imp_true_iff, filter_True]
theorem atomise_empty (hs : s.Nonempty) : (atomise s ∅).parts = {s} := by
  simp only [atomise, powerset_empty, image_singleton, not_mem_empty, IsEmpty.forall_iff,
    imp_true_iff, filter_True]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
hs : Finset.Nonempty s
⊢ (ofErase {s} (_ : SupIndep {s} id) (_ : sup {s} id = s)).parts = {s}

Next tactic:
exact erase_eq_of_not_mem (not_mem_singleton.2 hs.ne_empty.symm)
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
⊢ Finset.biUnion (filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts) id = t

Next tactic:
ext a
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  ext a
  

Proof state:
case a
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a✝ : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
a : α
⊢ a ∈ Finset.biUnion (filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts) id ↔ a ∈ t

Next tactic:
refine' mem_biUnion.trans ⟨fun ⟨u, hu, ha⟩ ↦ (mem_filter.1 hu).2.1 ha, fun ha ↦ _⟩
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  ext a
  refine' mem_biUnion.trans ⟨fun ⟨u, hu, ha⟩ ↦ (mem_filter.1 hu).2.1 ha, fun ha ↦ _⟩
  

Proof state:
case a
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a✝ : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
a : α
ha : a ∈ t
⊢ ∃ a_1 ∈ filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts, a ∈ id a_1

Next tactic:
obtain ⟨u, hu, hau⟩ := (atomise s F).exists_mem (hts ha)
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  ext a
  refine' mem_biUnion.trans ⟨fun ⟨u, hu, ha⟩ ↦ (mem_filter.1 hu).2.1 ha, fun ha ↦ _⟩
  obtain ⟨u, hu, hau⟩ := (atomise s F).exists_mem (hts ha)
  

Proof state:
case a.intro.intro
α : Type u_1
inst✝ : DecidableEq α
s t u✝ : Finset α
P : Finpartition s
a✝ : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
a : α
ha : a ∈ t
u : Finset α
hu : u ∈ (atomise s F).parts
hau : a ∈ u
⊢ ∃ a_1 ∈ filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts, a ∈ id a_1

Next tactic:
refine' ⟨u, mem_filter.2 ⟨hu, fun b hb ↦ _, _, hau⟩, hau⟩
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  ext a
  refine' mem_biUnion.trans ⟨fun ⟨u, hu, ha⟩ ↦ (mem_filter.1 hu).2.1 ha, fun ha ↦ _⟩
  obtain ⟨u, hu, hau⟩ := (atomise s F).exists_mem (hts ha)
  refine' ⟨u, mem_filter.2 ⟨hu, fun b hb ↦ _, _, hau⟩, hau⟩
  

Proof state:
case a.intro.intro
α : Type u_1
inst✝ : DecidableEq α
s t u✝ : Finset α
P : Finpartition s
a✝ : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
a : α
ha : a ∈ t
u : Finset α
hu : u ∈ (atomise s F).parts
hau : a ∈ u
b : α
hb : b ∈ u
⊢ b ∈ t

Next tactic:
obtain ⟨Q, _hQ, rfl⟩ := (mem_atomise.1 hu).2
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  ext a
  refine' mem_biUnion.trans ⟨fun ⟨u, hu, ha⟩ ↦ (mem_filter.1 hu).2.1 ha, fun ha ↦ _⟩
  obtain ⟨u, hu, hau⟩ := (atomise s F).exists_mem (hts ha)
  refine' ⟨u, mem_filter.2 ⟨hu, fun b hb ↦ _, _, hau⟩, hau⟩
  obtain ⟨Q, _hQ, rfl⟩ := (mem_atomise.1 hu).2
  

Proof state:
case a.intro.intro.intro.intro
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a✝ : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
a : α
ha : a ∈ t
b : α
Q : Finset (Finset α)
_hQ : Q ⊆ F
hu : filter (fun i => ∀ u ∈ F, u ∈ Q ↔ i ∈ u) s ∈ (atomise s F).parts
hau : a ∈ filter (fun i => ∀ u ∈ F, u ∈ Q ↔ i ∈ u) s
hb : b ∈ filter (fun i => ∀ u ∈ F, u ∈ Q ↔ i ∈ u) s
⊢ b ∈ t

Next tactic:
rw [mem_filter] at hau hb
theorem biUnion_filter_atomise (ht : t ∈ F) (hts : t ⊆ s) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).biUnion id = t := by
  ext a
  refine' mem_biUnion.trans ⟨fun ⟨u, hu, ha⟩ ↦ (mem_filter.1 hu).2.1 ha, fun ha ↦ _⟩
  obtain ⟨u, hu, hau⟩ := (atomise s F).exists_mem (hts ha)
  refine' ⟨u, mem_filter.2 ⟨hu, fun b hb ↦ _, _, hau⟩, hau⟩
  obtain ⟨Q, _hQ, rfl⟩ := (mem_atomise.1 hu).2
  rw [mem_filter] at hau hb
  

Proof state:
case a.intro.intro.intro.intro
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a✝ : α
F : Finset (Finset α)
ht : t ∈ F
hts : t ⊆ s
a : α
ha : a ∈ t
b : α
Q : Finset (Finset α)
_hQ : Q ⊆ F
hu : filter (fun i => ∀ u ∈ F, u ∈ Q ↔ i ∈ u) s ∈ (atomise s F).parts
hau : a ∈ s ∧ ∀ u ∈ F, u ∈ Q ↔ a ∈ u
hb : b ∈ s ∧ ∀ u ∈ F, u ∈ Q ↔ b ∈ u
⊢ b ∈ t

Next tactic:
rwa [← hb.2 _ ht, hau.2 _ ht]
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
⊢ card (filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts) ≤ 2 ^ (card F - 1)

Next tactic:
suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
h :
  filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts ⊆
    image (fun P => filter (fun i => ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x) s) (powerset (erase F t))
⊢ card (filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts) ≤ 2 ^ (card F - 1)

Next tactic:
refine' (card_le_of_subset h).trans (card_image_le.trans _)
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · refine' (card_le_of_subset h).trans (card_image_le.trans _)
    

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
h :
  filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts ⊆
    image (fun P => filter (fun i => ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x) s) (powerset (erase F t))
⊢ card (powerset (erase F t)) ≤ 2 ^ (card F - 1)

Next tactic:
rw [card_powerset, card_erase_of_mem ht]
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · refine' (card_le_of_subset h).trans (card_image_le.trans _)
    rw [card_powerset, card_erase_of_mem ht]
  

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
⊢ filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts ⊆
    image (fun P => filter (fun i => ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x) s) (powerset (erase F t))

Next tactic:
rw [subset_iff]
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · refine' (card_le_of_subset h).trans (card_image_le.trans _)
    rw [card_powerset, card_erase_of_mem ht]
  rw [subset_iff]
  

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
⊢ ∀ ⦃x : Finset α⦄,
    x ∈ filter (fun u => u ⊆ t ∧ Finset.Nonempty u) (atomise s F).parts →
      x ∈ image (fun P => filter (fun i => ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x) s) (powerset (erase F t))

Next tactic:
simp_rw [mem_image, mem_powerset, mem_filter, and_imp, Finset.Nonempty, exists_imp, mem_atomise,
    and_imp, Finset.Nonempty, exists_imp]
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · refine' (card_le_of_subset h).trans (card_image_le.trans _)
    rw [card_powerset, card_erase_of_mem ht]
  rw [subset_iff]
  simp_rw [mem_image, mem_powerset, mem_filter, and_imp, Finset.Nonempty, exists_imp, mem_atomise,
    and_imp, Finset.Nonempty, exists_imp]
  

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
⊢ ∀ ⦃x : Finset α⦄,
    ∀ x_1 ∈ x,
      ∀ x_2 ⊆ F,
        filter (fun i => ∀ u ∈ F, u ∈ x_2 ↔ i ∈ u) s = x →
          x ⊆ t → ∀ x_4 ∈ x, ∃ a ⊆ erase F t, filter (fun i => ∀ x ∈ F, x ∈ insert t a ↔ i ∈ x) s = x

Next tactic:
rintro P' i hi P PQ rfl hy₂ j _hj
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · refine' (card_le_of_subset h).trans (card_image_le.trans _)
    rw [card_powerset, card_erase_of_mem ht]
  rw [subset_iff]
  simp_rw [mem_image, mem_powerset, mem_filter, and_imp, Finset.Nonempty, exists_imp, mem_atomise,
    and_imp, Finset.Nonempty, exists_imp]
  rintro P' i hi P PQ rfl hy₂ j _hj
  

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P✝ : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
i : α
P : Finset (Finset α)
PQ : P ⊆ F
hi : i ∈ filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s
hy₂ : filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s ⊆ t
j : α
_hj : j ∈ filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s
⊢ ∃ a ⊆ erase F t, filter (fun i => ∀ x ∈ F, x ∈ insert t a ↔ i ∈ x) s = filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s

Next tactic:
refine' ⟨P.erase t, erase_subset_erase _ PQ, _⟩
theorem card_filter_atomise_le_two_pow (ht : t ∈ F) :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty).card ≤ 2 ^ (F.card - 1) := by
  suffices h :
    ((atomise s F).parts.filter fun u ↦ u ⊆ t ∧ u.Nonempty) ⊆
      (F.erase t).powerset.image fun P ↦ s.filter fun i ↦ ∀ x ∈ F, x ∈ insert t P ↔ i ∈ x
  · refine' (card_le_of_subset h).trans (card_image_le.trans _)
    rw [card_powerset, card_erase_of_mem ht]
  rw [subset_iff]
  simp_rw [mem_image, mem_powerset, mem_filter, and_imp, Finset.Nonempty, exists_imp, mem_atomise,
    and_imp, Finset.Nonempty, exists_imp]
  rintro P' i hi P PQ rfl hy₂ j _hj
  refine' ⟨P.erase t, erase_subset_erase _ PQ, _⟩
  

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
s t u : Finset α
P✝ : Finpartition s
a : α
F : Finset (Finset α)
ht : t ∈ F
i : α
P : Finset (Finset α)
PQ : P ⊆ F
hi : i ∈ filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s
hy₂ : filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s ⊆ t
j : α
_hj : j ∈ filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s
⊢ filter (fun i => ∀ x ∈ F, x ∈ insert t (erase P t) ↔ i ∈ x) s = filter (fun i => ∀ u ∈ F, u ∈ P ↔ i ∈ u) s

Next tactic:
simp only [insert_erase (((mem_filter.1 hi).2 _ ht).2 <| hy₂ hi)]
/-- Product of a multiset given a commutative monoid structure on `α`.
  `prod {a, b, c} = a * b * c` -/
@[to_additive
      "Sum of a multiset given a commutative additive monoid structure on `α`.
      `sum {a, b, c} = a + b + c`"]
def prod : Multiset α → α :=
  foldr (· * ·) (fun x y z => by 

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s t : Multiset α
a : α
m : Multiset ι
f g : ι → α
x y z : α
⊢ (fun x x_1 => x * x_1) x ((fun x x_1 => x * x_1) y z) = (fun x x_1 => x * x_1) y ((fun x x_1 => x * x_1) x z)

Next tactic:
simp [mul_left_comm]
@[to_additive]
theorem prod_eq_foldr (s : Multiset α) :
    prod s = foldr (· * ·) (fun x y z => by 

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s✝ t : Multiset α
a : α
m : Multiset ι
f g : ι → α
s : Multiset α
x y z : α
⊢ (fun x x_1 => x * x_1) x ((fun x x_1 => x * x_1) y z) = (fun x x_1 => x * x_1) y ((fun x x_1 => x * x_1) x z)

Next tactic:
simp [mul_left_comm]
@[to_additive]
theorem prod_eq_foldl (s : Multiset α) :
    prod s = foldl (· * ·) (fun x y z => by 

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s✝ t : Multiset α
a : α
m : Multiset ι
f g : ι → α
s : Multiset α
x y z : α
⊢ (fun x x_1 => x * x_1) ((fun x x_1 => x * x_1) x y) z = (fun x x_1 => x * x_1) ((fun x x_1 => x * x_1) x z) y

Next tactic:
simp [mul_right_comm]
@[to_additive]
theorem prod_eq_foldl (s : Multiset α) :
    prod s = foldl (· * ·) (fun x y z => by simp [mul_right_comm]) 1 s :=
  (foldr_swap _ _ _ _).trans (by 

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s✝ t : Multiset α
a : α
m : Multiset ι
f g : ι → α
s : Multiset α
⊢ foldl (fun x y => y * x) (_ : ∀ (_x _y _z : α), _z * (_y * _x) = _y * (_z * _x)) 1 s =
    foldl (fun x x_1 => x * x_1) (_ : ∀ (x y z : α), x * y * z = x * z * y) 1 s

Next tactic:
simp [mul_comm]
@[to_additive (attr := simp)]
theorem prod_toList (s : Multiset α) : s.toList.prod = s.prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s✝ t : Multiset α
a : α
m : Multiset ι
f g : ι → α
s : Multiset α
⊢ List.prod (toList s) = prod s

Next tactic:
conv_rhs => rw [← coe_toList s]
@[to_additive (attr := simp)]
theorem prod_toList (s : Multiset α) : s.toList.prod = s.prod := by
  conv_rhs => 

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s✝ t : Multiset α
a : α
m : Multiset ι
f g : ι → α
s : Multiset α
| prod s

Next tactic:
rw [← coe_toList s]
@[to_additive (attr := simp)]
theorem prod_toList (s : Multiset α) : s.toList.prod = s.prod := by
  conv_rhs => rw [← coe_toList s]
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : CommMonoid α
s✝ t : Multiset α
a : α
m : Multiset ι
f g : ι → α
s : Multiset α
⊢ List.prod (toList s) = prod ↑(toList s)

Next tactic:
rw [coe_prod]
@[to_additive (attr := simp)]
theorem prod_erase [DecidableEq α] (h : a ∈ s) : a * (s.erase a).prod = s.prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝¹ : CommMonoid α
s t : Multiset α
a : α
m : Multiset ι
f g : ι → α
inst✝ : DecidableEq α
h : a ∈ s
⊢ a * prod (erase s a) = prod s

Next tactic:
rw [← s.coe_toList, coe_erase, coe_prod, coe_prod, List.prod_erase (mem_toList.2 h)]
@[to_additive (attr := simp)]
theorem prod_map_erase [DecidableEq ι] {a : ι} (h : a ∈ m) :
    f a * ((m.erase a).map f).prod = (m.map f).prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝¹ : CommMonoid α
s t : Multiset α
a✝ : α
m : Multiset ι
f g : ι → α
inst✝ : DecidableEq ι
a : ι
h : a ∈ m
⊢ f a * prod (map f (erase m a)) = prod (map f m)

Next tactic:
rw [← m.coe_toList, coe_erase, coe_map, coe_map, coe_prod, coe_prod,
    List.prod_map_erase f (mem_toList.2 h)]