314 lines
14 KiB
Text
314 lines
14 KiB
Text
/-
|
||
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura
|
||
-/
|
||
import data.rbtree
|
||
|
||
universes u v
|
||
|
||
namespace rbmap
|
||
variables {α : Type u} {β : Type v} {lt : α → α → Prop}
|
||
|
||
/- Auxiliary instances -/
|
||
private def rbmap_lt_is_swo {α : Type u} {β : Type v} {lt : α → α → Prop} [is_strict_weak_order α lt] : is_strict_weak_order (α × β) (rbmap_lt lt) :=
|
||
{ irrefl := λ _, irrefl_of lt _,
|
||
trans := λ _ _ _ h₁ h₂, trans_of lt h₁ h₂,
|
||
incomp_trans := λ _ _ _ h₁ h₂, incomp_trans_of lt h₁ h₂ }
|
||
|
||
private def rbmap_lt_dec {α : Type u} {β : Type v} {lt : α → α → Prop} [h : decidable_rel lt] : decidable_rel (@rbmap_lt α β lt) :=
|
||
λ a b, h a.1 b.1
|
||
|
||
local attribute [instance] rbmap_lt_is_swo rbmap_lt_dec
|
||
|
||
/- Helper lemmas for reusing rbtree results. -/
|
||
|
||
private lemma to_rbtree_mem {k : α} {m : rbmap α β lt} : k ∈ m → ∃ v : β, rbtree.mem (k, v) m :=
|
||
begin
|
||
cases m with n p; cases n; intros h,
|
||
{ exact false.elim h },
|
||
all_goals { existsi n_val.2, exact h }
|
||
end
|
||
|
||
private lemma eqv_entries_of_eqv_keys {k₁ k₂ : α} (v₁ v₂ : β) : k₁ ≈[lt] k₂ → (k₁, v₁) ≈[rbmap_lt lt] (k₂, v₂) :=
|
||
id
|
||
|
||
private lemma eqv_keys_of_eqv_entries {k₁ k₂ : α} {v₁ v₂ : β} : (k₁, v₁) ≈[rbmap_lt lt] (k₂, v₂) → k₁ ≈[lt] k₂ :=
|
||
id
|
||
|
||
private lemma eqv_entries [is_irrefl α lt] (k : α) (v₁ v₂ : β) : (k, v₁) ≈[rbmap_lt lt] (k, v₂) :=
|
||
and.intro (irrefl_of lt k) (irrefl_of lt k)
|
||
|
||
private lemma to_rbmap_mem [is_strict_weak_order α lt] {k : α} {v : β} {m : rbmap α β lt} : rbtree.mem (k, v) m → k ∈ m :=
|
||
begin
|
||
cases m with n p; cases n; intros h,
|
||
{ exact false.elim h },
|
||
{ simp [has_mem.mem, rbmap.mem],
|
||
exact @rbtree.mem_of_mem_of_eqv _ _ _ ⟨rbnode.red_node n_lchild n_val n_rchild, p⟩ _ _ h (eqv_entries _ _ _) },
|
||
{ simp [has_mem.mem, rbmap.mem],
|
||
exact @rbtree.mem_of_mem_of_eqv _ _ _ ⟨rbnode.black_node n_lchild n_val n_rchild, p⟩ _ _ h (eqv_entries _ _ _) }
|
||
end
|
||
|
||
private lemma to_rbtree_mem' [is_strict_weak_order α lt] {k : α} {m : rbmap α β lt} (v : β) : k ∈ m → rbtree.mem (k, v) m :=
|
||
begin
|
||
intro h,
|
||
cases to_rbtree_mem h with v' hm,
|
||
apply rbtree.mem_of_mem_of_eqv hm,
|
||
apply eqv_entries
|
||
end
|
||
|
||
lemma eq_some_of_to_value_eq_some {e : option (α × β)} {v : β} : to_value e = some v → ∃ k, e = some (k, v) :=
|
||
begin
|
||
cases e with val; simp [to_value],
|
||
{ cases val, simp, intro h, subst v, constructor, refl }
|
||
end
|
||
|
||
lemma eq_none_of_to_value_eq_none {e : option (α × β)} : to_value e = none → e = none :=
|
||
by cases e; simp [to_value]
|
||
|
||
/- Lemmas -/
|
||
|
||
lemma not_mem_mk_rbmap : ∀ (k : α), k ∉ mk_rbmap α β lt :=
|
||
by simp [has_mem.mem, mk_rbmap, mk_rbtree, rbmap.mem]
|
||
|
||
lemma not_mem_of_empty {m : rbmap α β lt} (k : α) : m.empty = tt → k ∉ m :=
|
||
by cases m with n p; cases n; simp [has_mem.mem, mk_rbmap, mk_rbtree, rbmap.mem, rbmap.empty, rbtree.empty]
|
||
|
||
variables [decidable_rel lt]
|
||
|
||
lemma not_mem_of_find_entry_none [is_strict_weak_order α lt] {k : α} {m : rbmap α β lt} : m.find_entry k = none → k ∉ m :=
|
||
begin
|
||
cases m with t p, cases t; simp [find_entry],
|
||
{ intros, simp [has_mem.mem, rbmap.mem] },
|
||
all_goals { intro h, exact rbtree.not_mem_of_find_none h, }
|
||
end
|
||
|
||
lemma not_mem_of_find_none [is_strict_weak_order α lt] {k : α} {m : rbmap α β lt} : m.find k = none → k ∉ m :=
|
||
begin
|
||
simp [find], intro h,
|
||
have := eq_none_of_to_value_eq_none h,
|
||
exact not_mem_of_find_entry_none this
|
||
end
|
||
|
||
lemma mem_of_find_entry_some [is_strict_weak_order α lt] {k₁ : α} {e : α × β} {m : rbmap α β lt} : m.find_entry k₁ = some e → k₁ ∈ m :=
|
||
begin
|
||
cases m with t p, cases t; simp [find_entry],
|
||
all_goals { intro h, exact rbtree.mem_of_find_some h }
|
||
end
|
||
|
||
lemma mem_of_find_some [is_strict_weak_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.find k = some v → k ∈ m :=
|
||
begin
|
||
simp [find], intro h,
|
||
have := eq_some_of_to_value_eq_some h,
|
||
cases this with _ he,
|
||
exact mem_of_find_entry_some he
|
||
end
|
||
|
||
lemma find_entry_eq_find_entry_of_eqv [is_strict_weak_order α lt] {m : rbmap α β lt} {k₁ k₂ : α} : k₁ ≈[lt] k₂ → m.find_entry k₁ = m.find_entry k₂ :=
|
||
begin
|
||
intro h, cases m with t p, cases t; simp [find_entry],
|
||
all_goals { apply rbtree.find_eq_find_of_eqv, apply eqv_entries_of_eqv_keys, assumption }
|
||
end
|
||
|
||
lemma find_eq_find_of_eqv [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) : k₁ ≈[lt] k₂ → m.find k₁ = m.find k₂ :=
|
||
begin intro h, simp [find], apply congr_arg, apply find_entry_eq_find_entry_of_eqv, assumption end
|
||
|
||
lemma find_entry_correct [is_strict_weak_order α lt] (k : α) (m : rbmap α β lt) : k ∈ m ↔ (∃ e, m.find_entry k = some e ∧ k ≈[lt] e.1) :=
|
||
begin
|
||
apply iff.intro; cases m with t p,
|
||
{ intro h,
|
||
have h := to_rbtree_mem h, cases h with v h₁,
|
||
have hex := iff.mp (rbtree.find_correct _ _) h₁, cases hex with e h₂,
|
||
existsi e, cases t; simp [find_entry] at ⊢ h₂,
|
||
{ simp [rbtree.find, rbnode.find] at h₂, cases h₂ },
|
||
{ cases h₂ with h₂₁ h₂₂, split,
|
||
{ have := rbtree.find_eq_find_of_eqv ⟨rbnode.red_node t_lchild t_val t_rchild, p⟩ (eqv_entries k v t_val.2),
|
||
rw [←this], exact h₂₁ },
|
||
{ cases e, apply eqv_keys_of_eqv_entries h₂₂ } },
|
||
{ cases h₂ with h₂₁ h₂₂, split,
|
||
{ have := rbtree.find_eq_find_of_eqv ⟨rbnode.black_node t_lchild t_val t_rchild, p⟩ (eqv_entries k v t_val.2),
|
||
rw [←this], exact h₂₁ },
|
||
{ cases e, apply eqv_keys_of_eqv_entries h₂₂ } } },
|
||
{ intro h, cases h with e h,
|
||
cases h with h₁ h₂, cases t; simp [find_entry] at h₁,
|
||
{ contradiction },
|
||
all_goals { exact to_rbmap_mem (rbtree.mem_of_find_some h₁) } }
|
||
end
|
||
|
||
lemma eqv_of_find_entry_some [is_strict_weak_order α lt] {k₁ k₂ : α} {v : β} {m : rbmap α β lt} : m.find_entry k₁ = some (k₂, v) → k₁ ≈[lt] k₂ :=
|
||
begin
|
||
cases m with t p, cases t; simp [find_entry],
|
||
all_goals { intro h, exact eqv_keys_of_eqv_entries (rbtree.eqv_of_find_some h) }
|
||
end
|
||
|
||
lemma eq_of_find_entry_some [is_strict_total_order α lt] {k₁ k₂ : α} {v : β} {m : rbmap α β lt} : m.find_entry k₁ = some (k₂, v) → k₁ = k₂ :=
|
||
λ h, suffices k₁ ≈[lt] k₂, from eq_of_eqv_lt this,
|
||
eqv_of_find_entry_some h
|
||
|
||
lemma find_correct [is_strict_weak_order α lt] (k : α) (m : rbmap α β lt) : k ∈ m ↔ ∃ v, m.find k = some v :=
|
||
begin
|
||
apply iff.intro,
|
||
{ intro h,
|
||
have := iff.mp (find_entry_correct k m) h,
|
||
cases this with e h, cases h with h₁ h₂,
|
||
existsi e.2, simp [find, h₁, to_value] },
|
||
{ intro h,
|
||
cases h with v h,
|
||
simp [find] at h,
|
||
have h := eq_some_of_to_value_eq_some h,
|
||
cases h with k' h,
|
||
have heqv := eqv_of_find_entry_some h,
|
||
exact iff.mpr (find_entry_correct k m) ⟨(k', v), ⟨h, heqv⟩⟩ }
|
||
end
|
||
|
||
lemma constains_correct [is_strict_weak_order α lt] (k : α) (m : rbmap α β lt) : k ∈ m ↔ m.contains k = tt :=
|
||
begin
|
||
apply iff.intro,
|
||
{ intro h,
|
||
have h := iff.mp (find_entry_correct k m) h,
|
||
cases h with e h, cases h with h₁ h₂,
|
||
simp [contains, h₁, option.is_some] },
|
||
{ simp [contains],
|
||
intro h,
|
||
generalize he : find_entry m k = e,
|
||
cases e,
|
||
{ simp [he, option.is_some] at h, contradiction },
|
||
{ exact mem_of_find_entry_some he } }
|
||
end
|
||
|
||
lemma mem_of_mem_of_eqv [is_strict_weak_order α lt] {m : rbmap α β lt} {k₁ k₂ : α} : k₁ ∈ m → k₁ ≈[lt] k₂ → k₂ ∈ m :=
|
||
begin
|
||
intros h₁ h₂,
|
||
have h₁ := to_rbtree_mem h₁, cases h₁ with v h₁,
|
||
exact to_rbmap_mem (rbtree.mem_of_mem_of_eqv h₁ (eqv_entries_of_eqv_keys v v h₂))
|
||
end
|
||
|
||
lemma mem_insert_of_incomp [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : (¬ lt k₁ k₂ ∧ ¬ lt k₂ k₁) → k₁ ∈ m.insert k₂ v :=
|
||
λ h, to_rbmap_mem (rbtree.mem_insert_of_incomp m (eqv_entries_of_eqv_keys v v h))
|
||
|
||
lemma mem_insert [is_strict_weak_order α lt] (k : α) (m : rbmap α β lt) (v : β) : k ∈ m.insert k v :=
|
||
to_rbmap_mem (rbtree.mem_insert (k, v) m)
|
||
|
||
lemma mem_insert_of_equiv [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : k₁ ≈[lt] k₂ → k₁ ∈ m.insert k₂ v :=
|
||
mem_insert_of_incomp m v
|
||
|
||
lemma mem_insert_of_mem [is_strict_weak_order α lt] {k₁ : α} {m : rbmap α β lt} (k₂ : α) (v : β) : k₁ ∈ m → k₁ ∈ m.insert k₂ v :=
|
||
λ h, to_rbmap_mem (rbtree.mem_insert_of_mem (k₂, v) (to_rbtree_mem' v h))
|
||
|
||
lemma equiv_or_mem_of_mem_insert [is_strict_weak_order α lt] {k₁ k₂ : α} {v : β} {m : rbmap α β lt} : k₁ ∈ m.insert k₂ v → k₁ ≈[lt] k₂ ∨ k₁ ∈ m :=
|
||
λ h, or.elim (rbtree.equiv_or_mem_of_mem_insert (to_rbtree_mem' v h))
|
||
(λ h, or.inl (eqv_keys_of_eqv_entries h))
|
||
(λ h, or.inr (to_rbmap_mem h))
|
||
|
||
lemma incomp_or_mem_of_mem_ins [is_strict_weak_order α lt] {k₁ k₂ : α} {v : β} {m : rbmap α β lt} : k₁ ∈ m.insert k₂ v → (¬ lt k₁ k₂ ∧ ¬ lt k₂ k₁) ∨ k₁ ∈ m :=
|
||
equiv_or_mem_of_mem_insert
|
||
|
||
lemma eq_or_mem_of_mem_ins [is_strict_total_order α lt] {k₁ k₂ : α} {v : β} {m : rbmap α β lt} : k₁ ∈ m.insert k₂ v → k₁ = k₂ ∨ k₁ ∈ m :=
|
||
λ h, suffices k₁ ≈[lt] k₂ ∨ k₁ ∈ m, by simp [eqv_lt_iff_eq] at this; assumption,
|
||
incomp_or_mem_of_mem_ins h
|
||
|
||
lemma find_entry_insert_of_eqv [is_strict_weak_order α lt] (m : rbmap α β lt) {k₁ k₂ : α} (v : β) : k₁ ≈[lt] k₂ → (m.insert k₁ v).find_entry k₂ = some (k₁, v) :=
|
||
begin
|
||
intro h,
|
||
generalize h₁ : m.insert k₁ v = m',
|
||
cases m' with t p, cases t,
|
||
{ have := mem_insert k₁ m v, rw [h₁] at this, apply absurd this, apply not_mem_mk_rbmap },
|
||
all_goals { simp [find_entry], rw [←h₁, insert], apply rbtree.find_insert_of_eqv, apply eqv_entries_of_eqv_keys _ _ h }
|
||
end
|
||
|
||
lemma find_entry_insert [is_strict_weak_order α lt] (m : rbmap α β lt) (k : α) (v : β) : (m.insert k v).find_entry k = some (k, v) :=
|
||
find_entry_insert_of_eqv m v (refl k)
|
||
|
||
lemma find_insert_of_eqv [is_strict_weak_order α lt] (m : rbmap α β lt) {k₁ k₂ : α} (v : β) : k₁ ≈[lt] k₂ → (m.insert k₁ v).find k₂ = some v :=
|
||
begin
|
||
intro h,
|
||
have := find_entry_insert_of_eqv m v h,
|
||
simp [find, this, to_value]
|
||
end
|
||
|
||
lemma find_insert [is_strict_weak_order α lt] (m : rbmap α β lt) (k : α) (v : β) : (m.insert k v).find k = some v :=
|
||
find_insert_of_eqv m v (refl k)
|
||
|
||
lemma find_entry_insert_of_disj [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : lt k₁ k₂ ∨ lt k₂ k₁ → (m.insert k₁ v).find_entry k₂ = m.find_entry k₂ :=
|
||
begin
|
||
intro h,
|
||
have h' : ∀ {v₁ v₂ : β}, (rbmap_lt lt) (k₁, v₁) (k₂, v₂) ∨ (rbmap_lt lt) (k₂, v₂) (k₁, v₁) := λ _ _, h,
|
||
generalize h₁ : m = m₁,
|
||
generalize h₂ : insert m₁ k₁ v = m₂,
|
||
rw [←h₁] at h₂ ⊢, rw [←h₂],
|
||
cases m₁ with t₁ p₁; cases t₁; cases m₂ with t₂ p₂; cases t₂,
|
||
{ rw [h₂, h₁] },
|
||
iterate 2 {
|
||
rw [h₂],
|
||
conv { to_lhs, simp [find_entry] },
|
||
rw [←h₂, insert, rbtree.find_insert_of_disj _ h', h₁],
|
||
refl },
|
||
any_goals { simp [insert] at h₂,
|
||
exact absurd h₂ (rbtree.insert_ne_mk_rbtree m (k₁, v)) },
|
||
any_goals {
|
||
rw [h₂, h₁], simp [find_entry], rw [←h₂, ←h₁, insert, rbtree.find_insert_of_disj _ h'],
|
||
apply rbtree.find_eq_find_of_eqv, apply eqv_entries }
|
||
end
|
||
|
||
lemma find_entry_insert_of_not_eqv [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : ¬ k₁ ≈[lt] k₂ → (m.insert k₁ v).find_entry k₂ = m.find_entry k₂ :=
|
||
begin
|
||
intro hn,
|
||
have he : lt k₁ k₂ ∨ lt k₂ k₁, {
|
||
simp [strict_weak_order.equiv, decidable.not_and_iff_or_not, decidable.not_not_iff] at hn,
|
||
assumption },
|
||
apply find_entry_insert_of_disj _ _ he
|
||
end
|
||
|
||
lemma find_entry_insert_of_ne [is_strict_total_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : k₁ ≠ k₂ → (m.insert k₁ v).find_entry k₂ = m.find_entry k₂ :=
|
||
begin
|
||
intro h,
|
||
have : ¬ k₁ ≈[lt] k₂ := λ h', h (eq_of_eqv_lt h'),
|
||
apply find_entry_insert_of_not_eqv _ _ this
|
||
end
|
||
|
||
lemma find_insert_of_disj [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : lt k₁ k₂ ∨ lt k₂ k₁ → (m.insert k₁ v).find k₂ = m.find k₂ :=
|
||
begin intro h, have := find_entry_insert_of_disj m v h, simp [find, this] end
|
||
|
||
lemma find_insert_of_not_eqv [is_strict_weak_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : ¬ k₁ ≈[lt] k₂ → (m.insert k₁ v).find k₂ = m.find k₂ :=
|
||
begin intro h, have := find_entry_insert_of_not_eqv m v h, simp [find, this] end
|
||
|
||
lemma find_insert_of_ne [is_strict_total_order α lt] {k₁ k₂ : α} (m : rbmap α β lt) (v : β) : k₁ ≠ k₂ → (m.insert k₁ v).find k₂ = m.find k₂ :=
|
||
begin intro h, have := find_entry_insert_of_ne m v h, simp [find, this] end
|
||
|
||
lemma mem_of_min_eq [is_strict_total_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.min = some (k, v) → k ∈ m :=
|
||
λ h, to_rbmap_mem (rbtree.mem_of_min_eq h)
|
||
|
||
lemma mem_of_max_eq [is_strict_total_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.max = some (k, v) → k ∈ m :=
|
||
λ h, to_rbmap_mem (rbtree.mem_of_max_eq h)
|
||
|
||
lemma eq_leaf_of_min_eq_none [is_strict_weak_order α lt] {m : rbmap α β lt} : m.min = none → m = mk_rbmap α β lt :=
|
||
rbtree.eq_leaf_of_min_eq_none
|
||
|
||
lemma eq_leaf_of_max_eq_none [is_strict_weak_order α lt] {m : rbmap α β lt} : m.max = none → m = mk_rbmap α β lt :=
|
||
rbtree.eq_leaf_of_max_eq_none
|
||
|
||
lemma min_is_minimal [is_strict_weak_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.min = some (k, v) → ∀ {k'}, k' ∈ m → k ≈[lt] k' ∨ lt k k' :=
|
||
λ h k' hm, or.elim (rbtree.min_is_minimal h (to_rbtree_mem' v hm))
|
||
(λ h, or.inl (eqv_keys_of_eqv_entries h))
|
||
(λ h, or.inr h)
|
||
|
||
lemma max_is_maximal [is_strict_weak_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.max = some (k, v) → ∀ {k'}, k' ∈ m → k ≈[lt] k' ∨ lt k' k :=
|
||
λ h k' hm, or.elim (rbtree.max_is_maximal h (to_rbtree_mem' v hm))
|
||
(λ h, or.inl (eqv_keys_of_eqv_entries h))
|
||
(λ h, or.inr h)
|
||
|
||
lemma min_is_minimal_of_total [is_strict_total_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.min = some (k, v) → ∀ {k'}, k' ∈ m → k = k' ∨ lt k k' :=
|
||
λ h k' hm,
|
||
match min_is_minimal h hm with
|
||
| or.inl h := or.inl (eq_of_eqv_lt h)
|
||
| or.inr h := or.inr h
|
||
end
|
||
|
||
lemma max_is_maximal_of_total [is_strict_total_order α lt] {k : α} {v : β} {m : rbmap α β lt} : m.max = some (k, v) → ∀ {k'}, k' ∈ m → k = k' ∨ lt k' k :=
|
||
λ h k' hm,
|
||
match max_is_maximal h hm with
|
||
| or.inl h := or.inl (eq_of_eqv_lt h)
|
||
| or.inr h := or.inr h
|
||
end
|
||
|
||
end rbmap
|