Skip to content
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c06e1ed
initial commit
wkrozowski Oct 22, 2025
d618357
Add wellformedness
wkrozowski Oct 22, 2025
441b175
Pre-meeting push
wkrozowski Oct 22, 2025
7ba7184
union now works
wkrozowski Oct 22, 2025
54bb235
`toListModel_union_list` is working now
wkrozowski Oct 22, 2025
45d9caf
First lemmas are working
wkrozowski Oct 22, 2025
d909f30
Add Equiv lemmas
wkrozowski Oct 22, 2025
4723ef0
Add all non const lemmas
wkrozowski Oct 22, 2025
cd91c44
Add const lemmas
wkrozowski Oct 22, 2025
9261691
Add `union!`
wkrozowski Oct 23, 2025
6a00a89
Progress on lemmas
wkrozowski Oct 23, 2025
360fa81
Add lemmas about the slow versions
wkrozowski Oct 23, 2025
1155757
Add remaining const lemmas
wkrozowski Oct 23, 2025
1dc3989
Add non-const raw lemmas
wkrozowski Oct 23, 2025
9ff0d11
Add const raw lemmas
wkrozowski Oct 23, 2025
3a5a5db
Add non-const DTreeMap lemmas
wkrozowski Oct 23, 2025
c776f95
chore: add const DTreeMap lemmas
wkrozowski Oct 23, 2025
d548a45
Add Raw TreeMap lemmas
wkrozowski Oct 23, 2025
39dcf79
Add union on TreeMaps
wkrozowski Oct 23, 2025
51c99f3
chore: add TreeMap union lemmas
wkrozowski Oct 23, 2025
31dcd02
Add Raw lemmas for TreeSet
wkrozowski Oct 24, 2025
095490e
Add HashSet lemmas
wkrozowski Oct 24, 2025
4e9d7dc
chore: remove deprecated lemma usage
wkrozowski Oct 24, 2025
677875c
Update src/Std/Data/DTreeMap/Internal/Lemmas.lean
wkrozowski Oct 30, 2025
7b4616b
Update src/Std/Data/DTreeMap/Internal/Lemmas.lean
wkrozowski Oct 30, 2025
c3bb38b
Update src/Std/Data/TreeSet/Lemmas.lean
wkrozowski Oct 30, 2025
0508b5d
Update src/Std/Data/TreeSet/Lemmas.lean
wkrozowski Oct 30, 2025
0371fb3
Update src/Std/Data/TreeSet/Lemmas.lean
wkrozowski Oct 30, 2025
e1736e9
Update src/Std/Data/TreeMap/Lemmas.lean
wkrozowski Oct 30, 2025
58d3780
Update src/Std/Data/DTreeMap/Internal/Lemmas.lean
wkrozowski Oct 30, 2025
a856464
Update src/Std/Data/DTreeMap/Internal/Lemmas.lean
wkrozowski Oct 30, 2025
5de79d5
Update src/Std/Data/DTreeMap/Raw/Basic.lean
wkrozowski Oct 30, 2025
ecf687b
Update src/Std/Data/DTreeMap/Basic.lean
wkrozowski Oct 30, 2025
25a2051
Update src/Std/Data/DTreeMap/Internal/Operations.lean
wkrozowski Oct 30, 2025
d4210d5
Update src/Std/Data/DTreeMap/Lemmas.lean
wkrozowski Oct 30, 2025
2f5028e
Update src/Std/Data/TreeMap/Lemmas.lean
wkrozowski Oct 30, 2025
dbd6020
Update src/Std/Data/TreeMap/Lemmas.lean
wkrozowski Oct 30, 2025
65a8dfb
Respond to Paul's comments
wkrozowski Oct 30, 2025
76328c7
fix docstring
wkrozowski Oct 30, 2025
1a2830d
chore: fix names for (D)DTreeMap equiv lemma
wkrozowski Nov 3, 2025
8b52b63
Deprecate `union_insert_right_equiv_union_insert`
wkrozowski Nov 3, 2025
5e61ae5
Add depreciation tag
wkrozowski Nov 3, 2025
899d24c
Remove unnecessary lemma
wkrozowski Nov 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/Std/Data/DTreeMap/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,25 @@ appearance.
def insertMany {ρ} [ForIn Id ρ ((a : α) × β a)] (t : DTreeMap α β cmp) (l : ρ) : DTreeMap α β cmp :=
letI : Ord α := ⟨cmp⟩; ⟨t.inner.insertMany l t.wf.balanced, t.wf.insertMany⟩

/--
Inserts multiple mappings into the tree map by iterating over the given collection and calling
`insertIfNew`. If the same key appears multiple times, the first occurrence takes precedence.
-/
@[inline]
def insertManyIfNew {ρ} [ForIn Id ρ ((a : α) × β a)] (t : DTreeMap α β cmp) (l : ρ) : DTreeMap α β cmp :=
letI : Ord α := ⟨cmp⟩; ⟨t.inner.insertManyIfNew l t.wf.balanced, t.wf.insertManyIfNew⟩

/--
Computes the union of the given tree maps. If a key appears in both maps, the entry contained in
the second argument will appear in the result.

This function always merges the smaller map into the larger map.
-/
def union (t₁ t₂ : DTreeMap α β cmp) : DTreeMap α β cmp :=
letI : Ord α := ⟨cmp⟩; ⟨t₁.inner.union t₂.inner t₁.wf.balanced t₂.wf.balanced, @Impl.WF.union α β _ t₁.inner t₁.wf t₂.inner t₂.wf⟩

instance : Union (DTreeMap α β cmp) := ⟨union⟩

/--
Erases multiple mappings from the tree map by iterating over the given collection and calling
`erase`.
Expand Down
780 changes: 779 additions & 1 deletion src/Std/Data/DTreeMap/Internal/Lemmas.lean

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions src/Std/Data/DTreeMap/Internal/Operations.lean
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ def eraseMany! [Ord α] {ρ : Type w} [ForIn Id ρ α] (t : Impl α β) (l : ρ)
abbrev IteratedInsertionInto [Ord α] (t) :=
{ t' // ∀ {P : Impl α β → Prop}, P t → (∀ t'' a b h, P t'' → P (t''.insert a b h).impl) → P t' }

/-- A tree map obtained by inserting elements into `t` if they are new, bundled with an inductive principle. -/
abbrev IteratedNewInsertionInto [Ord α] (t) :=
{ t' // ∀ {P : Impl α β → Prop}, P t → (∀ t'' a b h, P t'' → P (t''.insertIfNew a b h).impl) → P t' }

/-- Iterate over `l` and insert all of its elements into `t`. -/
@[inline]
def insertMany [Ord α] {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] (t : Impl α β) (l : ρ) (h : t.Balanced) :
Expand All @@ -495,10 +499,32 @@ def insertMany [Ord α] {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] (t : Impl
r := ⟨r.val.insert a b hr |>.impl, fun h₀ h₁ => h₁ _ _ _ _ (r.2 h₀ h₁)⟩
return r

/-- Iterate over `l` and insert all of its elements into `t` if they are new. -/
@[inline]
def insertManyIfNew [Ord α] {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] (t : Impl α β) (l : ρ) (h : t.Balanced) :
IteratedNewInsertionInto t := Id.run do
let mut r := ⟨t, fun h _ => h⟩
for ⟨a, b⟩ in l do
let hr := r.2 h (fun t'' a b h _ => (t''.insertIfNew a b h).balanced_impl)
r := ⟨r.val.insertIfNew a b hr |>.impl, fun h₀ h₁ => h₁ _ _ _ _ (r.2 h₀ h₁)⟩
return r

/-- A tree map obtained by inserting elements into `t`, bundled with an inductive principle. -/
abbrev IteratedSlowInsertionInto [Ord α] (t) :=
{ t' // ∀ {P : Impl α β → Prop}, P t → (∀ t'' a b, P t'' → P (t''.insert! a b)) → P t' }

/-- A tree map obtained by inserting elements into `t` if they are new, bundled with an inductive principle. -/
abbrev IteratedSlowNewInsertionInto [Ord α] (t) :=
{ t' // ∀ {P : Impl α β → Prop}, P t → (∀ t'' a b, P t'' → P (t''.insertIfNew! a b)) → P t' }

/--
Computes the union of the given tree maps. If a key appears in both maps, the entry contained in the second argument will appear in the result.

This function always merges the smaller map into the larger map.
-/
def union [Ord α] (t₁ t₂ : Impl α β) (h₁ : t₁.Balanced) (h₂ : t₂.Balanced) : Impl α β :=
if t₁.size ≤ t₂.size then (t₂.insertManyIfNew t₁ h₂) else (t₁.insertMany t₂ h₁)

/--
Slower version of `insertMany` which can be used in absence of balance information but still
assumes the preconditions of `insertMany`, otherwise might panic.
Expand All @@ -511,6 +537,24 @@ def insertMany! [Ord α] {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] (t : Imp
r := ⟨r.val.insert! a b, fun h₀ h₁ => h₁ _ _ _ (r.2 h₀ h₁)⟩
return r

/--
Slower version of `insertManyIfNew` which can be used in absence of balance information but still
assumes the preconditions of `insertManyIfNew`, otherwise might panic.
-/
@[inline]
def insertManyIfNew! [Ord α] {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] (t : Impl α β) (l : ρ) :
IteratedSlowNewInsertionInto t := Id.run do
let mut r := ⟨t, fun h _ => h⟩
for ⟨a, b⟩ in l do
r := ⟨r.val.insertIfNew! a b, fun h₀ h₁ => h₁ _ _ _ (r.2 h₀ h₁)⟩
return r

/--
Slower version of `union` which can be used in absence of balance information but still assumes the preconditions of `union`, otherwise might panic.
-/
def union! [Ord α] (t₁ t₂ : Impl α β) : Impl α β :=
if t₁.size ≤ t₂.size then (t₂.insertManyIfNew! t₁) else (t₁.insertMany! t₂)

namespace Const

variable {β : Type v}
Expand Down
3 changes: 3 additions & 0 deletions src/Std/Data/DTreeMap/Internal/Queries.lean
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ def forIn {m} [Monad m] (f : (a : α) → β a → δ → m (ForInStep δ)) (ini
| ForInStep.done d => return d
| ForInStep.yield d => return d

instance : ForIn m (Impl α β) ((a : α) × β a) where
forIn m init f := m.forIn (fun a b acc => f ⟨a, b⟩ acc) init

/-- Returns a `List` of the keys in order. -/
@[inline] def keys (t : Impl α β) : List α :=
t.foldr (init := []) fun k _ l => k :: l
Expand Down
11 changes: 11 additions & 0 deletions src/Std/Data/DTreeMap/Internal/WF/Defs.lean
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ theorem WF.insertMany [Ord α] {ρ} [ForIn Id ρ ((a : α) × β a)] {t : Impl
WF (t.insertMany l h).val :=
(t.insertMany l h).2 hwf fun _ _ _ _ hwf' => hwf'.insert

theorem WF.insertManyIfNew [Ord α] {ρ} [ForIn Id ρ ((a : α) × β a)] {t : Impl α β} {l : ρ} {h} (hwf : WF t) :
WF (t.insertManyIfNew l h).val :=
(t.insertManyIfNew l h).2 hwf fun _ _ _ _ hwf' => hwf'.insertIfNew

theorem WF.constInsertMany [Ord α] {β : Type v} {ρ} [ForIn Id ρ (α × β)] {t : Impl α (fun _ => β)}
{l : ρ} {h} (hwf : WF t) : WF (Impl.Const.insertMany t l h).val :=
(Impl.Const.insertMany t l h).2 hwf fun _ _ _ _ hwf' => hwf'.insert
Expand All @@ -96,6 +100,13 @@ theorem WF.getThenInsertIfNew? [Ord α] [LawfulEqOrd α] {t : Impl α β} {k v}
· exact h.insertIfNew
· exact h

theorem WF.union [Ord α] {t₁ : Impl α β} {h₁ : t₁.WF} {t₂ : Impl α β} {h₂ : t₂.WF} :
(t₁.union t₂ h₁.balanced h₂.balanced).WF := by
simp [Impl.union]
split
. apply WF.insertManyIfNew h₂
. apply WF.insertMany h₁

section Const

variable {β : Type v}
Expand Down
132 changes: 132 additions & 0 deletions src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1580,11 +1580,70 @@ theorem insertMany_eq_foldl {_ : Ord α} {l : List ((a : α) × β a)} {t : Impl
(t.insertMany l h).val = l.foldl (init := t) fun acc ⟨k, v⟩ => acc.insert! k v := by
simp [insertMany, insert_eq_insert!, ← List.foldl_hom Subtype.val, List.forIn_pure_yield_eq_foldl]

theorem insertMany_eq_foldl_impl {_ : Ord α} {t₁ : Impl α β} (h₁ : t₁.Balanced) {t₂ : Impl α β}:
(t₁.insertMany t₂ h₁).val = t₂.foldl (init := t₁) fun acc k v => acc.insert! k v := by
simp [foldl_eq_foldl]
rw [← insertMany_eq_foldl]
rotate_left
. exact h₁
. simp only [insertMany, pure, ForIn.forIn, Id.run_bind]
rw [forIn_eq_forIn_toListModel]
congr

theorem insertMany!_eq_foldl_impl {_ : Ord α} {t₁ : Impl α β} {t₂ : Impl α β}:
(t₁.insertMany! t₂).val = t₂.foldl (init := t₁) fun acc k v => acc.insert! k v := by
simp [foldl_eq_foldl]
rw [← insertMany!_eq_foldl]
simp only [insertMany!, pure, ForIn.forIn, Id.run_bind]
rw [forIn_eq_forIn_toListModel]
congr

theorem insertManyIfNew_eq_foldl {_ : Ord α} {l : List ((a : α) × β a)} {t : Impl α β} (h : t.Balanced) :
(t.insertManyIfNew l h).val = l.foldl (init := t) fun acc ⟨k, v⟩ => acc.insertIfNew! k v := by
simp [insertManyIfNew, insertIfNew_eq_insertIfNew!, ← List.foldl_hom Subtype.val, List.forIn_pure_yield_eq_foldl]

theorem insertManyIfNew!_eq_foldl {_ : Ord α} {l : List ((a : α) × β a)} {t : Impl α β} :
(t.insertManyIfNew! l).val = l.foldl (init := t) fun acc ⟨k, v⟩ => acc.insertIfNew! k v := by
simp [insertManyIfNew!, ← List.foldl_hom Subtype.val, List.forIn_pure_yield_eq_foldl]

theorem insertManyIfNew_eq_foldl_impl {_ : Ord α} {t₁ : Impl α β} (h₁ : t₁.Balanced) {t₂ : Impl α β} :
(t₁.insertManyIfNew t₂ h₁).val = t₂.foldl (init := t₁) fun acc k v => acc.insertIfNew! k v := by
simp [foldl_eq_foldl]
rw [← insertManyIfNew_eq_foldl]
rotate_left
. exact h₁
. simp only [insertManyIfNew, ForIn.forIn, pure, Id.run_bind]
rw [forIn_eq_forIn_toListModel]
congr

theorem insertManyIfNew!_eq_foldl_impl {_ : Ord α} {t₁ : Impl α β} {t₂ : Impl α β}:
(t₁.insertManyIfNew! t₂).val = t₂.foldl (init := t₁) fun acc k v => acc.insertIfNew! k v := by
simp [foldl_eq_foldl]
rw [← insertManyIfNew!_eq_foldl]
simp only [insertManyIfNew!, ForIn.forIn, pure, Id.run_bind]
rw [forIn_eq_forIn_toListModel]
congr

theorem insertMany_eq_insertMany! {_ : Ord α} {l : List ((a : α) × β a)}
{t : Impl α β} (h : t.Balanced) :
(t.insertMany l h).val = (t.insertMany! l).val := by
simp only [insertMany_eq_foldl, insertMany!_eq_foldl]

theorem insertMany_eq_insertMany!_impl {_ : Ord α}
{t₁ t₂: Impl α β} (h : t₁.Balanced) :
(t₁.insertMany t₂ h).val = (t₁.insertMany! t₂).val := by
simp only [insertMany_eq_foldl_impl, insertMany!_eq_foldl_impl]

theorem insertManyIfNew_eq_insertManyIfNew! {_ : Ord α} {l : List ((a : α) × β a)}
{t : Impl α β} (h : t.Balanced) :
(t.insertMany l h).val = (t.insertMany! l).val := by
simp only [insertMany_eq_foldl, insertMany!_eq_foldl]

theorem insertManyIfNew_eq_insertManyIfNew!_impl {_ : Ord α}
{t₁ t₂ : Impl α β} (h : t₁.Balanced) :
(t₁.insertManyIfNew t₂ h).val = (t₁.insertManyIfNew! t₂).val := by
simp only [insertManyIfNew_eq_foldl_impl, insertManyIfNew!_eq_foldl_impl]

theorem toListModel_insertMany_list {_ : Ord α} [BEq α] [LawfulBEqOrd α] [TransOrd α]
{l : List ((a : α) × β a)}
{t : Impl α β} (h : t.WF) :
Expand All @@ -1597,6 +1656,68 @@ theorem toListModel_insertMany_list {_ : Ord α} [BEq α] [LawfulBEqOrd α] [Tra
exact insertList_perm_of_perm_first (toListModel_insert! h.balanced h.ordered)
h.insert!.ordered.distinctKeys

theorem toListModel_insertMany_impl {_ : Ord α} [BEq α] [LawfulBEqOrd α] [TransOrd α]
{t₁ : Impl α β} (h₁ : t₁.WF) {t₂ : Impl α β} :
List.Perm (t₁.insertMany t₂ h₁.balanced).val.toListModel (t₁.toListModel.insertList t₂.toListModel) := by
rw [insertMany_eq_foldl_impl]
rw [foldl_eq_foldl]
induction t₂.toListModel generalizing t₁ with
| nil => rfl
| cons e es ih =>
simp only [insertList, List.foldl_cons]
apply List.Perm.trans (@ih (t₁.insert! e.1 e.2) (h₁.insert!))
apply insertList_perm_of_perm_first
. apply toListModel_insert!
. exact h₁.balanced
. exact h₁.ordered
. apply h₁.insert!.ordered.distinctKeys

theorem toListModel_insertManyIfNew_impl {_ : Ord α} [BEq α] [LawfulBEqOrd α] [TransOrd α]
{t₁ : Impl α β} (h₁ : t₁.WF) {t₂ : Impl α β} :
List.Perm (t₁.insertManyIfNew t₂ h₁.balanced).val.toListModel (t₁.toListModel.insertListIfNew t₂.toListModel) := by
rw [insertManyIfNew_eq_foldl_impl]
rw [foldl_eq_foldl]
induction t₂.toListModel generalizing t₁ with
| nil => rfl
| cons e es ih =>
simp only [insertListIfNew, List.foldl_cons]
apply List.Perm.trans (@ih (t₁.insertIfNew! e.1 e.2) (h₁.insertIfNew!))
apply insertListIfNew_perm_of_perm_first
. apply toListModel_insertIfNew!
. exact h₁.balanced
. exact h₁.ordered
. apply h₁.insertIfNew!.ordered.distinctKeys

theorem toListModel_insertManyIfNew_list {_ : Ord α} [BEq α] [LawfulBEqOrd α] [TransOrd α]
{l : List ((a : α) × β a)}
{t : Impl α β} (h : t.WF) :
List.Perm (t.insertManyIfNew l h.balanced).val.toListModel (t.toListModel.insertListIfNew l) := by
simp only [insertManyIfNew_eq_foldl]
induction l generalizing t with
| nil => rfl
| cons e es ih =>
refine (ih h.insertIfNew!).trans ?_
exact insertListIfNew_perm_of_perm_first (toListModel_insertIfNew! h.balanced h.ordered)
h.insertIfNew!.ordered.distinctKeys

theorem toListModel_union_list {_ : Ord α} [BEq α] [LawfulBEqOrd α] [TransOrd α]
{t₁ t₂ : Impl α β} (h₁ : t₁.WF) (h₂ : t₂.WF) :
List.Perm (t₁.union t₂ h₁.balanced h₂.balanced).toListModel (t₁.toListModel.insertList t₂.toListModel) := by
unfold union
split
. apply List.Perm.trans
. apply toListModel_insertManyIfNew_impl h₂
. apply List.insertListIfNew_perm_insertList h₂.ordered.distinctKeys h₁.ordered.distinctKeys
. apply toListModel_insertMany_impl h₁

theorem union_eq_union! [Ord α]
{t₁ t₂ : Impl α β} (h₁ : t₁.WF) (h₂ : t₂.WF) :
(t₁.union t₂ h₁.balanced h₂.balanced) = t₁.union! t₂ := by
simp [union, union!]
split
. apply insertManyIfNew_eq_insertManyIfNew!_impl
. apply insertMany_eq_insertMany!_impl

theorem toListModel_insertMany!_list {_ : Ord α} [TransOrd α] [BEq α] [LawfulBEqOrd α]
{l : List ((a : α) × β a)} {t : Impl α β} (h : t.WF) :
List.Perm (t.insertMany! l).val.toListModel (t.toListModel.insertList l) := by
Expand All @@ -1606,6 +1727,17 @@ theorem WF.insertMany! {_ : Ord α} [TransOrd α] {ρ} [ForIn Id ρ ((a : α) ×
{t : Impl α β} (h : t.WF) : (t.insertMany! l).1.WF :=
(t.insertMany! l).2 h (fun _ _ _ h' => h'.insert!)

theorem WF.insertManyIfNew! {_ : Ord α} [TransOrd α] {ρ} [ForIn Id ρ ((a : α) × β a)] {l : ρ}
{t : Impl α β} (h : t.WF) : (t.insertManyIfNew! l).1.WF :=
(t.insertManyIfNew! l).2 h (fun _ _ _ h' => h'.insertIfNew!)

theorem WF.union! {_ : Ord α} [TransOrd α]
{t₁ : Impl α β} (h₁ : t₁.WF) {t₂ : Impl α β} (h₂ : t₂.WF) : (t₁.union! t₂).WF := by
simp [Impl.union!]
split
. exact WF.insertManyIfNew! h₂
. exact WF.insertMany! h₁

theorem WF.constInsertMany! {β : Type v} {_ : Ord α} [TransOrd α] {ρ} [ForIn Id ρ (α × β)] {l : ρ}
{t : Impl α β} (h : t.WF) : (Const.insertMany! t l).1.WF :=
(Const.insertMany! t l).2 h (fun _ _ _ h' => h'.insert!)
Expand Down
Loading
Loading