This PR provides lemmas about the tree map functions `getKey?`, `getKey`, `getKey!`, `getKeyD` and `insertIfNew` and their interaction with other functions for which lemmas already exist. --------- Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com>
337 lines
11 KiB
Text
337 lines
11 KiB
Text
/-
|
||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Markus Himmel, Paul Reichert
|
||
-/
|
||
prelude
|
||
import Std.Data.TreeMap.Lemmas
|
||
import Std.Data.TreeSet.Basic
|
||
|
||
/-!
|
||
# Tree set lemmas
|
||
|
||
This file contains lemmas about `Std.Data.TreeSet`. Most of the lemmas require
|
||
`TransCmp cmp` for the comparison function `cmp`.
|
||
-/
|
||
|
||
set_option linter.missingDocs true
|
||
set_option autoImplicit false
|
||
|
||
universe u v
|
||
|
||
namespace Std.TreeSet
|
||
|
||
variable {α : Type u} {cmp : α → α → Ordering} {t : TreeSet α cmp}
|
||
|
||
private theorem ext {t t' : TreeSet α cmp} : t.inner = t'.inner → t = t' := by
|
||
cases t; cases t'; rintro rfl; rfl
|
||
|
||
@[simp]
|
||
theorem isEmpty_emptyc : (∅ : TreeSet α cmp).isEmpty :=
|
||
TreeMap.isEmpty_emptyc
|
||
|
||
@[simp]
|
||
theorem isEmpty_insert [TransCmp cmp] {k : α} :
|
||
(t.insert k).isEmpty = false :=
|
||
TreeMap.isEmpty_insertIfNew
|
||
|
||
theorem mem_iff_contains {k : α} : k ∈ t ↔ t.contains k :=
|
||
TreeMap.mem_iff_contains
|
||
|
||
theorem contains_congr [TransCmp cmp] {k k' : α} (hab : cmp k k' = .eq) :
|
||
t.contains k = t.contains k' :=
|
||
TreeMap.contains_congr hab
|
||
|
||
theorem mem_congr [TransCmp cmp] {k k' : α} (hab : cmp k k' = .eq) : k ∈ t ↔ k' ∈ t :=
|
||
TreeMap.mem_congr hab
|
||
|
||
@[simp]
|
||
theorem contains_emptyc {k : α} : (∅ : TreeSet α cmp).contains k = false :=
|
||
TreeMap.contains_emptyc
|
||
|
||
@[simp]
|
||
theorem not_mem_emptyc {k : α} : k ∉ (∅ : TreeSet α cmp) :=
|
||
TreeMap.not_mem_emptyc
|
||
|
||
theorem contains_of_isEmpty [TransCmp cmp] {a : α} :
|
||
t.isEmpty → t.contains a = false :=
|
||
DTreeMap.contains_of_isEmpty
|
||
|
||
theorem not_mem_of_isEmpty [TransCmp cmp] {a : α} :
|
||
t.isEmpty → a ∉ t :=
|
||
DTreeMap.not_mem_of_isEmpty
|
||
|
||
theorem isEmpty_eq_false_iff_exists_contains_eq_true [TransCmp cmp] :
|
||
t.isEmpty = false ↔ ∃ a, t.contains a = true :=
|
||
DTreeMap.isEmpty_eq_false_iff_exists_contains_eq_true
|
||
|
||
theorem isEmpty_eq_false_iff_exists_mem [TransCmp cmp] :
|
||
t.isEmpty = false ↔ ∃ a, a ∈ t :=
|
||
DTreeMap.isEmpty_eq_false_iff_exists_mem
|
||
|
||
theorem isEmpty_iff_forall_contains [TransCmp cmp] :
|
||
t.isEmpty = true ↔ ∀ a, t.contains a = false :=
|
||
DTreeMap.isEmpty_iff_forall_contains
|
||
|
||
theorem isEmpty_iff_forall_not_mem [TransCmp cmp] :
|
||
t.isEmpty = true ↔ ∀ a, ¬a ∈ t :=
|
||
DTreeMap.isEmpty_iff_forall_not_mem
|
||
|
||
@[simp]
|
||
theorem insert_eq_insert {p : α} : Insert.insert p t = t.insert p :=
|
||
rfl
|
||
|
||
@[simp]
|
||
theorem singleton_eq_insert {p : α} :
|
||
Singleton.singleton p = (∅ : TreeSet α cmp).insert p :=
|
||
rfl
|
||
|
||
@[simp]
|
||
theorem contains_insert [h : TransCmp cmp] {k a : α} :
|
||
(t.insert k).contains a = (cmp k a == .eq || t.contains a) :=
|
||
TreeMap.contains_insertIfNew
|
||
|
||
@[simp]
|
||
theorem mem_insert [TransCmp cmp] {k a : α} :
|
||
a ∈ t.insert k ↔ cmp k a = .eq ∨ a ∈ t :=
|
||
TreeMap.mem_insertIfNew
|
||
|
||
theorem contains_insert_self [TransCmp cmp] {k : α} :
|
||
(t.insert k).contains k :=
|
||
TreeMap.contains_insertIfNew_self
|
||
|
||
theorem mem_insert_self [TransCmp cmp] {k : α} :
|
||
k ∈ t.insert k :=
|
||
TreeMap.mem_insertIfNew_self
|
||
|
||
theorem contains_of_contains_insert [TransCmp cmp] {k a : α} :
|
||
(t.insert k).contains a → cmp k a ≠ .eq → t.contains a :=
|
||
TreeMap.contains_of_contains_insertIfNew
|
||
|
||
theorem mem_of_mem_insert [TransCmp cmp] {k a : α} :
|
||
a ∈ t.insert k → cmp k a ≠ .eq → a ∈ t :=
|
||
TreeMap.mem_of_mem_insertIfNew
|
||
|
||
/-- This is a restatement of `mem_of_mem_insert` that is written to exactly match the
|
||
proof obligation in the statement of `get_insert`. -/
|
||
theorem mem_of_mem_insert' [TransCmp cmp] {k a : α} :
|
||
a ∈ t.insert k → ¬ (cmp k a = .eq ∧ ¬ k ∈ t) → a ∈ t :=
|
||
TreeMap.mem_of_mem_insertIfNew'
|
||
|
||
@[simp]
|
||
theorem size_emptyc : (∅ : TreeSet α cmp).size = 0 :=
|
||
TreeMap.size_emptyc
|
||
|
||
theorem isEmpty_eq_size_eq_zero :
|
||
t.isEmpty = (t.size == 0) :=
|
||
TreeMap.isEmpty_eq_size_eq_zero
|
||
|
||
theorem size_insert [TransCmp cmp] {k : α} :
|
||
(t.insert k).size = if t.contains k then t.size else t.size + 1 :=
|
||
TreeMap.size_insertIfNew
|
||
|
||
theorem size_le_size_insert [TransCmp cmp] {k : α} :
|
||
t.size ≤ (t.insert k).size :=
|
||
TreeMap.size_le_size_insertIfNew
|
||
|
||
theorem size_insert_le [TransCmp cmp] {k : α} :
|
||
(t.insert k).size ≤ t.size + 1 :=
|
||
TreeMap.size_insertIfNew_le
|
||
|
||
@[simp]
|
||
theorem erase_emptyc {k : α} :
|
||
(∅ : TreeSet α cmp).erase k = ∅ :=
|
||
ext <| TreeMap.erase_emptyc
|
||
|
||
@[simp]
|
||
theorem isEmpty_erase [TransCmp cmp] {k : α} :
|
||
(t.erase k).isEmpty = (t.isEmpty || (t.size == 1 && t.contains k)) :=
|
||
TreeMap.isEmpty_erase
|
||
|
||
@[simp]
|
||
theorem contains_erase [TransCmp cmp] {k a : α} :
|
||
(t.erase k).contains a = (cmp k a != .eq && t.contains a) :=
|
||
TreeMap.contains_erase
|
||
|
||
@[simp]
|
||
theorem mem_erase [TransCmp cmp] {k a : α} :
|
||
a ∈ t.erase k ↔ cmp k a ≠ .eq ∧ a ∈ t :=
|
||
TreeMap.mem_erase
|
||
|
||
theorem contains_of_contains_erase [TransCmp cmp] {k a : α} :
|
||
(t.erase k).contains a → t.contains a :=
|
||
TreeMap.contains_of_contains_erase
|
||
|
||
theorem mem_of_mem_erase [TransCmp cmp] {k a : α} :
|
||
(t.erase k).contains a → t.contains a :=
|
||
TreeMap.mem_of_mem_erase
|
||
|
||
theorem size_erase [TransCmp cmp] {k : α} :
|
||
(t.erase k).size = if t.contains k then t.size - 1 else t.size :=
|
||
TreeMap.size_erase
|
||
|
||
theorem size_erase_le [TransCmp cmp] {k : α} :
|
||
(t.erase k).size ≤ t.size :=
|
||
TreeMap.size_erase_le
|
||
|
||
theorem size_le_size_erase [TransCmp cmp] {k : α} :
|
||
t.size ≤ (t.erase k).size + 1 :=
|
||
TreeMap.size_le_size_erase
|
||
|
||
@[simp]
|
||
theorem get?_emptyc {a : α} : (∅ : TreeSet α cmp).get? a = none :=
|
||
TreeMap.getKey?_emptyc
|
||
|
||
theorem get?_of_isEmpty [TransCmp cmp] {a : α} :
|
||
t.isEmpty = true → t.get? a = none :=
|
||
TreeMap.getKey?_of_isEmpty
|
||
|
||
theorem get?_insert [TransCmp cmp] {k a : α} :
|
||
(t.insert k).get? a = if cmp k a = .eq ∧ ¬k ∈ t then some k else t.get? a :=
|
||
TreeMap.getKey?_insertIfNew
|
||
|
||
theorem contains_eq_isSome_get? [TransCmp cmp] {a : α} :
|
||
t.contains a = (t.get? a).isSome :=
|
||
TreeMap.contains_eq_isSome_getKey?
|
||
|
||
theorem get?_eq_none_of_contains_eq_false [TransCmp cmp] {a : α} :
|
||
t.contains a = false → t.get? a = none :=
|
||
TreeMap.getKey?_eq_none_of_contains_eq_false
|
||
|
||
theorem get?_eq_none [TransCmp cmp] {a : α} :
|
||
¬ a ∈ t → t.get? a = none :=
|
||
TreeMap.getKey?_eq_none
|
||
|
||
theorem get?_erase [TransCmp cmp] {k a : α} :
|
||
(t.erase k).get? a = if cmp k a = .eq then none else t.get? a :=
|
||
TreeMap.getKey?_erase
|
||
|
||
@[simp]
|
||
theorem get?_erase_self [TransCmp cmp] {k : α} :
|
||
(t.erase k).get? k = none :=
|
||
TreeMap.getKey?_erase_self
|
||
|
||
theorem get_insert [TransCmp cmp] {k a : α} {h₁} :
|
||
(t.insert k).get a h₁ =
|
||
if h₂ : cmp k a = .eq ∧ ¬ k ∈ t then k
|
||
else t.get a (mem_of_mem_insert' h₁ h₂) :=
|
||
TreeMap.getKey_insertIfNew
|
||
|
||
@[simp]
|
||
theorem get_erase [TransCmp cmp] {k a : α} {h'} :
|
||
(t.erase k).get a h' = t.get a (mem_of_mem_erase h') :=
|
||
TreeMap.getKey_erase
|
||
|
||
theorem get?_eq_some_get [TransCmp cmp] {a : α} {h'} :
|
||
t.get? a = some (t.get a h') :=
|
||
TreeMap.getKey?_eq_some_getKey
|
||
|
||
@[simp]
|
||
theorem get!_emptyc {a : α} [Inhabited α] :
|
||
(∅ : TreeSet α cmp).get! a = default :=
|
||
TreeMap.getKey!_emptyc
|
||
|
||
theorem get!_of_isEmpty [TransCmp cmp] [Inhabited α] {a : α} :
|
||
t.isEmpty = true → t.get! a = default :=
|
||
TreeMap.getKey!_of_isEmpty
|
||
|
||
theorem get!_insert [TransCmp cmp] [Inhabited α] {k a : α} :
|
||
(t.insert k).get! a = if cmp k a = .eq ∧ ¬ k ∈ t then k else t.get! a :=
|
||
TreeMap.getKey!_insertIfNew
|
||
|
||
theorem get!_eq_default_of_contains_eq_false [TransCmp cmp] [Inhabited α] {a : α} :
|
||
t.contains a = false → t.get! a = default :=
|
||
TreeMap.getKey!_eq_default_of_contains_eq_false
|
||
|
||
theorem get!_eq_default [TransCmp cmp] [Inhabited α] {a : α} :
|
||
¬ a ∈ t → t.get! a = default :=
|
||
TreeMap.getKey!_eq_default
|
||
|
||
theorem get!_erase [TransCmp cmp] [Inhabited α] {k a : α} :
|
||
(t.erase k).get! a = if cmp k a = .eq then default else t.get! a :=
|
||
TreeMap.getKey!_erase
|
||
|
||
@[simp]
|
||
theorem get!_erase_self [TransCmp cmp] [Inhabited α] {k : α} :
|
||
(t.erase k).get! k = default :=
|
||
TreeMap.getKey!_erase_self
|
||
|
||
theorem get?_eq_some_get!_of_contains [TransCmp cmp] [Inhabited α] {a : α} :
|
||
t.contains a = true → t.get? a = some (t.get! a) :=
|
||
TreeMap.getKey?_eq_some_getKey!_of_contains
|
||
|
||
theorem get?_eq_some_get! [TransCmp cmp] [Inhabited α] {a : α} :
|
||
a ∈ t → t.get? a = some (t.get! a) :=
|
||
TreeMap.getKey?_eq_some_getKey!
|
||
|
||
theorem get!_eq_get!_get? [TransCmp cmp] [Inhabited α] {a : α} :
|
||
t.get! a = (t.get? a).get! :=
|
||
TreeMap.getKey!_eq_get!_getKey?
|
||
|
||
theorem get_eq_get! [TransCmp cmp] [Inhabited α] {a : α} {h} :
|
||
t.get a h = t.get! a :=
|
||
TreeMap.getKey_eq_getKey!
|
||
|
||
@[simp]
|
||
theorem getD_emptyc {a : α} {fallback : α} :
|
||
(∅ : TreeSet α cmp).getD a fallback = fallback :=
|
||
TreeMap.getKeyD_emptyc
|
||
|
||
theorem getD_of_isEmpty [TransCmp cmp] {a fallback : α} :
|
||
t.isEmpty = true → t.getD a fallback = fallback :=
|
||
TreeMap.getKeyD_of_isEmpty
|
||
|
||
theorem getD_insert [TransCmp cmp] {k a fallback : α} :
|
||
(t.insert k).getD a fallback =
|
||
if cmp k a = .eq ∧ ¬ k ∈ t then k else t.getD a fallback :=
|
||
TreeMap.getKeyD_insertIfNew
|
||
|
||
theorem getD_eq_fallback_of_contains_eq_false [TransCmp cmp] {a fallback : α} :
|
||
t.contains a = false → t.getD a fallback = fallback :=
|
||
TreeMap.getKeyD_eq_fallback_of_contains_eq_false
|
||
|
||
theorem getD_eq_fallback [TransCmp cmp] {a fallback : α} :
|
||
¬ a ∈ t → t.getD a fallback = fallback :=
|
||
TreeMap.getKeyD_eq_fallback
|
||
|
||
theorem getD_erase [TransCmp cmp] {k a fallback : α} :
|
||
(t.erase k).getD a fallback =
|
||
if cmp k a = .eq then fallback else t.getD a fallback :=
|
||
TreeMap.getKeyD_erase
|
||
|
||
@[simp]
|
||
theorem getD_erase_self [TransCmp cmp] {k fallback : α} :
|
||
(t.erase k).getD k fallback = fallback :=
|
||
TreeMap.getKeyD_erase_self
|
||
|
||
theorem get?_eq_some_getD_of_contains [TransCmp cmp] {a fallback : α} :
|
||
t.contains a = true → t.get? a = some (t.getD a fallback) :=
|
||
TreeMap.getKey?_eq_some_getKeyD_of_contains
|
||
|
||
theorem get?_eq_some_getD [TransCmp cmp] {a fallback : α} :
|
||
a ∈ t → t.get? a = some (t.getD a fallback) :=
|
||
TreeMap.getKey?_eq_some_getKeyD
|
||
|
||
theorem getD_eq_getD_get? [TransCmp cmp] {a fallback : α} :
|
||
t.getD a fallback = (t.get? a).getD fallback :=
|
||
TreeMap.getKeyD_eq_getD_getKey?
|
||
|
||
theorem get_eq_getD [TransCmp cmp] {a fallback : α} {h} :
|
||
t.get a h = t.getD a fallback :=
|
||
TreeMap.getKey_eq_getKeyD
|
||
|
||
theorem get!_eq_getD_default [TransCmp cmp] [Inhabited α] {a : α} :
|
||
t.get! a = t.getD a default :=
|
||
TreeMap.getKey!_eq_getKeyD_default
|
||
|
||
@[simp]
|
||
theorem containsThenInsert_fst [TransCmp cmp] {k : α} :
|
||
(t.containsThenInsert k).1 = t.contains k :=
|
||
TreeMap.containsThenInsertIfNew_fst
|
||
|
||
@[simp]
|
||
theorem containsThenInsert_snd [TransCmp cmp] {k : α} :
|
||
(t.containsThenInsert k).2 = t.insert k :=
|
||
ext <| TreeMap.containsThenInsertIfNew_snd
|
||
|
||
end Std.TreeSet
|