diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 26e9789b32..a4abf06a78 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -4045,7 +4045,7 @@ theorem get?_map' [EquivBEq α] [LawfulHashable α] (fun _ h' => (contains_eq_isSome_get? m h).trans (Option.isSome_of_mem h')) := by simp_to_model [map, Const.get?, contains, getKey] using Const.getValue?_map -theorem get?_map [LawfulBEq α] [LawfulHashable α] +theorem get?_map [LawfulBEq α] {f : α → β → γ} {k : α} (h : m.1.WF) : Const.get? (m.map f) k = (Const.get? m k).map (f k) := by simp [get?_map' m h, getKey_eq m h] @@ -4063,7 +4063,7 @@ theorem get_map' [EquivBEq α] [LawfulHashable α] (Const.get m k (contains_of_contains_map m h h'))) := by simp_to_model [map, getKey, Const.get, contains] using List.getValue_map -theorem get_map [LawfulBEq α] [LawfulHashable α] +theorem get_map [LawfulBEq α] {f : α → β → γ} {k : α} (h : m.1.WF) {h'} : Const.get (m.map f) k h' = f k (Const.get m k (contains_of_contains_map m h h')) := by simp [get_map' m h, getKey_eq m h] @@ -4076,7 +4076,7 @@ theorem get!_map' [EquivBEq α] [LawfulHashable α] [Inhabited γ] (fun _ h' => (contains_eq_isSome_get? m h).trans (Option.isSome_of_mem h'))).get! := by simp_to_model [map, getKey, Const.get!, Const.get?, contains] using List.Const.getValue!_map -theorem get!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem get!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} (h : m.1.WF) : Const.get! (m.map f) k = ((Const.get? m k).map (f k)).get! := by simp [get!_map' m h, getKey_eq m h] @@ -4094,7 +4094,7 @@ theorem getD_map' [EquivBEq α] [LawfulHashable α] (fun _ h' => (contains_eq_isSome_get? m h).trans (Option.isSome_of_mem h'))).getD fallback := by simp_to_model [map, getKey, Const.getD, Const.get?, contains] using List.Const.getValueD_map -theorem getD_map [LawfulBEq α] [LawfulHashable α] +theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} (h : m.1.WF) : Const.getD (m.map f) k fallback = ((Const.get? m k).map (f k)).getD fallback := by simp [getD_map' m h, getKey_eq m h] diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 1436c5ca56..40715fc684 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -3694,7 +3694,7 @@ theorem get?_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get?_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get?_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem get?_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} : Const.get? (m.filterMap f) k = (Const.get? m k).bind fun x => f k x := by simp [get?_filterMap] @@ -3722,7 +3722,7 @@ theorem get_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem get_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {h} : Const.get (m.filterMap f) k h = (f k (Const.get m k (mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by @@ -3737,7 +3737,7 @@ theorem get!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ] /-- Simpler variant of `get!_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem get!_filterMap' [LawfulBEq α] [Inhabited γ] {f : α → β → Option γ} {k : α} : Const.get! (m.filterMap f) k = ((Const.get? m k).bind (f k) ).get!:= by simp [get!_filterMap] @@ -3756,7 +3756,7 @@ theorem getD_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getD_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {fallback : γ} : Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind (f k)).getD fallback := by simp [getD_filterMap] @@ -4023,7 +4023,7 @@ theorem get?_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get?_filter` when `LawfulBEq` is available. -/ @[simp, grind =] -theorem get?_filter' [LawfulBEq α] [LawfulHashable α] +theorem get?_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} : Const.get? (m.filter f) k = (Const.get? m k).filter (f k) := by simp [get?_filter] @@ -4049,7 +4049,7 @@ theorem get!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β] /-- Simpler variant of `get!_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem get!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β] +theorem get!_filter' [LawfulBEq α] [Inhabited β] {f : α → β → Bool} {k : α} : Const.get! (m.filter f) k = ((Const.get? m k).filter (f k)).get! := by simp [get!_filter] @@ -4068,7 +4068,7 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filter' [LawfulBEq α] [LawfulHashable α] +theorem getD_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} {fallback : β} : Const.getD (m.filter f) k fallback = ((Const.get? m k).filter (f k)).getD fallback := by simp [getD_filter] @@ -4228,7 +4228,7 @@ namespace Const variable {β : Type v} {γ : Type w} {m : DHashMap α fun _ => β} @[simp, grind =] -theorem get?_map [LawfulBEq α] [LawfulHashable α] +theorem get?_map [LawfulBEq α] {f : α → β → γ} {k : α} : Const.get? (m.map f) k = (Const.get? m k).map (f k) := Raw₀.Const.get?_map ⟨m.1, _⟩ m.2 @@ -4247,7 +4247,7 @@ theorem get?_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] Raw₀.Const.get?_map_of_getKey?_eq_some ⟨m.1, _⟩ m.2 h @[simp, grind =] -theorem get_map [LawfulBEq α] [LawfulHashable α] +theorem get_map [LawfulBEq α] {f : α → β → γ} {k : α} {h'} : Const.get (m.map f) k h' = f k (Const.get m k (mem_of_mem_map h')) := Raw₀.Const.get_map ⟨m.1, _⟩ m.2 @@ -4261,7 +4261,7 @@ theorem get_map' [EquivBEq α] [LawfulHashable α] Raw₀.Const.get_map' ⟨m.1, _⟩ m.2 @[grind =] -theorem get!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem get!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} : Const.get! (m.map f) k = ((Const.get? m k).map (f k)).get! := Raw₀.Const.get!_map ⟨m.1, _⟩ m.2 @@ -4280,7 +4280,7 @@ theorem get!_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited Raw₀.Const.get!_map_of_getKey?_eq_some ⟨m.1, _⟩ m.2 h @[grind =] -theorem getD_map [LawfulBEq α] [LawfulHashable α] +theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} : Const.getD (m.map f) k fallback = ((Const.get? m k).map (f k)).getD fallback := Raw₀.Const.getD_map ⟨m.1, _⟩ m.2 @@ -4300,8 +4300,8 @@ theorem getD_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited theorem toList_map {m : DHashMap α fun _ => β} {f : α → β → γ} : - (Raw.Const.toList (m.map f).1).Perm - ((Raw.Const.toList m.1).map (fun p => (p.1, f p.1 p.2))) := + (Const.toList (m.map f)).Perm + ((Const.toList m).map (fun p => (p.1, f p.1 p.2))) := Raw₀.Const.toList_map ⟨m.1, m.2.size_buckets_pos⟩ end Const diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index b3c71fc2a6..f013ee6dd6 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -1217,7 +1217,7 @@ theorem contains_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) {k : α} : simp_to_raw using Raw₀.contains_keys ⟨m, _⟩ h @[simp, grind =] -theorem mem_keys [LawfulBEq α] [LawfulHashable α] (h : m.WF) {k : α} : +theorem mem_keys [LawfulBEq α] (h : m.WF) {k : α} : k ∈ m.keys ↔ k ∈ m := by rw [mem_iff_contains] simp_to_raw using Raw₀.mem_keys ⟨m, _⟩ h @@ -3905,7 +3905,7 @@ theorem get?_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get?_filterMap` when `LawfulBEq` is available. -/ @[simp, grind =] -theorem get?_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem get?_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} (h : m.WF) : Const.get? (m.filterMap f) k = (Const.get? m k).bind (f k) := by simp [get?_filterMap, h] @@ -3942,7 +3942,7 @@ theorem get!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ] /-- Simpler variant of `get!_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem get!_filterMap' [LawfulBEq α] [Inhabited γ] {f : α → β → Option γ} {k : α} (h : m.WF) : Const.get! (m.filterMap f) k = ((Const.get? m k).bind (f k)).get! := by simp [get!_filterMap, h] @@ -3962,7 +3962,7 @@ theorem getD_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getD_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {fallback : γ} (h : m.WF) : Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind (f k)).getD fallback := by simp [getD_filterMap, h] @@ -4250,7 +4250,7 @@ theorem get?_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get?_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem get?_filter' [LawfulBEq α] [LawfulHashable α] +theorem get?_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} (h : m.WF) : Const.get? (m.filter f) k = (Const.get? m k).filter (f k) := by simp [get?_filter, h] @@ -4276,7 +4276,7 @@ theorem get!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β] /-- Simpler variant of `get!_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem get!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β] +theorem get!_filter' [LawfulBEq α] [Inhabited β] {f : α → β → Bool} {k : α} (h : m.WF) : Const.get! (m.filter f) k = ((Const.get? m k).filter (f k)).get! := by simp [get!_filter, h] @@ -4295,7 +4295,7 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filter' [LawfulBEq α] [LawfulHashable α] +theorem getD_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} {fallback : β} (h : m.WF) : Const.getD (m.filter f) k fallback = ((Const.get? m k).filter (f k)).getD fallback := by simp [getD_filter, h] @@ -4466,7 +4466,7 @@ theorem get?_map' [EquivBEq α] [LawfulHashable α] simp_to_raw using Raw₀.Const.get?_map' @[simp, grind =] -theorem get?_map [LawfulBEq α] [LawfulHashable α] +theorem get?_map [LawfulBEq α] {f : α → β → γ} {k : α} (h : m.WF) : Const.get? (m.map f) k = (Const.get? m k).map (f k) := by simp [get?_map' h, getKey_eq h] @@ -4486,7 +4486,7 @@ theorem get_map' [EquivBEq α] [LawfulHashable α] simp_to_raw using Raw₀.Const.get_map' @[simp, grind =] -theorem get_map [LawfulBEq α] [LawfulHashable α] +theorem get_map [LawfulBEq α] {f : α → β → γ} {k : α} (h : m.WF) {h'} : Const.get (m.map f) k h' = f k (Const.get m k (mem_of_mem_map h h')) := by simp [get_map' h, getKey_eq h] @@ -4501,7 +4501,7 @@ theorem get!_map' [EquivBEq α] [LawfulHashable α] [Inhabited γ] simp_to_raw using Raw₀.Const.get!_map' @[grind =] -theorem get!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem get!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} (h : m.WF) : Const.get! (m.map f) k = ((Const.get? m k).map (f k)).get! := by simp [get!_map' h, getKey_eq h] @@ -4521,7 +4521,7 @@ theorem getD_map' [EquivBEq α] [LawfulHashable α] simp_to_raw using Raw₀.Const.getD_map' @[grind =] -theorem getD_map [LawfulBEq α] [LawfulHashable α] +theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} (h : m.WF) : Const.getD (m.map f) k fallback = ((Const.get? m k).map (f k)).getD fallback := by simp [getD_map' h, getKey_eq h] diff --git a/src/Std/Data/DTreeMap/Internal/Lemmas.lean b/src/Std/Data/DTreeMap/Internal/Lemmas.lean index f1400b81a7..89634db8ce 100644 --- a/src/Std/Data/DTreeMap/Internal/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Internal/Lemmas.lean @@ -73,10 +73,7 @@ private def modifyMap : Std.HashMap Name Name := (`alter, ``toListModel_alter), (`Const.alter, ``Const.toListModel_alter), (`modify, ``toListModel_modify), - (`Const.modify, ``Const.toListModel_modify), - (`filter, ``toListModel_filter), - (`map, ``toListModel_map), - (`filterMap, ``toListModel_filterMap)] + (`Const.modify, ``Const.toListModel_modify)] private def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (TSyntax `term))) := .ofList @@ -126,10 +123,15 @@ private def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (TSynta ⟨`keyAtIdx!, (``keyAtIdx!_eq_get!_map_getElem?, #[])⟩, ⟨`keyAtIdxD, (``keyAtIdxD_eq_getD_map_getElem?, #[])⟩, ⟨`Equiv, (``equiv_iff_toListModel_perm, - #[``(_root_.List.Perm.congr_left), ``(_root_.List.Perm.congr_right)])⟩] + #[``(_root_.List.Perm.congr_left), ``(_root_.List.Perm.congr_right)])⟩, + -- Note: These are not query operations but `modifyMap` is for `Perm` lemmas + -- and these are equalities + ⟨`filter, (``toListModel_filter, #[])⟩, + ⟨`map, (``toListModel_map, #[])⟩, + ⟨`filterMap, (``toListModel_filterMap, #[])⟩] /-- Internal implementation detail of the tree map -/ -syntax "simp_to_model" (" [" (ident,*) "]")? ("using" term)? : tactic +scoped syntax "simp_to_model" (" [" (ident,*) "]")? ("using" term)? : tactic macro_rules | `(tactic| simp_to_model $[[$names,*]]? $[using $using?]?) => do @@ -1045,6 +1047,10 @@ theorem mem_iff_isSome_getKey? [TransOrd α] (h : t.WF) {a : α} : a ∈ t ↔ (t.getKey? a).isSome := by simpa [mem_iff_contains] using contains_eq_isSome_getKey? h +theorem mem_of_getKey?_eq_some [TransOrd α] {a a' : α} (h : t.WF) : + t.getKey? a = some a' → a' ∈ t := by + simp_to_model [getKey?, contains] using List.containsKey_of_getKey?_eq_some + theorem getKey?_eq_none_of_contains_eq_false [TransOrd α] (h : t.WF) {a : α} : t.contains a = false → t.getKey? a = none := by simp_to_model [contains, getKey?] using List.getKey?_eq_none @@ -1072,15 +1078,15 @@ theorem getKey?_erase!_self [TransOrd α] (h : t.WF) {k : α} : theorem compare_getKey?_self [TransOrd α] (h : t.WF) {k : α} : (t.getKey? k).all (compare · k = .eq) := by simp only [compare_eq_iff_beq, Bool.decide_eq_true] - simp_to_model using List.getKey?_beq + simp_to_model [getKey?] using List.getKey?_beq theorem getKey?_congr [TransOrd α] (h : t.WF) {k k' : α} (h' : compare k k' = .eq) : t.getKey? k = t.getKey? k' := by - simp_to_model using List.getKey?_congr <| compare_eq_iff_beq.mp h' + simp_to_model [getKey?] using List.getKey?_congr <| compare_eq_iff_beq.mp h' theorem getKey?_eq_some_of_contains [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k : α} : (h' : t.contains k) → t.getKey? k = some k := by - simp_to_model using List.getKey?_eq_some + simp_to_model [getKey?, contains] using List.getKey?_eq_some theorem getKey?_eq_some [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k : α} (h' : k ∈ t) : t.getKey? k = some k := @@ -1126,15 +1132,15 @@ theorem getKey?_eq_some_getKey [TransOrd α] (h : t.WF) {a : α} {h'} : theorem compare_getKey_self [TransOrd α] (h : t.WF) {k : α} (h' : k ∈ t) : compare (t.getKey k h') k = .eq := by - simp_to_model using List.getKey_beq + simp_to_model [getKey] using List.getKey_beq theorem getKey_congr [TransOrd α] (h : t.WF) {k₁ k₂ : α} (h' : compare k₁ k₂ = .eq) (h₁ : k₁ ∈ t) : t.getKey k₁ h₁ = t.getKey k₂ ((mem_congr h h').mp h₁) := by - simp_to_model using List.getKey_congr <| compare_eq_iff_beq.mp h' + simp_to_model [getKey] using List.getKey_congr <| compare_eq_iff_beq.mp h' theorem getKey_eq [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k : α} : (h' : k ∈ t) → t.getKey k h' = k := by - simp_to_model using List.getKey_eq + simp_to_model [getKey, contains] using List.getKey_eq theorem getKey!_empty {a : α} [Inhabited α] : (empty : Impl α β).getKey! a = default := by @@ -1204,11 +1210,11 @@ theorem getKey_eq_getKey! [TransOrd α] [Inhabited α] (h : t.WF) {a : α} {h} : theorem getKey!_congr [TransOrd α] [Inhabited α] (h : t.WF) {k k' : α} : (h' : compare k k' = .eq) → t.getKey! k = t.getKey! k' := by - simp_to_model using List.getKey!_congr + simp_to_model [getKey!] using List.getKey!_congr theorem getKey!_eq_of_contains [TransOrd α] [LawfulEqOrd α] [Inhabited α] (h : t.WF) {k : α} : (h' : t.contains k) → t.getKey! k = k := by - simp_to_model using List.getKey!_eq_of_containsKey + simp_to_model [getKey!, contains] using List.getKey!_eq_of_containsKey theorem getKey!_eq_of_mem [TransOrd α] [LawfulEqOrd α] [Inhabited α] (h : t.WF) {k : α} : (h' : k ∈ t) → t.getKey! k = k := by @@ -1291,11 +1297,11 @@ theorem getKey!_eq_getKeyD_default [TransOrd α] [Inhabited α] (h : t.WF) theorem getKeyD_congr [TransOrd α] (h : t.WF) {k k' fallback : α} : (h' : compare k k' = .eq) → t.getKeyD k fallback = t.getKeyD k' fallback := by - simp_to_model using List.getKeyD_congr + simp_to_model [getKeyD] using List.getKeyD_congr theorem getKeyD_eq_of_contains [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k fallback : α} : (h' : t.contains k) → t.getKeyD k fallback = k := by - simp_to_model using List.getKeyD_eq_of_containsKey + simp_to_model [getKeyD, contains] using List.getKeyD_eq_of_containsKey theorem getKeyD_eq_of_mem [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k fallback : α} (h' : k ∈ t) : t.getKeyD k fallback = k := @@ -1583,13 +1589,17 @@ theorem mem_keys [LawfulEqOrd α] [TransOrd α] {k : α} (h : t.WF) : k ∈ t.keys ↔ k ∈ t := by simpa only [mem_iff_contains, ← List.contains_iff, ← Bool.eq_iff_iff] using contains_keys h +theorem mem_of_mem_keys [TransOrd α] (h : t.WF) {k : α} + (h' : k ∈ t.keys) : k ∈ t := + (contains_keys h).symm.trans (List.elem_eq_true_of_mem h') + theorem distinct_keys [TransOrd α] (h : t.WF) : t.keys.Pairwise (fun a b => ¬ compare a b = .eq) := by simp_to_model [keys] using h.ordered.distinctKeys.distinct theorem ordered_keys [TransOrd α] (h : t.WF) : t.keys.Pairwise (fun a b => compare a b = .lt) := by - simp_to_model; simp only [keys_eq_map] + simp_to_model [keys]; simp only [keys_eq_map] exact h.ordered.map _ fun _ _ hcmp => hcmp theorem map_fst_toList_eq_keys : @@ -1680,7 +1690,7 @@ theorem distinct_keys_toList [TransOrd α] (h : t.WF) : theorem ordered_keys_toList [TransOrd α] (h : t.WF) : (toList t).Pairwise (fun a b => compare a.1 b.1 = .lt) := by - simp_to_model + simp_to_model [Const.toList] exact h.ordered.map _ fun _ _ hcmp => hcmp end Const @@ -4367,27 +4377,27 @@ theorem minKey?_empty : theorem minKey?_of_isEmpty [TransOrd α] (h : t.WF) : (he : t.isEmpty) → t.minKey? = none := by - simp_to_model using List.minKey?_of_isEmpty + simp_to_model [minKey?, isEmpty] using List.minKey?_of_isEmpty theorem minKey?_eq_none_iff [TransOrd α] (h : t.WF) : t.minKey? = none ↔ t.isEmpty := by - simp_to_model using List.minKey?_eq_none_iff_isEmpty + simp_to_model [minKey?, isEmpty] using List.minKey?_eq_none_iff_isEmpty theorem minKey?_eq_some_iff_getKey?_eq_self_and_forall [TransOrd α] (h : t.WF) {km} : t.minKey? = some km ↔ t.getKey? km = some km ∧ ∀ k ∈ t, (compare km k).isLE := by - simp_to_model using List.minKey?_eq_some_iff_getKey?_eq_self_and_forall + simp_to_model [minKey?, getKey?, contains] using List.minKey?_eq_some_iff_getKey?_eq_self_and_forall theorem minKey?_eq_some_iff_mem_and_forall [TransOrd α] [LawfulEqOrd α] (h : t.WF) {km} : t.minKey? = some km ↔ km ∈ t ∧ ∀ k ∈ t, (compare km k).isLE := by - simp_to_model using List.minKey?_eq_some_iff_mem_and_forall + simp_to_model [minKey?, contains] using List.minKey?_eq_some_iff_mem_and_forall theorem isNone_minKey?_eq_isEmpty [TransOrd α] (h : t.WF) : t.minKey?.isNone = t.isEmpty := by - simp_to_model using List.isNone_minKey?_eq_isEmpty + simp_to_model [minKey?, isEmpty] using List.isNone_minKey?_eq_isEmpty 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 + simp_to_model [minKey?, isEmpty] 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 @@ -4396,7 +4406,7 @@ theorem isSome_minKey?_iff_isEmpty_eq_false [TransOrd α] (h : t.WF) : theorem minKey?_insert [TransOrd α] (h : t.WF) {k v} : (t.insert k v h.balanced).impl.minKey? = 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 + simp_to_model [minKey?, insert] using List.minKey?_insertEntry theorem minKey?_insert! [TransOrd α] (h : t.WF) {k v} : (t.insert! k v).minKey? = @@ -4405,7 +4415,7 @@ theorem minKey?_insert! [TransOrd α] (h : t.WF) {k v} : theorem isSome_minKey?_insert [TransOrd α] (h : t.WF) {k v} : (t.insert k v h.balanced).impl.minKey?.isSome := by - simp_to_model [insert] using List.isSome_minKey?_insertEntry + simp_to_model [minKey?, insert] using List.isSome_minKey?_insertEntry theorem isSome_minKey?_insert! [TransOrd α] (h : t.WF) {k v} : (t.insert! k v).minKey?.isSome := by @@ -4415,7 +4425,7 @@ theorem minKey?_insert_le_minKey? [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.minKey? = some km) → (hkmi : (t.insert k v h.balanced |>.impl.minKey? |>.get <| isSome_minKey?_insert h) = kmi) → compare kmi km |>.isLE := by - simp_to_model [insert] using List.minKey?_insertEntry_le_minKey? + simp_to_model [minKey?, insert] using List.minKey?_insertEntry_le_minKey? theorem minKey?_insert!_le_minKey? [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.minKey? = some km) → @@ -4426,7 +4436,7 @@ theorem minKey?_insert!_le_minKey? [TransOrd α] (h : t.WF) {k v km kmi} : theorem minKey?_insert_le_self [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insert k v h.balanced |>.impl.minKey?.get <| isSome_minKey?_insert h) = kmi) → compare kmi k |>.isLE := by - simp_to_model [insert] using List.minKey?_insertEntry_le_self + simp_to_model [minKey?, insert] using List.minKey?_insertEntry_le_self theorem minKey?_insert!_le_self [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insert! k v |>.minKey?.get <| isSome_minKey?_insert! h) = kmi) → @@ -4436,16 +4446,16 @@ theorem minKey?_insert!_le_self [TransOrd α] (h : t.WF) {k v kmi} : theorem contains_minKey? [TransOrd α] (h : t.WF) {km} : (hkm : t.minKey? = some km) → t.contains km := by - simp_to_model using List.containsKey_minKey? + simp_to_model [minKey?, contains] using List.containsKey_minKey? theorem minKey?_mem [TransOrd α] (h : t.WF) {km} : (hkm : t.minKey? = some km) → km ∈ t := by - simp_to_model using List.containsKey_minKey? + simp_to_model [minKey?, contains] using List.containsKey_minKey? theorem isSome_minKey?_of_contains [TransOrd α] (h : t.WF) {k} : (hc : t.contains k) → t.minKey?.isSome := by - simp_to_model using List.isSome_minKey?_of_containsKey + simp_to_model [minKey?, contains] using List.isSome_minKey?_of_containsKey theorem isSome_minKey?_of_mem [TransOrd α] (h : t.WF) {k} : k ∈ t → t.minKey?.isSome := @@ -4454,7 +4464,7 @@ theorem isSome_minKey?_of_mem [TransOrd α] (h : t.WF) {k} : theorem minKey?_le_of_contains [TransOrd α] (h : t.WF) {k km} : (hc : t.contains k) → (hkm : (t.minKey?.get <| isSome_minKey?_of_contains h hc) = km) → compare km k |>.isLE := by - simp_to_model using minKey?_le_of_containsKey + simp_to_model [minKey?, contains] using minKey?_le_of_containsKey theorem minKey?_le_of_mem [TransOrd α] (h : t.WF) {k km} : (hc : k ∈ t) → (hkm : (t.minKey?.get <| isSome_minKey?_of_mem h hc) = km) → @@ -4464,34 +4474,34 @@ theorem minKey?_le_of_mem [TransOrd α] (h : t.WF) {k km} : theorem le_minKey? [TransOrd α] {k} (h : t.WF) : (∀ k', t.minKey? = some k' → (compare k k').isLE) ↔ (∀ k', k' ∈ t → (compare k k').isLE) := by - simp_to_model using List.le_minKey? + simp_to_model [minKey?, contains] using List.le_minKey? theorem getKey?_minKey? [TransOrd α] (h : t.WF) {km} : (hkm : t.minKey? = some km) → t.getKey? km = some km := by - simp_to_model using List.getKey?_minKey? + simp_to_model [minKey?, getKey?] using List.getKey?_minKey? theorem getKey_minKey? [TransOrd α] (h : t.WF) {km hc} : (hkm : t.minKey?.get (isSome_minKey?_of_contains h hc) = km) → t.getKey km hc = km := by - simp_to_model using List.getKey_minKey? + simp_to_model [minKey?, getKey] using List.getKey_minKey? theorem getKey!_minKey? [TransOrd α] [Inhabited α] (h : t.WF) {km} : (hkm : t.minKey? = some km) → t.getKey! km = km := by - simp_to_model using List.getKey!_minKey? + simp_to_model [minKey?, getKey!] using List.getKey!_minKey? theorem getKeyD_minKey? [TransOrd α] (h : t.WF) {km fallback} : (hkm : t.minKey? = some km) → t.getKeyD km fallback = km := by - simp_to_model using List.getKeyD_minKey? + simp_to_model [minKey?, getKeyD] using List.getKeyD_minKey? @[simp] theorem minKey?_bind_getKey? [TransOrd α] (h : t.WF) : t.minKey?.bind t.getKey? = t.minKey? := by change (t.minKey?.bind fun k => t.getKey? k) = t.minKey? - simp_to_model using List.minKey?_bind_getKey? + simp_to_model [minKey?, getKey?] using List.minKey?_bind_getKey? theorem minKey?_erase_eq_iff_not_compare_eq_minKey? [TransOrd α] (h : t.WF) {k} : (t.erase k h.balanced |>.impl.minKey?) = t.minKey? ↔ ∀ {km}, t.minKey? = some km → ¬ compare k km = .eq := by - simp_to_model [erase] using minKey?_eraseKey_eq_iff_beq_minKey?_eq_false + simp_to_model [erase, minKey?] using minKey?_eraseKey_eq_iff_beq_minKey?_eq_false theorem minKey?_erase!_eq_iff_not_compare_eq_minKey? [TransOrd α] (h : t.WF) {k} : (t.erase! k |>.minKey?) = t.minKey? ↔ @@ -4501,7 +4511,7 @@ theorem minKey?_erase!_eq_iff_not_compare_eq_minKey? [TransOrd α] (h : t.WF) {k theorem minKey?_erase_eq_of_not_compare_eq_minKey? [TransOrd α] (h : t.WF) {k} : (hc : ∀ {km}, t.minKey? = some km → ¬ compare k km = .eq) → (t.erase k h.balanced |>.impl.minKey?) = t.minKey? := by - simp_to_model [erase] using minKey?_eraseKey_eq_of_beq_minKey?_eq_false + simp_to_model [erase, minKey?] using minKey?_eraseKey_eq_of_beq_minKey?_eq_false theorem minKey?_erase!_eq_of_not_compare_eq_minKey? [TransOrd α] (h : t.WF) {k} : (hc : ∀ {km}, t.minKey? = some km → ¬ compare k km = .eq) → @@ -4511,7 +4521,7 @@ theorem minKey?_erase!_eq_of_not_compare_eq_minKey? [TransOrd α] (h : t.WF) {k} theorem isSome_minKey?_of_isSome_minKey?_erase [TransOrd α] (h : t.WF) {k} : (hs : t.erase k h.balanced |>.impl.minKey?.isSome) → t.minKey?.isSome := by - simp_to_model [erase] using isSome_minKey?_of_isSome_minKey?_eraseKey + simp_to_model [erase, minKey?] using isSome_minKey?_of_isSome_minKey?_eraseKey theorem isSome_minKey?_of_isSome_minKey?_erase! [TransOrd α] (h : t.WF) {k} : (hs : t.erase! k |>.minKey?.isSome) → @@ -4523,7 +4533,7 @@ theorem minKey?_le_minKey?_erase [TransOrd α] (h : t.WF) {k km kme} : (hkm : (t.minKey?.get <| isSome_minKey?_of_isSome_minKey?_erase h <| hkme ▸ Option.isSome_some) = km) → compare km kme |>.isLE := by - simp_to_model [erase] using minKey?_le_minKey?_eraseKey + simp_to_model [erase, minKey?] using minKey?_le_minKey?_eraseKey theorem minKey?_le_minKey?_erase! [TransOrd α] (h : t.WF) {k km kme} : (hkme : (t.erase! k |>.minKey?) = some kme) → @@ -4535,7 +4545,7 @@ theorem minKey?_le_minKey?_erase! [TransOrd α] (h : t.WF) {k km kme} : theorem minKey?_insertIfNew [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew k v h.balanced).impl.minKey? = some (t.minKey?.elim k fun k' => if compare k k' = .lt then k else k') := by - simp_to_model [insertIfNew] using List.minKey?_insertEntryIfNew + simp_to_model [insertIfNew, minKey?] using List.minKey?_insertEntryIfNew theorem minKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew! k v).minKey? = @@ -4544,7 +4554,7 @@ theorem minKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v} : theorem isSome_minKey?_insertIfNew [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew k v h.balanced).impl.minKey?.isSome := by - simp_to_model [insertIfNew] using List.isSome_minKey?_insertEntryIfNew + simp_to_model [insertIfNew, minKey?] using List.isSome_minKey?_insertEntryIfNew theorem isSome_minKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew! k v).minKey?.isSome := by @@ -4554,7 +4564,7 @@ theorem minKey?_insertIfNew_le_minKey? [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.minKey? = some km) → (hkmi : (t.insertIfNew k v h.balanced |>.impl.minKey? |>.get <| isSome_minKey?_insertIfNew h) = kmi) → compare kmi km |>.isLE := by - simp_to_model [insertIfNew] using List.minKey?_insertEntryIfNew_le_minKey? + simp_to_model [insertIfNew, minKey?] using List.minKey?_insertEntryIfNew_le_minKey? theorem minKey?_insertIfNew!_le_minKey? [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.minKey? = some km) → @@ -4565,7 +4575,7 @@ theorem minKey?_insertIfNew!_le_minKey? [TransOrd α] (h : t.WF) {k v km kmi} : theorem minKey?_insertIfNew_le_self [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insertIfNew k v h.balanced |>.impl.minKey?.get <| isSome_minKey?_insertIfNew h) = kmi) → compare kmi k |>.isLE := by - simp_to_model [insertIfNew] using List.minKey?_insertEntryIfNew_le_self + simp_to_model [insertIfNew, minKey?] using List.minKey?_insertEntryIfNew_le_self theorem minKey?_insertIfNew!_le_self [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insertIfNew! k v |>.minKey?.get <| isSome_minKey?_insertIfNew! h) = kmi) → @@ -4578,12 +4588,12 @@ theorem minKey?_eq_head?_keys [TransOrd α] (h : t.WF) : theorem minKey?_modify [TransOrd α] [LawfulEqOrd α] {k f} (h : t.WF) : (t.modify k f).minKey? = t.minKey? := by - simp_to_model [modify] using List.minKey?_modifyKey + simp_to_model [modify, minKey?] using List.minKey?_modifyKey theorem minKey?_alter_eq_self [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f} : (t.alter k f h.balanced).impl.minKey? = some k ↔ (f (t.get? k)).isSome ∧ ∀ k', k' ∈ t → (compare k k').isLE := by - simp_to_model [alter] using List.minKey?_alterKey_eq_self + simp_to_model [alter, minKey?, contains, get?] using List.minKey?_alterKey_eq_self theorem minKey?_alter!_eq_self [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f} : (t.alter! k f).minKey? = some k ↔ @@ -4596,31 +4606,31 @@ variable {β : Type v} {t : Impl α β} theorem minKey?_modify [TransOrd α] (h : t.WF) {k f} : (Const.modify k f t).minKey? = t.minKey?.map fun km => if compare km k = .eq then k else km := by - simp_to_model [Const.modify] using List.Const.minKey?_modifyKey + simp_to_model [Const.modify, minKey?] using List.Const.minKey?_modifyKey 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_eq_minKey? + simp_to_model [Const.modify, minKey?] 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 - simp_to_model [Const.modify] using List.Const.isSome_minKey?_modifyKey + simp_to_model [Const.modify, minKey?, isEmpty] using List.Const.isSome_minKey?_modifyKey theorem isSome_minKey?_modify_eq_isSome [TransOrd α] (h : t.WF) {k f} : (Const.modify k f t).minKey?.isSome = t.minKey?.isSome := by - simp_to_model [Const.modify] using List.Const.isSome_minKey?_modifyKey_eq_isSome + simp_to_model [Const.modify, minKey?] using List.Const.isSome_minKey?_modifyKey_eq_isSome theorem compare_minKey?_modify_eq [TransOrd α] (h : t.WF) {k f km kmm} : (hkm : t.minKey? = some km) → (hkmm : (Const.modify k f t |>.minKey? |>.get <| (isSome_minKey?_modify_eq_isSome h).trans <| hkm ▸ Option.isSome_some) = kmm) → compare kmm km = .eq := by - simp_to_model [Const.modify] using List.Const.minKey?_modifyKey_beq + simp_to_model [Const.modify, minKey?] using List.Const.minKey?_modifyKey_beq theorem minKey?_alter_eq_self [TransOrd α] (h : t.WF) {k f} : (Const.alter k f t h.balanced).impl.minKey? = some k ↔ (f (Const.get? t k)).isSome ∧ ∀ k', k' ∈ t → (compare k k').isLE := by - simp_to_model [Const.alter] using List.Const.minKey?_alterKey_eq_self + simp_to_model [Const.alter, minKey?, contains, Const.get?] using List.Const.minKey?_alterKey_eq_self theorem minKey?_alter!_eq_self [TransOrd α] (h : t.WF) {k f} : (Const.alter! k f t).minKey? = some k ↔ @@ -5204,27 +5214,27 @@ theorem maxKey?_empty : theorem maxKey?_of_isEmpty [TransOrd α] (h : t.WF) : (he : t.isEmpty) → t.maxKey? = none := by - simp_to_model using List.maxKey?_of_isEmpty + simp_to_model [maxKey?, isEmpty] using List.maxKey?_of_isEmpty theorem maxKey?_eq_none_iff [TransOrd α] (h : t.WF) : t.maxKey? = none ↔ t.isEmpty := by - simp_to_model using List.maxKey?_eq_none_iff_isEmpty + simp_to_model [maxKey?, isEmpty] using List.maxKey?_eq_none_iff_isEmpty theorem maxKey?_eq_some_iff_getKey?_eq_self_and_forall [TransOrd α] (h : t.WF) {km} : t.maxKey? = some km ↔ t.getKey? km = some km ∧ ∀ k ∈ t, (compare k km).isLE := by - simp_to_model using List.maxKey?_eq_some_iff_getKey?_eq_self_and_forall + simp_to_model [maxKey?, getKey?, contains] using List.maxKey?_eq_some_iff_getKey?_eq_self_and_forall theorem maxKey?_eq_some_iff_mem_and_forall [TransOrd α] [LawfulEqOrd α] (h : t.WF) {km} : t.maxKey? = some km ↔ km ∈ t ∧ ∀ k ∈ t, (compare k km).isLE := by - simp_to_model using List.maxKey?_eq_some_iff_mem_and_forall + simp_to_model [maxKey?, contains] using List.maxKey?_eq_some_iff_mem_and_forall theorem isNone_maxKey?_eq_isEmpty [TransOrd α] (h : t.WF) : t.maxKey?.isNone = t.isEmpty := by - simp_to_model using List.isNone_maxKey?_eq_isEmpty + simp_to_model [maxKey?, isEmpty] using List.isNone_maxKey?_eq_isEmpty theorem isSome_maxKey?_eq_not_isEmpty [TransOrd α] (h : t.WF) : t.maxKey?.isSome = !t.isEmpty := by - simp_to_model using List.isSome_maxKey?_eq_not_isEmpty + simp_to_model [maxKey?, isEmpty] using List.isSome_maxKey?_eq_not_isEmpty theorem isSome_maxKey?_iff_isEmpty_eq_false [TransOrd α] (h : t.WF) : t.maxKey?.isSome ↔ t.isEmpty = false := by @@ -5233,7 +5243,7 @@ theorem isSome_maxKey?_iff_isEmpty_eq_false [TransOrd α] (h : t.WF) : theorem maxKey?_insert [TransOrd α] (h : t.WF) {k v} : (t.insert k v h.balanced).impl.maxKey? = some (t.maxKey?.elim k fun k' => if compare k' k|>.isLE then k else k') := by - simp_to_model [insert] using List.maxKey?_insertEntry + simp_to_model [insert, maxKey?] using List.maxKey?_insertEntry theorem maxKey?_insert! [TransOrd α] (h : t.WF) {k v} : (t.insert! k v).maxKey? = @@ -5242,7 +5252,7 @@ theorem maxKey?_insert! [TransOrd α] (h : t.WF) {k v} : theorem isSome_maxKey?_insert [TransOrd α] (h : t.WF) {k v} : (t.insert k v h.balanced).impl.maxKey?.isSome := by - simp_to_model [insert] using List.isSome_maxKey?_insertEntry + simp_to_model [insert, maxKey?] using List.isSome_maxKey?_insertEntry theorem isSome_maxKey?_insert! [TransOrd α] (h : t.WF) {k v} : (t.insert! k v).maxKey?.isSome := by @@ -5252,7 +5262,7 @@ theorem maxKey?_le_maxKey?_insert [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.maxKey? = some km) → (hkmi : (t.insert k v h.balanced |>.impl.maxKey? |>.get <| isSome_maxKey?_insert h) = kmi) → compare km kmi |>.isLE := by - simp_to_model [insert] using List.maxKey?_le_maxKey?_insertEntry + simp_to_model [insert, maxKey?] using List.maxKey?_le_maxKey?_insertEntry theorem maxKey?_le_maxKey?_insert! [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.maxKey? = some km) → @@ -5263,7 +5273,7 @@ theorem maxKey?_le_maxKey?_insert! [TransOrd α] (h : t.WF) {k v km kmi} : theorem self_le_maxKey?_insert [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insert k v h.balanced |>.impl.maxKey?.get <| isSome_maxKey?_insert h) = kmi) → compare k kmi |>.isLE := by - simp_to_model [insert] using List.self_le_maxKey?_insertEntry + simp_to_model [insert, maxKey?] using List.self_le_maxKey?_insertEntry theorem self_le_maxKey?_insert! [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insert! k v |>.maxKey?.get <| isSome_maxKey?_insert! h) = kmi) → @@ -5273,16 +5283,16 @@ theorem self_le_maxKey?_insert! [TransOrd α] (h : t.WF) {k v kmi} : theorem contains_maxKey? [TransOrd α] (h : t.WF) {km} : (hkm : t.maxKey? = some km) → t.contains km := by - simp_to_model using List.containsKey_maxKey? + simp_to_model [maxKey?, contains] using List.containsKey_maxKey? theorem maxKey?_mem [TransOrd α] (h : t.WF) {km} : (hkm : t.maxKey? = some km) → km ∈ t := by - simp_to_model using List.containsKey_maxKey? + simp_to_model [maxKey?, contains] using List.containsKey_maxKey? theorem isSome_maxKey?_of_contains [TransOrd α] (h : t.WF) {k} : (hc : t.contains k) → t.maxKey?.isSome := by - simp_to_model using List.isSome_maxKey?_of_containsKey + simp_to_model [maxKey?, contains] using List.isSome_maxKey?_of_containsKey theorem isSome_maxKey?_of_mem [TransOrd α] (h : t.WF) {k} : k ∈ t → t.maxKey?.isSome := @@ -5291,7 +5301,7 @@ theorem isSome_maxKey?_of_mem [TransOrd α] (h : t.WF) {k} : theorem le_maxKey?_of_contains [TransOrd α] (h : t.WF) {k km} : (hc : t.contains k) → (hkm : (t.maxKey?.get <| isSome_maxKey?_of_contains h hc) = km) → compare k km |>.isLE := by - simp_to_model using maxKey?_le_of_containsKey + simp_to_model [maxKey?, contains] using maxKey?_le_of_containsKey theorem le_maxKey?_of_mem [TransOrd α] (h : t.WF) {k km} : (hc : k ∈ t) → (hkm : (t.maxKey?.get <| isSome_maxKey?_of_mem h hc) = km) → @@ -5301,34 +5311,34 @@ theorem le_maxKey?_of_mem [TransOrd α] (h : t.WF) {k km} : theorem maxKey?_le [TransOrd α] {k} (h : t.WF) : (∀ k', t.maxKey? = some k' → (compare k' k).isLE) ↔ (∀ k', k' ∈ t → (compare k' k).isLE) := by - simp_to_model using List.maxKey?_le + simp_to_model [maxKey?, contains] using List.maxKey?_le theorem getKey?_maxKey? [TransOrd α] (h : t.WF) {km} : (hkm : t.maxKey? = some km) → t.getKey? km = some km := by - simp_to_model using List.getKey?_maxKey? + simp_to_model [maxKey?, getKey?] using List.getKey?_maxKey? theorem getKey_maxKey? [TransOrd α] (h : t.WF) {km hc} : (hkm : t.maxKey?.get (isSome_maxKey?_of_contains h hc) = km) → t.getKey km hc = km := by - simp_to_model using List.getKey_maxKey? + simp_to_model [maxKey?, getKey] using List.getKey_maxKey? theorem getKey!_maxKey? [TransOrd α] [Inhabited α] (h : t.WF) {km} : (hkm : t.maxKey? = some km) → t.getKey! km = km := by - simp_to_model using List.getKey!_maxKey? + simp_to_model [maxKey?, getKey!] using List.getKey!_maxKey? theorem getKeyD_maxKey? [TransOrd α] (h : t.WF) {km fallback} : (hkm : t.maxKey? = some km) → t.getKeyD km fallback = km := by - simp_to_model using List.getKeyD_maxKey? + simp_to_model [maxKey?, getKeyD] using List.getKeyD_maxKey? @[simp] theorem maxKey?_bind_getKey? [TransOrd α] (h : t.WF) : t.maxKey?.bind t.getKey? = t.maxKey? := by change (t.maxKey?.bind fun k => t.getKey? k) = t.maxKey? - simp_to_model using List.maxKey?_bind_getKey? + simp_to_model [maxKey?, getKey?] using List.maxKey?_bind_getKey? theorem maxKey?_erase_eq_iff_not_compare_eq_maxKey? [TransOrd α] (h : t.WF) {k} : (t.erase k h.balanced |>.impl.maxKey?) = t.maxKey? ↔ ∀ {km}, t.maxKey? = some km → ¬ compare k km = .eq := by - simp_to_model [erase] using maxKey?_eraseKey_eq_iff_beq_maxKey?_eq_false + simp_to_model [erase, maxKey?] using maxKey?_eraseKey_eq_iff_beq_maxKey?_eq_false theorem maxKey?_erase!_eq_iff_not_compare_eq_maxKey? [TransOrd α] (h : t.WF) {k} : (t.erase! k |>.maxKey?) = t.maxKey? ↔ @@ -5338,7 +5348,7 @@ theorem maxKey?_erase!_eq_iff_not_compare_eq_maxKey? [TransOrd α] (h : t.WF) {k theorem maxKey?_erase_eq_of_not_compare_eq_maxKey? [TransOrd α] (h : t.WF) {k} : (hc : ∀ {km}, t.maxKey? = some km → ¬ compare k km = .eq) → (t.erase k h.balanced |>.impl.maxKey?) = t.maxKey? := by - simp_to_model [erase] using maxKey?_eraseKey_eq_of_beq_maxKey?_eq_false + simp_to_model [erase, maxKey?] using maxKey?_eraseKey_eq_of_beq_maxKey?_eq_false theorem maxKey?_erase!_eq_of_not_compare_eq_maxKey? [TransOrd α] (h : t.WF) {k} : (hc : ∀ {km}, t.maxKey? = some km → ¬ compare k km = .eq) → @@ -5348,7 +5358,7 @@ theorem maxKey?_erase!_eq_of_not_compare_eq_maxKey? [TransOrd α] (h : t.WF) {k} theorem isSome_maxKey?_of_isSome_maxKey?_erase [TransOrd α] (h : t.WF) {k} : (hs : t.erase k h.balanced |>.impl.maxKey?.isSome) → t.maxKey?.isSome := by - simp_to_model [erase] using isSome_maxKey?_of_isSome_maxKey?_eraseKey + simp_to_model [erase, maxKey?] using isSome_maxKey?_of_isSome_maxKey?_eraseKey theorem isSome_maxKey?_of_isSome_maxKey?_erase! [TransOrd α] (h : t.WF) {k} : (hs : t.erase! k |>.maxKey?.isSome) → @@ -5360,7 +5370,7 @@ theorem maxKey?_erase_le_maxKey? [TransOrd α] (h : t.WF) {k km kme} : (hkm : (t.maxKey?.get <| isSome_maxKey?_of_isSome_maxKey?_erase h <| hkme ▸ Option.isSome_some) = km) → compare kme km |>.isLE := by - simp_to_model [erase] using maxKey?_eraseKey_le_maxKey? + simp_to_model [erase, maxKey?] using maxKey?_eraseKey_le_maxKey? theorem maxKey?_erase!_le_maxKey? [TransOrd α] (h : t.WF) {k km kme} : (hkme : (t.erase! k |>.maxKey?) = some kme) → @@ -5372,7 +5382,7 @@ theorem maxKey?_erase!_le_maxKey? [TransOrd α] (h : t.WF) {k km kme} : theorem maxKey?_insertIfNew [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew k v h.balanced).impl.maxKey? = some (t.maxKey?.elim k fun k' => if compare k' k = .lt then k else k') := by - simp_to_model [insertIfNew] using List.maxKey?_insertEntryIfNew + simp_to_model [insertIfNew, maxKey?] using List.maxKey?_insertEntryIfNew theorem maxKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew! k v).maxKey? = @@ -5381,7 +5391,7 @@ theorem maxKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v} : theorem isSome_maxKey?_insertIfNew [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew k v h.balanced).impl.maxKey?.isSome := by - simp_to_model [insertIfNew] using List.isSome_maxKey?_insertEntryIfNew + simp_to_model [insertIfNew, maxKey?] using List.isSome_maxKey?_insertEntryIfNew theorem isSome_maxKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v} : (t.insertIfNew! k v).maxKey?.isSome := by @@ -5391,7 +5401,7 @@ theorem maxKey?_le_maxKey?_insertIfNew [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.maxKey? = some km) → (hkmi : (t.insertIfNew k v h.balanced |>.impl.maxKey? |>.get <| isSome_maxKey?_insertIfNew h) = kmi) → compare km kmi |>.isLE := by - simp_to_model [insertIfNew] using List.maxKey?_le_maxKey?_insertEntryIfNew + simp_to_model [insertIfNew, maxKey?] using List.maxKey?_le_maxKey?_insertEntryIfNew theorem maxKey?_le_maxKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v km kmi} : (hkm : t.maxKey? = some km) → @@ -5402,7 +5412,7 @@ theorem maxKey?_le_maxKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v km kmi} : theorem self_le_maxKey?_insertIfNew [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insertIfNew k v h.balanced |>.impl.maxKey?.get <| isSome_maxKey?_insertIfNew h) = kmi) → compare k kmi |>.isLE := by - simp_to_model [insertIfNew] using List.self_le_maxKey?_insertEntryIfNew + simp_to_model [insertIfNew, maxKey?] using List.self_le_maxKey?_insertEntryIfNew theorem self_le_maxKey?_insertIfNew! [TransOrd α] (h : t.WF) {k v kmi} : (hkmi : (t.insertIfNew! k v |>.maxKey?.get <| isSome_maxKey?_insertIfNew! h) = kmi) → @@ -5415,12 +5425,12 @@ theorem maxKey?_eq_getLast?_keys [TransOrd α] (h : t.WF) : theorem maxKey?_modify [TransOrd α] [LawfulEqOrd α] {k f} (h : t.WF) : (t.modify k f).maxKey? = t.maxKey? := by - simp_to_model [modify] using List.maxKey?_modifyKey + simp_to_model [modify, maxKey?] using List.maxKey?_modifyKey theorem maxKey?_alter_eq_self [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f} : (t.alter k f h.balanced).impl.maxKey? = some k ↔ (f (t.get? k)).isSome ∧ ∀ k', k' ∈ t → (compare k' k).isLE := by - simp_to_model [alter] using List.maxKey?_alterKey_eq_self + simp_to_model [alter, maxKey?, get?, contains] using List.maxKey?_alterKey_eq_self theorem maxKey?_alter!_eq_self [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f} : (t.alter! k f).maxKey? = some k ↔ @@ -5433,31 +5443,31 @@ variable {β : Type v} {t : Impl α β} theorem maxKey?_modify [TransOrd α] (h : t.WF) {k f} : (Const.modify k f t).maxKey? = t.maxKey?.map fun km => if compare km k = .eq then k else km := by - simp_to_model [Const.modify] using List.Const.maxKey?_modifyKey + simp_to_model [Const.modify, maxKey?] using List.Const.maxKey?_modifyKey theorem maxKey?_modify_eq_maxKey? [TransOrd α] [LawfulEqOrd α] (h : t.WF) {k f} : (Const.modify k f t).maxKey? = t.maxKey? := by - simp_to_model [Const.modify] using List.Const.maxKey?_modifyKey_eq_maxKey? + simp_to_model [Const.modify, maxKey?] using List.Const.maxKey?_modifyKey_eq_maxKey? theorem isSome_maxKey?_modify [TransOrd α] {k f} (h : t.WF) : (Const.modify k f t).maxKey?.isSome = !t.isEmpty := by - simp_to_model [Const.modify] using List.Const.isSome_maxKey?_modifyKey + simp_to_model [Const.modify, maxKey?, isEmpty] using List.Const.isSome_maxKey?_modifyKey theorem isSome_maxKey?_modify_eq_isSome [TransOrd α] (h : t.WF) {k f} : (Const.modify k f t).maxKey?.isSome = t.maxKey?.isSome := by - simp_to_model [Const.modify] using List.Const.isSome_maxKey?_modifyKey_eq_isSome + simp_to_model [Const.modify, maxKey?] using List.Const.isSome_maxKey?_modifyKey_eq_isSome theorem compare_maxKey?_modify_eq [TransOrd α] (h : t.WF) {k f km kmm} : (hkm : t.maxKey? = some km) → (hkmm : (Const.modify k f t |>.maxKey? |>.get <| (isSome_maxKey?_modify_eq_isSome h).trans <| hkm ▸ Option.isSome_some) = kmm) → compare kmm km = .eq := by - simp_to_model [Const.modify] using List.Const.maxKey?_modifyKey_beq + simp_to_model [Const.modify, maxKey?] using List.Const.maxKey?_modifyKey_beq theorem maxKey?_alter_eq_self [TransOrd α] (h : t.WF) {k f} : (Const.alter k f t h.balanced).impl.maxKey? = some k ↔ (f (Const.get? t k)).isSome ∧ ∀ k', k' ∈ t → (compare k' k).isLE := by - simp_to_model [Const.alter] using List.Const.maxKey?_alterKey_eq_self + simp_to_model [Const.alter, maxKey?, Const.get?, contains] using List.Const.maxKey?_alterKey_eq_self theorem maxKey?_alter!_eq_self [TransOrd α] (h : t.WF) {k f} : (Const.alter! k f t).maxKey? = some k ↔ @@ -6820,4 +6830,1107 @@ end Const end Equiv +section filterMap + +variable {γ : α → Type w} + +theorem toList_filterMap {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f h.balanced).1.toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := by + simp_to_model [filterMap, toList, Equiv] + +theorem toList_filterMap! {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap! f).toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := by + simpa only [filterMap_eq_filterMap!] using toList_filterMap h + +theorem isEmpty_filterMap_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f h.balanced).1.isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f k (t.get k h) = none := by + simp_to_model [filterMap, isEmpty, contains, get] using List.isEmpty_filterMap_eq_true + +theorem isEmpty_filterMap!_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap! f).isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f k (t.get k h) = none := by + simpa only [filterMap_eq_filterMap!] using isEmpty_filterMap_iff h + +theorem isEmpty_filterMap_eq_false_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f h.balanced).1.isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), (f k (t.get k h)).isSome := by + simp_to_model [filterMap, isEmpty, contains, get] using List.isEmpty_filterMap_eq_false + +theorem isEmpty_filterMap!_eq_false_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap! f).isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), (f k (t.get k h)).isSome := by + simpa only [filterMap_eq_filterMap!] using isEmpty_filterMap_eq_false_iff h + +theorem contains_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.contains k = (t.get? k).any (f k · |>.isSome) := by + simp_to_model [filterMap, contains, get?] using List.containsKey_filterMap + +theorem contains_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap! f).contains k = (t.get? k).any (f k · |>.isSome) := by + simpa only [filterMap_eq_filterMap!] using contains_filterMap h + +theorem contains_of_contains_filterMap [TransOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.contains k = true → t.contains k = true := by + simp_to_model [filterMap, contains] using containsKey_of_containsKey_filterMap + +theorem contains_of_contains_filterMap! [TransOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap! f).contains k = true → t.contains k = true := by + simpa only [filterMap_eq_filterMap!] using contains_of_contains_filterMap h + +theorem size_filterMap_le_size [TransOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f h.balanced).1.size ≤ t.size := by + simp_to_model [filterMap, size] using List.length_filterMap_le + +theorem size_filterMap!_le_size [TransOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap! f).size ≤ t.size := by + simpa only [filterMap_eq_filterMap!] using size_filterMap_le_size h + +theorem size_filterMap_eq_size_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f h.balanced).1.size = t.size ↔ ∀ (a : α) (h : t.contains a), (f a (t.get a h)).isSome := by + simp_to_model [filterMap, size, contains, get] using List.length_filterMap_eq_length_iff + +theorem size_filterMap!_eq_size_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap! f).size = t.size ↔ ∀ (a : α) (h : t.contains a), (f a (t.get a h)).isSome := by + simpa only [filterMap_eq_filterMap!] using size_filterMap_eq_size_iff h + +theorem get?_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.get? k = (t.get? k).bind (f k) := by + simp_to_model [filterMap, get?] using List.getValueCast?_filterMap + +theorem get?_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap! f).get? k = (t.get? k).bind (f k) := by + simpa only [filterMap_eq_filterMap!] using get?_filterMap h + +theorem isSome_apply_of_contains_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + ∀ (h' : (t.filterMap f h.balanced).1.contains k = true), + (f k (t.get k (contains_of_contains_filterMap h h'))).isSome := by + simp_to_model [filterMap, contains, get] using List.isSome_apply_of_containsKey_filterMap + +theorem isSome_apply_of_contains_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + ∀ (h' : (t.filterMap! f).contains k = true), + (f k (t.get k (contains_of_contains_filterMap! h h'))).isSome := by + simpa only [filterMap_eq_filterMap!] using isSome_apply_of_contains_filterMap h + +theorem get_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) {h'} : + (t.filterMap f h.balanced).1.get k h' = + (f k (t.get k (contains_of_contains_filterMap h h'))).get + (isSome_apply_of_contains_filterMap h h') := by + simp_to_model [filterMap, get] using List.getValueCast_filterMap + +theorem get_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) {h' : _} : + (t.filterMap! f).get k h' = + (f k (t.get k (contains_of_contains_filterMap! h h'))).get + (isSome_apply_of_contains_filterMap! h h') := by + simpa only [filterMap_eq_filterMap!] using + get_filterMap h (h' := by simpa only [filterMap_eq_filterMap!] using h') + +theorem get!_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} [Inhabited (γ k)] (h : t.WF) : + (t.filterMap f h.balanced).1.get! k = ((t.get? k).bind (f k)).get! := by + simp_to_model [filterMap, get!, get?] using List.getValueCast!_filterMap + +theorem get!_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} [Inhabited (γ k)] (h : t.WF) : + (t.filterMap! f).get! k = ((t.get? k).bind (f k)).get! := by + simpa only [filterMap_eq_filterMap!] using get!_filterMap h + +theorem getD_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} {fallback : γ k} (h : t.WF) : + (t.filterMap f h.balanced).1.getD k fallback = ((t.get? k).bind (f k)).getD fallback := by + simp_to_model [filterMap, getD, get?] using List.getValueCastD_filterMap + +theorem getD_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} {fallback : γ k} (h : t.WF) : + (t.filterMap! f).getD k fallback = ((t.get? k).bind (f k)).getD fallback := by + simpa only [filterMap_eq_filterMap!] using getD_filterMap h + +theorem getKey?_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome) := by + simp_to_model [filterMap, getKey?, get] using List.getKey?_filterMap + +theorem getKey?_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap! f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome) := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using getKey?_filterMap h + +theorem getKey_filterMap [TransOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) {h'} : + (t.filterMap f h.balanced).1.getKey k h' = t.getKey k (contains_of_contains_filterMap h h') := by + simp_to_model [filterMap, getKey] using List.getKey_filterMap + +theorem getKey_filterMap! [TransOrd α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) {h'} : + (t.filterMap! f).getKey k h' = t.getKey k (contains_of_contains_filterMap! h h') := by + simpa only [filterMap_eq_filterMap!] using + getKey_filterMap h (h' := by simpa only [filterMap_eq_filterMap!] using h') + +theorem getKey!_filterMap [TransOrd α] [LawfulEqOrd α] [Inhabited α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome)).get! := by + simp_to_model [filterMap, getKey!, getKey?, get] using List.getKey!_filterMap + +theorem getKey!_filterMap! [TransOrd α] [LawfulEqOrd α] [Inhabited α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap! f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome)).get! := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using getKey!_filterMap h + +theorem getKeyD_filterMap [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k fallback : α} (h : t.WF) : + (t.filterMap f h.balanced).1.getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := by + simp_to_model [filterMap, getKeyD, getKey?, get] using List.getKeyD_filterMap + +theorem getKeyD_filterMap! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Option (γ a)} {k fallback : α} (h : t.WF) : + (t.filterMap! f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using getKeyD_filterMap h + +namespace Const + +variable {β : Type v} {γ : Type w} {t : Impl α (fun _ => β)} + +theorem isEmpty_filterMap_iff [TransOrd α] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f h.balanced).1.isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f (t.getKey k h) (Const.get t k h) = none := by + simp_to_model [filterMap, isEmpty, contains, getKey, Const.get] using List.Const.isEmpty_filterMap_eq_true + +theorem isEmpty_filterMap!_iff [TransOrd α] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap! f).isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f (t.getKey k h) (Const.get t k h) = none := by + simpa only [filterMap_eq_filterMap!] using isEmpty_filterMap_iff h + +theorem isEmpty_filterMap_eq_false_iff [TransOrd α] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f h.balanced).1.isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), (f (t.getKey k h) (Const.get t k h)).isSome := by + simp_to_model [filterMap, isEmpty, contains, getKey, Const.get] using List.Const.isEmpty_filterMap_eq_false + +theorem isEmpty_filterMap!_eq_false_iff [TransOrd α] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap! f).isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), (f (t.getKey k h) (Const.get t k h)).isSome := by + simpa only [filterMap_eq_filterMap!] using isEmpty_filterMap_eq_false_iff h + +theorem contains_filterMap_iff [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.contains k = true ↔ ∃ (h' : t.contains k = true), + (f (t.getKey k h') (Const.get t k h')).isSome := by + simp_to_model [filterMap, contains, getKey, Const.get] using List.Const.containsKey_filterMap_iff + +theorem contains_filterMap!_iff [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap! f).contains k = true ↔ ∃ (h' : t.contains k = true), + (f (t.getKey k h') (Const.get t k h')).isSome := by + simpa only [filterMap_eq_filterMap!] using contains_filterMap_iff h + +theorem size_filterMap_eq_size_iff [TransOrd α] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f h.balanced).1.size = t.size ↔ + ∀ (a : α) (h : t.contains a), (f (t.getKey a h) (Const.get t a h)).isSome := by + simp_to_model [filterMap, size, getKey, contains, Const.get] using List.Const.length_filterMap_eq_length_iff + +theorem size_filterMap!_eq_size_iff [TransOrd α] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap! f).size = t.size ↔ + ∀ (a : α) (h : t.contains a), (f (t.getKey a h) (Const.get t a h)).isSome := by + simpa only [filterMap_eq_filterMap!] using size_filterMap_eq_size_iff h + +theorem get?_filterMap [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get? (t.filterMap f h.balanced).1 k = (Const.get? t k).pbind (fun x h' => + f (t.getKey k ((Const.mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := by + simp_to_model [filterMap, getKey, Const.get?] using List.Const.getValue?_filterMap + +theorem get?_filterMap! [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get? (t.filterMap! f) k = (Const.get? t k).pbind (fun x h' => + f (t.getKey k ((Const.mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := by + simpa only [filterMap_eq_filterMap!] using get?_filterMap h + +theorem get?_filterMap_of_getKey?_eq_some [TransOrd α] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get? (t.filterMap f h.balanced).1 k = + (Const.get? t k).bind fun x => f k' x := by + simp_to_model [filterMap, getKey?, Const.get?] + using List.Const.getValue?_filterMap_of_getKey?_eq_some + +theorem get?_filterMap!_of_getKey?_eq_some [TransOrd α] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get? (t.filterMap! f) k = + (Const.get? t k).bind fun x => f k' x := by + simpa only [filterMap_eq_filterMap!] using get?_filterMap_of_getKey?_eq_some h + +theorem isSome_apply_of_contains_filterMap [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + ∀ (h' : (t.filterMap f h.balanced).1.contains k = true), + (f (t.getKey k (contains_of_contains_filterMap h h')) + (Const.get t k (contains_of_contains_filterMap h h'))).isSome := by + simp_to_model [filterMap, getKey, Const.get, contains] using List.Const.isSome_apply_of_containsKey_filterMap + +theorem isSome_apply_of_contains_filterMap! [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + ∀ (h' : (t.filterMap! f).contains k = true), + (f (t.getKey k (contains_of_contains_filterMap! h h')) + (Const.get t k (contains_of_contains_filterMap! h h'))).isSome := by + simpa only [filterMap_eq_filterMap!] using isSome_apply_of_contains_filterMap h + +theorem get_filterMap [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) {h'} : + Const.get (t.filterMap f h.balanced).1 k h' = + (f (t.getKey k (contains_of_contains_filterMap h h')) + (Const.get t k (contains_of_contains_filterMap h h'))).get + (isSome_apply_of_contains_filterMap h h') := by + simp_to_model [filterMap, getKey, Const.get] using List.getValue_filterMap + +theorem get_filterMap! [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) {h'} : + Const.get (t.filterMap! f) k h' = + (f (t.getKey k (contains_of_contains_filterMap! h h')) + (Const.get t k (contains_of_contains_filterMap! h h'))).get + (isSome_apply_of_contains_filterMap! h h') := by + simpa only [filterMap_eq_filterMap!] using + get_filterMap h (h' := by simpa only [filterMap_eq_filterMap!] using h') + +theorem get!_filterMap [TransOrd α] [Inhabited γ] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get! (t.filterMap f h.balanced).1 k = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := by + simp_to_model [filterMap, Const.get!, getKey, Const.get?] using List.Const.getValue!_filterMap + +theorem get!_filterMap! [TransOrd α] [Inhabited γ] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get! (t.filterMap! f) k = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := by + simpa only [filterMap_eq_filterMap!] using get!_filterMap h + +theorem get!_filterMap_of_getKey?_eq_some [TransOrd α] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get! (t.filterMap f h.balanced).1 k = + ((Const.get? t k).bind fun x => f k' x).get! := by + simp_to_model [filterMap, getKey?, Const.get?, Const.get!] + using List.Const.getValue!_filterMap_of_getKey?_eq_some + +theorem get!_filterMap!_of_getKey?_eq_some [TransOrd α] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get! (t.filterMap! f) k = + ((Const.get? t k).bind fun x => f k' x).get! := by + simpa only [filterMap_eq_filterMap!] using get!_filterMap_of_getKey?_eq_some h + +theorem getD_filterMap [TransOrd α] + {f : α → β → Option γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.filterMap f h.balanced).1 k fallback = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := by + simp_to_model [filterMap, Const.getD, getKey, Const.get?] using List.Const.getValueD_filterMap + +theorem getD_filterMap! [TransOrd α] + {f : α → β → Option γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.filterMap! f) k fallback = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := by + simpa only [filterMap_eq_filterMap!] using getD_filterMap h + +theorem getD_filterMap_of_getKey?_eq_some [TransOrd α] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.WF) : + t.getKey? k = some k' → Const.getD (t.filterMap f h.balanced).1 k fallback = + ((Const.get? t k).bind fun x => f k' x).getD fallback := by + simp_to_model [filterMap, getKey?, Const.get?, Const.getD] + using List.Const.getValueD_filterMap_of_getKey?_eq_some + +theorem getD_filterMap!_of_getKey?_eq_some [TransOrd α] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.WF) : + t.getKey? k = some k' → Const.getD (t.filterMap! f) k fallback = + ((Const.get? t k).bind fun x => f k' x).getD fallback := by + simpa only [filterMap_eq_filterMap!] using getD_filterMap_of_getKey?_eq_some h + +theorem toList_filterMap {f : α → β → Option γ} (h : t.WF) : + Const.toList (t.filterMap f h.balanced).1 = + (Const.toList t).filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := by + simp_to_model [Const.toList, filterMap] + simp only [List.map_filterMap, List.filterMap_map, Function.comp_def, Option.map_map] + +theorem toList_filterMap! {f : α → β → Option γ} (h : t.WF) : + Const.toList (t.filterMap! f) = + (Const.toList t).filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := by + simpa only [filterMap_eq_filterMap!] using toList_filterMap h + +theorem getKey?_filterMap [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome) := by + simp_to_model [filterMap, Const.get, getKey?] using List.Const.getKey?_filterMap + +theorem getKey?_filterMap! [TransOrd α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap! f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome) := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using getKey?_filterMap h + +theorem getKey!_filterMap [TransOrd α] [Inhabited α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f h.balanced).1.getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome)).get! := by + simp_to_model [filterMap, Const.get, getKey?, getKey!] using List.Const.getKey!_filterMap + +theorem getKey!_filterMap! [TransOrd α] [Inhabited α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap! f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome)).get! := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using getKey!_filterMap h + +theorem getKeyD_filterMap [TransOrd α] + {f : α → β → Option γ} {k fallback : α} (h : t.WF) : + (t.filterMap f h.balanced).1.getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := by + simp_to_model [filterMap, Const.get, getKey?, getKeyD] using List.Const.getKeyD_filterMap + +theorem getKeyD_filterMap! [TransOrd α] + {f : α → β → Option γ} {k fallback : α} (h : t.WF) : + (t.filterMap! f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using getKeyD_filterMap h + +end Const + +end filterMap + +section filter + +theorem filterMap_equiv_filter {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filterMap (fun k => Option.guard (fun v => f k v)) h.balanced).1 ~m + (t.filter f h.balanced).1 := by + simp_to_model [filter, filterMap, Equiv] + simp only [Option.guard_def, ← List.filterMap_eq_filter, Option.map_if, List.Perm.rfl] + +theorem filterMap!_equiv_filter! {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filterMap! (fun k => Option.guard (fun v => f k v))) ~m + (t.filter! f) := by + simpa only [filter_eq_filter!, filterMap_eq_filterMap!] using filterMap_equiv_filter h + +theorem toList_filter {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.toList = t.toList.filter (fun p => f p.1 p.2) := by + simp_to_model [filter, toList, Equiv] + +theorem toList_filter! {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).toList = t.toList.filter (fun p => f p.1 p.2) := by + simpa only [filter_eq_filter!] using toList_filter h + +theorem keys_filter_key {f : α → Bool} (h : t.WF) : + (t.filter (fun k _ => f k) h.balanced).1.keys = t.keys.filter f := by + simp_to_model [keys, filter] + simp only [List.keys_eq_map, List.filter_map, Function.comp_def] + +theorem keys_filter!_key {f : α → Bool} (h : t.WF) : + (t.filter! (fun k _ => f k)).keys = t.keys.filter f := by + simpa only [filter_eq_filter!] using keys_filter_key h + +theorem isEmpty_filter_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f k (t.get k h) = false := by + simp_to_model [filter, contains, get, isEmpty] using List.isEmpty_filter_eq_true + +theorem isEmpty_filter!_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f k (t.get k h) = false := by + simpa only [filter_eq_filter!] using isEmpty_filter_iff h + +theorem isEmpty_filter_eq_false_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), f k (t.get k h) = true := by + simp_to_model [filter, contains, get, isEmpty] using List.isEmpty_filter_eq_false + +theorem isEmpty_filter!_eq_false_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), f k (t.get k h) = true := by + simpa only [filter_eq_filter!] using isEmpty_filter_eq_false_iff h + +theorem isEmpty_filter_key_iff [TransOrd α] + {f : α → Bool} (h : t.WF) : + (t.filter (fun a _ => f a) h.balanced).1.isEmpty ↔ + ∀ (k : α) (h : t.contains k), f (t.getKey k h) = false := by + simp_to_model [filter, contains, getKey, isEmpty] using List.isEmpty_filter_key_iff + +theorem isEmpty_filter!_key_iff [TransOrd α] + {f : α → Bool} (h : t.WF) : + (t.filter! (fun a _ => f a)).isEmpty ↔ + ∀ (k : α) (h : t.contains k), f (t.getKey k h) = false := by + simpa only [filter_eq_filter!] using isEmpty_filter_key_iff h + +theorem isEmpty_filter_key_eq_false_iff [TransOrd α] + {f : α → Bool} (h : t.WF) : + (t.filter (fun a _ => f a) h.balanced).1.isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), f (t.getKey k h) := by + rw [← Bool.not_eq_true, isEmpty_filter_key_iff h] + simp only [Classical.not_forall, Bool.not_eq_false] + +theorem isEmpty_filter!_key_eq_false_iff [TransOrd α] + {f : α → Bool} (h : t.WF) : + (t.filter! (fun a _ => f a)).isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), f (t.getKey k h) := by + simpa only [filter_eq_filter!] using isEmpty_filter_key_eq_false_iff h + +theorem contains_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.contains k = (t.get? k).any (f k) := by + simp_to_model [filter, contains, get?] using List.containsKey_filter + +theorem contains_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter! f).contains k = (t.get? k).any (f k) := by + simpa only [filter_eq_filter!] using contains_filter h + +theorem contains_filter_key_iff [TransOrd α] {f : α → Bool} {k : α} (h : t.WF) : + (t.filter (fun a _ => f a) h.balanced).1.contains k ↔ + ∃ h : t.contains k, f (t.getKey k h) := by + simp_to_model [filter, contains, getKey] using List.containsKey_filter_key + +theorem contains_filter!_key_iff [TransOrd α] {f : α → Bool} {k : α} (h : t.WF) : + (t.filter! (fun a _ => f a)).contains k ↔ + ∃ h : t.contains k, f (t.getKey k h) := by + simpa only [filter_eq_filter!] using contains_filter_key_iff h + +theorem contains_of_contains_filter [TransOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.contains k = true → t.contains k = true := by + simp_to_model [filter, contains] using containsKey_of_containsKey_filter + +theorem contains_of_contains_filter! [TransOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter! f).contains k = true → t.contains k = true := by + simpa only [filter_eq_filter!] using contains_of_contains_filter h + +theorem size_filter_le_size [TransOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.size ≤ t.size := by + simp_to_model [filter, size] using List.length_filter_le + +theorem size_filter!_le_size [TransOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).size ≤ t.size := by + simpa only [filter_eq_filter!] using size_filter_le_size h + +theorem size_filter_eq_size_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.size = t.size ↔ ∀ (a : α) (h : t.contains a), (f a (t.get a h)) = true := by + simp_to_model [filter, size, contains, get] using Internal.List.length_filter_eq_length_iff + +theorem size_filter!_eq_size_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).size = t.size ↔ ∀ (a : α) (h : t.contains a), (f a (t.get a h)) = true := by + simpa only [filter_eq_filter!] using size_filter_eq_size_iff h + +theorem filter_equiv_self_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.Equiv t ↔ ∀ (a : α) (h : t.contains a), (f a (t.get a h)) = true := by + simp_to_model [filter, Equiv, contains, get] using List.perm_filter_self_iff_forall_containsKey + +theorem filter!_equiv_self_iff [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).Equiv t ↔ ∀ (a : α) (h : t.contains a), (f a (t.get a h)) = true := by + simpa only [filter_eq_filter!] using filter_equiv_self_iff h + +theorem filter_key_equiv_self_iff [TransOrd α] + {f : (a : α) → Bool} (h : t.WF) : + (t.filter (fun k _ => f k) h.balanced).1.Equiv t ↔ ∀ (a : α) (h : t.contains a), f (t.getKey a h) = true := by + simp_to_model [filter, Equiv, contains, getKey] using List.perm_filter_key_self_iff_forall_containsKey + +theorem filter!_key_equiv_self_iff [TransOrd α] + {f : (a : α) → Bool} (h : t.WF) : + (t.filter! (fun k _ => f k)).Equiv t ↔ ∀ (a : α) (h : t.contains a), f (t.getKey a h) = true := by + simpa only [filter_eq_filter!] using filter_key_equiv_self_iff h + +theorem size_filter_key_eq_size_iff [TransOrd α] + {f : α → Bool} (h : t.WF) : + (t.filter (fun k _ => f k) h.balanced).1.size = t.size ↔ ∀ (k : α) (h : t.contains k), f (t.getKey k h) := by + simp_to_model [filter, size, contains, getKey] using List.length_filter_key_eq_length_iff + +theorem size_filter!_key_eq_size_iff [TransOrd α] + {f : α → Bool} (h : t.WF) : + (t.filter! (fun k _ => f k)).size = t.size ↔ ∀ (k : α) (h : t.contains k), f (t.getKey k h) := by + simpa only [filter_eq_filter!] using size_filter_key_eq_size_iff h + +theorem get?_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.get? k = (t.get? k).filter (f k) := by + simp_to_model [filter, get?] using List.getValueCast?_filter + +theorem get?_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter! f).get? k = (t.get? k).filter (f k) := by + simpa only [filter_eq_filter!] using get?_filter h + +theorem get_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) {h'} : + (t.filter f h.balanced).1.get k h' = + t.get k (contains_of_contains_filter h h') := by + simp_to_model [filter, get] using List.getValueCast_filter + +theorem get_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) {h'} : + (t.filter! f).get k h' = + t.get k (contains_of_contains_filter! h h') := by + simpa only [filter_eq_filter!] using + get_filter h (h' := by simpa only [filter_eq_filter!] using h') + +theorem get!_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} [Inhabited (β k)] (h : t.WF) : + (t.filter f h.balanced).1.get! k = ((t.get? k).filter (f k)).get! := by + simp_to_model [filter, get!, get?] using List.getValueCast!_filter + +theorem get!_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} [Inhabited (β k)] (h : t.WF) : + (t.filter! f).get! k = ((t.get? k).filter (f k)).get! := by + simpa only [filter_eq_filter!] using get!_filter h + +theorem getD_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} {fallback : β k} (h : t.WF) : + (t.filter f h.balanced).1.getD k fallback = ((t.get? k).filter (f k)).getD fallback := by + simp_to_model [filter, getD, get?] using List.getValueCastD_filter + +theorem getD_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} {fallback : β k} (h : t.WF) : + (t.filter! f).getD k fallback = ((t.get? k).filter (f k)).getD fallback := by + simpa only [filter_eq_filter!] using getD_filter h + +theorem keys_filter [TransOrd α] [LawfulEqOrd α] {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f h.balanced).1.keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (t.get x (mem_of_mem_keys h h')))).unattach := by + simp_to_model [keys, filter, Equiv, get] + rw [List.attach_congr Impl.keys_eq_keys] + rw [List.keys_filter h.ordered.distinctKeys] + simp only [List.filter_map, Function.comp_def, List.unattach, List.map_map] + +theorem keys_filter! [TransOrd α] [LawfulEqOrd α] {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter! f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (t.get x (mem_of_mem_keys h h')))).unattach := by + simpa only [filter_eq_filter!] using keys_filter h + +theorem getKey?_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.getKey? k = + (t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h'))) := by + simp_to_model [filter, getKey?, get] using List.getKey?_filter + +theorem getKey?_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter! f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h'))) := by + simpa only [filter_eq_filter!] using getKey?_filter h + +theorem getKey?_filter_key [TransOrd α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter (fun k _ => f k) h.balanced).1.getKey? k = (t.getKey? k).filter f := by + simp_to_model [filter, getKey?, get] using List.getKey?_filter_key + +theorem getKey?_filter!_key [TransOrd α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter! (fun k _ => f k)).getKey? k = (t.getKey? k).filter f := by + simpa only [filter_eq_filter!] using getKey?_filter_key h + +theorem getKey_filter [TransOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) {h'}: + (t.filter f h.balanced).1.getKey k h' = t.getKey k (contains_of_contains_filter h h') := by + simp_to_model [filter, getKey] using List.getKey_filter + +theorem getKey_filter! [TransOrd α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) {h'}: + (t.filter! f).getKey k h' = t.getKey k (contains_of_contains_filter! h h') := by + simpa only [filter_eq_filter!] using + getKey_filter h (h' := by simpa only [filter_eq_filter!] using h') + +theorem getKey!_filter [TransOrd α] [LawfulEqOrd α] [Inhabited α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.getKey! k = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h')))).get! := by + simp_to_model [filter, getKey?, get, getKey!] using List.getKey!_filter + +theorem getKey!_filter! [TransOrd α] [LawfulEqOrd α] [Inhabited α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter! f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h')))).get! := by + simpa only [filter_eq_filter!] using getKey!_filter h + +theorem getKey!_filter_key [TransOrd α] [Inhabited α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter (fun k _ => f k) h.balanced).1.getKey! k = ((t.getKey? k).filter f).get! := by + simp_to_model [filter, getKey?, get, getKey!] using List.getKey!_filter_key + +theorem getKey!_filter!_key [TransOrd α] [Inhabited α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter! (fun k _ => f k)).getKey! k = ((t.getKey? k).filter f).get! := by + simpa only [filter_eq_filter!] using getKey!_filter_key h + +theorem getKeyD_filter [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k fallback : α} (h : t.WF) : + (t.filter f h.balanced).1.getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h')))).getD fallback := by + simp_to_model [filter, getKey?, get, getKeyD] using List.getKeyD_filter + +theorem getKeyD_filter! [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → Bool} {k fallback : α} (h : t.WF) : + (t.filter! f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h')))).getD fallback := by + simpa only [filter_eq_filter!] using getKeyD_filter h + +theorem getKeyD_filter_key [TransOrd α] + {f : α → Bool} {k fallback : α} (h : t.WF) : + (t.filter (fun k _ => f k) h.balanced).1.getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := by + simp_to_model [filter, getKey?, get, getKeyD] using List.getKeyD_filter_key + +theorem getKeyD_filter!_key [TransOrd α] + {f : α → Bool} {k fallback : α} (h : t.WF) : + (t.filter! (fun k _ => f k)).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := by + simpa only [filter_eq_filter!] using getKeyD_filter_key h + +namespace Const + +variable {β : Type v} {γ : Type w} {t : Impl α (fun _ => β)} + +theorem isEmpty_filter_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter f h.balanced).1.isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f (t.getKey k h) (Const.get t k h) = false := by + simp_to_model [filter, isEmpty, contains, getKey, Const.get] using List.Const.isEmpty_filter_eq_true + +theorem isEmpty_filter!_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter! f).isEmpty = true ↔ + ∀ (k : α) (h : t.contains k = true), f (t.getKey k h) (Const.get t k h) = false := by + simpa only [filter_eq_filter!] using isEmpty_filter_iff h + +theorem isEmpty_filter_eq_false_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter f h.balanced).1.isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), (f (t.getKey k h) (Const.get t k h)) = true := by + simp_to_model [filter, isEmpty, contains, getKey, Const.get] using List.Const.isEmpty_filter_eq_false + +theorem isEmpty_filter!_eq_false_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter! f).isEmpty = false ↔ + ∃ (k : α) (h : t.contains k = true), (f (t.getKey k h) (Const.get t k h)) = true := by + simpa only [filter_eq_filter!] using isEmpty_filter_eq_false_iff h + +theorem contains_filter_iff [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.contains k = true ↔ ∃ (h' : t.contains k = true), + f (t.getKey k h') (Const.get t k h') := by + simp_to_model [filter, contains, getKey, Const.get] using List.Const.containsKey_filter_iff + +theorem contains_filter!_iff [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter! f).contains k = true ↔ ∃ (h' : t.contains k = true), + f (t.getKey k h') (Const.get t k h') := by + simpa only [filter_eq_filter!] using contains_filter_iff h + +theorem size_filter_le_size [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter f h.balanced).1.size ≤ t.size := by + simp_to_model [filter, size] using List.length_filter_le + +theorem size_filter!_le_size [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter! f).size ≤ t.size := by + simpa only [filter_eq_filter!] using size_filter_le_size h + +theorem size_filter_eq_size_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter f h.balanced).1.size = t.size ↔ ∀ (a : α) (h : t.contains a), + f (t.getKey a h) (Const.get t a h) := by + simp_to_model [filter, size, contains, getKey, Const.get] using List.Const.length_filter_eq_length_iff + +theorem size_filter!_eq_size_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter! f).size = t.size ↔ ∀ (a : α) (h : t.contains a), + f (t.getKey a h) (Const.get t a h) := by + simpa only [filter_eq_filter!] using size_filter_eq_size_iff h + +theorem filter_equiv_self_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter f h.balanced).1.Equiv t ↔ ∀ (a : α) (h : t.contains a), + f (t.getKey a h) (Const.get t a h) := by + simp_to_model [filter, Equiv, contains, getKey, Const.get] using + List.Const.perm_filter_self_iff_forall_containsKey + +theorem filter!_equiv_self_iff [TransOrd α] + {f : α → β → Bool} (h : t.WF) : + (t.filter! f).Equiv t ↔ ∀ (a : α) (h : t.contains a), + f (t.getKey a h) (Const.get t a h) := by + simpa only [filter_eq_filter!] using filter_equiv_self_iff h + +theorem get?_filter [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get? (t.filter f h.balanced).1 k = (Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := by + simp_to_model [filter, Const.get?, getKey] using List.Const.getValue?_filter + +theorem get?_filter! [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get? (t.filter! f) k = (Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := by + simpa only [filter_eq_filter!] using get?_filter h + +theorem get?_filter_of_getKey?_eq_some [TransOrd α] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + Const.get? (t.filter f h.balanced).1 k = (Const.get? t k).filter (fun x => f k' x) := by + simp_to_model [filter, Const.get?, getKey?] using List.Const.getValue?_filter_of_getKey?_eq_some + +theorem get?_filter!_of_getKey?_eq_some [TransOrd α] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + Const.get? (t.filter! f) k = (Const.get? t k).filter (fun x => f k' x) := by + simpa only [filter_eq_filter!] using get?_filter_of_getKey?_eq_some h + +theorem get_filter [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) {h'} : + Const.get (t.filter f h.balanced).1 k h' = Const.get t k (contains_of_contains_filter h h') := by + simp_to_model [filter, Const.get] using List.getValue_filter + +theorem get_filter! [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) {h'} : + Const.get (t.filter! f) k h' = Const.get t k (contains_of_contains_filter! h h') := by + simpa only [filter_eq_filter!] using + get_filter h (h' := by simpa only [filter_eq_filter!] using h') + +theorem get!_filter [TransOrd α] [Inhabited β] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get! (t.filter f h.balanced).1 k = + ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := by + simp_to_model [filter, Const.get!, getKey, Const.get?] using List.Const.getValue!_filter + +theorem get!_filter! [TransOrd α] [Inhabited β] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get! (t.filter! f) k = + ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := by + simpa only [filter_eq_filter!] using get!_filter h + +theorem get!_filter_of_getKey?_eq_some [TransOrd α] [Inhabited β] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + Const.get! (t.filter f h.balanced).1 k = ((Const.get? t k).filter (fun x => f k' x)).get! := by + simp_to_model [filter, Const.get?, getKey?, Const.get!] + using List.Const.getValue!_filter_of_getKey?_eq_some + +theorem get!_filter!_of_getKey?_eq_some [TransOrd α] [Inhabited β] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + Const.get! (t.filter! f) k = ((Const.get? t k).filter (fun x => f k' x)).get! := by + simpa only [filter_eq_filter!] using get!_filter_of_getKey?_eq_some h + +theorem getD_filter [TransOrd α] + {f : α → β → Bool} {k : α} {fallback : β} (h : t.WF) : + Const.getD (t.filter f h.balanced).1 k fallback = ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := by + simp_to_model [filter, Const.getD, getKey, Const.get?] using List.Const.getValueD_filter + +theorem getD_filter! [TransOrd α] + {f : α → β → Bool} {k : α} {fallback : β} (h : t.WF) : + Const.getD (t.filter! f) k fallback = ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := by + simpa only [filter_eq_filter!] using getD_filter h + +theorem getD_filter_of_getKey?_eq_some [TransOrd α] + {f : α → β → Bool} {k k' : α} {fallback : β} (h : t.WF) : + t.getKey? k = some k' → + Const.getD (t.filter f h.balanced).1 k fallback = + ((Const.get? t k).filter (fun x => f k' x)).getD fallback := by + simp_to_model [filter, Const.get?, getKey?, Const.getD] + using List.Const.getValueD_filter_of_getKey?_eq_some + +theorem getD_filter!_of_getKey?_eq_some [TransOrd α] + {f : α → β → Bool} {k k' : α} {fallback : β} (h : t.WF) : + t.getKey? k = some k' → + Const.getD (t.filter! f) k fallback = + ((Const.get? t k).filter (fun x => f k' x)).getD fallback := by + simpa only [filter_eq_filter!] using getD_filter_of_getKey?_eq_some h + +theorem toList_filter {f : α → β → Bool} (h : t.WF) : + Const.toList (t.filter f h.balanced).1 = + (Const.toList t).filter (fun p => f p.1 p.2) := by + simp_to_model [filter, Const.toList] + simp only [List.filter_map, Function.comp_def] + +theorem toList_filter! {f : α → β → Bool} (h : t.WF) : + Const.toList (t.filter! f) = + (Const.toList t).filter (fun p => f p.1 p.2) := by + simpa only [filter_eq_filter!] using toList_filter h + +theorem keys_filter [TransOrd α] {f : α → β → Bool} (h : t.WF): + (t.filter f h.balanced).1.keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h h')))).unattach := by + simp_to_model [keys, filter, Equiv, Const.get] + rw [List.attach_congr Impl.keys_eq_keys] + rw [List.Const.keys_filter h.ordered.distinctKeys] + simp only [List.filter_map, Function.comp_def, List.unattach, List.map_map] + +theorem keys_filter! [TransOrd α] {f : α → β → Bool} (h : t.WF): + (t.filter! f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h h')))).unattach := by + simpa only [filter_eq_filter!] using keys_filter h + +theorem getKey?_filter [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h')))) := by + simp_to_model [filter, getKey?, Const.get] using List.Const.getKey?_filter + +theorem getKey?_filter! [TransOrd α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter! f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h')))) := by + simpa only [filter_eq_filter!] using getKey?_filter h + +theorem getKey!_filter [TransOrd α] [Inhabited α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f h.balanced).1.getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))))).get! := by + simp_to_model [filter, getKey!, getKey?, Const.get] using List.Const.getKey!_filter + +theorem getKey!_filter! [TransOrd α] [Inhabited α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter! f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))))).get! := by + simpa only [filter_eq_filter!] using getKey!_filter h + +theorem getKeyD_filter [TransOrd α] + {f : α → β → Bool} {k fallback : α} (h : t.WF) : + (t.filter f h.balanced).1.getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))))).getD fallback := by + simp_to_model [filter, getKeyD, getKey?, Const.get] using List.Const.getKeyD_filter + +theorem getKeyD_filter! [TransOrd α] + {f : α → β → Bool} {k fallback : α} (h : t.WF) : + (t.filter! f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))))).getD fallback := by + simpa only [filter_eq_filter!] using getKeyD_filter h + +end Const + +end filter + +section map + +variable {γ : α → Type w} {δ : α → Type w'} + +theorem map_id_equiv : (t.map (fun _ v => v)).Equiv t := by + simp_to_model [map, Equiv] using List.Perm.of_eq (List.map_id _) + +theorem map_map_equiv {f : (a : α) → β a → γ a} {g : (a : α) → γ a → δ a} : + ((t.map f).map g).Equiv (t.map fun k v => g k (f k v)) := by + simp_to_model [map, Equiv, Const.toList] using List.Perm.of_eq (List.map_map) + +theorem toList_map {f : (a : α) → β a → γ a} : + (t.map f).toList = t.toList.map (fun p => ⟨p.1, f p.1 p.2⟩) := by + simp_to_model [map, toList, Equiv] + +theorem keys_map {f : (a : α) → β a → γ a} : (t.map f).keys = t.keys := by + simp_to_model [keys, map, Equiv] + rw [List.keys_map] + +theorem filterMap_equiv_map + {f : (a : α) → β a → γ a} (h : t.WF) : + (t.filterMap (fun k v => some (f k v)) h.balanced).1.Equiv (t.map f) := by + simp_to_model [map, filterMap, Equiv] + simp + +theorem filterMap!_equiv_map + {f : (a : α) → β a → γ a} (h : t.WF) : + (t.filterMap! (fun k v => some (f k v))).Equiv (t.map f) := by + simpa only [filterMap_eq_filterMap!] using filterMap_equiv_map h + +theorem isEmpty_map {f : (a : α) → β a → γ a} : + (t.map f).isEmpty = t.isEmpty := by + simp_to_model [map, isEmpty] using List.isEmpty_map + +theorem contains_map [TransOrd α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).contains k = t.contains k := by + simp_to_model [map, contains] using List.containsKey_map + +theorem contains_of_contains_map [TransOrd α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).contains k = true → t.contains k = true := by + simp [contains_map h] + +theorem get?_map [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).get? k = (t.get? k).map (f k) := by + simp_to_model [map, get?] using List.getValueCast?_map + +theorem get_map [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) {h'} : + (t.map f).get k h' = + f k (t.get k (contains_of_contains_map h h')) := by + simp_to_model [map, get] using List.getValueCast_map + +theorem get!_map [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → γ a} {k : α} [Inhabited (γ k)] (h : t.WF) : + (t.map f).get! k = ((t.get? k).map (f k)).get! := by + simp_to_model [map, get?, get!] using List.getValueCast!_map + +theorem getD_map [TransOrd α] [LawfulEqOrd α] + {f : (a : α) → β a → γ a} {k : α} {fallback : γ k} (h : t.WF) : + (t.map f).getD k fallback = ((t.get? k).map (f k)).getD fallback := by + simp_to_model [map, getD, get?] using List.getValueCastD_map + +theorem getKey?_map [TransOrd α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).getKey? k = t.getKey? k := by + simp_to_model [map, getKey?] using List.getKey?_map + +theorem getKey_map [TransOrd α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) {h'}: + (t.map f).getKey k h' = t.getKey k (contains_of_contains_map h h') := by + simp_to_model [map, getKey] using List.getKey_map + +theorem getKey!_map [TransOrd α] [Inhabited α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).getKey! k = t.getKey! k := by + simp_to_model [map, getKey!] using List.getKey!_map + +theorem getKeyD_map [TransOrd α] + {f : (a : α) → β a → γ a} {k fallback : α} (h : t.WF) : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := by + simp_to_model [map, getKeyD] using List.getKeyD_map + +namespace Const + +variable {β : Type v} {γ : Type w} {t : Impl α (fun _ => β)} + +/-- Variant of `get?_map` that holds without `LawfulEqOrd`. -/ +theorem get?_map' [TransOrd α] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get? (t.map f) k = (Const.get? t k).pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => (mem_iff_isSome_get? h).mpr (Option.isSome_of_mem h')) := by + simp_to_model [map, Const.get?, contains, getKey] using Const.getValue?_map + +theorem get?_map [TransOrd α] [LawfulEqOrd α] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get? (t.map f) k = (Const.get? t k).map (f k) := by + simp [get?_map' h, getKey_eq h] + +theorem get?_map_of_getKey?_eq_some [TransOrd α] + {f : α → β → γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get? (t.map f) k = (Const.get? t k).map (f k') := by + simp_to_model [map, Const.get?, getKey?] using Const.getValue?_map_of_getKey?_eq_some + +/-- Variant of `get_map` that holds without `LawfulEqOrd`. -/ +theorem get_map' [TransOrd α] + {f : α → β → γ} {k : α} (h : t.WF) {h'} : + Const.get (t.map f) k h' = + (f (t.getKey k (contains_of_contains_map h h')) + (Const.get t k (contains_of_contains_map h h'))) := by + simp_to_model [map, getKey, Const.get, contains] using List.getValue_map + +theorem get_map [TransOrd α] [LawfulEqOrd α] + {f : α → β → γ} {k : α} (h : t.WF) {h'} : + Const.get (t.map f) k h' = f k (Const.get t k (contains_of_contains_map h h')) := by + simp [get_map' h, getKey_eq h] + +/-- Variant of `get!_map` that holds without `LawfulEqOrd`. -/ +theorem get!_map' [TransOrd α] [Inhabited γ] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get! (t.map f) k = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => (mem_iff_isSome_get? h).mpr (Option.isSome_of_mem h'))).get! := by + simp_to_model [map, getKey, Const.get!, Const.get?, contains] using List.Const.getValue!_map + +theorem get!_map [TransOrd α] [LawfulEqOrd α] [Inhabited γ] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get! (t.map f) k = ((Const.get? t k).map (f k)).get! := by + simp [get!_map' h, getKey_eq h] + +theorem get!_map_of_getKey?_eq_some [TransOrd α] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get! (t.map f) k = ((Const.get? t k).map (f k')).get! := by + simp_to_model [map, Const.get!, Const.get?, getKey?] using Const.getValue!_map_of_getKey?_eq_some + +/-- Variant of `getD_map` that holds without `LawfulEqOrd`. -/ +theorem getD_map' [TransOrd α] + {f : α → β → γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.map f) k fallback = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => (mem_iff_isSome_get? h).mpr (Option.isSome_of_mem h'))).getD fallback := by + simp_to_model [map, getKey, Const.getD, Const.get?, contains] using List.Const.getValueD_map + +theorem getD_map [TransOrd α] [LawfulEqOrd α] + {f : α → β → γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k)).getD fallback := by + simp [getD_map' h, getKey_eq h] + +theorem getD_map_of_getKey?_eq_some [TransOrd α] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.WF) : + t.getKey? k = some k' → Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k')).getD fallback := by + simp_to_model [map, Const.getD, Const.get?, getKey?] using Const.getValueD_map_of_getKey?_eq_some + +theorem toList_map {f : α → β → γ} : + Const.toList (t.map f) = (Const.toList t).map (fun p => (p.1, f p.1 p.2)) := by + simp_to_model [map, Const.toList] + simp only [List.map_map, Function.comp_def] + +end Const + +end map + end Std.DTreeMap.Internal.Impl diff --git a/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean b/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean index 6e93b80362..9d57037139 100644 --- a/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Internal/WF/Lemmas.lean @@ -1820,7 +1820,7 @@ theorem sameKeys_map [Ord α] {t : Impl α β} {f : (a : α) → β a → γ a} | inner => apply SameKeys.inner <;> assumption @[simp] -theorem size_map [Ord α] {t : Impl α β} {f : (a : α) → β a → γ a} : (t.map f).size = t.size := +theorem size_map {instOrd : Ord α} {t : Impl α β} {f : (a : α) → β a → γ a} : (t.map f).size = t.size := sameKeys_map.size_eq theorem WF.map [Ord α] {t : Impl α β} {f : (a : α) → β a → γ a} (h : t.WF) : (t.map f).WF := diff --git a/src/Std/Data/DTreeMap/Lemmas.lean b/src/Std/Data/DTreeMap/Lemmas.lean index fae78bc714..f48b5e80c3 100644 --- a/src/Std/Data/DTreeMap/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Lemmas.lean @@ -356,10 +356,18 @@ theorem get_erase [TransCmp cmp] [LawfulEqCmp cmp] {k a : α} {h'} : (t.erase k).get a h' = t.get a (mem_of_mem_erase h') := Impl.get_erase t.wf -theorem get?_eq_some_get [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h'} : +theorem get?_eq_some_get [TransCmp cmp] [LawfulEqCmp cmp] {a : α} (h') : t.get? a = some (t.get a h') := Impl.get?_eq_some_get t.wf +theorem get_eq_get_get? [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h} : + t.get a h = (t.get? a).get (mem_iff_isSome_get?.mp h) := by + simp only [get?_eq_some_get h, Option.get_some] + +@[grind =] theorem get_get? [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h} : + (t.get? a).get h = t.get a (mem_iff_isSome_get?.mpr h) := + get_eq_get_get?.symm + namespace Const variable {β : Type v} {t : DTreeMap α β cmp} @@ -380,10 +388,18 @@ theorem get_erase [TransCmp cmp] {k a : α} {h'} : get (t.erase k) a h' = get t a (mem_of_mem_erase h') := Impl.Const.get_erase t.wf -theorem get?_eq_some_get [TransCmp cmp] {a : α} {h} : +theorem get?_eq_some_get [TransCmp cmp] {a : α} (h) : get? t a = some (get t a h) := Impl.Const.get?_eq_some_get t.wf +theorem get_eq_get_get? [TransCmp cmp] {a : α} {h} : + get t a h = (get? t a).get (mem_iff_isSome_get?.mp h) := by + simp only [get?_eq_some_get h, Option.get_some] + +@[grind =] theorem get_get? [TransCmp cmp] {a : α} {h} : + (get? t a).get h = get t a (mem_iff_isSome_get?.mpr h) := + get_eq_get_get?.symm + theorem get_eq_get [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h} : get t a h = t.get a h := Impl.Const.get_eq_get t.wf @@ -674,6 +690,10 @@ theorem isSome_getKey?_iff_mem [TransCmp cmp] {a : α} : (t.getKey? a).isSome ↔ a ∈ t := mem_iff_isSome_getKey?.symm +theorem mem_of_getKey?_eq_some [TransCmp cmp] {k k' : α} : + t.getKey? k = some k' → k' ∈ t := + Impl.mem_of_getKey?_eq_some t.wf + theorem getKey?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} : t.contains a = false → t.getKey? a = none := Impl.getKey?_eq_none_of_contains_eq_false t.wf @@ -725,10 +745,19 @@ theorem getKey_erase [TransCmp cmp] {k a : α} {h'} : (t.erase k).getKey a h' = t.getKey a (mem_of_mem_erase h') := Impl.getKey_erase t.wf -theorem getKey?_eq_some_getKey [TransCmp cmp] {a : α} {h'} : +theorem getKey?_eq_some_getKey [TransCmp cmp] {a : α} (h') : t.getKey? a = some (t.getKey a h') := Impl.getKey?_eq_some_getKey t.wf +theorem getKey_eq_get_getKey? [TransCmp cmp] {a : α} {h} : + t.getKey a h = (t.getKey? a).get (mem_iff_isSome_getKey?.mp h) := by + simp only [getKey?_eq_some_getKey h, Option.get_some] + +@[simp, grind =] +theorem get_getKey? [TransCmp cmp] {a : α} {h} : + (t.getKey? a).get h = t.getKey a (mem_iff_isSome_getKey?.mpr h) := + getKey_eq_get_getKey?.symm + theorem compare_getKey_self [TransCmp cmp] {k : α} (h' : k ∈ t) : cmp (t.getKey k h') k = .eq := Impl.compare_getKey_self t.wf h' @@ -1050,6 +1079,9 @@ theorem mem_keys [LawfulEqCmp cmp] [TransCmp cmp] {k : α} : k ∈ t.keys ↔ k ∈ t := Impl.mem_keys t.wf +theorem mem_of_mem_keys [TransCmp cmp] {k : α} (h : k ∈ t.keys) : k ∈ t := + Impl.mem_of_mem_keys t.wf h + theorem distinct_keys [TransCmp cmp] : t.keys.Pairwise (fun a b => ¬ cmp a b = .eq) := Impl.distinct_keys t.wf @@ -4821,4 +4853,781 @@ end Const end Equiv +section filterMap + +variable {γ : α → Type w} + +@[simp, grind =] +theorem toList_filterMap {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := + Impl.toList_filterMap t.wf + +@[grind =] +theorem isEmpty_filterMap_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f k (t.get k h) = none := + Impl.isEmpty_filterMap_iff t.wf + +theorem isEmpty_filterMap_eq_false_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), (f k (t.get k h)).isSome := + Impl.isEmpty_filterMap_eq_false_iff t.wf + +@[grind =] +theorem contains_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).contains k = (t.get? k).any (f k · |>.isSome) := + Impl.contains_filterMap t.wf + +@[grind =] +theorem mem_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + k ∈ t.filterMap f ↔ ∃ h, (f k (t.get k h)).isSome := by + simp only [mem_iff_contains, contains_filterMap, Option.any_eq_true_iff_get, + ← contains_eq_isSome_get?, get_get?] + +theorem contains_of_contains_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).contains k = true → t.contains k = true := + Impl.contains_of_contains_filterMap t.wf + +theorem mem_of_mem_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + k ∈ t.filterMap f → k ∈ t := + Impl.contains_of_contains_filterMap t.wf + +theorem size_filterMap_le_size [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).size ≤ t.size := + Impl.size_filterMap_le_size t.wf + +grind_pattern size_filterMap_le_size => (t.filterMap f).size + +theorem size_filterMap_eq_size_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), (f a (t.get a h)).isSome := + Impl.size_filterMap_eq_size_iff t.wf + +@[simp, grind =] +theorem get?_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).get? k = (t.get? k).bind (f k) := + Impl.get?_filterMap t.wf + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + ∀ (h' : k ∈ t.filterMap f), + (f k (t.get k (mem_of_mem_filterMap h'))).isSome := + Impl.isSome_apply_of_contains_filterMap t.wf + +@[simp, grind =] +theorem get_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {h'} : + (t.filterMap f).get k h' = + (f k (t.get k (mem_of_mem_filterMap h'))).get + (isSome_apply_of_mem_filterMap h') := + Impl.get_filterMap t.wf + +@[simp, grind =] +theorem get!_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} [Inhabited (γ k)] : + (t.filterMap f).get! k = ((t.get? k).bind (f k)).get! := + Impl.get!_filterMap t.wf + +@[simp, grind =] +theorem getD_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {fallback : γ k} : + (t.filterMap f).getD k fallback = ((t.get? k).bind (f k)).getD fallback := + Impl.getD_filterMap t.wf + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h'))).isSome) := + Impl.getKey?_filterMap t.wf + +@[simp, grind =] +theorem getKey_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {h'} : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h') := + Impl.getKey_filterMap t.wf + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h'))).isSome)).get! := + Impl.getKey!_filterMap t.wf + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k fallback : α} : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h'))).isSome)).getD fallback := + Impl.getKeyD_filterMap t.wf + +namespace Const + +variable {β : Type v} {γ : Type w} {t : DTreeMap α (fun _ => β) cmp} + +@[grind =] +theorem isEmpty_filterMap_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).isEmpty ↔ ∀ k h, f (t.getKey k h) (get t k h) = none := + Impl.Const.isEmpty_filterMap_iff t.wf + +theorem isEmpty_filterMap_eq_false_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).isEmpty = false ↔ ∃ k h, (f (t.getKey k h) (get t k h)).isSome := + Impl.Const.isEmpty_filterMap_eq_false_iff t.wf + +-- TODO: `contains_filterMap` is missing + +@[grind =] +theorem mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + k ∈ t.filterMap f ↔ ∃ h, (f (t.getKey k h) (Const.get t k h)).isSome := + Impl.Const.contains_filterMap_iff t.wf + +-- TODO: `size_filterMap_le_size` is missing + +theorem size_filterMap_eq_size_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).size = t.size ↔ ∀ k h, (f (t.getKey k h) (Const.get t k h)).isSome := + Impl.Const.size_filterMap_eq_size_iff t.wf + +@[simp] +theorem get?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + Const.get? (t.filterMap f) k = (Const.get? t k).pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x) := + Impl.Const.get?_filterMap t.wf + +/-- Simpler variant of `get?_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get?_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} : + Const.get? (t.filterMap f) k = (Const.get? t k).bind fun x => f k x := by + simp [get?_filterMap] + +theorem get?_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get? (t.filterMap f) k = (Const.get? t k).bind (f k') := + Impl.Const.get?_filterMap_of_getKey?_eq_some t.wf h + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + ∀ (h : k ∈ t.filterMap f), + (f (t.getKey k (mem_of_mem_filterMap h)) + (Const.get t k (mem_of_mem_filterMap h))).isSome := + Impl.Const.isSome_apply_of_contains_filterMap t.wf + +@[simp] +theorem get_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + Const.get (t.filterMap f) k h = + (f (t.getKey k (mem_of_mem_filterMap h)) + (Const.get t k (mem_of_mem_filterMap h))).get + (isSome_apply_of_mem_filterMap h) := + Impl.Const.get_filterMap t.wf + +/-- Simpler variant of `get_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + Const.get (t.filterMap f) k h = + (f k (Const.get t k (mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by + simp [get_filterMap] + +theorem get!_filterMap [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + Const.get! (t.filterMap f) k = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + Impl.Const.get!_filterMap t.wf + +/-- Simpler variant of `get!_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get!_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + Const.get! (t.filterMap f) k = ((Const.get? t k).bind (f k) ).get!:= by + simp [get!_filterMap] + +theorem get!_filterMap_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get! (t.filterMap f) k = ((Const.get? t k).bind (f k')).get! := + Impl.Const.get!_filterMap_of_getKey?_eq_some t.wf h + +theorem getD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + Const.getD (t.filterMap f) k fallback = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + Impl.Const.getD_filterMap t.wf + +/-- Simpler variant of `getD_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + Const.getD (t.filterMap f) k fallback = ((Const.get? t k).bind (f k)).getD fallback := by + simp [getD_filterMap] + +theorem getD_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + Const.getD (t.filterMap f) k fallback = ((Const.get? t k).bind (f k')).getD fallback := + Impl.Const.getD_filterMap_of_getKey?_eq_some t.wf h + +theorem toList_filterMap + {f : α → β → Option γ} : + Const.toList (t.filterMap fun k v => f k v) = + (Const.toList t).filterMap (fun p => (f p.1 p.2).map (fun x => (p.1, x))) := + Impl.Const.toList_filterMap t.wf + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))).isSome) := + Impl.Const.getKey?_filterMap t.wf + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [Inhabited α] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))).isSome)).get! := + Impl.Const.getKey!_filterMap t.wf + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k fallback : α} : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))).isSome)).getD fallback := + Impl.Const.getKeyD_filterMap t.wf + +end Const + +end filterMap + +section filter + +theorem filterMap_equiv_filter {f : (a : α) → β a → Bool} : + t.filterMap (fun k => Option.guard (fun v => f k v)) ~m t.filter f := + ⟨Impl.filterMap_equiv_filter t.wf⟩ + +@[simp, grind =] +theorem toList_filter {f : (a : α) → β a → Bool} : + (t.filter f).toList = t.toList.filter (fun p => f p.1 p.2) := + Impl.toList_filter t.wf + +theorem keys_filter_key {f : α → Bool} : + (t.filter fun k _ => f k).keys = t.keys.filter f := + Impl.keys_filter_key t.wf + +@[grind =] +theorem isEmpty_filter_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + (t.filter f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f k (t.get k h) = false := + Impl.isEmpty_filter_iff t.wf + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f k (t.get k h) = true := + Impl.isEmpty_filter_eq_false_iff t.wf + +theorem isEmpty_filter_key_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter (fun a _ => f a)).isEmpty ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) = false := + Impl.isEmpty_filter_key_iff t.wf + +theorem isEmpty_filter_key_eq_false_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter (fun a _ => f a)).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f (t.getKey k h) := + Impl.isEmpty_filter_key_eq_false_iff t.wf + +@[grind =] +theorem contains_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).contains k = (t.get? k).any (f k) := + Impl.contains_filter t.wf + +@[grind =] +theorem mem_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ h, f k (t.get k h) := by + simp only [mem_iff_contains, contains_filter, Option.any_eq_true_iff_get, + ← contains_eq_isSome_get?, get_get?] + +theorem mem_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} : + k ∈ t.filter (fun a _ => f a) ↔ ∃ h, f (t.getKey k h) := + Impl.contains_filter_key_iff t.wf + +theorem contains_of_contains_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).contains k = true → t.contains k = true := + Impl.contains_of_contains_filter t.wf + +theorem mem_of_mem_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + k ∈ (t.filter f) → k ∈ t := + Impl.contains_of_contains_filter t.wf + +theorem size_filter_le_size [TransCmp cmp] + {f : (a : α) → β a → Bool} : + (t.filter f).size ≤ t.size := + Impl.size_filter_le_size t.wf + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + (t.filter f).size = t.size ↔ ∀ k h, f k (t.get k h) := + Impl.size_filter_eq_size_iff t.wf + +theorem filter_equiv_self_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + t.filter f ~m t ↔ ∀ k h, f k (t.get k h) := + ⟨fun h => (Impl.filter_equiv_self_iff t.wf).mp h.1, + fun h => ⟨(Impl.filter_equiv_self_iff t.wf).mpr h⟩⟩ + +theorem filter_key_equiv_self_iff [TransCmp cmp] + {f : (a : α) → Bool} : + t.filter (fun k _ => f k) ~m t ↔ ∀ k h, f (t.getKey k h) := + ⟨fun h => (Impl.filter_key_equiv_self_iff t.wf).mp h.1, + fun h => ⟨(Impl.filter_key_equiv_self_iff t.wf).mpr h⟩⟩ + +theorem size_filter_key_eq_size_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter fun k _ => f k).size = t.size ↔ ∀ (k : α) (h : k ∈ t), f (t.getKey k h) := + Impl.size_filter_key_eq_size_iff t.wf + +@[simp, grind =] +theorem get?_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).get? k = (t.get? k).filter (f k) := + Impl.get?_filter t.wf + +@[simp, grind =] +theorem get_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {h'} : + (t.filter f).get k h' = t.get k (mem_of_mem_filter h') := + Impl.get_filter t.wf + +@[grind =] +theorem get!_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} [Inhabited (β k)] : + (t.filter f).get! k = ((t.get? k).filter (f k)).get! := + Impl.get!_filter t.wf + +@[grind =] +theorem getD_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {fallback : β k} : + (t.filter f).getD k fallback = ((t.get? k).filter (f k)).getD fallback := + Impl.getD_filter t.wf + +theorem keys_filter [TransCmp cmp] [LawfulEqCmp cmp] {f : (a : α) → β a → Bool} : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (t.get x (mem_of_mem_keys h')))).unattach := + Impl.keys_filter t.wf + +@[grind =] +theorem getKey?_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h'))) := + Impl.getKey?_filter t.wf + +theorem getKey?_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey? k = (t.getKey? k).filter f := + Impl.getKey?_filter_key t.wf + +@[simp, grind =] +theorem getKey_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {h'} : + (t.filter f).getKey k h' = t.getKey k (mem_of_mem_filter h') := + Impl.getKey_filter t.wf + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h')))).get! := + Impl.getKey!_filter t.wf + +theorem getKey!_filter_key [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey! k = ((t.getKey? k).filter f).get! := + Impl.getKey!_filter_key t.wf + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k fallback : α} : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h')))).getD fallback := + Impl.getKeyD_filter t.wf + +theorem getKeyD_filter_key [TransCmp cmp] + {f : α → Bool} {k fallback : α} : + (t.filter fun k _ => f k).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := + Impl.getKeyD_filter_key t.wf + +namespace Const + +variable {β : Type v} {γ : Type w} {t : DTreeMap α (fun _ => β) cmp} + +@[grind =] +theorem isEmpty_filter_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) (Const.get t k h) = false := + Impl.Const.isEmpty_filter_iff t.wf + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), (f (t.getKey k h) (Const.get t k h)) = true := + Impl.Const.isEmpty_filter_eq_false_iff t.wf + +-- TODO: `contains_filter` is missing + +@[grind =] +theorem mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ (h' : k ∈ t), + f (t.getKey k h') (Const.get t k h') := + Impl.Const.contains_filter_iff t.wf + +theorem size_filter_le_size [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size ≤ t.size := + Impl.Const.size_filter_le_size t.wf + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), + f (t.getKey a h) (Const.get t a h) := + Impl.Const.size_filter_eq_size_iff t.wf + +theorem filter_equiv_self_iff [TransCmp cmp] + {f : α → β → Bool} : + t.filter f ~m t ↔ ∀ k h, f (t.getKey k h) (Const.get t k h) := + ⟨fun h => (Impl.Const.filter_equiv_self_iff t.wf).mp h.1, + fun h => ⟨(Impl.Const.filter_equiv_self_iff t.wf).mpr h⟩ ⟩ + +theorem get?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + Const.get? (t.filter f) k = (Const.get? t k).pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x) := + Impl.Const.get?_filter t.wf + +/-- Simpler variant of `get?_filter` when `LawfulEqCmp` is available. -/ +@[simp, grind =] +theorem get?_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} : + Const.get? (t.filter f) k = (Const.get? t k).filter (f k) := by + simp [get?_filter] + +theorem get?_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + Const.get? (t.filter f) k = (Const.get? t k).filter (fun x => f k' x) := + Impl.Const.get?_filter_of_getKey?_eq_some t.wf + +@[simp, grind =] +theorem get_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} : + Const.get (t.filter f) k h' = Const.get t k (mem_of_mem_filter h') := + Impl.Const.get_filter t.wf + +theorem get!_filter [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + Const.get! (t.filter f) k = + ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + Impl.Const.get!_filter t.wf + +/-- Simpler variant of `get!_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get!_filter' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + Const.get! (t.filter f) k = ((Const.get? t k).filter (f k)).get! := by + simp [get!_filter] + +theorem get!_filter_of_getKey?_eq_some [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + Const.get! (t.filter f) k = ((Const.get? t k).filter (fun x => f k' x)).get! := + Impl.Const.get!_filter_of_getKey?_eq_some t.wf + +theorem getD_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + Const.getD (t.filter f) k fallback = ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + Impl.Const.getD_filter t.wf + +/-- Simpler variant of `getD_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + Const.getD (t.filter f) k fallback = ((Const.get? t k).filter (f k)).getD fallback := by + simp [getD_filter] + +theorem getD_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} {fallback : β} : + t.getKey? k = some k' → + Const.getD (t.filter f) k fallback = + ((Const.get? t k).filter (fun x => f k' x)).getD fallback := + Impl.Const.getD_filter_of_getKey?_eq_some t.wf + +@[simp, grind =] +theorem toList_filter {f : α → β → Bool} : + toList (t.filter f) = + (toList t).filter (fun p => f p.1 p.2) := + Impl.Const.toList_filter t.wf + +theorem keys_filter [TransCmp cmp] {f : α → β → Bool} : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h')))).unattach := + Impl.Const.keys_filter t.wf + +@[grind =] +theorem getKey?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h')))) := + Impl.Const.getKey?_filter t.wf + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [Inhabited α] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))))).get! := + Impl.Const.getKey!_filter t.wf + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] + {f : α → β → Bool} {k fallback : α} : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))))).getD fallback := + Impl.Const.getKeyD_filter t.wf + +end Const + +end filter + +section map + +variable {γ : α → Type w} {δ : α → Type w'} + +theorem map_id_equiv : t.map (fun _ v => v) ~m t := + ⟨Impl.map_id_equiv⟩ + +theorem map_map_equiv {f : (a : α) → β a → γ a} {g : (a : α) → γ a → δ a} : + (t.map f).map g ~m t.map fun k v => g k (f k v) := + ⟨Impl.map_map_equiv⟩ + +@[simp, grind =] +theorem toList_map {f : (a : α) → β a → γ a} : + (t.map f).toList = t.toList.map (fun p => ⟨p.1, f p.1 p.2⟩) := + Impl.toList_map + +@[simp, grind =] +theorem keys_map {f : (a : α) → β a → γ a} : (t.map f).keys = t.keys := + Impl.keys_map + +theorem filterMap_equiv_map [TransCmp cmp] + {f : (a : α) → β a → γ a} : + (t.filterMap (fun k v => some (f k v))) ~m t.map f := + ⟨Impl.filterMap_equiv_map t.wf⟩ + +@[simp, grind =] +theorem isEmpty_map [TransCmp cmp] + {f : (a : α) → β a → γ a} : + (t.map f).isEmpty = t.isEmpty := + Impl.isEmpty_map + +@[grind =] +theorem contains_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).contains k = t.contains k := + Impl.contains_map t.wf + +theorem contains_of_contains_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).contains k = true → t.contains k = true := + Impl.contains_of_contains_map t.wf + +@[simp, grind =] +theorem mem_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + k ∈ t.map f ↔ k ∈ t := by + simp only [mem_iff_contains, contains_map] + +theorem mem_of_mem_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + k ∈ t.map f → k ∈ t := + Impl.contains_of_contains_map t.wf + +@[simp, grind =] +theorem size_map [TransCmp cmp] + {f : (a : α) → β a → γ a} : + (t.map f).size = t.size := + Impl.size_map + +@[simp, grind =] +theorem get?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).get? k = (t.get? k).map (f k) := + Impl.get?_map t.wf + +@[simp, grind =] +theorem get_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {h'} : + (t.map f).get k h' = f k (t.get k (mem_of_mem_map h')) := + Impl.get_map t.wf + +@[grind =] +theorem get!_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} [Inhabited (γ k)] : + (t.map f).get! k = ((t.get? k).map (f k)).get! := + Impl.get!_map t.wf + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {fallback : γ k} : + (t.map f).getD k fallback = ((t.get? k).map (f k)).getD fallback := + Impl.getD_map t.wf + +@[simp, grind =] +theorem getKey?_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).getKey? k = t.getKey? k := + Impl.getKey?_map t.wf + +@[simp, grind =] +theorem getKey_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {h'} : + (t.map f).getKey k h' = t.getKey k (mem_of_mem_map h') := + Impl.getKey_map t.wf + +@[simp, grind =] +theorem getKey!_map [TransCmp cmp] [Inhabited α] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).getKey! k = t.getKey! k := + Impl.getKey!_map t.wf + +@[simp, grind =] +theorem getKeyD_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k fallback : α} : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := + Impl.getKeyD_map t.wf + +namespace Const + +variable {β : Type v} {γ : Type w} {t : DTreeMap α (fun _ => β) cmp} + +@[simp, grind =] +theorem get?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} : + Const.get? (t.map f) k = (Const.get? t k).map (f k) := + Impl.Const.get?_map t.wf + +/-- Variant of `get?_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem get?_map' [TransCmp cmp] + {f : α → β → γ} {k : α} : + Const.get? (t.map f) k = (Const.get? t k).pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h')) := + Impl.Const.get?_map' t.wf + +theorem get?_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get? (t.map f) k = (Const.get? t k).map (f k') := + Impl.Const.get?_map_of_getKey?_eq_some t.wf h + +@[simp, grind =] +theorem get_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {h'} : + Const.get (t.map f) k h' = f k (Const.get t k (mem_of_mem_map h')) := + Impl.Const.get_map t.wf + +/-- Variant of `get_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem get_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} : + Const.get (t.map f) k h' = + f (t.getKey k (mem_of_mem_map h')) (Const.get t k (mem_of_mem_map h')) := + Impl.Const.get_map' t.wf + +@[grind =] +theorem get!_map [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + Const.get! (t.map f) k = ((Const.get? t k).map (f k)).get! := + Impl.Const.get!_map t.wf + +/-- Variant of `get!_map` that holds without `LawfulEqCmp`. -/ +theorem get!_map' [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + Const.get! (t.map f) k = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_get?.mpr (Option.isSome_of_mem h'))).get! := + Impl.Const.get!_map' t.wf + +theorem get!_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get! (t.map f) k = ((Const.get? t k).map (f k')).get! := + Impl.Const.get!_map_of_getKey?_eq_some t.wf h + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k)).getD fallback := + Impl.Const.getD_map t.wf + +/-- Variant of `getD_map` that holds without `LawfulEqCmp`. -/ +theorem getD_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + Const.getD (t.map f) k fallback = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))).getD fallback := + Impl.Const.getD_map' t.wf + +theorem getD_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k')).getD fallback := + Impl.Const.getD_map_of_getKey?_eq_some t.wf h + +@[simp, grind =] +theorem toList_map {f : α → β → γ} : + (Const.toList (t.map f)) = + (Const.toList t).map (fun p => (p.1, f p.1 p.2)) := + Impl.Const.toList_map + +end Const + +end map + end Std.DTreeMap diff --git a/src/Std/Data/DTreeMap/Raw/Lemmas.lean b/src/Std/Data/DTreeMap/Raw/Lemmas.lean index 41fb38d5e1..adc9f7dc15 100644 --- a/src/Std/Data/DTreeMap/Raw/Lemmas.lean +++ b/src/Std/Data/DTreeMap/Raw/Lemmas.lean @@ -357,10 +357,18 @@ theorem get_erase [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k a : α} {h'} : (t.erase k).get a h' = t.get a (mem_of_mem_erase h h') := Impl.get_erase! h -theorem get?_eq_some_get [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {a : α} {h'} : +theorem get?_eq_some_get [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {a : α} (h') : t.get? a = some (t.get a h') := Impl.get?_eq_some_get h +theorem get_eq_get_get? [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {a : α} {h'} : + t.get a h' = (t.get? a).get ((mem_iff_isSome_get? h).mp h') := by + simp only [get?_eq_some_get h h', Option.get_some] + +@[grind =] theorem get_get? [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {a : α} {h'} : + (t.get? a).get h' = t.get a ((mem_iff_isSome_get? h).mpr h') := + (get_eq_get_get? h).symm + namespace Const variable {β : Type v} {t : Raw α β cmp} @@ -381,10 +389,18 @@ theorem get_erase [TransCmp cmp] (h : t.WF) {k a : α} {h'} : get (t.erase k) a h' = get t a (mem_of_mem_erase h h') := Impl.Const.get_erase! h -theorem get?_eq_some_get [TransCmp cmp] (h : t.WF) {a : α} {h'} : +theorem get?_eq_some_get [TransCmp cmp] (h : t.WF) {a : α} (h') : get? t a = some (get t a h') := Impl.Const.get?_eq_some_get h +theorem get_eq_get_get? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + get t a h' = (get? t a).get ((mem_iff_isSome_get? h).mp h') := by + simp only [get?_eq_some_get h h', Option.get_some] + +@[grind =] theorem get_get? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + (get? t a).get h' = get t a ((mem_iff_isSome_get? h).mpr h') := + (get_eq_get_get? h).symm + theorem get_eq_get [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {a : α} {h'} : get t a h' = t.get a h' := Impl.Const.get_eq_get h @@ -677,6 +693,10 @@ theorem isSome_getKey?_iff_mem [TransCmp cmp] (h : t.WF) {a : α} : (t.getKey? a).isSome ↔ a ∈ t := (mem_iff_isSome_getKey? h).symm +theorem mem_of_getKey?_eq_some [TransCmp cmp] (h : t.WF) {k k' : α} : + t.getKey? k = some k' → k' ∈ t := + Impl.mem_of_getKey?_eq_some h + theorem getKey?_eq_none_of_contains_eq_false [TransCmp cmp] (h : t.WF) {a : α} : t.contains a = false → t.getKey? a = none := Impl.getKey?_eq_none_of_contains_eq_false h @@ -729,10 +749,19 @@ theorem getKey_erase [TransCmp cmp] (h : t.WF) {k a : α} {h'} : (t.erase k).getKey a h' = t.getKey a (mem_of_mem_erase h h') := Impl.getKey_erase! h -theorem getKey?_eq_some_getKey [TransCmp cmp] (h : t.WF) {a : α} {h'} : +theorem getKey?_eq_some_getKey [TransCmp cmp] (h : t.WF) {a : α} (h') : t.getKey? a = some (t.getKey a h') := Impl.getKey?_eq_some_getKey h +theorem getKey_eq_get_getKey? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + t.getKey a h' = (t.getKey? a).get ((mem_iff_isSome_getKey? h).mp h') := by + simp only [getKey?_eq_some_getKey h h', Option.get_some] + +@[simp, grind =] +theorem get_getKey? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + (t.getKey? a).get h' = t.getKey a ((mem_iff_isSome_getKey? h).mpr h') := + (getKey_eq_get_getKey? h).symm + theorem compare_getKey_self [TransCmp cmp] (h : t.WF) {k : α} (h' : k ∈ t) : cmp (t.getKey k h') k = .eq := Impl.compare_getKey_self h h' @@ -1060,6 +1089,10 @@ theorem mem_keys [LawfulEqCmp cmp] [TransCmp cmp] (h : t.WF) {k : α} : k ∈ t.keys ↔ k ∈ t := Impl.mem_keys h +theorem mem_of_mem_keys [TransCmp cmp] (h : t.WF) {k : α} + (h' : k ∈ t.keys) : k ∈ t := + Impl.mem_of_mem_keys h h' + theorem distinct_keys [TransCmp cmp] (h : t.WF) : t.keys.Pairwise (fun a b => ¬ cmp a b = .eq) := Impl.distinct_keys h.out @@ -4251,7 +4284,7 @@ theorem map (h : t₁ ~m t₂) (f : (a : α) → β a → γ a) : t₁.map f ~m t₂.map f := ⟨h.1.map⟩ -theorem filterMap (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (f : (a : α) → β a → Option (γ a)) : +theorem filterMap (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (f : (a : α) → β a → Option (γ a)) : t₁.filterMap f ~m t₂.filterMap f := ⟨h.1.filterMap! h₁.1 h₂.1⟩ @@ -4507,4 +4540,772 @@ end Const end Equiv +section filterMap + +theorem toList_filterMap {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f).toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := + Impl.toList_filterMap! h + +@[grind =] +theorem isEmpty_filterMap_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f k (t.get k h) = none := + Impl.isEmpty_filterMap!_iff h + +theorem isEmpty_filterMap_eq_false_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), (f k (t.get k h)).isSome := + Impl.isEmpty_filterMap!_eq_false_iff h + +@[grind =] +theorem contains_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f).contains k = (t.get? k).any (f k · |>.isSome) := + Impl.contains_filterMap! h + +@[grind =] +theorem mem_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + k ∈ t.filterMap f ↔ ∃ h, (f k (t.get k h)).isSome := by + simp only [mem_iff_contains, contains_filterMap, Option.any_eq_true_iff_get, + ← contains_eq_isSome_get?, get_get?, h] + +theorem contains_of_contains_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f).contains k = true → t.contains k = true := + Impl.contains_of_contains_filterMap! h + +theorem mem_of_mem_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + k ∈ t.filterMap f → k ∈ t := + contains_of_contains_filterMap h + +theorem size_filterMap_le_size [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f).size ≤ t.size := + Impl.size_filterMap!_le_size h + +grind_pattern size_filterMap_le_size => (t.filterMap f).size + +theorem size_filterMap_eq_size_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} (h : t.WF) : + (t.filterMap f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), (f a (t.get a h)).isSome := + Impl.size_filterMap!_eq_size_iff h + +@[simp, grind =] +theorem get?_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f).get? k = (t.get? k).bind (f k) := + Impl.get?_filterMap! h + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + ∀ (h' : k ∈ t.filterMap f), + (f k (t.get k (mem_of_mem_filterMap h h'))).isSome := + Impl.isSome_apply_of_contains_filterMap! h + +@[simp, grind =] +theorem get_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {h'} (h : t.WF) : + (t.filterMap f).get k h' = + (f k (t.get k (mem_of_mem_filterMap h h'))).get + (isSome_apply_of_mem_filterMap h h') := + Impl.get_filterMap! h + +@[grind =] +theorem get!_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} [Inhabited (γ k)] (h : t.WF) : + (t.filterMap f).get! k = ((t.get? k).bind (f k)).get! := + Impl.get!_filterMap! h + +@[grind =] +theorem getD_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {fallback : γ k} (h : t.WF) : + (t.filterMap f).getD k fallback = ((t.get? k).bind (f k)).getD fallback := + Impl.getD_filterMap! h + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome) := + Impl.getKey?_filterMap! h + +@[simp, grind =] +theorem getKey_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {h'} (h : t.WF) : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h h') := + Impl.getKey_filterMap! h + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] + {f : (a : α) → β a → Option (γ a)} {k : α} (h : t.WF) : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome)).get! := + Impl.getKey!_filterMap! h + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k fallback : α} (h : t.WF) : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := + Impl.getKeyD_filterMap! h + +namespace Const + +variable {β : Type v} {γ : Type w} {t : Raw α (fun _ => β) cmp} + +@[grind =] +theorem isEmpty_filterMap_iff [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) (Const.get t k h) = none := + Impl.Const.isEmpty_filterMap!_iff h + +theorem isEmpty_filterMap_eq_false_iff [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), (f (t.getKey k h) (Const.get t k h)).isSome := + Impl.Const.isEmpty_filterMap!_eq_false_iff h + +-- TODO: `contains_filterMap` is missing + +@[grind =] +theorem mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + k ∈ t.filterMap f ↔ ∃ h, (f (t.getKey k h) (Const.get t k h)).isSome := + Impl.Const.contains_filterMap!_iff h + +theorem size_filterMap_eq_size_iff [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).size = t.size ↔ ∀ k h, (f (t.getKey k h) (Const.get t k h)).isSome := + Impl.Const.size_filterMap!_eq_size_iff h + +-- TODO: `size_filterMap_le_size` is missing + +theorem get?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get? (t.filterMap f) k = (Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := + Impl.Const.get?_filterMap! h + +/-- Simpler variant of `get?_filterMap` when `LawfulEqCmp` is available. -/ +@[simp, grind =] +theorem get?_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get? (t.filterMap f) k = (Const.get? t k).bind (f k) := by + simp [get?_filterMap, h] + +theorem get?_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get? (t.filterMap f) k = (Const.get? t k).bind (f k') := + Impl.Const.get?_filterMap!_of_getKey?_eq_some h + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + ∀ (h' : k ∈ t.filterMap f), + (f (t.getKey k (mem_of_mem_filterMap h h')) + (Const.get t k (mem_of_mem_filterMap h h'))).isSome := + Impl.Const.isSome_apply_of_contains_filterMap! h + +@[simp, grind =] +theorem get_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h'} (h : t.WF) : + Const.get (t.filterMap f) k h' = + (f (t.getKey k (mem_of_mem_filterMap h h')) + (Const.get t k (mem_of_mem_filterMap h h'))).get + (isSome_apply_of_mem_filterMap h h') := + Impl.Const.get_filterMap! h + +theorem get!_filterMap [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get! (t.filterMap f) k = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) + x)).get! := + Impl.Const.get!_filterMap! h + +/-- Simpler variant of `get!_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get!_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} (h : t.WF) : + Const.get! (t.filterMap f) k = ((Const.get? t k).bind (f k)).get! := by + simp [get!_filterMap, h] + +theorem get!_filterMap_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get! (t.filterMap f) k = ((Const.get? t k).bind + fun x => f k' x).get! := + Impl.Const.get!_filterMap!_of_getKey?_eq_some h + +theorem getD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.filterMap f) k fallback = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + Impl.Const.getD_filterMap! h + +/-- Simpler variant of `getD_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.filterMap f) k fallback = ((Const.get? t k).bind (f k)).getD fallback := by + simp [getD_filterMap, h] + +theorem getD_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.WF) : + t.getKey? k = some k' → Const.getD (t.filterMap f) k fallback = ((Const.get? t k).bind + fun x => f k' x).getD fallback := + Impl.Const.getD_filterMap!_of_getKey?_eq_some h + +theorem toList_filterMap + {f : α → β → Option γ} (h : t.WF) : + Const.toList (t.filterMap f) = + (Const.toList t).filterMap (fun p => (f p.1 p.2).map (fun x => (p.1, x))) := + Impl.Const.toList_filterMap! h + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome) := + Impl.Const.getKey?_filterMap! h + +@[simp, grind =] +theorem getKey_filterMap [TransCmp cmp] + {f : (a : α) → β → Option γ} {k : α} {h'} (h : t.WF) : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h h') := + Impl.getKey_filterMap! h + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [Inhabited α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome)).get! := + Impl.Const.getKey!_filterMap! h + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k fallback : α} (h : t.WF) : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := + Impl.Const.getKeyD_filterMap! h + +end Const + +end filterMap + +section filter + +theorem filterMap_equiv_filter {f : (a : α) → β a → Bool} (h : t.WF) : + t.filterMap (fun k => Option.guard (fun v => f k v)) ~m t.filter f := + ⟨Impl.filterMap!_equiv_filter! h⟩ + +theorem toList_filter {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f).toList = t.toList.filter (fun p => f p.1 p.2) := + Impl.toList_filter! h + +theorem keys_filter_key {f : α → Bool} (h : t.WF) : + (t.filter fun k _ => f k).keys = t.keys.filter f := + Impl.keys_filter!_key h + +@[grind =] +theorem isEmpty_filter_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f k (t.get k h) = false := + Impl.isEmpty_filter!_iff h + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f k (t.get k h) = true := + Impl.isEmpty_filter!_eq_false_iff h + +theorem isEmpty_filter_key_iff [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter (fun a _ => f a)).isEmpty ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) = false := + Impl.isEmpty_filter!_key_iff h + +theorem isEmpty_filter_key_eq_false_iff [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter (fun a _ => f a)).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f (t.getKey k h) := + Impl.isEmpty_filter!_key_eq_false_iff h + +@[grind =] +theorem contains_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f).contains k = (t.get? k).any (f k) := + Impl.contains_filter! h + +@[grind =] +theorem mem_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + k ∈ t.filter f ↔ (t.get? k).any (f k) := by + simpa only [mem_iff_contains, Bool.coe_iff_coe] using contains_filter h + +theorem mem_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} (h : t.WF) : + k ∈ (t.filter (fun a _ => f a)) ↔ ∃ h : k ∈ t, f (t.getKey k h) := + Impl.contains_filter!_key_iff h + +theorem contains_of_contains_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f).contains k = true → t.contains k = true := + Impl.contains_of_contains_filter! h + +theorem mem_of_mem_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + k ∈ t.filter f → k ∈ t := + Impl.contains_of_contains_filter! h + +theorem size_filter_le_size [TransCmp cmp] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f).size ≤ t.size := + Impl.size_filter!_le_size h + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f).size = t.size ↔ ∀ k h, f k (t.get k h) = true := + Impl.size_filter!_eq_size_iff h + +theorem filter_equiv_self_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} (h : t.WF) : + t.filter f ~m t ↔ ∀ k h, f k (t.get k h) = true := + equiv_iff.trans (Impl.filter!_equiv_self_iff h) + +theorem filter_key_equiv_self_iff [TransCmp cmp] + {f : (a : α) → Bool} (h : t.WF) : + t.filter (fun k _ => f k) ~m t ↔ ∀ k h, f (t.getKey k h) = true := + equiv_iff.trans (Impl.filter!_key_equiv_self_iff h) + +theorem size_filter_key_eq_size_iff [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter fun k _ => f k).size = t.size ↔ ∀ (k : α) (h : k ∈ t), f (t.getKey k h) := + Impl.size_filter!_key_eq_size_iff h + +@[simp, grind =] +theorem get?_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f).get? k = (t.get? k).filter (f k) := + Impl.get?_filter! h + +@[simp, grind =] +theorem get_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {h'} (h : t.WF) : + (t.filter f).get k h' = t.get k (mem_of_mem_filter h h') := + Impl.get_filter! h + +@[grind =] +theorem get!_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} [Inhabited (β k)] (h : t.WF) : + (t.filter f).get! k = ((t.get? k).filter (f k)).get! := + Impl.get!_filter! h + +@[grind =] +theorem getD_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {fallback : β k} (h : t.WF) : + (t.filter f).getD k fallback = ((t.get? k).filter (f k)).getD fallback := + Impl.getD_filter! h + +theorem keys_filter [TransCmp cmp] [LawfulEqCmp cmp] {f : (a : α) → β a → Bool} (h : t.WF) : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (t.get x (mem_of_mem_keys h h')))).unattach := + Impl.keys_filter! h + +@[grind =] +theorem getKey?_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h'))) := + Impl.getKey?_filter! h + +theorem getKey?_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter fun k _ => f k).getKey? k = (t.getKey? k).filter f := + Impl.getKey?_filter!_key h + +@[simp, grind =] +theorem getKey_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {h'} (h : t.WF) : + (t.filter f).getKey k h' = t.getKey k (mem_of_mem_filter h h') := + Impl.getKey_filter! h + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] + {f : (a : α) → β a → Bool} {k : α} (h : t.WF) : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h')))).get! := + Impl.getKey!_filter! h + +theorem getKey!_filter_key [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter fun k _ => f k).getKey! k = ((t.getKey? k).filter f).get! := + Impl.getKey!_filter!_key h + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k fallback : α} (h : t.WF) : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h h')))).getD fallback := + Impl.getKeyD_filter! h + +theorem getKeyD_filter_key [TransCmp cmp] + {f : α → Bool} {k fallback : α} (h : t.WF) : + (t.filter fun k _ => f k).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := + Impl.getKeyD_filter!_key h + +namespace Const + +variable {β : Type v} {γ : Type w} {t : Raw α (fun _ => β) cmp} + +@[grind =] +theorem isEmpty_filter_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) (Const.get t k h) = false := + Impl.Const.isEmpty_filter!_iff h + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), (f (t.getKey k h) (Const.get t k h)) = true := + Impl.Const.isEmpty_filter!_eq_false_iff h + +-- TODO: `contains_filter` is missing + +@[grind =] +theorem mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + k ∈ t.filter f ↔ ∃ (h' : k ∈ t), + f (t.getKey k h') (Const.get t k h') := + Impl.Const.contains_filter!_iff h + +theorem size_filter_le_size [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).size ≤ t.size := + Impl.Const.size_filter!_le_size h + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), + f (t.getKey a h) (Const.get t a h) := + Impl.Const.size_filter!_eq_size_iff h + +theorem filter_equiv_self_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + t.filter f ~m t ↔ ∀ (a : α) (h : a ∈ t), + f (t.getKey a h) (Const.get t a h) := + equiv_iff.trans (Impl.Const.filter!_equiv_self_iff h) + +@[simp] +theorem get?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get? (t.filter f) k = (Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := + Impl.Const.get?_filter! h + +/-- Simpler variant of `get?_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get?_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get? (t.filter f) k = (Const.get? t k).filter (f k) := by + simp [get?_filter, h] + +theorem get?_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + Const.get? (t.filter f) k = (Const.get? t k).filter (fun x => f k' x) := + Impl.Const.get?_filter!_of_getKey?_eq_some h + +@[simp, grind =] +theorem get_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} (h : t.WF) : + Const.get (t.filter f) k h' = Const.get t k (mem_of_mem_filter h h') := + Impl.Const.get_filter! h + +theorem get!_filter [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get! (t.filter f) k = + ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := + Impl.Const.get!_filter! h + +/-- Simpler variant of `get!_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get!_filter' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} (h : t.WF) : + Const.get! (t.filter f) k = ((Const.get? t k).filter (f k)).get! := by + simp [get!_filter, h] + +theorem get!_filter_of_getKey?_eq_some [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + Const.get! (t.filter f) k = ((Const.get? t k).filter (fun x => f k' x)).get! := + Impl.Const.get!_filter!_of_getKey?_eq_some h + +theorem getD_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} (h : t.WF) : + Const.getD (t.filter f) k fallback = ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + Impl.Const.getD_filter! h + +/-- Simpler variant of `getD_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} (h : t.WF) : + Const.getD (t.filter f) k fallback = ((Const.get? t k).filter (f k)).getD fallback := by + simp [getD_filter, h] + +theorem getD_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} {fallback : β} (h : t.WF) : + t.getKey? k = some k' → + Const.getD (t.filter f) k fallback = + ((Const.get? t k).filter (fun x => f k' x)).getD fallback := + Impl.Const.getD_filter!_of_getKey?_eq_some h + +theorem toList_filter {f : α → β → Bool} (h : t.WF) : + Const.toList (t.filter f) = + (Const.toList t).filter (fun p => f p.1 p.2) := + Impl.Const.toList_filter! h + +theorem keys_filter [TransCmp cmp] {f : α → β → Bool} (h : t.WF) : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h h')))).unattach := + Impl.Const.keys_filter! h + +@[grind =] +theorem getKey?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h')))) := + Impl.Const.getKey?_filter! h + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [Inhabited α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))))).get! := + Impl.Const.getKey!_filter! h + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] + {f : α → β → Bool} {k fallback : α} (h : t.WF) : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h h'))))).getD fallback := + Impl.Const.getKeyD_filter! h + +end Const + +end filter + +section map + +variable {γ : α → Type w} {δ : α → Type w'} + +theorem map_id_equiv : t.map (fun _ v => v) ~m t := + ⟨Impl.map_id_equiv⟩ + +theorem map_map_equiv {f : (a : α) → β a → γ a} {g : (a : α) → γ a → δ a} : + (t.map f).map g ~m t.map fun k v => g k (f k v) := + ⟨Impl.map_map_equiv⟩ + +theorem toList_map {f : (a : α) → β a → γ a} : + (t.map f).toList = t.toList.map (fun p => ⟨p.1, f p.1 p.2⟩) := + Impl.toList_map + +theorem keys_map {f : (a : α) → β a → γ a} : (t.map f).keys = t.keys := + Impl.keys_map + +theorem filterMap_equiv_map [TransCmp cmp] + {f : (a : α) → β a → γ a} (h : t.WF) : + (t.filterMap (fun k v => some (f k v))) ~m t.map f := + ⟨Impl.filterMap!_equiv_map h⟩ + +@[simp, grind =] +theorem isEmpty_map [TransCmp cmp] {f : (a : α) → β a → γ a} : + (t.map f).isEmpty = t.isEmpty := + Impl.isEmpty_map + +@[grind =] +theorem contains_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).contains k = t.contains k := + Impl.contains_map h + +theorem contains_of_contains_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).contains k = true → t.contains k = true := + Impl.contains_of_contains_map h + +@[simp, grind =] +theorem mem_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + k ∈ (t.map f) ↔ k ∈ t := by + simpa only [mem_iff_contains, Bool.coe_iff_coe] using Impl.contains_map h + +theorem mem_of_mem_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + k ∈ (t.map f) → k ∈ t := + Impl.contains_of_contains_map h + +@[simp, grind =] +theorem size_map [TransCmp cmp] {f : (a : α) → β a → γ a} : + (t.map f).size = t.size := + Impl.size_map + +@[simp, grind =] +theorem get?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).get? k = (t.get? k).map (f k) := + Impl.get?_map h + +@[simp, grind =] +theorem get_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {h'} (h : t.WF) : + (t.map f).get k h' = f k (t.get k (mem_of_mem_map h h')) := + Impl.get_map h + +@[grind =] +theorem get!_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} [Inhabited (γ k)] (h : t.WF) : + (t.map f).get! k = ((t.get? k).map (f k)).get! := + Impl.get!_map h + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {fallback : γ k} (h : t.WF) : + (t.map f).getD k fallback = ((t.get? k).map (f k)).getD fallback := + Impl.getD_map h + +@[simp, grind =] +theorem getKey?_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).getKey? k = t.getKey? k := + Impl.getKey?_map h + +@[simp, grind =] +theorem getKey_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {h'} (h : t.WF) : + (t.map f).getKey k h' = t.getKey k (mem_of_mem_map h h') := + Impl.getKey_map h + +@[simp, grind =] +theorem getKey!_map [TransCmp cmp] [Inhabited α] + {f : (a : α) → β a → γ a} {k : α} (h : t.WF) : + (t.map f).getKey! k = t.getKey! k := + Impl.getKey!_map h + +@[simp, grind =] +theorem getKeyD_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k fallback : α} (h : t.WF) : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := + Impl.getKeyD_map h + +namespace Const + +variable {β : Type v} {γ : Type w} {t : Raw α (fun _ => β) cmp} + +/-- Variant of `get?_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem get?_map' [TransCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get? (t.map f) k = (Const.get? t k).pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => (mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h')) := + Impl.Const.get?_map' h + +@[simp, grind =] +theorem get?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get? (t.map f) k = (Const.get? t k).map (f k) := by + simp [get?_map' h, getKey_eq h] + +theorem get?_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get? (t.map f) k = (Const.get? t k).map (f k') := + Impl.Const.get?_map_of_getKey?_eq_some h + +/-- Variant of `get_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem get_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} (h : t.WF) : + Const.get (t.map f) k h' = + (f (t.getKey k (mem_of_mem_map h h')) + (Const.get t k (mem_of_mem_map h h'))) := + Impl.Const.get_map' h + +@[simp, grind =] +theorem get_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) {h'} : + Const.get (t.map f) k h' = f k (Const.get t k (mem_of_mem_map h h')) := by + simp [get_map' h, getKey_eq h] + +/-- Variant of `get!_map` that holds without `LawfulEqCmp`. -/ +theorem get!_map' [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get! (t.map f) k = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => (mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))).get! := + Impl.Const.get!_map' h + +@[grind =] +theorem get!_map [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} (h : t.WF) : + Const.get! (t.map f) k = ((Const.get? t k).map (f k)).get! := by + simp [get!_map' h, getKey_eq h] + +theorem get!_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → Const.get! (t.map f) k = ((Const.get? t k).map (f k')).get! := + Impl.Const.get!_map_of_getKey?_eq_some h + +/-- Variant of `getD_map` that holds without `LawfulEqCmp`. -/ +theorem getD_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.map f) k fallback = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => (mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))).getD fallback := + Impl.Const.getD_map' h + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} (h : t.WF) : + Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k)).getD fallback := by + simp [getD_map' h, getKey_eq h] + +theorem getD_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.WF) : + t.getKey? k = some k' → Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k')).getD fallback := + Impl.Const.getD_map_of_getKey?_eq_some h + +theorem toList_map {f : α → β → γ} : + Const.toList (t.map f) = + (Const.toList t).map (fun p => (p.1, f p.1 p.2)) := + Impl.Const.toList_map + +end Const + +end map + end Std.DTreeMap.Raw diff --git a/src/Std/Data/ExtDHashMap/Lemmas.lean b/src/Std/Data/ExtDHashMap/Lemmas.lean index 81d6be269a..01431e398d 100644 --- a/src/Std/Data/ExtDHashMap/Lemmas.lean +++ b/src/Std/Data/ExtDHashMap/Lemmas.lean @@ -2952,7 +2952,7 @@ theorem get?_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get?_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get?_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem get?_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} : Const.get? (m.filterMap f) k = (Const.get? m k).bind (f k) := by simp [get?_filterMap] @@ -2980,7 +2980,7 @@ theorem get_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem get_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {h} : Const.get (m.filterMap f) k h = (f k (Const.get m k (mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by simp [get_filterMap] @@ -2994,7 +2994,7 @@ theorem get!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ] /-- Simpler variant of `get!_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem get!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem get!_filterMap' [LawfulBEq α] [Inhabited γ] {f : α → β → Option γ} {k : α} : Const.get! (m.filterMap f) k = ((Const.get? m k).bind (f k)).get! := by simp [get!_filterMap] @@ -3013,7 +3013,7 @@ theorem getD_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getD_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {fallback : γ} : Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind (f k)).getD fallback := by simp [getD_filterMap] @@ -3057,7 +3057,6 @@ theorem filterMap_eq_filter [EquivBEq α] [LawfulHashable α] {f : (a : α) → m.filterMap (fun k => Option.guard (fun v => f k v)) = m.filter f := m.inductionOn fun _ => sound DHashMap.filterMap_equiv_filter -@[simp] theorem filter_eq_empty_iff [LawfulBEq α] {f : (a : α) → β a → Bool} : m.filter f = ∅ ↔ ∀ k h, f k (m.get k h) = false := @@ -3217,7 +3216,7 @@ theorem get?_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `get?_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem get?_filter' [LawfulBEq α] [LawfulHashable α] +theorem get?_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} : Const.get? (m.filter f) k = (Const.get? m k).filter (f k) := by simp [get?_filter] @@ -3243,7 +3242,7 @@ theorem get!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β] /-- Simpler variant of `get!_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem get!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β] +theorem get!_filter' [LawfulBEq α] [Inhabited β] {f : α → β → Bool} {k : α} : Const.get! (m.filter f) k = ((Const.get? m k).filter (f k)).get! := by simp [get!_filter] @@ -3262,7 +3261,7 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filter' [LawfulBEq α] [LawfulHashable α] +theorem getD_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} {fallback : β} : Const.getD (m.filter f) k fallback = ((Const.get? m k).filter (f k)).getD fallback := by simp [getD_filter] @@ -3402,7 +3401,7 @@ namespace Const variable {β : Type v} {γ : Type w} {m : ExtDHashMap α fun _ => β} @[simp, grind =] -theorem get?_map [LawfulBEq α] [LawfulHashable α] +theorem get?_map [LawfulBEq α] {f : α → β → γ} {k : α} : Const.get? (m.map f) k = (Const.get? m k).map (f k) := m.inductionOn fun _ => DHashMap.Const.get?_map @@ -3421,7 +3420,7 @@ theorem get?_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] m.inductionOn (fun _ h => DHashMap.Const.get?_map_of_getKey?_eq_some h) h @[simp, grind =] -theorem get_map [LawfulBEq α] [LawfulHashable α] +theorem get_map [LawfulBEq α] {f : α → β → γ} {k : α} {h'} : Const.get (m.map f) k h' = f k (Const.get m k (mem_of_mem_map h')) := m.inductionOn (fun _ _ => DHashMap.Const.get_map) h' @@ -3434,7 +3433,7 @@ theorem get_map' [EquivBEq α] [LawfulHashable α] f (m.getKey k (mem_of_mem_map h')) (Const.get m k (mem_of_mem_map h')) := m.inductionOn (fun _ _ => DHashMap.Const.get_map') h' -@[grind =] theorem get!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +@[grind =] theorem get!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} : Const.get! (m.map f) k = ((Const.get? m k).map (f k)).get! := m.inductionOn fun _ => DHashMap.Const.get!_map @@ -3452,7 +3451,7 @@ theorem get!_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited Const.get! (m.map f) k = ((Const.get? m k).map (f k')).get! := m.inductionOn (fun _ h => DHashMap.Const.get!_map_of_getKey?_eq_some h) h -@[grind =] theorem getD_map [LawfulBEq α] [LawfulHashable α] +@[grind =] theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} : Const.getD (m.map f) k fallback = ((Const.get? m k).map (f k)).getD fallback := m.inductionOn fun _ => DHashMap.Const.getD_map diff --git a/src/Std/Data/ExtDTreeMap/Lemmas.lean b/src/Std/Data/ExtDTreeMap/Lemmas.lean index 7579770a8e..a9ad41c665 100644 --- a/src/Std/Data/ExtDTreeMap/Lemmas.lean +++ b/src/Std/Data/ExtDTreeMap/Lemmas.lean @@ -334,7 +334,15 @@ theorem get_erase [TransCmp cmp] [LawfulEqCmp cmp] {k a : α} {h'} : theorem get?_eq_some_get [TransCmp cmp] [LawfulEqCmp cmp] {a : α} (h') : t.get? a = some (t.get a h') := - t.inductionOn (fun _ _ => DTreeMap.get?_eq_some_get) h' + t.inductionOn (fun _ => DTreeMap.get?_eq_some_get) h' + +theorem get_eq_get_get? [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h} : + t.get a h = (t.get? a).get (mem_iff_isSome_get?.mp h) := + t.inductionOn (fun _ _ => DTreeMap.get_eq_get_get?) h + +@[grind =] theorem get_get? [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h} : + (t.get? a).get h = t.get a (mem_iff_isSome_get?.mpr h) := + t.inductionOn (fun _ _ => DTreeMap.get_get?) h namespace Const @@ -358,7 +366,15 @@ theorem get_erase [TransCmp cmp] {k a : α} {h'} : theorem get?_eq_some_get [TransCmp cmp] {a : α} (h) : get? t a = some (get t a h) := - t.inductionOn (fun _ _ => DTreeMap.Const.get?_eq_some_get) h + t.inductionOn (fun _ => DTreeMap.Const.get?_eq_some_get) h + +theorem get_eq_get_get? [TransCmp cmp] {a : α} {h} : + get t a h = (get? t a).get (mem_iff_isSome_get?.mp h) := + t.inductionOn (fun _ _ => DTreeMap.Const.get_eq_get_get?) h + +@[grind =] theorem get_get? [TransCmp cmp] {a : α} {h} : + (get? t a).get h = get t a (mem_iff_isSome_get?.mpr h) := + t.inductionOn (fun _ _ => DTreeMap.Const.get_get?) h theorem get_eq_get [TransCmp cmp] [LawfulEqCmp cmp] {a : α} {h} : get t a h = t.get a h := t.inductionOn (fun _ _ => DTreeMap.Const.get_eq_get) h @@ -630,6 +646,10 @@ theorem isSome_getKey?_iff_mem [TransCmp cmp] {a : α} : (t.getKey? a).isSome ↔ a ∈ t := t.inductionOn fun _ => DTreeMap.isSome_getKey?_iff_mem +theorem mem_of_getKey?_eq_some [TransCmp cmp] {k k' : α} : + t.getKey? k = some k' → k' ∈ t := + t.inductionOn fun _ => DTreeMap.mem_of_getKey?_eq_some + theorem getKey?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} : t.contains a = false → t.getKey? a = none := t.inductionOn fun _ => DTreeMap.getKey?_eq_none_of_contains_eq_false @@ -683,7 +703,16 @@ theorem getKey_erase [TransCmp cmp] {k a : α} {h'} : theorem getKey?_eq_some_getKey [TransCmp cmp] {a : α} (h') : t.getKey? a = some (t.getKey a h') := - t.inductionOn (fun _ _ => DTreeMap.getKey?_eq_some_getKey) h' + t.inductionOn (fun _ => DTreeMap.getKey?_eq_some_getKey) h' + +theorem getKey_eq_get_getKey? [TransCmp cmp] {a : α} {h} : + t.getKey a h = (t.getKey? a).get (mem_iff_isSome_getKey?.mp h) := + t.inductionOn (fun _ _ => DTreeMap.getKey_eq_get_getKey?) h + +@[simp, grind =] +theorem get_getKey? [TransCmp cmp] {a : α} {h} : + (t.getKey? a).get h = t.getKey a (mem_iff_isSome_getKey?.mpr h) := + t.inductionOn (fun _ _ => DTreeMap.get_getKey?) h theorem compare_getKey_self [TransCmp cmp] {k : α} (h' : k ∈ t) : cmp (t.getKey k h') k = .eq := @@ -1004,6 +1033,9 @@ theorem mem_keys [LawfulEqCmp cmp] [TransCmp cmp] {k : α} : k ∈ t.keys ↔ k ∈ t := t.inductionOn fun _ => DTreeMap.mem_keys +theorem mem_of_mem_keys [TransCmp cmp] {k : α} (h : k ∈ t.keys) : k ∈ t := + t.inductionOn (fun _ => DTreeMap.mem_of_mem_keys) h + theorem distinct_keys [TransCmp cmp] : t.keys.Pairwise (fun a b => ¬ cmp a b = .eq) := t.inductionOn fun _ => DTreeMap.distinct_keys @@ -4378,4 +4410,739 @@ end Const end Ext +section filterMap + +variable {γ : α → Type w} + +@[simp, grind =] +theorem toList_filterMap [TransCmp cmp] {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩)) := + t.inductionOn fun _ => DTreeMap.toList_filterMap + +theorem filterMap_eq_empty_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + t.filterMap f = ∅ ↔ ∀ k h, f k (t.get k h) = none := + isEmpty_iff.symm.trans <| t.inductionOn fun _ => DTreeMap.isEmpty_filterMap_iff + +@[grind =] +theorem contains_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).contains k = (t.get? k).any (f k · |>.isSome) := + t.inductionOn fun _ => DTreeMap.contains_filterMap + +@[grind =] +theorem mem_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + k ∈ t.filterMap f ↔ ∃ h, (f k (t.get k h)).isSome := by + simp only [mem_iff_contains, contains_filterMap, Option.any_eq_true_iff_get, + ← contains_eq_isSome_get?, get_get?] + +theorem contains_of_contains_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).contains k = true → t.contains k = true := + t.inductionOn fun _ => DTreeMap.contains_of_contains_filterMap + +theorem mem_of_mem_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + k ∈ t.filterMap f → k ∈ t := + t.inductionOn fun _ => DTreeMap.contains_of_contains_filterMap + +theorem size_filterMap_le_size [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).size ≤ t.size := + t.inductionOn fun _ => DTreeMap.size_filterMap_le_size + +grind_pattern size_filterMap_le_size => (t.filterMap f).size + +theorem size_filterMap_eq_size_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} : + (t.filterMap f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), (f a (t.get a h)).isSome := + t.inductionOn fun _ => DTreeMap.size_filterMap_eq_size_iff + +@[simp, grind =] +theorem get?_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).get? k = (t.get? k).bind (f k) := + t.inductionOn fun _ => DTreeMap.get?_filterMap + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + ∀ (h' : k ∈ t.filterMap f), + (f k (t.get k (mem_of_mem_filterMap h'))).isSome := + t.inductionOn fun _ => DTreeMap.isSome_apply_of_mem_filterMap + +@[simp, grind =] +theorem get_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {h'} : + (t.filterMap f).get k h' = + (f k (t.get k (mem_of_mem_filterMap h'))).get + (isSome_apply_of_mem_filterMap h') := + t.inductionOn (fun _ _ => DTreeMap.get_filterMap) h' + +@[simp, grind =] +theorem get!_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} [Inhabited (γ k)] : + (t.filterMap f).get! k = ((t.get? k).bind (f k)).get! := + t.inductionOn fun _ => DTreeMap.get!_filterMap + +@[simp, grind =] +theorem getD_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {fallback : γ k} : + (t.filterMap f).getD k fallback = ((t.get? k).bind (f k)).getD fallback := + t.inductionOn fun _ => DTreeMap.getD_filterMap + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h'))).isSome) := + t.inductionOn fun _ => DTreeMap.getKey?_filterMap + +@[simp, grind =] +theorem getKey_filterMap [TransCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k : α} {h'} : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h') := + t.inductionOn (fun _ _ => DTreeMap.getKey_filterMap) h' + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] + {f : (a : α) → β a → Option (γ a)} {k : α} : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h'))).isSome)).get! := + t.inductionOn fun _ => DTreeMap.getKey!_filterMap + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Option (γ a)} {k fallback : α} : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t.get x (mem_of_getKey?_eq_some h'))).isSome)).getD fallback := + t.inductionOn fun _ => DTreeMap.getKeyD_filterMap + +namespace Const + +variable {β : Type v} {γ : Type w} {t : ExtDTreeMap α (fun _ => β) cmp} + +theorem filterMap_eq_empty_iff [TransCmp cmp] {f : α → β → Option γ} : + t.filterMap f = ∅ ↔ ∀ k h, f (t.getKey k h) (get t k h) = none := + isEmpty_iff.symm.trans <| t.inductionOn fun _ => DTreeMap.Const.isEmpty_filterMap_iff + +-- TODO: `contains_filterMap` is missing + +@[grind =] +theorem mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + k ∈ t.filterMap f ↔ ∃ h, (f (t.getKey k h) (Const.get t k h)).isSome := + t.inductionOn fun _ => DTreeMap.Const.mem_filterMap + +-- TODO: `size_filterMap_le_size` is missing + +theorem size_filterMap_eq_size_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).size = t.size ↔ ∀ k h, (f (t.getKey k h) (Const.get t k h)).isSome := + t.inductionOn fun _ => DTreeMap.Const.size_filterMap_eq_size_iff + +@[simp] +theorem get?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + Const.get? (t.filterMap f) k = (Const.get? t k).pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x) := + t.inductionOn fun _ => DTreeMap.Const.get?_filterMap + +/-- Simpler variant of `get?_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get?_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} : + Const.get? (t.filterMap f) k = (Const.get? t k).bind fun x => f k x := by + simp [get?_filterMap] + +theorem get?_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get? (t.filterMap f) k = (Const.get? t k).bind (f k') := + t.inductionOn (fun _ => DTreeMap.Const.get?_filterMap_of_getKey?_eq_some) h + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + ∀ (h : k ∈ t.filterMap f), + (f (t.getKey k (mem_of_mem_filterMap h)) + (Const.get t k (mem_of_mem_filterMap h))).isSome := + t.inductionOn fun _ => DTreeMap.Const.isSome_apply_of_mem_filterMap + +@[simp] +theorem get_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + Const.get (t.filterMap f) k h = + (f (t.getKey k (mem_of_mem_filterMap h)) + (Const.get t k (mem_of_mem_filterMap h))).get + (isSome_apply_of_mem_filterMap h) := + t.inductionOn (fun _ _ => DTreeMap.Const.get_filterMap) h + +/-- Simpler variant of `get_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + Const.get (t.filterMap f) k h = + (f k (Const.get t k (mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by + simp [get_filterMap] + +theorem get!_filterMap [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + Const.get! (t.filterMap f) k = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + t.inductionOn fun _ => DTreeMap.Const.get!_filterMap + +/-- Simpler variant of `get!_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get!_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + Const.get! (t.filterMap f) k = ((Const.get? t k).bind (f k) ).get!:= by + simp [get!_filterMap] + +theorem get!_filterMap_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get! (t.filterMap f) k = ((Const.get? t k).bind (f k')).get! := + t.inductionOn (fun _ => DTreeMap.Const.get!_filterMap_of_getKey?_eq_some) h + +theorem getD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + Const.getD (t.filterMap f) k fallback = + ((Const.get? t k).pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getD_filterMap + +/-- Simpler variant of `getD_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + Const.getD (t.filterMap f) k fallback = ((Const.get? t k).bind (f k)).getD fallback := by + simp [getD_filterMap] + +theorem getD_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + Const.getD (t.filterMap f) k fallback = ((Const.get? t k).bind (f k')).getD fallback := + t.inductionOn (fun _ => DTreeMap.Const.getD_filterMap_of_getKey?_eq_some) h + +theorem toList_filterMap [TransCmp cmp] {f : α → β → Option γ} : + Const.toList (t.filterMap fun k v => f k v) = + (Const.toList t).filterMap (fun p => (f p.1 p.2).map (fun x => (p.1, x))) := + t.inductionOn fun _ => DTreeMap.Const.toList_filterMap + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))).isSome) := + t.inductionOn fun _ => DTreeMap.Const.getKey?_filterMap + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [Inhabited α] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))).isSome)).get! := + t.inductionOn fun _ => DTreeMap.Const.getKey!_filterMap + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k fallback : α} : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))).isSome)).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getKeyD_filterMap + +end Const + +end filterMap + +section filter + +theorem filterMap_eq_filter {f : (a : α) → β a → Bool} : + t.filterMap (fun k => Option.guard (fun v => f k v)) = t.filter f := + t.inductionOn fun _ => sound DTreeMap.filterMap_equiv_filter + +@[simp, grind =] +theorem toList_filter [TransCmp cmp] {f : (a : α) → β a → Bool} : + (t.filter f).toList = t.toList.filter (fun p => f p.1 p.2) := + t.inductionOn fun _ => DTreeMap.toList_filter + +theorem keys_filter_key [TransCmp cmp] {f : α → Bool} : + (t.filter fun k _ => f k).keys = t.keys.filter f := + t.inductionOn fun _ => DTreeMap.keys_filter_key + +theorem filter_eq_empty_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + t.filter f = ∅ ↔ ∀ k h, f k (t.get k h) = false := + isEmpty_iff.symm.trans <| t.inductionOn fun _ => DTreeMap.isEmpty_filter_iff + +theorem filter_key_eq_empty_iff [TransCmp cmp] {f : α → Bool} : + t.filter (fun a _ => f a) = ∅ ↔ ∀ k h, f (t.getKey k h) = false := + isEmpty_iff.symm.trans <| t.inductionOn fun _ => DTreeMap.isEmpty_filter_key_iff + +@[grind =] +theorem contains_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).contains k = (t.get? k).any (f k) := + t.inductionOn fun _ => DTreeMap.contains_filter + +@[grind =] +theorem mem_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ h, f k (t.get k h) := by + simp only [mem_iff_contains, contains_filter, Option.any_eq_true_iff_get, + ← contains_eq_isSome_get?, get_get?] + +theorem mem_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} : + k ∈ t.filter (fun a _ => f a) ↔ ∃ h, f (t.getKey k h) := + t.inductionOn fun _ => DTreeMap.mem_filter_key + +theorem contains_of_contains_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).contains k = true → t.contains k = true := + t.inductionOn fun _ => DTreeMap.contains_of_contains_filter + +theorem mem_of_mem_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + k ∈ (t.filter f) → k ∈ t := + t.inductionOn fun _ => DTreeMap.contains_of_contains_filter + +theorem size_filter_le_size [TransCmp cmp] + {f : (a : α) → β a → Bool} : + (t.filter f).size ≤ t.size := + t.inductionOn fun _ => DTreeMap.size_filter_le_size + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + (t.filter f).size = t.size ↔ ∀ k h, f k (t.get k h) := + t.inductionOn fun _ => DTreeMap.size_filter_eq_size_iff + +theorem filter_eq_self_iff [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} : + t.filter f = t ↔ ∀ k h, f k (t.get k h) := + t.inductionOn fun _ => Iff.trans ⟨exact, sound⟩ DTreeMap.filter_equiv_self_iff + +theorem filter_key_equiv_self_iff [TransCmp cmp] + {f : (a : α) → Bool} : + t.filter (fun k _ => f k) = t ↔ ∀ k h, f (t.getKey k h) := + t.inductionOn fun _ => Iff.trans ⟨exact, sound⟩ DTreeMap.filter_key_equiv_self_iff + +theorem size_filter_key_eq_size_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter fun k _ => f k).size = t.size ↔ ∀ (k : α) (h : k ∈ t), f (t.getKey k h) := + t.inductionOn fun _ => DTreeMap.size_filter_key_eq_size_iff + +@[simp, grind =] +theorem get?_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).get? k = (t.get? k).filter (f k) := + t.inductionOn fun _ => DTreeMap.get?_filter + +@[simp, grind =] +theorem get_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {h'} : + (t.filter f).get k h' = t.get k (mem_of_mem_filter h') := + t.inductionOn (fun _ _ => DTreeMap.get_filter) h' + +@[grind =] +theorem get!_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} [Inhabited (β k)] : + (t.filter f).get! k = ((t.get? k).filter (f k)).get! := + t.inductionOn fun _ => DTreeMap.get!_filter + +@[grind =] +theorem getD_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {fallback : β k} : + (t.filter f).getD k fallback = ((t.get? k).filter (f k)).getD fallback := + t.inductionOn fun _ => DTreeMap.getD_filter + +theorem keys_filter [TransCmp cmp] [LawfulEqCmp cmp] {f : (a : α) → β a → Bool} : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (t.get x (mem_of_mem_keys h')))).unattach := + t.inductionOn fun _ => DTreeMap.keys_filter + +@[grind =] +theorem getKey?_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h'))) := + t.inductionOn fun _ => DTreeMap.getKey?_filter + +theorem getKey?_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey? k = (t.getKey? k).filter f := + t.inductionOn fun _ => DTreeMap.getKey?_filter_key + +@[simp, grind =] +theorem getKey_filter [TransCmp cmp] + {f : (a : α) → β a → Bool} {k : α} {h'} : + (t.filter f).getKey k h' = t.getKey k (mem_of_mem_filter h') := + t.inductionOn (fun _ _ => DTreeMap.getKey_filter) h' + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] + {f : (a : α) → β a → Bool} {k : α} : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h')))).get! := + t.inductionOn fun _ => DTreeMap.getKey!_filter + +theorem getKey!_filter_key [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey! k = ((t.getKey? k).filter f).get! := + t.inductionOn fun _ => DTreeMap.getKey!_filter_key + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → Bool} {k fallback : α} : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + f x (t.get x (mem_of_getKey?_eq_some h')))).getD fallback := + t.inductionOn fun _ => DTreeMap.getKeyD_filter + +theorem getKeyD_filter_key [TransCmp cmp] + {f : α → Bool} {k fallback : α} : + (t.filter fun k _ => f k).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := + t.inductionOn fun _ => DTreeMap.getKeyD_filter_key + +namespace Const + +variable {β : Type v} {γ : Type w} {t : ExtDTreeMap α (fun _ => β) cmp} + +theorem filter_eq_empty_iff [TransCmp cmp] {f : α → β → Bool} : + t.filter f = ∅ ↔ ∀ k h, f (t.getKey k h) (Const.get t k h) = false := + isEmpty_iff.symm.trans <| t.inductionOn fun _ => DTreeMap.Const.isEmpty_filter_iff + +-- TODO: `contains_filter` is missing + +@[grind =] +theorem mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ (h' : k ∈ t), + f (t.getKey k h') (Const.get t k h') := + t.inductionOn fun _ => DTreeMap.Const.mem_filter + +theorem size_filter_le_size [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size ≤ t.size := + t.inductionOn fun _ => DTreeMap.Const.size_filter_le_size + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), + f (t.getKey a h) (Const.get t a h) := + t.inductionOn fun _ => DTreeMap.Const.size_filter_eq_size_iff + +theorem filter_eq_self_iff [TransCmp cmp] + {f : α → β → Bool} : + t.filter f = t ↔ ∀ k h, f (t.getKey k h) (Const.get t k h) := + t.inductionOn fun _ => Iff.trans ⟨exact, sound⟩ DTreeMap.Const.filter_equiv_self_iff + +theorem get?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + Const.get? (t.filter f) k = (Const.get? t k).pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x) := + t.inductionOn fun _ => DTreeMap.Const.get?_filter + +/-- Simpler variant of `get?_filter` when `LawfulEqCmp` is available. -/ +@[simp, grind =] +theorem get?_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} : + Const.get? (t.filter f) k = (Const.get? t k).filter (f k) := by + simp [get?_filter] + +theorem get?_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + Const.get? (t.filter f) k = (Const.get? t k).filter (fun x => f k' x) := + t.inductionOn fun _ => DTreeMap.Const.get?_filter_of_getKey?_eq_some + +@[simp, grind =] +theorem get_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} : + Const.get (t.filter f) k h' = Const.get t k (mem_of_mem_filter h') := + t.inductionOn (fun _ _ => DTreeMap.Const.get_filter) h' + +theorem get!_filter [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + Const.get! (t.filter f) k = + ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + t.inductionOn fun _ => DTreeMap.Const.get!_filter + +/-- Simpler variant of `get!_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem get!_filter' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + Const.get! (t.filter f) k = ((Const.get? t k).filter (f k)).get! := by + simp [get!_filter] + +theorem get!_filter_of_getKey?_eq_some [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + Const.get! (t.filter f) k = ((Const.get? t k).filter (fun x => f k' x)).get! := + t.inductionOn fun _ => DTreeMap.Const.get!_filter_of_getKey?_eq_some + +theorem getD_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + Const.getD (t.filter f) k fallback = ((Const.get? t k).pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getD_filter + +/-- Simpler variant of `getD_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + Const.getD (t.filter f) k fallback = ((Const.get? t k).filter (f k)).getD fallback := by + simp [getD_filter] + +theorem getD_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} {fallback : β} : + t.getKey? k = some k' → + Const.getD (t.filter f) k fallback = + ((Const.get? t k).filter (fun x => f k' x)).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getD_filter_of_getKey?_eq_some + +@[simp, grind =] +theorem toList_filter [TransCmp cmp] {f : α → β → Bool} : + toList (t.filter f) = + (toList t).filter (fun p => f p.1 p.2) := + t.inductionOn fun _ => DTreeMap.Const.toList_filter + +theorem keys_filter [TransCmp cmp] {f : α → β → Bool} : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h')))).unattach := + t.inductionOn fun _ => DTreeMap.Const.keys_filter + +@[grind =] +theorem getKey?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h')))) := + t.inductionOn fun _ => DTreeMap.Const.getKey?_filter + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [Inhabited α] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))))).get! := + t.inductionOn fun _ => DTreeMap.Const.getKey!_filter + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] + {f : α → β → Bool} {k fallback : α} : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (Const.get t x (mem_of_getKey?_eq_some h'))))).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getKeyD_filter + +end Const + +end filter + +section map + +variable {γ : α → Type w} {δ : α → Type w'} + +@[simp] +theorem map_id : t.map (fun _ v => v) = t := + t.inductionOn fun _ => sound DTreeMap.map_id_equiv + +@[simp, grind =] +theorem map_map {f : (a : α) → β a → γ a} {g : (a : α) → γ a → δ a} : + (t.map f).map g = t.map fun k v => g k (f k v) := + t.inductionOn fun _ => sound DTreeMap.map_map_equiv + +@[simp, grind =] +theorem toList_map [TransCmp cmp] {f : (a : α) → β a → γ a} : + (t.map f).toList = t.toList.map (fun p => ⟨p.1, f p.1 p.2⟩) := + t.inductionOn fun _ => DTreeMap.toList_map + +@[simp, grind =] +theorem keys_map [TransCmp cmp] {f : (a : α) → β a → γ a} : (t.map f).keys = t.keys := + t.inductionOn fun _ => DTreeMap.keys_map + +theorem filterMap_eq_map [TransCmp cmp] + {f : (a : α) → β a → γ a} : + (t.filterMap (fun k v => some (f k v))) = t.map f := + t.inductionOn fun _ => sound DTreeMap.filterMap_equiv_map + +@[simp] +theorem map_eq_empty_iff [TransCmp cmp] {f : (a : α) → β a → γ a} : + t.map f = ∅ ↔ t = ∅ := by + simp only [← isEmpty_iff, Bool.coe_iff_coe] + exact t.inductionOn fun _ => DTreeMap.isEmpty_map + +@[grind =] +theorem contains_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).contains k = t.contains k := + t.inductionOn fun _ => DTreeMap.contains_map + +theorem contains_of_contains_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).contains k = true → t.contains k = true := + t.inductionOn fun _ => DTreeMap.contains_of_contains_map + +@[simp, grind =] +theorem mem_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + k ∈ t.map f ↔ k ∈ t := by + simp only [mem_iff_contains, contains_map] + +theorem mem_of_mem_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + k ∈ t.map f → k ∈ t := + t.inductionOn fun _ => DTreeMap.contains_of_contains_map + +@[simp, grind =] +theorem size_map [TransCmp cmp] + {f : (a : α) → β a → γ a} : + (t.map f).size = t.size := + t.inductionOn fun _ => DTreeMap.size_map + +@[simp, grind =] +theorem get?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).get? k = (t.get? k).map (f k) := + t.inductionOn fun _ => DTreeMap.get?_map + +@[simp, grind =] +theorem get_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {h'} : + (t.map f).get k h' = f k (t.get k (mem_of_mem_map h')) := + t.inductionOn (fun _ _ => DTreeMap.get_map) h' + +@[grind =] +theorem get!_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} [Inhabited (γ k)] : + (t.map f).get! k = ((t.get? k).map (f k)).get! := + t.inductionOn fun _ => DTreeMap.get!_map + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {fallback : γ k} : + (t.map f).getD k fallback = ((t.get? k).map (f k)).getD fallback := + t.inductionOn fun _ => DTreeMap.getD_map + +@[simp, grind =] +theorem getKey?_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).getKey? k = t.getKey? k := + t.inductionOn fun _ => DTreeMap.getKey?_map + +@[simp, grind =] +theorem getKey_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k : α} {h'} : + (t.map f).getKey k h' = t.getKey k (mem_of_mem_map h') := + t.inductionOn (fun _ _ => DTreeMap.getKey_map) h' + +@[simp, grind =] +theorem getKey!_map [TransCmp cmp] [Inhabited α] + {f : (a : α) → β a → γ a} {k : α} : + (t.map f).getKey! k = t.getKey! k := + t.inductionOn fun _ => DTreeMap.getKey!_map + +@[simp, grind =] +theorem getKeyD_map [TransCmp cmp] + {f : (a : α) → β a → γ a} {k fallback : α} : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := + t.inductionOn fun _ => DTreeMap.getKeyD_map + +namespace Const + +variable {β : Type v} {γ : Type w} {t : ExtDTreeMap α (fun _ => β) cmp} + +@[simp, grind =] +theorem get?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} : + Const.get? (t.map f) k = (Const.get? t k).map (f k) := + t.inductionOn fun _ => DTreeMap.Const.get?_map + +/-- Variant of `get?_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem get?_map' [TransCmp cmp] + {f : α → β → γ} {k : α} : + Const.get? (t.map f) k = (Const.get? t k).pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h')) := + t.inductionOn fun _ => DTreeMap.Const.get?_map' + +theorem get?_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get? (t.map f) k = (Const.get? t k).map (f k') := + t.inductionOn (fun _ => DTreeMap.Const.get?_map_of_getKey?_eq_some) h + +@[simp, grind =] +theorem get_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {h'} : + Const.get (t.map f) k h' = f k (Const.get t k (mem_of_mem_map h')) := + t.inductionOn (fun _ _ => DTreeMap.Const.get_map) h' + +/-- Variant of `get_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem get_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} : + Const.get (t.map f) k h' = + f (t.getKey k (mem_of_mem_map h')) (Const.get t k (mem_of_mem_map h')) := + t.inductionOn (fun _ _ => DTreeMap.Const.get_map') h' + +@[grind =] +theorem get!_map [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + Const.get! (t.map f) k = ((Const.get? t k).map (f k)).get! := + t.inductionOn fun _ => DTreeMap.Const.get!_map + +/-- Variant of `get!_map` that holds without `LawfulEqCmp`. -/ +theorem get!_map' [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + Const.get! (t.map f) k = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_get?.mpr (Option.isSome_of_mem h'))).get! := + t.inductionOn fun _ => DTreeMap.Const.get!_map' + +theorem get!_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + Const.get! (t.map f) k = ((Const.get? t k).map (f k')).get! := + t.inductionOn (fun _ => DTreeMap.Const.get!_map_of_getKey?_eq_some) h + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k)).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getD_map + +/-- Variant of `getD_map` that holds without `LawfulEqCmp`. -/ +theorem getD_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + Const.getD (t.map f) k fallback = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))).getD fallback := + t.inductionOn fun _ => DTreeMap.Const.getD_map' + +theorem getD_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + Const.getD (t.map f) k fallback = ((Const.get? t k).map (f k')).getD fallback := + t.inductionOn (fun _ => DTreeMap.Const.getD_map_of_getKey?_eq_some) h + +@[simp, grind =] +theorem toList_map [TransCmp cmp] {f : α → β → γ} : + Const.toList (t.map f) = + (Const.toList t).map (fun p => (p.1, f p.1 p.2)) := + t.inductionOn fun _ => DTreeMap.Const.toList_map + +end Const + +end map + end Std.ExtDTreeMap diff --git a/src/Std/Data/ExtHashMap/Lemmas.lean b/src/Std/Data/ExtHashMap/Lemmas.lean index 3b550402a6..425176c08c 100644 --- a/src/Std/Data/ExtHashMap/Lemmas.lean +++ b/src/Std/Data/ExtHashMap/Lemmas.lean @@ -1854,7 +1854,7 @@ theorem getElem?_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem?_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem?_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getElem?_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} : (m.filterMap f)[k]? = m[k]?.bind fun x => f k x := by simp [getElem?_filterMap] @@ -1881,7 +1881,7 @@ theorem isSome_apply_of_mem_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getElem_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {h} : (m.filterMap f)[k]'h = (f k (m[k]'(mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by @@ -1992,7 +1992,7 @@ theorem getElem?_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem?_filter` when `LawfulBEq` is available. -/ @[simp, grind =] -theorem getElem?_filter' [LawfulBEq α] [LawfulHashable α] +theorem getElem?_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} : (m.filter f)[k]? = m[k]?.filter (f k) := by simp [getElem?_filter] @@ -2017,7 +2017,7 @@ theorem getElem!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β] /-- Simpler variant of `getElem!_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β] +theorem getElem!_filter' [LawfulBEq α] [Inhabited β] {f : α → β → Bool} {k : α} : (m.filter f)[k]! = (m[k]?.filter (f k)).get! := by simp [getElem!_filter] @@ -2036,7 +2036,7 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filter' [LawfulBEq α] [LawfulHashable α] +theorem getD_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} {fallback : β} : (m.filter f).getD k fallback = (m[k]?.filter (f k)).getD fallback := by simp [getD_filter] @@ -2144,7 +2144,7 @@ theorem size_map [EquivBEq α] [LawfulHashable α] ExtDHashMap.size_map @[simp, grind =] -theorem getElem?_map [LawfulBEq α] [LawfulHashable α] +theorem getElem?_map [LawfulBEq α] {f : α → β → γ} {k : α} : (m.map f)[k]? = m[k]?.map (f k) := ExtDHashMap.Const.get?_map @@ -2163,7 +2163,7 @@ theorem getElem?_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] ExtDHashMap.Const.get?_map_of_getKey?_eq_some h @[simp, grind =] -theorem getElem_map [LawfulBEq α] [LawfulHashable α] +theorem getElem_map [LawfulBEq α] {f : α → β → γ} {k : α} {h'} : (m.map f)[k]' h' = f k (m[k]'(mem_of_mem_map h')) := @@ -2177,7 +2177,7 @@ theorem getElem_map' [EquivBEq α] [LawfulHashable α] f (m.getKey k (mem_of_mem_map h')) (m[k]'(mem_of_mem_map h')) := ExtDHashMap.Const.get_map' (h' := h') -@[grind =] theorem getElem!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +@[grind =] theorem getElem!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} : (m.map f)[k]! = (m[k]?.map (f k)).get! := @@ -2196,7 +2196,7 @@ theorem getElem!_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhab (m.map f)[k]! = (m[k]?.map (f k')).get! := ExtDHashMap.Const.get!_map_of_getKey?_eq_some h -@[grind =] theorem getD_map [LawfulBEq α] [LawfulHashable α] +@[grind =] theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} : (m.map f).getD k fallback = (m[k]?.map (f k)).getD fallback := diff --git a/src/Std/Data/ExtHashSet/Lemmas.lean b/src/Std/Data/ExtHashSet/Lemmas.lean index d233539288..3380676c57 100644 --- a/src/Std/Data/ExtHashSet/Lemmas.lean +++ b/src/Std/Data/ExtHashSet/Lemmas.lean @@ -209,6 +209,10 @@ theorem isSome_get?_iff_mem [EquivBEq α] [LawfulHashable α] {a : α} : (m.get? a).isSome ↔ a ∈ m := mem_iff_isSome_get?.symm +theorem mem_of_get?_eq_some [EquivBEq α] [LawfulHashable α] {k k' : α} + (h : m.get? k = some k') : k' ∈ m := + ExtHashMap.mem_of_getKey?_eq_some h + theorem get?_eq_none_of_contains_eq_false [EquivBEq α] [LawfulHashable α] {a : α} : m.contains a = false → m.get? a = none := ExtHashMap.getKey?_eq_none_of_contains_eq_false diff --git a/src/Std/Data/ExtTreeMap/Lemmas.lean b/src/Std/Data/ExtTreeMap/Lemmas.lean index 644693c6af..94417c619f 100644 --- a/src/Std/Data/ExtTreeMap/Lemmas.lean +++ b/src/Std/Data/ExtTreeMap/Lemmas.lean @@ -24,7 +24,7 @@ universe u v w w' namespace Std.ExtTreeMap -variable {α : Type u} {β : Type v} {γ : Type w} {cmp : α → α → Ordering} {t : ExtTreeMap α β cmp} +variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type w'} {cmp : α → α → Ordering} {t : ExtTreeMap α β cmp} private theorem ext {t t' : ExtTreeMap α β cmp} : t.inner = t'.inner → t = t' := by cases t; cases t'; rintro rfl; rfl @@ -284,6 +284,14 @@ theorem getElem?_eq_some_getElem [TransCmp cmp] {a : α} (h) : t[a]? = some (t[a]'h) := ExtDTreeMap.Const.get?_eq_some_get h +theorem getElem_eq_get_getElem? [TransCmp cmp] {a : α} {h} : + t[a] = t[a]?.get (mem_iff_isSome_getElem?.mp h) := + ExtDTreeMap.Const.get_eq_get_get? (h := h) + +@[grind =] theorem get_getElem? [TransCmp cmp] {a : α} {h} : + t[a]?.get h = t[a]'(mem_iff_isSome_getElem?.mpr h) := + ExtDTreeMap.Const.get_get? + theorem getElem_congr [TransCmp cmp] {a b : α} (hab : cmp a b = .eq) {h'} : t[a]'h' = t[b]'((mem_congr hab).mp h') := ExtDTreeMap.Const.get_congr hab (h' := h') @@ -433,6 +441,10 @@ theorem isSome_getKey?_iff_mem [TransCmp cmp] {a : α} : (t.getKey? a).isSome ↔ a ∈ t := mem_iff_isSome_getKey?.symm +theorem mem_of_getKey?_eq_some [TransCmp cmp] {k k' : α} : + t.getKey? k = some k' → k' ∈ t := + ExtDTreeMap.mem_of_getKey?_eq_some + theorem getKey?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} : t.contains a = false → t.getKey? a = none := ExtDTreeMap.getKey?_eq_none_of_contains_eq_false @@ -486,6 +498,15 @@ theorem getKey?_eq_some_getKey [TransCmp cmp] {a : α} (h') : t.getKey? a = some (t.getKey a h') := ExtDTreeMap.getKey?_eq_some_getKey h' +theorem getKey_eq_get_getKey? [TransCmp cmp] {a : α} {h} : + t.getKey a h = (t.getKey? a).get (mem_iff_isSome_getKey?.mp h) := + ExtDTreeMap.getKey_eq_get_getKey? + +@[simp, grind =] +theorem get_getKey? [TransCmp cmp] {a : α} {h} : + (t.getKey? a).get h = t.getKey a (mem_iff_isSome_getKey?.mpr h) := + ExtDTreeMap.get_getKey? + theorem compare_getKey_self [TransCmp cmp] {k : α} (h' : k ∈ t) : cmp (t.getKey k h') k = .eq := ExtDTreeMap.compare_getKey_self h' @@ -763,6 +784,10 @@ theorem mem_keys [LawfulEqCmp cmp] [TransCmp cmp] {k : α} : k ∈ t.keys ↔ k ∈ t := ExtDTreeMap.mem_keys +theorem mem_of_mem_keys [TransCmp cmp] {k : α} : + k ∈ t.keys → k ∈ t := + ExtDTreeMap.mem_of_mem_keys + theorem distinct_keys [TransCmp cmp] : t.keys.Pairwise (fun a b => ¬ cmp a b = .eq) := ExtDTreeMap.distinct_keys @@ -3020,4 +3045,495 @@ theorem ext_keys_unit [TransCmp cmp] {t₁ t₂ : ExtTreeMap α Unit cmp} (h : t end Ext +section filterMap + +variable {t : ExtTreeMap α β cmp} + +@[simp, grind =] +theorem toList_filterMap [TransCmp cmp] {f : (a : α) → β → Option γ} : + (t.filterMap f).toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => (p.1, x))) := + ExtDTreeMap.Const.toList_filterMap + +theorem filterMap_eq_empty_iff [TransCmp cmp] {f : α → β → Option γ} : + t.filterMap f = ∅ ↔ ∀ k h, f (t.getKey k h) (t[k]'h) = none := + ext_iff.trans ExtDTreeMap.Const.filterMap_eq_empty_iff + +-- TODO: `contains_filterMap` is missing + +@[grind =] +theorem mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + k ∈ t.filterMap f ↔ ∃ h, (f (t.getKey k h) t[k]).isSome := + ExtDTreeMap.Const.mem_filterMap + +theorem contains_of_contains_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).contains k = true → t.contains k = true := + ExtDTreeMap.contains_of_contains_filterMap + +theorem mem_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + k ∈ t.filterMap f → k ∈ t := + ExtDTreeMap.mem_of_mem_filterMap + +theorem size_filterMap_le_size [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).size ≤ t.size := + ExtDTreeMap.size_filterMap_le_size + +grind_pattern size_filterMap_le_size => (t.filterMap f).size + +theorem size_filterMap_eq_size_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).size = t.size ↔ ∀ k h, (f (t.getKey k h) t[k]).isSome := + ExtDTreeMap.Const.size_filterMap_eq_size_iff + +@[simp] +theorem getElem?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]? = t[k]?.pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x) := + ExtDTreeMap.Const.get?_filterMap + +/-- Simpler variant of `getElem?_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem?_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]? = t[k]?.bind fun x => f k x := by + simp [getElem?_filterMap] + +theorem getElem?_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + (t.filterMap f)[k]? = t[k]?.bind (f k') := + ExtDTreeMap.Const.get?_filterMap_of_getKey?_eq_some h + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + ∀ (h : k ∈ t.filterMap f), + (f (t.getKey k (mem_of_mem_filterMap h)) + (t[k]'(mem_of_mem_filterMap h))).isSome := + ExtDTreeMap.Const.isSome_apply_of_mem_filterMap + +@[simp] +theorem getElem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + (t.filterMap f)[k]'h = + (f (t.getKey k (mem_of_mem_filterMap h)) + (t[k]'(mem_of_mem_filterMap h))).get + (isSome_apply_of_mem_filterMap h) := + ExtDTreeMap.Const.get_filterMap (h := h) + +/-- Simpler variant of `getElem_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + (t.filterMap f)[k]'h = + (f k (t[k]'(mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by + simp [getElem_filterMap] + +theorem getElem!_filterMap [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]! = + (t[k]?.pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + ExtDTreeMap.Const.get!_filterMap + +/-- Simpler variant of `getElem!_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem!_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]! = (t[k]?.bind (f k)).get! := by + simp [getElem!_filterMap] + +theorem getElem!_filterMap_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + (t.filterMap f)[k]! = (t[k]?.bind (f k')).get! := + ExtDTreeMap.Const.get!_filterMap_of_getKey?_eq_some h + +theorem getD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + (t.filterMap f).getD k fallback = + (t[k]?.pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + ExtDTreeMap.Const.getD_filterMap + +/-- Simpler variant of `getD_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + (t.filterMap f).getD k fallback = (t[k]?.bind (f k)).getD fallback := by + simp [getD_filterMap] + +theorem getD_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + (t.filterMap f).getD k fallback = (t[k]?.bind (f k')).getD fallback := + ExtDTreeMap.Const.getD_filterMap_of_getKey?_eq_some h + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))).isSome) := + ExtDTreeMap.Const.getKey?_filterMap + +@[simp, grind =] +theorem getKey_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h'} : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h') := + ExtDTreeMap.getKey_filterMap + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [Inhabited α] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))).isSome)).get! := + ExtDTreeMap.Const.getKey!_filterMap + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k fallback : α} : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))).isSome)).getD fallback := + ExtDTreeMap.Const.getKeyD_filterMap + +end filterMap + +section filter + +variable {t : ExtTreeMap α β cmp} + +theorem filterMap_equiv_filter {f : α → β → Bool} : + t.filterMap (fun k => Option.guard (fun v => f k v)) = t.filter f := + ext ExtDTreeMap.filterMap_eq_filter + +@[simp, grind =] +theorem toList_filter [TransCmp cmp] {f : α → β → Bool} : + (t.filter f).toList = t.toList.filter (fun p => f p.1 p.2) := + ExtDTreeMap.Const.toList_filter + +theorem keys_filter_key [TransCmp cmp] {f : α → Bool} : + (t.filter fun k _ => f k).keys = t.keys.filter f := + ExtDTreeMap.keys_filter_key + +theorem filter_eq_empty_iff [TransCmp cmp] {f : α → β → Bool} : + t.filter f = ∅ ↔ ∀ k h, f (t.getKey k h) (t[k]'h) = false := + ext_iff.trans ExtDTreeMap.Const.filter_eq_empty_iff + +-- TODO: `contains_filter` is missing + +@[grind =] +theorem mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ (h' : k ∈ t), f (t.getKey k h') t[k] := + ExtDTreeMap.Const.mem_filter + +theorem contains_of_contains_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f).contains k = true → t.contains k = true := + ExtDTreeMap.contains_of_contains_filter + +theorem mem_of_mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + k ∈ t.filter f → k ∈ t := + ExtDTreeMap.mem_of_mem_filter + +theorem size_filter_le_size [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size ≤ t.size := + ExtDTreeMap.size_filter_le_size + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size = t.size ↔ ∀ k h, f (t.getKey k h) (t.get k h) := + ExtDTreeMap.Const.size_filter_eq_size_iff + +theorem filter_eq_self_iff [TransCmp cmp] + {f : α → β → Bool} : + t.filter f = t ↔ ∀ k h, f (t.getKey k h) (t.get k h) := + ext_iff.trans ExtDTreeMap.Const.filter_eq_self_iff + +@[simp] +theorem getElem?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]? = t[k]?.pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x) := + ExtDTreeMap.Const.get?_filter + +/-- Simpler variant of `getElem?_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem?_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]? = t[k]?.filter (f k) := by + simp [getElem?_filter] + +theorem getElem?_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + (t.filter f)[k]? = t[k]?.filter (fun x => f k' x) := + ExtDTreeMap.Const.get?_filter_of_getKey?_eq_some + +@[simp, grind =] +theorem getElem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} : + (t.filter f)[k]'(h') = t[k]'(mem_of_mem_filter h') := + ExtDTreeMap.Const.get_filter (h' := h') + +theorem getElem!_filter [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]! = + (t[k]?.pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + ExtDTreeMap.Const.get!_filter + +/-- Simpler variant of `getElem!_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem!_filter' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]! = (t[k]?.filter (f k)).get! := by + simp [getElem!_filter] + +theorem getElem!_filter_of_getKey?_eq_some [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + (t.filter f)[k]! = (t[k]?.filter (f k')).get! := + ExtDTreeMap.Const.get!_filter_of_getKey?_eq_some + +theorem getD_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + (t.filter f).getD k fallback = (t[k]?.pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + ExtDTreeMap.Const.getD_filter + +/-- Simpler variant of `getD_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + (t.filter f).getD k fallback = (t[k]?.filter (f k)).getD fallback := by + simp [getD_filter] + +theorem getD_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} {fallback : β} : + t.getKey? k = some k' → + (t.filter f).getD k fallback = + (t[k]?.filter (fun x => f k' x)).getD fallback := + ExtDTreeMap.Const.getD_filter_of_getKey?_eq_some + +theorem keys_filter [TransCmp cmp] {f : α → β → Bool} : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h')))).unattach := + ExtDTreeMap.Const.keys_filter + +@[grind =] +theorem getKey?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h')))) := + ExtDTreeMap.Const.getKey?_filter + +theorem getKey?_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey? k = (t.getKey? k).filter f := + ExtDTreeMap.getKey?_filter_key + +@[simp, grind =] +theorem getKey_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} : + (t.filter f).getKey k h' = t.getKey k (mem_of_mem_filter h') := + ExtDTreeMap.getKey_filter + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [Inhabited α] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))))).get! := + ExtDTreeMap.Const.getKey!_filter + +theorem getKey!_filter_key [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey! k = ((t.getKey? k).filter f).get! := + ExtDTreeMap.getKey!_filter_key + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] + {f : α → β → Bool} {k fallback : α} : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))))).getD fallback := + ExtDTreeMap.Const.getKeyD_filter + +theorem getKeyD_filter_key [TransCmp cmp] + {f : α → Bool} {k fallback : α} : + (t.filter fun k _ => f k).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := + ExtDTreeMap.getKeyD_filter_key + +end filter + +section map + +variable {t : ExtTreeMap α β cmp} + +@[simp] +theorem map_id : t.map (fun _ v => v) = t := + ext ExtDTreeMap.map_id + +@[simp, grind =] +theorem map_map {f : α → β → γ} {g : α → γ → δ} : + (t.map f).map g = t.map fun k v => g k (f k v) := + ext ExtDTreeMap.map_map + +@[simp, grind =] +theorem toList_map [TransCmp cmp] {f : α → β → γ} : + (t.map f).toList = t.toList.map (fun p => (p.1, f p.1 p.2)) := + ExtDTreeMap.Const.toList_map + +@[simp, grind =] +theorem keys_map [TransCmp cmp] {f : α → β → γ} : (t.map f).keys = t.keys := + ExtDTreeMap.keys_map + +theorem filterMap_eq_map [TransCmp cmp] + {f : α → β → γ} : + t.filterMap (fun k v => some (f k v)) = t.map f := + ext ExtDTreeMap.filterMap_eq_map + +@[simp] +theorem map_eq_empty_iff [TransCmp cmp] {f : α → β → γ} : + t.map f = ∅ ↔ t = ∅ := by + simpa only [ext_iff] using ExtDTreeMap.map_eq_empty_iff + +@[simp, grind =] +theorem contains_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f).contains k = t.contains k := + ExtDTreeMap.contains_map + +theorem contains_of_contains_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f).contains k = true → t.contains k = true := + ExtDTreeMap.contains_of_contains_map + +@[simp, grind =] +theorem mem_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + k ∈ t.map f ↔ k ∈ t := by + simp only [mem_iff_contains, contains_map] + +theorem mem_of_mem_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + k ∈ t.map f → k ∈ t := + ExtDTreeMap.contains_of_contains_map + +@[simp, grind =] +theorem size_map [TransCmp cmp] + {f : α → β → γ} : + (t.map f).size = t.size := + ExtDTreeMap.size_map + +@[simp, grind =] +theorem getElem?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f)[k]? = t[k]?.map (f k) := + ExtDTreeMap.Const.get?_map + +/-- Variant of `getElem?_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem getElem?_map' [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f)[k]? = t[k]?.pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h')) := + ExtDTreeMap.Const.get?_map' + +theorem getElem?_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + (t.map f)[k]? = t[k]?.map (f k') := + ExtDTreeMap.Const.get?_map_of_getKey?_eq_some h + +@[simp, grind =] +theorem getElem_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {h'} : + (t.map f)[k]'(h') = + f k (t[k]'(mem_of_mem_map h')) := + ExtDTreeMap.Const.get_map (h' := h') + +/-- Variant of `getElem_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem getElem_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} : + (t.map f)[k]'(h') = + f (t.getKey k (mem_of_mem_map h')) (t[k]'(mem_of_mem_map h')) := + ExtDTreeMap.Const.get_map' (h' := h') + +@[grind =] +theorem getElem!_map [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + (t.map f)[k]! = + (t[k]?.map (f k)).get! := + ExtDTreeMap.Const.get!_map + +/-- Variant of `getElem!_map` that holds without `LawfulEqCmp`. -/ +theorem getElem!_map' [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + (t.map f)[k]! = + (t[k]?.pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_getElem?.mpr (Option.isSome_of_mem h'))).get! := + ExtDTreeMap.Const.get!_map' + +theorem getElem!_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + (t.map f)[k]! = (t[k]?.map (f k')).get! := + ExtDTreeMap.Const.get!_map_of_getKey?_eq_some h + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + (t.map f).getD k fallback = + (t[k]?.map (f k)).getD fallback := + ExtDTreeMap.Const.getD_map + +/-- Variant of `getD_map` that holds without `LawfulEqCmp`. -/ +theorem getD_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + (t.map f).getD k fallback = + (t[k]?.pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))).getD fallback := + ExtDTreeMap.Const.getD_map' + +theorem getD_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + (t.map f).getD k fallback = (t[k]?.map (f k')).getD fallback := + ExtDTreeMap.Const.getD_map_of_getKey?_eq_some h + +@[simp, grind =] +theorem getKey?_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f).getKey? k = t.getKey? k := + ExtDTreeMap.getKey?_map + +@[simp, grind =] +theorem getKey_map [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} : + (t.map f).getKey k h' = t.getKey k (mem_of_mem_map h') := + ExtDTreeMap.getKey_map + +@[simp, grind =] +theorem getKey!_map [TransCmp cmp] [Inhabited α] + {f : α → β → γ} {k : α} : + (t.map f).getKey! k = t.getKey! k := + ExtDTreeMap.getKey!_map + +@[simp, grind =] +theorem getKeyD_map [TransCmp cmp] + {f : α → β → γ} {k fallback : α} : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := + ExtDTreeMap.getKeyD_map + +end map + end Std.ExtTreeMap diff --git a/src/Std/Data/ExtTreeSet/Lemmas.lean b/src/Std/Data/ExtTreeSet/Lemmas.lean index c960edd7eb..78c506165d 100644 --- a/src/Std/Data/ExtTreeSet/Lemmas.lean +++ b/src/Std/Data/ExtTreeSet/Lemmas.lean @@ -221,6 +221,10 @@ theorem isSome_get?_iff_mem [TransCmp cmp] {a : α} : (t.get? a).isSome ↔ a ∈ t := mem_iff_isSome_get?.symm +theorem mem_of_get?_eq_some [TransCmp cmp] {k k' : α} + (h : t.get? k = some k') : k' ∈ t := + ExtTreeMap.mem_of_getKey?_eq_some h + theorem get?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} : t.contains a = false → t.get? a = none := ExtTreeMap.getKey?_eq_none_of_contains_eq_false @@ -268,6 +272,14 @@ theorem get?_eq_some_get [TransCmp cmp] {a : α} (h') : t.get? a = some (t.get a h') := ExtTreeMap.getKey?_eq_some_getKey h' +theorem get_eq_get_get? [TransCmp cmp] {k : α} {h} : + t.get k h = (t.get? k).get (mem_iff_isSome_get?.mp h) := + ExtTreeMap.getKey_eq_get_getKey? + +@[grind =] theorem get_get? [TransCmp cmp] {k : α} {h} : + (t.get? k).get h = t.get k (mem_iff_isSome_get?.mpr h) := + ExtTreeMap.get_getKey? + theorem compare_get_self [TransCmp cmp] {k : α} (h' : k ∈ t) : cmp (t.get k h') k = .eq := ExtTreeMap.compare_getKey_self h' @@ -1540,4 +1552,77 @@ theorem toList_inj [TransCmp cmp] : t₁.toList = t₂.toList ↔ t₁ = t₂ := end Ext +section filter + +variable {t : ExtTreeSet α cmp} + +theorem toList_filter [TransCmp cmp] {f : α → Bool} : + (t.filter f).toList = t.toList.filter f := + ExtTreeMap.keys_filter_key + +theorem filter_eq_empty_iff [TransCmp cmp] {f : α → Bool} : + t.filter f = ∅ ↔ ∀ k h, f (t.get k h) = false := + ext_iff.trans ExtTreeMap.filter_eq_empty_iff + +-- TODO: `contains_filter` is missing. + +@[simp, grind =] +theorem mem_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ h, f (t.get k h) := + ExtTreeMap.mem_filter + +theorem contains_of_contains_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter f).contains k → t.contains k := + ExtTreeMap.contains_of_contains_filter + +theorem mem_of_mem_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + k ∈ t.filter f → k ∈ t := + ExtTreeMap.mem_of_mem_filter + +theorem size_filter_le_size [TransCmp cmp] + {f : α → Bool} : + (t.filter f).size ≤ t.size := + ExtTreeMap.size_filter_le_size + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter f).size = t.size ↔ ∀ k h, f (t.get k h) := + ExtTreeMap.size_filter_eq_size_iff + +theorem filter_eq_self_iff [TransCmp cmp] + {f : α → Bool} : + t.filter f = t ↔ ∀ k h, f (t.get k h) := + ext_iff.trans ExtTreeMap.filter_eq_self_iff + +@[simp, grind =] +theorem get?_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter f).get? k = (t.get? k).filter f := + ExtTreeMap.getKey?_filter_key + +@[simp, grind =] +theorem get_filter [TransCmp cmp] + {f : α → Bool} {k : α} {h} : + (t.filter f).get k h = t.get k (mem_of_mem_filter h) := + ExtTreeMap.getKey_filter + +@[grind =] +theorem get!_filter [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} : + (t.filter f).get! k = ((t.get? k).filter f).get! := + ExtTreeMap.getKey!_filter_key + +@[grind =] +theorem getD_filter [TransCmp cmp] + {f : α → Bool} {k fallback : α} : + (t.filter f).getD k fallback = ((t.get? k).filter f).getD fallback := + ExtTreeMap.getKeyD_filter_key + +end filter + end Std.ExtTreeSet diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 69901c39e7..5f87480b48 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -848,7 +848,7 @@ theorem contains_keys [EquivBEq α] [LawfulHashable α] {k : α} : DHashMap.contains_keys @[simp, grind =] -theorem mem_keys [LawfulBEq α] [LawfulHashable α] {k : α} : +theorem mem_keys [LawfulBEq α] {k : α} : k ∈ m.keys ↔ k ∈ m := DHashMap.mem_keys @@ -2430,7 +2430,7 @@ theorem getElem?_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem?_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem?_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getElem?_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} : (m.filterMap f)[k]? = m[k]?.bind fun x => f k x := by simp [getElem?_filterMap] @@ -2458,7 +2458,7 @@ theorem getElem_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getElem_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {h} : (m.filterMap f)[k]'h = (f k (m[k]'(mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by @@ -2473,7 +2473,7 @@ theorem getElem!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ] /-- Simpler variant of `getElem!_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem getElem!_filterMap' [LawfulBEq α] [Inhabited γ] {f : α → β → Option γ} {k : α} : (m.filterMap f)[k]! = (m[k]?.bind (f k)).get! := by simp [getElem!_filterMap] @@ -2492,7 +2492,7 @@ theorem getD_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getD_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {fallback : γ} : (m.filterMap f).getD k fallback = (m[k]?.bind (f k)).getD fallback := by simp [getD_filterMap] @@ -2608,7 +2608,7 @@ theorem getElem?_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem?_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem?_filter' [LawfulBEq α] [LawfulHashable α] +theorem getElem?_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} : (m.filter f)[k]? = m[k]?.filter (f k) := by simp [getElem?_filter] @@ -2634,7 +2634,7 @@ theorem getElem!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β] /-- Simpler variant of `getElem!_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β] +theorem getElem!_filter' [LawfulBEq α] [Inhabited β] {f : α → β → Bool} {k : α} : (m.filter f)[k]! = (m[k]?.filter (f k)).get! := by simp [getElem!_filter] @@ -2653,7 +2653,7 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filter' [LawfulBEq α] [LawfulHashable α] +theorem getD_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} {fallback : β} : (m.filter f).getD k fallback = (m[k]?.filter (f k)).getD fallback := by simp [getD_filter] @@ -2775,7 +2775,7 @@ theorem size_map [EquivBEq α] [LawfulHashable α] DHashMap.size_map @[simp, grind =] -theorem getElem?_map [LawfulBEq α] [LawfulHashable α] +theorem getElem?_map [LawfulBEq α] {f : α → β → γ} {k : α} : (m.map f)[k]? = m[k]?.map (f k) := DHashMap.Const.get?_map @@ -2794,7 +2794,7 @@ theorem getElem?_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] DHashMap.Const.get?_map_of_getKey?_eq_some h @[simp, grind =] -theorem getElem_map [LawfulBEq α] [LawfulHashable α] +theorem getElem_map [LawfulBEq α] {f : α → β → γ} {k : α} {h'} : (m.map f)[k]'(h') = f k (m[k]'(mem_of_mem_map h')) := @@ -2809,7 +2809,7 @@ theorem getElem_map' [EquivBEq α] [LawfulHashable α] DHashMap.Const.get_map' @[grind =] -theorem getElem!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem getElem!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} : (m.map f)[k]! = (m[k]?.map (f k)).get! := @@ -2829,7 +2829,7 @@ theorem getElem!_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhab DHashMap.Const.get!_map_of_getKey?_eq_some h @[grind =] -theorem getD_map [LawfulBEq α] [LawfulHashable α] +theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} : (m.map f).getD k fallback = (m[k]?.map (f k)).getD fallback := diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 3705b99a75..7a3bf3a411 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -2451,7 +2451,7 @@ theorem getElem?_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem?_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem?_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getElem?_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} (h : m.WF) : (m.filterMap f)[k]? = m[k]?.bind fun x => f k x := by simp [getElem?_filterMap, h] @@ -2480,7 +2480,7 @@ theorem getElem_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getElem_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {g} (h : m.WF) : (m.filterMap f)[k]'g = (f k (m[k]'(mem_of_mem_filterMap h g))).get (by simpa [h] using isSome_apply_of_mem_filterMap h g) := by @@ -2496,7 +2496,7 @@ theorem getElem!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ] /-- Simpler variant of `getElem!_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem getElem!_filterMap' [LawfulBEq α] [Inhabited γ] {f : α → β → Option γ} {k : α} (h : m.WF) : (m.filterMap f)[k]! = (m[k]?.bind (f k)).get! := by simp [getElem!_filterMap, h] @@ -2516,7 +2516,7 @@ theorem getD_filterMap [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α] +theorem getD_filterMap' [LawfulBEq α] {f : α → β → Option γ} {k : α} {fallback : γ} (h : m.WF) : getD (m.filterMap f) k fallback = (m[k]?.bind (f k)).getD fallback := by simp [getD_filterMap, h] @@ -2630,7 +2630,7 @@ theorem getElem?_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getElem?_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem?_filter' [LawfulBEq α] [LawfulHashable α] +theorem getElem?_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} (h : m.WF) : (m.filter f)[k]? = m[k]?.filter (f k) := by simp [getElem?_filter, h] @@ -2656,7 +2656,7 @@ theorem getElem!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β] /-- Simpler variant of `getElem!_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getElem!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β] +theorem getElem!_filter' [LawfulBEq α] [Inhabited β] {f : α → β → Bool} {k : α} (h : m.WF) : (m.filter f)[k]! = (m[k]?.filter (f k)).get! := by simp [getElem!_filter, h] @@ -2675,7 +2675,7 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] /-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/ @[grind =] -theorem getD_filter' [LawfulBEq α] [LawfulHashable α] +theorem getD_filter' [LawfulBEq α] {f : α → β → Bool} {k : α} {fallback : β} (h : m.WF) : getD (m.filter f) k fallback = (m[k]?.filter (f k)).getD fallback := by simp [getD_filter, h] @@ -2819,7 +2819,7 @@ theorem getKeyD_map [EquivBEq α] [LawfulHashable α] DHashMap.Raw.getKeyD_map h.out @[simp, grind =] -theorem getElem?_map [LawfulBEq α] [LawfulHashable α] +theorem getElem?_map [LawfulBEq α] {f : α → β → γ} {k : α} (h : m.WF) : (m.map f)[k]? = m[k]?.map (f k) := DHashMap.Raw.Const.get?_map h.out @@ -2838,7 +2838,7 @@ theorem getElem?_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] DHashMap.Raw.Const.get?_map_of_getKey?_eq_some h.out h' @[simp, grind =] -theorem getElem_map [LawfulBEq α] [LawfulHashable α] +theorem getElem_map [LawfulBEq α] {f : α → β → γ} {k : α} {h'} (h : m.WF) : (m.map f)[k]' h' = (f k (m[k]' (mem_of_mem_map h h'))) := @@ -2854,7 +2854,7 @@ theorem getElem_map' [EquivBEq α] [LawfulHashable α] DHashMap.Raw.Const.get_map' h.out (h':= h') @[grind =] -theorem getElem!_map [LawfulBEq α] [LawfulHashable α] [Inhabited γ] +theorem getElem!_map [LawfulBEq α] [Inhabited γ] {f : α → β → γ} {k : α} (h : m.WF) : (m.map f)[k]! = (m[k]?.map (f k)).get! := @@ -2874,7 +2874,7 @@ theorem getElem!_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhab DHashMap.Raw.Const.get!_map_of_getKey?_eq_some h.out h' @[grind =] -theorem getD_map [LawfulBEq α] [LawfulHashable α] +theorem getD_map [LawfulBEq α] {f : α → β → γ} {k : α} {fallback : γ} (h : m.WF) : (m.map f).getD k fallback = (m[k]?.map (f k)).getD fallback := diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index 20c6560adf..7d863df44b 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -257,6 +257,10 @@ theorem isSome_get?_iff_mem [EquivBEq α] [LawfulHashable α] {a : α} : (m.get? a).isSome ↔ a ∈ m := mem_iff_isSome_get?.symm +theorem mem_of_get?_eq_some [EquivBEq α] [LawfulHashable α] {k k' : α} + (h : m.get? k = some k') : k' ∈ m := + HashMap.mem_of_getKey?_eq_some h + theorem get?_eq_none_of_contains_eq_false [EquivBEq α] [LawfulHashable α] {a : α} : m.contains a = false → m.get? a = none := HashMap.getKey?_eq_none_of_contains_eq_false @@ -474,11 +478,15 @@ theorem contains_toList [EquivBEq α] [LawfulHashable α] {k : α} : HashMap.contains_keys @[simp, grind =] -theorem mem_toList [LawfulBEq α] [LawfulHashable α] {k : α} : +theorem mem_toList [LawfulBEq α] {k : α} : k ∈ m.toList ↔ k ∈ m := HashMap.mem_keys -theorem distinct_toList [EquivBEq α] [LawfulHashable α]: +theorem mem_of_mem_toList [EquivBEq α] [LawfulHashable α] {k : α} : + k ∈ m.toList → k ∈ m := + HashMap.mem_of_mem_keys + +theorem distinct_toList [EquivBEq α] [LawfulHashable α] : m.toList.Pairwise (fun a b => (a == b) = false) := HashMap.distinct_keys diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index ef9de07580..60e891885d 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -269,6 +269,10 @@ theorem isSome_get?_iff_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) {a : α (m.get? a).isSome ↔ a ∈ m := (mem_iff_isSome_get? h).symm +theorem mem_of_get?_eq_some [EquivBEq α] [LawfulHashable α] (h : m.WF) {a a' : α} : + m.get? a = some a' → a' ∈ m := + HashMap.Raw.mem_of_getKey?_eq_some h.out + theorem get?_eq_none_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) {a : α} : m.contains a = false → m.get? a = none := HashMap.Raw.getKey?_eq_none_of_contains_eq_false h.out @@ -498,10 +502,14 @@ theorem contains_toList [EquivBEq α] [LawfulHashable α] {k : α} (h : m.WF) : HashMap.Raw.contains_keys h.1 @[simp, grind =] -theorem mem_toList [LawfulBEq α] [LawfulHashable α] (h : m.WF) {k : α} : +theorem mem_toList [LawfulBEq α] (h : m.WF) {k : α} : k ∈ m.toList ↔ k ∈ m := HashMap.Raw.mem_keys h.1 +theorem mem_of_mem_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) {k : α} : + k ∈ m.toList → k ∈ m := + HashMap.Raw.mem_of_mem_keys h.1 + theorem distinct_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.toList.Pairwise (fun a b => (a == b) = false) := HashMap.Raw.distinct_keys h.1 diff --git a/src/Std/Data/TreeMap/Lemmas.lean b/src/Std/Data/TreeMap/Lemmas.lean index e2c582ad95..6f05f7c1a7 100644 --- a/src/Std/Data/TreeMap/Lemmas.lean +++ b/src/Std/Data/TreeMap/Lemmas.lean @@ -26,7 +26,7 @@ universe u v w w' namespace Std.TreeMap -variable {α : Type u} {β : Type v} {γ : Type w} {cmp : α → α → Ordering} {t : TreeMap α β cmp} +variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type w} {cmp : α → α → Ordering} {t : TreeMap α β cmp} private theorem ext {t t' : TreeMap α β cmp} : t.inner = t'.inner → t = t' := by cases t; cases t'; rintro rfl; rfl @@ -255,6 +255,10 @@ theorem isSome_getElem?_iff_mem [TransCmp cmp] {a : α} : t[a]?.isSome ↔ a ∈ t := mem_iff_isSome_getElem?.symm +theorem mem_of_getKey?_eq_some [TransCmp cmp] {k k' : α} + (h : t.getKey? k = some k') : k' ∈ t := + DTreeMap.mem_of_getKey?_eq_some h + theorem getElem?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} : t.contains a = false → t[a]? = none := DTreeMap.Const.get?_eq_none_of_contains_eq_false @@ -292,9 +296,17 @@ theorem getElem_erase [TransCmp cmp] {k a : α} {h'} : (t.erase k)[a]'h' = t[a]'(mem_of_mem_erase h') := DTreeMap.Const.get_erase -theorem getElem?_eq_some_getElem [TransCmp cmp] {a : α} {h} : +theorem getElem?_eq_some_getElem [TransCmp cmp] {a : α} (h) : t[a]? = some (t[a]'h) := - DTreeMap.Const.get?_eq_some_get + DTreeMap.Const.get?_eq_some_get h + +theorem getElem_eq_get_getElem? [TransCmp cmp] {a : α} {h} : + t[a] = t[a]?.get (mem_iff_isSome_getElem?.mp h) := + DTreeMap.Const.get_eq_get_get? + +@[grind =] theorem get_getElem? [TransCmp cmp] {a : α} {h} : + t[a]?.get h = t[a]'(mem_iff_isSome_getElem?.mpr h) := + DTreeMap.Const.get_get? theorem getElem_congr [TransCmp cmp] {a b : α} (hab : cmp a b = .eq) {h'} : t[a]'h' = t[b]'((mem_congr hab).mp h') := @@ -506,9 +518,18 @@ theorem getKey_erase [TransCmp cmp] {k a : α} {h'} : (t.erase k).getKey a h' = t.getKey a (mem_of_mem_erase h') := DTreeMap.getKey_erase -theorem getKey?_eq_some_getKey [TransCmp cmp] {a : α} {h'} : +theorem getKey?_eq_some_getKey [TransCmp cmp] {a : α} (h') : t.getKey? a = some (t.getKey a h') := - DTreeMap.getKey?_eq_some_getKey + DTreeMap.getKey?_eq_some_getKey h' + +theorem getKey_eq_get_getKey? [TransCmp cmp] {a : α} {h} : + t.getKey a h = (t.getKey? a).get (mem_iff_isSome_getKey?.mp h) := + DTreeMap.getKey_eq_get_getKey? + +@[simp, grind =] +theorem get_getKey? [TransCmp cmp] {a : α} {h} : + (t.getKey? a).get h = t.getKey a (mem_iff_isSome_getKey?.mpr h) := + DTreeMap.get_getKey? theorem compare_getKey_self [TransCmp cmp] {k : α} (h' : k ∈ t) : cmp (t.getKey k h') k = .eq := @@ -762,7 +783,7 @@ theorem getThenInsertIfNew?_snd [TransCmp cmp] {k : α} {v : β} : instance [TransCmp cmp] : LawfulGetElem (TreeMap α β cmp) α β (fun m a => a ∈ m) where getElem?_def m a _ := by split - · exact getElem?_eq_some_getElem + · exact getElem?_eq_some_getElem _ · exact getElem?_eq_none ‹_› getElem!_def m a := by rw [getElem!_eq_get!_getElem?] @@ -792,6 +813,9 @@ theorem mem_keys [LawfulEqCmp cmp] [TransCmp cmp] {k : α} : k ∈ t.keys ↔ k ∈ t := DTreeMap.mem_keys +theorem mem_of_mem_keys [TransCmp cmp] {k : α} (h : k ∈ t.keys) : k ∈ t := + DTreeMap.mem_of_mem_keys h + theorem distinct_keys [TransCmp cmp] : t.keys.Pairwise (fun a b => ¬ cmp a b = .eq) := DTreeMap.distinct_keys @@ -3444,4 +3468,511 @@ theorem Equiv.of_keys_unit_perm {t₁ t₂ : TreeMap α Unit cmp} : t₁.keys.Pe end Equiv +section filterMap + +variable {t : TreeMap α β cmp} + +@[simp, grind =] +theorem toList_filterMap {f : (a : α) → β → Option γ} : + (t.filterMap f).toList = + t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => (p.1, x))) := + DTreeMap.Const.toList_filterMap + +@[grind =] +theorem isEmpty_filterMap_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).isEmpty ↔ ∀ k h, f (t.getKey k h) t[k] = none := + DTreeMap.Const.isEmpty_filterMap_iff + +theorem isEmpty_filterMap_eq_false_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).isEmpty = false ↔ ∃ k h, (f (t.getKey k h) t[k]).isSome := + DTreeMap.Const.isEmpty_filterMap_eq_false_iff + +-- TODO: `contains_filterMap` is missing + +@[grind =] +theorem mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + k ∈ t.filterMap f ↔ ∃ h, (f (t.getKey k h) t[k]).isSome := + DTreeMap.Const.mem_filterMap + +theorem contains_of_contains_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).contains k = true → t.contains k = true := + DTreeMap.contains_of_contains_filterMap + +theorem mem_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + k ∈ t.filterMap f → k ∈ t := + DTreeMap.mem_of_mem_filterMap + +theorem size_filterMap_le_size [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).size ≤ t.size := + DTreeMap.size_filterMap_le_size + +grind_pattern size_filterMap_le_size => (t.filterMap f).size + +theorem size_filterMap_eq_size_iff [TransCmp cmp] + {f : α → β → Option γ} : + (t.filterMap f).size = t.size ↔ ∀ k h, (f (t.getKey k h) t[k]).isSome := + DTreeMap.Const.size_filterMap_eq_size_iff + +@[simp] +theorem getElem?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]? = t[k]?.pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x) := + DTreeMap.Const.get?_filterMap + +/-- Simpler variant of `getElem?_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem?_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]? = t[k]?.bind fun x => f k x := by + simp [getElem?_filterMap] + +theorem getElem?_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + (t.filterMap f)[k]? = t[k]?.bind (f k') := + DTreeMap.Const.get?_filterMap_of_getKey?_eq_some h + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + ∀ (h : k ∈ t.filterMap f), + (f (t.getKey k (mem_of_mem_filterMap h)) + (t[k]'(mem_of_mem_filterMap h))).isSome := + DTreeMap.Const.isSome_apply_of_mem_filterMap + +@[simp] +theorem getElem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + (t.filterMap f)[k]'h = + (f (t.getKey k (mem_of_mem_filterMap h)) + (t[k]'(mem_of_mem_filterMap h))).get + (isSome_apply_of_mem_filterMap h) := + DTreeMap.Const.get_filterMap + +/-- Simpler variant of `getElem_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {h} : + (t.filterMap f)[k]'h = + (f k (t[k]'(mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by + simp [getElem_filterMap] + +theorem getElem!_filterMap [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]! = + (t[k]?.pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + DTreeMap.Const.get!_filterMap + +/-- Simpler variant of `getElem!_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem!_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} : + (t.filterMap f)[k]! = (t[k]?.bind (f k)).get! := by + simp [getElem!_filterMap] + +theorem getElem!_filterMap_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.getKey? k = some k') : + (t.filterMap f)[k]! = (t[k]?.bind (f k')).get! := + DTreeMap.Const.get!_filterMap_of_getKey?_eq_some h + +theorem getD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + (t.filterMap f).getD k fallback = + (t[k]?.pbind (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + DTreeMap.Const.getD_filterMap + +/-- Simpler variant of `getD_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} : + (t.filterMap f).getD k fallback = (t[k]?.bind (f k)).getD fallback := by + simp [getD_filterMap] + +theorem getD_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + (t.filterMap f).getD k fallback = (t[k]?.bind (f k')).getD fallback := + DTreeMap.Const.getD_filterMap_of_getKey?_eq_some h + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))).isSome) := + DTreeMap.Const.getKey?_filterMap + +@[simp, grind =] +theorem getKey_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {h'} : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h') := + DTreeMap.getKey_filterMap + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [Inhabited α] + {f : α → β → Option γ} {k : α} : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))).isSome)).get! := + DTreeMap.Const.getKey!_filterMap + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k fallback : α} : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))).isSome)).getD fallback := + DTreeMap.Const.getKeyD_filterMap + +end filterMap + +section filter + +variable {t : TreeMap α β cmp} + +theorem filterMap_equiv_filter {f : α → β → Bool} : + (t.filterMap (fun k => Option.guard (fun v => f k v))) ~m t.filter f := + ⟨DTreeMap.filterMap_equiv_filter⟩ + +@[simp, grind =] +theorem toList_filter {f : α → β → Bool} : + (t.filter f).toList = t.toList.filter (fun p => f p.1 p.2) := + DTreeMap.Const.toList_filter + +theorem keys_filter_key {f : α → Bool} : + (t.filter fun k _ => f k).keys = t.keys.filter f := + DTreeMap.keys_filter_key + +@[grind =] +theorem isEmpty_filter_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) t[k] = false := + DTreeMap.Const.isEmpty_filter_iff + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f (t.getKey k h) t[k] = true := + DTreeMap.Const.isEmpty_filter_eq_false_iff + +-- TODO: `contains_filter` is missing + +@[grind =] +theorem mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ (h' : k ∈ t), f (t.getKey k h') t[k] := + DTreeMap.Const.mem_filter + +theorem contains_of_contains_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f).contains k = true → t.contains k = true := + DTreeMap.contains_of_contains_filter + +theorem mem_of_mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + k ∈ t.filter f → k ∈ t := + DTreeMap.mem_of_mem_filter + +theorem size_filter_le_size [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size ≤ t.size := + DTreeMap.size_filter_le_size + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → β → Bool} : + (t.filter f).size = t.size ↔ ∀ k h, f (t.getKey k h) (t.get k h) := + DTreeMap.Const.size_filter_eq_size_iff + +theorem filter_equiv_self_iff [TransCmp cmp] + {f : α → β → Bool} : + t.filter f ~m t ↔ ∀ k h, f (t.getKey k h) (t.get k h) := + ⟨fun h => DTreeMap.Const.filter_equiv_self_iff.mp h.1, + fun h => ⟨DTreeMap.Const.filter_equiv_self_iff.mpr h⟩⟩ + +@[simp] +theorem getElem?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]? = t[k]?.pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x) := + DTreeMap.Const.get?_filter + +/-- Simpler variant of `getElem?_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem?_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]? = t[k]?.filter (f k) := by + simp [getElem?_filter] + +theorem getElem?_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + (t.filter f)[k]? = t[k]?.filter (fun x => f k' x) := + DTreeMap.Const.get?_filter_of_getKey?_eq_some + +@[simp, grind =] +theorem getElem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} : + (t.filter f)[k]'(h') = t[k]'(mem_of_mem_filter h') := + DTreeMap.Const.get_filter + +theorem getElem!_filter [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]! = + (t[k]?.pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).get! := + DTreeMap.Const.get!_filter + +/-- Simpler variant of `getElem!_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem!_filter' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} : + (t.filter f)[k]! = (t[k]?.filter (f k)).get! := by + simp [getElem!_filter] + +theorem getElem!_filter_of_getKey?_eq_some [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k k' : α} : + t.getKey? k = some k' → + (t.filter f)[k]! = (t[k]?.filter (f k')).get! := + DTreeMap.Const.get!_filter_of_getKey?_eq_some + +theorem getD_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + (t.filter f).getD k fallback = (t[k]?.pfilter (fun x h' => + f (t.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + DTreeMap.Const.getD_filter + +/-- Simpler variant of `getD_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} : + (t.filter f).getD k fallback = (t[k]?.filter (f k)).getD fallback := by + simp [getD_filter] + +theorem getD_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} {fallback : β} : + t.getKey? k = some k' → + (t.filter f).getD k fallback = + (t[k]?.filter (fun x => f k' x)).getD fallback := + DTreeMap.Const.getD_filter_of_getKey?_eq_some + +theorem keys_filter [TransCmp cmp] {f : α → β → Bool} : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (get t x (mem_of_mem_keys h')))).unattach := + DTreeMap.Const.keys_filter + +@[grind =] +theorem getKey?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h')))) := + DTreeMap.Const.getKey?_filter + +theorem getKey?_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey? k = (t.getKey? k).filter f := + DTreeMap.getKey?_filter_key + +@[simp, grind =] +theorem getKey_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} : + (t.filter f).getKey k h' = t.getKey k (mem_of_mem_filter h') := + DTreeMap.getKey_filter + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [Inhabited α] + {f : α → β → Bool} {k : α} : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))))).get! := + DTreeMap.Const.getKey!_filter + +theorem getKey!_filter_key [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} : + (t.filter fun k _ => f k).getKey! k = ((t.getKey? k).filter f).get! := + DTreeMap.getKey!_filter_key + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] + {f : α → β → Bool} {k fallback : α} : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h'))))).getD fallback := + DTreeMap.Const.getKeyD_filter + +theorem getKeyD_filter_key [TransCmp cmp] + {f : α → Bool} {k fallback : α} : + (t.filter fun k _ => f k).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := + DTreeMap.getKeyD_filter_key + +end filter + +section map + +variable {t : TreeMap α β cmp} + +theorem map_id_equiv : t.map (fun _ v => v) ~m t := + ⟨DTreeMap.map_id_equiv⟩ + +theorem map_map_equiv {f : α → β → γ} {g : α → γ → δ} : + (t.map f).map g ~m t.map fun k v => g k (f k v) := + ⟨DTreeMap.map_map_equiv⟩ + +@[simp, grind =] +theorem toList_map {f : α → β → γ} : + (t.map f).toList = t.toList.map (fun p => (p.1, f p.1 p.2)) := + DTreeMap.Const.toList_map + +@[simp, grind =] +theorem keys_map {f : α → β → γ} : (t.map f).keys = t.keys := + DTreeMap.keys_map + +theorem filterMap_equiv_map [TransCmp cmp] + {f : α → β → γ} : + (t.filterMap (fun k v => some (f k v))) ~m t.map f := + ⟨DTreeMap.filterMap_equiv_map⟩ + +@[simp, grind =] +theorem isEmpty_map [TransCmp cmp] + {f : α → β → γ} : + (t.map f).isEmpty = t.isEmpty := + DTreeMap.isEmpty_map + +@[simp, grind =] +theorem contains_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f).contains k = t.contains k := + DTreeMap.contains_map + +theorem contains_of_contains_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f).contains k = true → t.contains k = true := + DTreeMap.contains_of_contains_map + +@[simp, grind =] +theorem mem_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + k ∈ t.map f ↔ k ∈ t := by + simp only [mem_iff_contains, contains_map] + +theorem mem_of_mem_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + k ∈ t.map f → k ∈ t := + DTreeMap.contains_of_contains_map + +@[simp, grind =] +theorem size_map [TransCmp cmp] + {f : α → β → γ} : + (t.map f).size = t.size := + DTreeMap.size_map + +@[simp, grind =] +theorem getElem?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f)[k]? = t[k]?.map (f k) := + DTreeMap.Const.get?_map + +/-- Variant of `getElem?_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem getElem?_map' [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f)[k]? = t[k]?.pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h')) := + DTreeMap.Const.get?_map' + +theorem getElem?_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + (t.map f)[k]? = t[k]?.map (f k') := + DTreeMap.Const.get?_map_of_getKey?_eq_some h + +@[simp, grind =] +theorem getElem_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {h'} : + (t.map f)[k]'(h') = + f k (t[k]'(mem_of_mem_map h')) := + DTreeMap.Const.get_map + +/-- Variant of `getElem_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem getElem_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} : + (t.map f)[k]'(h') = + f (t.getKey k (mem_of_mem_map h')) (t[k]'(mem_of_mem_map h')) := + DTreeMap.Const.get_map' + +@[grind =] +theorem getElem!_map [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + (t.map f)[k]! = + (t[k]?.map (f k)).get! := + DTreeMap.Const.get!_map + +/-- Variant of `getElem!_map` that holds without `LawfulEqCmp`. -/ +theorem getElem!_map' [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} : + (t.map f)[k]! = + (t[k]?.pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_getElem?.mpr (Option.isSome_of_mem h'))).get! := + DTreeMap.Const.get!_map' + +theorem getElem!_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.getKey? k = some k') : + (t.map f)[k]! = (t[k]?.map (f k')).get! := + DTreeMap.Const.get!_map_of_getKey?_eq_some h + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + (t.map f).getD k fallback = + (t[k]?.map (f k)).getD fallback := + DTreeMap.Const.getD_map + +/-- Variant of `getD_map` that holds without `LawfulEqCmp`. -/ +theorem getD_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} : + (t.map f).getD k fallback = + (t[k]?.pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))).getD fallback := + DTreeMap.Const.getD_map' + +theorem getD_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.getKey? k = some k') : + (t.map f).getD k fallback = (t[k]?.map (f k')).getD fallback := + DTreeMap.Const.getD_map_of_getKey?_eq_some h + +@[simp, grind =] +theorem getKey?_map [TransCmp cmp] + {f : α → β → γ} {k : α} : + (t.map f).getKey? k = t.getKey? k := + DTreeMap.getKey?_map + +@[simp, grind =] +theorem getKey_map [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} : + (t.map f).getKey k h' = t.getKey k (mem_of_mem_map h') := + DTreeMap.getKey_map + +@[simp, grind =] +theorem getKey!_map [TransCmp cmp] [Inhabited α] + {f : α → β → γ} {k : α} : + (t.map f).getKey! k = t.getKey! k := + DTreeMap.getKey!_map + +@[simp, grind =] +theorem getKeyD_map [TransCmp cmp] + {f : α → β → γ} {k fallback : α} : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := + DTreeMap.getKeyD_map + +end map + end Std.TreeMap diff --git a/src/Std/Data/TreeMap/Raw/Lemmas.lean b/src/Std/Data/TreeMap/Raw/Lemmas.lean index 14c6e8eb97..3f9b8ae8b7 100644 --- a/src/Std/Data/TreeMap/Raw/Lemmas.lean +++ b/src/Std/Data/TreeMap/Raw/Lemmas.lean @@ -27,7 +27,7 @@ universe u v w w' namespace Std.TreeMap.Raw -variable {α : Type u} {β : Type v} {γ : Type w} {cmp : α → α → Ordering} {t : TreeMap.Raw α β cmp} +variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type w'} {cmp : α → α → Ordering} {t : TreeMap.Raw α β cmp} private theorem ext {t t' : Raw α β cmp} : t.inner = t'.inner → t = t' := by cases t; cases t'; rintro rfl; rfl @@ -292,9 +292,17 @@ theorem getElem_erase [TransCmp cmp] (h : t.WF) {k a : α} {h'} : (t.erase k)[a]'h' = t[a]'(mem_of_mem_erase h h') := DTreeMap.Raw.Const.get_erase h -theorem getElem?_eq_some_getElem [TransCmp cmp] (h : t.WF) {a : α} {h'} : +theorem getElem?_eq_some_getElem [TransCmp cmp] (h : t.WF) {a : α} (h') : t[a]? = some (t[a]'h') := - DTreeMap.Raw.Const.get?_eq_some_get h + DTreeMap.Raw.Const.get?_eq_some_get h h' + +theorem getElem_eq_get_getElem? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + t[a] = t[a]?.get ((mem_iff_isSome_getElem? h).mp h') := + DTreeMap.Raw.Const.get_eq_get_get? h + +@[grind =] theorem get_getElem? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + t[a]?.get h' = t[a]'((mem_iff_isSome_getElem? h).mpr h') := + DTreeMap.Raw.Const.get_get? h theorem getElem_congr [TransCmp cmp] (h : t.WF) {a b : α} (hab : cmp a b = .eq) {h'} : t[a]'h' = t[b]'((mem_congr h hab).mp h') := @@ -457,6 +465,10 @@ theorem isSome_getKey?_iff_mem [TransCmp cmp] (h : t.WF) {a : α} : (t.getKey? a).isSome ↔ a ∈ t := (mem_iff_isSome_getKey? h).symm +theorem mem_of_getKey?_eq_some [TransCmp cmp] {a a' : α} (h : t.WF) : + t.getKey? a = some a' → a' ∈ t := + DTreeMap.Raw.mem_of_getKey?_eq_some h + theorem getKey?_eq_none_of_contains_eq_false [TransCmp cmp] (h : t.WF) {a : α} : t.contains a = false → t.getKey? a = none := DTreeMap.Raw.getKey?_eq_none_of_contains_eq_false h @@ -506,9 +518,18 @@ theorem getKey_erase [TransCmp cmp] (h : t.WF) {k a : α} {h'} : (t.erase k).getKey a h' = t.getKey a (mem_of_mem_erase h h') := DTreeMap.Raw.getKey_erase h -theorem getKey?_eq_some_getKey [TransCmp cmp] (h : t.WF) {a : α} {h'} : +theorem getKey?_eq_some_getKey [TransCmp cmp] (h : t.WF) {a : α} (h') : t.getKey? a = some (t.getKey a h') := - DTreeMap.Raw.getKey?_eq_some_getKey h + DTreeMap.Raw.getKey?_eq_some_getKey h h' + +theorem getKey_eq_get_getKey? [TransCmp cmp] (h : t.WF) {a : α} {h' : a ∈ t} : + t.getKey a h' = (t.getKey? a).get ((mem_iff_isSome_getKey? h).mp h') := + DTreeMap.Raw.getKey_eq_get_getKey? h.out + +@[simp, grind =] +theorem get_getKey? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + (t.getKey? a).get h' = t.getKey a ((mem_iff_isSome_getKey? h).mpr h') := + DTreeMap.Raw.get_getKey? h.out theorem compare_getKey_self [TransCmp cmp] (h : t.WF) {k : α} (h' : k ∈ t) : cmp (t.getKey k h') k = .eq := @@ -786,6 +807,10 @@ theorem mem_keys [LawfulEqCmp cmp] [TransCmp cmp] (h : t.WF) {k : α} : k ∈ t.keys ↔ k ∈ t := DTreeMap.Raw.mem_keys h +theorem mem_of_mem_keys [TransCmp cmp] (h : t.WF) {k : α} : + k ∈ t.keys → k ∈ t := + DTreeMap.Raw.mem_of_mem_keys h + theorem distinct_keys [TransCmp cmp] (h : t.WF) : t.keys.Pairwise (fun a b => ¬ cmp a b = .eq) := DTreeMap.Raw.distinct_keys h @@ -3150,4 +3175,501 @@ theorem Equiv.of_keys_unit_perm {t₁ t₂ : Raw α Unit cmp} : t₁.keys.Perm t end Equiv +section filterMap + +theorem toList_filterMap {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).toList = + (t.toList.filterMap (fun p => (f p.1 p.2).map (fun x => ⟨p.1, x⟩))) := + DTreeMap.Raw.Const.toList_filterMap h + +@[grind =] +theorem isEmpty_filterMap_iff [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) (t[k]'h) = none := + DTreeMap.Raw.Const.isEmpty_filterMap_iff h.out + +theorem isEmpty_filterMap_eq_false_iff [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), (f (t.getKey k h) (t[k]'h)).isSome := + DTreeMap.Raw.Const.isEmpty_filterMap_eq_false_iff h.out + +-- TODO: `contains_filterMap` is missing + +@[grind =] +theorem mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + k ∈ (t.filterMap f) ↔ ∃ (g : k ∈ t), + (f (t.getKey k g) (t[k]'g)).isSome := + DTreeMap.Raw.Const.mem_filterMap h.out + +theorem mem_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) (h' : k ∈ (t.filterMap f)) : + k ∈ t := + DTreeMap.Raw.mem_of_mem_filterMap h.out h' + +theorem size_filterMap_le_size [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).size ≤ t.size := + DTreeMap.Raw.size_filterMap_le_size h.out + +grind_pattern size_filterMap_le_size => (t.filterMap f).size +theorem size_filterMap_eq_size_iff [TransCmp cmp] + {f : α → β → Option γ} (h : t.WF) : + (t.filterMap f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), + (f (t.getKey a h) (t[a]'h)).isSome := + DTreeMap.Raw.Const.size_filterMap_eq_size_iff h.out + +@[simp] +theorem getElem?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f)[k]? = t[k]?.pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))) x) := + DTreeMap.Raw.Const.get?_filterMap h.out + +/-- Simpler variant of `getElem?_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem?_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f)[k]? = t[k]?.bind fun x => f k x := by + simp [getElem?_filterMap, h] + +theorem getElem?_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → (t.filterMap f)[k]? = t[k]?.bind + fun x => f k' x := + DTreeMap.Raw.Const.get?_filterMap_of_getKey?_eq_some h.out + +theorem isSome_apply_of_mem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + ∀ (h' : k ∈ t.filterMap f), + (f (t.getKey k (mem_of_mem_filterMap h h')) + (t[k]'(mem_of_mem_filterMap h h'))).isSome := + DTreeMap.Raw.Const.isSome_apply_of_mem_filterMap h.out + +@[simp] +theorem getElem_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {g} (h : t.WF) : + (t.filterMap f)[k]'g = + (f (t.getKey k (mem_of_mem_filterMap h g)) + (t[k]'(mem_of_mem_filterMap h g))).get + (isSome_apply_of_mem_filterMap h g) := + DTreeMap.Raw.Const.get_filterMap h.out (h':= g) + +/-- Simpler variant of `getElem_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {g} (h : t.WF) : + (t.filterMap f)[k]'g = + (f k (t[k]'(mem_of_mem_filterMap h g))).get (by simpa [h] using isSome_apply_of_mem_filterMap h g) := by + simp [getElem_filterMap, h] + +theorem getElem!_filterMap [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f)[k]! = + (t[k]?.pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))) + x)).get! := + DTreeMap.Raw.Const.get!_filterMap h.out + +/-- Simpler variant of `getElem!_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem!_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f)[k]! = (t[k]?.bind (f k)).get! := by + simp [getElem!_filterMap, h] + +theorem getElem!_filterMap_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → Option γ} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → (t.filterMap f)[k]! = (t[k]?.bind + fun x => f k' x).get! := + DTreeMap.Raw.Const.get!_filterMap_of_getKey?_eq_some h.out + +theorem getD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} (h : t.WF) : + getD (t.filterMap f) k fallback = + (t[k]?.pbind (fun x h' => + f (t.getKey k ((mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + DTreeMap.Raw.Const.getD_filterMap h.out + +/-- Simpler variant of `getD_filterMap` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filterMap' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Option γ} {k : α} {fallback : γ} (h : t.WF) : + getD (t.filterMap f) k fallback = (t[k]?.bind (f k)).getD fallback := by + simp [getD_filterMap, h] + +theorem getD_filterMap_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Option γ} {k k' : α} {fallback : γ} (h : t.WF) : + t.getKey? k = some k' → getD (t.filterMap f) k fallback = (t[k]?.bind + fun x => f k' x).getD fallback := + DTreeMap.Raw.Const.getD_filterMap_of_getKey?_eq_some h.out + +@[grind =] +theorem getKey?_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h h'))).isSome) := + DTreeMap.Raw.Const.getKey?_filterMap h.out + +@[simp] +theorem getKey_filterMap [TransCmp cmp] + {f : (a : α) → β → Option γ} {k : α} {h'} (h : t.WF) : + (t.filterMap f).getKey k h' = t.getKey k (mem_of_mem_filterMap h h') := + DTreeMap.Raw.getKey_filterMap h.out + +@[grind =] +theorem getKey!_filterMap [TransCmp cmp] [Inhabited α] + {f : α → β → Option γ} {k : α} (h : t.WF) : + (t.filterMap f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h h'))).isSome)).get! := + DTreeMap.Raw.Const.getKey!_filterMap h.out + +@[grind =] +theorem getKeyD_filterMap [TransCmp cmp] + {f : α → β → Option γ} {k fallback : α} (h : t.WF) : + (t.filterMap f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]'(mem_of_getKey?_eq_some h h'))).isSome)).getD fallback := + DTreeMap.Raw.Const.getKeyD_filterMap h.out + +end filterMap + +section filter + +theorem filterMap_equiv_filter {f : α → β → Bool} (h : t.WF) : + (t.filterMap (fun k => Option.guard (fun v => f k v))) ~m (t.filter f) := + ⟨DTreeMap.Raw.filterMap_equiv_filter h.out⟩ + +theorem toList_filter + {f : (a : α) → β → Bool} (h : t.WF) : + (t.filter f).toList = t.toList.filter (fun p => f p.1 p.2) := + DTreeMap.Raw.Const.toList_filter h.out + +theorem keys_filter_key {f : α → Bool} (h : t.WF) : + (t.filter fun k _ => f k).keys = t.keys.filter f := + DTreeMap.Raw.keys_filter_key h.out + +@[grind =] +theorem isEmpty_filter_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).isEmpty = true ↔ + ∀ (k : α) (h : k ∈ t), f (t.getKey k h) (t[k]' h) = false := + DTreeMap.Raw.Const.isEmpty_filter_iff h.out + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f (t.getKey k h) (t[k]'h) := + DTreeMap.Raw.Const.isEmpty_filter_eq_false_iff h.out + +-- TODO: `contains_filter` is missing + +@[grind =] +theorem mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + k ∈ t.filter f ↔ ∃ (h' : k ∈ t), + f (t.getKey k h') (t[k]' h') := + DTreeMap.Raw.Const.mem_filter h.out + +theorem mem_of_mem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + k ∈ t.filter f → k ∈ t := + DTreeMap.Raw.mem_of_mem_filter h.out + +theorem size_filter_le_size [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).size ≤ t.size := + DTreeMap.Raw.size_filter_le_size h.out + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f).size = t.size ↔ ∀ (a : α) (h : a ∈ t), + f (t.getKey a h) t[a] := + DTreeMap.Raw.Const.size_filter_eq_size_iff h.out + +theorem filter_equiv_self_iff [TransCmp cmp] + {f : α → β → Bool} (h : t.WF) : + (t.filter f) ~m t ↔ ∀ (a : α) (h : a ∈ t), + f (t.getKey a h) t[a] := + ⟨fun h' => (DTreeMap.Raw.Const.filter_equiv_self_iff h.out).mp h'.1, + fun h' => ⟨(DTreeMap.Raw.Const.filter_equiv_self_iff h.out).mpr h'⟩⟩ + +@[simp] +theorem getElem?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f)[k]? = t[k]?.pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))) x) := + DTreeMap.Raw.Const.get?_filter h.out + +/-- Simpler variant of `getElem?_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem?_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f)[k]? = t[k]?.filter (f k) := by + simp [getElem?_filter, h] + +theorem getElem?_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + (t.filter f)[k]? = t[k]?.filter (f k') := + DTreeMap.Raw.Const.get?_filter_of_getKey?_eq_some h.out + +@[simp, grind =] +theorem getElem_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {h'} (h : t.WF) : + (t.filter f)[k]' h' = t[k]' (mem_of_mem_filter h h') := + DTreeMap.Raw.Const.get_filter h.out (h' := h') + +theorem getElem!_filter [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f)[k]! = + (t[k]?.pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := + DTreeMap.Raw.Const.get!_filter h.out + +/-- Simpler variant of `getElem!_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getElem!_filter' [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited β] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f)[k]! = (t[k]?.filter (f k)).get! := by + simp [getElem!_filter, h] + +theorem getElem!_filter_of_getKey?_eq_some [TransCmp cmp] [Inhabited β] + {f : α → β → Bool} {k k' : α} (h : t.WF) : + t.getKey? k = some k' → + (t.filter f)[k]! = (t[k]?.filter (fun x => f k' x)).get! := + DTreeMap.Raw.Const.get!_filter_of_getKey?_eq_some h.out + +theorem getD_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} (h : t.WF) : + getD (t.filter f) k fallback = (t[k]?.pfilter (fun x h' => + f (t.getKey k ((mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := + DTreeMap.Raw.Const.getD_filter h.out + +/-- Simpler variant of `getD_filter` when `LawfulEqCmp` is available. -/ +@[grind =] +theorem getD_filter' [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → Bool} {k : α} {fallback : β} (h : t.WF) : + getD (t.filter f) k fallback = (t[k]?.filter (f k)).getD fallback := by + simp [getD_filter, h] + +theorem getD_filter_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → Bool} {k k' : α} {fallback : β} (h : t.WF) : + t.getKey? k = some k' → + getD (t.filter f) k fallback = + (t[k]?.filter (fun x => f k' x)).getD fallback := + DTreeMap.Raw.Const.getD_filter_of_getKey?_eq_some h.out + +theorem keys_filter [TransCmp cmp] {f : α → β → Bool} (h : t.WF) : + (t.filter f).keys = + (t.keys.attach.filter (fun ⟨x, h'⟩ => f x (t[x]' (mem_of_mem_keys h h')))).unattach := + DTreeMap.Raw.Const.keys_filter h.out + +@[grind =] +theorem getKey?_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f).getKey? k = + (t.getKey? k).pfilter (fun x h' => + (f x (t[x]' (mem_of_getKey?_eq_some h h')))) := + DTreeMap.Raw.Const.getKey?_filter h.out + +theorem getKey?_filter_key [TransCmp cmp] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter fun k _ => f k).getKey? k = (t.getKey? k).filter f := + DTreeMap.Raw.getKey?_filter_key h.out + +@[simp, grind =] +theorem getKey_filter [TransCmp cmp] + {f : α → β → Bool} {k : α} (h : t.WF) {h'} : + (t.filter f).getKey k h' = t.getKey k (mem_of_mem_filter h h') := + DTreeMap.Raw.getKey_filter h.out + +@[grind =] +theorem getKey!_filter [TransCmp cmp] [Inhabited α] + {f : α → β → Bool} {k : α} (h : t.WF) : + (t.filter f).getKey! k = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]' (mem_of_getKey?_eq_some h h'))))).get! := + DTreeMap.Raw.Const.getKey!_filter h.out + +theorem getKey!_filter_key [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter fun k _ => f k).getKey! k = ((t.getKey? k).filter f).get! := + DTreeMap.Raw.getKey!_filter_key h.out + +@[grind =] +theorem getKeyD_filter [TransCmp cmp] + {f : α → β → Bool} {k fallback : α} (h : t.WF) : + (t.filter f).getKeyD k fallback = + ((t.getKey? k).pfilter (fun x h' => + (f x (t[x]' (mem_of_getKey?_eq_some h h'))))).getD fallback := + DTreeMap.Raw.Const.getKeyD_filter h.out + +theorem getKeyD_filter_key [TransCmp cmp] + {f : α → Bool} {k fallback : α} (h : t.WF) : + (t.filter fun k _ => f k).getKeyD k fallback = ((t.getKey? k).filter f).getD fallback := + DTreeMap.Raw.getKeyD_filter_key h.out + +end filter + +section map + +theorem map_id_equiv : (t.map fun _ v => v) ~m t := + ⟨DTreeMap.Raw.map_id_equiv⟩ + +theorem map_map_equiv {f : α → β → γ} {g : α → γ → δ} : + ((t.map f).map g) ~m (t.map fun k v => g k (f k v)) := + ⟨DTreeMap.Raw.map_map_equiv⟩ + +theorem toList_map {f : (a : α) → β → γ} : + (t.map f).toList = t.toList.map (fun p => ⟨p.1, f p.1 p.2⟩) := + DTreeMap.Raw.Const.toList_map + +theorem keys_map {f : α → β → γ} : (t.map f).keys = t.keys := + DTreeMap.Raw.keys_map + +theorem filterMap_equiv_map [TransCmp cmp] + {f : α → β → γ} (h : t.WF) : + (t.filterMap (fun k v => Option.some (f k v))) ~m (t.map f) := + ⟨DTreeMap.Raw.filterMap_equiv_map h.out⟩ + +@[simp, grind =] +theorem isEmpty_map [TransCmp cmp] {f : α → β → γ} : + (t.map f).isEmpty = t.isEmpty := + DTreeMap.Raw.isEmpty_map + +@[simp, grind =] +theorem contains_map [TransCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f).contains k = t.contains k := + DTreeMap.Raw.contains_map h.out + +theorem contains_of_contains_map [TransCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f).contains k = true → t.contains k = true := + DTreeMap.Raw.contains_of_contains_map h.out + +@[simp, grind =] +theorem mem_map [TransCmp cmp] + {f : (a : α) → β → γ} {k : α} (h : t.WF) : + k ∈ (t.map f) ↔ k ∈ t := + DTreeMap.Raw.mem_map h.out + +theorem mem_of_mem_map [TransCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + k ∈ (t.map f) → k ∈ t := + DTreeMap.Raw.mem_of_mem_map h.out + +@[simp, grind =] +theorem size_map [TransCmp cmp] {f : α → β → γ} : + (t.map f).size = t.size := + DTreeMap.Raw.size_map + +@[simp, grind =] +theorem getKey?_map [TransCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f).getKey? k = t.getKey? k := + DTreeMap.Raw.getKey?_map h.out + +@[simp, grind =] +theorem getKey_map [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} (h : t.WF) : + (t.map f).getKey k h' = t.getKey k (mem_of_mem_map h h') := + DTreeMap.Raw.getKey_map h.out + +@[simp, grind =] +theorem getKey!_map [TransCmp cmp] [Inhabited α] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f).getKey! k = t.getKey! k := + DTreeMap.Raw.getKey!_map h.out + +@[simp, grind =] +theorem getKeyD_map [TransCmp cmp] + {f : α → β → γ} {k fallback : α} (h : t.WF) : + (t.map f).getKeyD k fallback = t.getKeyD k fallback := + DTreeMap.Raw.getKeyD_map h.out + +@[simp, grind =] +theorem getElem?_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f)[k]? = t[k]?.map (f k) := + DTreeMap.Raw.Const.get?_map h.out + +/-- Variant of `getElem?_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem getElem?_map' [TransCmp cmp] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f)[k]? = t[k]?.pmap (fun v h' => f (t.getKey k h') v) + (fun _ h' => (mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h')) := + DTreeMap.Raw.Const.get?_map' h.out + +theorem getElem?_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} (h : t.WF) (h' : t.getKey? k = some k') : + (t.map f)[k]? = t[k]?.map (f k') := + DTreeMap.Raw.Const.get?_map_of_getKey?_eq_some h.out h' + +@[simp, grind =] +theorem getElem_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {h'} (h : t.WF) : + (t.map f)[k]' h' = + (f k (t[k]' (mem_of_mem_map h h'))) := + DTreeMap.Raw.Const.get_map h.out (h':= h') + +/-- Variant of `getElem_map` that holds without `LawfulEqCmp`. -/ +@[simp (low)] +theorem getElem_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {h'} (h : t.WF) : + (t.map f)[k]' h' = + (f (t.getKey k (mem_of_mem_map h h')) + (t[k]' (mem_of_mem_map h h'))) := + DTreeMap.Raw.Const.get_map' h.out (h':= h') + +@[grind =] +theorem getElem!_map [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f)[k]! = + (t[k]?.map (f k)).get! := + DTreeMap.Raw.Const.get!_map h.out + +/-- Variant of `getElem!_map` that holds without `LawfulEqCmp`. -/ +theorem getElem!_map' [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k : α} (h : t.WF) : + (t.map f)[k]! = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => (mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))).get! := + DTreeMap.Raw.Const.get!_map' h.out + +theorem getElem!_map_of_getKey?_eq_some [TransCmp cmp] [Inhabited γ] + {f : α → β → γ} {k k' : α} (h : t.WF) (h' : t.getKey? k = some k') : + (t.map f)[k]! = (t[k]?.map (f k')).get! := + DTreeMap.Raw.Const.get!_map_of_getKey?_eq_some h.out h' + +@[grind =] +theorem getD_map [TransCmp cmp] [LawfulEqCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} (h : t.WF) : + (t.map f).getD k fallback = + (t[k]?.map (f k)).getD fallback := + DTreeMap.Raw.Const.getD_map h.out + +/-- Variant of `getD_map` that holds without `LawfulEqCmp`. -/ +theorem getD_map' [TransCmp cmp] + {f : α → β → γ} {k : α} {fallback : γ} (h : t.WF) : + getD (t.map f) k fallback = + ((get? t k).pmap (fun v h => f (t.getKey k h) v) + (fun _ h' => (mem_iff_isSome_getElem? h).mpr (Option.isSome_of_eq_some h'))).getD fallback := + DTreeMap.Raw.Const.getD_map' h.out + +theorem getD_map_of_getKey?_eq_some [TransCmp cmp] + {f : α → β → γ} {k k' : α} {fallback : γ} (h : t.WF) (h' : t.getKey? k = some k') : + (t.map f).getD k fallback = (t[k]?.map (f k')).getD fallback := + DTreeMap.Raw.Const.getD_map_of_getKey?_eq_some h.out h' + +end map + end Std.TreeMap.Raw diff --git a/src/Std/Data/TreeSet/Lemmas.lean b/src/Std/Data/TreeSet/Lemmas.lean index 586070711a..feeb9c76ac 100644 --- a/src/Std/Data/TreeSet/Lemmas.lean +++ b/src/Std/Data/TreeSet/Lemmas.lean @@ -65,31 +65,31 @@ theorem not_mem_emptyc {k : α} : k ∉ (∅ : TreeSet α cmp) := theorem contains_of_isEmpty [TransCmp cmp] {a : α} : t.isEmpty → t.contains a = false := - DTreeMap.contains_of_isEmpty + TreeMap.contains_of_isEmpty theorem not_mem_of_isEmpty [TransCmp cmp] {a : α} : t.isEmpty → a ∉ t := - DTreeMap.not_mem_of_isEmpty + TreeMap.not_mem_of_isEmpty theorem isEmpty_eq_false_iff_exists_contains_eq_true [TransCmp cmp] : t.isEmpty = false ↔ ∃ a, t.contains a = true := - DTreeMap.isEmpty_eq_false_iff_exists_contains_eq_true + TreeMap.isEmpty_eq_false_iff_exists_contains_eq_true theorem isEmpty_eq_false_iff_exists_mem [TransCmp cmp] : t.isEmpty = false ↔ ∃ a, a ∈ t := - DTreeMap.isEmpty_eq_false_iff_exists_mem + TreeMap.isEmpty_eq_false_iff_exists_mem theorem isEmpty_eq_false_of_contains [TransCmp cmp] {a : α} (hc : t.contains a = true) : t.isEmpty = false := - DTreeMap.isEmpty_eq_false_of_contains hc + TreeMap.isEmpty_eq_false_of_contains hc theorem isEmpty_iff_forall_contains [TransCmp cmp] : t.isEmpty = true ↔ ∀ a, t.contains a = false := - DTreeMap.isEmpty_iff_forall_contains + TreeMap.isEmpty_iff_forall_contains theorem isEmpty_iff_forall_not_mem [TransCmp cmp] : t.isEmpty = true ↔ ∀ a, ¬a ∈ t := - DTreeMap.isEmpty_iff_forall_not_mem + TreeMap.isEmpty_iff_forall_not_mem @[simp] theorem insert_eq_insert {p : α} : Insert.insert p t = t.insert p := @@ -165,7 +165,7 @@ theorem isEmpty_erase [TransCmp cmp] {k : α} : theorem isEmpty_eq_isEmpty_erase_and_not_contains [TransCmp cmp] (k : α) : t.isEmpty = ((t.erase k).isEmpty && !(t.contains k)) := - DTreeMap.isEmpty_eq_isEmpty_erase_and_not_contains k + TreeMap.isEmpty_eq_isEmpty_erase_and_not_contains k theorem isEmpty_eq_false_of_isEmpty_erase_eq_false [TransCmp cmp] {k : α} (he : (t.erase k).isEmpty = false) : @@ -224,6 +224,19 @@ theorem isSome_get?_eq_contains [TransCmp cmp] {a : α} : (t.get? a).isSome = t.contains a := contains_eq_isSome_get?.symm +theorem mem_iff_isSome_get? [TransCmp cmp] {a : α} : + a ∈ t ↔ (t.get? a).isSome := + TreeMap.mem_iff_isSome_getKey? + +@[simp] +theorem isSome_get?_iff_mem [TransCmp cmp] {a : α} : + (t.get? a).isSome ↔ a ∈ t := + mem_iff_isSome_get?.symm + +theorem mem_of_get?_eq_some [TransCmp cmp] {k k' : α} + (h : t.get? k = some k') : k' ∈ t := + TreeMap.mem_of_getKey?_eq_some h + theorem get?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} : t.contains a = false → t.get? a = none := TreeMap.getKey?_eq_none_of_contains_eq_false @@ -241,21 +254,21 @@ theorem get?_erase_self [TransCmp cmp] {k : α} : (t.erase k).get? k = none := TreeMap.getKey?_erase_self -theorem get?_beq [TransCmp cmp] {k : α} : +theorem compare_getKey?_self [TransCmp cmp] {k : α} : (t.get? k).all (cmp · k = .eq) := - DTreeMap.compare_getKey?_self + TreeMap.compare_getKey?_self theorem get?_congr [TransCmp cmp] {k k' : α} (h' : cmp k k' = .eq) : t.get? k = t.get? k' := - DTreeMap.getKey?_congr h' + TreeMap.getKey?_congr h' theorem get?_eq_some_of_contains [TransCmp cmp] [LawfulEqCmp cmp] {k : α} (h' : t.contains k) : t.get? k = some k := - DTreeMap.getKey?_eq_some_of_contains h' + TreeMap.getKey?_eq_some_of_contains h' theorem get?_eq_some [TransCmp cmp] [LawfulEqCmp cmp] {k : α} (h' : k ∈ t) : t.get? k = some k := - DTreeMap.getKey?_eq_some_of_contains h' + TreeMap.getKey?_eq_some_of_contains h' @[grind =] theorem get_insert [TransCmp cmp] {k a : α} {h₁} : (t.insert k).get a h₁ = @@ -267,22 +280,30 @@ theorem get?_eq_some [TransCmp cmp] [LawfulEqCmp cmp] {k : α} (h' : k ∈ t) : (t.erase k).get a h' = t.get a (mem_of_mem_erase h') := TreeMap.getKey_erase -theorem get?_eq_some_get [TransCmp cmp] {a : α} {h'} : +theorem get?_eq_some_get [TransCmp cmp] {a : α} (h') : t.get? a = some (t.get a h') := - TreeMap.getKey?_eq_some_getKey + TreeMap.getKey?_eq_some_getKey h' -theorem get_beq [TransCmp cmp] {k : α} (h' : k ∈ t) : +theorem get_eq_get_get? [TransCmp cmp] {k : α} {h} : + t.get k h = (t.get? k).get (mem_iff_isSome_get?.mp h) := + TreeMap.getKey_eq_get_getKey? + +@[grind =] theorem get_get? [TransCmp cmp] {k : α} {h} : + (t.get? k).get h = t.get k (mem_iff_isSome_get?.mpr h) := + TreeMap.get_getKey? + +theorem compare_get_self [TransCmp cmp] {k : α} (h' : k ∈ t) : cmp (t.get k h') k = .eq := - DTreeMap.compare_getKey_self h' + TreeMap.compare_getKey_self h' theorem get_congr [TransCmp cmp] {k₁ k₂ : α} (h' : cmp k₁ k₂ = .eq) (h₁ : k₁ ∈ t) : t.get k₁ h₁ = t.get k₂ ((mem_congr h').mp h₁) := - DTreeMap.getKey_congr h' h₁ + TreeMap.getKey_congr h' h₁ @[simp, grind =] theorem get_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} (h' : k ∈ t) : t.get k h' = k := - DTreeMap.getKey_eq h' + TreeMap.getKey_eq h' @[simp, grind =] theorem get!_emptyc {a : α} [Inhabited α] : @@ -332,16 +353,16 @@ theorem get_eq_get! [TransCmp cmp] [Inhabited α] {a : α} {h} : theorem get!_congr [TransCmp cmp] [Inhabited α] {k k' : α} (h' : cmp k k' = .eq) : t.get! k = t.get! k' := - DTreeMap.getKey!_congr h' + TreeMap.getKey!_congr h' theorem get!_eq_of_contains [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] {k : α} (h' : t.contains k) : t.get! k = k := - DTreeMap.getKey!_eq_of_contains h' + TreeMap.getKey!_eq_of_contains h' theorem get!_eq_of_mem [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] {k : α} (h' : k ∈ t) : t.get! k = k := - DTreeMap.getKey!_eq_of_mem h' + TreeMap.getKey!_eq_of_mem h' @[simp, grind =] theorem getD_emptyc {a : α} {fallback : α} : @@ -397,15 +418,15 @@ theorem get!_eq_getD_default [TransCmp cmp] [Inhabited α] {a : α} : theorem getD_congr [TransCmp cmp] {k k' fallback : α} (h' : cmp k k' = .eq) : t.getD k fallback = t.getD k' fallback := - DTreeMap.getKeyD_congr h' + TreeMap.getKeyD_congr h' theorem getD_eq_of_contains [TransCmp cmp] [LawfulEqCmp cmp] {k fallback : α} (h' : t.contains k) : t.getD k fallback = k := - DTreeMap.getKeyD_eq_of_contains h' + TreeMap.getKeyD_eq_of_contains h' theorem getD_eq_of_mem [TransCmp cmp] [LawfulEqCmp cmp] {k fallback : α} (h' : k ∈ t) : t.getD k fallback = k := - DTreeMap.getKeyD_eq_of_contains h' + TreeMap.getKeyD_eq_of_contains h' @[simp, grind =] theorem containsThenInsert_fst [TransCmp cmp] {k : α} : @@ -420,30 +441,34 @@ theorem containsThenInsert_snd [TransCmp cmp] {k : α} : @[simp, grind =] theorem length_toList [TransCmp cmp] : t.toList.length = t.size := - DTreeMap.length_keys + TreeMap.length_keys @[simp, grind =] theorem isEmpty_toList : t.toList.isEmpty = t.isEmpty := - DTreeMap.isEmpty_keys + TreeMap.isEmpty_keys @[simp, grind =] theorem contains_toList [BEq α] [LawfulBEqCmp cmp] [TransCmp cmp] {k : α} : t.toList.contains k = t.contains k := - DTreeMap.contains_keys + TreeMap.contains_keys @[simp] theorem mem_toList [LawfulEqCmp cmp] [TransCmp cmp] {k : α} : k ∈ t.toList ↔ k ∈ t := - DTreeMap.mem_keys + TreeMap.mem_keys + +theorem mem_of_mem_toList [TransCmp cmp] {k : α} : + k ∈ t.toList → k ∈ t := + TreeMap.mem_of_mem_keys theorem distinct_toList [TransCmp cmp] : t.toList.Pairwise (fun a b => ¬ cmp a b = .eq) := - DTreeMap.distinct_keys + TreeMap.distinct_keys theorem ordered_toList [TransCmp cmp] : t.toList.Pairwise (fun a b => cmp a b = .lt) := - DTreeMap.ordered_keys + TreeMap.ordered_keys section monadic @@ -746,7 +771,7 @@ theorem isSome_min?_eq_not_isEmpty [TransCmp cmp] : theorem isSome_min?_iff_isEmpty_eq_false [TransCmp cmp] : t.min?.isSome ↔ t.isEmpty = false := - DTreeMap.isSome_minKey?_iff_isEmpty_eq_false + TreeMap.isSome_minKey?_iff_isEmpty_eq_false @[grind =] theorem min?_insert [TransCmp cmp] {k} : (t.insert k).min? = @@ -797,19 +822,19 @@ theorem le_min? [TransCmp cmp] {k} : theorem get?_min? [TransCmp cmp] {km} : (hkm : t.min? = some km) → t.get? km = some km := - DTreeMap.getKey?_minKey? + TreeMap.getKey?_minKey? theorem get_min? [TransCmp cmp] {km hc} : (hkm : t.min?.get (isSome_min?_of_contains hc) = km) → t.get km hc = km := - DTreeMap.getKey_minKey? + TreeMap.getKey_minKey? theorem get!_min? [TransCmp cmp] [Inhabited α] {km} : (hkm : t.min? = some km) → t.get! km = km := - DTreeMap.getKey!_minKey? + TreeMap.getKey!_minKey? theorem getD_min? [TransCmp cmp] {km fallback} : (hkm : t.min? = some km) → t.getD km fallback = km := - DTreeMap.getKeyD_minKey? + TreeMap.getKeyD_minKey? @[simp] theorem min?_bind_get? [TransCmp cmp] : @@ -861,164 +886,164 @@ theorem min_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] {he km} : @[grind =] 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 + TreeMap.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 + TreeMap.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 + TreeMap.minKey_insertIfNew_le_self @[grind =] theorem contains_min [TransCmp cmp] {he} : t.contains (t.min he) := - DTreeMap.contains_minKey + TreeMap.contains_minKey @[grind] theorem min_mem [TransCmp cmp] {he} : t.min he ∈ t := - DTreeMap.minKey_mem + TreeMap.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 + TreeMap.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 + TreeMap.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 + TreeMap.le_minKey @[simp, grind =] theorem get?_min [TransCmp cmp] {he} : t.get? (t.min he) = some (t.min he) := - DTreeMap.getKey?_minKey + TreeMap.getKey?_minKey @[simp, grind =] theorem get_min [TransCmp cmp] {he hc} : t.get (t.min he) hc = t.min he := - DTreeMap.getKey_minKey + TreeMap.getKey_minKey @[simp, grind =] theorem get!_min [TransCmp cmp] [Inhabited α] {he} : t.get! (t.min he) = t.min he := - DTreeMap.getKey!_minKey + TreeMap.getKey!_minKey @[simp, grind =] theorem getD_min [TransCmp cmp] {he fallback} : t.getD (t.min he) fallback = t.min he := - DTreeMap.getKeyD_minKey + TreeMap.getKeyD_minKey @[simp] theorem min_erase_eq_iff_not_compare_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 + TreeMap.minKey_erase_eq_iff_not_compare_eq_minKey theorem min_erase_eq_of_not_compare_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 + TreeMap.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 + TreeMap.minKey_le_minKey_erase theorem min_eq_head_toList [TransCmp cmp] {he} : t.min he = t.toList.head (List.isEmpty_eq_false_iff.mp <| isEmpty_toList ▸ he) := - DTreeMap.minKey_eq_head_keys + TreeMap.minKey_eq_head_keys theorem min?_eq_some_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.min? = some t.min! := - DTreeMap.minKey?_eq_some_minKey! he + TreeMap.minKey?_eq_some_minKey! he theorem min_eq_min! [TransCmp cmp] [Inhabited α] {he : t.isEmpty = false} : t.min he = t.min! := - DTreeMap.minKey_eq_minKey! + TreeMap.minKey_eq_minKey! theorem min!_eq_default [TransCmp cmp] [Inhabited α] (he : t.isEmpty) : t.min! = default := - DTreeMap.minKey!_eq_default he + TreeMap.minKey!_eq_default he theorem min!_eq_iff_get?_eq_self_and_forall [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {km} : t.min! = km ↔ t.get? km = some km ∧ ∀ k, k ∈ t → (cmp km k).isLE := - DTreeMap.minKey!_eq_iff_getKey?_eq_self_and_forall he + TreeMap.minKey!_eq_iff_getKey?_eq_self_and_forall he theorem min!_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] (he : t.isEmpty = false) {km} : t.min! = km ↔ km ∈ t ∧ ∀ k, k ∈ t → (cmp km k).isLE := - DTreeMap.minKey!_eq_iff_mem_and_forall he + TreeMap.minKey!_eq_iff_mem_and_forall he @[grind =] theorem min!_insert [TransCmp cmp] [Inhabited α] {k} : (t.insert k |>.min!) = t.min?.elim k fun k' => if cmp k k' = .lt then k else k' := - DTreeMap.minKey!_insertIfNew + TreeMap.minKey!_insertIfNew theorem min!_insert_le_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {k} : cmp (t.insert k |>.min!) t.min! |>.isLE := - DTreeMap.minKey!_insertIfNew_le_minKey! he + TreeMap.minKey!_insertIfNew_le_minKey! he theorem min!_insert_le_self [TransCmp cmp] [Inhabited α] {k} : cmp (t.insert k |>.min!) k |>.isLE := - DTreeMap.minKey!_insertIfNew_le_self + TreeMap.minKey!_insertIfNew_le_self @[grind =] theorem contains_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.contains t.min! := - DTreeMap.contains_minKey! he + TreeMap.contains_minKey! he @[grind] theorem min!_mem [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.min! ∈ t := - DTreeMap.minKey!_mem he + TreeMap.minKey!_mem he theorem min!_le_of_contains [TransCmp cmp] [Inhabited α] {k} (hc : t.contains k) : cmp t.min! k |>.isLE := - DTreeMap.minKey!_le_of_contains hc + TreeMap.minKey!_le_of_contains hc theorem min!_le_of_mem [TransCmp cmp] [Inhabited α] {k} (hc : k ∈ t) : cmp t.min! k |>.isLE := - DTreeMap.minKey!_le_of_mem hc + TreeMap.minKey!_le_of_mem hc theorem le_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {k} : (cmp k t.min!).isLE ↔ (∀ k', k' ∈ t → (cmp k k').isLE) := - DTreeMap.le_minKey! he + TreeMap.le_minKey! he theorem get?_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.get? t.min! = some t.min! := - DTreeMap.getKey?_minKey! he + TreeMap.getKey?_minKey! he @[grind =] theorem get_min! [TransCmp cmp] [Inhabited α] {hc} : t.get t.min! hc = t.min! := - DTreeMap.getKey_minKey! + TreeMap.getKey_minKey! @[simp, grind =] theorem get_min!_eq_min [TransCmp cmp] [Inhabited α] {hc} : t.get t.min! hc = t.min (isEmpty_eq_false_of_contains hc) := - DTreeMap.getKey_minKey!_eq_minKey + TreeMap.getKey_minKey!_eq_minKey theorem get!_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.get! t.min! = t.min! := - DTreeMap.getKey!_minKey! he + TreeMap.getKey!_minKey! he theorem getD_min! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {fallback} : t.getD t.min! fallback = t.min! := - DTreeMap.getKeyD_minKey! he + TreeMap.getKeyD_minKey! he theorem min!_erase_eq_of_not_compare_min!_eq [TransCmp cmp] [Inhabited α] {k} (he : (t.erase k).isEmpty = false) (heq : ¬ cmp k t.min! = .eq) : (t.erase k |>.min!) = t.min! := - DTreeMap.minKey!_erase_eq_of_not_compare_minKey!_eq he heq + TreeMap.minKey!_erase_eq_of_not_compare_minKey!_eq he heq theorem min!_le_min!_erase [TransCmp cmp] [Inhabited α] {k} (he : (t.erase k).isEmpty = false) : cmp t.min! (t.erase k |>.min!) |>.isLE := - DTreeMap.minKey!_le_minKey!_erase he + TreeMap.minKey!_le_minKey!_erase he theorem min!_eq_head!_toList [TransCmp cmp] [Inhabited α] : t.min! = t.toList.head! := @@ -1148,7 +1173,7 @@ theorem isSome_max?_eq_not_isEmpty [TransCmp cmp] : theorem isSome_max?_iff_isEmpty_eq_false [TransCmp cmp] : t.max?.isSome ↔ t.isEmpty = false := - DTreeMap.isSome_maxKey?_iff_isEmpty_eq_false + TreeMap.isSome_maxKey?_iff_isEmpty_eq_false @[grind =] theorem max?_insert [TransCmp cmp] {k} : (t.insert k).max? = @@ -1199,19 +1224,19 @@ theorem max?_le [TransCmp cmp] {k} : theorem get?_max? [TransCmp cmp] {km} : (hkm : t.max? = some km) → t.get? km = some km := - DTreeMap.getKey?_maxKey? + TreeMap.getKey?_maxKey? theorem get_max? [TransCmp cmp] {km hc} : (hkm : t.max?.get (isSome_max?_of_contains hc) = km) → t.get km hc = km := - DTreeMap.getKey_maxKey? + TreeMap.getKey_maxKey? theorem get!_max? [TransCmp cmp] [Inhabited α] {km} : (hkm : t.max? = some km) → t.get! km = km := - DTreeMap.getKey!_maxKey? + TreeMap.getKey!_maxKey? theorem getD_max? [TransCmp cmp] {km fallback} : (hkm : t.max? = some km) → t.getD km fallback = km := - DTreeMap.getKeyD_maxKey? + TreeMap.getKeyD_maxKey? @[simp] theorem max?_bind_get? [TransCmp cmp] : @@ -1339,89 +1364,89 @@ theorem max_eq_getLast_toList [TransCmp cmp] {he} : theorem max?_eq_some_max! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.max? = some t.max! := - DTreeMap.maxKey?_eq_some_maxKey! he + TreeMap.maxKey?_eq_some_maxKey! he theorem max_eq_max! [TransCmp cmp] [Inhabited α] {he : t.isEmpty = false} : t.max he = t.max! := - DTreeMap.maxKey_eq_maxKey! + TreeMap.maxKey_eq_maxKey! theorem max!_eq_default [TransCmp cmp] [Inhabited α] (he : t.isEmpty) : t.max! = default := - DTreeMap.maxKey!_eq_default he + TreeMap.maxKey!_eq_default he theorem max!_eq_iff_get?_eq_self_and_forall [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {km} : t.max! = km ↔ t.get? km = some km ∧ ∀ k, k ∈ t → (cmp k km).isLE := - DTreeMap.maxKey!_eq_iff_getKey?_eq_self_and_forall he + TreeMap.maxKey!_eq_iff_getKey?_eq_self_and_forall he theorem max!_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] (he : t.isEmpty = false) {km} : t.max! = km ↔ km ∈ t ∧ ∀ k, k ∈ t → (cmp k km).isLE := - DTreeMap.maxKey!_eq_iff_mem_and_forall he + TreeMap.maxKey!_eq_iff_mem_and_forall he @[grind =] theorem max!_insert [TransCmp cmp] [Inhabited α] {k} : (t.insert k |>.max!) = t.max?.elim k fun k' => if cmp k' k = .lt then k else k' := - DTreeMap.maxKey!_insertIfNew + TreeMap.maxKey!_insertIfNew theorem max!_le_max!_insert [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {k} : cmp t.max! (t.insert k |>.max!) |>.isLE := - DTreeMap.maxKey!_le_maxKey!_insertIfNew he + TreeMap.maxKey!_le_maxKey!_insertIfNew he theorem self_le_max!_insert [TransCmp cmp] [Inhabited α] {k} : cmp k (t.insert k |>.max!) |>.isLE := - DTreeMap.self_le_maxKey!_insertIfNew + TreeMap.self_le_maxKey!_insertIfNew @[grind =] theorem contains_max! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.contains t.max! := - DTreeMap.contains_maxKey! he + TreeMap.contains_maxKey! he @[grind] theorem max!_mem [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.max! ∈ t := - DTreeMap.maxKey!_mem he + TreeMap.maxKey!_mem he theorem le_max!_of_contains [TransCmp cmp] [Inhabited α] {k} (hc : t.contains k) : cmp k t.max! |>.isLE := - DTreeMap.le_maxKey!_of_contains hc + TreeMap.le_maxKey!_of_contains hc theorem le_max!_of_mem [TransCmp cmp] [Inhabited α] {k} (hc : k ∈ t) : cmp k t.max! |>.isLE := - DTreeMap.le_maxKey!_of_mem hc + TreeMap.le_maxKey!_of_mem hc theorem max!_le [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {k} : (cmp t.max! k).isLE ↔ (∀ k', k' ∈ t → (cmp k' k).isLE) := - DTreeMap.maxKey!_le he + TreeMap.maxKey!_le he theorem get?_max! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.get? t.max! = some t.max! := - DTreeMap.getKey?_maxKey! he + TreeMap.getKey?_maxKey! he @[grind =] theorem get_max! [TransCmp cmp] [Inhabited α] {hc} : t.get t.max! hc = t.max! := - DTreeMap.getKey_maxKey! + TreeMap.getKey_maxKey! @[simp, grind =] theorem get_max!_eq_max [TransCmp cmp] [Inhabited α] {hc} : t.get t.max! hc = t.max (isEmpty_eq_false_of_contains hc) := - DTreeMap.getKey_maxKey!_eq_maxKey + TreeMap.getKey_maxKey!_eq_maxKey theorem get!_max! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) : t.get! t.max! = t.max! := - DTreeMap.getKey!_maxKey! he + TreeMap.getKey!_maxKey! he theorem getD_max! [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) {fallback} : t.getD t.max! fallback = t.max! := - DTreeMap.getKeyD_maxKey! he + TreeMap.getKeyD_maxKey! he theorem max!_erase_eq_of_not_compare_max!_eq [TransCmp cmp] [Inhabited α] {k} (he : (t.erase k).isEmpty = false) (heq : ¬ cmp k t.max! = .eq) : (t.erase k |>.max!) = t.max! := - DTreeMap.maxKey!_erase_eq_of_not_compare_maxKey!_eq he heq + TreeMap.maxKey!_erase_eq_of_not_compare_maxKey!_eq he heq theorem max!_erase_le_max! [TransCmp cmp] [Inhabited α] {k} (he : (t.erase k).isEmpty = false) : cmp (t.erase k |>.max!) t.max! |>.isLE := - DTreeMap.maxKey!_erase_le_maxKey! he + TreeMap.maxKey!_erase_le_maxKey! he @[grind =_] theorem max!_eq_getLast!_toList [TransCmp cmp] [Inhabited α] : @@ -1776,4 +1801,84 @@ theorem equiv_iff_toList_eq [TransCmp cmp] : end Equiv +section filter + +variable {t : TreeSet α cmp} + +theorem toList_filter {f : α → Bool} : + (t.filter f).toList = t.toList.filter f := + TreeMap.keys_filter_key + +@[grind =] theorem isEmpty_filter_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter f).isEmpty ↔ ∀ k h, f (t.get k h) = false := + TreeMap.isEmpty_filter_iff + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter f).isEmpty = false ↔ ∃ k h, f (t.get k h) := + TreeMap.isEmpty_filter_eq_false_iff + +-- TODO: `contains_filter` is missing. + +@[simp, grind =] +theorem mem_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + k ∈ t.filter f ↔ ∃ h, f (t.get k h) := + TreeMap.mem_filter + +theorem contains_of_contains_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter f).contains k → t.contains k := + TreeMap.contains_of_contains_filter + +theorem mem_of_mem_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + k ∈ t.filter f → k ∈ t := + TreeMap.mem_of_mem_filter + +theorem size_filter_le_size [TransCmp cmp] + {f : α → Bool} : + (t.filter f).size ≤ t.size := + TreeMap.size_filter_le_size + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → Bool} : + (t.filter f).size = t.size ↔ ∀ k h, f (t.get k h) := + TreeMap.size_filter_eq_size_iff + +theorem filter_equiv_self_iff [TransCmp cmp] + {f : α → Bool} : + t.filter f ~m t ↔ ∀ k h, f (t.get k h) := + ⟨fun h => TreeMap.filter_equiv_self_iff.mp h.1, + fun h => ⟨TreeMap.filter_equiv_self_iff.mpr h⟩⟩ + +@[simp, grind =] +theorem get?_filter [TransCmp cmp] + {f : α → Bool} {k : α} : + (t.filter f).get? k = (t.get? k).filter f := + TreeMap.getKey?_filter_key + +@[simp, grind =] +theorem get_filter [TransCmp cmp] + {f : α → Bool} {k : α} {h} : + (t.filter f).get k h = t.get k (mem_of_mem_filter h) := + TreeMap.getKey_filter + +@[grind =] +theorem get!_filter [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} : + (t.filter f).get! k = ((t.get? k).filter f).get! := + TreeMap.getKey!_filter_key + +@[grind =] +theorem getD_filter [TransCmp cmp] + {f : α → Bool} {k fallback : α} : + (t.filter f).getD k fallback = ((t.get? k).filter f).getD fallback := + TreeMap.getKeyD_filter_key + +end filter + end Std.TreeSet diff --git a/src/Std/Data/TreeSet/Raw/Lemmas.lean b/src/Std/Data/TreeSet/Raw/Lemmas.lean index 4f9eca0978..db5651f2c4 100644 --- a/src/Std/Data/TreeSet/Raw/Lemmas.lean +++ b/src/Std/Data/TreeSet/Raw/Lemmas.lean @@ -65,19 +65,19 @@ theorem not_mem_emptyc {k : α} : k ∉ (∅ : Raw α cmp) := theorem contains_of_isEmpty [TransCmp cmp] (h : t.WF) {a : α} : t.isEmpty → t.contains a = false := - DTreeMap.Raw.contains_of_isEmpty h + TreeMap.Raw.contains_of_isEmpty h theorem not_mem_of_isEmpty [TransCmp cmp] (h : t.WF) {a : α} : t.isEmpty → a ∉ t := - DTreeMap.Raw.not_mem_of_isEmpty h + TreeMap.Raw.not_mem_of_isEmpty h theorem isEmpty_eq_false_iff_exists_contains_eq_true [TransCmp cmp] (h : t.WF) : t.isEmpty = false ↔ ∃ a, t.contains a = true := - DTreeMap.Raw.isEmpty_eq_false_iff_exists_contains_eq_true h + TreeMap.Raw.isEmpty_eq_false_iff_exists_contains_eq_true h theorem isEmpty_eq_false_iff_exists_mem [TransCmp cmp] (h : t.WF) : t.isEmpty = false ↔ ∃ a, a ∈ t := - DTreeMap.Raw.isEmpty_eq_false_iff_exists_mem h + TreeMap.Raw.isEmpty_eq_false_iff_exists_mem h theorem isEmpty_eq_false_of_contains [TransCmp cmp] (h : t.WF) {a : α} (hc : t.contains a = true) : t.isEmpty = false := @@ -85,11 +85,11 @@ theorem isEmpty_eq_false_of_contains [TransCmp cmp] (h : t.WF) {a : α} (hc : t. theorem isEmpty_iff_forall_contains [TransCmp cmp] (h : t.WF) : t.isEmpty = true ↔ ∀ a, t.contains a = false := - DTreeMap.Raw.isEmpty_iff_forall_contains h + TreeMap.Raw.isEmpty_iff_forall_contains h theorem isEmpty_iff_forall_not_mem [TransCmp cmp] (h : t.WF) : t.isEmpty = true ↔ ∀ a, ¬a ∈ t := - DTreeMap.Raw.isEmpty_iff_forall_not_mem h + TreeMap.Raw.isEmpty_iff_forall_not_mem h @[simp] theorem insert_eq_insert {p : α} : Insert.insert p t = t.insert p := @@ -222,6 +222,19 @@ theorem isSome_get?_eq_contains [TransCmp cmp] (h : t.WF) {a : α} : (t.get? a).isSome = t.contains a := (contains_eq_isSome_get? h).symm +theorem mem_iff_isSome_get? [TransCmp cmp] (h : t.WF) {a : α} : + a ∈ t ↔ (t.get? a).isSome := + TreeMap.Raw.mem_iff_isSome_getKey? h + +@[simp] +theorem isSome_get?_iff_mem [TransCmp cmp] (h : t.WF) {a : α} : + (t.get? a).isSome ↔ a ∈ t := + (mem_iff_isSome_get? h).symm + +theorem mem_of_get?_eq_some [TransCmp cmp] (h : t.WF) {a a' : α} : + t.get? a = some a' → a' ∈ t := + TreeMap.Raw.mem_of_getKey?_eq_some h + theorem get?_eq_none_of_contains_eq_false [TransCmp cmp] (h : t.WF) {a : α} : t.contains a = false → t.get? a = none := TreeMap.Raw.getKey?_eq_none_of_contains_eq_false h @@ -239,7 +252,7 @@ theorem get?_erase_self [TransCmp cmp] (h : t.WF) {k : α} : (t.erase k).get? k = none := TreeMap.Raw.getKey?_erase_self h -theorem get?_beq [TransCmp cmp] (h : t.WF) {k : α} : +theorem compare_get?_self [TransCmp cmp] (h : t.WF) {k : α} : (t.get? k).all (cmp · k = .eq) := TreeMap.Raw.compare_getKey?_self h @@ -267,11 +280,20 @@ theorem get_erase [TransCmp cmp] (h : t.WF) {k a : α} {h'} : (t.erase k).get a h' = t.get a (mem_of_mem_erase h h') := TreeMap.Raw.getKey_erase h -theorem get?_eq_some_get [TransCmp cmp] (h : t.WF) {a : α} {h'} : +theorem get?_eq_some_get [TransCmp cmp] (h : t.WF) {a : α} (h') : t.get? a = some (t.get a h') := - TreeMap.Raw.getKey?_eq_some_getKey h + TreeMap.Raw.getKey?_eq_some_getKey h h' -theorem get_beq [TransCmp cmp] (h : t.WF) {k : α} (h' : k ∈ t) : +theorem get_eq_get_get? [TransCmp cmp] (h : t.WF) {a : α} {h' : a ∈ t} : + t.get a h' = (t.get? a).get ((mem_iff_isSome_get? h).mp h') := + TreeMap.Raw.getKey_eq_get_getKey? h.out + +@[simp, grind =] +theorem get_get? [TransCmp cmp] (h : t.WF) {a : α} {h'} : + (t.get? a).get h' = t.get a ((mem_iff_isSome_get? h).mpr h') := + TreeMap.Raw.get_getKey? h.out + +theorem compare_get_self [TransCmp cmp] (h : t.WF) {k : α} (h' : k ∈ t) : cmp (t.get k h') k = .eq := TreeMap.Raw.compare_getKey_self h h' @@ -421,30 +443,34 @@ theorem containsThenInsert_snd [TransCmp cmp] (h : t.WF) {k : α} : @[simp, grind =] theorem length_toList [TransCmp cmp] (h : t.WF) : t.toList.length = t.size := - DTreeMap.Raw.length_keys h + TreeMap.Raw.length_keys h @[simp, grind =] theorem isEmpty_toList : t.toList.isEmpty = t.isEmpty := - DTreeMap.Raw.isEmpty_keys + TreeMap.Raw.isEmpty_keys @[simp, grind =] theorem contains_toList [BEq α] [LawfulBEqCmp cmp] [TransCmp cmp] (h : t.WF) {k : α} : t.toList.contains k = t.contains k := - DTreeMap.Raw.contains_keys h + TreeMap.Raw.contains_keys h @[simp, grind =] theorem mem_toList [LawfulEqCmp cmp] [TransCmp cmp] (h : t.WF) {k : α} : k ∈ t.toList ↔ k ∈ t := - DTreeMap.Raw.mem_keys h + TreeMap.Raw.mem_keys h + +theorem mem_of_mem_toList [TransCmp cmp] (h : t.WF) {k : α} : + k ∈ t.toList → k ∈ t := + TreeMap.Raw.mem_of_mem_keys h theorem distinct_toList [TransCmp cmp] (h : t.WF) : t.toList.Pairwise (fun a b => ¬ cmp a b = .eq) := - DTreeMap.Raw.distinct_keys h + TreeMap.Raw.distinct_keys h theorem ordered_toList [TransCmp cmp] (h : t.WF) : t.toList.Pairwise (fun a b => cmp a b = .lt) := - DTreeMap.Raw.ordered_keys h + TreeMap.Raw.ordered_keys h section monadic @@ -723,11 +749,11 @@ theorem min?_eq_none_iff [TransCmp cmp] (h : t.WF) : theorem min?_eq_some_iff_get?_eq_self_and_forall [TransCmp cmp] (h : t.WF) {km} : t.min? = some km ↔ t.get? km = some km ∧ ∀ k ∈ t, (cmp km k).isLE := - DTreeMap.Raw.minKey?_eq_some_iff_getKey?_eq_self_and_forall h + TreeMap.Raw.minKey?_eq_some_iff_getKey?_eq_self_and_forall h theorem min?_eq_some_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {km} : t.min? = some km ↔ km ∈ t ∧ ∀ k ∈ t, (cmp km k).isLE := - DTreeMap.Raw.minKey?_eq_some_iff_mem_and_forall h + TreeMap.Raw.minKey?_eq_some_iff_mem_and_forall h @[simp, grind =] theorem isNone_min?_eq_isEmpty [TransCmp cmp] (h : t.WF) : @@ -841,81 +867,81 @@ theorem min?_eq_head?_toList [TransCmp cmp] (h : t.WF) : theorem min?_eq_some_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.min? = some t.min! := - DTreeMap.Raw.minKey?_eq_some_minKey! h he + TreeMap.Raw.minKey?_eq_some_minKey! h he theorem min!_eq_default [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty) : t.min! = default := - DTreeMap.Raw.minKey!_eq_default h he + TreeMap.Raw.minKey!_eq_default h he theorem min!_eq_iff_get?_eq_self_and_forall [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {km} : t.min! = km ↔ t.get? km = some km ∧ ∀ k, k ∈ t → (cmp km k).isLE := - DTreeMap.Raw.minKey!_eq_iff_getKey?_eq_self_and_forall h he + TreeMap.Raw.minKey!_eq_iff_getKey?_eq_self_and_forall h he theorem min!_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {km} : t.min! = km ↔ km ∈ t ∧ ∀ k, k ∈ t → (cmp km k).isLE := - DTreeMap.Raw.minKey!_eq_iff_mem_and_forall h he + TreeMap.Raw.minKey!_eq_iff_mem_and_forall h he @[grind =] theorem min!_insert [TransCmp cmp] [Inhabited α] (h : t.WF) {k} : (t.insert k |>.min!) = t.min?.elim k fun k' => if cmp k k' = .lt then k else k' := - DTreeMap.Raw.minKey!_insertIfNew h + TreeMap.Raw.minKey!_insertIfNew h theorem min!_insert_le_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {k} : cmp (t.insert k |>.min!) t.min! |>.isLE := - DTreeMap.Raw.minKey!_insertIfNew_le_minKey! h he + TreeMap.Raw.minKey!_insertIfNew_le_minKey! h he theorem min!_insert_le_self [TransCmp cmp] [Inhabited α] (h : t.WF) {k} : cmp (t.insert k |>.min!) k |>.isLE := - DTreeMap.Raw.minKey!_insertIfNew_le_self h + TreeMap.Raw.minKey!_insertIfNew_le_self h @[grind =] theorem contains_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.contains t.min! := - DTreeMap.Raw.contains_minKey! h he + TreeMap.Raw.contains_minKey! h he @[grind] theorem min!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.min! ∈ t := - DTreeMap.Raw.minKey!_mem h he + TreeMap.Raw.minKey!_mem h he theorem min!_le_of_contains [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (hc : t.contains k) : cmp t.min! k |>.isLE := - DTreeMap.Raw.minKey!_le_of_contains h hc + TreeMap.Raw.minKey!_le_of_contains h hc theorem min!_le_of_mem [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (hc : k ∈ t) : cmp t.min! k |>.isLE := - DTreeMap.Raw.minKey!_le_of_mem h hc + TreeMap.Raw.minKey!_le_of_mem h hc theorem le_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {k} : (cmp k t.min!).isLE ↔ (∀ k', k' ∈ t → (cmp k k').isLE) := - DTreeMap.Raw.le_minKey! h he + TreeMap.Raw.le_minKey! h he theorem get?_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.get? t.min! = some t.min! := - DTreeMap.Raw.getKey?_minKey! h he + TreeMap.Raw.getKey?_minKey! h he theorem get_min! [TransCmp cmp] [Inhabited α] (h : t.WF) {hc} : t.get t.min! hc = t.min! := - DTreeMap.Raw.getKey_minKey! h + TreeMap.Raw.getKey_minKey! h theorem get!_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.get! t.min! = t.min! := - DTreeMap.Raw.getKey!_minKey! h he + TreeMap.Raw.getKey!_minKey! h he theorem getD_min! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.getD t.min! fallback = t.min! := - DTreeMap.Raw.getKeyD_minKey! h he + TreeMap.Raw.getKeyD_minKey! h he theorem min!_erase_eq_of_not_compare_min!_eq [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (he : (t.erase k).isEmpty = false) (heq : ¬ cmp k t.min! = .eq) : (t.erase k |>.min!) = t.min! := - DTreeMap.Raw.minKey!_erase_eq_of_not_compare_minKey!_eq h he heq + TreeMap.Raw.minKey!_erase_eq_of_not_compare_minKey!_eq h he heq theorem min!_le_min!_erase [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (he : (t.erase k).isEmpty = false) : cmp t.min! (t.erase k |>.min!) |>.isLE := - DTreeMap.Raw.minKey!_le_minKey!_erase h he + TreeMap.Raw.minKey!_le_minKey!_erase h he @[grind =_] theorem min!_eq_head!_toList [TransCmp cmp] [Inhabited α] (h : t.WF) : @@ -924,85 +950,85 @@ theorem min!_eq_head!_toList [TransCmp cmp] [Inhabited α] (h : t.WF) : theorem min?_eq_some_minD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.min? = some (t.minD fallback) := - DTreeMap.Raw.minKey?_eq_some_minKeyD h he + TreeMap.Raw.minKey?_eq_some_minKeyD h he theorem minD_eq_fallback [TransCmp cmp] (h : t.WF) (he : t.isEmpty) {fallback} : t.minD fallback = fallback := - DTreeMap.Raw.minKeyD_eq_fallback h he + TreeMap.Raw.minKeyD_eq_fallback h he theorem min!_eq_minD_default [TransCmp cmp] [Inhabited α] (h : t.WF) : t.min! = t.minD default := - DTreeMap.Raw.minKey!_eq_minKeyD_default h + TreeMap.Raw.minKey!_eq_minKeyD_default h theorem minD_eq_iff_get?_eq_self_and_forall [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {km fallback} : t.minD fallback = km ↔ t.get? km = some km ∧ ∀ k, k ∈ t → (cmp km k).isLE := - DTreeMap.Raw.minKeyD_eq_iff_getKey?_eq_self_and_forall h he + TreeMap.Raw.minKeyD_eq_iff_getKey?_eq_self_and_forall h he theorem minD_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) (he : t.isEmpty = false) {km fallback} : t.minD fallback = km ↔ km ∈ t ∧ ∀ k, k ∈ t → (cmp km k).isLE := - DTreeMap.Raw.minKeyD_eq_iff_mem_and_forall h he + TreeMap.Raw.minKeyD_eq_iff_mem_and_forall h he @[grind =] theorem minD_insert [TransCmp cmp] (h : t.WF) {k fallback} : (t.insert k |>.minD fallback) = t.min?.elim k fun k' => if cmp k k' = .lt then k else k' := - DTreeMap.Raw.minKeyD_insertIfNew h + TreeMap.Raw.minKeyD_insertIfNew h theorem minD_insert_le_minD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {k fallback} : cmp (t.insert k |>.minD fallback) (t.minD fallback) |>.isLE := - DTreeMap.Raw.minKeyD_insertIfNew_le_minKeyD h he + TreeMap.Raw.minKeyD_insertIfNew_le_minKeyD h he theorem minD_insert_le_self [TransCmp cmp] (h : t.WF) {k fallback} : cmp (t.insert k |>.minD fallback) k |>.isLE := - DTreeMap.Raw.minKeyD_insertIfNew_le_self h + TreeMap.Raw.minKeyD_insertIfNew_le_self h @[grind =] theorem contains_minD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.contains (t.minD fallback) := - DTreeMap.Raw.contains_minKeyD h he + TreeMap.Raw.contains_minKeyD h he @[grind] theorem minD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.minD fallback ∈ t := - DTreeMap.Raw.minKeyD_mem h he + TreeMap.Raw.minKeyD_mem h he theorem minD_le_of_contains [TransCmp cmp] (h : t.WF) {k} (hc : t.contains k) {fallback} : cmp (t.minD fallback) k |>.isLE := - DTreeMap.Raw.minKeyD_le_of_contains h hc + TreeMap.Raw.minKeyD_le_of_contains h hc theorem minD_le_of_mem [TransCmp cmp] (h : t.WF) {k} (hc : k ∈ t) {fallback} : cmp (t.minD fallback) k |>.isLE := - DTreeMap.Raw.minKeyD_le_of_mem h hc + TreeMap.Raw.minKeyD_le_of_mem h hc theorem le_minD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {k fallback} : (cmp k (t.minD fallback)).isLE ↔ (∀ k', k' ∈ t → (cmp k k').isLE) := - DTreeMap.Raw.le_minKeyD h he + TreeMap.Raw.le_minKeyD h he theorem get?_minD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.get? (t.minD fallback) = some (t.minD fallback) := - DTreeMap.Raw.getKey?_minKeyD h he + TreeMap.Raw.getKey?_minKeyD h he theorem get_minD [TransCmp cmp] (h : t.WF) {fallback hc} : t.get (t.minD fallback) hc = t.minD fallback := - DTreeMap.Raw.getKey_minKeyD h + TreeMap.Raw.getKey_minKeyD h theorem get!_minD [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.get! (t.minD fallback) = t.minD fallback := - DTreeMap.Raw.getKey!_minKeyD h he + TreeMap.Raw.getKey!_minKeyD h he theorem getD_minD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback fallback'} : t.getD (t.minD fallback) fallback' = t.minD fallback := - DTreeMap.Raw.getKeyD_minKeyD h he + TreeMap.Raw.getKeyD_minKeyD h he theorem minD_erase_eq_of_not_compare_minD_eq [TransCmp cmp] (h : t.WF) {k fallback} (he : (t.erase k).isEmpty = false) (heq : ¬ cmp k (t.minD fallback) = .eq) : (t.erase k |>.minD fallback) = t.minD fallback := - DTreeMap.Raw.minKeyD_erase_eq_of_not_compare_minKeyD_eq h he heq + TreeMap.Raw.minKeyD_erase_eq_of_not_compare_minKeyD_eq h he heq theorem minD_le_minD_erase [TransCmp cmp] (h : t.WF) {k} (he : (t.erase k).isEmpty = false) {fallback} : cmp (t.minD fallback) (t.erase k |>.minD fallback) |>.isLE := - DTreeMap.Raw.minKeyD_le_minKeyD_erase h he + TreeMap.Raw.minKeyD_le_minKeyD_erase h he @[grind =_] theorem minD_eq_headD_toList [TransCmp cmp] (h : t.WF) {fallback} : @@ -1029,11 +1055,11 @@ theorem max?_eq_none_iff [TransCmp cmp] (h : t.WF) : theorem max?_eq_some_iff_get?_eq_self_and_forall [TransCmp cmp] (h : t.WF) {km} : t.max? = some km ↔ t.get? km = some km ∧ ∀ k ∈ t, (cmp k km).isLE := - DTreeMap.Raw.maxKey?_eq_some_iff_getKey?_eq_self_and_forall h + TreeMap.Raw.maxKey?_eq_some_iff_getKey?_eq_self_and_forall h theorem max?_eq_some_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {km} : t.max? = some km ↔ km ∈ t ∧ ∀ k ∈ t, (cmp k km).isLE := - DTreeMap.Raw.maxKey?_eq_some_iff_mem_and_forall h + TreeMap.Raw.maxKey?_eq_some_iff_mem_and_forall h @[simp, grind =] theorem isNone_max?_eq_isEmpty [TransCmp cmp] (h : t.WF) : @@ -1151,81 +1177,81 @@ theorem max?_eq_head?_toList [TransCmp cmp] (h : t.WF) : theorem max?_eq_some_max! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.max? = some t.max! := - DTreeMap.Raw.maxKey?_eq_some_maxKey! h he + TreeMap.Raw.maxKey?_eq_some_maxKey! h he theorem max!_eq_default [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty) : t.max! = default := - DTreeMap.Raw.maxKey!_eq_default h he + TreeMap.Raw.maxKey!_eq_default h he theorem max!_eq_iff_get?_eq_self_and_forall [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {km} : t.max! = km ↔ t.get? km = some km ∧ ∀ k, k ∈ t → (cmp k km).isLE := - DTreeMap.Raw.maxKey!_eq_iff_getKey?_eq_self_and_forall h he + TreeMap.Raw.maxKey!_eq_iff_getKey?_eq_self_and_forall h he theorem max!_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {km} : t.max! = km ↔ km ∈ t ∧ ∀ k, k ∈ t → (cmp k km).isLE := - DTreeMap.Raw.maxKey!_eq_iff_mem_and_forall h he + TreeMap.Raw.maxKey!_eq_iff_mem_and_forall h he @[grind =] theorem max!_insert [TransCmp cmp] [Inhabited α] (h : t.WF) {k} : (t.insert k |>.max!) = t.max?.elim k fun k' => if cmp k' k = .lt then k else k' := - DTreeMap.Raw.maxKey!_insertIfNew h + TreeMap.Raw.maxKey!_insertIfNew h theorem max!_le_max!_insert [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {k} : cmp t.max! (t.insert k |>.max!) |>.isLE := - DTreeMap.Raw.maxKey!_le_maxKey!_insertIfNew h he + TreeMap.Raw.maxKey!_le_maxKey!_insertIfNew h he theorem self_le_max!_insert [TransCmp cmp] [Inhabited α] (h : t.WF) {k} : cmp k (t.insert k |>.max!) |>.isLE := - DTreeMap.Raw.self_le_maxKey!_insertIfNew h + TreeMap.Raw.self_le_maxKey!_insertIfNew h @[grind =] theorem contains_max! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.contains t.max! := - DTreeMap.Raw.contains_maxKey! h he + TreeMap.Raw.contains_maxKey! h he @[grind] theorem max!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.max! ∈ t := - DTreeMap.Raw.maxKey!_mem h he + TreeMap.Raw.maxKey!_mem h he theorem le_max!_of_contains [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (hc : t.contains k) : cmp k t.max! |>.isLE := - DTreeMap.Raw.le_maxKey!_of_contains h hc + TreeMap.Raw.le_maxKey!_of_contains h hc theorem le_max!_of_mem [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (hc : k ∈ t) : cmp k t.max! |>.isLE := - DTreeMap.Raw.le_maxKey!_of_mem h hc + TreeMap.Raw.le_maxKey!_of_mem h hc theorem max!_le [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {k} : (cmp t.max! k).isLE ↔ (∀ k', k' ∈ t → (cmp k' k).isLE) := - DTreeMap.Raw.maxKey!_le h he + TreeMap.Raw.maxKey!_le h he theorem get?_max! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.get? t.max! = some t.max! := - DTreeMap.Raw.getKey?_maxKey! h he + TreeMap.Raw.getKey?_maxKey! h he theorem get_max! [TransCmp cmp] [Inhabited α] (h : t.WF) {hc} : t.get t.max! hc = t.max! := - DTreeMap.Raw.getKey_maxKey! h + TreeMap.Raw.getKey_maxKey! h theorem get!_max! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) : t.get! t.max! = t.max! := - DTreeMap.Raw.getKey!_maxKey! h he + TreeMap.Raw.getKey!_maxKey! h he theorem getD_max! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.getD t.max! fallback = t.max! := - DTreeMap.Raw.getKeyD_maxKey! h he + TreeMap.Raw.getKeyD_maxKey! h he theorem max!_erase_eq_of_not_compare_max!_eq [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (he : (t.erase k).isEmpty = false) (heq : ¬ cmp k t.max! = .eq) : (t.erase k |>.max!) = t.max! := - DTreeMap.Raw.maxKey!_erase_eq_of_not_compare_maxKey!_eq h he heq + TreeMap.Raw.maxKey!_erase_eq_of_not_compare_maxKey!_eq h he heq theorem max!_erase_le_max! [TransCmp cmp] [Inhabited α] (h : t.WF) {k} (he : (t.erase k).isEmpty = false) : cmp (t.erase k |>.max!) t.max! |>.isLE := - DTreeMap.Raw.maxKey!_erase_le_maxKey! h he + TreeMap.Raw.maxKey!_erase_le_maxKey! h he @[grind =_] theorem max!_eq_getLast!_toList [TransCmp cmp] [Inhabited α] (h : t.WF) : @@ -1234,85 +1260,85 @@ theorem max!_eq_getLast!_toList [TransCmp cmp] [Inhabited α] (h : t.WF) : theorem max?_eq_some_maxD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.max? = some (t.maxD fallback) := - DTreeMap.Raw.maxKey?_eq_some_maxKeyD h he + TreeMap.Raw.maxKey?_eq_some_maxKeyD h he theorem maxD_eq_fallback [TransCmp cmp] (h : t.WF) (he : t.isEmpty) {fallback} : t.maxD fallback = fallback := - DTreeMap.Raw.maxKeyD_eq_fallback h he + TreeMap.Raw.maxKeyD_eq_fallback h he theorem max!_eq_maxD_default [TransCmp cmp] [Inhabited α] (h : t.WF) : t.max! = t.maxD default := - DTreeMap.Raw.maxKey!_eq_maxKeyD_default h + TreeMap.Raw.maxKey!_eq_maxKeyD_default h theorem maxD_eq_iff_get?_eq_self_and_forall [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {km fallback} : t.maxD fallback = km ↔ t.get? km = some km ∧ ∀ k, k ∈ t → (cmp k km).isLE := - DTreeMap.Raw.maxKeyD_eq_iff_getKey?_eq_self_and_forall h he + TreeMap.Raw.maxKeyD_eq_iff_getKey?_eq_self_and_forall h he theorem maxD_eq_iff_mem_and_forall [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) (he : t.isEmpty = false) {km fallback} : t.maxD fallback = km ↔ km ∈ t ∧ ∀ k, k ∈ t → (cmp k km).isLE := - DTreeMap.Raw.maxKeyD_eq_iff_mem_and_forall h he + TreeMap.Raw.maxKeyD_eq_iff_mem_and_forall h he @[grind =] theorem maxD_insert [TransCmp cmp] (h : t.WF) {k fallback} : (t.insert k |>.maxD fallback) = t.max?.elim k fun k' => if cmp k' k = .lt then k else k' := - DTreeMap.Raw.maxKeyD_insertIfNew h + TreeMap.Raw.maxKeyD_insertIfNew h theorem maxD_le_maxD_insert [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {k fallback} : cmp (t.maxD fallback) (t.insert k |>.maxD fallback) |>.isLE := - DTreeMap.Raw.maxKeyD_le_maxKeyD_insertIfNew h he + TreeMap.Raw.maxKeyD_le_maxKeyD_insertIfNew h he theorem self_le_maxD_insert [TransCmp cmp] (h : t.WF) {k fallback} : cmp k (t.insert k |>.maxD fallback) |>.isLE := - DTreeMap.Raw.self_le_maxKeyD_insertIfNew h + TreeMap.Raw.self_le_maxKeyD_insertIfNew h @[grind =] theorem contains_maxD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.contains (t.maxD fallback) := - DTreeMap.Raw.contains_maxKeyD h he + TreeMap.Raw.contains_maxKeyD h he @[grind] theorem maxD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.maxD fallback ∈ t := - DTreeMap.Raw.maxKeyD_mem h he + TreeMap.Raw.maxKeyD_mem h he theorem le_maxD_of_contains [TransCmp cmp] (h : t.WF) {k} (hc : t.contains k) {fallback} : cmp k (t.maxD fallback) |>.isLE := - DTreeMap.Raw.le_maxKeyD_of_contains h hc + TreeMap.Raw.le_maxKeyD_of_contains h hc theorem le_maxD_of_mem [TransCmp cmp] (h : t.WF) {k} (hc : k ∈ t) {fallback} : cmp k (t.maxD fallback) |>.isLE := - DTreeMap.Raw.le_maxKeyD_of_mem h hc + TreeMap.Raw.le_maxKeyD_of_mem h hc theorem maxD_le [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {k fallback} : (cmp (t.maxD fallback) k).isLE ↔ (∀ k', k' ∈ t → (cmp k' k).isLE) := - DTreeMap.Raw.maxKeyD_le h he + TreeMap.Raw.maxKeyD_le h he theorem get?_maxD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.get? (t.maxD fallback) = some (t.maxD fallback) := - DTreeMap.Raw.getKey?_maxKeyD h he + TreeMap.Raw.getKey?_maxKeyD h he theorem get_maxD [TransCmp cmp] (h : t.WF) {fallback hc} : t.get (t.maxD fallback) hc = t.maxD fallback := - DTreeMap.Raw.getKey_maxKeyD h + TreeMap.Raw.getKey_maxKeyD h theorem get!_maxD [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) {fallback} : t.get! (t.maxD fallback) = t.maxD fallback := - DTreeMap.Raw.getKey!_maxKeyD h he + TreeMap.Raw.getKey!_maxKeyD h he theorem getD_maxD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback fallback'} : t.getD (t.maxD fallback) fallback' = t.maxD fallback := - DTreeMap.Raw.getKeyD_maxKeyD h he + TreeMap.Raw.getKeyD_maxKeyD h he theorem maxD_erase_eq_of_not_compare_maxD_eq [TransCmp cmp] (h : t.WF) {k fallback} (he : (t.erase k).isEmpty = false) (heq : ¬ cmp k (t.maxD fallback) = .eq) : (t.erase k |>.maxD fallback) = t.maxD fallback := - DTreeMap.Raw.maxKeyD_erase_eq_of_not_compare_maxKeyD_eq h he heq + TreeMap.Raw.maxKeyD_erase_eq_of_not_compare_maxKeyD_eq h he heq theorem maxD_erase_le_maxD [TransCmp cmp] (h : t.WF) {k} (he : (t.erase k).isEmpty = false) {fallback} : cmp (t.erase k |>.maxD fallback) (t.maxD fallback) |>.isLE := - DTreeMap.Raw.maxKeyD_erase_le_maxKeyD h he + TreeMap.Raw.maxKeyD_erase_le_maxKeyD h he @[grind =_] theorem maxD_eq_getLastD_toList [TransCmp cmp] (h : t.WF) {fallback} : @@ -1571,4 +1597,77 @@ theorem equiv_iff_toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) : end Equiv +section filter + +theorem toList_filter {f : α → Bool} (h : t.WF) : + (t.filter f).toList = t.toList.filter f := + TreeMap.Raw.keys_filter_key h + +@[grind =] theorem isEmpty_filter_iff [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter f).isEmpty ↔ + ∀ (k : α) (h : k ∈ t), f (t.get k h) = false := + TreeMap.Raw.isEmpty_filter_iff h.out + +theorem isEmpty_filter_eq_false_iff [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter f).isEmpty = false ↔ + ∃ (k : α) (h : k ∈ t), f (t.get k h) := + TreeMap.Raw.isEmpty_filter_eq_false_iff h.out + +-- TODO: `contains_filter` is missing. + +@[simp, grind =] +theorem mem_filter [TransCmp cmp] + {f : α → Bool} {k : α} (h : t.WF) : + (k ∈ t.filter f) ↔ ∃ (h' : k ∈ t), f (t.get k h') := + TreeMap.Raw.mem_filter h.out + +theorem mem_of_mem_filter [TransCmp cmp] + {f : α → Bool} {k : α} (h : t.WF) : + k ∈ (t.filter f) → k ∈ t := + TreeMap.Raw.mem_of_mem_filter h.out + +theorem size_filter_le_size [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter f).size ≤ t.size := + TreeMap.Raw.size_filter_le_size h.out + +grind_pattern size_filter_le_size => (t.filter f).size + +theorem size_filter_eq_size_iff [TransCmp cmp] + {f : α → Bool} (h : t.WF) : + (t.filter f).size = t.size ↔ ∀ (k : α) (h : k ∈ t), f (t.get k h) := + TreeMap.Raw.size_filter_eq_size_iff h.out + +theorem filter_equiv_self_iff [TransCmp cmp] + {f : (a : α) → Bool} (h : t.WF) : + (t.filter f) ~m t ↔ ∀ (a : α) (h : a ∈ t), f (t.get a h) = true := + ⟨fun h' => (TreeMap.Raw.filter_equiv_self_iff h.out).mp h'.1, + fun h' => ⟨(TreeMap.Raw.filter_equiv_self_iff h.out).mpr h'⟩⟩ + +@[simp, grind =] +theorem get?_filter [TransCmp cmp] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter f).get? k = (t.get? k).filter f := + TreeMap.Raw.getKey?_filter_key h.out + +@[simp, grind =] +theorem get_filter [TransCmp cmp] + {f : α → Bool} {k : α} {h'} (h : t.WF) : + (t.filter f).get k h' = (t.get k (mem_of_mem_filter h h')) := + TreeMap.Raw.getKey_filter h.out + +@[grind =] theorem get!_filter [TransCmp cmp] [Inhabited α] + {f : α → Bool} {k : α} (h : t.WF) : + (t.filter f).get! k = ((t.get? k).filter f).get! := + TreeMap.Raw.getKey!_filter_key h.out + +@[grind =] theorem getD_filter [TransCmp cmp] + {f : α → Bool} {k fallback : α} (h : t.WF) : + (t.filter f).getD k fallback = ((t.get? k).filter f).getD fallback := + TreeMap.Raw.getKeyD_filter_key h.out + +end filter + end Std.TreeSet.Raw