Skip to content

Commit 03cc2f9

Browse files
feat(Data): lemmas for List.bagInter (#35892)
Basic API lemmas for `List.bagInter` and correct a few misnamed lemmas. Co-authored-by: Aristotle (Harmonic) <aristotle-harmonic@harmonic.fun>
1 parent 5961646 commit 03cc2f9

3 files changed

Lines changed: 66 additions & 5 deletions

File tree

Mathlib/Data/List/Lattice.lean

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ theorem inter_reverse {xs ys : List α} : xs ∩ ys.reverse = xs ∩ ys := by
157157
theorem Subset.inter_eq_left {xs ys : List α} (h : xs ⊆ ys) : xs ∩ ys = xs :=
158158
List.filter_eq_self.mpr fun _ ha => elem_eq_true_of_mem (h ha)
159159

160+
theorem Sublist.inter_left {l₁ l₂ l₃ : List α} (h : l₂.Sublist l₃) :
161+
(l₁ ∩ l₂).Sublist (l₁ ∩ l₃) := by
162+
grind [inter_def, monotone_filter_right]
163+
164+
theorem Sublist.inter_right {l₁ l₂ l₃ : List α} (h : l₁.Sublist l₂) :
165+
(l₁ ∩ l₃).Sublist (l₂ ∩ l₃) := by
166+
grind [inter_def]
167+
160168
end Inter
161169

162170
/-! ### `bagInter` -/
@@ -171,20 +179,34 @@ theorem nil_bagInter (l : List α) : [].bagInter l = [] := by cases l <;> rfl
171179
theorem bagInter_nil (l : List α) : l.bagInter [] = [] := by cases l <;> rfl
172180

173181
@[simp]
174-
theorem cons_bagInter_of_pos (l₁ : List α) (h : a ∈ l₂) :
182+
theorem cons_bagInter_of_mem (l₁ : List α) (h : a ∈ l₂) :
175183
(a :: l₁).bagInter l₂ = a :: l₁.bagInter (l₂.erase a) := by
176184
cases l₂ with grind [List.bagInter]
177185

186+
@[deprecated (since := "2026-05-13")]
187+
alias cons_bagInter_of_pos := cons_bagInter_of_mem
188+
178189
@[simp]
179-
theorem cons_bagInter_of_neg (l₁ : List α) (h : a ∉ l₂) :
190+
theorem cons_bagInter_of_not_mem (l₁ : List α) (h : a ∉ l₂) :
180191
(a :: l₁).bagInter l₂ = l₁.bagInter l₂ := by
181192
cases l₂ with grind [List.bagInter]
182193

194+
@[deprecated (since := "2026-05-13")]
195+
alias cons_bagInter_of_neg := cons_bagInter_of_not_mem
196+
183197
@[grind =]
184-
theorem cons_bagInteger :
198+
theorem cons_bagInter :
185199
(a :: l₁).bagInter l₂ = if a ∈ l₂ then a :: l₁.bagInter (l₂.erase a) else l₁.bagInter l₂ := by
186200
split_ifs <;> simp_all
187201

202+
@[deprecated (since := "2026-05-13")]
203+
alias cons_bagInteger := cons_bagInter
204+
205+
@[simp]
206+
theorem bagInter_cons_of_not_mem (l₂ : List α) (h : a ∉ l₁) :
207+
l₁.bagInter (a :: l₂) = l₁.bagInter l₂ := by
208+
induction l₁ generalizing l₂ <;> grind
209+
188210
@[simp]
189211
theorem mem_bagInter {a : α} {l₁ l₂ : List α} : a ∈ l₁.bagInter l₂ ↔ a ∈ l₁ ∧ a ∈ l₂ := by
190212
fun_induction List.bagInter with grind
@@ -197,13 +219,49 @@ theorem count_bagInter {a : α} {l₁ l₂ : List α} :
197219
theorem bagInter_sublist_left {l₁ l₂ : List α} : l₁.bagInter l₂ <+ l₁ := by
198220
fun_induction List.bagInter with grind
199221

222+
theorem singleton_bagInter (a : α) : [a].bagInter l₁ = if a ∈ l₁ then [a] else [] := by
223+
grind
224+
225+
theorem bagInter_singleton (a : α) : l₁.bagInter [a] = if a ∈ l₁ then [a] else [] := by
226+
induction l₁ <;> grind
227+
228+
@[simp]
229+
theorem bagInter_erase_of_not_mem (h : a ∉ l₁) :
230+
l₁.bagInter (l₂.erase a) = l₁.bagInter l₂ := by
231+
induction l₁ generalizing l₂ <;> grind
232+
233+
@[simp]
234+
theorem erase_bagInter_of_not_mem (h : a ∉ l₂) :
235+
(l₁.erase a).bagInter l₂ = l₁.bagInter l₂ := by
236+
induction l₁ generalizing l₂ <;> grind
237+
200238
theorem bagInter_nil_iff_inter_nil : ∀ l₁ l₂ : List α, l₁.bagInter l₂ = [] ↔ l₁ ∩ l₂ = []
201239
| [], l₂ => by simp
202240
| b :: l₁, l₂ => by
203241
by_cases h : b ∈ l₂
204242
· simp [h]
205243
· simpa [h] using bagInter_nil_iff_inter_nil l₁ l₂
206244

245+
@[simp]
246+
theorem bagInter_eq_nil_iff_disjoint : l₁.bagInter l₂ = [] ↔ l₁.Disjoint l₂ :=
247+
(bagInter_nil_iff_inter_nil _ _).trans inter_eq_nil_iff_disjoint
248+
249+
theorem Nodup.bagInter_right (h : l₁.Nodup) : (l₁.bagInter l₂).Nodup :=
250+
nodup_iff_count.mpr fun x ↦ (by grind [List.count_bagInter])
251+
252+
theorem Nodup.bagInter_left (h : l₂.Nodup) : (l₁.bagInter l₂).Nodup :=
253+
nodup_iff_count.mpr fun x ↦ (by grind [List.count_bagInter])
254+
255+
theorem Sublist.bagInter_inter : (l₁.bagInter l₂).Sublist (l₁ ∩ l₂) := by
256+
induction l₁ generalizing l₂ with
257+
| nil => simp
258+
| cons _ _ ih =>
259+
rw [cons_bagInter]
260+
split
261+
· rw [inter_cons_of_mem _ (by assumption), cons_sublist_cons]
262+
exact ih.trans <| Sublist.inter_left (by grind [erase_sublist])
263+
· simp_all
264+
207265
end BagInter
208266

209267
end List

Mathlib/Data/List/Perm/Lattice.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ theorem Perm.bagInter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t
4545
l₁.bagInter t₁ ~ l₂.bagInter t₂ :=
4646
ht.bagInter_left l₂ ▸ hl.bagInter_right _
4747

48+
theorem Perm.bagInter_symm (l₁ l₂ : List α) : (l₁.bagInter l₂).Perm (l₂.bagInter l₁) :=
49+
perm_iff_count.mpr fun _ ↦ (by simp [List.count_bagInter, Nat.min_comm])
50+
4851
theorem Perm.inter_append {l t₁ t₂ : List α} (h : Disjoint t₁ t₂) :
4952
l ∩ (t₁ ++ t₂) ~ l ∩ t₁ ++ l ∩ t₂ := by
5053
induction l with

Mathlib/Data/Multiset/UnionInter.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ instance : Inter (Multiset α) := ⟨inter⟩
9999

100100
@[simp]
101101
lemma cons_inter_of_pos (s : Multiset α) : a ∈ t → (a ::ₘ s) ∩ t = a ::ₘ s ∩ t.erase a :=
102-
Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_pos _ h
102+
Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_mem _ h
103103

104104
@[simp]
105105
lemma cons_inter_of_neg (s : Multiset α) : a ∉ t → (a ::ₘ s) ∩ t = s ∩ t :=
106-
Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_neg _ h
106+
Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_not_mem _ h
107107

108108
lemma inter_le_left : s ∩ t ≤ s :=
109109
Quotient.inductionOn₂ s t fun _l₁ _l₂ => bagInter_sublist_left.subperm

0 commit comments

Comments
 (0)