feat: equivalence of tree maps (#8210)

This PR adds an equivalence relation to tree maps akin to the existing
one for hash maps. In order to get many congruence lemmas to eventually
use for defining functions on extensional tree maps, almost all of the
remaining tree map functions have also been given lemmas to relate them
to list functions, although these aren't currently used to prove lemmas
other than congruence lemmas.
This commit is contained in:
Rob23oba 2025-06-10 16:49:52 +02:00 committed by GitHub
parent 2344e3f254
commit be4ebb8ac3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 4264 additions and 181 deletions

View file

@ -3621,8 +3621,8 @@ We can prove that two folds over the same array are related (by some arbitrary r
if we know that the initial elements are related and the folding function, for each element of the array,
preserves the relation.
-/
theorem foldl_rel {xs : Array α} {f g : β → α → β} {a b : β} {r : β → β → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f c a) (g c' a)) :
theorem foldl_rel {xs : Array α} {f : β → α → β} {g : γαγ} {a : β} {b : γ} {r : β → γ → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c : β) (c' : γ), r c c' → r (f c a) (g c' a)) :
r (xs.foldl (fun acc a => f acc a) a) (xs.foldl (fun acc a => g acc a) b) := by
rcases xs with ⟨xs⟩
simpa using List.foldl_rel h (by simpa using h')
@ -3632,8 +3632,8 @@ We can prove that two folds over the same array are related (by some arbitrary r
if we know that the initial elements are related and the folding function, for each element of the array,
preserves the relation.
-/
theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} {r : β → β → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f a c) (g a c')) :
theorem foldr_rel {xs : Array α} {f : α → β → β} {g : αγγ} {a : β} {b : γ} {r : β → γ → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c : β) (c' : γ), r c c' → r (f a c) (g a c')) :
r (xs.foldr (fun a acc => f a acc) a) (xs.foldr (fun a acc => g a acc) b) := by
rcases xs with ⟨xs⟩
simpa using List.foldr_rel h (by simpa using h')

View file

@ -2778,8 +2778,8 @@ We can prove that two folds over the same list are related (by some arbitrary re
if we know that the initial elements are related and the folding function, for each element of the list,
preserves the relation.
-/
theorem foldl_rel {l : List α} {f g : β → α → β} {a b : β} {r : β → β → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ l → ∀ (c c' : β), r c c' → r (f c a) (g c' a)) :
theorem foldl_rel {l : List α} {f : β → α → β} {g : γαγ} {a : β} {b : γ} {r : β → γ → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ l → ∀ (c : β) (c' : γ), r c c' → r (f c a) (g c' a)) :
r (l.foldl (fun acc a => f acc a) a) (l.foldl (fun acc a => g acc a) b) := by
induction l generalizing a b with
| nil => simp_all
@ -2794,8 +2794,8 @@ We can prove that two folds over the same list are related (by some arbitrary re
if we know that the initial elements are related and the folding function, for each element of the list,
preserves the relation.
-/
theorem foldr_rel {l : List α} {f g : α → β → β} {a b : β} {r : β → β → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ l → ∀ (c c' : β), r c c' → r (f a c) (g a c')) :
theorem foldr_rel {l : List α} {f : α → β → β} {g : αγγ} {a : β} {b : γ} {r : β → γ → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ l → ∀ (c : β) (c' : γ), r c c' → r (f a c) (g a c')) :
r (l.foldr (fun a acc => f a acc) a) (l.foldr (fun a acc => g a acc) b) := by
induction l generalizing a b with
| nil => simp_all

View file

@ -2538,23 +2538,23 @@ theorem foldr_hom (f : β₁ → β₂) {g₁ : α → β₁ → β₁} {g₂ :
rw [Array.foldr_hom _ H]
/--
We can prove that two folds over the same array are related (by some arbitrary relation)
if we know that the initial elements are related and the folding function, for each element of the array,
preserves the relation.
We can prove that two folds over the same vector are related (by some arbitrary relation)
if we know that the initial elements are related and the folding function, for each element of the
vector, preserves the relation.
-/
theorem foldl_rel {xs : Vector α n} {f g : β → α → β} {a b : β} {r : β → β → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f c a) (g c' a)) :
theorem foldl_rel {xs : Vector α n} {f : β → α → β} {g : γαγ} {a : β} {b : γ} {r : β → γ → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c : β) (c' : γ), r c c' → r (f c a) (g c' a)) :
r (xs.foldl (fun acc a => f acc a) a) (xs.foldl (fun acc a => g acc a) b) := by
rcases xs with ⟨xs, rfl⟩
simpa using Array.foldl_rel h (by simpa using h')
/--
We can prove that two folds over the same array are related (by some arbitrary relation)
if we know that the initial elements are related and the folding function, for each element of the array,
preserves the relation.
We can prove that two folds over the same vector are related (by some arbitrary relation)
if we know that the initial elements are related and the folding function, for each element of the
vector, preserves the relation.
-/
theorem foldr_rel {xs : Vector α n} {f g : α → β → β} {a b : β} {r : β → β → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c c' : β), r c c' → r (f a c) (g a c')) :
theorem foldr_rel {xs : Vector α n} {f : α → β → β} {g : αγγ} {a : β} {b : γ} {r : β → γ → Prop}
(h : r a b) (h' : ∀ (a : α), a ∈ xs → ∀ (c : β) (c' : γ), r c c' → r (f a c) (g a c')) :
r (xs.foldr (fun a acc => f a acc) a) (xs.foldr (fun a acc => g a acc) b) := by
rcases xs with ⟨xs, rfl⟩
simpa using Array.foldr_rel h (by simpa using h')

View file

@ -66,7 +66,7 @@ def getEntryLE [TransCmp cmp] (t : DTreeMap α β cmp) (k : α) (h : ∃ a ∈ t
letI : Ord α := ⟨cmp⟩; Impl.getEntryLE k t.inner t.wf.ordered h
/--
Given a proof that such a mapping exists, retrieves the key-value pair with the smallest key that is
Given a proof that such a mapping exists, retrieves the key-value pair with the largest key that is
less than the given key.
-/
@[inline]
@ -99,7 +99,7 @@ def getKeyLE [TransCmp cmp] (t : DTreeMap α β cmp) (k : α) (h : ∃ a ∈ t,
letI : Ord α := ⟨cmp⟩; Impl.getKeyLE k t.inner t.wf.ordered h
/--
Given a proof that such a mapping exists, retrieves the smallest key that is
Given a proof that such a mapping exists, retrieves the largest key that is
less than the given key.
-/
@[inline]
@ -138,7 +138,7 @@ def getEntryLE [TransCmp cmp] (t : DTreeMap α β cmp) (k : α) (h : ∃ a ∈ t
letI : Ord α := ⟨cmp⟩; Impl.Const.getEntryLE k t.inner t.wf.ordered h
/--
Given a proof that such a mapping exists, retrieves the key-value pair with the smallest key that is
Given a proof that such a mapping exists, retrieves the key-value pair with the largest key that is
less than the given key.
-/
@[inline]

View file

@ -83,6 +83,13 @@ instance : EmptyCollection (DTreeMap α β cmp) where
instance : Inhabited (DTreeMap α β cmp) where
default := ∅
@[inherit_doc Impl.Equiv]
structure Equiv (m₁ m₂ : DTreeMap α β cmp) where
/-- Internal implementation detail of the tree map -/
inner : m₁.1.Equiv m₂.1
@[inherit_doc] scoped infix:50 " ~m " => Equiv
@[simp]
theorem empty_eq_emptyc : (empty : DTreeMap α β cmp) = ∅ :=
rfl
@ -500,7 +507,7 @@ def getEntryLE? (t : DTreeMap α β cmp) (k : α) : Option ((a : α) × β a) :=
letI : Ord α := ⟨cmp⟩; Impl.getEntryLE? k t.inner
/--
Tries to retrieve the key-value pair with the smallest key that is less than the given key,
Tries to retrieve the key-value pair with the largest key that is less than the given key,
returning `none` if no such pair exists.
-/
@[inline]
@ -537,7 +544,7 @@ def getEntryLE! [Inhabited (Sigma β)] (t : DTreeMap α β cmp) (k : α) : (a :
letI : Ord α := ⟨cmp⟩; Impl.getEntryLE! k t.inner
/--
Tries to retrieve the key-value pair with the smallest key that is less than the given key,
Tries to retrieve the key-value pair with the largest key that is less than the given key,
panicking if no such pair exists.
-/
@[inline]
@ -569,7 +576,7 @@ def getEntryLED (t : DTreeMap α β cmp) (k : α) (fallback : Sigma β) : (a :
letI : Ord α := ⟨cmp⟩; Impl.getEntryLED k t.inner fallback
/--
Tries to retrieve the key-value pair with the smallest key that is less than the given key,
Tries to retrieve the key-value pair with the largest key that is less than the given key,
returning `fallback` if no such pair exists.
-/
@[inline]
@ -601,7 +608,7 @@ def getKeyLE? (t : DTreeMap α β cmp) (k : α) : Option α :=
letI : Ord α := ⟨cmp⟩; t.inner.getKeyLE? k
/--
Tries to retrieve the smallest key that is less than the given key,
Tries to retrieve the largest key that is less than the given key,
returning `none` if no such key exists.
-/
@[inline]
@ -638,7 +645,7 @@ def getKeyLE! [Inhabited α] (t : DTreeMap α β cmp) (k : α) : α :=
letI : Ord α := ⟨cmp⟩; Impl.getKeyLE! k t.inner
/--
Tries to retrieve the smallest key that is less than the given key,
Tries to retrieve the largest key that is less than the given key,
panicking if no such key exists.
-/
@[inline]
@ -670,7 +677,7 @@ def getKeyLED (t : DTreeMap α β cmp) (k : α) (fallback : α) : α :=
letI : Ord α := ⟨cmp⟩; Impl.getKeyLED k t.inner fallback
/--
Tries to retrieve the smallest key that is less than the given key,
Tries to retrieve the largest key that is less than the given key,
returning `fallback` if no such key exists.
-/
@[inline]

View file

@ -20,11 +20,11 @@ set_option autoImplicit false
open Std.Internal.List
open Std.Internal
universe u v w
universe u v w w'
namespace Std.DTreeMap.Internal.Impl
variable {α : Type u} {β : α → Type v} {instOrd : Ord α} {t : Impl α β}
variable {α : Type u} {β : α → Type v} {γ : α → Type w} {instOrd : Ord α} {t : Impl α β}
private local instance : Coe (Type v) (α → Type v) where coe γ := fun _ => γ
attribute [local instance low] beqOfOrd
@ -41,7 +41,8 @@ macro_rules
| apply WF.erase | apply WF.insertMany
| apply WF.constInsertMany | apply WF.constInsertManyIfNewUnit
| apply WF.alter | apply WF.constAlter
| apply WF.modify | apply WF.constModify) <;> wf_trivial)
| apply WF.modify | apply WF.constModify
| apply WF.filterMap | apply WF.filter | apply WF.map) <;> wf_trivial)
/-- Internal implementation detail of the tree map -/
scoped macro "empty" : tactic => `(tactic| { intros; simp_all [List.isEmpty_iff] } )
@ -67,7 +68,10 @@ private def modifyMap : Std.HashMap Name Name :=
(`alter, ``toListModel_alter),
(`Const.alter, ``Const.toListModel_alter),
(`modify, ``toListModel_modify),
(`Const.modify, ``Const.toListModel_modify)]
(`Const.modify, ``Const.toListModel_modify),
(`filter, ``toListModel_filter),
(`map, ``toListModel_map),
(`filterMap, ``toListModel_filterMap)]
private def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (TSyntax `term))) :=
.ofList
@ -102,7 +106,22 @@ private def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (TSynta
⟨`maxKey?, (``maxKey?_eq_maxKey?, #[``(maxKey?_of_perm _)])⟩,
⟨`maxKey, (``maxKey_eq_maxKey, #[``(maxKey_of_perm _)])⟩,
⟨`maxKey!, (``maxKey!_eq_maxKey!, #[``(maxKey!_of_perm _)])⟩,
⟨`maxKeyD, (``maxKeyD_eq_maxKeyD, #[``(maxKeyD_of_perm _)])⟩]
⟨`maxKeyD, (``maxKeyD_eq_maxKeyD, #[``(maxKeyD_of_perm _)])⟩,
⟨`minEntry?, (``minEntry?_eq_minEntry?, #[``(minEntry?_of_perm _)])⟩,
⟨`entryAtIdx?, (``entryAtIdx?_eq_getElem?, #[])⟩,
⟨`entryAtIdx, (``entryAtIdx_eq_getElem, #[])⟩,
⟨`entryAtIdx!, (``entryAtIdx!_eq_getElem!, #[])⟩,
⟨`entryAtIdxD, (``entryAtIdxD_eq_getD, #[])⟩,
⟨`Const.entryAtIdx?, (``Const.entryAtIdx?_eq_getElem?, #[])⟩,
⟨`Const.entryAtIdx, (``Const.entryAtIdx_eq_getElem, #[])⟩,
⟨`Const.entryAtIdx!, (``Const.entryAtIdx!_eq_get!_map_getElem?, #[])⟩,
⟨`Const.entryAtIdxD, (``Const.entryAtIdxD_eq_getD_map_getElem?, #[])⟩,
⟨`keyAtIdx?, (``keyAtIdx?_eq_getElem?, #[])⟩,
⟨`keyAtIdx, (``keyAtIdx_eq_getElem_fst, #[])⟩,
⟨`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)])⟩]
/-- Internal implementation detail of the tree map -/
scoped syntax "simp_to_model" (" [" (ident,*) "]")? ("using" term)? : tactic
@ -1663,7 +1682,7 @@ end Const
section monadic
variable {t : Impl α β} {δ : Type w} {m : Type w → Type w}
variable {t : Impl α β} {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m]
{f : δ → (a : α) → β a → m δ} {init : δ} :
@ -6005,4 +6024,795 @@ end Const
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : Impl α β} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (Impl α β) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty := by
simp_to_model [isEmpty] using List.Perm.isEmpty_eq h.1
theorem contains_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.contains k = t₂.contains k := by
simp_to_model [contains] using List.containsKey_of_perm h.1
theorem mem_iff [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
k ∈ t₁ ↔ k ∈ t₂ := by
simp only [mem_iff_contains, Bool.coe_iff_coe, contains_eq h₁ h₂ h]
theorem size_eq (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.size = t₂.size := by
simp_to_model [size] using List.Perm.length_eq h.1
theorem get?_eq [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.get? k = t₂.get? k := by
simp_to_model [get?] using List.getValueCast?_of_perm _ h.1
theorem get_eq [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} (hk : k ∈ t₁) : t₁.get k hk = t₂.get k ((h.mem_iff h₁ h₂).mp hk) := by
simp_to_model [get] using List.getValueCast_of_perm _ h.1
theorem get!_eq [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited (β k)] : t₁.get! k = t₂.get! k := by
simp_to_model [get!] using List.getValueCast!_of_perm _ h.1
theorem getD_eq [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : β k} : t₁.getD k fallback = t₂.getD k fallback := by
simp_to_model [getD] using List.getValueCastD_of_perm _ h.1
theorem getKey?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getKey? k = t₂.getKey? k := by
simp_to_model [getKey?] using List.getKey?_of_perm _ h.1
theorem getKey_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} (hk : k ∈ t₁) : t₁.getKey k hk = t₂.getKey k ((h.mem_iff h₁ h₂).mp hk) := by
simp_to_model [getKey] using List.getKey_of_perm _ h.1
theorem getKey!_eq [TransOrd α] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} : t₁.getKey! k = t₂.getKey! k := by
simp_to_model [getKey!] using List.getKey!_of_perm _ h.1
theorem getKeyD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k fallback : α} : t₁.getKeyD k fallback = t₂.getKeyD k fallback := by
simp_to_model [getKeyD] using List.getKeyD_of_perm _ h.1
theorem toList_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.toList = t₂.toList := by
simp_to_model [toList] using h.toListModel_eq
theorem toArray_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.toArray = t₂.toArray := by
simp only [toArray_eq_toArray, h.toListModel_eq h₁.ordered h₂.ordered]
theorem keys_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.keys = t₂.keys := by
simp_to_model [keys]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem keysArray_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.keysArray = t₂.keysArray := by
simp only [keysArray_eq_toArray_keys, h.toListModel_eq h₁.ordered h₂.ordered]
theorem foldlM_eq [TransOrd α] [Monad m] [LawfulMonad m] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{f : δ → (a : α) → β a → m δ} {init : δ} :
t₁.foldlM f init = t₂.foldlM f init := by
simp_to_model [foldlM]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem foldl_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{f : δ → (a : α) → β a → δ} {init : δ} :
t₁.foldl f init = t₂.foldl f init := by
simp_to_model [foldl]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem foldrM_eq [TransOrd α] [Monad m] [LawfulMonad m] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{f : (a : α) → β a → δ → m δ} {init : δ} :
t₁.foldrM f init = t₂.foldrM f init := by
simp_to_model [foldrM]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem foldr_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{f : (a : α) → β a → δ → δ} {init : δ} :
t₁.foldr f init = t₂.foldr f init := by
simp_to_model [foldr]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem forIn_eq [TransOrd α] [Monad m] [LawfulMonad m] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{f : (a : α) → β a → δ → m (ForInStep δ)} {init : δ} :
t₁.forIn f init = t₂.forIn f init := by
simp_to_model [forIn]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem forM_eq [TransOrd α] [Monad m] [LawfulMonad m] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{f : (a : α) → β a → m PUnit} :
t₁.forM f = t₂.forM f := by
simp_to_model [forM]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem minKey?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKey? = t₂.minKey? := by
simp_to_model [minKey?]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem minKey_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (h' : t₁.isEmpty = false) :
t₁.minKey h' = t₂.minKey (h.isEmpty_eq.symm.trans h') := by
simp_to_model [minKey]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem minKey!_eq [TransOrd α] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKey! = t₂.minKey! := by
simp_to_model [minKey!]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem minKeyD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {fallback : α} :
t₁.minKeyD fallback = t₂.minKeyD fallback := by
simp_to_model [minKeyD]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem maxKey?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKey? = t₂.maxKey? := by
simp_to_model [maxKey?]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem maxKey_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (h' : t₁.isEmpty = false) :
t₁.maxKey h' = t₂.maxKey (h.isEmpty_eq.symm.trans h') := by
simp_to_model [maxKey]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem maxKey!_eq [TransOrd α] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKey! = t₂.maxKey! := by
simp_to_model [maxKey!]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem maxKeyD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {fallback : α} :
t₁.maxKeyD fallback = t₂.maxKeyD fallback := by
simp_to_model [maxKeyD]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem minEntry?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minEntry? = t₂.minEntry? := by
simp_to_model [minEntry?]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem minEntry_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {he} :
t₁.minEntry he = t₂.minEntry (h.isEmpty_eq.symm.trans he) := by
simp only [minEntry_eq_get_minEntry?, h.minEntry?_eq h₁ h₂]
theorem minEntry!_eq [TransOrd α] [Inhabited ((a : α) × β a)]
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.minEntry! = t₂.minEntry! := by
simp only [minEntry!_eq_get!_minEntry?, h.minEntry?_eq h₁ h₂]
theorem minEntryD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{fallback : (a : α) × β a} : t₁.minEntryD fallback = t₂.minEntryD fallback := by
simp only [minEntryD_eq_getD_minEntry?, h.minEntry?_eq h₁ h₂]
theorem maxEntry?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxEntry? = t₂.maxEntry? := by
simp only [maxEntry?_eq_minEntry?, h₁.ordered, h₂.ordered]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem maxEntry_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {he} :
t₁.maxEntry he = t₂.maxEntry (h.isEmpty_eq.symm.trans he) := by
apply Option.some.inj
simp only [some_maxEntry_eq_maxEntry?, h.maxEntry?_eq h₁ h₂]
theorem maxEntry!_eq [TransOrd α] [Inhabited ((a : α) × β a)]
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.maxEntry! = t₂.maxEntry! := by
simp only [maxEntry!_eq_get!_maxEntry?, h.maxEntry?_eq h₁ h₂]
theorem maxEntryD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{fallback : (a : α) × β a} : t₁.maxEntryD fallback = t₂.maxEntryD fallback := by
simp only [maxEntryD_eq_getD_maxEntry?, h.maxEntry?_eq h₁ h₂]
theorem entryAtIdx?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat} :
t₁.entryAtIdx? i = t₂.entryAtIdx? i := by
simp_to_model [entryAtIdx?]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem entryAtIdx_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat} {h'} :
t₁.entryAtIdx h₁.balanced i h' = t₂.entryAtIdx h₂.balanced i (h.size_eq h₁ h₂ ▸ h') := by
simp_to_model [entryAtIdx]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem entryAtIdx!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat}
[Inhabited ((a : α) × β a)] : t₁.entryAtIdx! i = t₂.entryAtIdx! i := by
simp_to_model [entryAtIdx!]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem entryAtIdxD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat}
{fallback : (a : α) × β a} : t₁.entryAtIdxD i fallback = t₂.entryAtIdxD i fallback := by
simp_to_model [entryAtIdxD]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem keyAtIdx?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat} :
t₁.keyAtIdx? i = t₂.keyAtIdx? i := by
simp_to_model [keyAtIdx?]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem keyAtIdx_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat} {h'} :
t₁.keyAtIdx h₁.balanced i h' = t₂.keyAtIdx h₂.balanced i (h.size_eq h₁ h₂ ▸ h') := by
simp_to_model [keyAtIdx]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem keyAtIdx!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat}
[Inhabited α] : t₁.keyAtIdx! i = t₂.keyAtIdx! i := by
simp_to_model [keyAtIdx!]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem keyAtIdxD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat}
{fallback : α} : t₁.keyAtIdxD i fallback = t₂.keyAtIdxD i fallback := by
simp_to_model [keyAtIdxD]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem getEntryGE?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getEntryGE? k = t₂.getEntryGE? k := by
simp only [getEntryGE?_eq_find?, h₁.ordered, h₂.ordered]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem getEntryGE_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getEntryGE k h₁.ordered he = t₂.getEntryGE k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
apply Option.some.inj
simp only [some_getEntryGE_eq_getEntryGE?, h.getEntryGE?_eq h₁ h₂]
theorem getEntryGE!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited ((a : α) × β a)] : t₁.getEntryGE! k = t₂.getEntryGE! k := by
simp only [getEntryGE!_eq_get!_getEntryGE?, h.getEntryGE?_eq h₁ h₂]
theorem getEntryGED_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : (a : α) × β a} : t₁.getEntryGED k fallback = t₂.getEntryGED k fallback := by
simp only [getEntryGED_eq_getD_getEntryGE?, h.getEntryGE?_eq h₁ h₂]
theorem getEntryGT?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getEntryGT? k = t₂.getEntryGT? k := by
simp only [getEntryGT?_eq_find?, h₁.ordered, h₂.ordered]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem getEntryGT_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getEntryGT k h₁.ordered he = t₂.getEntryGT k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
apply Option.some.inj
simp only [some_getEntryGT_eq_getEntryGT?, h.getEntryGT?_eq h₁ h₂]
theorem getEntryGT!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited ((a : α) × β a)] : t₁.getEntryGT! k = t₂.getEntryGT! k := by
simp only [getEntryGT!_eq_get!_getEntryGT?, h.getEntryGT?_eq h₁ h₂]
theorem getEntryGTD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : (a : α) × β a} : t₁.getEntryGTD k fallback = t₂.getEntryGTD k fallback := by
simp only [getEntryGTD_eq_getD_getEntryGT?, h.getEntryGT?_eq h₁ h₂]
theorem getEntryLE?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getEntryLE? k = t₂.getEntryLE? k := by
simp only [getEntryLE?_eq_findRev?, h₁.ordered, h₂.ordered]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem getEntryLE_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getEntryLE k h₁.ordered he = t₂.getEntryLE k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
apply Option.some.inj
simp only [some_getEntryLE_eq_getEntryLE?, h.getEntryLE?_eq h₁ h₂]
theorem getEntryLE!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited ((a : α) × β a)] : t₁.getEntryLE! k = t₂.getEntryLE! k := by
simp only [getEntryLE!_eq_get!_getEntryLE?, h.getEntryLE?_eq h₁ h₂]
theorem getEntryLED_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : (a : α) × β a} : t₁.getEntryLED k fallback = t₂.getEntryLED k fallback := by
simp only [getEntryLED_eq_getD_getEntryLE?, h.getEntryLE?_eq h₁ h₂]
theorem getEntryLT?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getEntryLT? k = t₂.getEntryLT? k := by
simp only [getEntryLT?_eq_findRev?, h₁.ordered, h₂.ordered]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem getEntryLT_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getEntryLT k h₁.ordered he = t₂.getEntryLT k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
apply Option.some.inj
simp only [some_getEntryLT_eq_getEntryLT?, h.getEntryLT?_eq h₁ h₂]
theorem getEntryLT!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited ((a : α) × β a)] : t₁.getEntryLT! k = t₂.getEntryLT! k := by
simp only [getEntryLT!_eq_get!_getEntryLT?, h.getEntryLT?_eq h₁ h₂]
theorem getEntryLTD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : (a : α) × β a} : t₁.getEntryLTD k fallback = t₂.getEntryLTD k fallback := by
simp only [getEntryLTD_eq_getD_getEntryLT?, h.getEntryLT?_eq h₁ h₂]
theorem getKeyGE?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getKeyGE? k = t₂.getKeyGE? k := by
simp only [getKeyGE?_eq_getEntryGE?, h.getEntryGE?_eq h₁ h₂]
theorem getKeyGE_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getKeyGE k h₁.ordered he = t₂.getKeyGE k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [getKeyGE_eq_getEntryGE, h.getEntryGE_eq h₁ h₂]
theorem getKeyGE!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited α] : t₁.getKeyGE! k = t₂.getKeyGE! k := by
simp only [getKeyGE!_eq_get!_getKeyGE?, h.getKeyGE?_eq h₁ h₂]
theorem getKeyGED_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k fallback : α} : t₁.getKeyGED k fallback = t₂.getKeyGED k fallback := by
simp only [getKeyGED_eq_getD_getKeyGE?, h.getKeyGE?_eq h₁ h₂]
theorem getKeyGT?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getKeyGT? k = t₂.getKeyGT? k := by
simp only [getKeyGT?_eq_getEntryGT?, h.getEntryGT?_eq h₁ h₂]
theorem getKeyGT_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getKeyGT k h₁.ordered he = t₂.getKeyGT k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [getKeyGT_eq_getEntryGT, h.getEntryGT_eq h₁ h₂]
theorem getKeyGT!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited α] : t₁.getKeyGT! k = t₂.getKeyGT! k := by
simp only [getKeyGT!_eq_get!_getKeyGT?, h.getKeyGT?_eq h₁ h₂]
theorem getKeyGTD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k fallback : α} : t₁.getKeyGTD k fallback = t₂.getKeyGTD k fallback := by
simp only [getKeyGTD_eq_getD_getKeyGT?, h.getKeyGT?_eq h₁ h₂]
theorem getKeyLE?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getKeyLE? k = t₂.getKeyLE? k := by
simp only [getKeyLE?_eq_getEntryLE?, h.getEntryLE?_eq h₁ h₂]
theorem getKeyLE_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getKeyLE k h₁.ordered he = t₂.getKeyLE k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [getKeyLE_eq_getEntryLE, h.getEntryLE_eq h₁ h₂]
theorem getKeyLE!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited α] : t₁.getKeyLE! k = t₂.getKeyLE! k := by
simp only [getKeyLE!_eq_get!_getKeyLE?, h.getKeyLE?_eq h₁ h₂]
theorem getKeyLED_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k fallback : α} : t₁.getKeyLED k fallback = t₂.getKeyLED k fallback := by
simp only [getKeyLED_eq_getD_getKeyLE?, h.getKeyLE?_eq h₁ h₂]
theorem getKeyLT?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
t₁.getKeyLT? k = t₂.getKeyLT? k := by
simp only [getKeyLT?_eq_getEntryLT?, h.getEntryLT?_eq h₁ h₂]
theorem getKeyLT_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
t₁.getKeyLT k h₁.ordered he = t₂.getKeyLT k h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [getKeyLT_eq_getEntryLT, h.getEntryLT_eq h₁ h₂]
theorem getKeyLT!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited α] : t₁.getKeyLT! k = t₂.getKeyLT! k := by
simp only [getKeyLT!_eq_get!_getKeyLT?, h.getKeyLT?_eq h₁ h₂]
theorem getKeyLTD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k fallback : α} : t₁.getKeyLTD k fallback = t₂.getKeyLTD k fallback := by
simp only [getKeyLTD_eq_getD_getKeyLT?, h.getKeyLT?_eq h₁ h₂]
theorem insert [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {v : β k} : (t₁.insert k v h₁.balanced).impl ~m (t₂.insert k v h₂.balanced).impl := by
simp_to_model [insert, Equiv] using List.insertEntry_of_perm _ h.1
theorem insert! [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {v : β k} : t₁.insert! k v ~m t₂.insert! k v := by
simpa only [insert_eq_insert!] using h.insert h₁ h₂
theorem erase [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} : (t₁.erase k h₁.balanced).impl ~m (t₂.erase k h₂.balanced).impl := by
simp_to_model [erase, Equiv] using List.eraseKey_of_perm _ h.1
theorem erase! [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} : t₁.erase! k ~m t₂.erase! k := by
simpa only [erase_eq_erase!] using h.erase h₁ h₂
theorem insertIfNew [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {v : β k} : (t₁.insertIfNew k v h₁.balanced).impl ~m (t₂.insertIfNew k v h₂.balanced).impl := by
simp_to_model [insertIfNew, Equiv] using List.insertEntryIfNew_of_perm _ h.1
theorem insertIfNew! [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {v : β k} : t₁.insertIfNew! k v ~m t₂.insertIfNew! k v := by
simpa only [insertIfNew_eq_insertIfNew!] using h.insertIfNew h₁ h₂
theorem alter [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {f : Option (β k) → Option (β k)} :
(t₁.alter k f h₁.balanced).impl ~m (t₂.alter k f h₂.balanced).impl := by
simp_to_model [alter, Equiv] using List.alterKey_of_perm _ h.1
theorem alter! [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {f : Option (β k) → Option (β k)} :
t₁.alter! k f ~m t₂.alter! k f := by
simpa only [alter_eq_alter!] using h.alter h₁ h₂
theorem modify [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {f : β k → β k} : t₁.modify k f ~m t₂.modify k f := by
simp_to_model [modify, Equiv] using List.modifyKey_of_perm _ h.1
theorem filter (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {f : (a : α) → β a → Bool} :
(t₁.filter f h₁.balanced).impl ~m (t₂.filter f h₂.balanced).impl := by
simpa only [equiv_iff_toListModel_perm, toListModel_filter] using h.impl.filter _
theorem filter! (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {f : (a : α) → β a → Bool} :
t₁.filter! f ~m t₂.filter! f := by
simpa only [filter_eq_filter!] using h.filter h₁ h₂
theorem map (h : t₁ ~m t₂) {f : (a : α) → β a → γ a} : t₁.map f ~m t₂.map f := by
simpa only [equiv_iff_toListModel_perm, toListModel_map] using h.impl.map _
theorem filterMap (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {f : (a : α) → β a → Option (γ a)} :
(t₁.filterMap f h₁.balanced).impl ~m (t₂.filterMap f h₂.balanced).impl := by
simpa only [equiv_iff_toListModel_perm, toListModel_filterMap] using h.impl.filterMap _
theorem filterMap! (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {f : (a : α) → β a → Option (γ a)} :
t₁.filterMap! f ~m t₂.filterMap! f := by
simpa only [filterMap_eq_filterMap!] using h.filterMap h₁ h₂
theorem insertMany_list [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{l : List ((a : α) × β a)} :
(t₁.insertMany l h₁.balanced).1 ~m (t₂.insertMany l h₂.balanced).1 := by
simp only [insertMany_eq_foldl]
refine (List.foldl_rel (r := fun a b : Impl α β => a.WF ∧ b.WF ∧ a ~m b) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
refine ⟨hc.1.insert!, hc.2.1.insert!, hc.2.2.insert! hc.1 hc.2.1⟩
theorem insertMany!_list [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{l : List ((a : α) × β a)} :
(t₁.insertMany! l).1 ~m (t₂.insertMany! l).1 := by
simpa only [insertMany_eq_insertMany!] using h.insertMany_list h₁ h₂
theorem eraseMany_list [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{l : List α} :
(t₁.eraseMany l h₁.balanced).1 ~m (t₂.eraseMany l h₂.balanced).1 := by
simp only [eraseMany, bind_pure_comp, map_pure, List.forIn_pure_yield_eq_foldl, bind_pure,
Id.run_pure]
refine (List.foldl_rel (r := fun (a : t₁.IteratedErasureFrom) (b : t₂.IteratedErasureFrom) =>
a.1.WF ∧ b.1.WF ∧ a.1 ~m b.1) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
refine ⟨hc.1.erase, hc.2.1.erase, hc.2.2.erase hc.1 hc.2.1⟩
theorem eraseMany!_list [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{l : List α} :
(t₁.eraseMany! l).1 ~m (t₂.eraseMany! l).1 := by
simp only [eraseMany!, bind_pure_comp, map_pure, List.forIn_pure_yield_eq_foldl, bind_pure,
Id.run_pure]
refine (List.foldl_rel (r := fun (a : t₁.IteratedSlowErasureFrom) (b : t₂.IteratedSlowErasureFrom) =>
a.1.WF ∧ b.1.WF ∧ a.1 ~m b.1) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
refine ⟨hc.1.erase!, hc.2.1.erase!, hc.2.2.erase! hc.1 hc.2.1⟩
theorem mergeWith [TransOrd α] [LawfulEqOrd α]
(h : t₁ ~m t₂) (h' : t₃ ~m t₄)
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
{f : (a : α) → β a → β a → β a} :
(t₁.mergeWith f t₃ h₁.balanced).impl ~m (t₂.mergeWith f t₄ h₂.balanced).impl := by
simp only [Impl.mergeWith, h'.foldl_eq h₃ h₄, foldl_eq_foldl]
refine (List.foldl_rel (r := fun a b : BalancedTree α β =>
a.impl.WF ∧ b.impl.WF ∧ a.impl ~m b.impl) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
exact ⟨hc.1.alter, hc.2.1.alter, hc.2.2.alter hc.1 hc.2.1⟩
theorem mergeWith! [TransOrd α] [LawfulEqOrd α]
(h : t₁ ~m t₂) (h' : t₃ ~m t₄)
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
{f : (a : α) → β a → β a → β a} :
t₁.mergeWith! f t₃ ~m t₂.mergeWith! f t₄ := by
simpa only [mergeWith_eq_mergeWith!] using h.mergeWith h' h₁ h₂ h₃ h₄
section Const
variable {β : Type v} {t₁ t₂ t₃ t₄ : Impl α β} {δ : Type w} {m : Type w → Type w}
theorem constGet?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
Const.get? t₁ k = Const.get? t₂ k := by
simp_to_model [Const.get?] using List.getValue?_of_perm _ h.1
theorem constGet_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} (hk : k ∈ t₁) : Const.get t₁ k hk = Const.get t₂ k ((h.mem_iff h₁ h₂).mp hk) := by
simp_to_model [Const.get] using List.getValue_of_perm _ h.1
theorem constGet!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited β] : Const.get! t₁ k = Const.get! t₂ k := by
simp_to_model [Const.get!] using List.getValue!_of_perm _ h.1
theorem constGetD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : β} : Const.getD t₁ k fallback = Const.getD t₂ k fallback := by
simp_to_model [Const.getD] using List.getValueD_of_perm _ h.1
theorem constToList_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.toList t₁ = Const.toList t₂ := by
simp_to_model [Const.toList] using congrArg _ (h.toListModel_eq ..)
theorem constToArray_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.toArray t₁ = Const.toArray t₂ := by
simp only [Const.toArray_eq_toArray_map, h.toListModel_eq h₁.ordered h₂.ordered]
theorem values_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.values = t₂.values := by
simp only [values_eq_map_snd, h.toListModel_eq h₁.ordered h₂.ordered]
theorem valuesArray_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.valuesArray = t₂.valuesArray := by
simp only [valuesArray_eq_toArray_map, h.toListModel_eq h₁.ordered h₂.ordered]
theorem constMinEntry?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.minEntry? t₁ = Const.minEntry? t₂ := by
simp only [Const.minEntry?_eq_minEntry?, h.minEntry?_eq h₁ h₂]
theorem constMinEntry_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {he} :
Const.minEntry t₁ he = Const.minEntry t₂ (h.isEmpty_eq.symm.trans he) := by
apply Option.some.inj
simp only [Const.some_minEntry_eq_minEntry?, h.constMinEntry?_eq h₁ h₂]
theorem constMinEntry!_eq [TransOrd α] [Inhabited (α × β)]
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : Const.minEntry! t₁ = Const.minEntry! t₂ := by
simp only [Const.minEntry!_eq_get!_minEntry?, h.constMinEntry?_eq h₁ h₂]
theorem constMinEntryD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{fallback : α × β} : Const.minEntryD t₁ fallback = Const.minEntryD t₂ fallback := by
simp only [Const.minEntryD_eq_getD_minEntry?, h.constMinEntry?_eq h₁ h₂]
theorem constMaxEntry?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.maxEntry? t₁ = Const.maxEntry? t₂ := by
simp only [Const.maxEntry?_eq_maxEntry?, h.maxEntry?_eq h₁ h₂]
theorem constMaxEntry_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {he} :
Const.maxEntry t₁ he = Const.maxEntry t₂ (h.isEmpty_eq.symm.trans he) := by
apply Option.some.inj
simp only [Const.some_maxEntry_eq_maxEntry?, h.constMaxEntry?_eq h₁ h₂]
theorem constMaxEntry!_eq [TransOrd α] [Inhabited (α × β)]
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : Const.maxEntry! t₁ = Const.maxEntry! t₂ := by
simp only [Const.maxEntry!_eq_get!_maxEntry?, h.constMaxEntry?_eq h₁ h₂]
theorem constMaxEntryD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{fallback : α × β} : Const.maxEntryD t₁ fallback = Const.maxEntryD t₂ fallback := by
simp only [Const.maxEntryD_eq_getD_maxEntry?, h.constMaxEntry?_eq h₁ h₂]
theorem constEntryAtIdx?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat} :
Const.entryAtIdx? t₁ i = Const.entryAtIdx? t₂ i := by
simp_to_model [Const.entryAtIdx?]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem constEntryAtIdx_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat} {h'} :
Const.entryAtIdx t₁ h₁.balanced i h' = Const.entryAtIdx t₂ h₂.balanced i (h.size_eq h₁ h₂ ▸ h') := by
simp_to_model [Const.entryAtIdx]
simp only [h.toListModel_eq h₁.ordered h₂.ordered]
theorem constEntryAtIdx!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat}
[Inhabited (α × β)] : Const.entryAtIdx! t₁ i = Const.entryAtIdx! t₂ i := by
simp_to_model [Const.entryAtIdx!]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem constEntryAtIdxD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {i : Nat}
{fallback : α × β} : Const.entryAtIdxD t₁ i fallback = Const.entryAtIdxD t₂ i fallback := by
simp_to_model [Const.entryAtIdxD]
rw [h.toListModel_eq h₁.ordered h₂.ordered]
theorem constGetEntryGE?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
Const.getEntryGE? k t₁ = Const.getEntryGE? k t₂ := by
simp only [Const.getEntryGE?_eq_map, h.getEntryGE?_eq h₁ h₂]
theorem constGetEntryGE_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
Const.getEntryGE k t₁ h₁.ordered he = Const.getEntryGE k t₂ h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [Const.getEntryGE_eq, h.getEntryGE_eq h₁ h₂]
theorem constGetEntryGE!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited (α × β)] : Const.getEntryGE! k t₁ = Const.getEntryGE! k t₂ := by
simp only [Const.getEntryGE!_eq_get!_getEntryGE?, h.constGetEntryGE?_eq h₁ h₂]
theorem constGetEntryGED_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {fallback : α × β} : Const.getEntryGED k t₁ fallback = Const.getEntryGED k t₂ fallback := by
simp only [Const.getEntryGED_eq_getD_getEntryGE?, h.constGetEntryGE?_eq h₁ h₂]
theorem constGetEntryGT?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
Const.getEntryGT? k t₁ = Const.getEntryGT? k t₂ := by
simp only [Const.getEntryGT?_eq_map, h.getEntryGT?_eq h₁ h₂]
theorem constGetEntryGT_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
Const.getEntryGT k t₁ h₁.ordered he = Const.getEntryGT k t₂ h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [Const.getEntryGT_eq, h.getEntryGT_eq h₁ h₂]
theorem constGetEntryGT!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited (α × β)] : Const.getEntryGT! k t₁ = Const.getEntryGT! k t₂ := by
simp only [Const.getEntryGT!_eq_get!_getEntryGT?, h.constGetEntryGT?_eq h₁ h₂]
theorem constGetEntryGTD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α}
{fallback : α × β} : Const.getEntryGTD k t₁ fallback = Const.getEntryGTD k t₂ fallback := by
simp only [Const.getEntryGTD_eq_getD_getEntryGT?, h.constGetEntryGT?_eq h₁ h₂]
theorem constGetEntryLE?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
Const.getEntryLE? k t₁ = Const.getEntryLE? k t₂ := by
simp only [Const.getEntryLE?_eq_map, h.getEntryLE?_eq h₁ h₂]
theorem constGetEntryLE_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
Const.getEntryLE k t₁ h₁.ordered he = Const.getEntryLE k t₂ h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [Const.getEntryLE_eq, h.getEntryLE_eq h₁ h₂]
theorem constGetEntryLE!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited (α × β)] : Const.getEntryLE! k t₁ = Const.getEntryLE! k t₂ := by
simp only [Const.getEntryLE!_eq_get!_getEntryLE?, h.constGetEntryLE?_eq h₁ h₂]
theorem constGetEntryLED_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α}
{fallback : α × β} : Const.getEntryLED k t₁ fallback = Const.getEntryLED k t₂ fallback := by
simp only [Const.getEntryLED_eq_getD_getEntryLE?, h.constGetEntryLE?_eq h₁ h₂]
theorem constGetEntryLT?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} :
Const.getEntryLT? k t₁ = Const.getEntryLT? k t₂ := by
simp only [Const.getEntryLT?_eq_map, h.getEntryLT?_eq h₁ h₂]
theorem constGetEntryLT_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α} {he} :
Const.getEntryLT k t₁ h₁.ordered he = Const.getEntryLT k t₂ h₂.ordered (by simpa only [← h.mem_iff h₁ h₂]) := by
simp only [Const.getEntryLT_eq, h.getEntryLT_eq h₁ h₂]
theorem constGetEntryLT!_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} [Inhabited (α × β)] : Const.getEntryLT! k t₁ = Const.getEntryLT! k t₂ := by
simp only [Const.getEntryLT!_eq_get!_getEntryLT?, h.constGetEntryLT?_eq h₁ h₂]
theorem constGetEntryLTD_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {k : α}
{fallback : α × β} : Const.getEntryLTD k t₁ fallback = Const.getEntryLTD k t₂ fallback := by
simp only [Const.getEntryLTD_eq_getD_getEntryLT?, h.constGetEntryLT?_eq h₁ h₂]
theorem constAlter [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {f : Option β → Option β} :
(Const.alter k f t₁ h₁.balanced).impl ~m (Const.alter k f t₂ h₂.balanced).impl := by
simp_to_model [Const.alter, Equiv] using List.Const.alterKey_of_perm _ h.1
theorem constAlter! [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {f : Option β → Option β} :
Const.alter! k f t₁ ~m Const.alter! k f t₂ := by
simpa only [Const.alter_eq_alter!] using h.constAlter h₁ h₂
theorem constModify [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{k : α} {f : β → β} : Const.modify k f t₁ ~m Const.modify k f t₂ := by
simp_to_model [Const.modify, Equiv] using List.Const.modifyKey_of_perm _ h.1
theorem constInsertMany_list [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{l : List (α × β)} :
(Const.insertMany t₁ l h₁.balanced).1 ~m (Const.insertMany t₂ l h₂.balanced).1 := by
simp only [Const.insertMany_eq_foldl]
refine (List.foldl_rel (r := fun a b : Impl α β => a.WF ∧ b.WF ∧ a ~m b) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
refine ⟨hc.1.insert!, hc.2.1.insert!, hc.2.2.insert! hc.1 hc.2.1⟩
theorem constInsertMany!_list [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
{l : List (α × β)} :
(Const.insertMany! t₁ l).1 ~m (Const.insertMany! t₂ l).1 := by
simpa only [Const.insertMany_eq_insertMany!] using h.constInsertMany_list h₁ h₂
theorem constInsertManyIfNewUnit_list [TransOrd α] {t₁ t₂ : Impl α Unit}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {l : List α} :
(Const.insertManyIfNewUnit t₁ l h₁.balanced).1 ~m (Const.insertManyIfNewUnit t₂ l h₂.balanced).1 := by
simp only [Const.insertManyIfNewUnit_eq_foldl]
refine (List.foldl_rel (r := fun a b : Impl α Unit => a.WF ∧ b.WF ∧ a ~m b) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
refine ⟨hc.1.insertIfNew!, hc.2.1.insertIfNew!, hc.2.2.insertIfNew! hc.1 hc.2.1⟩
theorem constInsertManyIfNewUnit!_list [TransOrd α] {t₁ t₂ : Impl α Unit}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) {l : List α} :
(Const.insertManyIfNewUnit! t₁ l).1 ~m (Const.insertManyIfNewUnit! t₂ l).1 := by
simpa only [Const.insertManyIfNewUnit_eq_insertManyIfNewUnit!] using h.constInsertManyIfNewUnit_list h₁ h₂
theorem constMergeWith [TransOrd α]
(h : t₁ ~m t₂) (h' : t₃ ~m t₄)
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
{f : α → β → β → β} :
(Const.mergeWith f t₁ t₃ h₁.balanced).impl ~m (Const.mergeWith f t₂ t₄ h₂.balanced).impl := by
simp only [Impl.Const.mergeWith, h'.foldl_eq h₃ h₄, foldl_eq_foldl]
refine (List.foldl_rel (r := fun a b : BalancedTree α β =>
a.impl.WF ∧ b.impl.WF ∧ a.impl ~m b.impl) ⟨h₁, h₂, h⟩ ?_).2.2
intro a ha c c' hc
exact ⟨hc.1.constAlter, hc.2.1.constAlter, hc.2.2.constAlter hc.1 hc.2.1⟩
theorem constMergeWith! [TransOrd α]
(h : t₁ ~m t₂) (h' : t₃ ~m t₄)
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
{f : α → β → β → β} :
Const.mergeWith! f t₁ t₃ ~m Const.mergeWith! f t₂ t₄ := by
simpa only [Const.mergeWith_eq_mergeWith!] using h.constMergeWith h' h₁ h₂ h₃ h₄
end Const
-- extensionalities
theorem of_forall_get?_eq [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) :
(∀ k, t₁.get? k = t₂.get? k) → t₁ ~m t₂ := by
simp_to_model [get?, Equiv] using List.getValueCast?_ext
section Const
variable {β : Type v} {t₁ t₂ : Impl α β}
theorem of_forall_getKey_eq_of_forall_constGet?_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) :
(∀ k hk hk', t₁.getKey k hk = t₂.getKey k hk') →
(∀ k, Const.get? t₁ k = Const.get? t₂ k) → t₁ ~m t₂ := by
simp_to_model [Const.get?, Equiv, getKey, contains] using List.getKey_getValue?_ext
theorem of_forall_constGet?_eq [TransOrd α] [LawfulEqOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) :
(∀ k, Const.get? t₁ k = Const.get? t₂ k) → t₁ ~m t₂ := by
simp_to_model [Const.get?, Equiv]
simpa only [getValue?_eq_getValueCast?] using
List.getValueCast?_ext h₁.ordered.distinctKeys h₂.ordered.distinctKeys
theorem of_forall_getKey?_unit_eq [TransOrd α] {t₁ t₂ : Impl α fun _ => Unit}
(h₁ : t₁.WF) (h₂ : t₂.WF) : (∀ k, t₁.getKey? k = t₂.getKey? k) → t₁ ~m t₂ := by
simp_to_model [getKey?, Equiv] using List.getKey?_ext
theorem of_forall_contains_unit_eq [TransOrd α] [LawfulEqOrd α]
{t₁ t₂ : Impl α fun _ => Unit} (h₁ : t₁.WF) (h₂ : t₂.WF) :
(∀ k, t₁.contains k = t₂.contains k) → t₁ ~m t₂ := by
simp_to_model [contains, Equiv] using List.containsKey_ext
theorem of_forall_mem_unit_iff [TransOrd α] [LawfulEqOrd α]
{t₁ t₂ : Impl α Unit} (h₁ : t₁.WF) (h₂ : t₂.WF) :
(∀ k, k ∈ t₁ ↔ k ∈ t₂) → t₁ ~m t₂ := by
simpa [mem_iff_contains] using of_forall_contains_unit_eq h₁ h₂
end Const
end Equiv
section Equiv
variable {t₁ t₂ : Impl α β}
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty := by
simp [equiv_iff_toListModel_perm, isEmpty_eq_isEmpty]
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
Equiv.comm.trans equiv_empty_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList := by
simp_to_model [toList, Equiv]
theorem Equiv.of_toList_perm : t₁.toList.Perm t₂.toList → t₁ ~m t₂ :=
equiv_iff_toList_perm.mpr
theorem equiv_iff_toList_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
⟨Equiv.toList_eq h₁ h₂, .of_toList_perm ∘ .of_eq⟩
section Const
variable {β : Type v} {t₁ t₂ : Impl α β}
theorem Const.equiv_iff_toList_perm : t₁ ~m t₂ ↔ (Const.toList t₁).Perm (Const.toList t₂) := by
simp_to_model [Const.toList, Equiv]
constructor
· exact List.Perm.map _
· intro h
have := h.map (fun (x, y) => (⟨x, y⟩ : (_ : α) × β))
simpa only [List.map_map, Function.comp_def, List.map_id'] using this
theorem Const.equiv_iff_toList_eq [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ Const.toList t₁ = Const.toList t₂ := by
simp_to_model [Const.toList]
rw [List.map_inj_right fun _ _ => congrArg fun x : α × β => (⟨x.1, x.2⟩ : (_ : α) × β)]
exact ⟨(·.toListModel_eq h₁.ordered h₂.ordered), .mk ∘ .of_eq⟩
theorem Const.equiv_iff_keys_perm {t₁ t₂ : Impl α Unit} :
t₁ ~m t₂ ↔ t₁.keys.Perm t₂.keys := by
simp_to_model [keys, Equiv]
simp only [List.keys_eq_map]
constructor
· exact List.Perm.map _
· intro h
have := h.map (fun x => (⟨x, ()⟩ : (_ : α) × Unit))
simpa only [List.map_map, Function.comp_def, List.map_id'] using this
theorem Const.equiv_iff_keys_eq {t₁ t₂ : Impl α Unit} [TransOrd α] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.keys = t₂.keys := by
simp_to_model [keys]
simp only [List.keys_eq_map]
rw [List.map_inj_right fun _ _ => congrArg fun x : α => (⟨x, ()⟩ : (_ : α) × Unit)]
exact ⟨(·.toListModel_eq h₁.ordered h₂.ordered), .mk ∘ .of_eq⟩
end Const
end Equiv
end Std.DTreeMap.Internal.Impl

View file

@ -116,6 +116,100 @@ def explore {γ : Type w} [Ord α] (k : α → Ordering) (init : γ)
| .eq => inner init <| .eq l.toListModel (Cell.ofEq ky y h) r.toListModel
| .gt => explore k (inner init <| .gt l.toListModel ky h y) inner r
/-
Note: these congruence lemmas are proven manually because `simp` currently can't handle
matches with hypotheses on discriminants properly.
-/
@[congr]
theorem applyPartition.go.match_1.congr {α : Sort u} {o o' : Ordering}
{lt : o = .lt → α} {eq : o = .eq → α} {gt : o = .gt → α}
{lt' : o' = .lt → α} {eq' : o' = .eq → α} {gt' : o' = .gt → α}
(ho : o = o')
(hlt : ∀ h, lt (ho.trans h) = lt' h)
(heq : ∀ h, eq (ho.trans h) = eq' h)
(hgt : ∀ h, gt (ho.trans h) = gt' h) :
(match (generalizing := false) h : o with | .lt => lt h | .eq => eq h | .gt => gt h) =
(match (generalizing := false) h : o' with | .lt => lt' h | .eq => eq' h | .gt => gt' h) := by
induction ho; induction funext hlt; induction funext heq; induction funext hgt
rfl
@[congr]
theorem entryAtIdx.match_1.congr {α : Sort u} {o o' : Ordering}
{lt : o = .lt → α} {eq : o = .eq → α} {gt : o = .gt → α}
{lt' : o' = .lt → α} {eq' : o' = .eq → α} {gt' : o' = .gt → α}
(ho : o = o')
(hlt : ∀ h, lt (ho.trans h) = lt' h)
(heq : ∀ h, eq (ho.trans h) = eq' h)
(hgt : ∀ h, gt (ho.trans h) = gt' h) :
entryAtIdx.match_1 (fun _ => α) o lt eq gt = entryAtIdx.match_1 (fun _ => α) o' lt' eq' gt' := by
induction ho; induction funext hlt; induction funext heq; induction funext hgt
rfl
@[congr]
theorem getEntryLE.match_1.congr {α : Sort u} {o o' : Ordering}
{lt : o = .lt → α} {eq : o = .eq → α} {gt : o = .gt → α}
{lt' : o' = .lt → α} {eq' : o' = .eq → α} {gt' : o' = .gt → α}
(ho : o = o')
(hlt : ∀ h, lt (ho.trans h) = lt' h)
(heq : ∀ h, eq (ho.trans h) = eq' h)
(hgt : ∀ h, gt (ho.trans h) = gt' h) :
getEntryLE.match_1 (fun _ => α) o gt eq lt = getEntryLE.match_1 (fun _ => α) o' gt' eq' lt' := by
induction ho; induction funext hlt; induction funext heq; induction funext hgt
rfl
@[congr]
theorem get?.match_1.congr {α : Sort u} {o o' : Ordering}
{lt : o = .lt → α} {eq : o = .eq → α} {gt : o = .gt → α}
{lt' : o' = .lt → α} {eq' : o' = .eq → α} {gt' : o' = .gt → α}
(ho : o = o')
(hlt : ∀ h, lt (ho.trans h) = lt' h)
(heq : ∀ h, eq (ho.trans h) = eq' h)
(hgt : ∀ h, gt (ho.trans h) = gt' h) :
get?.match_1 (fun _ => α) o lt gt eq = get?.match_1 (fun _ => α) o' lt' gt' eq' := by
induction ho; induction funext hlt; induction funext heq; induction funext hgt
rfl
/--
Induction principle on `Impl` with an additional case split on `k ky` for
`Impl.inner _ ky _ _ _` without generalization.
-/
@[elab_as_elim]
theorem tree_split_ind_no_gen [Ord α] (k : α → Ordering)
{motive : (l : Impl α β) → Prop}
(leaf : motive .leaf)
(lt : ∀ n ky y l r, (h : k ky = .lt) →
motive l → motive (.inner n ky y l r))
(eq : ∀ n ky y l r, (h : k ky = .eq) →
motive l → motive r → motive (.inner n ky y l r))
(gt : ∀ n ky y l r, (h : k ky = .gt) →
motive r → motive (.inner n ky y l r))
(t : Impl α β) : motive t := by
induction t with
| leaf => exact leaf
| inner n ky v l r ih ih' =>
cases h : k ky
· exact lt n ky v l r h ih
· exact eq n ky v l r h ih ih'
· exact gt n ky v l r h ih'
/--
Induction principle on `Impl` with an additional case split on `k ky` for
`Impl.inner _ ky _ _ _` and a generalization built in for convenience.
-/
@[elab_as_elim]
theorem tree_split_ind {γ : Sort w} [Ord α] (k : α → Ordering)
{motive : (l : Impl α β) → γ → Prop}
(leaf : ∀ x, motive .leaf x)
(lt : ∀ n ky y l r, (h : k ky = .lt) →
(∀ x, motive l x) → ∀ x, motive (.inner n ky y l r) x)
(eq : ∀ n ky y l r, (h : k ky = .eq) →
(∀ x, motive l x) → (∀ x, motive r x) → ∀ x, motive (.inner n ky y l r) x)
(gt : ∀ n ky y l r, (h : k ky = .gt) →
(∀ x, motive r x) → ∀ x, motive (.inner n ky y l r) x)
(t : Impl α β) : (x : γ) → motive t x :=
tree_split_ind_no_gen k leaf lt eq gt t
open ExplorationStep
theorem applyPartition_go_step [Ord α] {k : α → Ordering} {init : δ} (l₁ l₂) (l l' : Impl α β) (h)
@ -376,7 +470,7 @@ theorem contains_eq_containsₘ [Ord α] (k : α) (l : Impl α β) :
simp only [containsₘ]
induction l
· simp only [contains, applyCell]
split <;> split <;> simp_all
split <;> simp_all
· simp [contains, applyCell]
theorem get?_eq_get?ₘ [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) (l : Impl α β) :
@ -384,15 +478,14 @@ theorem get?_eq_get?ₘ [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) (l :
simp only [get?ₘ]
induction l
· simp only [applyCell, get?]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.get?, Cell.ofEq]
split <;> simp_all [Cell.get?, Cell.ofEq]
· simp [get?, applyCell]
theorem get_eq_get? [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) (l : Impl α β) {h} :
some (l.get k h) = l.get? k := by
induction l
· simp only [applyCell, get, get?]
split <;> rename_i ihl ihr hcmp <;> simp_all
split <;> simp_all
· contradiction
theorem get_eq_getₘ [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) (l : Impl α β) {h} (h') :
@ -405,8 +498,7 @@ theorem get!_eq_get!ₘ [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) [Inh
simp only [get!ₘ, get?ₘ]
induction l
· simp only [applyCell, get!]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.get?, Cell.ofEq]
split <;> simp_all [Cell.get?, Cell.ofEq]
· simp only [get!, applyCell, Cell.get?_empty, Option.get!_none]; rfl
theorem getD_eq_getDₘ [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) (l : Impl α β)
@ -414,8 +506,7 @@ theorem getD_eq_getDₘ [Ord α] [OrientedOrd α] [LawfulEqOrd α] (k : α) (l :
simp only [getDₘ, get?ₘ]
induction l
· simp only [applyCell, getD]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.get?, Cell.ofEq]
split <;> simp_all [Cell.get?, Cell.ofEq]
· simp only [getD, applyCell, Cell.get?_empty, Option.getD_none]
theorem getKey?_eq_getKey?ₘ [Ord α] (k : α) (l : Impl α β) :
@ -423,15 +514,14 @@ theorem getKey?_eq_getKey?ₘ [Ord α] (k : α) (l : Impl α β) :
simp only [getKey?ₘ]
induction l
· simp only [applyCell, getKey?]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.getKey?, Cell.ofEq]
split <;> simp_all [Cell.getKey?, Cell.ofEq]
· simp [getKey?, applyCell]
theorem getKey_eq_getKey? [Ord α] (k : α) (l : Impl α β) {h} :
some (l.getKey k h) = l.getKey? k := by
induction l
· simp only [applyCell, getKey, getKey?]
split <;> rename_i ihl ihr hcmp <;> simp_all
split <;> simp_all
· contradiction
theorem getKey_eq_getKeyₘ [Ord α] (k : α) (l : Impl α β) {h} (h') :
@ -444,8 +534,7 @@ theorem getKey!_eq_getKey!ₘ [Ord α] (k : α) [Inhabited α] (l : Impl α β)
simp only [getKey!ₘ, getKey?ₘ]
induction l
· simp only [applyCell, getKey!]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.getKey?, Cell.ofEq]
split <;> simp_all [Cell.getKey?, Cell.ofEq]
· simp only [getKey!, applyCell, Cell.getKey?_empty, Option.get!_none]; rfl
theorem getKeyD_eq_getKeyDₘ [Ord α] (k : α) (l : Impl α β)
@ -453,8 +542,7 @@ theorem getKeyD_eq_getKeyDₘ [Ord α] (k : α) (l : Impl α β)
simp only [getKeyDₘ, getKey?ₘ]
induction l
· simp only [applyCell, getKeyD]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.getKey?, Cell.ofEq]
split <;> simp_all [Cell.getKey?, Cell.ofEq]
· simp only [getKeyD, applyCell, Cell.getKey?_empty, Option.getD_none]
theorem minEntry?_eq_minEntry?ₘ' [Ord α] {l : Impl α β} : l.minEntry? = l.minEntry?ₘ' := by
@ -467,47 +555,105 @@ theorem minEntry?ₘ'_eq_minEntry?ₘ [Ord α] {l : Impl α β} : l.minEntry?ₘ
theorem minEntry?_eq_minEntry?ₘ [Ord α] {l : Impl α β} : l.minEntry? = l.minEntry?ₘ := by
rw [minEntry?_eq_minEntry?ₘ', minEntry?ₘ'_eq_minEntry?ₘ]
theorem minKey?_eq_minEntry?_map_fst [Ord α] {l : Impl α β} : l.minKey? = l.minEntry?.map Sigma.fst := by
induction l using minKey?.induct <;> simp only [minKey?, minEntry?] <;> trivial
theorem minEntry!_eq_get!_minEntry? [Inhabited ((a : α) × β a)] {l : Impl α β} :
l.minEntry! = l.minEntry?.get! := by
induction l using minEntry?.induct_unfolding <;> simp only [minEntry!] <;> trivial
theorem some_minEntry_eq_minEntry? [Ord α] {l : Impl α β} {he} :
theorem minEntryD_eq_getD_minEntry? {l : Impl α β} {fallback : (a : α) × β a} :
l.minEntryD fallback = l.minEntry?.getD fallback := by
induction l using minEntry?.induct_unfolding <;> simp only [minEntryD] <;> trivial
theorem some_minEntry_eq_minEntry? {l : Impl α β} {he} :
some (l.minEntry he) = l.minEntry? := by
induction l, he using minEntry.induct <;> simp_all [minEntry, minEntry?]
induction l, he using minEntry.induct_unfolding <;> simp only [minEntry?] <;> assumption
theorem minEntry_eq_get_minEntry? [Ord α] {l : Impl α β} {he} :
theorem minEntry_eq_get_minEntry? {l : Impl α β} {he} :
l.minEntry he = l.minEntry?.get (by simp [← some_minEntry_eq_minEntry? (he := he)]) := by
simp [← some_minEntry_eq_minEntry? (he := he)]
theorem minKey_eq_minEntry_fst [Ord α] {l : Impl α β} {he} : l.minKey he = (l.minEntry he).fst := by
induction l, he using minKey.induct <;> simp only [minKey, minEntry] <;> trivial
theorem maxEntry?_eq_minEntry?_reverse {l : Impl α β} : l.maxEntry? = l.reverse.minEntry? := by
induction l using maxEntry?.induct_unfolding <;> simp only [minEntry?, reverse] <;> assumption
theorem minKey!_eq_get!_minKey? [Ord α] [Inhabited α] {l : Impl α β} :
theorem maxEntry!_eq_get!_maxEntry? [Inhabited ((a : α) × β a)] {l : Impl α β} :
l.maxEntry! = l.maxEntry?.get! := by
induction l using maxEntry?.induct_unfolding <;> simp only [maxEntry!] <;> trivial
theorem maxEntryD_eq_getD_maxEntry? {l : Impl α β} {fallback : (a : α) × β a} :
l.maxEntryD fallback = l.maxEntry?.getD fallback := by
induction l using maxEntry?.induct_unfolding <;> simp only [maxEntryD] <;> trivial
theorem some_maxEntry_eq_maxEntry? {l : Impl α β} {he} : some (l.maxEntry he) = l.maxEntry? := by
induction l, he using maxEntry.induct_unfolding <;> simp only [maxEntry?] <;> assumption
theorem minKey?_eq_minEntry?_map_fst {l : Impl α β} : l.minKey? = l.minEntry?.map Sigma.fst := by
induction l using minKey?.induct_unfolding <;> simp only [minEntry?] <;> trivial
theorem minKey_eq_minEntry_fst {l : Impl α β} {he} : l.minKey he = (l.minEntry he).fst := by
induction l, he using minKey.induct_unfolding <;> simp only [minEntry] <;> trivial
theorem minKey!_eq_get!_minKey? [Inhabited α] {l : Impl α β} :
l.minKey! = l.minKey?.get! := by
induction l using minKey!.induct <;> simp_all only [minKey!, minKey?] <;> rfl
induction l using minKey!.induct_unfolding <;> simp only [minKey?] <;> trivial
theorem minKeyD_eq_getD_minKey? [Ord α] {l : Impl α β} {fallback} :
theorem minKeyD_eq_getD_minKey? {l : Impl α β} {fallback} :
l.minKeyD fallback = l.minKey?.getD fallback := by
induction l, fallback using minKeyD.induct <;> simp_all only [minKeyD, minKey?] <;> rfl
induction l, fallback using minKeyD.induct_unfolding <;> simp only [minKey?] <;> trivial
theorem maxKey?_eq_minKey?_reverse [Ord α] {l : Impl α β} :
l.maxKey? = (letI : Ord α := .opposite inferInstance; (reverse l).minKey?) := by
induction l using maxKey?.induct <;> simp_all only [minKey?, maxKey?, reverse]
theorem maxKey?_eq_minKey?_reverse {l : Impl α β} : l.maxKey? = l.reverse.minKey? := by
induction l using maxKey?.induct_unfolding <;> simp only [minKey?, reverse] <;> assumption
theorem some_maxKey_eq_maxKey? [Ord α] {l : Impl α β} {he} :
some (l.maxKey he) = l.maxKey? := by
induction l, he using maxKey.induct <;> simp_all [maxKey, maxKey?]
theorem some_maxKey_eq_maxKey? {l : Impl α β} {he} : some (l.maxKey he) = l.maxKey? := by
induction l, he using maxKey.induct_unfolding <;> simp only [maxKey?] <;> assumption
theorem maxKey_eq_get_maxKey? [Ord α] {l : Impl α β} {he} :
theorem maxKey_eq_get_maxKey? {l : Impl α β} {he} :
l.maxKey he = l.maxKey?.get (by simp [← some_maxKey_eq_maxKey? (he := he)]) := by
simp [← some_maxKey_eq_maxKey? (he := he)]
theorem maxKey!_eq_get!_maxKey? [Ord α] [Inhabited α] {l : Impl α β} :
theorem maxKey!_eq_get!_maxKey? [Inhabited α] {l : Impl α β} :
l.maxKey! = l.maxKey?.get! := by
induction l using maxKey!.induct <;> simp_all only [maxKey!, maxKey?] <;> rfl
induction l using maxKey!.induct_unfolding <;> simp only [maxKey?] <;> trivial
theorem maxKeyD_eq_getD_maxKey? [Ord α] {l : Impl α β} {fallback} :
theorem maxKeyD_eq_getD_maxKey? {l : Impl α β} {fallback} :
l.maxKeyD fallback = l.maxKey?.getD fallback := by
induction l, fallback using maxKeyD.induct <;> simp_all only [maxKeyD, maxKey?] <;> rfl
induction l using maxKey?.induct_unfolding <;> simp only [maxKeyD] <;> trivial
namespace Const
variable {β : Type v}
theorem minEntry?_eq_minEntry? [Ord α] {l : Impl α fun _ => β} :
minEntry? l = l.minEntry?.map (fun x => (x.1, x.2)) := by
induction l using minEntry?.induct_unfolding <;> simp only [Impl.minEntry?] <;> trivial
theorem minEntry!_eq_get!_minEntry? [Ord α] {l : Impl α fun _ => β} [Inhabited (α × β)] :
minEntry! l = (minEntry? l).get! := by
induction l using minEntry?.induct_unfolding <;> simp only [minEntry!] <;> trivial
theorem minEntryD_eq_getD_minEntry? [Ord α] {l : Impl α fun _ => β} {fallback : α × β} :
minEntryD l fallback = (minEntry? l).getD fallback := by
induction l using minEntry?.induct_unfolding <;> simp only [minEntryD] <;> trivial
theorem some_minEntry_eq_minEntry? [Ord α] {l : Impl α fun _ => β} {he} :
some (minEntry l he) = minEntry? l := by
induction l, he using minEntry.induct_unfolding <;> simp only [minEntry?] <;> trivial
theorem maxEntry?_eq_maxEntry? [Ord α] {l : Impl α fun _ => β} :
maxEntry? l = l.maxEntry?.map (fun x => (x.1, x.2)) := by
induction l using maxEntry?.induct_unfolding <;> simp only [Impl.maxEntry?] <;> trivial
theorem maxEntry!_eq_get!_maxEntry? [Ord α] {l : Impl α fun _ => β} [Inhabited (α × β)] :
maxEntry! l = (maxEntry? l).get! := by
induction l using maxEntry?.induct_unfolding <;> simp only [maxEntry!] <;> trivial
theorem maxEntryD_eq_getD_maxEntry? [Ord α] {l : Impl α fun _ => β} {fallback : α × β} :
maxEntryD l fallback = (maxEntry? l).getD fallback := by
induction l using maxEntry?.induct_unfolding <;> simp only [maxEntryD] <;> trivial
theorem some_maxEntry_eq_maxEntry? [Ord α] {l : Impl α fun _ => β} {he} :
some (maxEntry l he) = maxEntry? l := by
induction l, he using maxEntry.induct_unfolding <;> simp only [maxEntry?] <;> trivial
end Const
theorem balanceL_eq_balance {k : α} {v : β k} {l r : Impl α β} {hlb hrb hlr} :
balanceL k v l r hlb hrb hlr = balance k v l r hlb hrb (Or.inl hlr.erase) := by
@ -606,10 +752,8 @@ theorem erase_eq_erase! [Ord α] {k : α} {t : Impl α β} {h} :
theorem erase_eq_eraseₘ [Ord α] {k : α} {t : Impl α β} {h} :
(erase k t h).impl = eraseₘ k t h := by
simp only [eraseₘ]
induction t
· simp only [erase, updateCell]
split <;> split <;> simp_all [balanceLErase_eq_balance, balanceRErase_eq_balance]
· simp [erase, eraseₘ, updateCell]
induction t using tree_split_ind_no_gen (compare k) <;>
simp only [erase, updateCell, *, Cell.empty_inner, balanceRErase_eq_balance, balanceLErase_eq_balance]
theorem erase!_eq_eraseₘ [Ord α] {k : α} {t : Impl α β} (h : t.Balanced) :
erase! k t = eraseₘ k t h := by
@ -701,18 +845,12 @@ variable {β : Type v}
theorem get?_eq_get?ₘ [Ord α] (k : α) (l : Impl α (fun _ => β)) :
Const.get? l k = Const.get?ₘ l k := by
simp only [Const.get?ₘ]
induction l
· simp only [applyCell, Const.get?]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.Const.get?, Cell.ofEq]
· simp [Const.get?, applyCell]
induction l using tree_split_ind_no_gen (compare k) <;>
simp only [*, get?, applyCell, Cell.Const.get?, Cell.empty_inner, Cell.ofEq_inner]
theorem get_eq_get? [Ord α] (k : α) (l : Impl α (fun _ => β)) {h} :
some (get l k h) = get? l k := by
induction l
· simp only [applyCell, get, get?]
split <;> rename_i ihl ihr hcmp <;> simp_all
· contradiction
induction l using tree_split_ind_no_gen (compare k) <;> simp only [*, get, get?] <;> contradiction
theorem get_eq_getₘ [Ord α] (k : α) (l : Impl α (fun _ => β)) {h} (h') :
get l k h = getₘ l k h' := by
@ -721,21 +859,361 @@ theorem get_eq_getₘ [Ord α] (k : α) (l : Impl α (fun _ => β)) {h} (h') :
theorem get!_eq_get!ₘ [Ord α] (k : α) [Inhabited β] (l : Impl α (fun _ => β)) :
get! l k = get!ₘ l k := by
simp only [get!ₘ, get?ₘ]
induction l
· simp only [applyCell, get!]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.Const.get?, Cell.ofEq]
· simp only [get!, applyCell, Option.get!_none]; rfl
rw [get!ₘ, get?ₘ]
induction l using tree_split_ind_no_gen (compare k) <;>
simp only [*, get!, applyCell, Cell.Const.get?, Cell.ofEq, Option.get!_some]
· rfl
theorem getD_eq_getDₘ [Ord α] (k : α) (l : Impl α (fun _ => β))
(fallback : β) : getD l k fallback = getDₘ l k fallback := by
simp only [getDₘ, get?ₘ]
induction l
· simp only [applyCell, getD]
split <;> rename_i hcmp₁ <;> split <;> rename_i hcmp₂ <;> try (simp [hcmp₁] at hcmp₂; done)
all_goals simp_all [Cell.Const.get?, Cell.ofEq]
· simp only [getD, applyCell, Cell.Const.get?_empty, Option.getD_none]
rw [getDₘ, get?ₘ]
induction l using tree_split_ind_no_gen (compare k) <;>
simp only [*, getD, applyCell, Cell.Const.get?, Cell.ofEq, Option.getD_some]
· rfl
end Const
theorem entryAtIdx?_eq_some_entryAtIdx {t : Impl α β} (htb : t.Balanced) {i : Nat} (h) :
t.entryAtIdx? i = some (t.entryAtIdx htb i h) := by
induction t, htb, i, h using entryAtIdx.induct_unfolding <;> simp only [entryAtIdx?, *]
theorem entryAtIdx!_eq_get!_entryAtIdx? {t : Impl α β} {i : Nat} [Inhabited ((a : α) × β a)] :
t.entryAtIdx! i = (t.entryAtIdx? i).get! := by
induction t, i using entryAtIdx?.induct_unfolding <;> simp only [entryAtIdx!, *] <;> trivial
theorem entryAtIdxD_eq_getD_entryAtIdx? {t : Impl α β} {i : Nat} {fallback : (a : α) × β a} :
t.entryAtIdxD i fallback = (t.entryAtIdx? i).getD fallback := by
induction t, i using entryAtIdx?.induct_unfolding <;> simp only [entryAtIdxD, *] <;> trivial
theorem keyAtIdx?_eq_entryAtIdx? {t : Impl α β} {i : Nat} :
t.keyAtIdx? i = (t.entryAtIdx? i).map (·.1) := by
induction t, i using entryAtIdx?.induct_unfolding <;> simp only [keyAtIdx?, *] <;> trivial
theorem keyAtIdx_eq_entryAtIdx_fst {t : Impl α β} (htb : t.Balanced) {i : Nat} {h} :
t.keyAtIdx htb i h = (t.entryAtIdx htb i h).1 := by
induction t, htb, i, h using keyAtIdx.induct_unfolding <;> simp only [entryAtIdx, *]
theorem keyAtIdx!_eq_get!_keyAtIdx? [Inhabited α] {t : Impl α β} {i : Nat} :
t.keyAtIdx! i = (t.keyAtIdx? i).get! := by
induction t, i using keyAtIdx?.induct_unfolding <;> simp only [keyAtIdx!, *] <;> trivial
theorem keyAtIdxD_eq_getD_keyAtIdx? {t : Impl α β} {i : Nat} {fallback : α} :
t.keyAtIdxD i fallback = (t.keyAtIdx? i).getD fallback := by
induction t, i using keyAtIdx?.induct_unfolding <;> simp only [keyAtIdxD, *] <;> trivial
/-- Implementation detail of the tree map -/
def getEntryGE?ₘ [Ord α] (k : α) (t : Impl α β) : Option ((a : α) × β a) :=
applyPartition (compare k) t fun _ c _ r => c.inner.or r.head?
/-- Implementation detail of the tree map -/
def getEntryGE?ₘ' [Ord α] (k : α) (t : Impl α β) : Option ((a : α) × β a) :=
t.explore (compare k) none fun
| _, .lt k' _ v _ => some ⟨k', v⟩
| base, .eq _ c r => (c.inner.or r.head?).or base
| base, .gt _ _ _ _ => base
theorem getEntryGE?_eq_getEntryGE?ₘ' [Ord α] (k : α) (t : Impl α β) :
getEntryGE? k t = getEntryGE?ₘ' k t := by
rw [getEntryGE?ₘ', getEntryGE?]
induction t, none using tree_split_ind (compare k) <;> simp [*, getEntryGE?.go, explore]
theorem getEntryGE?_eq_getEntryGE?ₘ [Ord α] (k : α) (t : Impl α β) :
getEntryGE? k t = getEntryGE?ₘ k t := by
rw [getEntryGE?_eq_getEntryGE?ₘ', getEntryGE?ₘ', getEntryGE?ₘ, explore_eq_applyPartition] <;> simp
/-- Implementation detail of the tree map -/
def getEntryGT?ₘ [Ord α] (k : α) (t : Impl α β) : Option ((a : α) × β a) :=
applyPartition (fun k' => (compare k k').then .gt) t fun _ _ _ r => r.head?
/-- Implementation detail of the tree map -/
def getEntryGT?ₘ' [Ord α] (k : α) (t : Impl α β) : Option ((a : α) × β a) :=
t.explore (fun k' => (compare k k').then .gt) none fun
| _, .lt k' _ v _ => some ⟨k', v⟩
| base, .eq _ _ r => r.head?.or base
| base, .gt _ _ _ _ => base
theorem getEntryGT?_eq_getEntryGT?ₘ' [Ord α] (k : α) (t : Impl α β) :
getEntryGT? k t = getEntryGT?ₘ' k t := by
rw [getEntryGT?ₘ', getEntryGT?]
induction t, none using tree_split_ind (compare k) <;> simp [*, getEntryGT?.go, explore]
theorem getEntryGT?_eq_getEntryGT?ₘ [Ord α] (k : α) (t : Impl α β) :
getEntryGT? k t = getEntryGT?ₘ k t := by
rw [getEntryGT?_eq_getEntryGT?ₘ', getEntryGT?ₘ', getEntryGT?ₘ, explore_eq_applyPartition] <;> simp
theorem getEntryLT?_eq_getEntryGT?_reverse [o : Ord α] [TransOrd α] {t : Impl α β} {k : α} :
getEntryLT? k t = @getEntryGT? α β o.opposite k t.reverse := by
rw [getEntryLT?, @getEntryGT?.eq_def, Ord.opposite]
induction t, none using tree_split_ind (compare k) <;>
simp only [*, getEntryLT?.go, reverse, getEntryGT?.go, OrientedCmp.eq_swap (b := k),
Ordering.swap]
theorem getEntryLE?_eq_getEntryGE?_reverse [o : Ord α] [TransOrd α] {t : Impl α β} {k : α} :
getEntryLE? k t = @getEntryGE? α β o.opposite k t.reverse := by
rw [getEntryLE?, @getEntryGE?.eq_def, Ord.opposite]
induction t, none using tree_split_ind (compare k) <;>
simp only [*, getEntryLE?.go, reverse, getEntryGE?.go, OrientedCmp.eq_swap (b := k),
Ordering.swap]
theorem getEntryGE!_eq_get!_getEntryGE? [Ord α] {t : Impl α β} {k : α} [Inhabited ((a : α) × β a)] :
t.getEntryGE! k = (t.getEntryGE? k).get! := rfl
theorem getEntryGT!_eq_get!_getEntryGT? [Ord α] {t : Impl α β} {k : α} [Inhabited ((a : α) × β a)] :
t.getEntryGT! k = (t.getEntryGT? k).get! := rfl
theorem getEntryLE!_eq_get!_getEntryLE? [Ord α] {t : Impl α β} {k : α} [Inhabited ((a : α) × β a)] :
t.getEntryLE! k = (t.getEntryLE? k).get! := rfl
theorem getEntryLT!_eq_get!_getEntryLT? [Ord α] {t : Impl α β} {k : α} [Inhabited ((a : α) × β a)] :
t.getEntryLT! k = (t.getEntryLT? k).get! := rfl
theorem getEntryGED_eq_getD_getEntryGE? [Ord α] {t : Impl α β} {k : α} {fallback : (a : α) × β a} :
t.getEntryGED k fallback = (t.getEntryGE? k).getD fallback := rfl
theorem getEntryGTD_eq_getD_getEntryGT? [Ord α] {t : Impl α β} {k : α} {fallback : (a : α) × β a} :
t.getEntryGTD k fallback = (t.getEntryGT? k).getD fallback := rfl
theorem getEntryLED_eq_getD_getEntryLE? [Ord α] {t : Impl α β} {k : α} {fallback : (a : α) × β a} :
t.getEntryLED k fallback = (t.getEntryLE? k).getD fallback := rfl
theorem getEntryLTD_eq_getD_getEntryLT? [Ord α] {t : Impl α β} {k : α} {fallback : (a : α) × β a} :
t.getEntryLTD k fallback = (t.getEntryLT? k).getD fallback := rfl
theorem getEntryGE?.eq_go [Ord α] (k : α) (x) (t : Impl α β) :
(getEntryGE? k t).or x = getEntryGE?.go k x t := by
rw [getEntryGE?]
induction t, x using tree_split_ind (compare k) <;>
simp only [go, Option.none_or, Option.some_or, *]
case _ ih _ => rw [← ih, Option.or_assoc, Option.some_or]
theorem getEntryGT?.eq_go [Ord α] (k : α) (x) (t : Impl α β) :
(getEntryGT? k t).or x = getEntryGT?.go k x t := by
rw [getEntryGT?]
induction t, x using tree_split_ind (compare k) <;>
simp only [go, Option.none_or, Option.some_or, *]
case _ ih _ => rw [← ih, Option.or_assoc, Option.some_or]
theorem getEntryLE?.eq_go [Ord α] (k : α) (x) (t : Impl α β) :
(getEntryLE? k t).or x = getEntryLE?.go k x t := by
rw [getEntryLE?]
induction t, x using tree_split_ind (compare k) <;>
simp only [go, Option.none_or, Option.some_or, *]
case _ ih _ => rw [← ih, Option.or_assoc, Option.some_or]
theorem getEntryLT?.eq_go [Ord α] (k : α) (x) (t : Impl α β) :
(getEntryLT? k t).or x = getEntryLT?.go k x t := by
rw [getEntryLT?]
induction t, x using tree_split_ind (compare k) <;>
simp only [go, Option.none_or, Option.some_or, *]
case _ ih _ => rw [← ih, Option.or_assoc, Option.some_or]
theorem some_getEntryGE_eq_getEntryGE? [Ord α] [TransOrd α] (k : α) (t : Impl α β) {ho he} :
some (getEntryGE k t ho he) = getEntryGE? k t := by
rw [getEntryGE?]; apply of_eq_true
induction t, none using tree_split_ind (compare k) <;>
simp only [*, getEntryGE?.go, getEntryGE, getEntryGED, ← Option.or_some,
getEntryGE?.eq_go] <;> contradiction
theorem some_getEntryGT_eq_getEntryGT? [Ord α] [TransOrd α] (k : α) (t : Impl α β) {ho he} :
some (getEntryGT k t ho he) = getEntryGT? k t := by
rw [getEntryGT?]; apply of_eq_true
induction t, none using tree_split_ind (compare k) <;>
simp only [*, getEntryGT?.go, getEntryGT, getEntryGTD, ← Option.or_some,
getEntryGT?.eq_go, ↓reduceDIte, reduceCtorEq] <;> contradiction
theorem some_getEntryLE_eq_getEntryLE? [Ord α] [TransOrd α] (k : α) (t : Impl α β) {ho he} :
some (getEntryLE k t ho he) = getEntryLE? k t := by
rw [getEntryLE?]; apply of_eq_true
induction t, none using tree_split_ind (compare k) <;>
simp only [*, getEntryLE?.go, getEntryLE, getEntryLED, ← Option.or_some,
getEntryLE?.eq_go] <;> contradiction
theorem some_getEntryLT_eq_getEntryLT? [Ord α] [TransOrd α] (k : α) (t : Impl α β) {ho he} :
some (getEntryLT k t ho he) = getEntryLT? k t := by
rw [getEntryLT?]; apply of_eq_true
induction t, none using tree_split_ind (compare k) <;>
simp only [*, getEntryLT?.go, getEntryLT, getEntryLTD, ← Option.or_some,
getEntryLT?.eq_go, ↓reduceDIte, reduceCtorEq] <;> contradiction
theorem getKeyGE?_eq_getEntryGE? [Ord α] {t : Impl α β} {k : α} :
getKeyGE? k t = (getEntryGE? k t).map (·.1) := by
rw [getKeyGE?, getEntryGE?]; symm
change _ = getKeyGE?.go k (Option.map (·.1) (none : Option ((a : α) × β a))) _
induction t, none using tree_split_ind (compare k) <;> simp [getKeyGE?.go, getEntryGE?.go, *]
theorem getKeyGT?_eq_getEntryGT? [Ord α] {t : Impl α β} {k : α} :
getKeyGT? k t = (getEntryGT? k t).map (·.1) := by
rw [getKeyGT?, getEntryGT?]; symm
change _ = getKeyGT?.go k (Option.map (·.1) (none : Option ((a : α) × β a))) _
induction t, none using tree_split_ind (compare k) <;> simp [getKeyGT?.go, getEntryGT?.go, *]
theorem getKeyLE?_eq_getEntryLE? [Ord α] {t : Impl α β} {k : α} :
getKeyLE? k t = (getEntryLE? k t).map (·.1) := by
rw [getKeyLE?, getEntryLE?]; symm
change _ = getKeyLE?.go k (Option.map (·.1) (none : Option ((a : α) × β a))) _
induction t, none using tree_split_ind (compare k) <;> simp [getKeyLE?.go, getEntryLE?.go, *]
theorem getKeyLT?_eq_getEntryLT? [Ord α] {t : Impl α β} {k : α} :
getKeyLT? k t = (getEntryLT? k t).map (·.1) := by
rw [getKeyLT?, getEntryLT?]; symm
change _ = getKeyLT?.go k (Option.map (·.1) (none : Option ((a : α) × β a))) _
induction t, none using tree_split_ind (compare k) <;> simp [getKeyLT?.go, getEntryLT?.go, *]
theorem getKeyGE!_eq_get!_getKeyGE? [Ord α] {t : Impl α β} {k : α} [Inhabited α] :
t.getKeyGE! k = (t.getKeyGE? k).get! := rfl
theorem getKeyGT!_eq_get!_getKeyGT? [Ord α] {t : Impl α β} {k : α} [Inhabited α] :
t.getKeyGT! k = (t.getKeyGT? k).get! := rfl
theorem getKeyLE!_eq_get!_getKeyLE? [Ord α] {t : Impl α β} {k : α} [Inhabited α] :
t.getKeyLE! k = (t.getKeyLE? k).get! := rfl
theorem getKeyLT!_eq_get!_getKeyLT? [Ord α] {t : Impl α β} {k : α} [Inhabited α] :
t.getKeyLT! k = (t.getKeyLT? k).get! := rfl
theorem getKeyGED_eq_getD_getKeyGE? [Ord α] {t : Impl α β} {k fallback : α} :
t.getKeyGED k fallback = (t.getKeyGE? k).getD fallback := rfl
theorem getKeyGTD_eq_getD_getKeyGT? [Ord α] {t : Impl α β} {k fallback : α} :
t.getKeyGTD k fallback = (t.getKeyGT? k).getD fallback := rfl
theorem getKeyLED_eq_getD_getKeyLE? [Ord α] {t : Impl α β} {k fallback : α} :
t.getKeyLED k fallback = (t.getKeyLE? k).getD fallback := rfl
theorem getKeyLTD_eq_getD_getKeyLT? [Ord α] {t : Impl α β} {k fallback : α} :
t.getKeyLTD k fallback = (t.getKeyLT? k).getD fallback := rfl
theorem getKeyGE_eq_getEntryGE [Ord α] [TransOrd α] {t : Impl α β} {k : α} {hto he} :
getKeyGE k t hto he = (getEntryGE k t hto he).1 := by
induction t using tree_split_ind_no_gen (compare k) <;> simp only [getKeyGE, getEntryGE, *]
· contradiction
· rw [getKeyGED, getEntryGED, getKeyGE?_eq_getEntryGE?]; symm
exact (Option.getD_map _ _ _).symm
theorem getKeyGT_eq_getEntryGT [Ord α] [TransOrd α] {t : Impl α β} {k : α} {hto he} :
getKeyGT k t hto he = (getEntryGT k t hto he).1 := by
induction t using tree_split_ind_no_gen (compare k) <;>
simp only [getKeyGT, getEntryGT, *, ↓reduceDIte, reduceCtorEq]
· contradiction
· rw [getKeyGTD, getEntryGTD, getKeyGT?_eq_getEntryGT?]; symm
exact (Option.getD_map _ _ _).symm
theorem getKeyLE_eq_getEntryLE [Ord α] [TransOrd α] {t : Impl α β} {k : α} {hto he} :
getKeyLE k t hto he = (getEntryLE k t hto he).1 := by
induction t using tree_split_ind_no_gen (compare k) <;> simp only [getKeyLE, getEntryLE, *]
· contradiction
· rw [getKeyLED, getEntryLED, getKeyLE?_eq_getEntryLE?]; symm
exact (Option.getD_map _ _ _).symm
theorem getKeyLT_eq_getEntryLT [Ord α] [TransOrd α] {t : Impl α β} {k : α} {hto he} :
getKeyLT k t hto he = (getEntryLT k t hto he).1 := by
induction t using tree_split_ind_no_gen (compare k) <;>
simp only [getKeyLT, getEntryLT, *, ↓reduceDIte, reduceCtorEq]
· contradiction
· rw [getKeyLTD, getEntryLTD, getKeyLT?_eq_getEntryLT?]; symm
exact (Option.getD_map _ _ _).symm
namespace Const
variable {β : Type v}
theorem entryAtIdx?_eq_map {t : Impl α fun _ => β} {i : Nat} :
entryAtIdx? t i = (t.entryAtIdx? i).map (fun x => (x.1, x.2)) := by
induction t, i using entryAtIdx?.induct_unfolding <;> simp only [Impl.entryAtIdx?, *] <;> rfl
theorem entryAtIdx_eq {t : Impl α fun _ => β} (htb : t.Balanced) {i : Nat} {h} :
entryAtIdx t htb i h = ((t.entryAtIdx htb i h).1, (t.entryAtIdx htb i h).2) := by
induction t, htb, i, h using entryAtIdx.induct_unfolding <;> simp only [Impl.entryAtIdx, *]
theorem entryAtIdx!_eq_get!_entryAtIdx? {t : Impl α fun _ => β} {i : Nat} [Inhabited (α × β)] :
entryAtIdx! t i = (entryAtIdx? t i).get! := by
induction t, i using entryAtIdx?.induct_unfolding <;> simp only [entryAtIdx!, *] <;> rfl
theorem entryAtIdxD_eq_getD_entryAtIdx? {t : Impl α fun _ => β} {i : Nat} {fallback : α × β} :
entryAtIdxD t i fallback = (entryAtIdx? t i).getD fallback := by
induction t, i using entryAtIdx?.induct_unfolding <;> simp only [entryAtIdxD, *] <;> rfl
theorem getEntryGE?_eq_map [Ord α] {t : Impl α fun _ => β} {k : α} :
getEntryGE? k t = (Impl.getEntryGE? k t).map (fun x => (x.1, x.2)) := by
rw [getEntryGE?, Impl.getEntryGE?]; symm
change _ = getEntryGE?.go k (Option.map (fun x => (x.1, x.2)) (none : Option ((_ : α) × β))) _
induction t, none using tree_split_ind (compare k) <;> simp [getEntryGE?.go, Impl.getEntryGE?.go, *]
theorem getEntryGT?_eq_map [Ord α] {t : Impl α fun _ => β} {k : α} :
getEntryGT? k t = (Impl.getEntryGT? k t).map (fun x => (x.1, x.2)) := by
rw [getEntryGT?, Impl.getEntryGT?]; symm
change _ = getEntryGT?.go k (Option.map (fun x => (x.1, x.2)) (none : Option ((_ : α) × β))) _
induction t, none using tree_split_ind (compare k) <;> simp [getEntryGT?.go, Impl.getEntryGT?.go, *]
theorem getEntryLE?_eq_map [Ord α] {t : Impl α fun _ => β} {k : α} :
getEntryLE? k t = (Impl.getEntryLE? k t).map (fun x => (x.1, x.2)) := by
rw [getEntryLE?, Impl.getEntryLE?]; symm
change _ = getEntryLE?.go k (Option.map (fun x => (x.1, x.2)) (none : Option ((_ : α) × β))) _
induction t, none using tree_split_ind (compare k) <;> simp [getEntryLE?.go, Impl.getEntryLE?.go, *]
theorem getEntryLT?_eq_map [Ord α] {t : Impl α fun _ => β} {k : α} :
getEntryLT? k t = (Impl.getEntryLT? k t).map (fun x => (x.1, x.2)) := by
rw [getEntryLT?, Impl.getEntryLT?]; symm
change _ = getEntryLT?.go k (Option.map (fun x => (x.1, x.2)) (none : Option ((_ : α) × β))) _
induction t, none using tree_split_ind (compare k) <;> simp [getEntryLT?.go, Impl.getEntryLT?.go, *]
theorem getEntryGE!_eq_get!_getEntryGE? [Ord α] {t : Impl α fun _ => β} {k : α} [Inhabited (α × β)] :
getEntryGE! k t = (getEntryGE? k t).get! := rfl
theorem getEntryGT!_eq_get!_getEntryGT? [Ord α] {t : Impl α fun _ => β} {k : α} [Inhabited (α × β)] :
getEntryGT! k t = (getEntryGT? k t).get! := rfl
theorem getEntryLE!_eq_get!_getEntryLE? [Ord α] {t : Impl α fun _ => β} {k : α} [Inhabited (α × β)] :
getEntryLE! k t = (getEntryLE? k t).get! := rfl
theorem getEntryLT!_eq_get!_getEntryLT? [Ord α] {t : Impl α fun _ => β} {k : α} [Inhabited (α × β)] :
getEntryLT! k t = (getEntryLT? k t).get! := rfl
theorem getEntryGED_eq_getD_getEntryGE? [Ord α] {t : Impl α fun _ => β} {k : α} {fallback : α × β} :
getEntryGED k t fallback = (getEntryGE? k t).getD fallback := rfl
theorem getEntryGTD_eq_getD_getEntryGT? [Ord α] {t : Impl α fun _ => β} {k : α} {fallback : α × β} :
getEntryGTD k t fallback = (getEntryGT? k t).getD fallback := rfl
theorem getEntryLED_eq_getD_getEntryLE? [Ord α] {t : Impl α fun _ => β} {k : α} {fallback : α × β} :
getEntryLED k t fallback = (getEntryLE? k t).getD fallback := rfl
theorem getEntryLTD_eq_getD_getEntryLT? [Ord α] {t : Impl α fun _ => β} {k : α} {fallback : α × β} :
getEntryLTD k t fallback = (getEntryLT? k t).getD fallback := rfl
theorem getEntryGE_eq [Ord α] [TransOrd α] {t : Impl α fun _ => β} (hto : t.Ordered) {k : α} (he) :
getEntryGE k t hto he = (letI e := Impl.getEntryGE k t hto he; (e.1, e.2)) := by
induction t using tree_split_ind_no_gen (compare k) <;> simp only [getEntryGE, Impl.getEntryGE, *]
· contradiction
· rename_i l _ _ _
rw [getEntryGED, Impl.getEntryGED, getEntryGE?_eq_map]
exact Option.getD_map (fun x => (x.1, x.2)) ⟨_, _⟩ (Impl.getEntryGE? k l)
theorem getEntryGT_eq [Ord α] [TransOrd α] {t : Impl α fun _ => β} (hto : t.Ordered) {k : α} (he) :
getEntryGT k t hto he = (letI e := Impl.getEntryGT k t hto he; (e.1, e.2)) := by
induction t using tree_split_ind_no_gen (compare k) <;>
simp only [getEntryGT, Impl.getEntryGT, *, ↓reduceDIte, reduceCtorEq]
· contradiction
· rename_i l _ _ _
rw [getEntryGTD, Impl.getEntryGTD, getEntryGT?_eq_map]
exact Option.getD_map (fun x => (x.1, x.2)) ⟨_, _⟩ (Impl.getEntryGT? k l)
theorem getEntryLE_eq [Ord α] [TransOrd α] {t : Impl α fun _ => β} (hto : t.Ordered) {k : α} (he) :
getEntryLE k t hto he = (letI e := Impl.getEntryLE k t hto he; (e.1, e.2)) := by
induction t using tree_split_ind_no_gen (compare k) <;> simp only [getEntryLE, Impl.getEntryLE, *]
· contradiction
· rename_i r _ _
rw [getEntryLED, Impl.getEntryLED, getEntryLE?_eq_map]
exact Option.getD_map (fun x => (x.1, x.2)) ⟨_, _⟩ (Impl.getEntryLE? k r)
theorem getEntryLT_eq [Ord α] [TransOrd α] {t : Impl α fun _ => β} (hto : t.Ordered) {k : α} (he) :
getEntryLT k t hto he = (letI e := Impl.getEntryLT k t hto he; (e.1, e.2)) := by
induction t using tree_split_ind_no_gen (compare k) <;>
simp only [getEntryLT, Impl.getEntryLT, *, ↓reduceDIte, reduceCtorEq]
· contradiction
· rename_i r _ _
rw [getEntryLTD, Impl.getEntryLTD, getEntryLT?_eq_map]
exact Option.getD_map (fun x => (x.1, x.2)) ⟨_, _⟩ (Impl.getEntryLT? k r)
end Const

View file

@ -26,6 +26,13 @@ private local instance : Coe (Type v) (α → Type v) where coe γ := fun _ =>
namespace Std.DTreeMap.Internal.Impl
/-- Two tree maps are equivalent in the sense of Equiv iff all the keys and values are equal. -/
structure Equiv (t t' : Impl α β) where
/-- Implementation detail of the tree map -/
impl : t.toListModel.Perm t'.toListModel
@[inherit_doc] scoped infix:50 " ~m " => Equiv
/-- Returns `true` if the given key is contained in the map. -/
def contains [Ord α] (k : α) (t : Impl α β) : Bool :=
match t with

View file

@ -26,7 +26,7 @@ can be found in `Std.Data.Internal.Lemmas`.
set_option autoImplicit false
set_option linter.all true
universe u v w
universe u v w w'
variable {α : Type u} {β : α → Type v} {γ : α → Type w} {δ : Type w}
private local instance : Coe (Type v) (α → Type v) where coe γ := fun _ => γ
@ -255,12 +255,6 @@ theorem toListModel_filter_lt_of_lt [Ord α] [TransOrd α] {k : α → Ordering}
List.append_cancel_left_eq, List.cons.injEq, List.filter_eq_self, beq_iff_eq, true_and]
exact fun p hp => IsCut.lt hcmp (ho.compare_right hp)
instance [Ord α] [TransOrd α] {k : α} : IsStrictCut compare (compare k) where
lt := TransCmp.lt_trans
gt h₁ h₂ := OrientedCmp.gt_of_lt (TransCmp.lt_trans (OrientedCmp.lt_of_gt h₂)
(OrientedCmp.lt_of_gt h₁))
eq _ _ := TransCmp.congr_left
theorem findCell_of_gt [Ord α] [TransOrd α] {k : α → Ordering} [IsStrictCut compare k]
{sz k' v' l r} (hcmp : k k' = .gt) (ho : (inner sz k' v' l r : Impl α β).Ordered) :
List.findCell (inner sz k' v' l r).toListModel k = List.findCell r.toListModel k :=
@ -287,25 +281,21 @@ theorem toListModel_updateCell [Ord α] [TransOrd α] {k : α}
· simp_all [updateCell]
· rename_i sz k' v' l r hb hcmp l' hl'₁ hl'₂ hl'₃ hup ih
simp only [updateCell, hcmp]
split <;> rename_i hcmp' <;> try (simp [hcmp] at hcmp'; done)
rw [toListModel_balance, toListModel_filter_gt_of_lt hcmp hlo,
toListModel_filter_lt_of_lt hcmp hlo, findCell_of_lt hcmp hlo, ih hlo.left]
simp
· rename_i sz k' v' l r hl hcmp hf
simp only [updateCell, hcmp, hf]
split <;> rename_i hcmp' <;> try (simp [hcmp] at hcmp'; done)
rw [toListModel_glue, toListModel_filter_gt_of_eq hcmp hlo, findCell_of_eq hcmp hlo,
hf, toListModel_filter_lt_of_eq hcmp hlo]
simp
· rename_i sz k' v' l r hl hcmp k'' v'' hf
simp only [updateCell, hcmp, hf]
split <;> rename_i hcmp' <;> try (simp [hcmp] at hcmp'; done)
rw [toListModel_inner, toListModel_filter_gt_of_eq hcmp hlo, findCell_of_eq hcmp hlo,
toListModel_filter_lt_of_eq hcmp hlo, hf]
simp
· rename_i sz k' v' l r hb hcmp l' hl'₁ hl'₂ hl'₃ hup ih
simp only [updateCell, hcmp]
split <;> rename_i hcmp' <;> try (simp [hcmp] at hcmp'; done)
rw [toListModel_filter_gt_of_gt hcmp hlo, findCell_of_gt hcmp hlo,
toListModel_filter_lt_of_gt hcmp hlo, toListModel_balance, ih hlo.right]
simp
@ -545,6 +535,22 @@ theorem applyCell_eq_apply_toListModel [Ord α] [TransOrd α] [BEq α] [LawfulBE
## Verification of access operations
-/
/-!
### Equiv
-/
theorem equiv_iff_toListModel_perm {t t' : Impl α β} :
t.Equiv t' ↔ t.toListModel.Perm t'.toListModel :=
⟨Equiv.impl, Equiv.mk⟩
theorem Equiv.toListModel_eq [Ord α] [OrientedOrd α]
{t t' : Impl α β} (h : t.Equiv t') (htb : t.Ordered) (htb' : t'.Ordered) :
t.toListModel = t'.toListModel := by
refine List.Perm.eq_of_sorted ?_ htb htb' h.1
intro a b ha hb hlt hgt
rw [OrientedOrd.eq_swap, hlt] at hgt
contradiction
/-!
### `isEmpty`
-/
@ -1018,7 +1024,7 @@ theorem toListModel_filterMap [Ord α] {t : Impl α β} {h} {f : (a : α) → β
induction t with
| leaf => rfl
| inner sz k v _ _ ihl ihr =>
simp [filterMap]
simp only [filterMap, toListModel_inner, List.filterMap_append]
cases h : f k v
all_goals simp [h, ihl, ihr]
@ -1047,6 +1053,11 @@ theorem filter_eq_filterMap [Ord α] {t : Impl α β} {h} {f : (a : α) → β a
simp [filter, filterMap]
cases hf : f k v <;> rw [ihl, ihr] <;> rfl
theorem toListModel_filter [Ord α] {t : Impl α β} {h} {f : (a : α) → β a → Bool} :
(t.filter f h).impl.toListModel = t.toListModel.filter (fun e => f e.1 e.2) := by
rw [filter_eq_filterMap, toListModel_filterMap, ← List.filterMap_eq_filter]
congr; simp only [Option.map_if, Option.guard_def]
theorem ordered_filter [Ord α] {t : Impl α β} {h} {f : (a : α) → β a → Bool} (hto : t.Ordered) :
(t.filter f h).impl.Ordered := by
simpa only [filter_eq_filterMap] using ordered_filterMap hto
@ -1085,11 +1096,8 @@ theorem alter_eq_alterₘ [Ord α] [TransOrd α] [LawfulEqOrd α] {t : Impl α
rw [alter, updateCell]
split <;> rename_i heq <;> simp only [heq]
· simp [ihl htb.left hto.left]
split <;> simp_all
· simp [ihr htb.right hto.right]
split <;> simp_all
· apply Eq.symm
split <;> (try simp_all; done)
simp [Cell.alter, Cell.ofOption, cast]
cases h₁ : f _ <;> rfl
@ -1217,10 +1225,15 @@ theorem foldr_eq_foldr {t : Impl α β} {δ} {f : (a : α) → β a → δ →
theorem toList_eq_toListModel {t : Impl α β} :
t.toList = t.toListModel := by
rw [toList, foldr_eq_foldr]
induction t with
| leaf => rfl
| inner sz k v l r ihl ihr => simp
simp [toList, foldr_eq_foldr]
/-!
### toArray
-/
theorem toArray_eq_toArray {t : Impl α β} :
t.toArray = t.toListModel.toArray := by
simp [toArray, foldl_eq_foldl]
/-!
### keys
@ -1228,19 +1241,37 @@ theorem toList_eq_toListModel {t : Impl α β} :
theorem keys_eq_keys {t : Impl α β} :
t.keys = t.toListModel.keys := by
rw [keys, foldr_eq_foldr, List.keys.eq_def]
simp
induction t.toListModel with
| nil => rfl
| cons e es ih =>
simp [ih]
rw [List.keys.eq_def]
simp [keys, foldr_eq_foldr, List.keys_eq_map]
/-!
### keysArray
-/
theorem keysArray_eq_toArray_keys {t : Impl α β} :
t.keysArray = t.toListModel.keys.toArray := by
simp [keysArray, foldl_eq_foldl, List.keys_eq_map]
/-!
### values
-/
theorem values_eq_map_snd {β : Type v} {t : Impl α β} :
t.values = t.toListModel.map (·.2) := by
simp [values, foldr_eq_foldr]
/-!
### valuesArray
-/
theorem valuesArray_eq_toArray_map {β : Type v} {t : Impl α β} :
t.valuesArray = (t.toListModel.map (·.2)).toArray := by
simp [valuesArray, foldl_eq_foldl]
/-!
### forM
-/
theorem forM_eq_forM {t: Impl α β} {m : Type w → Type w} [Monad m] [LawfulMonad m]
theorem forM_eq_forM {t : Impl α β} {m : Type w → Type w'} [Monad m] [LawfulMonad m]
{f : (a : α) → β a → m PUnit} :
t.forM f = t.toListModel.forM (fun a => f a.1 a.2) := by
simp only [Impl.forM, foldlM_eq_foldlM_toListModel]
@ -1252,7 +1283,7 @@ theorem forM_eq_forM {t: Impl α β} {m : Type w → Type w} [Monad m] [LawfulMo
### forIn
-/
theorem forInStep_eq_foldlM {δ : Type w} {t : Impl α β} {m : Type w → Type w} [Monad m] [LawfulMonad m]
theorem forInStep_eq_foldlM {δ : Type w} {t : Impl α β} {m : Type w → Type w'} [Monad m] [LawfulMonad m]
{f : (a : α) → β a → δ → m (ForInStep δ)} {init : δ} :
t.forInStep f init = t.foldlM (init := .yield init) fun
| .yield d => fun k v => f k v d
@ -1279,7 +1310,7 @@ theorem forInStep_eq_foldlM {δ : Type w} {t : Impl α β} {m : Type w → Type
induction r <;> simp [foldlM, *]
theorem forIn_eq_forIn_toListModel {δ : Type w} {t : Impl α β} {m : Type w → Type w} [Monad m] [LawfulMonad m]
theorem forIn_eq_forIn_toListModel {δ : Type w} {t : Impl α β} {m : Type w → Type w'} [Monad m] [LawfulMonad m]
{f : (a : α) → β a → δ → m (ForInStep δ)} {init : δ} :
t.forIn f init = ForIn.forIn t.toListModel init (fun a d => f a.1 a.2 d) := by
rw [Impl.forIn, forInStep_eq_foldlM, List.forIn_eq_foldlM, foldlM_eq_foldlM_toListModel]
@ -1339,11 +1370,8 @@ theorem alter_eq_alterₘ [Ord α] [TransOrd α] {t : Impl α β} {a f}
rw [alter, updateCell]
split <;> rename_i heq <;> simp only [heq]
· simp [ihl htb.left hto.left]
split <;> simp_all
· simp [ihr htb.right hto.right]
split <;> simp_all
· apply Eq.symm
split <;> (try simp_all; done)
simp [Cell.Const.alter, Cell.ofOption, cast]
cases h₁ : f _ <;> rfl
@ -1424,11 +1452,16 @@ theorem ordered_mergeWith [Ord α] [TransOrd α] {t₁ t₂ : Impl α β} {f}
-/
theorem toList_eq_toListModel_map {t : Impl α β} :
Const.toList t = t.toListModel.map fun ⟨k, v⟩ => (k, v) := by
rw [toList, foldr_eq_foldr]
induction t with
| leaf => rfl
| inner sz k v l r ihl ihr => simp
Const.toList t = t.toListModel.map fun e => (e.1, e.2) := by
simp [toList, foldr_eq_foldr]
/-!
### toArray
-/
theorem toArray_eq_toArray_map {t : Impl α β} :
Const.toArray t = (t.toListModel.map fun e => (e.1, e.2)).toArray := by
simp [toArray, foldl_eq_foldl]
end Const
@ -1460,11 +1493,11 @@ theorem WF.ordered [Ord α] [TransOrd α] {l : Impl α β} (h : WF l) : l.Ordere
variable {β'} in
/-- Internal implementation detail of the tree map -/
inductive SameKeys : Impl α β → Impl α β' → Prop where
/-- Internal implementation detail of the tree map -/
| leaf : SameKeys .leaf .leaf
/-- Internal implementation detail of the tree map -/
| inner (sz k v v' r r' l l') : SameKeys r r' → SameKeys l l' →
SameKeys (.inner sz k v l r) (.inner sz k v' l' r')
/-- Internal implementation detail of the tree map -/
| leaf : SameKeys .leaf .leaf
/-- Internal implementation detail of the tree map -/
| inner (sz k v v' r r' l l') : SameKeys r r' → SameKeys l l' →
SameKeys (.inner sz k v l r) (.inner sz k v' l' r')
namespace SameKeys
@ -1793,11 +1826,6 @@ theorem WF.map [Ord α] {t : Impl α β} {f : (a : α) → β a → γ a} (h : t
### `minEntry?`
-/
instance [Ord α] : IsStrictCut (compare : αα → Ordering) (fun _ => .lt) where
lt := by simp
gt := by simp
eq := by simp
theorem minEntry?ₘ_eq_minEntry? [Ord α] [TransOrd α] {l : Impl α β} (hlo : l.Ordered) :
l.minEntry?ₘ = List.minEntry? l.toListModel := by
rw [minEntry?ₘ, applyPartition_eq_apply_toListModel' hlo]
@ -1844,6 +1872,14 @@ theorem Ordered.reverse [Ord α] {t : Impl α β} (h : t.Ordered) :
simp only [Ordered, toListModel_reverse]
exact List.pairwise_reverse.mpr h
theorem maxEntry?_eq_minEntry? [o : Ord α] [to : TransOrd α] {t : Impl α β} (hlo : t.Ordered) :
t.maxEntry? = (letI := o.opposite; List.minEntry? t.toListModel) := by
rw [maxEntry?_eq_minEntry?_reverse, @minEntry?_eq_minEntry? _ _ (_) _ _ hlo.reverse]
apply @List.minEntry?_of_perm _ _ o.opposite to.opposite (@beqOfOrd _ o.opposite)
· exact @hlo.reverse.distinctKeys _ _ (@beqOfOrd _ o.opposite) (_) _
· rw [toListModel_reverse]
exact List.reverse_perm t.toListModel
theorem maxKey?_eq_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {t : Impl α β}
(hlo : t.Ordered) :
t.maxKey? = List.maxKey? t.toListModel := by
@ -1865,4 +1901,131 @@ theorem maxKeyD_eq_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {t
t.maxKeyD fallback = List.maxKeyD t.toListModel fallback := by
simp only [List.maxKeyD_eq_getD_maxKey?, maxKeyD_eq_getD_maxKey?, maxKey?_eq_maxKey? hlo]
/-!
### `entryAtIdx?` / `keyAtIdx?`
-/
theorem entryAtIdx?_eq_getElem? {t : Impl α β} (htb : t.Balanced) {i : Nat} :
t.entryAtIdx? i = t.toListModel[i]? := by
induction t, i using entryAtIdx?.induct_unfolding with
| case1 => rfl
| case2 _ _ _ _ _ _ h ih =>
simp only [toListModel_inner, *, htb.left]
simp_all only [toListModel_inner, Nat.compare_eq_lt, ← size_eq_length,
List.getElem?_append_left, htb.left]
| case3 =>
simp only [toListModel_inner, *]
simp_all only [Nat.compare_eq_eq, List.getElem?_append_right, Nat.le_refl, htb.left,
← size_eq_length, Nat.sub_self, List.getElem?_cons_zero]
| case4 =>
simp only [toListModel_inner, *, htb.right]
simp_all only [Nat.compare_eq_gt, List.getElem?_append_right, Nat.le_of_lt,
← size_eq_length, htb.left, List.getElem?_cons, Nat.sub_eq_zero_iff_le,
← Nat.not_lt, not_true, ↓reduceIte]
theorem entryAtIdx_eq_getElem {t : Impl α β} (htb : t.Balanced) {i : Nat} {h} :
t.entryAtIdx htb i h = t.toListModel[i]'(size_eq_length t htb ▸ h) := by
simp only [List.getElem_eq_getElem?_get, ← entryAtIdx?_eq_getElem? htb,
entryAtIdx?_eq_some_entryAtIdx htb h, Option.get_some]
theorem entryAtIdx!_eq_getElem! {t : Impl α β} (htb : t.Balanced) {i : Nat}
[Inhabited ((a : α) × β a)] : t.entryAtIdx! i = t.toListModel[i]! := by
simp only [entryAtIdx!_eq_get!_entryAtIdx?, entryAtIdx?_eq_getElem? htb,
List.getElem!_eq_getElem?_getD, Option.get!_eq_getD]
theorem entryAtIdxD_eq_getD {t : Impl α β} (htb : t.Balanced) {i : Nat} {fallback : (a : α) × β a} :
t.entryAtIdxD i fallback = t.toListModel.getD i fallback := by
simp only [entryAtIdxD_eq_getD_entryAtIdx?, entryAtIdx?_eq_getElem? htb,
List.getD_eq_getElem?_getD]
theorem keyAtIdx?_eq_getElem? {t : Impl α β} (htb : t.Balanced) {i : Nat} :
t.keyAtIdx? i = t.toListModel[i]?.map (·.1) := by
rw [keyAtIdx?_eq_entryAtIdx?, entryAtIdx?_eq_getElem? htb]
theorem keyAtIdx_eq_getElem_fst {t : Impl α β} (htb : t.Balanced) {i : Nat} {h} :
t.keyAtIdx htb i h = (t.toListModel[i]'(size_eq_length t htb ▸ h)).1 := by
rw [keyAtIdx_eq_entryAtIdx_fst, entryAtIdx_eq_getElem htb]
theorem keyAtIdx!_eq_get!_map_getElem? [Inhabited α] {t : Impl α β} (htb : t.Balanced) {i : Nat} :
t.keyAtIdx! i = (t.toListModel[i]?.map (·.1)).get! := by
rw [keyAtIdx!_eq_get!_keyAtIdx?, keyAtIdx?_eq_getElem? htb]
theorem keyAtIdxD_eq_getD_map_getElem? {t : Impl α β} (htb : t.Balanced) {i : Nat} {fallback : α} :
t.keyAtIdxD i fallback = (t.toListModel[i]?.map (·.1)).getD fallback := by
rw [keyAtIdxD_eq_getD_keyAtIdx?, keyAtIdx?_eq_getElem? htb]
namespace Const
variable {β : Type v}
theorem entryAtIdx?_eq_getElem? {t : Impl α β} (htb : t.Balanced) {i : Nat} :
entryAtIdx? t i = t.toListModel[i]?.map (fun x => (x.1, x.2)) := by
rw [entryAtIdx?_eq_map, Impl.entryAtIdx?_eq_getElem? htb]
theorem entryAtIdx_eq_getElem {t : Impl α β} (htb : t.Balanced) {i : Nat} {h} :
entryAtIdx t htb i h = (letI x := t.toListModel[i]'(size_eq_length t htb ▸ h); (x.1, x.2)) := by
rw [entryAtIdx_eq, Impl.entryAtIdx_eq_getElem htb]
theorem entryAtIdx!_eq_get!_map_getElem? {t : Impl α β} (htb : t.Balanced) {i : Nat}
[Inhabited (α × β)] :
entryAtIdx! t i = (t.toListModel[i]?.map (fun x => (x.1, x.2))).get! := by
rw [entryAtIdx!_eq_get!_entryAtIdx?, entryAtIdx?_eq_getElem? htb]
theorem entryAtIdxD_eq_getD_map_getElem? {t : Impl α β} (htb : t.Balanced) {i : Nat}
{fallback : α × β} :
entryAtIdxD t i fallback = (t.toListModel[i]?.map (fun x => (x.1, x.2))).getD fallback := by
rw [entryAtIdxD_eq_getD_entryAtIdx?, entryAtIdx?_eq_getElem? htb]
end Const
/-!
### `getEntryLE?` / `getKeyLE?` / ...
-/
theorem getEntryGE?_eq_find? [Ord α] [TransOrd α] {t : Impl α β} (hto : t.Ordered) {k : α} :
t.getEntryGE? k = t.toListModel.find? (fun e => (compare e.1 k).isGE) := by
rw [getEntryGE?_eq_getEntryGE?ₘ, getEntryGE?ₘ, applyPartition_eq hto, List.head?_filter,
List.findCell_inner]
simp only [OrientedCmp.eq_swap (b := k), Ordering.isGE_swap, ← Ordering.isEq_eq_beq_eq,
← Ordering.isLT_eq_beq_lt]
change t.toListModel.Pairwise _ at hto
revert hto
induction t.toListModel using List.assoc_induction with
| nil => intro hto; rfl
| cons k' v t ih =>
intro hto
simp only [List.find?_cons]
rw [List.pairwise_cons] at hto
cases h : compare k k'
· simp only [Option.or_some, Ordering.isLE_lt, Option.some.injEq,
Ordering.isLT_lt, Ordering.isEq_lt]
rw [List.find?_eq_none.mpr, Option.getD_none]
intro x hx hkx; have := hto.1 x hx
simp [TransCmp.lt_trans h this] at hkx
· rfl
· exact ih hto.2
theorem getEntryGT?_eq_find? [Ord α] [TransOrd α] {t : Impl α β} (hto : t.Ordered) {k : α} :
t.getEntryGT? k = t.toListModel.find? (fun e => (compare e.1 k).isGT) := by
rw [getEntryGT?_eq_getEntryGT?ₘ, getEntryGT?ₘ, applyPartition_eq hto, List.head?_filter]
congr; funext x; rw [Bool.eq_iff_iff, beq_iff_eq, Ordering.isGT_iff_eq_gt]
simp [OrientedCmp.eq_swap (a := k), Ordering.then_eq_lt]
theorem getEntryLE?_eq_findRev? [Ord α] [TransOrd α] {t : Impl α β} (hto : t.Ordered) {k : α} :
getEntryLE? k t = t.toListModel.findRev? (fun e => (compare e.1 k).isLE) := by
rw [getEntryLE?_eq_getEntryGE?_reverse, @getEntryGE?_eq_find?, List.findRev?_eq_find?_reverse,
toListModel_reverse]
· simp only [Ord.opposite, Bool.coe_iff_coe.mp OrientedCmp.isGE_iff_isLE]
· exact hto.reverse
theorem getEntryLT?_eq_findRev? [Ord α] [TransOrd α] {t : Impl α β} (hto : t.Ordered) {k : α} :
getEntryLT? k t = t.toListModel.findRev? (fun e => (compare e.1 k).isLT) := by
rw [getEntryLT?_eq_getEntryGT?_reverse, @getEntryGT?_eq_find?, List.findRev?_eq_find?_reverse,
toListModel_reverse]
· congr; funext e
rw [← Bool.coe_iff_coe]
simp only [Ord.opposite, Ordering.isGT_iff_eq_gt, Ordering.isLT_iff_eq_lt]
exact OrientedCmp.gt_iff_lt
· exact hto.reverse
end Std.DTreeMap.Internal.Impl

View file

@ -6,6 +6,7 @@ Authors: Markus Himmel, Paul Reichert
prelude
import Std.Data.DTreeMap.Internal.Lemmas
import Std.Data.DTreeMap.Basic
import Std.Data.DTreeMap.AdditionalOperations
/-!
# Dependent tree map lemmas
@ -19,11 +20,11 @@ open Std.DTreeMap.Internal
set_option linter.missingDocs true
set_option autoImplicit false
universe u v w
universe u v w w'
namespace Std.DTreeMap
variable {α : Type u} {β : α → Type v} {cmp : αα → Ordering} {t : DTreeMap α β cmp}
variable {α : Type u} {β : α → Type v} {γ : α → Type w} {cmp : αα → Ordering} {t : DTreeMap α β cmp}
private local instance : Coe (Type v) (α → Type v) where coe γ := fun _ => γ
private theorem ext {t t' : DTreeMap α β cmp} : t.inner = t'.inner → t = t' := by
@ -1153,7 +1154,7 @@ end Const
section monadic
variable {δ : Type w} {m : Type w → Type w}
variable {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m]
{f : δ → (a : α) → β a → m δ} {init : δ} :
@ -2206,7 +2207,7 @@ theorem mem_alter [TransCmp cmp] [LawfulEqCmp cmp] {k k' : α}
if cmp k k' = .eq then (f (t.get? k)).isSome = true else k' ∈ t :=
Impl.mem_alter t.wf
theorem mem_alter_of_compare_eq [TransCmp cmp] [LawfulEqCmp cmp] {k k': α}
theorem mem_alter_of_compare_eq [TransCmp cmp] [LawfulEqCmp cmp] {k k' : α}
{f : Option (β k) → Option (β k)}
(he : cmp k k' = .eq) :
k' ∈ t.alter k f ↔ (f (t.get? k)).isSome :=
@ -2432,7 +2433,7 @@ theorem mem_alter [TransCmp cmp] {k k' : α} {f : Option β → Option β} :
if cmp k k' = .eq then (f (get? t k)).isSome = true else k' ∈ t :=
Impl.Const.mem_alter t.wf
theorem mem_alter_of_compare_eq [TransCmp cmp] {k k': α} {f : Option β → Option β}
theorem mem_alter_of_compare_eq [TransCmp cmp] {k k' : α} {f : Option β → Option β}
(he : cmp k k' = .eq) :
k' ∈ alter t k f ↔ (f (get? t k)).isSome :=
Impl.Const.mem_alter_of_compare_eq t.wf he
@ -4193,4 +4194,628 @@ end Const
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : DTreeMap α β cmp} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (DTreeMap α β cmp) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty :=
h.1.isEmpty_eq
theorem contains_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.contains k = t₂.contains k :=
h.1.contains_eq t₁.2 t₂.2
theorem mem_iff [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
k ∈ t₁ ↔ k ∈ t₂ :=
h.1.mem_iff t₁.2 t₂.2
theorem size_eq (h : t₁ ~m t₂) : t₁.size = t₂.size :=
h.1.size_eq t₁.2 t₂.2
theorem get?_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.get? k = t₂.get? k :=
h.1.get?_eq t₁.2 t₂.2
theorem get_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {hk : k ∈ t₁} (h : t₁ ~m t₂) :
t₁.get k hk = t₂.get k (h.mem_iff.mp hk) :=
h.1.get_eq t₁.2 t₂.2 hk
theorem get!_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} [Inhabited (β k)] (h : t₁ ~m t₂) :
t₁.get! k = t₂.get! k :=
h.1.get!_eq t₁.2 t₂.2
theorem getD_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {fallback : β k} (h : t₁ ~m t₂) :
t₁.getD k fallback = t₂.getD k fallback :=
h.1.getD_eq t₁.2 t₂.2
theorem getKey?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKey? k = t₂.getKey? k :=
h.1.getKey?_eq t₁.2 t₂.2
theorem getKey_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h : t₁ ~m t₂) :
t₁.getKey k hk = t₂.getKey k (h.mem_iff.mp hk) :=
h.1.getKey_eq t₁.2 t₂.2 hk
theorem getKey!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKey! k = t₂.getKey! k :=
h.1.getKey!_eq t₁.2 t₂.2
theorem getKeyD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyD k fallback = t₂.getKeyD k fallback :=
h.1.getKeyD_eq t₁.2 t₂.2
theorem toList_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.toList = t₂.toList :=
h.1.toList_eq t₁.2 t₂.2
theorem toArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.toArray = t₂.toArray :=
h.1.toArray_eq t₁.2 t₂.2
theorem keys_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.keys = t₂.keys :=
h.1.keys_eq t₁.2 t₂.2
theorem keysArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.keysArray = t₂.keysArray :=
h.1.keysArray_eq t₁.2 t₂.2
theorem foldlM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : δ → (a : α) → β a → m δ}
{init : δ} (h : t₁ ~m t₂) :
t₁.foldlM f init = t₂.foldlM f init :=
h.1.foldlM_eq t₁.2 t₂.2
theorem foldl_eq [TransCmp cmp] {f : δ → (a : α) → β a → δ} {init : δ} (h : t₁ ~m t₂) :
t₁.foldl f init = t₂.foldl f init :=
h.1.foldl_eq t₁.2 t₂.2
theorem foldrM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : (a : α) → β a → δ → m δ}
{init : δ} (h : t₁ ~m t₂) :
t₁.foldrM f init = t₂.foldrM f init :=
h.1.foldrM_eq t₁.2 t₂.2
theorem foldr_eq [TransCmp cmp] {f : (a : α) → β a → δ → δ} {init : δ} (h : t₁ ~m t₂) :
t₁.foldr f init = t₂.foldr f init :=
h.1.foldr_eq t₁.2 t₂.2
theorem forIn_eq [TransCmp cmp] [Monad m] [LawfulMonad m]
{b : δ} {f : (a : α) × β a → δ → m (ForInStep δ)} (h : t₁ ~m t₂) :
ForIn.forIn t₁ b f = ForIn.forIn t₂ b f :=
h.1.forIn_eq t₁.2 t₂.2
theorem forM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : (a : α) × β a → m PUnit}
(h : t₁ ~m t₂) :
ForM.forM t₁ f = ForM.forM t₂ f :=
h.1.forM_eq t₁.2 t₂.2
theorem any_eq [TransCmp cmp] {p : (a : α) → β a → Bool} (h : t₁ ~m t₂) : t₁.any p = t₂.any p := by
simp only [any, h.forIn_eq]
theorem all_eq [TransCmp cmp] {p : (a : α) → β a → Bool} (h : t₁ ~m t₂) : t₁.all p = t₂.all p := by
simp only [all, h.forIn_eq]
theorem minKey?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.minKey? = t₂.minKey? :=
h.1.minKey?_eq t₁.2 t₂.2
theorem minKey_eq [TransCmp cmp] {h' : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.minKey h' = t₂.minKey (h.isEmpty_eq.symm.trans h') :=
h.1.minKey_eq t₁.2 t₂.2 h'
theorem minKey!_eq [TransCmp cmp] [Inhabited α] (h : t₁ ~m t₂) :
t₁.minKey! = t₂.minKey! :=
h.1.minKey!_eq t₁.2 t₂.2
theorem minKeyD_eq [TransCmp cmp] {fallback : α} (h : t₁ ~m t₂) :
t₁.minKeyD fallback = t₂.minKeyD fallback :=
h.1.minKeyD_eq t₁.2 t₂.2
theorem maxKey?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.maxKey? = t₂.maxKey? :=
h.1.maxKey?_eq t₁.2 t₂.2
theorem maxKey_eq [TransCmp cmp] {h' : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.maxKey h' = t₂.maxKey (h.isEmpty_eq.symm.trans h') :=
h.1.maxKey_eq t₁.2 t₂.2 h'
theorem maxKey!_eq [TransCmp cmp] [Inhabited α] (h : t₁ ~m t₂) :
t₁.maxKey! = t₂.maxKey! :=
h.1.maxKey!_eq t₁.2 t₂.2
theorem maxKeyD_eq [TransCmp cmp] {fallback : α} (h : t₁ ~m t₂) :
t₁.maxKeyD fallback = t₂.maxKeyD fallback :=
h.1.maxKeyD_eq t₁.2 t₂.2
theorem minEntry?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.minEntry? = t₂.minEntry? :=
h.1.minEntry?_eq t₁.2 t₂.2
theorem minEntry_eq [TransCmp cmp] {he : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.minEntry he = t₂.minEntry (h.isEmpty_eq.symm.trans he) :=
h.1.minEntry_eq t₁.2 t₂.2
theorem minEntry!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] (h : t₁ ~m t₂) :
t₁.minEntry! = t₂.minEntry! :=
h.1.minEntry!_eq t₁.2 t₂.2
theorem minEntryD_eq [TransCmp cmp] {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.minEntryD fallback = t₂.minEntryD fallback :=
h.1.minEntryD_eq t₁.2 t₂.2
theorem maxEntry?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.maxEntry? = t₂.maxEntry? :=
h.1.maxEntry?_eq t₁.2 t₂.2
theorem maxEntry_eq [TransCmp cmp] {he : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.maxEntry he = t₂.maxEntry (h.isEmpty_eq.symm.trans he) :=
h.1.maxEntry_eq t₁.2 t₂.2
theorem maxEntry!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] (h : t₁ ~m t₂) :
t₁.maxEntry! = t₂.maxEntry! :=
h.1.maxEntry!_eq t₁.2 t₂.2
theorem maxEntryD_eq [TransCmp cmp] {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.maxEntryD fallback = t₂.maxEntryD fallback :=
h.1.maxEntryD_eq t₁.2 t₂.2
theorem entryAtIdx?_eq [TransCmp cmp] {i : Nat} (h : t₁ ~m t₂) :
t₁.entryAtIdx? i = t₂.entryAtIdx? i :=
h.1.entryAtIdx?_eq t₁.2 t₂.2
theorem entryAtIdx_eq [TransCmp cmp] {i : Nat} {h' : i < t₁.size} (h : t₁ ~m t₂) :
t₁.entryAtIdx i h' = t₂.entryAtIdx i (h.size_eq ▸ h') :=
h.1.entryAtIdx_eq t₁.2 t₂.2
theorem entryAtIdx!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {i : Nat} (h : t₁ ~m t₂) :
t₁.entryAtIdx! i = t₂.entryAtIdx! i :=
h.1.entryAtIdx!_eq t₁.2 t₂.2
theorem entryAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.entryAtIdxD i fallback = t₂.entryAtIdxD i fallback :=
h.1.entryAtIdxD_eq t₁.2 t₂.2
theorem keyAtIdx?_eq [TransCmp cmp] {i : Nat} (h : t₁ ~m t₂) :
t₁.keyAtIdx? i = t₂.keyAtIdx? i :=
h.1.keyAtIdx?_eq t₁.2 t₂.2
theorem keyAtIdx_eq [TransCmp cmp] {i : Nat} {h' : i < t₁.size} (h : t₁ ~m t₂) :
t₁.keyAtIdx i h' = t₂.keyAtIdx i (h.size_eq ▸ h') :=
h.1.keyAtIdx_eq t₁.2 t₂.2
theorem keyAtIdx!_eq [TransCmp cmp] [Inhabited α] {i : Nat} (h : t₁ ~m t₂) :
t₁.keyAtIdx! i = t₂.keyAtIdx! i :=
h.1.keyAtIdx!_eq t₁.2 t₂.2
theorem keyAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α} (h : t₁ ~m t₂) :
t₁.keyAtIdxD i fallback = t₂.keyAtIdxD i fallback :=
h.1.keyAtIdxD_eq t₁.2 t₂.2
theorem getEntryGE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGE? k = t₂.getEntryGE? k :=
h.1.getEntryGE?_eq t₁.2 t₂.2
theorem getEntryGE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryGE k h' = t₂.getEntryGE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getEntryGE_eq t₁.2 t₂.2
theorem getEntryGE!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGE! k = t₂.getEntryGE! k :=
h.1.getEntryGE!_eq t₁.2 t₂.2
theorem getEntryGED_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.getEntryGED k fallback = t₂.getEntryGED k fallback :=
h.1.getEntryGED_eq t₁.2 t₂.2
theorem getEntryGT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGT? k = t₂.getEntryGT? k :=
h.1.getEntryGT?_eq t₁.2 t₂.2
theorem getEntryGT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryGT k h' = t₂.getEntryGT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getEntryGT_eq t₁.2 t₂.2
theorem getEntryGT!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGT! k = t₂.getEntryGT! k :=
h.1.getEntryGT!_eq t₁.2 t₂.2
theorem getEntryGTD_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.getEntryGTD k fallback = t₂.getEntryGTD k fallback :=
h.1.getEntryGTD_eq t₁.2 t₂.2
theorem getEntryLE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLE? k = t₂.getEntryLE? k :=
h.1.getEntryLE?_eq t₁.2 t₂.2
theorem getEntryLE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryLE k h' = t₂.getEntryLE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getEntryLE_eq t₁.2 t₂.2
theorem getEntryLE!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLE! k = t₂.getEntryLE! k :=
h.1.getEntryLE!_eq t₁.2 t₂.2
theorem getEntryLED_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.getEntryLED k fallback = t₂.getEntryLED k fallback :=
h.1.getEntryLED_eq t₁.2 t₂.2
theorem getEntryLT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLT? k = t₂.getEntryLT? k :=
h.1.getEntryLT?_eq t₁.2 t₂.2
theorem getEntryLT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryLT k h' = t₂.getEntryLT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getEntryLT_eq t₁.2 t₂.2
theorem getEntryLT!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLT! k = t₂.getEntryLT! k :=
h.1.getEntryLT!_eq t₁.2 t₂.2
theorem getEntryLTD_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h : t₁ ~m t₂) :
t₁.getEntryLTD k fallback = t₂.getEntryLTD k fallback :=
h.1.getEntryLTD_eq t₁.2 t₂.2
theorem getKeyGE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGE? k = t₂.getKeyGE? k :=
h.1.getKeyGE?_eq t₁.2 t₂.2
theorem getKeyGE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyGE k h' = t₂.getKeyGE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyGE_eq t₁.2 t₂.2
theorem getKeyGE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGE! k = t₂.getKeyGE! k :=
h.1.getKeyGE!_eq t₁.2 t₂.2
theorem getKeyGED_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyGED k fallback = t₂.getKeyGED k fallback :=
h.1.getKeyGED_eq t₁.2 t₂.2
theorem getKeyGT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGT? k = t₂.getKeyGT? k :=
h.1.getKeyGT?_eq t₁.2 t₂.2
theorem getKeyGT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyGT k h' = t₂.getKeyGT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyGT_eq t₁.2 t₂.2
theorem getKeyGT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGT! k = t₂.getKeyGT! k :=
h.1.getKeyGT!_eq t₁.2 t₂.2
theorem getKeyGTD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyGTD k fallback = t₂.getKeyGTD k fallback :=
h.1.getKeyGTD_eq t₁.2 t₂.2
theorem getKeyLE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLE? k = t₂.getKeyLE? k :=
h.1.getKeyLE?_eq t₁.2 t₂.2
theorem getKeyLE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyLE k h' = t₂.getKeyLE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyLE_eq t₁.2 t₂.2
theorem getKeyLE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLE! k = t₂.getKeyLE! k :=
h.1.getKeyLE!_eq t₁.2 t₂.2
theorem getKeyLED_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyLED k fallback = t₂.getKeyLED k fallback :=
h.1.getKeyLED_eq t₁.2 t₂.2
theorem getKeyLT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLT? k = t₂.getKeyLT? k :=
h.1.getKeyLT?_eq t₁.2 t₂.2
theorem getKeyLT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyLT k h' = t₂.getKeyLT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyLT_eq t₁.2 t₂.2
theorem getKeyLT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLT! k = t₂.getKeyLT! k :=
h.1.getKeyLT!_eq t₁.2 t₂.2
theorem getKeyLTD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyLTD k fallback = t₂.getKeyLTD k fallback :=
h.1.getKeyLTD_eq t₁.2 t₂.2
theorem insert [TransCmp cmp] (h : t₁ ~m t₂) (k : α) (v : β k) : t₁.insert k v ~m t₂.insert k v :=
⟨h.1.insert t₁.2 t₂.2⟩
theorem erase [TransCmp cmp] (h : t₁ ~m t₂) (k : α) : t₁.erase k ~m t₂.erase k :=
⟨h.1.erase t₁.2 t₂.2⟩
theorem insertIfNew [TransCmp cmp] (h : t₁ ~m t₂) (k : α) (v : β k) :
t₁.insertIfNew k v ~m t₂.insertIfNew k v :=
⟨h.1.insertIfNew t₁.2 t₂.2⟩
theorem alter [TransCmp cmp] [LawfulEqCmp cmp] (h : t₁ ~m t₂)
(k : α) (f : Option (β k) → Option (β k)) : t₁.alter k f ~m t₂.alter k f :=
⟨h.1.alter t₁.2 t₂.2⟩
theorem modify [TransCmp cmp] [LawfulEqCmp cmp] (h : t₁ ~m t₂)
(k : α) (f : β k → β k) : t₁.modify k f ~m t₂.modify k f :=
⟨h.1.modify t₁.2 t₂.2⟩
theorem filter (h : t₁ ~m t₂) (f : (a : α) → β a → Bool) : t₁.filter f ~m t₂.filter f :=
⟨h.1.filter t₁.2 t₂.2⟩
theorem map (h : t₁ ~m t₂) (f : (a : α) → β a → γ a) : t₁.map f ~m t₂.map f :=
⟨h.1.map⟩
theorem filterMap (h : t₁ ~m t₂) (f : (a : α) → β a → Option (γ a)) :
t₁.filterMap f ~m t₂.filterMap f :=
⟨h.1.filterMap t₁.2 t₂.2⟩
theorem insertMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List ((a : α) × β a)) :
t₁.insertMany l ~m t₂.insertMany l :=
⟨h.1.insertMany_list t₁.2 t₂.2⟩
theorem eraseMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List α) :
t₁.eraseMany l ~m t₂.eraseMany l :=
⟨h.1.eraseMany_list t₁.2 t₂.2⟩
theorem mergeWith [TransCmp cmp] [LawfulEqCmp cmp] (f : (a : α) → β a → β a → β a)
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) : t₁.mergeWith f t₃ ~m t₂.mergeWith f t₄ :=
⟨h.1.mergeWith h'.1 t₁.2 t₂.2 t₃.2 t₄.2⟩
section Const
variable {β : Type v} {t₁ t₂ t₃ t₄ : DTreeMap α β cmp} {δ : Type w} {m : Type w → Type w}
theorem constGet?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) : Const.get? t₁ k = Const.get? t₂ k :=
h.1.constGet?_eq t₁.2 t₂.2
theorem constGet_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h : t₁ ~m t₂) :
Const.get t₁ k hk = Const.get t₂ k (h.mem_iff.mp hk) :=
h.1.constGet_eq t₁.2 t₂.2 hk
theorem constGet!_eq [TransCmp cmp] [Inhabited β] {k : α} (h : t₁ ~m t₂) :
Const.get! t₁ k = Const.get! t₂ k :=
h.1.constGet!_eq t₁.2 t₂.2
theorem constGetD_eq [TransCmp cmp] {k : α} {fallback : β} (h : t₁ ~m t₂) :
Const.getD t₁ k fallback = Const.getD t₂ k fallback :=
h.1.constGetD_eq t₁.2 t₂.2
theorem constToList_eq [TransCmp cmp] (h : t₁ ~m t₂) : Const.toList t₁ = Const.toList t₂ :=
h.1.constToList_eq t₁.2 t₂.2
theorem constToArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : Const.toArray t₁ = Const.toArray t₂ :=
h.1.constToArray_eq t₁.2 t₂.2
theorem values_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.values = t₂.values :=
h.1.values_eq t₁.2 t₂.2
theorem valuesArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.valuesArray = t₂.valuesArray :=
h.1.valuesArray_eq t₁.2 t₂.2
theorem constMinEntry?_eq [TransCmp cmp] (h : t₁ ~m t₂) :
Const.minEntry? t₁ = Const.minEntry? t₂ :=
h.1.constMinEntry?_eq t₁.2 t₂.2
theorem constMinEntry_eq [TransCmp cmp] {he : t₁.isEmpty = false} (h : t₁ ~m t₂) :
Const.minEntry t₁ he = Const.minEntry t₂ (h.isEmpty_eq.symm.trans he) :=
h.1.constMinEntry_eq t₁.2 t₂.2
theorem constMinEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h : t₁ ~m t₂) :
Const.minEntry! t₁ = Const.minEntry! t₂ :=
h.1.constMinEntry!_eq t₁.2 t₂.2
theorem constMinEntryD_eq [TransCmp cmp] {fallback : α × β} (h : t₁ ~m t₂) :
Const.minEntryD t₁ fallback = Const.minEntryD t₂ fallback :=
h.1.constMinEntryD_eq t₁.2 t₂.2
theorem constMaxEntry?_eq [TransCmp cmp] (h : t₁ ~m t₂) :
Const.maxEntry? t₁ = Const.maxEntry? t₂ :=
h.1.constMaxEntry?_eq t₁.2 t₂.2
theorem constMaxEntry_eq [TransCmp cmp] {he : t₁.isEmpty = false} (h : t₁ ~m t₂) :
Const.maxEntry t₁ he = Const.maxEntry t₂ (h.isEmpty_eq.symm.trans he) :=
h.1.constMaxEntry_eq t₁.2 t₂.2
theorem constMaxEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h : t₁ ~m t₂) :
Const.maxEntry! t₁ = Const.maxEntry! t₂ :=
h.1.constMaxEntry!_eq t₁.2 t₂.2
theorem constMaxEntryD_eq [TransCmp cmp] {fallback : α × β} (h : t₁ ~m t₂) :
Const.maxEntryD t₁ fallback = Const.maxEntryD t₂ fallback :=
h.1.constMaxEntryD_eq t₁.2 t₂.2
theorem constEntryAtIdx?_eq [TransCmp cmp] {i : Nat} (h : t₁ ~m t₂) :
Const.entryAtIdx? t₁ i = Const.entryAtIdx? t₂ i :=
h.1.constEntryAtIdx?_eq t₁.2 t₂.2
theorem constEntryAtIdx_eq [TransCmp cmp] {i : Nat} {h' : i < t₁.size} (h : t₁ ~m t₂) :
Const.entryAtIdx t₁ i h' = Const.entryAtIdx t₂ i (h.size_eq ▸ h') :=
h.1.constEntryAtIdx_eq t₁.2 t₂.2
theorem constEntryAtIdx!_eq [TransCmp cmp] [Inhabited (α × β)] {i : Nat} (h : t₁ ~m t₂) :
Const.entryAtIdx! t₁ i = Const.entryAtIdx! t₂ i :=
h.1.constEntryAtIdx!_eq t₁.2 t₂.2
theorem constEntryAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α × β} (h : t₁ ~m t₂) :
Const.entryAtIdxD t₁ i fallback = Const.entryAtIdxD t₂ i fallback :=
h.1.constEntryAtIdxD_eq t₁.2 t₂.2
theorem constGetEntryGE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
Const.getEntryGE? t₁ k = Const.getEntryGE? t₂ k :=
h.1.constGetEntryGE?_eq t₁.2 t₂.2
theorem constGetEntryGE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
Const.getEntryGE t₁ k h' = Const.getEntryGE t₂ k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryGE_eq t₁.2 t₂.2
theorem constGetEntryGE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
Const.getEntryGE! t₁ k = Const.getEntryGE! t₂ k :=
h.1.constGetEntryGE!_eq t₁.2 t₂.2
theorem constGetEntryGED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
Const.getEntryGED t₁ k fallback = Const.getEntryGED t₂ k fallback :=
h.1.constGetEntryGED_eq t₁.2 t₂.2
theorem constGetEntryGT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
Const.getEntryGT? t₁ k = Const.getEntryGT? t₂ k :=
h.1.constGetEntryGT?_eq t₁.2 t₂.2
theorem constGetEntryGT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
Const.getEntryGT t₁ k h' = Const.getEntryGT t₂ k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryGT_eq t₁.2 t₂.2
theorem constGetEntryGT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
Const.getEntryGT! t₁ k = Const.getEntryGT! t₂ k :=
h.1.constGetEntryGT!_eq t₁.2 t₂.2
theorem constGetEntryGTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
Const.getEntryGTD t₁ k fallback = Const.getEntryGTD t₂ k fallback :=
h.1.constGetEntryGTD_eq t₁.2 t₂.2
theorem constGetEntryLE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
Const.getEntryLE? t₁ k = Const.getEntryLE? t₂ k :=
h.1.constGetEntryLE?_eq t₁.2 t₂.2
theorem constGetEntryLE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
Const.getEntryLE t₁ k h' = Const.getEntryLE t₂ k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryLE_eq t₁.2 t₂.2
theorem constGetEntryLE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
Const.getEntryLE! t₁ k = Const.getEntryLE! t₂ k :=
h.1.constGetEntryLE!_eq t₁.2 t₂.2
theorem constGetEntryLED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
Const.getEntryLED t₁ k fallback = Const.getEntryLED t₂ k fallback :=
h.1.constGetEntryLED_eq t₁.2 t₂.2
theorem constGetEntryLT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
Const.getEntryLT? t₁ k = Const.getEntryLT? t₂ k :=
h.1.constGetEntryLT?_eq t₁.2 t₂.2
theorem constGetEntryLT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
Const.getEntryLT t₁ k h' = Const.getEntryLT t₂ k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryLT_eq t₁.2 t₂.2
theorem constGetEntryLT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
Const.getEntryLT! t₁ k = Const.getEntryLT! t₂ k :=
h.1.constGetEntryLT!_eq t₁.2 t₂.2
theorem constGetEntryLTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
Const.getEntryLTD t₁ k fallback = Const.getEntryLTD t₂ k fallback :=
h.1.constGetEntryLTD_eq t₁.2 t₂.2
theorem constAlter [TransCmp cmp] (h : t₁ ~m t₂) (k : α) (f : Option β → Option β) :
Const.alter t₁ k f ~m Const.alter t₂ k f :=
⟨h.1.constAlter t₁.2 t₂.2⟩
theorem constModify [TransCmp cmp] (h : t₁ ~m t₂) (k : α) (f : β → β) :
Const.modify t₁ k f ~m Const.modify t₂ k f :=
⟨h.1.constModify t₁.2 t₂.2⟩
theorem constInsertMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List (α × β)) :
Const.insertMany t₁ l ~m Const.insertMany t₂ l :=
⟨h.1.constInsertMany_list t₁.2 t₂.2⟩
theorem constInsertManyIfNewUnit_list [TransCmp cmp] {t₁ t₂ : DTreeMap α Unit cmp}
(h : t₁ ~m t₂) (l : List α) :
Const.insertManyIfNewUnit t₁ l ~m Const.insertManyIfNewUnit t₂ l :=
⟨h.1.constInsertManyIfNewUnit_list t₁.2 t₂.2⟩
theorem constMergeWith [TransCmp cmp] (f : α → β → β → β) (h : t₁ ~m t₂) (h' : t₃ ~m t₄) :
Const.mergeWith f t₁ t₃ ~m Const.mergeWith f t₂ t₄ :=
⟨h.1.constMergeWith h'.1 t₁.2 t₂.2 t₃.2 t₄.2⟩
end Const
-- extensionalities
theorem of_forall_get?_eq [TransCmp cmp] [LawfulEqCmp cmp]
(h : ∀ k, t₁.get? k = t₂.get? k) : t₁ ~m t₂ :=
⟨.of_forall_get?_eq t₁.2 t₂.2 h⟩
section Const
variable {β : Type v} {t₁ t₂ : DTreeMap α β cmp}
theorem of_forall_getKey_eq_of_forall_constGet?_eq [TransCmp cmp]
(hk : ∀ k hk hk', t₁.getKey k hk = t₂.getKey k hk')
(hv : ∀ k, Const.get? t₁ k = Const.get? t₂ k) : t₁ ~m t₂ :=
⟨.of_forall_getKey_eq_of_forall_constGet?_eq t₁.2 t₂.2 hk hv⟩
theorem of_forall_constGet?_eq [TransCmp cmp] [LawfulEqCmp cmp]
(h : ∀ k, Const.get? t₁ k = Const.get? t₂ k) : t₁ ~m t₂ :=
⟨.of_forall_constGet?_eq t₁.2 t₂.2 h⟩
theorem of_forall_getKey?_unit_eq [TransCmp cmp] {t₁ t₂ : DTreeMap α Unit cmp}
(h : ∀ k, t₁.getKey? k = t₂.getKey? k) : t₁ ~m t₂ :=
⟨.of_forall_getKey?_unit_eq t₁.2 t₂.2 h⟩
theorem of_forall_contains_unit_eq [TransCmp cmp] [LawfulEqCmp cmp] {t₁ t₂ : DTreeMap α Unit cmp}
(h : ∀ k, t₁.contains k = t₂.contains k) : t₁ ~m t₂ :=
⟨.of_forall_contains_unit_eq t₁.2 t₂.2 h⟩
theorem of_forall_mem_unit_iff [TransCmp cmp] [LawfulEqCmp cmp] {t₁ t₂ : DTreeMap α Unit cmp}
(h : ∀ k, k ∈ t₁ ↔ k ∈ t₂) : t₁ ~m t₂ :=
⟨.of_forall_mem_unit_iff t₁.2 t₂.2 h⟩
end Const
end Equiv
section Equiv
variable {t₁ t₂ : DTreeMap α β cmp}
private theorem equiv_iff_equiv : t₁ ~m t₂ ↔ t₁.1.Equiv t₂.1 :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty :=
equiv_iff_equiv.trans Impl.equiv_empty_iff_isEmpty
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
Equiv.comm.trans equiv_empty_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList :=
equiv_iff_equiv.trans Impl.equiv_iff_toList_perm
theorem Equiv.of_toList_perm (h : t₁.toList.Perm t₂.toList) : t₁ ~m t₂ :=
⟨.of_toList_perm h⟩
theorem equiv_iff_toList_eq [TransCmp cmp] :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
equiv_iff_equiv.trans (Impl.equiv_iff_toList_eq t₁.2 t₂.2)
section Const
variable {β : Type v} {t₁ t₂ : DTreeMap α β cmp}
theorem Const.equiv_iff_toList_perm : t₁ ~m t₂ ↔ (Const.toList t₁).Perm (Const.toList t₂) :=
equiv_iff_equiv.trans Impl.Const.equiv_iff_toList_perm
theorem Const.equiv_iff_toList_eq [TransCmp cmp] : t₁ ~m t₂ ↔ Const.toList t₁ = Const.toList t₂ :=
equiv_iff_equiv.trans (Impl.Const.equiv_iff_toList_eq t₁.2 t₂.2)
theorem Const.equiv_iff_keys_unit_perm {t₁ t₂ : DTreeMap α Unit cmp} : t₁ ~m t₂ ↔ t₁.keys.Perm t₂.keys :=
equiv_iff_equiv.trans Impl.Const.equiv_iff_keys_perm
theorem Const.equiv_iff_keys_unit_eq [TransCmp cmp] {t₁ t₂ : DTreeMap α Unit cmp} :
t₁ ~m t₂ ↔ t₁.keys = t₂.keys :=
equiv_iff_equiv.trans (Impl.Const.equiv_iff_keys_eq t₁.2 t₂.2)
theorem Equiv.of_constToList_perm : (Const.toList t₁).Perm (Const.toList t₂) → t₁ ~m t₂ :=
Const.equiv_iff_toList_perm.mpr
theorem Equiv.of_keys_unit_perm {t₁ t₂ : DTreeMap α Unit cmp} : t₁.keys.Perm t₂.keys → t₁ ~m t₂ :=
Const.equiv_iff_keys_unit_perm.mpr
end Const
end Equiv
end Std.DTreeMap

View file

@ -92,6 +92,13 @@ instance : EmptyCollection (Raw α β cmp) := ⟨empty⟩
instance : Inhabited (Raw α β cmp) := ⟨∅⟩
@[inherit_doc Impl.Equiv]
structure Equiv (m₁ m₂ : Raw α β cmp) where
/-- Internal implementation detail of the tree map -/
inner : m₁.1.Equiv m₂.1
@[inherit_doc] scoped infix:50 " ~m " => Equiv
@[simp]
theorem empty_eq_emptyc : (empty : Raw α β cmp) = ∅ :=
rfl

View file

@ -6,6 +6,7 @@ Authors: Markus Himmel, Paul Reichert
prelude
import Std.Data.DTreeMap.Internal.Lemmas
import Std.Data.DTreeMap.Raw.Basic
import Std.Data.DTreeMap.Raw.AdditionalOperations
/-!
# Dependent tree map lemmas
@ -20,11 +21,11 @@ set_option autoImplicit false
open Std.DTreeMap.Internal
universe u v w
universe u v w w'
namespace Std.DTreeMap.Raw
variable {α : Type u} {β : α → Type v} {cmp : αα → Ordering} {t : DTreeMap.Raw α β cmp}
variable {α : Type u} {β : α → Type v} {γ : α → Type w} {cmp : αα → Ordering} {t : DTreeMap.Raw α β cmp}
private local instance : Coe (Type v) (α → Type v) where coe γ := fun _ => γ
private theorem ext {t t' : Raw α β cmp} : t.inner = t'.inner → t = t' := by
@ -1164,7 +1165,7 @@ end Const
section monadic
variable {δ : Type w} {m : Type w → Type w}
variable {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m] {f : δ → (a : α) → β a → m δ} {init : δ} :
t.foldlM f init = t.toList.foldlM (fun a b => f a b.1 b.2) init :=
@ -2241,7 +2242,7 @@ theorem mem_alter [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k k' : α}
k' ∈ t.alter k f ↔ if cmp k k' = .eq then (f (t.get? k)).isSome = true else k' ∈ t :=
Impl.mem_alter! h
theorem mem_alter_of_compare_eq [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k k': α}
theorem mem_alter_of_compare_eq [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k k' : α}
{f : Option (β k) → Option (β k)}
(he : cmp k k' = .eq) :
k' ∈ t.alter k f ↔ (f (t.get? k)).isSome :=
@ -2467,7 +2468,7 @@ theorem mem_alter [TransCmp cmp] (h : t.WF) {k k' : α} {f : Option β → Optio
if cmp k k' = .eq then (f (get? t k)).isSome = true else k' ∈ t :=
Impl.Const.mem_alter! h
theorem mem_alter_of_compare_eq [TransCmp cmp] (h : t.WF) {k k': α} {f : Option β → Option β}
theorem mem_alter_of_compare_eq [TransCmp cmp] (h : t.WF) {k k' : α} {f : Option β → Option β}
(he : cmp k k' = .eq) :
k' ∈ alter t k f ↔ (f (get? t k)).isSome :=
Impl.Const.mem_alter!_of_compare_eq h he
@ -3130,7 +3131,7 @@ theorem minKey?_modify_eq_minKey? [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k
Impl.Const.minKey?_modify_eq_minKey? h
@[grind =]
theorem isSome_minKey?_modify [TransCmp cmp] {k f} (h : t.WF) :
theorem isSome_minKey?_modify [TransCmp cmp] {k f} (h : t.WF) :
(Const.modify t k f).minKey?.isSome = !t.isEmpty :=
Impl.Const.isSome_minKey?_modify h
@ -3627,7 +3628,7 @@ theorem maxKey?_modify_eq_maxKey? [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k
(Const.modify t k f).maxKey? = t.maxKey? :=
Impl.Const.maxKey?_modify_eq_maxKey? h
theorem isSome_maxKey?_modify [TransCmp cmp] {k f} (h : t.WF) :
theorem isSome_maxKey?_modify [TransCmp cmp] {k f} (h : t.WF) :
(Const.modify t k f).maxKey?.isSome = !t.isEmpty :=
Impl.Const.isSome_maxKey?_modify h
@ -3941,4 +3942,576 @@ end Const
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : Raw α β cmp} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (Raw α β cmp) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty :=
h.1.isEmpty_eq
theorem contains_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.contains k = t₂.contains k :=
h.1.contains_eq h₁.1 h₂.1
theorem mem_iff [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
k ∈ t₁ ↔ k ∈ t₂ :=
h.1.mem_iff h₁.1 h₂.1
theorem size_eq (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.size = t₂.size :=
h.1.size_eq h₁.1 h₂.1
theorem get?_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.get? k = t₂.get? k :=
h.1.get?_eq h₁.1 h₂.1
theorem get_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {hk : k ∈ t₁} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.get k hk = t₂.get k ((h.mem_iff h₁ h₂).mp hk) :=
h.1.get_eq h₁.1 h₂.1 hk
theorem get!_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} [Inhabited (β k)] (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.get! k = t₂.get! k :=
h.1.get!_eq h₁.1 h₂.1
theorem getD_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {fallback : β k} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getD k fallback = t₂.getD k fallback :=
h.1.getD_eq h₁.1 h₂.1
theorem getKey?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKey? k = t₂.getKey? k :=
h.1.getKey?_eq h₁.1 h₂.1
theorem getKey_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKey k hk = t₂.getKey k ((h.mem_iff h₁ h₂).mp hk) :=
h.1.getKey_eq h₁.1 h₂.1 hk
theorem getKey!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKey! k = t₂.getKey! k :=
h.1.getKey!_eq h₁.1 h₂.1
theorem getKeyD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyD k fallback = t₂.getKeyD k fallback :=
h.1.getKeyD_eq h₁.1 h₂.1
theorem toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.toList = t₂.toList :=
h.1.toList_eq h₁.1 h₂.1
theorem toArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.toArray = t₂.toArray :=
h.1.toArray_eq h₁.1 h₂.1
theorem keys_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.keys = t₂.keys :=
h.1.keys_eq h₁.1 h₂.1
theorem keysArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.keysArray = t₂.keysArray :=
h.1.keysArray_eq h₁.1 h₂.1
theorem foldlM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : δ → (a : α) → β a → m δ}
{init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.foldlM f init = t₂.foldlM f init :=
h.1.foldlM_eq h₁.1 h₂.1
theorem foldl_eq [TransCmp cmp] {f : δ → (a : α) → β a → δ} {init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) :
t₁.foldl f init = t₂.foldl f init :=
h.1.foldl_eq h₁.1 h₂.1
theorem foldrM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : (a : α) → β a → δ → m δ}
{init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.foldrM f init = t₂.foldrM f init :=
h.1.foldrM_eq h₁.1 h₂.1
theorem foldr_eq [TransCmp cmp] {f : (a : α) → β a → δ → δ} {init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) :
t₁.foldr f init = t₂.foldr f init :=
h.1.foldr_eq h₁.1 h₂.1
theorem forIn_eq [TransCmp cmp] [Monad m] [LawfulMonad m]
{b : δ} {f : (a : α) × β a → δ → m (ForInStep δ)} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
ForIn.forIn t₁ b f = ForIn.forIn t₂ b f :=
h.1.forIn_eq h₁.1 h₂.1
theorem forM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : (a : α) × β a → m PUnit}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
ForM.forM t₁ f = ForM.forM t₂ f :=
h.1.forM_eq h₁.1 h₂.1
theorem any_eq [TransCmp cmp] {p : (a : α) → β a → Bool} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.any p = t₂.any p := by
simp only [any, h.forIn_eq h₁ h₂]
theorem all_eq [TransCmp cmp] {p : (a : α) → β a → Bool} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.all p = t₂.all p := by
simp only [all, h.forIn_eq h₁ h₂]
theorem minKey?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKey? = t₂.minKey? :=
h.1.minKey?_eq h₁.1 h₂.1
theorem minKey!_eq [TransCmp cmp] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKey! = t₂.minKey! :=
h.1.minKey!_eq h₁.1 h₂.1
theorem minKeyD_eq [TransCmp cmp] {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKeyD fallback = t₂.minKeyD fallback :=
h.1.minKeyD_eq h₁.1 h₂.1
theorem maxKey?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKey? = t₂.maxKey? :=
h.1.maxKey?_eq h₁.1 h₂.1
theorem maxKey!_eq [TransCmp cmp] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKey! = t₂.maxKey! :=
h.1.maxKey!_eq h₁.1 h₂.1
theorem maxKeyD_eq [TransCmp cmp] {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKeyD fallback = t₂.maxKeyD fallback :=
h.1.maxKeyD_eq h₁.1 h₂.1
theorem minEntry?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minEntry? = t₂.minEntry? :=
h.1.minEntry?_eq h₁.1 h₂.1
theorem minEntry!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.minEntry! = t₂.minEntry! :=
h.1.minEntry!_eq h₁.1 h₂.1
theorem minEntryD_eq [TransCmp cmp] {fallback : (a : α) × β a} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.minEntryD fallback = t₂.minEntryD fallback :=
h.1.minEntryD_eq h₁.1 h₂.1
theorem maxEntry?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxEntry? = t₂.maxEntry? :=
h.1.maxEntry?_eq h₁.1 h₂.1
theorem maxEntry!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.maxEntry! = t₂.maxEntry! :=
h.1.maxEntry!_eq h₁.1 h₂.1
theorem maxEntryD_eq [TransCmp cmp] {fallback : (a : α) × β a} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.maxEntryD fallback = t₂.maxEntryD fallback :=
h.1.maxEntryD_eq h₁.1 h₂.1
theorem entryAtIdx?_eq [TransCmp cmp] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.entryAtIdx? i = t₂.entryAtIdx? i :=
h.1.entryAtIdx?_eq h₁.1 h₂.1
theorem entryAtIdx!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {i : Nat} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.entryAtIdx! i = t₂.entryAtIdx! i :=
h.1.entryAtIdx!_eq h₁.1 h₂.1
theorem entryAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : (a : α) × β a} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.entryAtIdxD i fallback = t₂.entryAtIdxD i fallback :=
h.1.entryAtIdxD_eq h₁.1 h₂.1
theorem keyAtIdx?_eq [TransCmp cmp] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.keyAtIdx? i = t₂.keyAtIdx? i :=
h.1.keyAtIdx?_eq h₁.1 h₂.1
theorem keyAtIdx!_eq [TransCmp cmp] [Inhabited α] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.keyAtIdx! i = t₂.keyAtIdx! i :=
h.1.keyAtIdx!_eq h₁.1 h₂.1
theorem keyAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.keyAtIdxD i fallback = t₂.keyAtIdxD i fallback :=
h.1.keyAtIdxD_eq h₁.1 h₂.1
theorem getEntryGE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryGE? k = t₂.getEntryGE? k :=
h.1.getEntryGE?_eq h₁.1 h₂.1
theorem getEntryGE!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryGE! k = t₂.getEntryGE! k :=
h.1.getEntryGE!_eq h₁.1 h₂.1
theorem getEntryGED_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryGED k fallback = t₂.getEntryGED k fallback :=
h.1.getEntryGED_eq h₁.1 h₂.1
theorem getEntryGT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryGT? k = t₂.getEntryGT? k :=
h.1.getEntryGT?_eq h₁.1 h₂.1
theorem getEntryGT!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryGT! k = t₂.getEntryGT! k :=
h.1.getEntryGT!_eq h₁.1 h₂.1
theorem getEntryGTD_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryGTD k fallback = t₂.getEntryGTD k fallback :=
h.1.getEntryGTD_eq h₁.1 h₂.1
theorem getEntryLE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryLE? k = t₂.getEntryLE? k :=
h.1.getEntryLE?_eq h₁.1 h₂.1
theorem getEntryLE!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryLE! k = t₂.getEntryLE! k :=
h.1.getEntryLE!_eq h₁.1 h₂.1
theorem getEntryLED_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryLED k fallback = t₂.getEntryLED k fallback :=
h.1.getEntryLED_eq h₁.1 h₂.1
theorem getEntryLT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryLT? k = t₂.getEntryLT? k :=
h.1.getEntryLT?_eq h₁.1 h₂.1
theorem getEntryLT!_eq [TransCmp cmp] [Inhabited ((a : α) × β a)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryLT! k = t₂.getEntryLT! k :=
h.1.getEntryLT!_eq h₁.1 h₂.1
theorem getEntryLTD_eq [TransCmp cmp] {k : α} {fallback : (a : α) × β a} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryLTD k fallback = t₂.getEntryLTD k fallback :=
h.1.getEntryLTD_eq h₁.1 h₂.1
theorem getKeyGE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGE? k = t₂.getKeyGE? k :=
h.1.getKeyGE?_eq h₁.1 h₂.1
theorem getKeyGE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGE! k = t₂.getKeyGE! k :=
h.1.getKeyGE!_eq h₁.1 h₂.1
theorem getKeyGED_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGED k fallback = t₂.getKeyGED k fallback :=
h.1.getKeyGED_eq h₁.1 h₂.1
theorem getKeyGT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGT? k = t₂.getKeyGT? k :=
h.1.getKeyGT?_eq h₁.1 h₂.1
theorem getKeyGT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGT! k = t₂.getKeyGT! k :=
h.1.getKeyGT!_eq h₁.1 h₂.1
theorem getKeyGTD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGTD k fallback = t₂.getKeyGTD k fallback :=
h.1.getKeyGTD_eq h₁.1 h₂.1
theorem getKeyLE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLE? k = t₂.getKeyLE? k :=
h.1.getKeyLE?_eq h₁.1 h₂.1
theorem getKeyLE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLE! k = t₂.getKeyLE! k :=
h.1.getKeyLE!_eq h₁.1 h₂.1
theorem getKeyLED_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLED k fallback = t₂.getKeyLED k fallback :=
h.1.getKeyLED_eq h₁.1 h₂.1
theorem getKeyLT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLT? k = t₂.getKeyLT? k :=
h.1.getKeyLT?_eq h₁.1 h₂.1
theorem getKeyLT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLT! k = t₂.getKeyLT! k :=
h.1.getKeyLT!_eq h₁.1 h₂.1
theorem getKeyLTD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLTD k fallback = t₂.getKeyLTD k fallback :=
h.1.getKeyLTD_eq h₁.1 h₂.1
theorem insert [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (v : β k) : t₁.insert k v ~m t₂.insert k v :=
⟨h.1.insert! h₁.1 h₂.1⟩
theorem erase [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) : t₁.erase k ~m t₂.erase k :=
⟨h.1.erase! h₁.1 h₂.1⟩
theorem insertIfNew [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (v : β k) : t₁.insertIfNew k v ~m t₂.insertIfNew k v :=
⟨h.1.insertIfNew! h₁.1 h₂.1⟩
theorem alter [TransCmp cmp] [LawfulEqCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (f : Option (β k) → Option (β k)) :
t₁.alter k f ~m t₂.alter k f :=
⟨h.1.alter! h₁.1 h₂.1⟩
theorem modify [TransCmp cmp] [LawfulEqCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (f : β k → β k) : t₁.modify k f ~m t₂.modify k f :=
⟨h.1.modify h₁.1 h₂.1⟩
theorem filter (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (f : (a : α) → β a → Bool) :
t₁.filter f ~m t₂.filter f :=
⟨h.1.filter! h₁.1 h₂.1⟩
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)) :
t₁.filterMap f ~m t₂.filterMap f :=
⟨h.1.filterMap! h₁.1 h₂.1⟩
theorem insertMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(l : List ((a : α) × β a)) : t₁.insertMany l ~m t₂.insertMany l :=
⟨h.1.insertMany!_list h₁.1 h₂.1⟩
theorem eraseMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (l : List α) :
t₁.eraseMany l ~m t₂.eraseMany l :=
⟨h.1.eraseMany!_list h₁.1 h₂.1⟩
theorem mergeWith [TransCmp cmp] [LawfulEqCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
(f : (a : α) → β a → β a → β a)
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) :
t₁.mergeWith f t₃ ~m t₂.mergeWith f t₄ :=
⟨h.1.mergeWith! h'.1 h₁.1 h₂.1 h₃.1 h₄.1⟩
section Const
variable {β : Type v} {t₁ t₂ t₃ t₄ : Raw α β cmp} (δ : Type w) (m : Type w → Type w)
theorem constGet?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.get? t₁ k = Const.get? t₂ k :=
h.1.constGet?_eq h₁.1 h₂.1
theorem constGet_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.get t₁ k hk = Const.get t₂ k ((h.mem_iff h₁ h₂).mp hk) :=
h.1.constGet_eq h₁.1 h₂.1 hk
theorem constGet!_eq [TransCmp cmp] [Inhabited β] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.get! t₁ k = Const.get! t₂ k :=
h.1.constGet!_eq h₁.1 h₂.1
theorem constGetD_eq [TransCmp cmp] {k : α} {fallback : β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getD t₁ k fallback = Const.getD t₂ k fallback :=
h.1.constGetD_eq h₁.1 h₂.1
theorem constToList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.toList t₁ = Const.toList t₂ :=
h.1.constToList_eq h₁.1 h₂.1
theorem constToArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.toArray t₁ = Const.toArray t₂ :=
h.1.constToArray_eq h₁.1 h₂.1
theorem values_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.values = t₂.values :=
h.1.values_eq h₁.1 h₂.1
theorem valuesArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.valuesArray = t₂.valuesArray :=
h.1.valuesArray_eq h₁.1 h₂.1
theorem constMinEntry?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.minEntry? t₁ = Const.minEntry? t₂ :=
h.1.constMinEntry?_eq h₁.1 h₂.1
theorem constMinEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.minEntry! t₁ = Const.minEntry! t₂ :=
h.1.constMinEntry!_eq h₁.1 h₂.1
theorem constMinEntryD_eq [TransCmp cmp] {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.minEntryD t₁ fallback = Const.minEntryD t₂ fallback :=
h.1.constMinEntryD_eq h₁.1 h₂.1
theorem constMaxEntry?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.maxEntry? t₁ = Const.maxEntry? t₂ :=
h.1.constMaxEntry?_eq h₁.1 h₂.1
theorem constMaxEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.maxEntry! t₁ = Const.maxEntry! t₂ :=
h.1.constMaxEntry!_eq h₁.1 h₂.1
theorem constMaxEntryD_eq [TransCmp cmp] {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.maxEntryD t₁ fallback = Const.maxEntryD t₂ fallback :=
h.1.constMaxEntryD_eq h₁.1 h₂.1
theorem constEntryAtIdx?_eq [TransCmp cmp] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.entryAtIdx? t₁ i = Const.entryAtIdx? t₂ i :=
h.1.constEntryAtIdx?_eq h₁.1 h₂.1
theorem constEntryAtIdx!_eq [TransCmp cmp] [Inhabited (α × β)] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.entryAtIdx! t₁ i = Const.entryAtIdx! t₂ i :=
h.1.constEntryAtIdx!_eq h₁.1 h₂.1
theorem constEntryAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.entryAtIdxD t₁ i fallback = Const.entryAtIdxD t₂ i fallback :=
h.1.constEntryAtIdxD_eq h₁.1 h₂.1
theorem constGetEntryGE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.getEntryGE? t₁ k = Const.getEntryGE? t₂ k :=
h.1.constGetEntryGE?_eq h₁.1 h₂.1
theorem constGetEntryGE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryGE! t₁ k = Const.getEntryGE! t₂ k :=
h.1.constGetEntryGE!_eq h₁.1 h₂.1
theorem constGetEntryGED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryGED t₁ k fallback = Const.getEntryGED t₂ k fallback :=
h.1.constGetEntryGED_eq h₁.1 h₂.1
theorem constGetEntryGT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.getEntryGT? t₁ k = Const.getEntryGT? t₂ k :=
h.1.constGetEntryGT?_eq h₁.1 h₂.1
theorem constGetEntryGT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryGT! t₁ k = Const.getEntryGT! t₂ k :=
h.1.constGetEntryGT!_eq h₁.1 h₂.1
theorem constGetEntryGTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryGTD t₁ k fallback = Const.getEntryGTD t₂ k fallback :=
h.1.constGetEntryGTD_eq h₁.1 h₂.1
theorem constGetEntryLE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.getEntryLE? t₁ k = Const.getEntryLE? t₂ k :=
h.1.constGetEntryLE?_eq h₁.1 h₂.1
theorem constGetEntryLE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryLE! t₁ k = Const.getEntryLE! t₂ k :=
h.1.constGetEntryLE!_eq h₁.1 h₂.1
theorem constGetEntryLED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryLED t₁ k fallback = Const.getEntryLED t₂ k fallback :=
h.1.constGetEntryLED_eq h₁.1 h₂.1
theorem constGetEntryLT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
Const.getEntryLT? t₁ k = Const.getEntryLT? t₂ k :=
h.1.constGetEntryLT?_eq h₁.1 h₂.1
theorem constGetEntryLT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryLT! t₁ k = Const.getEntryLT! t₂ k :=
h.1.constGetEntryLT!_eq h₁.1 h₂.1
theorem constGetEntryLTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : Const.getEntryLTD t₁ k fallback = Const.getEntryLTD t₂ k fallback :=
h.1.constGetEntryLTD_eq h₁.1 h₂.1
theorem constAlter [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (f : Option β → Option β) :
Const.alter t₁ k f ~m Const.alter t₂ k f :=
⟨h.1.constAlter! h₁.1 h₂.1⟩
theorem constModify [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (f : β → β) : Const.modify t₁ k f ~m Const.modify t₂ k f :=
⟨h.1.constModify h₁.1 h₂.1⟩
theorem constInsertMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(l : List (α × β)) : Const.insertMany t₁ l ~m Const.insertMany t₂ l :=
⟨h.1.constInsertMany!_list h₁.1 h₂.1⟩
theorem constInsertManyIfNewUnit_list [TransCmp cmp] {t₁ t₂ : Raw α Unit cmp}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (l : List α) :
Const.insertManyIfNewUnit t₁ l ~m Const.insertManyIfNewUnit t₂ l :=
⟨h.1.constInsertManyIfNewUnit!_list h₁.1 h₂.1⟩
theorem constMergeWith [TransCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
(f : α → β → β → β)
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) :
Const.mergeWith f t₁ t₃ ~m Const.mergeWith f t₂ t₄ :=
⟨h.1.constMergeWith! h'.1 h₁.1 h₂.1 h₃.1 h₄.1⟩
end Const
-- extensionalities
theorem of_forall_get?_eq [TransCmp cmp] [LawfulEqCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, t₁.get? k = t₂.get? k) : t₁ ~m t₂ :=
⟨.of_forall_get?_eq h₁.1 h₂.1 h⟩
section Const
variable {β : Type v} {t₁ t₂ : Raw α β cmp}
theorem of_forall_getKey_eq_of_forall_constGet?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF)
(hk : ∀ k hk hk', t₁.getKey k hk = t₂.getKey k hk')
(hv : ∀ k, Const.get? t₁ k = Const.get? t₂ k) : t₁ ~m t₂ :=
⟨.of_forall_getKey_eq_of_forall_constGet?_eq h₁.1 h₂.1 hk hv⟩
theorem of_forall_constGet?_eq [TransCmp cmp] [LawfulEqCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, Const.get? t₁ k = Const.get? t₂ k) : t₁ ~m t₂ :=
⟨.of_forall_constGet?_eq h₁.1 h₂.1 h⟩
theorem of_forall_getKey?_unit_eq [TransCmp cmp] {t₁ t₂ : Raw α Unit cmp}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : ∀ k, t₁.getKey? k = t₂.getKey? k) : t₁ ~m t₂ :=
⟨.of_forall_getKey?_unit_eq h₁.1 h₂.1 h⟩
theorem of_forall_contains_unit_eq [TransCmp cmp] [LawfulEqCmp cmp]
{t₁ t₂ : Raw α Unit cmp} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, t₁.contains k = t₂.contains k) : t₁ ~m t₂ :=
⟨.of_forall_contains_unit_eq h₁.1 h₂.1 h⟩
theorem of_forall_mem_unit_iff [TransCmp cmp] [LawfulEqCmp cmp]
{t₁ t₂ : Raw α Unit cmp} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, k ∈ t₁ ↔ k ∈ t₂) : t₁ ~m t₂ :=
⟨.of_forall_mem_unit_iff h₁.1 h₂.1 h⟩
end Const
end Equiv
section Equiv
variable {t₁ t₂ : Raw α β cmp}
private theorem equiv_iff : t₁ ~m t₂ ↔ t₁.1.Equiv t₂.1 :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty :=
equiv_iff.trans Impl.equiv_empty_iff_isEmpty
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
equiv_iff.trans Impl.empty_equiv_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList :=
equiv_iff.trans Impl.equiv_iff_toList_perm
theorem Equiv.of_toList_perm (h : t₁.toList.Perm t₂.toList) : t₁ ~m t₂ :=
⟨.of_toList_perm h⟩
theorem equiv_iff_toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
equiv_iff.trans (Impl.equiv_iff_toList_eq h₁.1 h₂.1)
section Const
variable {β : Type v} {t₁ t₂ : Raw α β cmp}
theorem Const.equiv_iff_toList_perm : t₁ ~m t₂ ↔ (Const.toList t₁).Perm (Const.toList t₂) :=
equiv_iff.trans Impl.Const.equiv_iff_toList_perm
theorem Const.equiv_iff_toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ Const.toList t₁ = Const.toList t₂ :=
equiv_iff.trans (Impl.Const.equiv_iff_toList_eq h₁.1 h₂.1)
theorem Const.equiv_iff_keys_unit_perm {t₁ t₂ : Raw α Unit cmp} :
t₁ ~m t₂ ↔ t₁.keys.Perm t₂.keys :=
equiv_iff.trans Impl.Const.equiv_iff_keys_perm
theorem Const.equiv_iff_keys_unit_eq {t₁ t₂ : Raw α Unit cmp} [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.keys = t₂.keys :=
equiv_iff.trans (Impl.Const.equiv_iff_keys_eq h₁.1 h₂.1)
theorem Equiv.of_constToList_perm : (Const.toList t₁).Perm (Const.toList t₂) → t₁ ~m t₂ :=
Const.equiv_iff_toList_perm.mpr
theorem Equiv.of_keys_unit_perm {t₁ t₂ : Raw α Unit cmp} : t₁.keys.Perm t₂.keys → t₁ ~m t₂ :=
Const.equiv_iff_keys_unit_perm.mpr
end Const
end Equiv
end Std.DTreeMap.Raw

View file

@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
prelude
import Init.Data.Ord
import Std.Classes.Ord.Basic
set_option autoImplicit false
@ -35,4 +35,24 @@ theorem IsStrictCut.lt_of_isLE_of_lt [IsStrictCut cmp cut] {k k' : α} :
| lt => exact fun _ => IsCut.lt h₁
| eq => exact fun h₂ h₃ => by rw [← h₃, IsStrictCut.eq (cmp := cmp) k h₁]
instance [Ord α] [TransOrd α] {k : α} : IsStrictCut compare (compare k) where
lt := TransCmp.lt_trans
gt h₁ h₂ := OrientedCmp.gt_of_lt (TransCmp.lt_trans (OrientedCmp.lt_of_gt h₂)
(OrientedCmp.lt_of_gt h₁))
eq _ _ := TransCmp.congr_left
instance [Ord α] : IsStrictCut (compare : αα → Ordering) (fun _ => .lt) where
lt := by simp
gt := by simp
eq := by simp
instance [Ord α] [TransOrd α] {k : α} : IsStrictCut compare fun k' => (compare k k').then .gt where
lt {_ _} := by simpa [Ordering.then_eq_lt] using TransCmp.lt_trans
eq {_ _} := by simp [Ordering.then_eq_eq]
gt h h' := by
simp only [Ordering.then_eq_gt, and_true] at h ⊢
rcases h with (h | h)
· exact .inl (TransCmp.gt_trans h h')
· exact .inl (TransCmp.gt_of_eq_of_gt h h')
end Std.Internal

View file

@ -25,7 +25,7 @@ set_option linter.missingDocs true
set_option autoImplicit false
set_option Elab.async false
universe u v w
universe u v w w'
variable {α : Type u} {β : α → Type v} {γ : α → Type w}
@ -2529,7 +2529,7 @@ theorem pairwise_fst_eq_false_map_toProd [BEq α] {β : Type v}
simp [List.pairwise_map]
assumption
theorem foldlM_eq_foldlM_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
theorem foldlM_eq_foldlM_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w'} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : δ → (a : α) → β → m' δ} {init : δ} :
l.foldlM (fun a b => f a b.fst b.snd) init =
(l.map fun x => (x.1, x.2)).foldlM (fun a b => f a b.fst b.snd) init := by
@ -2545,7 +2545,7 @@ theorem foldl_eq_foldl_toProd {β : Type v} {δ : Type w}
| nil => simp
| cons hd tl ih => simp [ih]
theorem foldrM_eq_foldrM_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
theorem foldrM_eq_foldrM_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w'} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : (a : α) → β → δ → m' δ} {init : δ} :
l.foldrM (fun a b => f a.1 a.2 b) init =
(l.map fun x => (x.1, x.2)).foldrM (fun a b => f a.1 a.2 b) init := by
@ -2553,7 +2553,7 @@ theorem foldrM_eq_foldrM_toProd {β : Type v} {δ : Type w} {m' : Type w → Typ
| nil => simp
| cons hd tl ih => simp [ih]
theorem foldrM_eq_foldrM_toProd' {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
theorem foldrM_eq_foldrM_toProd' {β : Type v} {δ : Type w} {m' : Type w → Type w'} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : δ → (a : α) → β → m' δ} {init : δ} :
l.foldrM (fun a b => f b a.1 a.2) init =
(l.map fun x => (x.1, x.2)).foldrM (fun a b => f b a.1 a.2) init := by
@ -2577,14 +2577,14 @@ theorem foldr_eq_foldr_toProd' {β : Type v} {δ : Type w}
| nil => simp
| cons hd tl ih => simp [ih]
theorem forM_eq_forM_toProd {β : Type v} {m' : Type w → Type w} [Monad m']
theorem forM_eq_forM_toProd {β : Type v} {m' : Type w → Type w'} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : (a : α) → β → m' PUnit} :
forM l (fun a => f a.1 a.2) = forM (l.map (fun x => (x.1, x.2))) fun a => f a.1 a.2 := by
cases l with
| nil => simp
| cons hd tl => simp
theorem forIn_eq_forIn_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
theorem forIn_eq_forIn_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w'} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn l init (fun a d => f a.1 a.2 d) =
ForIn.forIn (l.map (fun x => (x.1, x.2))) init fun a d => f a.1 a.2 d := by
@ -2592,7 +2592,7 @@ theorem forIn_eq_forIn_toProd {β : Type v} {δ : Type w} {m' : Type w → Type
| nil => simp
| cons hd tl => simp
theorem foldlM_eq_foldlM_keys {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
theorem foldlM_eq_foldlM_keys {δ : Type w} {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
{l : List ((a : α) × β a)} {f : δ → α → m' δ} {init : δ} :
l.foldlM (fun a b => f a b.1) init = (keys l).foldlM f init := by
induction l generalizing init with
@ -2609,7 +2609,7 @@ theorem foldl_eq_foldl_keys {δ : Type w}
| nil => simp
| cons hd tl ih => simp [List.foldlM_cons, keys, ih]
theorem foldrM_eq_foldrM_keys {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
theorem foldrM_eq_foldrM_keys {δ : Type w} {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
{l : List ((a : α) × β a)} {f : α → δ → m' δ} {init : δ} :
l.foldrM (fun a b => f a.1 b) init = (keys l).foldrM f init := by
induction l generalizing init with
@ -2617,7 +2617,7 @@ theorem foldrM_eq_foldrM_keys {δ : Type w} {m' : Type w → Type w} [Monad m']
| cons hd tl ih =>
simp [keys, ih]
theorem foldrM_eq_foldrM_keys' {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
theorem foldrM_eq_foldrM_keys' {δ : Type w} {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
{l : List ((a : α) × β a)} {f : δ → α → m' δ} {init : δ} :
l.foldrM (fun a b => f b a.1) init = (keys l).foldrM (fun a b => f b a) init := by
induction l generalizing init with
@ -2639,7 +2639,7 @@ theorem foldr_eq_foldr_keys' {δ : Type w}
| nil => simp
| cons hd tl ih => simp [keys, ih]
theorem forM_eq_forM_keys {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
theorem forM_eq_forM_keys {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
{l : List ((a : α) × β a)} {f : α → m' PUnit} :
l.forM (fun a => f a.1) = (keys l).forM f := by
induction l with
@ -2650,7 +2650,7 @@ theorem forM_eq_forM_keys {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
funext x
apply ih
theorem forIn_eq_forIn_keys {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
theorem forIn_eq_forIn_keys {δ : Type w} {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} {l : List ((a : α) × β a)} :
ForIn.forIn l init (fun a d => f a.fst d) = ForIn.forIn (keys l) init f := by
induction l generalizing init with

View file

@ -71,6 +71,13 @@ instance : EmptyCollection (TreeMap α β cmp) where
instance : Inhabited (TreeMap α β cmp) := ⟨∅⟩
@[inherit_doc DTreeMap.Equiv]
structure Equiv (m₁ m₂ : TreeMap α β cmp) where
/-- Internal implementation detail of the tree map -/
inner : m₁.1.Equiv m₂.1
@[inherit_doc] scoped infix:50 " ~m " => Equiv
@[simp]
theorem empty_eq_emptyc : (empty : TreeMap α β cmp) = ∅ :=
rfl

View file

@ -6,6 +6,7 @@ Authors: Markus Himmel, Paul Reichert
prelude
import Std.Data.DTreeMap.Lemmas
import Std.Data.TreeMap.Basic
import Std.Data.TreeMap.AdditionalOperations
/-!
# Tree map lemmas
@ -17,11 +18,11 @@ This file contains lemmas about `Std.Data.TreeMap`. Most of the lemmas require
set_option linter.missingDocs true
set_option autoImplicit false
universe u v w
universe u v w w'
namespace Std.TreeMap
variable {α : Type u} {β : Type v} {cmp : αα → Ordering} {t : TreeMap α β cmp}
variable {α : Type u} {β : Type v} {γ : 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
@ -849,7 +850,7 @@ theorem ordered_keys_toList [TransCmp cmp] :
section monadic
variable {δ : Type w} {m : Type w → Type w}
variable {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m] {f : δ → α → β → m δ} {init : δ} :
t.foldlM f init = t.toList.foldlM (fun a b => f a b.1 b.2) init :=
@ -1176,7 +1177,7 @@ theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem [TransCmp cmp]
DTreeMap.Const.getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem k_eq not_mem distinct mem
theorem getKey!_insertManyIfNewUnit_list_of_mem [TransCmp cmp]
[Inhabited α] {l : List α} {k : α} (mem : k ∈ t):
[Inhabited α] {l : List α} {k : α} (mem : k ∈ t) :
getKey! (insertManyIfNewUnit t l) k = getKey! t k :=
DTreeMap.Const.getKey!_insertManyIfNewUnit_list_of_mem mem
@ -1516,7 +1517,7 @@ theorem mem_alter [TransCmp cmp] {k k' : α} {f : Option β → Option β} :
if cmp k k' = .eq then (f t[k]?).isSome = true else k' ∈ t :=
DTreeMap.Const.mem_alter
theorem mem_alter_of_compare_eq [TransCmp cmp] {k k': α} {f : Option β → Option β}
theorem mem_alter_of_compare_eq [TransCmp cmp] {k k' : α} {f : Option β → Option β}
(he : cmp k k' = .eq) :
k' ∈ alter t k f ↔ (f t[k]?).isSome :=
DTreeMap.Const.mem_alter_of_compare_eq he
@ -2997,4 +2998,446 @@ theorem maxKeyD_alter_eq_self [TransCmp cmp] {k f}
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : TreeMap α β cmp} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (TreeMap α β cmp) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty :=
h.1.isEmpty_eq
theorem contains_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.contains k = t₂.contains k :=
h.1.contains_eq
theorem mem_iff [TransCmp cmp] (h : t₁ ~m t₂) {k : α} :
k ∈ t₁ ↔ k ∈ t₂ :=
h.1.mem_iff
theorem size_eq (h : t₁ ~m t₂) : t₁.size = t₂.size :=
h.1.size_eq
theorem getElem?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) : t₁[k]? = t₂[k]? :=
h.1.constGet?_eq
theorem getElem_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h : t₁ ~m t₂) :
t₁[k] = t₂[k]'(h.mem_iff.mp hk) :=
h.1.constGet_eq
theorem getElem!_eq [TransCmp cmp] [Inhabited β] {k : α} (h : t₁ ~m t₂) :
t₁[k]! = t₂[k]! :=
h.1.constGet!_eq
theorem getD_eq [TransCmp cmp] {k : α} {fallback : β} (h : t₁ ~m t₂) :
t₁.getD k fallback = t₂.getD k fallback :=
h.1.constGetD_eq
theorem getKey?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKey? k = t₂.getKey? k :=
h.1.getKey?_eq
theorem getKey_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h : t₁ ~m t₂) :
t₁.getKey k hk = t₂.getKey k (h.mem_iff.mp hk) :=
h.1.getKey_eq
theorem getKey!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKey! k = t₂.getKey! k :=
h.1.getKey!_eq
theorem getKeyD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyD k fallback = t₂.getKeyD k fallback :=
h.1.getKeyD_eq
theorem toList_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.toList = t₂.toList :=
h.1.constToList_eq
theorem toArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.toArray = t₂.toArray :=
h.1.constToArray_eq
theorem keys_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.keys = t₂.keys :=
h.1.keys_eq
theorem keysArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.keysArray = t₂.keysArray :=
h.1.keysArray_eq
theorem foldlM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : δ → α → β → m δ} {init : δ}
(h : t₁ ~m t₂) :
t₁.foldlM f init = t₂.foldlM f init :=
h.1.foldlM_eq
theorem foldl_eq [TransCmp cmp] {f : δ → α → β → δ} {init : δ} (h : t₁ ~m t₂) :
t₁.foldl f init = t₂.foldl f init :=
h.1.foldl_eq
theorem foldrM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α → β → δ → m δ} {init : δ}
(h : t₁ ~m t₂) :
t₁.foldrM f init = t₂.foldrM f init :=
h.1.foldrM_eq
theorem foldr_eq [TransCmp cmp] {f : α → β → δ → δ} {init : δ} (h : t₁ ~m t₂) :
t₁.foldr f init = t₂.foldr f init :=
h.1.foldr_eq
theorem forIn_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {b : δ} {f : α × β → δ → m (ForInStep δ)}
(h : t₁ ~m t₂) : ForIn.forIn t₁ b f = ForIn.forIn t₂ b f :=
h.1.forIn_eq (f := fun ⟨a, b⟩ => f ⟨a, b⟩)
theorem forM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α × β → m PUnit} (h : t₁ ~m t₂) :
ForM.forM t₁ f = ForM.forM t₂ f :=
h.1.forM_eq (f := fun x : (_ : α) × β => f (x.1, x.2))
theorem any_eq [TransCmp cmp] {p : α → β → Bool} (h : t₁ ~m t₂) : t₁.any p = t₂.any p :=
h.1.any_eq
theorem all_eq [TransCmp cmp] {p : α → β → Bool} (h : t₁ ~m t₂) : t₁.all p = t₂.all p :=
h.1.all_eq
theorem minKey?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.minKey? = t₂.minKey? :=
h.1.minKey?_eq
theorem minKey_eq [TransCmp cmp] {h' : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.minKey h' = t₂.minKey (h.isEmpty_eq.symm.trans h') :=
h.1.minKey_eq
theorem minKey!_eq [TransCmp cmp] [Inhabited α] (h : t₁ ~m t₂) :
t₁.minKey! = t₂.minKey! :=
h.1.minKey!_eq
theorem minKeyD_eq [TransCmp cmp] {fallback : α} (h : t₁ ~m t₂) :
t₁.minKeyD fallback = t₂.minKeyD fallback :=
h.1.minKeyD_eq
theorem maxKey?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.maxKey? = t₂.maxKey? :=
h.1.maxKey?_eq
theorem maxKey_eq [TransCmp cmp] {h' : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.maxKey h' = t₂.maxKey (h.isEmpty_eq.symm.trans h') :=
h.1.maxKey_eq
theorem maxKey!_eq [TransCmp cmp] [Inhabited α] (h : t₁ ~m t₂) :
t₁.maxKey! = t₂.maxKey! :=
h.1.maxKey!_eq
theorem maxKeyD_eq [TransCmp cmp] {fallback : α} (h : t₁ ~m t₂) :
t₁.maxKeyD fallback = t₂.maxKeyD fallback :=
h.1.maxKeyD_eq
theorem minEntry?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.minEntry? = t₂.minEntry? :=
h.1.constMinEntry?_eq
theorem minEntry_eq [TransCmp cmp] {he : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.minEntry he = t₂.minEntry (h.isEmpty_eq.symm.trans he) :=
h.1.constMinEntry_eq
theorem minEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h : t₁ ~m t₂) :
t₁.minEntry! = t₂.minEntry! :=
h.1.constMinEntry!_eq
theorem minEntryD_eq [TransCmp cmp] {fallback : α × β} (h : t₁ ~m t₂) :
t₁.minEntryD fallback = t₂.minEntryD fallback :=
h.1.constMinEntryD_eq
theorem maxEntry?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.maxEntry? = t₂.maxEntry? :=
h.1.constMaxEntry?_eq
theorem maxEntry_eq [TransCmp cmp] {he : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.maxEntry he = t₂.maxEntry (h.isEmpty_eq.symm.trans he) :=
h.1.constMaxEntry_eq
theorem maxEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h : t₁ ~m t₂) :
t₁.maxEntry! = t₂.maxEntry! :=
h.1.constMaxEntry!_eq
theorem maxEntryD_eq [TransCmp cmp] {fallback : α × β} (h : t₁ ~m t₂) :
t₁.maxEntryD fallback = t₂.maxEntryD fallback :=
h.1.constMaxEntryD_eq
theorem entryAtIdx?_eq [TransCmp cmp] {i : Nat} (h : t₁ ~m t₂) :
t₁.entryAtIdx? i = t₂.entryAtIdx? i :=
h.1.constEntryAtIdx?_eq
theorem entryAtIdx_eq [TransCmp cmp] {i : Nat} {h' : i < t₁.size} (h : t₁ ~m t₂) :
t₁.entryAtIdx i h' = t₂.entryAtIdx i (h.size_eq ▸ h') :=
h.1.constEntryAtIdx_eq
theorem entryAtIdx!_eq [TransCmp cmp] [Inhabited (α × β)] {i : Nat} (h : t₁ ~m t₂) :
t₁.entryAtIdx! i = t₂.entryAtIdx! i :=
h.1.constEntryAtIdx!_eq
theorem entryAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α × β} (h : t₁ ~m t₂) :
t₁.entryAtIdxD i fallback = t₂.entryAtIdxD i fallback :=
h.1.constEntryAtIdxD_eq
theorem keyAtIdx?_eq [TransCmp cmp] {i : Nat} (h : t₁ ~m t₂) :
t₁.keyAtIdx? i = t₂.keyAtIdx? i :=
h.1.keyAtIdx?_eq
theorem keyAtIdx_eq [TransCmp cmp] {i : Nat} {h' : i < t₁.size} (h : t₁ ~m t₂) :
t₁.keyAtIdx i h' = t₂.keyAtIdx i (h.size_eq ▸ h') :=
h.1.keyAtIdx_eq
theorem keyAtIdx!_eq [TransCmp cmp] [Inhabited α] {i : Nat} (h : t₁ ~m t₂) :
t₁.keyAtIdx! i = t₂.keyAtIdx! i :=
h.1.keyAtIdx!_eq
theorem keyAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α} (h : t₁ ~m t₂) :
t₁.keyAtIdxD i fallback = t₂.keyAtIdxD i fallback :=
h.1.keyAtIdxD_eq
theorem getEntryGE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGE? k = t₂.getEntryGE? k :=
h.1.constGetEntryGE?_eq
theorem getEntryGE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryGE k h' = t₂.getEntryGE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryGE_eq
theorem getEntryGE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGE! k = t₂.getEntryGE! k :=
h.1.constGetEntryGE!_eq
theorem getEntryGED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
t₁.getEntryGED k fallback = t₂.getEntryGED k fallback :=
h.1.constGetEntryGED_eq
theorem getEntryGT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGT? k = t₂.getEntryGT? k :=
h.1.constGetEntryGT?_eq
theorem getEntryGT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryGT k h' = t₂.getEntryGT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryGT_eq
theorem getEntryGT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryGT! k = t₂.getEntryGT! k :=
h.1.constGetEntryGT!_eq
theorem getEntryGTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
t₁.getEntryGTD k fallback = t₂.getEntryGTD k fallback :=
h.1.constGetEntryGTD_eq
theorem getEntryLE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLE? k = t₂.getEntryLE? k :=
h.1.constGetEntryLE?_eq
theorem getEntryLE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryLE k h' = t₂.getEntryLE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryLE_eq
theorem getEntryLE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLE! k = t₂.getEntryLE! k :=
h.1.constGetEntryLE!_eq
theorem getEntryLED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
t₁.getEntryLED k fallback = t₂.getEntryLED k fallback :=
h.1.constGetEntryLED_eq
theorem getEntryLT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLT? k = t₂.getEntryLT? k :=
h.1.constGetEntryLT?_eq
theorem getEntryLT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getEntryLT k h' = t₂.getEntryLT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.constGetEntryLT_eq
theorem getEntryLT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h : t₁ ~m t₂) :
t₁.getEntryLT! k = t₂.getEntryLT! k :=
h.1.constGetEntryLT!_eq
theorem getEntryLTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h : t₁ ~m t₂) :
t₁.getEntryLTD k fallback = t₂.getEntryLTD k fallback :=
h.1.constGetEntryLTD_eq
theorem getKeyGE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGE? k = t₂.getKeyGE? k :=
h.1.getKeyGE?_eq
theorem getKeyGE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyGE k h' = t₂.getKeyGE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyGE_eq
theorem getKeyGE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGE! k = t₂.getKeyGE! k :=
h.1.getKeyGE!_eq
theorem getKeyGED_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyGED k fallback = t₂.getKeyGED k fallback :=
h.1.getKeyGED_eq
theorem getKeyGT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGT? k = t₂.getKeyGT? k :=
h.1.getKeyGT?_eq
theorem getKeyGT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyGT k h' = t₂.getKeyGT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyGT_eq
theorem getKeyGT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyGT! k = t₂.getKeyGT! k :=
h.1.getKeyGT!_eq
theorem getKeyGTD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyGTD k fallback = t₂.getKeyGTD k fallback :=
h.1.getKeyGTD_eq
theorem getKeyLE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLE? k = t₂.getKeyLE? k :=
h.1.getKeyLE?_eq
theorem getKeyLE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyLE k h' = t₂.getKeyLE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyLE_eq
theorem getKeyLE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLE! k = t₂.getKeyLE! k :=
h.1.getKeyLE!_eq
theorem getKeyLED_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyLED k fallback = t₂.getKeyLED k fallback :=
h.1.getKeyLED_eq
theorem getKeyLT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLT? k = t₂.getKeyLT? k :=
h.1.getKeyLT?_eq
theorem getKeyLT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getKeyLT k h' = t₂.getKeyLT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyLT_eq
theorem getKeyLT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getKeyLT! k = t₂.getKeyLT! k :=
h.1.getKeyLT!_eq
theorem getKeyLTD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getKeyLTD k fallback = t₂.getKeyLTD k fallback :=
h.1.getKeyLTD_eq
theorem insert [TransCmp cmp] (h : t₁ ~m t₂) (k : α) (v : β) : t₁.insert k v ~m t₂.insert k v :=
⟨h.1.insert k v⟩
theorem erase [TransCmp cmp] (h : t₁ ~m t₂) (k : α) : t₁.erase k ~m t₂.erase k :=
⟨h.1.erase k⟩
theorem insertIfNew [TransCmp cmp] (h : t₁ ~m t₂) (k : α) (v : β) :
t₁.insertIfNew k v ~m t₂.insertIfNew k v :=
⟨h.1.insertIfNew k v⟩
theorem alter [TransCmp cmp] [LawfulEqCmp cmp] (h : t₁ ~m t₂)
(k : α) (f : Option β → Option β) : t₁.alter k f ~m t₂.alter k f :=
⟨h.1.constAlter k f⟩
theorem modify [TransCmp cmp] [LawfulEqCmp cmp] (h : t₁ ~m t₂)
(k : α) (f : β → β) : t₁.modify k f ~m t₂.modify k f :=
⟨h.1.constModify k f⟩
theorem filter (h : t₁ ~m t₂) (f : α → β → Bool) : t₁.filter f ~m t₂.filter f :=
⟨h.1.filter f⟩
theorem map (h : t₁ ~m t₂) (f : α → β → γ) : t₁.map f ~m t₂.map f :=
⟨h.1.map f⟩
theorem filterMap (h : t₁ ~m t₂) (f : α → β → Option γ) : t₁.filterMap f ~m t₂.filterMap f :=
⟨h.1.filterMap f⟩
theorem insertMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List (α × β)) :
t₁.insertMany l ~m t₂.insertMany l :=
⟨h.1.constInsertMany_list l⟩
theorem insertManyIfNewUnit_list [TransCmp cmp] {t₁ t₂ : TreeMap α Unit cmp}
(h : t₁ ~m t₂) (l : List α) :
t₁.insertManyIfNewUnit l ~m t₂.insertManyIfNewUnit l :=
⟨h.1.constInsertManyIfNewUnit_list l⟩
theorem eraseMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List α) :
t₁.eraseMany l ~m t₂.eraseMany l :=
⟨h.1.eraseMany_list l⟩
theorem mergeWith [TransCmp cmp] [LawfulEqCmp cmp] (f : α → β → β → β)
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) : t₁.mergeWith f t₃ ~m t₂.mergeWith f t₄ :=
⟨h.1.constMergeWith f h'.1⟩
theorem values_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.values = t₂.values :=
h.1.values_eq
theorem valuesArray_eq [TransCmp cmp] (h : t₁ ~m t₂) :
t₁.valuesArray = t₂.valuesArray :=
h.1.valuesArray_eq
-- extensionalities
theorem of_forall_getKey_eq_of_forall_constGet?_eq [TransCmp cmp]
(hk : ∀ k hk hk', t₁.getKey k hk = t₂.getKey k hk')
(hv : ∀ k : α, t₁[k]? = t₂[k]?) : t₁ ~m t₂ :=
⟨.of_forall_getKey_eq_of_forall_constGet?_eq hk hv⟩
theorem of_forall_constGet?_eq [TransCmp cmp] [LawfulEqCmp cmp]
(h : ∀ k : α, t₁[k]? = t₂[k]?) : t₁ ~m t₂ :=
⟨.of_forall_constGet?_eq h⟩
theorem of_forall_getKey?_unit_eq [TransCmp cmp] {t₁ t₂ : TreeMap α Unit cmp}
(h : ∀ k, t₁.getKey? k = t₂.getKey? k) : t₁ ~m t₂ :=
⟨.of_forall_getKey?_unit_eq h⟩
theorem of_forall_contains_unit_eq [TransCmp cmp] [LawfulEqCmp cmp] {t₁ t₂ : TreeMap α Unit cmp}
(h : ∀ k, t₁.contains k = t₂.contains k) : t₁ ~m t₂ :=
⟨.of_forall_contains_unit_eq h⟩
theorem of_forall_mem_unit_iff [TransCmp cmp] [LawfulEqCmp cmp] {t₁ t₂ : TreeMap α Unit cmp}
(h : ∀ k, k ∈ t₁ ↔ k ∈ t₂) : t₁ ~m t₂ :=
⟨.of_forall_mem_unit_iff h⟩
end Equiv
section Equiv
variable {t₁ t₂ : TreeMap α β cmp}
private theorem equiv_iff_equiv : t₁ ~m t₂ ↔ t₁.1.Equiv t₂.1 :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty :=
equiv_iff_equiv.trans DTreeMap.equiv_empty_iff_isEmpty
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
Equiv.comm.trans equiv_empty_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList :=
equiv_iff_equiv.trans DTreeMap.Const.equiv_iff_toList_perm
theorem Equiv.of_toList_perm (h : t₁.toList.Perm t₂.toList) : t₁ ~m t₂ :=
⟨.of_constToList_perm h⟩
theorem equiv_iff_toList_eq [TransCmp cmp] :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
equiv_iff_equiv.trans DTreeMap.Const.equiv_iff_toList_eq
theorem equiv_iff_keys_unit_perm {t₁ t₂ : TreeMap α Unit cmp} :
t₁ ~m t₂ ↔ t₁.keys.Perm t₂.keys :=
equiv_iff_equiv.trans DTreeMap.Const.equiv_iff_keys_unit_perm
theorem equiv_iff_keys_unit_eq [TransCmp cmp] {t₁ t₂ : TreeMap α Unit cmp} :
t₁ ~m t₂ ↔ t₁.keys = t₂.keys :=
equiv_iff_equiv.trans DTreeMap.Const.equiv_iff_keys_unit_eq
theorem Equiv.of_keys_unit_perm {t₁ t₂ : TreeMap α Unit cmp} : t₁.keys.Perm t₂.keys → t₁ ~m t₂ :=
equiv_iff_keys_unit_perm.mpr
end Equiv
end Std.TreeMap

View file

@ -88,6 +88,13 @@ instance : EmptyCollection (Raw α β cmp) where
instance : Inhabited (Raw α β cmp) where
default := ∅
@[inherit_doc DTreeMap.Equiv]
structure Equiv (m₁ m₂ : Raw α β cmp) where
/-- Internal implementation detail of the tree map -/
inner : m₁.1.Equiv m₂.1
@[inherit_doc] scoped infix:50 " ~m " => Equiv
@[simp]
theorem empty_eq_emptyc : (empty : Raw α β cmp) = ∅ :=
rfl

View file

@ -6,6 +6,7 @@ Authors: Markus Himmel, Paul Reichert
prelude
import Std.Data.DTreeMap.Raw.Lemmas
import Std.Data.TreeMap.Raw.Basic
import Std.Data.TreeMap.Raw.AdditionalOperations
/-!
# Tree map lemmas
@ -18,11 +19,11 @@ These proofs can be obtained from `Std.Data.TreeMap.Raw.WF`.
set_option linter.missingDocs true
set_option autoImplicit false
universe u v w
universe u v w w'
namespace Std.TreeMap.Raw
variable {α : Type u} {β : Type v} {cmp : αα → Ordering} {t : TreeMap.Raw α β cmp}
variable {α : Type u} {β : Type v} {γ : 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
@ -844,7 +845,7 @@ theorem ordered_keys_toList [TransCmp cmp] (h : t.WF) :
section monadic
variable {δ : Type w} {m : Type w → Type w}
variable {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m] {f : δ → α → β → m δ} {init : δ} :
t.foldlM f init = t.toList.foldlM (fun a b => f a b.1 b.2) init :=
@ -2735,4 +2736,414 @@ theorem maxKeyD_alter_eq_self [TransCmp cmp] (h : t.WF) {k f}
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : Raw α β cmp} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (Raw α β cmp) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty :=
h.1.isEmpty_eq
theorem contains_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.contains k = t₂.contains k :=
h.1.contains_eq h₁.1 h₂.1
theorem mem_iff [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
k ∈ t₁ ↔ k ∈ t₂ :=
h.1.mem_iff h₁.1 h₂.1
theorem size_eq (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.size = t₂.size :=
h.1.size_eq h₁.1 h₂.1
theorem getElem?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁[k]? = t₂[k]? :=
h.1.constGet?_eq h₁.1 h₂.1
theorem getElem_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁[k] = t₂[k]'((h.mem_iff h₁ h₂).mp hk) :=
h.1.constGet_eq h₁.1 h₂.1
theorem getElem!_eq [TransCmp cmp] [Inhabited β] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁[k]! = t₂[k]! :=
h.1.constGet!_eq h₁.1 h₂.1
theorem getD_eq [TransCmp cmp] {k : α} {fallback : β} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getD k fallback = t₂.getD k fallback :=
h.1.constGetD_eq h₁.1 h₂.1
theorem getKey?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKey? k = t₂.getKey? k :=
h.1.getKey?_eq h₁.1 h₂.1
theorem getKey_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKey k hk = t₂.getKey k ((h.mem_iff h₁ h₂).mp hk) :=
h.1.getKey_eq h₁.1 h₂.1
theorem getKey!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKey! k = t₂.getKey! k :=
h.1.getKey!_eq h₁.1 h₂.1
theorem getKeyD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyD k fallback = t₂.getKeyD k fallback :=
h.1.getKeyD_eq h₁.1 h₂.1
theorem toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.toList = t₂.toList :=
h.1.constToList_eq h₁.1 h₂.1
theorem toArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.toArray = t₂.toArray :=
h.1.constToArray_eq h₁.1 h₂.1
theorem keys_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.keys = t₂.keys :=
h.1.keys_eq h₁.1 h₂.1
theorem keysArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.keysArray = t₂.keysArray :=
h.1.keysArray_eq h₁.1 h₂.1
theorem foldlM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : δ → α → β → m δ}
{init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.foldlM f init = t₂.foldlM f init :=
h.1.foldlM_eq h₁.1 h₂.1
theorem foldl_eq [TransCmp cmp] {f : δ → α → β → δ} {init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) :
t₁.foldl f init = t₂.foldl f init :=
h.1.foldl_eq h₁.1 h₂.1
theorem foldrM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α → β → δ → m δ}
{init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.foldrM f init = t₂.foldrM f init :=
h.1.foldrM_eq h₁.1 h₂.1
theorem foldr_eq [TransCmp cmp] {f : α → β → δ → δ} {init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) :
t₁.foldr f init = t₂.foldr f init :=
h.1.foldr_eq h₁.1 h₂.1
theorem forIn_eq [TransCmp cmp] [Monad m] [LawfulMonad m]
{b : δ} {f : α × β → δ → m (ForInStep δ)} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
ForIn.forIn t₁ b f = ForIn.forIn t₂ b f :=
h.1.forIn_eq h₁.1 h₂.1 (f := fun ⟨a, b⟩ => f ⟨a, b⟩)
theorem forM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α × β → m PUnit}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
ForM.forM t₁ f = ForM.forM t₂ f :=
h.1.forM_eq h₁.1 h₂.1 (f := fun x : (_ : α) × β => f (x.1, x.2))
theorem any_eq [TransCmp cmp] {p : α → β → Bool} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.any p = t₂.any p :=
h.1.any_eq h₁.1 h₂.1
theorem all_eq [TransCmp cmp] {p : α → β → Bool} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.all p = t₂.all p :=
h.1.all_eq h₁.1 h₂.1
theorem minKey?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKey? = t₂.minKey? :=
h.1.minKey?_eq h₁.1 h₂.1
theorem minKey!_eq [TransCmp cmp] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKey! = t₂.minKey! :=
h.1.minKey!_eq h₁.1 h₂.1
theorem minKeyD_eq [TransCmp cmp] {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minKeyD fallback = t₂.minKeyD fallback :=
h.1.minKeyD_eq h₁.1 h₂.1
theorem maxKey?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKey? = t₂.maxKey? :=
h.1.maxKey?_eq h₁.1 h₂.1
theorem maxKey!_eq [TransCmp cmp] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKey! = t₂.maxKey! :=
h.1.maxKey!_eq h₁.1 h₂.1
theorem maxKeyD_eq [TransCmp cmp] {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxKeyD fallback = t₂.maxKeyD fallback :=
h.1.maxKeyD_eq h₁.1 h₂.1
theorem minEntry?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minEntry? = t₂.minEntry? :=
h.1.constMinEntry?_eq h₁.1 h₂.1
theorem minEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.minEntry! = t₂.minEntry! :=
h.1.constMinEntry!_eq h₁.1 h₂.1
theorem minEntryD_eq [TransCmp cmp] {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.minEntryD fallback = t₂.minEntryD fallback :=
h.1.constMinEntryD_eq h₁.1 h₂.1
theorem maxEntry?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxEntry? = t₂.maxEntry? :=
h.1.constMaxEntry?_eq h₁.1 h₂.1
theorem maxEntry!_eq [TransCmp cmp] [Inhabited (α × β)] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.maxEntry! = t₂.maxEntry! :=
h.1.constMaxEntry!_eq h₁.1 h₂.1
theorem maxEntryD_eq [TransCmp cmp] {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.maxEntryD fallback = t₂.maxEntryD fallback :=
h.1.constMaxEntryD_eq h₁.1 h₂.1
theorem entryAtIdx?_eq [TransCmp cmp] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.entryAtIdx? i = t₂.entryAtIdx? i :=
h.1.constEntryAtIdx?_eq h₁.1 h₂.1
theorem entryAtIdx!_eq [TransCmp cmp] [Inhabited (α × β)] {i : Nat} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.entryAtIdx! i = t₂.entryAtIdx! i :=
h.1.constEntryAtIdx!_eq h₁.1 h₂.1
theorem entryAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α × β} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.entryAtIdxD i fallback = t₂.entryAtIdxD i fallback :=
h.1.constEntryAtIdxD_eq h₁.1 h₂.1
theorem keyAtIdx?_eq [TransCmp cmp] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.keyAtIdx? i = t₂.keyAtIdx? i :=
h.1.keyAtIdx?_eq h₁.1 h₂.1
theorem keyAtIdx!_eq [TransCmp cmp] [Inhabited α] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.keyAtIdx! i = t₂.keyAtIdx! i :=
h.1.keyAtIdx!_eq h₁.1 h₂.1
theorem keyAtIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.keyAtIdxD i fallback = t₂.keyAtIdxD i fallback :=
h.1.keyAtIdxD_eq h₁.1 h₂.1
theorem getEntryGE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryGE? k = t₂.getEntryGE? k :=
h.1.constGetEntryGE?_eq h₁.1 h₂.1
theorem getEntryGE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryGE! k = t₂.getEntryGE! k :=
h.1.constGetEntryGE!_eq h₁.1 h₂.1
theorem getEntryGED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryGED k fallback = t₂.getEntryGED k fallback :=
h.1.constGetEntryGED_eq h₁.1 h₂.1
theorem getEntryGT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryGT? k = t₂.getEntryGT? k :=
h.1.constGetEntryGT?_eq h₁.1 h₂.1
theorem getEntryGT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryGT! k = t₂.getEntryGT! k :=
h.1.constGetEntryGT!_eq h₁.1 h₂.1
theorem getEntryGTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryGTD k fallback = t₂.getEntryGTD k fallback :=
h.1.constGetEntryGTD_eq h₁.1 h₂.1
theorem getEntryLE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryLE? k = t₂.getEntryLE? k :=
h.1.constGetEntryLE?_eq h₁.1 h₂.1
theorem getEntryLE!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryLE! k = t₂.getEntryLE! k :=
h.1.constGetEntryLE!_eq h₁.1 h₂.1
theorem getEntryLED_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryLED k fallback = t₂.getEntryLED k fallback :=
h.1.constGetEntryLED_eq h₁.1 h₂.1
theorem getEntryLT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getEntryLT? k = t₂.getEntryLT? k :=
h.1.constGetEntryLT?_eq h₁.1 h₂.1
theorem getEntryLT!_eq [TransCmp cmp] [Inhabited (α × β)] {k : α} (h₁ : t₁.WF)
(h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.getEntryLT! k = t₂.getEntryLT! k :=
h.1.constGetEntryLT!_eq h₁.1 h₂.1
theorem getEntryLTD_eq [TransCmp cmp] {k : α} {fallback : α × β} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.getEntryLTD k fallback = t₂.getEntryLTD k fallback :=
h.1.constGetEntryLTD_eq h₁.1 h₂.1
theorem getKeyGE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGE? k = t₂.getKeyGE? k :=
h.1.getKeyGE?_eq h₁.1 h₂.1
theorem getKeyGE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGE! k = t₂.getKeyGE! k :=
h.1.getKeyGE!_eq h₁.1 h₂.1
theorem getKeyGED_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGED k fallback = t₂.getKeyGED k fallback :=
h.1.getKeyGED_eq h₁.1 h₂.1
theorem getKeyGT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGT? k = t₂.getKeyGT? k :=
h.1.getKeyGT?_eq h₁.1 h₂.1
theorem getKeyGT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGT! k = t₂.getKeyGT! k :=
h.1.getKeyGT!_eq h₁.1 h₂.1
theorem getKeyGTD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyGTD k fallback = t₂.getKeyGTD k fallback :=
h.1.getKeyGTD_eq h₁.1 h₂.1
theorem getKeyLE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLE? k = t₂.getKeyLE? k :=
h.1.getKeyLE?_eq h₁.1 h₂.1
theorem getKeyLE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLE! k = t₂.getKeyLE! k :=
h.1.getKeyLE!_eq h₁.1 h₂.1
theorem getKeyLED_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLED k fallback = t₂.getKeyLED k fallback :=
h.1.getKeyLED_eq h₁.1 h₂.1
theorem getKeyLT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLT? k = t₂.getKeyLT? k :=
h.1.getKeyLT?_eq h₁.1 h₂.1
theorem getKeyLT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLT! k = t₂.getKeyLT! k :=
h.1.getKeyLT!_eq h₁.1 h₂.1
theorem getKeyLTD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getKeyLTD k fallback = t₂.getKeyLTD k fallback :=
h.1.getKeyLTD_eq h₁.1 h₂.1
theorem insert [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (v : β) : t₁.insert k v ~m t₂.insert k v :=
⟨h.1.insert h₁.1 h₂.1 k v⟩
theorem erase [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) : t₁.erase k ~m t₂.erase k :=
⟨h.1.erase h₁.1 h₂.1 k⟩
theorem insertIfNew [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (v : β) : t₁.insertIfNew k v ~m t₂.insertIfNew k v :=
⟨h.1.insertIfNew h₁.1 h₂.1 k v⟩
theorem alter [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (f : Option β → Option β) :
t₁.alter k f ~m t₂.alter k f :=
⟨h.1.constAlter h₁.1 h₂.1 k f⟩
theorem modify [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(k : α) (f : β → β) : t₁.modify k f ~m t₂.modify k f :=
⟨h.1.constModify h₁.1 h₂.1 k f⟩
theorem filter (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (f : α → β → Bool) :
t₁.filter f ~m t₂.filter f :=
⟨h.1.filter h₁.1 h₂.1 f⟩
theorem map (h : t₁ ~m t₂) (f : α → β → γ) : t₁.map f ~m t₂.map f :=
⟨h.1.map f⟩
theorem filterMap (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (f : α → β → Option γ) :
t₁.filterMap f ~m t₂.filterMap f :=
⟨h.1.filterMap h₁.1 h₂.1 f⟩
theorem insertMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(l : List (α × β)) : t₁.insertMany l ~m t₂.insertMany l :=
⟨h.1.constInsertMany_list h₁.1 h₂.1 l⟩
theorem insertManyIfNewUnit_list [TransCmp cmp] {t₁ t₂ : Raw α Unit cmp}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (l : List α) :
t₁.insertManyIfNewUnit l ~m t₂.insertManyIfNewUnit l :=
⟨h.1.constInsertManyIfNewUnit_list h₁.1 h₂.1 l⟩
theorem eraseMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (l : List α) :
t₁.eraseMany l ~m t₂.eraseMany l :=
⟨h.1.eraseMany_list h₁.1 h₂.1 l⟩
theorem mergeWith [TransCmp cmp] [LawfulEqCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
(f : α → β → β → β)
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) :
t₁.mergeWith f t₃ ~m t₂.mergeWith f t₄ :=
⟨h.1.constMergeWith h₁.1 h₂.1 h₃.1 h₄.1 f h'.1⟩
theorem values_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.values = t₂.values :=
h.1.values_eq h₁.1 h₂.1
theorem valuesArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.valuesArray = t₂.valuesArray :=
h.1.valuesArray_eq h₁.1 h₂.1
-- extensionalities
theorem of_forall_getKey_eq_of_forall_getElem?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF)
(hk : ∀ k hk hk', t₁.getKey k hk = t₂.getKey k hk')
(hv : ∀ k : α, t₁[k]? = t₂[k]?) : t₁ ~m t₂ :=
⟨.of_forall_getKey_eq_of_forall_constGet?_eq h₁.1 h₂.1 hk hv⟩
theorem of_forall_getElem?_eq [TransCmp cmp] [LawfulEqCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k : α, t₁[k]? = t₂[k]?) : t₁ ~m t₂ :=
⟨.of_forall_constGet?_eq h₁.1 h₂.1 h⟩
theorem of_forall_getKey?_unit_eq [TransCmp cmp] {t₁ t₂ : Raw α Unit cmp}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : ∀ k, t₁.getKey? k = t₂.getKey? k) : t₁ ~m t₂ :=
⟨.of_forall_getKey?_unit_eq h₁.1 h₂.1 h⟩
theorem of_forall_contains_unit_eq [TransCmp cmp] [LawfulEqCmp cmp]
{t₁ t₂ : Raw α Unit cmp} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, t₁.contains k = t₂.contains k) : t₁ ~m t₂ :=
⟨.of_forall_contains_unit_eq h₁.1 h₂.1 h⟩
theorem of_forall_mem_unit_iff [TransCmp cmp] [LawfulEqCmp cmp]
{t₁ t₂ : Raw α Unit cmp} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, k ∈ t₁ ↔ k ∈ t₂) : t₁ ~m t₂ :=
⟨.of_forall_mem_unit_iff h₁.1 h₂.1 h⟩
end Equiv
section Equiv
variable {t₁ t₂ : Raw α β cmp}
private theorem equiv_iff : t₁ ~m t₂ ↔ t₁.1.Equiv t₂.1 :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty :=
equiv_iff.trans DTreeMap.Raw.equiv_empty_iff_isEmpty
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
equiv_iff.trans DTreeMap.Raw.empty_equiv_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList :=
equiv_iff.trans DTreeMap.Raw.Const.equiv_iff_toList_perm
theorem Equiv.of_toList_perm (h : t₁.toList.Perm t₂.toList) : t₁ ~m t₂ :=
⟨.of_constToList_perm h⟩
theorem equiv_iff_toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
equiv_iff.trans (DTreeMap.Raw.Const.equiv_iff_toList_eq h₁.1 h₂.1)
theorem equiv_iff_keys_unit_perm {t₁ t₂ : Raw α Unit cmp} :
t₁ ~m t₂ ↔ t₁.keys.Perm t₂.keys :=
equiv_iff.trans DTreeMap.Raw.Const.equiv_iff_keys_unit_perm
theorem equiv_iff_keys_unit_eq {t₁ t₂ : Raw α Unit cmp} [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.keys = t₂.keys :=
equiv_iff.trans (DTreeMap.Raw.Const.equiv_iff_keys_unit_eq h₁.1 h₂.1)
theorem Equiv.of_keys_unit_perm {t₁ t₂ : Raw α Unit cmp} : t₁.keys.Perm t₂.keys → t₁ ~m t₂ :=
equiv_iff_keys_unit_perm.mpr
end Equiv
end Std.TreeMap.Raw

View file

@ -22,7 +22,7 @@ universe u v w
variable {α : Type u} {β : Type v} {cmp : αα → Ordering}
namespace Std.TreeMap
namespace Std.TreeSet
/-!
We do not provide `get*GE`, `get*GT`, `get*LE` and `get*LT` functions for the raw trees.
@ -60,4 +60,4 @@ less than the given element.
def getLT [TransCmp cmp] (t : TreeSet α cmp) (k : α) (h : ∃ a ∈ t, cmp a k = .lt) : α :=
TreeMap.getKeyLT t.inner k h
end Std.TreeMap
end Std.TreeSet

View file

@ -76,6 +76,13 @@ instance : EmptyCollection (TreeSet α cmp) where
instance : Inhabited (TreeSet α cmp) where
default := ∅
/-- Two tree sets are equivalent in the sense of Equiv iff all the values are equal. -/
structure Equiv (m₁ m₂ : TreeSet α cmp) where
/-- Internal implementation detail of the tree map -/
inner : m₁.1.Equiv m₂.1
@[inherit_doc] scoped infix:50 " ~m " => Equiv
@[simp]
theorem empty_eq_emptyc : (empty : TreeSet α cmp) = ∅ :=
rfl

View file

@ -6,6 +6,7 @@ Authors: Markus Himmel, Paul Reichert
prelude
import Std.Data.TreeMap.Lemmas
import Std.Data.TreeSet.Basic
import Std.Data.TreeSet.AdditionalOperations
/-!
# Tree set lemmas
@ -17,7 +18,7 @@ This file contains lemmas about `Std.Data.TreeSet`. Most of the lemmas require
set_option linter.missingDocs true
set_option autoImplicit false
universe u v w
universe u v w w'
namespace Std.TreeSet
@ -442,7 +443,7 @@ theorem ordered_toList [TransCmp cmp] :
section monadic
variable {δ : Type w} {m : Type w → Type w}
variable {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m] {f : δ → α → m δ} {init : δ} :
t.foldlM f init = t.toList.foldlM f init :=
@ -1511,4 +1512,264 @@ theorem maxD_eq_getLastD_toList [TransCmp cmp] {fallback} :
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : TreeSet α cmp} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (TreeSet α cmp) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty :=
h.1.isEmpty_eq
theorem contains_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.contains k = t₂.contains k :=
h.1.contains_eq
theorem mem_iff [TransCmp cmp] (h : t₁ ~m t₂) {k : α} :
k ∈ t₁ ↔ k ∈ t₂ :=
h.1.mem_iff
theorem size_eq (h : t₁ ~m t₂) : t₁.size = t₂.size :=
h.1.size_eq
theorem get?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.get? k = t₂.get? k :=
h.1.getKey?_eq
theorem get_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h : t₁ ~m t₂) :
t₁.get k hk = t₂.get k (h.mem_iff.mp hk) :=
h.1.getKey_eq
theorem get!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.get! k = t₂.get! k :=
h.1.getKey!_eq
theorem getD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getD k fallback = t₂.getD k fallback :=
h.1.getKeyD_eq
theorem toList_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.toList = t₂.toList :=
h.1.keys_eq
theorem toArray_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.toArray = t₂.toArray :=
h.1.keysArray_eq
theorem foldlM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : δ → α → m δ} {init : δ}
(h : t₁ ~m t₂) : t₁.foldlM f init = t₂.foldlM f init :=
h.1.foldlM_eq
theorem foldl_eq [TransCmp cmp] {f : δ → α → δ} {init : δ} (h : t₁ ~m t₂) :
t₁.foldl f init = t₂.foldl f init :=
h.1.foldl_eq
theorem foldrM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α → δ → m δ} {init : δ}
(h : t₁ ~m t₂) :
t₁.foldrM f init = t₂.foldrM f init :=
h.1.foldrM_eq
theorem foldr_eq [TransCmp cmp] {f : α → δ → δ} {init : δ} (h : t₁ ~m t₂) :
t₁.foldr f init = t₂.foldr f init :=
h.1.foldr_eq
theorem forIn_eq [TransCmp cmp] [Monad m] [LawfulMonad m]
{b : δ} {f : α → δ → m (ForInStep δ)} (h : t₁ ~m t₂) :
ForIn.forIn t₁ b f = ForIn.forIn t₂ b f :=
h.1.forIn_eq (f := fun x => f x.1)
theorem forM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α → m PUnit} (h : t₁ ~m t₂) :
ForM.forM t₁ f = ForM.forM t₂ f :=
h.1.forM_eq (f := fun x => f x.1)
theorem any_eq [TransCmp cmp] {p : α → Bool} (h : t₁ ~m t₂) : t₁.any p = t₂.any p :=
h.1.any_eq
theorem all_eq [TransCmp cmp] {p : α → Bool} (h : t₁ ~m t₂) : t₁.all p = t₂.all p :=
h.1.all_eq
theorem min?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.min? = t₂.min? :=
h.1.minKey?_eq
theorem min_eq [TransCmp cmp] {h' : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.min h' = t₂.min (h.isEmpty_eq.symm.trans h') :=
h.1.minKey_eq
theorem min!_eq [TransCmp cmp] [Inhabited α] (h : t₁ ~m t₂) :
t₁.min! = t₂.min! :=
h.1.minKey!_eq
theorem minD_eq [TransCmp cmp] {fallback : α} (h : t₁ ~m t₂) :
t₁.minD fallback = t₂.minD fallback :=
h.1.minKeyD_eq
theorem max?_eq [TransCmp cmp] (h : t₁ ~m t₂) : t₁.max? = t₂.max? :=
h.1.maxKey?_eq
theorem max_eq [TransCmp cmp] {h' : t₁.isEmpty = false} (h : t₁ ~m t₂) :
t₁.max h' = t₂.max (h.isEmpty_eq.symm.trans h') :=
h.1.maxKey_eq
theorem max!_eq [TransCmp cmp] [Inhabited α] (h : t₁ ~m t₂) :
t₁.max! = t₂.max! :=
h.1.maxKey!_eq
theorem maxD_eq [TransCmp cmp] {fallback : α} (h : t₁ ~m t₂) :
t₁.maxD fallback = t₂.maxD fallback :=
h.1.maxKeyD_eq
theorem atIdx?_eq [TransCmp cmp] {i : Nat} (h : t₁ ~m t₂) :
t₁.atIdx? i = t₂.atIdx? i :=
h.1.keyAtIdx?_eq
theorem atIdx_eq [TransCmp cmp] {i : Nat} {h' : i < t₁.size} (h : t₁ ~m t₂) :
t₁.atIdx i h' = t₂.atIdx i (h.size_eq ▸ h') :=
h.1.keyAtIdx_eq
theorem atIdx!_eq [TransCmp cmp] [Inhabited α] {i : Nat} (h : t₁ ~m t₂) :
t₁.atIdx! i = t₂.atIdx! i :=
h.1.keyAtIdx!_eq
theorem atIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α} (h : t₁ ~m t₂) :
t₁.atIdxD i fallback = t₂.atIdxD i fallback :=
h.1.keyAtIdxD_eq
theorem getGE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getGE? k = t₂.getGE? k :=
h.1.getKeyGE?_eq
theorem getGE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getGE k h' = t₂.getGE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyGE_eq
theorem getGE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getGE! k = t₂.getGE! k :=
h.1.getKeyGE!_eq
theorem getGED_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getGED k fallback = t₂.getGED k fallback :=
h.1.getKeyGED_eq
theorem getGT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getGT? k = t₂.getGT? k :=
h.1.getKeyGT?_eq
theorem getGT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getGT k h' = t₂.getGT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyGT_eq
theorem getGT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getGT! k = t₂.getGT! k :=
h.1.getKeyGT!_eq
theorem getGTD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getGTD k fallback = t₂.getGTD k fallback :=
h.1.getKeyGTD_eq
theorem getLE?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getLE? k = t₂.getLE? k :=
h.1.getKeyLE?_eq
theorem getLE_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getLE k h' = t₂.getLE k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyLE_eq
theorem getLE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getLE! k = t₂.getLE! k :=
h.1.getKeyLE!_eq
theorem getLED_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getLED k fallback = t₂.getLED k fallback :=
h.1.getKeyLED_eq
theorem getLT?_eq [TransCmp cmp] {k : α} (h : t₁ ~m t₂) :
t₁.getLT? k = t₂.getLT? k :=
h.1.getKeyLT?_eq
theorem getLT_eq [TransCmp cmp] {k : α} {h'} (h : t₁ ~m t₂) :
t₁.getLT k h' = t₂.getLT k (h'.imp fun _ ⟨h₁, h₂⟩ => ⟨h.mem_iff.mp h₁, h₂⟩) :=
h.1.getKeyLT_eq
theorem getLT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h : t₁ ~m t₂) :
t₁.getLT! k = t₂.getLT! k :=
h.1.getKeyLT!_eq
theorem getLTD_eq [TransCmp cmp] {k fallback : α} (h : t₁ ~m t₂) :
t₁.getLTD k fallback = t₂.getLTD k fallback :=
h.1.getKeyLTD_eq
theorem insert [TransCmp cmp] (h : t₁ ~m t₂) (k : α) : t₁.insert k ~m t₂.insert k :=
⟨h.1.insertIfNew k ()⟩
theorem erase [TransCmp cmp] (h : t₁ ~m t₂) (k : α) : t₁.erase k ~m t₂.erase k :=
⟨h.1.erase k⟩
theorem filter (h : t₁ ~m t₂) (f : α → Bool) : t₁.filter f ~m t₂.filter f :=
⟨h.1.filter _⟩
theorem insertMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List α) :
t₁.insertMany l ~m t₂.insertMany l :=
⟨h.1.insertManyIfNewUnit_list l⟩
theorem eraseMany_list [TransCmp cmp] (h : t₁ ~m t₂) (l : List α) :
t₁.eraseMany l ~m t₂.eraseMany l :=
⟨h.1.eraseMany_list l⟩
theorem merge [TransCmp cmp] [LawfulEqCmp cmp]
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) : t₁.merge t₃ ~m t₂.merge t₄ :=
⟨h.1.mergeWith _ h'.1⟩
-- extensionalities
theorem of_forall_get?_eq [TransCmp cmp] (h : ∀ k, t₁.get? k = t₂.get? k) : t₁ ~m t₂ :=
⟨.of_forall_getKey?_unit_eq h⟩
theorem of_forall_contains_eq [TransCmp cmp] [LawfulEqCmp cmp]
(h : ∀ k, t₁.contains k = t₂.contains k) : t₁ ~m t₂ :=
⟨.of_forall_contains_unit_eq h⟩
theorem of_forall_mem_iff [TransCmp cmp] [LawfulEqCmp cmp]
(h : ∀ k, k ∈ t₁ ↔ k ∈ t₂) : t₁ ~m t₂ :=
⟨.of_forall_mem_unit_iff h⟩
end Equiv
section Equiv
variable {t₁ t₂ : TreeSet α cmp}
private theorem equiv_iff_equiv : t₁ ~m t₂ ↔ t₁.1.Equiv t₂.1 :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty :=
equiv_iff_equiv.trans TreeMap.equiv_empty_iff_isEmpty
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
Equiv.comm.trans equiv_empty_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList :=
equiv_iff_equiv.trans TreeMap.equiv_iff_keys_unit_perm
theorem Equiv.of_toList_perm (h : t₁.toList.Perm t₂.toList) : t₁ ~m t₂ :=
⟨.of_keys_unit_perm h⟩
theorem equiv_iff_toList_eq [TransCmp cmp] :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
equiv_iff_equiv.trans TreeMap.equiv_iff_keys_unit_eq
end Equiv
end Std.TreeSet

View file

@ -88,6 +88,13 @@ instance : EmptyCollection (Raw α cmp) where
instance : Inhabited (Raw α cmp) where
default := ∅
/-- Two tree sets are equivalent in the sense of Equiv iff all the values are equal. -/
structure Equiv (m₁ m₂ : Raw α cmp) where
/-- Internal implementation detail of the tree map -/
inner : m₁.1.Equiv m₂.1
@[inherit_doc] scoped infix:50 " ~m " => Equiv
@[simp]
theorem empty_eq_emptyc : (empty : Raw α cmp) = ∅ :=
rfl
@ -298,7 +305,7 @@ def forIn (f : α → δ → m (ForInStep δ)) (init : δ) (t : Raw α cmp) : m
instance : ForM m (Raw α cmp) α where
forM t f := t.forM f
instance {t : Type w → Type w} : ForIn t (Raw α cmp) α where
instance : ForIn m (Raw α cmp) α where
forIn t init f := t.forIn (fun a acc => f a acc) init
@[inline, inherit_doc TreeSet.empty]

View file

@ -18,7 +18,7 @@ These proofs can be obtained from `Std.Data.TreeSet.Raw.WF`.
set_option linter.missingDocs true
set_option autoImplicit false
universe u v w
universe u v w w'
namespace Std.TreeSet.Raw
@ -444,7 +444,7 @@ theorem ordered_toList [TransCmp cmp] (h : t.WF) :
section monadic
variable {δ : Type w} {m : Type w → Type w}
variable {δ : Type w} {m : Type w → Type w'}
theorem foldlM_eq_foldlM_toList [Monad m] [LawfulMonad m]
{f : δ → α → m δ} {init : δ} :
@ -1317,4 +1317,254 @@ theorem maxD_eq_getLastD_toList [TransCmp cmp] (h : t.WF) {fallback} :
end Max
namespace Equiv
variable {t₁ t₂ t₃ t₄ : Raw α cmp} {δ : Type w} {m : Type w → Type w'}
@[refl, simp] theorem rfl : Equiv t t := ⟨.rfl⟩
@[symm] theorem symm : Equiv t₁ t₂ → Equiv t₂ t₁
| ⟨h⟩ => ⟨h.symm⟩
theorem trans : Equiv t₁ t₂ → Equiv t₂ t₃ → Equiv t₁ t₃
| ⟨h⟩, ⟨h'⟩ => ⟨h.trans h'⟩
instance instTrans : @Trans (Raw α cmp) _ _ Equiv Equiv Equiv := ⟨trans⟩
theorem comm : t₁ ~m t₂ ↔ t₂ ~m t₁ := ⟨symm, symm⟩
theorem congr_left (h : t₁ ~m t₂) : t₁ ~m t₃ ↔ t₂ ~m t₃ := ⟨h.symm.trans, h.trans⟩
theorem congr_right (h : t₁ ~m t₂) : t₃ ~m t₁ ↔ t₃ ~m t₂ :=
⟨fun h' => h'.trans h, fun h' => h'.trans h.symm⟩
-- congruence lemmas
theorem isEmpty_eq (h : t₁ ~m t₂) : t₁.isEmpty = t₂.isEmpty :=
h.1.isEmpty_eq
theorem contains_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.contains k = t₂.contains k :=
h.1.contains_eq h₁.1 h₂.1
theorem mem_iff [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
k ∈ t₁ ↔ k ∈ t₂ :=
h.1.mem_iff h₁.1 h₂.1
theorem size_eq (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.size = t₂.size :=
h.1.size_eq h₁.1 h₂.1
theorem get?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.get? k = t₂.get? k :=
h.1.getKey?_eq h₁.1 h₂.1
theorem getKey_eq [TransCmp cmp] {k : α} {hk : k ∈ t₁} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.get k hk = t₂.get k ((h.mem_iff h₁ h₂).mp hk) :=
h.1.getKey_eq h₁.1 h₂.1
theorem getKey!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.get! k = t₂.get! k :=
h.1.getKey!_eq h₁.1 h₂.1
theorem getKeyD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getD k fallback = t₂.getD k fallback :=
h.1.getKeyD_eq h₁.1 h₂.1
theorem toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) : t₁.toList = t₂.toList :=
h.1.keys_eq h₁.1 h₂.1
theorem toArray_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.toArray = t₂.toArray :=
h.1.keysArray_eq h₁.1 h₂.1
theorem foldlM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : δ → α → m δ}
{init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.foldlM f init = t₂.foldlM f init :=
h.1.foldlM_eq h₁.1 h₂.1
theorem foldl_eq [TransCmp cmp] {f : δ → α → δ} {init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) :
t₁.foldl f init = t₂.foldl f init :=
h.1.foldl_eq h₁.1 h₂.1
theorem foldrM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α → δ → m δ}
{init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.foldrM f init = t₂.foldrM f init :=
h.1.foldrM_eq h₁.1 h₂.1
theorem foldr_eq [TransCmp cmp] {f : α → δ → δ} {init : δ} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) :
t₁.foldr f init = t₂.foldr f init :=
h.1.foldr_eq h₁.1 h₂.1
theorem forIn_eq [TransCmp cmp] [Monad m] [LawfulMonad m]
{b : δ} {f : α → δ → m (ForInStep δ)} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
ForIn.forIn t₁ b f = ForIn.forIn t₂ b f :=
h.1.forIn_eq h₁.1 h₂.1 (f := fun x => f x.1)
theorem forM_eq [TransCmp cmp] [Monad m] [LawfulMonad m] {f : α → m PUnit}
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
ForM.forM t₁ f = ForM.forM t₂ f :=
h.1.forM_eq h₁.1 h₂.1 (f := fun x => f x.1)
theorem any_eq [TransCmp cmp] {p : α → Bool} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.any p = t₂.any p :=
h.1.any_eq h₁.1 h₂.1
theorem all_eq [TransCmp cmp] {p : α → Bool} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.all p = t₂.all p :=
h.1.all_eq h₁.1 h₂.1
theorem min?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.min? = t₂.min? :=
h.1.minKey?_eq h₁.1 h₂.1
theorem min!_eq [TransCmp cmp] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.min! = t₂.min! :=
h.1.minKey!_eq h₁.1 h₂.1
theorem minD_eq [TransCmp cmp] {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.minD fallback = t₂.minD fallback :=
h.1.minKeyD_eq h₁.1 h₂.1
theorem max?_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.max? = t₂.max? :=
h.1.maxKey?_eq h₁.1 h₂.1
theorem max!_eq [TransCmp cmp] [Inhabited α] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.max! = t₂.max! :=
h.1.maxKey!_eq h₁.1 h₂.1
theorem maxD_eq [TransCmp cmp] {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.maxD fallback = t₂.maxD fallback :=
h.1.maxKeyD_eq h₁.1 h₂.1
theorem atIdx?_eq [TransCmp cmp] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.atIdx? i = t₂.atIdx? i :=
h.1.keyAtIdx?_eq h₁.1 h₂.1
theorem atIdx!_eq [TransCmp cmp] [Inhabited α] {i : Nat} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.atIdx! i = t₂.atIdx! i :=
h.1.keyAtIdx!_eq h₁.1 h₂.1
theorem atIdxD_eq [TransCmp cmp] {i : Nat} {fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF)
(h : t₁ ~m t₂) : t₁.atIdxD i fallback = t₂.atIdxD i fallback :=
h.1.keyAtIdxD_eq h₁.1 h₂.1
theorem getGE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getGE? k = t₂.getGE? k :=
h.1.getKeyGE?_eq h₁.1 h₂.1
theorem getGE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getGE! k = t₂.getGE! k :=
h.1.getKeyGE!_eq h₁.1 h₂.1
theorem getGED_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getGED k fallback = t₂.getGED k fallback :=
h.1.getKeyGED_eq h₁.1 h₂.1
theorem getGT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getGT? k = t₂.getGT? k :=
h.1.getKeyGT?_eq h₁.1 h₂.1
theorem getGT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getGT! k = t₂.getGT! k :=
h.1.getKeyGT!_eq h₁.1 h₂.1
theorem getGTD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getGTD k fallback = t₂.getGTD k fallback :=
h.1.getKeyGTD_eq h₁.1 h₂.1
theorem getLE?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getLE? k = t₂.getLE? k :=
h.1.getKeyLE?_eq h₁.1 h₂.1
theorem getLE!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getLE! k = t₂.getLE! k :=
h.1.getKeyLE!_eq h₁.1 h₂.1
theorem getLED_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getLED k fallback = t₂.getLED k fallback :=
h.1.getKeyLED_eq h₁.1 h₂.1
theorem getLT?_eq [TransCmp cmp] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getLT? k = t₂.getLT? k :=
h.1.getKeyLT?_eq h₁.1 h₂.1
theorem getLT!_eq [TransCmp cmp] [Inhabited α] {k : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getLT! k = t₂.getLT! k :=
h.1.getKeyLT!_eq h₁.1 h₂.1
theorem getLTD_eq [TransCmp cmp] {k fallback : α} (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) :
t₁.getLTD k fallback = t₂.getLTD k fallback :=
h.1.getKeyLTD_eq h₁.1 h₂.1
theorem insert [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (k : α) :
t₁.insert k ~m t₂.insert k :=
⟨h.1.insertIfNew h₁.1 h₂.1 k ()⟩
theorem erase [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (k : α) :
t₁.erase k ~m t₂.erase k :=
⟨h.1.erase h₁.1 h₂.1 k⟩
theorem filter (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (f : α → Bool) :
t₁.filter f ~m t₂.filter f :=
⟨h.1.filter h₁.1 h₂.1 _⟩
theorem insertMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂)
(l : List α) : t₁.insertMany l ~m t₂.insertMany l :=
⟨h.1.insertManyIfNewUnit_list h₁.1 h₂.1 l⟩
theorem eraseMany_list [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) (h : t₁ ~m t₂) (l : List α) :
t₁.eraseMany l ~m t₂.eraseMany l :=
⟨h.1.eraseMany_list h₁.1 h₂.1 l⟩
theorem merge [TransCmp cmp] [LawfulEqCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h₃ : t₃.WF) (h₄ : t₄.WF)
(h : t₁ ~m t₂) (h' : t₃ ~m t₄) :
t₁.merge t₃ ~m t₂.merge t₄ :=
⟨h.1.mergeWith h₁.1 h₂.1 h₃.1 h₄.1 _ h'.1⟩
-- extensionalities
theorem of_forall_get?_eq [TransCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF) (h : ∀ k, t₁.get? k = t₂.get? k) : t₁ ~m t₂ :=
⟨.of_forall_getKey?_unit_eq h₁.1 h₂.1 h⟩
theorem of_forall_contains_eq [TransCmp cmp] [LawfulEqCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, t₁.contains k = t₂.contains k) : t₁ ~m t₂ :=
⟨.of_forall_contains_unit_eq h₁.1 h₂.1 h⟩
theorem of_forall_mem_iff [TransCmp cmp] [LawfulEqCmp cmp]
(h₁ : t₁.WF) (h₂ : t₂.WF)
(h : ∀ k, k ∈ t₁ ↔ k ∈ t₂) : t₁ ~m t₂ :=
⟨.of_forall_mem_unit_iff h₁.1 h₂.1 h⟩
end Equiv
section Equiv
variable {t₁ t₂ : Raw α cmp}
private theorem equiv_iff : t₁ ~m t₂ ↔ t₁.1.Equiv t₂.1 :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
theorem equiv_empty_iff_isEmpty : t ~m empty ↔ t.isEmpty :=
equiv_iff.trans TreeMap.Raw.equiv_empty_iff_isEmpty
theorem empty_equiv_iff_isEmpty : empty ~m t ↔ t.isEmpty :=
equiv_iff.trans TreeMap.Raw.empty_equiv_iff_isEmpty
theorem equiv_iff_toList_perm : t₁ ~m t₂ ↔ t₁.toList.Perm t₂.toList :=
equiv_iff.trans TreeMap.Raw.equiv_iff_keys_unit_perm
theorem Equiv.of_toList_perm (h : t₁.toList.Perm t₂.toList) : t₁ ~m t₂ :=
⟨.of_keys_unit_perm h⟩
theorem equiv_iff_toList_eq [TransCmp cmp] (h₁ : t₁.WF) (h₂ : t₂.WF) :
t₁ ~m t₂ ↔ t₁.toList = t₂.toList :=
equiv_iff.trans (TreeMap.Raw.equiv_iff_keys_unit_eq h₁.1 h₂.1)
end Equiv
end Std.TreeSet.Raw