lean4-htt/src/Std/Data/TreeSet/Lemmas.lean
Paul Reichert 7e2d6e2254
feat: tree map lemmas for the getKey variants and insertIfNew functions (#7221)
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>
2025-02-26 07:36:28 +00:00

337 lines
11 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
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