From 0a96b4cf72402350591cd0b7339946250a7febda Mon Sep 17 00:00:00 2001 From: Paul Reichert <6992158+datokrat@users.noreply.github.com> Date: Mon, 24 Mar 2025 14:08:19 +0100 Subject: [PATCH] feat: tree map lemmas for minKey (#7660) This PR provides lemmas for the tree map function `minKey` and its interations with other functions for which lemmas already exist. --------- Co-authored-by: Paul Reichert --- src/Std/Data/DTreeMap/Internal/Lemmas.lean | 165 +++++++++++++- src/Std/Data/DTreeMap/Internal/Model.lean | 11 + src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean | 5 + src/Std/Data/DTreeMap/Lemmas.lean | 153 +++++++++++++ src/Std/Data/DTreeMap/Raw/Lemmas.lean | 13 ++ src/Std/Data/Internal/List/Associative.lean | 206 +++++++++++++++++- src/Std/Data/TreeMap/Lemmas.lean | 144 +++++++++++- src/Std/Data/TreeMap/Raw/Lemmas.lean | 18 ++ src/Std/Data/TreeSet/Lemmas.lean | 101 +++++++++ src/Std/Data/TreeSet/Raw/Lemmas.lean | 13 ++ 10 files changed, 823 insertions(+), 6 deletions(-) diff --git a/src/Std/Data/DTreeMap/Internal/Lemmas.lean b/src/Std/Data/DTreeMap/Internal/Lemmas.lean index ad0f46aba6..1f30f26f41 100644 --- a/src/Std/Data/DTreeMap/Internal/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Internal/Lemmas.lean @@ -96,7 +96,8 @@ private def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (TSynta ⟨`foldr, (``foldr_eq_foldr, #[])⟩, ⟨`forIn, (``forIn_eq_forIn_toListModel, #[])⟩, ⟨`forM, (``forM_eq_forM, #[])⟩, - ⟨`minKey?, (``minKey?_eq_minKey?, #[``(minKey?_of_perm _)])⟩] + ⟨`minKey?, (``minKey?_eq_minKey?, #[``(minKey?_of_perm _)])⟩, + ⟨`minKey, (``minKey_eq_minKey, #[``(minKey_of_perm _)])⟩] /-- Internal implementation detail of the tree map -/ scoped syntax "simp_to_model" (" [" (ident,*) "]")? ("using" term)? : tactic @@ -275,6 +276,25 @@ theorem isEmpty_erase! [TransOrd α] (h : t.WF) {k : α} : (t.erase! k).isEmpty = (t.isEmpty || (t.size = 1 && t.contains k)) := by simpa only [erase_eq_erase!] using isEmpty_erase h +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransOrd α] (h : t.WF) (k : α) : + t.isEmpty = ((t.erase k h.balanced).impl.isEmpty && !(t.contains k)) := by + simp_to_model [erase, isEmpty, contains] using + List.isEmpty_eq_isEmpty_eraseKey_and_not_containsKey + +theorem isEmpty_eq_isEmpty_erase!_and_not_containsKey [TransOrd α] (h : t.WF) (k : α) : + t.isEmpty = ((t.erase! k).isEmpty && !(t.contains k)) := by + simpa [erase_eq_erase!] using isEmpty_eq_isEmpty_erase_and_not_containsKey h k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransOrd α] (h : t.WF) {k : α} : + (he : (t.erase k h.balanced).impl.isEmpty = false) → + t.isEmpty = false := by + simp_to_model [erase, isEmpty, contains] using List.isEmpty_eq_false_of_isEmpty_eraseKey_eq_false + +theorem isEmpty_eq_false_of_isEmpty_erase!_eq_false [TransOrd α] (h : t.WF) {k : α} : + (he : (t.erase! k).isEmpty = false) → + t.isEmpty = false := by + simpa [erase_eq_erase!] using isEmpty_eq_false_of_isEmpty_erase_eq_false h + theorem contains_erase [TransOrd α] (h : t.WF) {k a : α} : (t.erase k h.balanced).impl.contains a = (!(compare k a == .eq) && t.contains a) := by simp_to_model [erase, contains] using List.containsKey_eraseKey @@ -4243,14 +4263,18 @@ theorem isSome_minKey?_eq_not_isEmpty [TransOrd α] (h : t.WF) : t.minKey?.isSome = !t.isEmpty := by simp_to_model using List.isSome_minKey?_eq_not_isEmpty +theorem isSome_minKey?_iff_isEmpty_eq_false [TransOrd α] (h : t.WF) : + t.minKey?.isSome ↔ t.isEmpty = false := by + simp [isSome_minKey?_eq_not_isEmpty h] + theorem minKey?_insert [TransOrd α] (h : t.WF) {k v} : (t.insert k v h.balanced).impl.minKey? = - t.minKey?.elim k fun k' => if compare k k'|>.isLE then k else k' := by + some (t.minKey?.elim k fun k' => if compare k k'|>.isLE then k else k') := by simp_to_model [insert] using List.minKey?_insertEntry theorem minKey?_insert! [TransOrd α] (h : t.WF) {k v} : (t.insert! k v).minKey? = - t.minKey?.elim k fun k' => if compare k k'|>.isLE then k else k' := by + some (t.minKey?.elim k fun k' => if compare k k'|>.isLE then k else k') := by simpa only [insert_eq_insert!] using minKey?_insert h theorem isSome_minKey?_insert [TransOrd α] (h : t.WF) {k v} : @@ -4434,7 +4458,7 @@ theorem minKey?_modify [TransOrd α] (h : t.WF) {k f} : theorem minKey?_modify_eq_minKey? [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f} : (Const.modify k f t).minKey? = t.minKey? := by - simp_to_model [Const.modify] using List.Const.minKey?_modifyKey_of_lawfulEqOrd + simp_to_model [Const.modify] using List.Const.minKey?_modifyKey_eq_minKey? theorem isSome_minKey?_modify [TransOrd α] {k f} (h : t.WF) : (Const.modify k f t).minKey?.isSome = !t.isEmpty := by @@ -4463,6 +4487,139 @@ theorem minKey?_alter!_eq_self [TransOrd α] (h : t.WF) {k f} : end Const +theorem minKey_eq_get_minKey? [TransOrd α] (h : t.WF) {he} : + t.minKey he = t.minKey?.get (isSome_minKey?_iff_isEmpty_eq_false h |>.mpr he) := by + simp_to_model [minKey, minKey?] using List.minKey_eq_get_minKey? + +theorem minKey?_eq_some_minKey [TransOrd α] (h : t.WF) {he} : + t.minKey? = some (t.minKey he) := by + simp_to_model [minKey, minKey?] using List.minKey?_eq_some_minKey + +theorem minKey_eq_iff_getKey?_eq_self_and_forall [TransOrd α] (h : t.WF) {he km} : + t.minKey he = km ↔ t.getKey? km = some km ∧ ∀ k ∈ t, (compare km k).isLE := by + simp_to_model [minKey, getKey?, contains] using List.minKey_eq_iff_getKey?_eq_self_and_forall + +theorem minKey_eq_some_iff_mem_and_forall [TransOrd α] [LawfulEqOrd α] (h : t.WF) {he km} : + t.minKey he = km ↔ km ∈ t ∧ ∀ k ∈ t, (compare km k).isLE := by + simp_to_model [minKey, contains] using List.minKey_eq_some_iff_mem_and_forall + +theorem minKey_insert [TransOrd α] (h : t.WF) {k v} : + (t.insert k v h.balanced).impl.minKey (isEmpty_insert h) = + (t.minKey?).elim k fun k' => if compare k k'|>.isLE then k else k' := by + simp_to_model [insert, minKey, minKey?] using List.minKey_insertEntry + +theorem minKey_insert_le_minKey [TransOrd α] (h : t.WF) {k v he} : + compare (t.insert k v h.balanced |>.impl.minKey <| isEmpty_insert h) (t.minKey he) |>.isLE := by + simp_to_model [minKey, insert] using List.minKey_insertEntry_le_minKey + +theorem minKey_insert_le_self [TransOrd α] (h : t.WF) {k v} : + compare (t.insert k v h.balanced |>.impl.minKey <| isEmpty_insert h) k |>.isLE := by + simp_to_model [minKey, insert] using List.minKey_insertEntry_le_self + +theorem contains_minKey [TransOrd α] (h : t.WF) {he} : + t.contains (t.minKey he) := by + simp_to_model [minKey, contains] using List.containsKey_minKey + +theorem minKey_mem [TransOrd α] (h : t.WF) {he} : + t.minKey he ∈ t := + contains_minKey h + +theorem minKey_le_of_contains [TransOrd α] (h : t.WF) {k} : + (hc : t.contains k) → + compare (t.minKey <| (isEmpty_eq_false_iff_exists_contains_eq_true h).mpr ⟨k, hc⟩) k |>.isLE := by + simp_to_model [minKey, contains] using minKey_le_of_containsKey + +theorem minKey_le_of_mem [TransOrd α] (h : t.WF) {k} (hc : k ∈ t) : + compare (t.minKey <| (isEmpty_eq_false_iff_exists_contains_eq_true h).mpr ⟨k, hc⟩) k |>.isLE := + minKey_le_of_contains h hc + +theorem le_minKey [TransOrd α] (h : t.WF) {k he} : + (compare k (t.minKey he)).isLE ↔ (∀ k', k' ∈ t → (compare k k').isLE) := by + simp_to_model [minKey, contains] using List.le_minKey + +theorem getKey?_minKey [TransOrd α] (h : t.WF) {he} : + t.getKey? (t.minKey he) = some (t.minKey he) := by + simp_to_model [getKey?, minKey] using List.getKey?_minKey + +theorem getKey_minKey [TransOrd α] (h : t.WF) {he hc} : + t.getKey (t.minKey he) hc = t.minKey he := by + simp_to_model [getKey, minKey] using List.getKey_minKey + +theorem getKey!_minKey [TransOrd α] [Inhabited α] (h : t.WF) {he} : + t.getKey! (t.minKey he) = t.minKey he := by + simp_to_model [getKey!, minKey] using List.getKey!_minKey + +theorem getKeyD_minKey [TransOrd α] (h : t.WF) {he fallback} : + t.getKeyD (t.minKey he) fallback = t.minKey he := by + simp_to_model [getKeyD, minKey] using List.getKeyD_minKey + +theorem minKey_erase_eq_iff_not_compare_eq_minKey [TransOrd α] (h : t.WF) {k he} : + (t.erase k h.balanced |>.impl.minKey he) = + t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false h he) ↔ + ¬ compare k (t.minKey <| isEmpty_eq_false_of_isEmpty_erase_eq_false h he) = .eq := by + simp_to_model [minKey, erase] using List.minKey_eraseKey_eq_iff_beq_minKey_eq_false + +theorem minKey_erase_eq_of_not_compare_eq_minKey [TransOrd α] (h : t.WF) {k he} : + (hc : ¬ compare k (t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false h he)) = .eq) → + (t.erase k h.balanced |>.impl.minKey he) = + t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false h he) := by + simp_to_model [minKey, erase] using List.minKey_eraseKey_eq_of_beq_minKey_eq_false + +theorem minKey_le_minKey_erase [TransOrd α] (h : t.WF) {k he} : + compare (t.minKey <| isEmpty_eq_false_of_isEmpty_erase_eq_false h he) + (t.erase k h.balanced |>.impl.minKey he) |>.isLE := by + simp_to_model [minKey, erase] using List.minKey_le_minKey_erase + +theorem minKey_insertIfNew [TransOrd α] (h : t.WF) {k v} : + (t.insertIfNew k v h.balanced).impl.minKey (isEmpty_insertIfNew h) = + t.minKey?.elim k fun k' => if compare k k' = .lt then k else k' := by + simp_to_model [minKey, minKey?, insertIfNew] using List.minKey_insertEntryIfNew + +theorem minKey_insertIfNew_le_minKey [TransOrd α] (h : t.WF) {k v he} : + compare (t.insertIfNew k v h.balanced |>.impl.minKey <| isEmpty_insertIfNew h) + (t.minKey he) |>.isLE := by + simp_to_model [minKey, insertIfNew] using List.minKey_insertEntryIfNew_le_minKey + +theorem minKey_insertIfNew_le_self [TransOrd α] (h : t.WF) {k v} : + compare (t.insertIfNew k v h.balanced |>.impl.minKey <| isEmpty_insertIfNew h) k |>.isLE := by + simp_to_model [minKey, insertIfNew] using List.minKey_insertEntryIfNew_le_self + +theorem minKey_modify [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f he} : + (t.modify k f).minKey he = t.minKey (isEmpty_modify h ▸ he):= by + simp_to_model [minKey, modify] using List.minKey_modifyKey + +theorem minKey_alter_eq_self [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f he} : + (t.alter k f h.balanced).impl.minKey he = k ↔ + (f (t.get? k)).isSome ∧ ∀ k', k' ∈ t → (compare k k').isLE := by + simp_to_model [minKey, alter, get?, contains] using List.minKey_alterKey_eq_self + +namespace Const + +variable {β : Type v} {t : Impl α β} + +theorem minKey_modify [TransOrd α] (h : t.WF) {k f he} : + (modify k f t).minKey he = + if compare (t.minKey <| isEmpty_modify h ▸ he) k = .eq then + k + else + (t.minKey <| Const.isEmpty_modify h ▸ he) := by + simp_to_model [minKey, Const.modify] using List.Const.minKey_modifyKey + +theorem minKey_modify_eq_minKey [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f he} : + (modify k f t).minKey he = t.minKey (isEmpty_modify h ▸ he) := by + simp_to_model [minKey, Const.modify] using List.Const.minKey_modifyKey_eq_minKey + +theorem compare_minKey_modify_eq [TransOrd α] (h : t.WF) {k f he} : + compare (modify k f t |>.minKey he) (t.minKey <| isEmpty_modify h ▸ he) = .eq := by + simp_to_model [minKey, Const.modify] using List.Const.minKey_modifyKey_beq + +theorem minKey_alter_eq_self [TransOrd α] (h : t.WF) {k f he} : + (alter k f t h.balanced).impl.minKey he = k ↔ + (f (get? t k)).isSome ∧ ∀ k', k' ∈ t → (compare k k').isLE := by + simp_to_model [minKey, Const.alter, contains, Const.get?] using List.Const.minKey_alterKey_eq_self + +end Const + end Min end Std.DTreeMap.Internal.Impl diff --git a/src/Std/Data/DTreeMap/Internal/Model.lean b/src/Std/Data/DTreeMap/Internal/Model.lean index ac282b74ac..cc870c64f2 100644 --- a/src/Std/Data/DTreeMap/Internal/Model.lean +++ b/src/Std/Data/DTreeMap/Internal/Model.lean @@ -465,6 +465,17 @@ theorem minEntry?_eq_minEntry?ₘ [Ord α] {l : Impl α β} : l.minEntry? = l.mi theorem minKey?_eq_minEntry?_map_fst [Ord α] {l : Impl α β} : l.minKey? = l.minEntry?.map Sigma.fst := by induction l using minKey?.induct <;> simp only [minKey?, minEntry?] <;> trivial +theorem some_minEntry_eq_minEntry? [Ord α] {l : Impl α β} {he} : + some (l.minEntry he) = l.minEntry? := by + induction l, he using minEntry.induct <;> simp_all [minEntry, minEntry?] + +theorem minEntry_eq_get_minEntry? [Ord α] {l : Impl α β} {he} : + l.minEntry he = l.minEntry?.get (by simp [← some_minEntry_eq_minEntry? (he := he)]) := by + simp [← some_minEntry_eq_minEntry? (he := he)] + +theorem minKey_eq_minEntry_fst [Ord α] {l : Impl α β} {he} : l.minKey he = (l.minEntry he).fst := by + induction l, he using minKey.induct <;> simp only [minKey, minEntry] <;> trivial + theorem balanceL_eq_balance {k : α} {v : β k} {l r : Impl α β} {hlb hrb hlr} : balanceL k v l r hlb hrb hlr = balance k v l r hlb hrb (Or.inl hlr.erase) := by rw [balanceL_eq_balanceLErase, balanceLErase_eq_balanceL!, diff --git a/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean b/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean index 9e96c93dce..24ef498f42 100644 --- a/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean @@ -1828,4 +1828,9 @@ theorem minKey?_eq_minKey? [Ord α] [TransOrd α] {l : Impl α β} (hlo : l.Orde l.minKey? = List.minKey? l.toListModel := by simp only [minKey?_eq_minEntry?_map_fst, minEntry?_eq_minEntry? hlo, List.minKey?] +theorem minKey_eq_minKey [Ord α] [TransOrd α] {l : Impl α β} (hlo : l.Ordered) {he} : + l.minKey he = List.minKey l.toListModel (isEmpty_eq_isEmpty ▸ he) := by + simp [minKey_eq_get_minKey?, minKey_eq_minEntry_fst, minEntry_eq_get_minEntry?, + minEntry?_eq_minEntry? hlo, List.minKey?, Option.get_map] + end Std.DTreeMap.Internal.Impl diff --git a/src/Std/Data/DTreeMap/Lemmas.lean b/src/Std/Data/DTreeMap/Lemmas.lean index d7392400c5..3ee76d9d09 100644 --- a/src/Std/Data/DTreeMap/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Lemmas.lean @@ -145,6 +145,15 @@ theorem isEmpty_erase [TransCmp cmp] {k : α} : (t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) := Impl.isEmpty_erase t.wf +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransCmp cmp] (k : α) : + t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := + Impl.isEmpty_eq_isEmpty_erase_and_not_containsKey t.wf k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] {k : α} + (he : (t.erase k).isEmpty = false) : + t.isEmpty = false := + Impl.isEmpty_eq_false_of_isEmpty_erase_eq_false t.wf he + @[simp] theorem contains_erase [TransCmp cmp] {k a : α} : (t.erase k).contains a = (cmp k a != .eq && t.contains a) := @@ -2797,6 +2806,10 @@ theorem isSome_minKey?_eq_not_isEmpty [TransCmp cmp] : t.minKey?.isSome = !t.isEmpty := Impl.isSome_minKey?_eq_not_isEmpty t.wf +theorem isSome_minKey?_iff_isEmpty_eq_false [TransCmp cmp] : + t.minKey?.isSome ↔ t.isEmpty = false := + Impl.isSome_minKey?_iff_isEmpty_eq_false t.wf + theorem minKey?_insert [TransCmp cmp] {k v} : (t.insert k v).minKey? = some (t.minKey?.elim k fun k' => if cmp k k'|>.isLE then k else k') := @@ -2946,6 +2959,146 @@ theorem minKey?_alter_eq_self [TransCmp cmp] {k f} : end Const +theorem minKey_eq_get_minKey? [TransCmp cmp] {he} : + t.minKey he = t.minKey?.get (isSome_minKey?_iff_isEmpty_eq_false.mpr he) := + Impl.minKey_eq_get_minKey? t.wf + +theorem minKey?_eq_some_minKey [TransCmp cmp] {he} : + t.minKey? = some (t.minKey he) := + Impl.minKey?_eq_some_minKey t.wf + +theorem minKey_eq_iff_getKey?_eq_self_and_forall [TransCmp cmp] {he km} : + t.minKey he = km ↔ t.getKey? km = some km ∧ ∀ k ∈ t, (cmp km k).isLE := + Impl.minKey_eq_iff_getKey?_eq_self_and_forall t.wf + +theorem minKey_eq_some_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] {he km} : + t.minKey he = km ↔ km ∈ t ∧ ∀ k ∈ t, (cmp km k).isLE := + Impl.minKey_eq_some_iff_mem_and_forall t.wf + +theorem minKey_insert [TransCmp cmp] {k v} : + (t.insert k v).minKey isEmpty_insert = + (t.minKey?).elim k fun k' => if cmp k k'|>.isLE then k else k' := + Impl.minKey_insert t.wf + +theorem minKey_insert_le_minKey [TransCmp cmp] {k v he} : + cmp (t.insert k v |>.minKey isEmpty_insert) (t.minKey he) |>.isLE := + Impl.minKey_insert_le_minKey t.wf + +theorem minKey_insert_le_self [TransCmp cmp] {k v} : + cmp (t.insert k v |>.minKey isEmpty_insert) k |>.isLE := + Impl.minKey_insert_le_self t.wf + +theorem contains_minKey [TransCmp cmp] {he} : + t.contains (t.minKey he) := + Impl.contains_minKey t.wf + +theorem minKey_mem [TransCmp cmp] {he} : + t.minKey he ∈ t := + Impl.minKey_mem t.wf + +theorem minKey_le_of_contains [TransCmp cmp] {k} (hc : t.contains k) : + cmp (t.minKey <| isEmpty_eq_false_iff_exists_contains_eq_true.mpr ⟨k, hc⟩) k |>.isLE := + Impl.minKey_le_of_contains t.wf hc + +theorem minKey_le_of_mem [TransCmp cmp] {k} (hc : k ∈ t) : + cmp (t.minKey <| isEmpty_eq_false_iff_exists_contains_eq_true.mpr ⟨k, hc⟩) k |>.isLE := + Impl.minKey_le_of_mem t.wf hc + +theorem le_minKey [TransCmp cmp] {k he} : + (cmp k (t.minKey he)).isLE ↔ (∀ k', k' ∈ t → (cmp k k').isLE) := + Impl.le_minKey t.wf + +@[simp] +theorem getKey?_minKey [TransCmp cmp] {he} : + t.getKey? (t.minKey he) = some (t.minKey he) := + Impl.getKey?_minKey t.wf + +@[simp] +theorem getKey_minKey [TransCmp cmp] {he hc} : + t.getKey (t.minKey he) hc = t.minKey he := + Impl.getKey_minKey t.wf + +@[simp] +theorem getKey!_minKey [TransCmp cmp] [Inhabited α] {he} : + t.getKey! (t.minKey he) = t.minKey he := + Impl.getKey!_minKey t.wf + +@[simp] +theorem getKeyD_minKey [TransCmp cmp] {he fallback} : + t.getKeyD (t.minKey he) fallback = t.minKey he := + Impl.getKeyD_minKey t.wf + +@[simp] +theorem minKey_erase_eq_iff_not_compare_eq_minKey [TransCmp cmp] {k he} : + (t.erase k |>.minKey he) = + t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false he) ↔ + ¬ cmp k (t.minKey <| isEmpty_eq_false_of_isEmpty_erase_eq_false he) = .eq := + Impl.minKey_erase_eq_iff_not_compare_eq_minKey t.wf + +theorem minKey_erase_eq_of_not_compare_eq_minKey [TransCmp cmp] {k he} : + (hc : ¬ cmp k (t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false he)) = .eq) → + (t.erase k |>.minKey he) = + t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false he) := + Impl.minKey_erase_eq_of_not_compare_eq_minKey t.wf + +theorem minKey_le_minKey_erase [TransCmp cmp] {k he} : + cmp (t.minKey <| isEmpty_eq_false_of_isEmpty_erase_eq_false he) + (t.erase k |>.minKey he) |>.isLE := + Impl.minKey_le_minKey_erase t.wf + +theorem minKey_insertIfNew [TransCmp cmp] {k v} : + (t.insertIfNew k v).minKey isEmpty_insertIfNew = + t.minKey?.elim k fun k' => if cmp k k' = .lt then k else k' := + Impl.minKey_insertIfNew t.wf + +theorem minKey_insertIfNew_le_minKey [TransCmp cmp] {k v he} : + cmp (t.insertIfNew k v |>.minKey isEmpty_insertIfNew) + (t.minKey he) |>.isLE := + Impl.minKey_insertIfNew_le_minKey t.wf + +theorem minKey_insertIfNew_le_self [TransCmp cmp] {k v} : + cmp (t.insertIfNew k v |>.minKey <| isEmpty_insertIfNew) k |>.isLE := + Impl.minKey_insertIfNew_le_self t.wf + +@[simp] +theorem minKey_modify [TransCmp cmp] [LawfulEqCmp cmp] {k f he} : + (t.modify k f).minKey he = t.minKey (cast (congrArg (· = false) isEmpty_modify) he) := + Impl.minKey_modify t.wf + +theorem minKey_alter_eq_self [TransCmp cmp] [LawfulEqCmp cmp] {k f he} : + (t.alter k f).minKey he = k ↔ + (f (t.get? k)).isSome ∧ ∀ k', k' ∈ t → (cmp k k').isLE := + Impl.minKey_alter_eq_self t.wf + +namespace Const + +variable {β : Type v} {t : DTreeMap α β cmp} + +theorem minKey_modify [TransCmp cmp] {k f he} : + (modify t k f).minKey he = + if cmp (t.minKey <| cast (congrArg (· = false) isEmpty_modify) he) k = .eq then + k + else + (t.minKey <| cast (congrArg (· = false) isEmpty_modify) he) := + Impl.Const.minKey_modify t.wf + +@[simp] +theorem minKey_modify_eq_minKey [TransCmp cmp] [LawfulEqCmp cmp] {k f he} : + (modify t k f).minKey he = t.minKey (cast (congrArg (· = false) isEmpty_modify) he) := + Impl.Const.minKey_modify_eq_minKey t.wf + +theorem compare_minKey_modify_eq [TransCmp cmp] {k f he} : + cmp (modify t k f |>.minKey he) + (t.minKey <| cast (congrArg (· = false) isEmpty_modify) he) = .eq := + Impl.Const.compare_minKey_modify_eq t.wf + +theorem minKey_alter_eq_self [TransCmp cmp] {k f he} : + (alter t k f).minKey he = k ↔ + (f (get? t k)).isSome ∧ ∀ k', k' ∈ t → (cmp k k').isLE := + Impl.Const.minKey_alter_eq_self t.wf + +end Const + end Min end Std.DTreeMap diff --git a/src/Std/Data/DTreeMap/Raw/Lemmas.lean b/src/Std/Data/DTreeMap/Raw/Lemmas.lean index 5d31c94fd9..1fe9236a72 100644 --- a/src/Std/Data/DTreeMap/Raw/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Raw/Lemmas.lean @@ -146,6 +146,15 @@ theorem isEmpty_erase [TransCmp cmp] (h : t.WF) {k : α} : (t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) := Impl.isEmpty_erase! h +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransCmp cmp] (h : t.WF) (k : α) : + t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := + Impl.isEmpty_eq_isEmpty_erase!_and_not_containsKey h k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] (h : t.WF) {k : α} + (he : (t.erase k).isEmpty = false) : + t.isEmpty = false := + Impl.isEmpty_eq_false_of_isEmpty_erase!_eq_false h he + @[simp] theorem contains_erase [TransCmp cmp] (h : t.WF) {k a : α} : (t.erase k).contains a = (cmp k a != .eq && t.contains a) := @@ -2802,6 +2811,10 @@ theorem isSome_minKey?_eq_not_isEmpty [TransCmp cmp] (h : t.WF) : t.minKey?.isSome = !t.isEmpty := Impl.isSome_minKey?_eq_not_isEmpty h +theorem isSome_minKey?_iff_isEmpty_eq_false [TransCmp cmp] (h : t.WF) : + t.minKey?.isSome ↔ t.isEmpty = false := + Impl.isSome_minKey?_iff_isEmpty_eq_false h + theorem minKey?_insert [TransCmp cmp] (h : t.WF) {k v} : (t.insert k v).minKey? = some (t.minKey?.elim k fun k' => if cmp k k'|>.isLE then k else k') := diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 92991e5d6f..a5bf07591e 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -1770,6 +1770,27 @@ theorem containsKey_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) (hl : DistinctKeys l) : containsKey a (eraseKey k l) = (!(k == a) && containsKey a l) := by simp [containsKey_eq_isSome_getEntry?, getEntry?_eraseKey hl, apply_ite] +theorem isEmpty_eq_isEmpty_eraseKey_and_not_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) (k : α) : + l.isEmpty = ((eraseKey k l).isEmpty && !(containsKey k l)) := by + rw [Bool.eq_iff_iff, Bool.and_eq_true, Bool.not_eq_true'] + simp only [isEmpty_iff_forall_containsKey, containsKey_eraseKey hd, Bool.and_eq_false_iff, + Bool.not_eq_false'] + constructor + · exact fun h => ⟨fun a => Or.inr (h a), h k⟩ + · rintro ⟨h₁, h₂⟩ a + specialize h₁ a + cases hbeq : k == a + · simp_all + · simp only [hbeq, true_or] at h₁ + exact containsKey_congr hbeq ▸ h₂ + +theorem isEmpty_eq_false_of_isEmpty_eraseKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k : α} + (he : (eraseKey k l).isEmpty = false) : + l.isEmpty = false := by + simp_all [isEmpty_eq_isEmpty_eraseKey_and_not_containsKey hd k] + theorem getValueCast?_eraseKey [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α} (hl : DistinctKeys l) : getValueCast? a (eraseKey k l) = if k == a then none else getValueCast? a l := by @@ -4348,6 +4369,10 @@ theorem isSome_minKey?_eq_not_isEmpty [Ord α] {l : List ((a : α) × β a)} : (minKey? l).isSome = !l.isEmpty := by simpa [minKey?] using isSome_minEntry?_eq_not_isEmpty +theorem isSome_minKey?_iff_isEmpty_eq_false [Ord α] {l : List ((a : α) × β a)} : + (minKey? l).isSome ↔ l.isEmpty = false := by + simp [isSome_minKey?_eq_not_isEmpty] + theorem min_apply [Ord α] {e₁ e₂ : (a : α) × β a} {f : (a : α) × β a → (a : α) × β a} (hf : compare e₁.1 e₂.1 = compare (f e₁).1 (f e₂).1) : min (f e₁) (f e₂) = f (min e₁ e₂) := by @@ -4689,7 +4714,7 @@ theorem minKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f have := TransCmp.lt_of_isLE_of_lt hkm hcmp simp [this] at h -theorem minKey?_modifyKey_of_lawfulEqOrd [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] +theorem minKey?_modifyKey_eq_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] {k f} {l : List ((_ : α) × β)} (hd : DistinctKeys l) : minKey? (modifyKey k f l) = minKey? l := by simp only [minKey?_modifyKey hd] @@ -4741,6 +4766,185 @@ theorem minKey?_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd end Const +/-- Given a proof that the list is nonempty, returns the smallest key in an associative list. -/ +def minKey [Ord α] (xs : List ((a : α) × β a)) (h : xs.isEmpty = false) : α := + minKey? xs |>.get (by simp [isSome_minKey?_eq_not_isEmpty, h]) + +theorem minKey_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l l' : List ((a : α) × β a)} + {hl} (hd : DistinctKeys l) (hp : l.Perm l') : + minKey l hl = minKey l' (hp.isEmpty_eq ▸ hl) := by + simp [minKey, minKey?_of_perm hd hp] + +theorem minKey_eq_get_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} {he} : + minKey l he = (minKey? l |>.get (by simp [isSome_minKey?_eq_not_isEmpty, he])) := + rfl + +theorem minKey?_eq_some_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} {he} : + minKey? l = some (minKey l he) := by + simp [minKey_eq_get_minKey?] + +private theorem Option.get_eq_iff_eq_some {o : Option α} {h k} : + o.get h = k ↔ o = some k := by + simp [Option.eq_some_iff_get_eq, exists_prop_of_true h] + +private theorem Option.eq_get_iff_some_eq {o : Option α} {h k} : + k = o.get h ↔ some k = o := by + conv => congr <;> rw [eq_comm] + exact get_eq_iff_eq_some + +theorem minKey_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he km} : + minKey l he = km ↔ getKey? km l = some km ∧ ∀ k, containsKey k l → (compare km k).isLE := by + simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, + minKey?_eq_some_iff_getKey?_eq_self_and_forall hd] + +theorem minKey_eq_some_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + [LawfulEqOrd α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he km} : + minKey l he = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare km k).isLE := by + simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_eq_some_iff_mem_and_forall hd] + +theorem minKey_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l : List ((a : α) × β a)} + (hd : DistinctKeys l) {k v} : + (insertEntry k v l |> minKey <| isEmpty_insertEntry) = + ((minKey? l).elim k fun k' => if compare k k'|>.isLE then k else k') := by + simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_insertEntry hd] + +theorem minKey_insertEntry_le_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v he} : + compare (insertEntry k v l |> minKey <| isEmpty_insertEntry) (minKey l he) |>.isLE := by + simp only [minKey_eq_get_minKey?] + exact minKey?_insertEntry_le_minKey? hd (by simp) rfl + +theorem minKey_insertEntry_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} : + compare (insertEntry k v l |> minKey <| isEmpty_insertEntry) k |>.isLE := by + simp only [minKey_eq_get_minKey?] + exact minKey?_insertEntry_le_self hd rfl + +theorem containsKey_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} : + containsKey (minKey l he) l := + containsKey_minKey? hd minKey?_eq_some_minKey + +theorem minKey_le_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) : + compare (minKey l <| isEmpty_eq_false_iff_exists_containsKey.mpr ⟨k, hc⟩) k |>.isLE := + minKey?_le_of_containsKey hd hc minKey_eq_get_minKey?.symm + +theorem le_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} : + (compare k (minKey l he)).isLE ↔ (∀ k', containsKey k' l → (compare k k').isLE) := by + simp only [minKey_eq_get_minKey?, ← le_minKey? hd, Option.eq_some_iff_get_eq] + simp only [exists_prop_of_true (isSome_minKey?_iff_isEmpty_eq_false.mpr he), forall_eq'] + +theorem getKey?_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} : + getKey? (minKey l he) l = some (minKey l he) := + getKey?_minKey? hd minKey?_eq_some_minKey + +theorem getKey_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} : + getKey (minKey l he) l (containsKey_minKey hd) = minKey l he := by + simpa [getKey?_eq_some_getKey (containsKey_minKey hd)] using getKey?_minKey hd (he := he) + +theorem getKey!_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} : + getKey! (minKey l he) l = minKey l he := by + simpa [getKey_eq_getKey!] using getKey_minKey hd + +theorem getKeyD_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he fallback} : + getKeyD (minKey l he) l fallback = minKey l he := by + simpa [getKey_eq_getKeyD (fallback := fallback)] using getKey_minKey hd + +theorem minKey_eraseKey_eq_iff_beq_minKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} : + (eraseKey k l |> minKey <| he) = + minKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) ↔ + (k == (minKey l <| isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he)) = false := by + simp only [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, Option.some_get] + constructor + · intro h + exact minKey?_eraseKey_eq_iff_beq_minKey?_eq_false hd |>.mp h (by rw [Option.some_get]) + · intro h + apply minKey?_eraseKey_eq_iff_beq_minKey?_eq_false hd |>.mpr + intro km hkm + simp_all only [Option.get_some] + +theorem minKey_eraseKey_eq_of_beq_minKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} : + (hc : (k == (minKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he))) = false) → + (eraseKey k l |> minKey <| he) = + minKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) := + minKey_eraseKey_eq_iff_beq_minKey_eq_false hd |>.mpr + +theorem minKey_le_minKey_erase [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} : + compare (minKey l <| isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) + (eraseKey k l |> minKey <| he) |>.isLE := + minKey?_le_minKey?_eraseKey hd minKey?_eq_some_minKey minKey_eq_get_minKey?.symm + +theorem minKey_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} : + (insertEntryIfNew k v l |> minKey <| isEmpty_insertEntryIfNew) = + (minKey? l).elim k fun k' => if compare k k' = .lt then k else k' := by + simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, ← minKey?_insertEntryIfNew hd (v := v)] + +theorem minKey_insertEntryIfNew_le_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v he} : + compare (insertEntryIfNew k v l |> minKey <| isEmpty_insertEntryIfNew) + (minKey l he) |>.isLE := + minKey?_insertEntryIfNew_le_minKey? hd minKey?_eq_some_minKey minKey_eq_get_minKey?.symm + +theorem minKey_insertEntryIfNew_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} : + compare (insertEntryIfNew k v l |> minKey <| isEmpty_insertEntryIfNew) k |>.isLE := + minKey?_insertEntryIfNew_le_self hd minKey_eq_get_minKey?.symm + +theorem minKey_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] {k f} + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} : + (modifyKey k f l |> minKey <| he) = minKey l (isEmpty_modifyKey k f l ▸ he):= by + simp [minKey_eq_get_minKey?, minKey?_modifyKey hd] + +theorem minKey_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] + {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f he} : + (alterKey k f l |> minKey <| he) = k ↔ + (f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by + simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_alterKey_eq_self hd] + +namespace Const + +variable {β : Type v} + +theorem minKey_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} : + (modifyKey k f l |> minKey <| he) = + if (minKey l <| isEmpty_modifyKey k f l ▸ he) == k then + k + else + (minKey l <| isEmpty_modifyKey k f l ▸ he) := by + simp [minKey_eq_get_minKey?, minKey?_modifyKey hd, Option.get_map] + +theorem minKey_modifyKey_eq_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] + {l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} : + (modifyKey k f l |> minKey <| he) = minKey l (isEmpty_modifyKey k f l ▸ he) := by + simp [minKey_eq_get_minKey?, minKey?_modifyKey_eq_minKey? hd] + +theorem minKey_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} : + (modifyKey k f l |> minKey <| he) == (minKey l <| isEmpty_modifyKey k f l ▸ he) := + minKey?_modifyKey_beq hd minKey?_eq_some_minKey rfl + +theorem minKey_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] + {l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} : + (alterKey k f l |> minKey <| he) = k ↔ + (f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by + simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_alterKey_eq_self hd] + +end Const + end Min end Std.Internal.List diff --git a/src/Std/Data/TreeMap/Lemmas.lean b/src/Std/Data/TreeMap/Lemmas.lean index afe6531703..ff9abb064c 100644 --- a/src/Std/Data/TreeMap/Lemmas.lean +++ b/src/Std/Data/TreeMap/Lemmas.lean @@ -142,6 +142,15 @@ theorem isEmpty_erase [TransCmp cmp] {k : α} : (t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) := DTreeMap.isEmpty_erase +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransCmp cmp] (k : α) : + t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := + DTreeMap.isEmpty_eq_isEmpty_erase_and_not_containsKey k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] {k : α} + (he : (t.erase k).isEmpty = false) : + t.isEmpty = false := + DTreeMap.isEmpty_eq_false_of_isEmpty_erase_eq_false he + @[simp] theorem contains_erase [TransCmp cmp] {k a : α} : (t.erase k).contains a = (cmp k a != .eq && t.contains a) := @@ -310,6 +319,11 @@ theorem getElem?_eq_some_getElem! [TransCmp cmp] [Inhabited β] {a : α} : a ∈ t → t[a]? = some t[a]! := DTreeMap.Const.get?_eq_some_get! +theorem getElem!_eq_get!_getElem? [TransCmp cmp] [Inhabited β] {a : α} : + t[a]! = t[a]?.get! := + DTreeMap.Const.get!_eq_get!_get? + +@[deprecated getElem!_eq_get!_getElem? (since := "2025-03-19")] theorem getElem!_eq_getElem!_getElem? [TransCmp cmp] [Inhabited β] {a : α} : t[a]! = t[a]?.get! := DTreeMap.Const.get!_eq_get!_get? @@ -1766,6 +1780,10 @@ theorem isSome_minKey?_eq_not_isEmpty [TransCmp cmp] : t.minKey?.isSome = !t.isEmpty := DTreeMap.isSome_minKey?_eq_not_isEmpty +theorem isSome_minKey?_iff_isEmpty_eq_false [TransCmp cmp] : + t.minKey?.isSome ↔ t.isEmpty = false := + DTreeMap.isSome_minKey?_iff_isEmpty_eq_false + theorem minKey?_insert [TransCmp cmp] {k v} : (t.insert k v).minKey? = some (t.minKey?.elim k fun k' => if cmp k k'|>.isLE then k else k') := @@ -1891,9 +1909,133 @@ theorem compare_minKey?_modify_eq [TransCmp cmp] {k f km kmm} : theorem minKey?_alter_eq_self [TransCmp cmp] {k f} : (t.alter k f).minKey? = some k ↔ - (f (t.get? k)).isSome ∧ ∀ k', k' ∈ t → (cmp k k').isLE := + (f t[k]?).isSome ∧ ∀ k', k' ∈ t → (cmp k k').isLE := DTreeMap.Const.minKey?_alter_eq_self +theorem minKey_eq_get_minKey? [TransCmp cmp] {he} : + t.minKey he = t.minKey?.get (isSome_minKey?_iff_isEmpty_eq_false.mpr he) := + DTreeMap.minKey_eq_get_minKey? + +theorem minKey?_eq_some_minKey [TransCmp cmp] {he} : + t.minKey? = some (t.minKey he) := + DTreeMap.minKey?_eq_some_minKey + +theorem minKey_eq_iff_getKey?_eq_self_and_forall [TransCmp cmp] {he km} : + t.minKey he = km ↔ t.getKey? km = some km ∧ ∀ k ∈ t, (cmp km k).isLE := + DTreeMap.minKey_eq_iff_getKey?_eq_self_and_forall + +theorem minKey_eq_some_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] {he km} : + t.minKey he = km ↔ km ∈ t ∧ ∀ k ∈ t, (cmp km k).isLE := + DTreeMap.minKey_eq_some_iff_mem_and_forall + +theorem minKey_insert [TransCmp cmp] {k v} : + (t.insert k v).minKey isEmpty_insert = + (t.minKey?).elim k fun k' => if cmp k k'|>.isLE then k else k' := + DTreeMap.minKey_insert + +theorem minKey_insert_le_minKey [TransCmp cmp] {k v he} : + cmp (t.insert k v |>.minKey isEmpty_insert) (t.minKey he) |>.isLE := + DTreeMap.minKey_insert_le_minKey + +theorem minKey_insert_le_self [TransCmp cmp] {k v} : + cmp (t.insert k v |>.minKey isEmpty_insert) k |>.isLE := + DTreeMap.minKey_insert_le_self + +theorem contains_minKey [TransCmp cmp] {he} : + t.contains (t.minKey he) := + DTreeMap.contains_minKey + +theorem minKey_mem [TransCmp cmp] {he} : + t.minKey he ∈ t := + DTreeMap.minKey_mem + +theorem minKey_le_of_contains [TransCmp cmp] {k} (hc : t.contains k) : + cmp (t.minKey <| isEmpty_eq_false_iff_exists_contains_eq_true.mpr ⟨k, hc⟩) k |>.isLE := + DTreeMap.minKey_le_of_contains hc + +theorem minKey_le_of_mem [TransCmp cmp] {k} (hc : k ∈ t) : + cmp (t.minKey <| isEmpty_eq_false_iff_exists_contains_eq_true.mpr ⟨k, hc⟩) k |>.isLE := + DTreeMap.minKey_le_of_mem hc + +theorem le_minKey [TransCmp cmp] {k he} : + (cmp k (t.minKey he)).isLE ↔ (∀ k', k' ∈ t → (cmp k k').isLE) := + DTreeMap.le_minKey + +@[simp] +theorem getKey?_minKey [TransCmp cmp] {he} : + t.getKey? (t.minKey he) = some (t.minKey he) := + DTreeMap.getKey?_minKey + +@[simp] +theorem getKey_minKey [TransCmp cmp] {he hc} : + t.getKey (t.minKey he) hc = t.minKey he := + DTreeMap.getKey_minKey + +@[simp] +theorem getKey!_minKey [TransCmp cmp] [Inhabited α] {he} : + t.getKey! (t.minKey he) = t.minKey he := + DTreeMap.getKey!_minKey + +@[simp] +theorem getKeyD_minKey [TransCmp cmp] {he fallback} : + t.getKeyD (t.minKey he) fallback = t.minKey he := + DTreeMap.getKeyD_minKey + +@[simp] +theorem minKey_erase_eq_iff_not_cmp_eq_minKey [TransCmp cmp] {k he} : + (t.erase k |>.minKey he) = + t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false he) ↔ + ¬ cmp k (t.minKey <| isEmpty_eq_false_of_isEmpty_erase_eq_false he) = .eq := + DTreeMap.minKey_erase_eq_iff_not_compare_eq_minKey + +theorem minKey_erase_eq_of_not_cmp_eq_minKey [TransCmp cmp] {k he} : + (hc : ¬ cmp k (t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false he)) = .eq) → + (t.erase k |>.minKey he) = + t.minKey (isEmpty_eq_false_of_isEmpty_erase_eq_false he) := + DTreeMap.minKey_erase_eq_of_not_compare_eq_minKey + +theorem minKey_le_minKey_erase [TransCmp cmp] {k he} : + cmp (t.minKey <| isEmpty_eq_false_of_isEmpty_erase_eq_false he) + (t.erase k |>.minKey he) |>.isLE := + DTreeMap.minKey_le_minKey_erase + +theorem minKey_insertIfNew [TransCmp cmp] {k v} : + (t.insertIfNew k v).minKey isEmpty_insertIfNew = + t.minKey?.elim k fun k' => if cmp k k' = .lt then k else k' := + DTreeMap.minKey_insertIfNew + +theorem minKey_insertIfNew_le_minKey [TransCmp cmp] {k v he} : + cmp (t.insertIfNew k v |>.minKey isEmpty_insertIfNew) + (t.minKey he) |>.isLE := + DTreeMap.minKey_insertIfNew_le_minKey (t := t.inner) (he := he) + +theorem minKey_insertIfNew_le_self [TransCmp cmp] {k v} : + cmp (t.insertIfNew k v |>.minKey <| isEmpty_insertIfNew) k |>.isLE := + DTreeMap.minKey_insertIfNew_le_self + +theorem minKey_modify [TransCmp cmp] {k f he} : + (modify t k f).minKey he = + if cmp (t.minKey <| cast (congrArg (· = false) isEmpty_modify) he) k = .eq then + k + else + (t.minKey <| cast (congrArg (· = false) isEmpty_modify) he) := + DTreeMap.Const.minKey_modify + +@[simp] +theorem minKey_modify_eq_minKey [TransCmp cmp] [LawfulEqCmp cmp] {k f he} : + (modify t k f).minKey he = t.minKey (cast (congrArg (· = false) isEmpty_modify) he) := + DTreeMap.Const.minKey_modify_eq_minKey + +theorem compare_minKey_modify_eq [TransCmp cmp] {k f he} : + cmp (modify t k f |>.minKey he) + (t.minKey <| cast (congrArg (· = false) isEmpty_modify) he) = .eq := + DTreeMap.Const.compare_minKey_modify_eq + +theorem minKey_alter_eq_self [TransCmp cmp] {k f he} : + (alter t k f).minKey he = k ↔ + (f t[k]?).isSome ∧ ∀ k', k' ∈ t → (cmp k k').isLE := + DTreeMap.Const.minKey_alter_eq_self + end Min end Std.TreeMap diff --git a/src/Std/Data/TreeMap/Raw/Lemmas.lean b/src/Std/Data/TreeMap/Raw/Lemmas.lean index e92f7d1eb5..8ca8ee261e 100644 --- a/src/Std/Data/TreeMap/Raw/Lemmas.lean +++ b/src/Std/Data/TreeMap/Raw/Lemmas.lean @@ -143,6 +143,15 @@ theorem isEmpty_erase [TransCmp cmp] (h : t.WF) {k : α} : (t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) := DTreeMap.Raw.isEmpty_erase h +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransCmp cmp] (h : t.WF) (k : α) : + t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := + DTreeMap.Raw.isEmpty_eq_isEmpty_erase_and_not_containsKey h k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] (h : t.WF) {k : α} + (he : (t.erase k).isEmpty = false) : + t.isEmpty = false := + DTreeMap.Raw.isEmpty_eq_false_of_isEmpty_erase_eq_false h he + @[simp] theorem contains_erase [TransCmp cmp] (h : t.WF) {k a : α} : (t.erase k).contains a = (cmp k a != .eq && t.contains a) := @@ -311,6 +320,11 @@ theorem getElem?_eq_some_getElem! [TransCmp cmp] [Inhabited β] (h : t.WF) {a : a ∈ t → t[a]? = some t[a]! := DTreeMap.Raw.Const.get?_eq_some_get! h +theorem getElem!_eq_get!_getElem? [TransCmp cmp] [Inhabited β] (h : t.WF) {a : α} : + t[a]! = t[a]?.get! := + DTreeMap.Raw.Const.get!_eq_get!_get? h + +@[deprecated getElem!_eq_get!_getElem? (since := "2025-03-19")] theorem getElem!_eq_getElem!_getElem? [TransCmp cmp] [Inhabited β] (h : t.WF) {a : α} : t[a]! = t[a]?.get! := DTreeMap.Raw.Const.get!_eq_get!_get? h @@ -1775,6 +1789,10 @@ theorem isSome_minKey?_eq_not_isEmpty [TransCmp cmp] (h : t.WF) : t.minKey?.isSome = !t.isEmpty := DTreeMap.Raw.isSome_minKey?_eq_not_isEmpty h +theorem isSome_minKey?_iff_isEmpty_eq_false [TransCmp cmp] (h : t.WF) : + t.minKey?.isSome ↔ t.isEmpty = false := + DTreeMap.Raw.isSome_minKey?_iff_isEmpty_eq_false h + theorem minKey?_insert [TransCmp cmp] (h : t.WF) {k v} : (t.insert k v).minKey? = some (t.minKey?.elim k fun k' => if cmp k k'|>.isLE then k else k') := diff --git a/src/Std/Data/TreeSet/Lemmas.lean b/src/Std/Data/TreeSet/Lemmas.lean index ec2361ccf6..6eee9f52b4 100644 --- a/src/Std/Data/TreeSet/Lemmas.lean +++ b/src/Std/Data/TreeSet/Lemmas.lean @@ -148,6 +148,15 @@ theorem isEmpty_erase [TransCmp cmp] {k : α} : (t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) := TreeMap.isEmpty_erase +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransCmp cmp] (k : α) : + t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := + DTreeMap.isEmpty_eq_isEmpty_erase_and_not_containsKey k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] {k : α} + (he : (t.erase k).isEmpty = false) : + t.isEmpty = false := + TreeMap.isEmpty_eq_false_of_isEmpty_erase_eq_false he + @[simp] theorem contains_erase [TransCmp cmp] {k a : α} : (t.erase k).contains a = (cmp k a != .eq && t.contains a) := @@ -689,6 +698,10 @@ theorem isSome_min?_eq_not_isEmpty [TransCmp cmp] : t.min?.isSome = !t.isEmpty := TreeMap.isSome_minKey?_eq_not_isEmpty +theorem isSome_min?_iff_isEmpty_eq_false [TransCmp cmp] : + t.min?.isSome ↔ t.isEmpty = false := + DTreeMap.isSome_minKey?_iff_isEmpty_eq_false + theorem min?_insert [TransCmp cmp] {k} : (t.insert k).min? = t.min?.elim k fun k' => if cmp k k' = .lt then k else k' := @@ -767,6 +780,94 @@ theorem min?_le_min?_erase [TransCmp cmp] {k km kme} : cmp km kme |>.isLE := TreeMap.minKey?_le_minKey?_erase +theorem min_eq_get_min? [TransCmp cmp] {he} : + t.min he = t.min?.get (isSome_min?_iff_isEmpty_eq_false.mpr he) := + TreeMap.minKey_eq_get_minKey? + +theorem min?_eq_some_min [TransCmp cmp] {he} : + t.min? = some (t.min he) := + TreeMap.minKey?_eq_some_minKey + +theorem min_eq_iff_getKey?_eq_self_and_forall [TransCmp cmp] {he km} : + t.min he = km ↔ t.get? km = some km ∧ ∀ k ∈ t, (cmp km k).isLE := + TreeMap.minKey_eq_iff_getKey?_eq_self_and_forall + +theorem min_eq_some_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] {he km} : + t.min he = km ↔ km ∈ t ∧ ∀ k ∈ t, (cmp km k).isLE := + TreeMap.minKey_eq_some_iff_mem_and_forall + +theorem min_insert [TransCmp cmp] {k} : + (t.insert k).min isEmpty_insert = + t.min?.elim k fun k' => if cmp k k' = .lt then k else k' := + DTreeMap.minKey_insertIfNew + +theorem min_insert_le_min [TransCmp cmp] {k he} : + cmp (t.insert k |>.min isEmpty_insert) + (t.min he) |>.isLE := + DTreeMap.minKey_insertIfNew_le_minKey + +theorem min_insert_le_self [TransCmp cmp] {k} : + cmp (t.insert k |>.min <| isEmpty_insert) k |>.isLE := + DTreeMap.minKey_insertIfNew_le_self + +theorem contains_min [TransCmp cmp] {he} : + t.contains (t.min he) := + DTreeMap.contains_minKey + +theorem min_mem [TransCmp cmp] {he} : + t.min he ∈ t := + DTreeMap.minKey_mem + +theorem min_le_of_contains [TransCmp cmp] {k} (hc : t.contains k) : + cmp (t.min <| isEmpty_eq_false_iff_exists_contains_eq_true.mpr ⟨k, hc⟩) k |>.isLE := + DTreeMap.minKey_le_of_contains hc + +theorem min_le_of_mem [TransCmp cmp] {k} (hc : k ∈ t) : + cmp (t.min <| isEmpty_eq_false_iff_exists_contains_eq_true.mpr ⟨k, hc⟩) k |>.isLE := + DTreeMap.minKey_le_of_mem hc + +theorem le_min [TransCmp cmp] {k he} : + (cmp k (t.min he)).isLE ↔ (∀ k', k' ∈ t → (cmp k k').isLE) := + DTreeMap.le_minKey + +@[simp] +theorem get?_min [TransCmp cmp] {he} : + t.get? (t.min he) = some (t.min he) := + DTreeMap.getKey?_minKey + +@[simp] +theorem get_min [TransCmp cmp] {he hc} : + t.get (t.min he) hc = t.min he := + DTreeMap.getKey_minKey + +@[simp] +theorem get!_min [TransCmp cmp] [Inhabited α] {he} : + t.get! (t.min he) = t.min he := + DTreeMap.getKey!_minKey + +@[simp] +theorem getD_min [TransCmp cmp] {he fallback} : + t.getD (t.min he) fallback = t.min he := + DTreeMap.getKeyD_minKey + +@[simp] +theorem min_erase_eq_iff_not_cmp_eq_min [TransCmp cmp] {k he} : + (t.erase k |>.min he) = + t.min (isEmpty_eq_false_of_isEmpty_erase_eq_false he) ↔ + ¬ cmp k (t.min <| isEmpty_eq_false_of_isEmpty_erase_eq_false he) = .eq := + DTreeMap.minKey_erase_eq_iff_not_compare_eq_minKey + +theorem min_erase_eq_of_not_cmp_eq_min [TransCmp cmp] {k he} : + (hc : ¬ cmp k (t.min (isEmpty_eq_false_of_isEmpty_erase_eq_false he)) = .eq) → + (t.erase k |>.min he) = + t.min (isEmpty_eq_false_of_isEmpty_erase_eq_false he) := + DTreeMap.minKey_erase_eq_of_not_compare_eq_minKey + +theorem min_le_min_erase [TransCmp cmp] {k he} : + cmp (t.min <| isEmpty_eq_false_of_isEmpty_erase_eq_false he) + (t.erase k |>.min he) |>.isLE := + DTreeMap.minKey_le_minKey_erase + end Min end Std.TreeSet diff --git a/src/Std/Data/TreeSet/Raw/Lemmas.lean b/src/Std/Data/TreeSet/Raw/Lemmas.lean index 7d3a3cacbe..9a5a3fd5e1 100644 --- a/src/Std/Data/TreeSet/Raw/Lemmas.lean +++ b/src/Std/Data/TreeSet/Raw/Lemmas.lean @@ -149,6 +149,15 @@ theorem isEmpty_erase [TransCmp cmp] (h : t.WF) {k : α} : (t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) := TreeMap.Raw.isEmpty_erase h +theorem isEmpty_eq_isEmpty_erase_and_not_containsKey [TransCmp cmp] (h : t.WF) (k : α) : + t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := + TreeMap.Raw.isEmpty_eq_isEmpty_erase_and_not_containsKey h k + +theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] (h : t.WF) {k : α} + (he : (t.erase k).isEmpty = false) : + t.isEmpty = false := + TreeMap.Raw.isEmpty_eq_false_of_isEmpty_erase_eq_false h he + @[simp] theorem contains_erase [TransCmp cmp] (h : t.WF) {k a : α} : (t.erase k).contains a = (cmp k a != .eq && t.contains a) := @@ -687,6 +696,10 @@ theorem isSome_min?_eq_not_isEmpty [TransCmp cmp] (h : t.WF) : t.min?.isSome = !t.isEmpty := TreeMap.Raw.isSome_minKey?_eq_not_isEmpty h +theorem isSome_min?_iff_isEmpty_eq_false [TransCmp cmp] (h : t.WF) : + t.min?.isSome ↔ t.isEmpty = false := + TreeMap.Raw.isSome_minKey?_iff_isEmpty_eq_false h + theorem min?_insert [TransCmp cmp] (h : t.WF) {k} : (t.insert k).min? = t.min?.elim k fun k' => if cmp k k' = .lt then k else k' :=