lean4-htt/library/data/rbtree/insert.lean

737 lines
31 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) 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.find
universes u v
namespace rbnode
variables {α : Type u}
lemma balance1_ne_leaf (l : rbnode α) (x r v t) : balance1 l x r v t ≠ leaf :=
by cases l; cases r; simp [balance1]; intro; contradiction
lemma balance1_node_ne_leaf {s : rbnode α} (a : α) (t : rbnode α) : s ≠ leaf → balance1_node s a t ≠ leaf :=
begin
intro h, cases s,
{ contradiction },
all_goals { simp [balance1_node], apply balance1_ne_leaf }
end
lemma balance2_ne_leaf (l : rbnode α) (x r v t) : balance2 l x r v t ≠ leaf :=
by cases l; cases r; simp [balance2]; intro; contradiction
lemma balance2_node_ne_leaf {s : rbnode α} (a : α) (t : rbnode α) : s ≠ leaf → balance2_node s a t ≠ leaf :=
begin
intro h, cases s,
{ contradiction },
all_goals { simp [balance2_node], apply balance2_ne_leaf }
end
variables (lt : αα → Prop) [decidable_rel lt]
open color
@[elab_as_eliminator]
lemma ins.induction {p : rbnode α → Prop}
(t x)
(h₁ : p leaf)
(h₂ : ∀ a y b (hc : cmp_using lt x y = ordering.lt) (ih : p a), p (red_node a y b))
(h₃ : ∀ a y b (hc : cmp_using lt x y = ordering.eq), p (red_node a y b))
(h₄ : ∀ a y b (hc : cmp_using lt x y = ordering.gt) (ih : p b), p (red_node a y b))
(h₅ : ∀ a y b (hc : cmp_using lt x y = ordering.lt) (hr : get_color a = red) (ih : p a), p (black_node a y b))
(h₆ : ∀ a y b (hc : cmp_using lt x y = ordering.lt) (hnr : get_color a ≠ red) (ih : p a), p (black_node a y b))
(h₇ : ∀ a y b (hc : cmp_using lt x y = ordering.eq), p (black_node a y b))
(h₈ : ∀ a y b (hc : cmp_using lt x y = ordering.gt) (hr : get_color b = red) (ih : p b), p (black_node a y b))
(h₉ : ∀ a y b (hc : cmp_using lt x y = ordering.gt) (hnr : get_color b ≠ red) (ih : p b), p (black_node a y b))
: p t :=
begin
induction t,
case leaf { apply h₁ },
case red_node a y b {
generalize h : cmp_using lt x y = c,
cases c,
case ordering.lt { apply h₂; assumption },
case ordering.eq { apply h₃; assumption },
case ordering.gt { apply h₄; assumption },
},
case black_node a y b {
generalize h : cmp_using lt x y = c,
cases c,
case ordering.lt {
by_cases get_color a = red,
{ apply h₅; assumption },
{ apply h₆; assumption },
},
case ordering.eq { apply h₇; assumption },
case ordering.gt {
by_cases get_color b = red,
{ apply h₈; assumption },
{ apply h₉; assumption },
}
}
end
lemma is_searchable_balance1 {l y r v t lo hi} (hl : is_searchable lt l lo (some y)) (hr : is_searchable lt r (some y) (some v)) (ht : is_searchable lt t (some v) hi) : is_searchable lt (balance1 l y r v t) lo hi :=
by cases l; cases r; simp [balance1]; is_searchable_tactic
lemma is_searchable_balance1_node {t} [is_trans α lt] : ∀ {y s lo hi}, is_searchable lt t lo (some y) → is_searchable lt s (some y) hi → is_searchable lt (balance1_node t y s) lo hi :=
begin
cases t; simp [balance1_node]; intros; is_searchable_tactic,
{ cases lo,
{ apply is_searchable_none_low_of_is_searchable_some_low, assumption },
{ simp [lift] at *, apply is_searchable_some_low_of_is_searchable_of_lt; assumption } },
all_goals { apply is_searchable_balance1; assumption }
end
lemma is_searchable_balance2 {l y r v t lo hi} (ht : is_searchable lt t lo (some v)) (hl : is_searchable lt l (some v) (some y)) (hr : is_searchable lt r (some y) hi) : is_searchable lt (balance2 l y r v t) lo hi :=
by cases l; cases r; simp [balance2]; is_searchable_tactic
lemma is_searchable_balance2_node {t} [is_trans α lt] : ∀ {y s lo hi}, is_searchable lt s lo (some y) → is_searchable lt t (some y) hi → is_searchable lt (balance2_node t y s) lo hi :=
begin
induction t; simp [balance2_node]; intros; is_searchable_tactic,
{ cases hi,
{ apply is_searchable_none_high_of_is_searchable_some_high, assumption },
{ simp [lift] at *, apply is_searchable_some_high_of_is_searchable_of_lt, assumption' } },
all_goals { apply is_searchable_balance2, assumption' }
end
lemma is_searchable_ins {t x} [is_strict_weak_order α lt] : ∀ {lo hi} (h : is_searchable lt t lo hi), lift lt lo (some x) → lift lt (some x) hi → is_searchable lt (ins lt t x) lo hi :=
begin
apply ins.induction lt t x; intros; simp [ins, lift, *] at * {eta := ff}; is_searchable_tactic,
{ apply ih hs₁, assumption, simp [lift, *] },
{ apply is_searchable_of_is_searchable_of_incomp hc, assumption },
{ apply is_searchable_of_incomp_of_is_searchable hc, assumption },
{ apply ih hs₂, cases hi; simp [lift, *], assumption },
{ apply is_searchable_balance1_node, apply ih hs₁, assumption, simp [lift, *], assumption },
{ apply ih hs₁, assumption, simp [lift, *] },
{ apply is_searchable_of_is_searchable_of_incomp hc, assumption },
{ apply is_searchable_of_incomp_of_is_searchable hc, assumption },
{ apply is_searchable_balance2_node, assumption, apply ih hs₂, simp [lift, *], assumption },
{ apply ih hs₂, assumption, simp [lift, *] }
end
lemma is_searchable_mk_insert_result {c t} : is_searchable lt t none none → is_searchable lt (mk_insert_result c t) none none :=
begin
cases c; cases t; simp [mk_insert_result],
any_goals { exact id },
{ intro h, is_searchable_tactic }
end
lemma is_searchable_insert {t x} [is_strict_weak_order α lt] : is_searchable lt t none none → is_searchable lt (insert lt t x) none none :=
begin
intro h, simp [insert], apply is_searchable_mk_insert_result, apply is_searchable_ins, assumption, simp [lift], simp [lift]
end
end rbnode
namespace rbnode
section membership_lemmas
parameters {α : Type u} (lt : αα → Prop) [decidable_rel lt]
local infix `∈` := mem lt
lemma mem_balance1_node_of_mem_left {x s} (v) (t : rbnode α) : x ∈ s → x ∈ balance1_node s v t :=
begin
cases s,
{ simp [mem] },
all_goals {
intro h,
simp [balance1_node], cases lchild; cases rchild,
any_goals { simp [*, mem, balance1] at * },
all_goals { blast_disjs; simp [*] }
}
end
lemma mem_balance2_node_of_mem_left {x s} (v) (t : rbnode α) : x ∈ s → x ∈ balance2_node s v t :=
begin
cases s,
{ simp [mem] },
all_goals {
intro h,
simp [balance2_node], cases lchild; cases rchild,
any_goals { simp [*, mem, balance2] at * },
all_goals { blast_disjs; simp [*] }
}
end
lemma mem_balance1_node_of_mem_right {x t} (v) (s : rbnode α) : x ∈ t → x ∈ balance1_node s v t :=
begin
intros, cases s,
{ simp [mem, balance1_node, *] },
all_goals { simp [balance1_node], cases lchild; cases rchild; simp [*, mem, balance1] }
end
lemma mem_balance2_node_of_mem_right {x t} (v) (s : rbnode α) : x ∈ t → x ∈ balance2_node s v t :=
begin
intros, cases s,
{ simp [mem, balance2_node, *] },
all_goals { simp [balance2_node], cases lchild; cases rchild; simp [*, mem, balance2] }
end
lemma mem_balance1_node_of_incomp {x v} (s t) : (¬ lt x v ∧ ¬ lt v x) → s ≠ leaf → x ∈ balance1_node s v t :=
begin
intros, cases s,
case leaf { contradiction },
all_goals { simp [balance1_node], cases lchild; cases rchild; simp [*, mem, balance1] }
end
lemma mem_balance2_node_of_incomp {x v} (s t) : (¬ lt v x ∧ ¬ lt x v) → s ≠ leaf → x ∈ balance2_node s v t :=
begin
intros, cases s,
case leaf { contradiction },
all_goals { simp [balance2_node], cases lchild; cases rchild; simp [*, mem, balance2] }
end
lemma ins_ne_leaf (t : rbnode α) (x : α) : t.ins lt x ≠ leaf :=
begin
apply ins.induction lt t x,
any_goals { intros, simp [ins, *], contradiction},
{ intros, simp [ins, *], apply balance1_node_ne_leaf, assumption },
{ intros, simp [ins, *], apply balance2_node_ne_leaf, assumption },
end
lemma insert_ne_leaf (t : rbnode α) (x : α) : insert lt t x ≠ leaf :=
begin
simp [insert],
generalize he : ins lt t x = t',
cases t'; cases get_color t; simp [mk_insert_result],
{ have := ins_ne_leaf lt t x, contradiction },
any_goals { contradiction },
{ exact absurd he (ins_ne_leaf _ _ _) }
end
lemma mem_ins_of_incomp (t : rbnode α) {x y : α} : ∀ h : ¬ lt x y ∧ ¬ lt y x, x ∈ t.ins lt y :=
begin
apply ins.induction lt t y,
{ simp [ins, mem], apply id },
any_goals { intros, simp [ins, mem, *] },
{ have := ih h, apply mem_balance1_node_of_mem_left, assumption },
{ have := ih h, apply mem_balance2_node_of_mem_left, assumption }
end
lemma mem_ins_of_mem [is_strict_weak_order α lt] {t : rbnode α} (z : α) : ∀ {x} (h : x ∈ t), x ∈ t.ins lt z :=
begin
apply ins.induction lt t z; intros,
{ simp [mem, ins] at h, contradiction },
all_goals { simp [ins, mem, *] at *, blast_disjs },
any_goals { simp [h] },
any_goals { simp [ih h] },
{ have := incomp_trans_of lt h ⟨hc.2, hc.1⟩, simp [this] },
{ apply mem_balance1_node_of_mem_left, apply ih h },
{ have := ins_ne_leaf lt a z, apply mem_balance1_node_of_incomp, cases h, all_goals { simp [*] } },
{ apply mem_balance1_node_of_mem_right, assumption },
{ have := incomp_trans_of lt hc ⟨h.2, h.1⟩, simp [this] },
{ apply mem_balance2_node_of_mem_right, assumption },
{ have := ins_ne_leaf lt a z, apply mem_balance2_node_of_incomp, cases h, simp [*], apply ins_ne_leaf },
{ apply mem_balance2_node_of_mem_left, apply ih h }
end
lemma mem_mk_insert_result {a t} (c) : mem lt a t → mem lt a (mk_insert_result c t) :=
by intros; cases c; cases t; simp [mk_insert_result, mem, *] at *
lemma mem_of_mem_mk_insert_result {a t c} : mem lt a (mk_insert_result c t) → mem lt a t :=
by cases t; cases c; simp [mk_insert_result, mem]; intros; assumption
lemma mem_insert_of_incomp (t : rbnode α) {x y : α} : ∀ h : ¬ lt x y ∧ ¬ lt y x, x ∈ t.insert lt y :=
by intros; unfold insert; apply mem_mk_insert_result; apply mem_ins_of_incomp; assumption
lemma mem_insert_of_mem [is_strict_weak_order α lt] {t x} (z) : x ∈ t → x ∈ t.insert lt z :=
by intros; apply mem_mk_insert_result; apply mem_ins_of_mem; assumption
lemma of_mem_balance1_node [is_strict_weak_order α lt] {x s v t} : x ∈ balance1_node s v t → x ∈ s (¬ lt x v ∧ ¬ lt v x) x ∈ t :=
begin
cases s,
{ simp [mem, balance1_node], intros, simp [*] },
all_goals { cases lchild; cases rchild; simp [mem, balance1, balance1_node]; intros; blast_disjs; simp [*] }
end
lemma of_mem_balance2_node [is_strict_weak_order α lt] {x s v t} : x ∈ balance2_node s v t → x ∈ s (¬ lt x v ∧ ¬ lt v x) x ∈ t :=
begin
cases s,
{ simp [mem, balance2_node], intros, simp [*] },
all_goals { cases lchild; cases rchild; simp [mem, balance2, balance2_node]; intros; blast_disjs; simp [*] }
end
lemma equiv_or_mem_of_mem_ins [is_strict_weak_order α lt] {t : rbnode α} {x z} : ∀ (h : x ∈ t.ins lt z), x ≈[lt] z x ∈ t :=
begin
apply ins.induction lt t z; intros; simp [mem, ins, strict_weak_order.equiv, *] at *; blast_disjs,
any_goals { simp [h] },
any_goals { have ih := ih h, cases ih; simp [*], done },
{ have h := of_mem_balance1_node lt h, blast_disjs, have := ih h, blast_disjs, all_goals { simp [*] } },
{ have h := of_mem_balance2_node lt h, blast_disjs, have := ih h, blast_disjs, all_goals { simp [*] } }
end
lemma equiv_or_mem_of_mem_insert [is_strict_weak_order α lt] {t : rbnode α} {x z} : ∀ (h : x ∈ t.insert lt z), x ≈[lt] z x ∈ t :=
begin
simp [insert], intros, apply equiv_or_mem_of_mem_ins, exact mem_of_mem_mk_insert_result lt h
end
lemma mem_exact_balance1_node_of_mem_exact {x s} (v) (t : rbnode α) : mem_exact x s → mem_exact x (balance1_node s v t) :=
begin
cases s,
{ simp [mem_exact] },
all_goals {
intro h,
simp [balance1_node], cases lchild; cases rchild,
any_goals { simp [*, mem_exact, balance1] at * },
all_goals { blast_disjs; simp [*] }
}
end
lemma mem_exact_balance2_node_of_mem_exact {x s} (v) (t : rbnode α) : mem_exact x s → mem_exact x (balance2_node s v t) :=
begin
cases s,
{ simp [mem_exact] },
all_goals {
intro h,
simp [balance2_node], cases lchild; cases rchild,
any_goals { simp [*, mem_exact, balance2] at * },
all_goals { blast_disjs; simp [*] }
}
end
lemma find_balance1_node [is_strict_weak_order α lt] {x y z t s} : ∀ {lo hi}, is_searchable lt t lo (some z) → is_searchable lt s (some z) hi → find lt t y = some x → y ≈[lt] x → find lt (balance1_node t z s) y = some x :=
begin
intros _ _ hs₁ hs₂ heq heqv,
have hs := is_searchable_balance1_node lt hs₁ hs₂,
have := eq.trans (find_eq_find_of_eqv hs₁ heqv.symm) heq,
have := iff.mpr (find_correct_exact hs₁) this,
have := mem_exact_balance1_node_of_mem_exact z s this,
have := iff.mp (find_correct_exact hs) this,
exact eq.trans (find_eq_find_of_eqv hs heqv) this
end
lemma find_balance2_node [is_strict_weak_order α lt] {x y z s t} [is_trans α lt] : ∀ {lo hi}, is_searchable lt s lo (some z) → is_searchable lt t (some z) hi → find lt t y = some x → y ≈[lt] x → find lt (balance2_node t z s) y = some x :=
begin
intros _ _ hs₁ hs₂ heq heqv,
have hs := is_searchable_balance2_node lt hs₁ hs₂,
have := eq.trans (find_eq_find_of_eqv hs₂ heqv.symm) heq,
have := iff.mpr (find_correct_exact hs₂) this,
have := mem_exact_balance2_node_of_mem_exact z s this,
have := iff.mp (find_correct_exact hs) this,
exact eq.trans (find_eq_find_of_eqv hs heqv) this
end
/- Auxiliary lemma -/
lemma ite_eq_of_not_lt [is_strict_order α lt] {a b} {β : Type v} (t s : β) (h : lt b a) : (if lt a b then t else s) = s :=
begin have := not_lt_of_lt h, simp [*] end
local attribute [simp] ite_eq_of_not_lt
private meta def simp_fi : tactic unit :=
`[simp [find, ins, *, cmp_using]]
lemma find_ins_of_eqv [is_strict_weak_order α lt] {x y : α} {t : rbnode α} (he : x ≈[lt] y) : ∀ {lo hi} (hs : is_searchable lt t lo hi) (hlt₁ : lift lt lo (some x)) (hlt₂ : lift lt (some x) hi), find lt (ins lt t x) y = some x :=
begin
simp [strict_weak_order.equiv] at he,
apply ins.induction lt t x; intros,
{ simp_fi },
all_goals { simp at hc, cases hs },
{ have := lt_of_incomp_of_lt he.swap hc,
have := ih hs₁ hlt₁ hc,
simp_fi },
{ simp_fi },
{ have := lt_of_lt_of_incomp hc he,
have := ih hs₂ hc hlt₂,
simp_fi },
{ simp_fi,
have := is_searchable_ins lt hs₁ hlt₁ hc,
apply find_balance1_node lt this hs₂ (ih hs₁ hlt₁ hc) he.symm },
{ have := lt_of_incomp_of_lt he.swap hc,
have := ih hs₁ hlt₁ hc,
simp_fi },
{ simp_fi },
{ simp_fi,
have := is_searchable_ins lt hs₂ hc hlt₂,
apply find_balance2_node lt hs₁ this (ih hs₂ hc hlt₂) he.symm },
{ have := lt_of_lt_of_incomp hc he,
have := ih hs₂ hc hlt₂,
simp_fi }
end
lemma find_mk_insert_result (c : color) (t : rbnode α) (x : α) : find lt (mk_insert_result c t) x = find lt t x :=
begin
cases t; cases c; simp [mk_insert_result],
{ simp [find], cases cmp_using lt x val; simp [find] }
end
lemma find_insert_of_eqv [is_strict_weak_order α lt] {x y : α} {t : rbnode α} (he : x ≈[lt] y) : is_searchable lt t none none → find lt (insert lt t x) y = some x :=
begin
intro hs,
simp [insert, find_mk_insert_result],
apply find_ins_of_eqv lt he hs; simp [lift]
end
lemma weak_trichotomous (x y) : lt x y (¬ lt x y ∧ ¬ lt y x) lt y x :=
by by_cases lt x y; by_cases lt y x; simp [*]
section find_ins_of_not_eqv
section simp_aux_lemmas
lemma find_black_eq_find_red {l y r x} : find lt (black_node l y r) x = find lt (red_node l y r) x :=
begin simp [find], all_goals { cases cmp_using lt x y; simp [find] } end
lemma find_red_of_lt {l y r x} (h : lt x y) : find lt (red_node l y r) x = find lt l x :=
by simp [find, cmp_using, *]
lemma find_red_of_gt [is_strict_order α lt] {l y r x} (h : lt y x) : find lt (red_node l y r) x = find lt r x :=
begin have := not_lt_of_lt h, simp [find, cmp_using, *] end
lemma find_red_of_incomp {l y r x} (h : ¬ lt x y ∧ ¬ lt y x) : find lt (red_node l y r) x = some y :=
by simp [find, cmp_using, *]
end simp_aux_lemmas
local attribute [simp]
find_black_eq_find_red find_red_of_lt find_red_of_lt find_red_of_gt
find_red_of_incomp
variable [is_strict_weak_order α lt]
lemma find_balance1_lt {l r t v x y lo hi}
(h : lt x y)
(hl : is_searchable lt l lo (some v))
(hr : is_searchable lt r (some v) (some y))
(ht : is_searchable lt t (some y) hi)
: find lt (balance1 l v r y t) x = find lt (red_node l v r) x :=
begin
cases l; cases r; simp [balance1, *]; is_searchable_tactic,
{ have h₁ := weak_trichotomous lt x v, blast_disjs,
{ have := trans h₁ (lo_lt_hi hs₁), simp [*] },
{ have := lt_of_incomp_of_lt h₁ (lo_lt_hi hs₁),
simp [*] },
{ have h := weak_trichotomous lt x val, blast_disjs; simp [*] } },
{ have := weak_trichotomous lt x v, blast_disjs; simp [*] },
{ have := weak_trichotomous lt x v, blast_disjs; simp [*] },
{ have := weak_trichotomous lt x v, blast_disjs; simp [*] },
{ have hvv_1 := lo_lt_hi hs₁_1,
have h₁ := weak_trichotomous lt x v, blast_disjs,
{ have := trans h₁ hvv_1, simp [*] },
{ have := lt_of_incomp_of_lt h₁ (lo_lt_hi hs₁_1),
simp [*] },
{ have h₂ := weak_trichotomous lt x val_1, blast_disjs; simp [*] } }
end
meta def ins_ne_leaf_tac := `[apply ins_ne_leaf]
lemma find_balance1_node_lt {t s x y lo hi} (hlt : lt y x)
(ht : is_searchable lt t lo (some x))
(hs : is_searchable lt s (some x) hi)
(hne : t ≠ leaf . ins_ne_leaf_tac)
: find lt (balance1_node t x s) y = find lt t y :=
begin
cases t; simp [balance1_node],
{ contradiction },
all_goals { intros, is_searchable_tactic, apply find_balance1_lt, assumption' }
end
lemma find_balance1_gt {l r t v x y lo hi}
(h : lt y x)
(hl : is_searchable lt l lo (some v))
(hr : is_searchable lt r (some v) (some y))
(ht : is_searchable lt t (some y) hi)
: find lt (balance1 l v r y t) x = find lt t x :=
begin
cases l; cases r; simp [balance1, *]; is_searchable_tactic,
{ have := trans_of lt (lo_lt_hi hs₂) h, simp [*] },
{ have := trans_of lt a h, simp [*] },
twice { have := trans_of lt (trans (lo_lt_hi hs₁_1) (lo_lt_hi hs₂_1)) h, simp [*] },
{ have := trans_of lt (lo_lt_hi hs₂_1) h, simp [*] }
end
lemma find_balance1_node_gt {t s x y lo hi} (h : lt x y)
(ht : is_searchable lt t lo (some x))
(hs : is_searchable lt s (some x) hi)
(hne : t ≠ leaf . ins_ne_leaf_tac)
: find lt (balance1_node t x s) y = find lt s y :=
begin
cases t; simp [balance1_node],
all_goals { intros, is_searchable_tactic, apply find_balance1_gt, assumption' }
end
lemma find_balance1_eqv {l r t v x y lo hi}
(h : ¬ lt x y ∧ ¬ lt y x)
(hl : is_searchable lt l lo (some v))
(hr : is_searchable lt r (some v) (some y))
(ht : is_searchable lt t (some y) hi)
: find lt (balance1 l v r y t) x = some y :=
begin
cases l; cases r; simp [balance1, *]; is_searchable_tactic,
{ have : lt val x := lt_of_lt_of_incomp (lo_lt_hi hs₂) h.swap, simp [*] },
{ have : lt v x := lt_of_lt_of_incomp a h.swap, simp [*] },
twice { have : lt v x := lt_of_lt_of_incomp (trans (lo_lt_hi hs₁_1) (lo_lt_hi hs₂_1)) h.swap,
simp [*] },
{ have : lt val_1 x := lt_of_lt_of_incomp (lo_lt_hi hs₂_1) h.swap, simp [*] }
end
lemma find_balance1_node_eqv {t s x y lo hi}
(h : ¬ lt x y ∧ ¬ lt y x)
(ht : is_searchable lt t lo (some y))
(hs : is_searchable lt s (some y) hi)
(hne : t ≠ leaf . ins_ne_leaf_tac)
: find lt (balance1_node t y s) x = some y :=
begin
cases t; simp [balance1_node],
{ contradiction },
all_goals { intros, is_searchable_tactic, apply find_balance1_eqv, assumption' }
end
lemma find_balance2_lt {l v r t x y lo hi}
(h : lt x y)
(hl : is_searchable lt l (some y) (some v))
(hr : is_searchable lt r (some v) hi)
(ht : is_searchable lt t lo (some y))
: find lt (balance2 l v r y t) x = find lt t x :=
begin
cases l; cases r; simp [balance2, *]; is_searchable_tactic,
{ have := trans h a, simp [*] },
{ have := trans h (lo_lt_hi hs₁), simp [*] },
twice { have := trans h (lo_lt_hi hs₁), simp [*] },
{ have := trans h (trans (lo_lt_hi hs₁) (lo_lt_hi hs₂)), simp [*] }
end
lemma find_balance2_node_lt {s t x y lo hi}
(h : lt x y)
(ht : is_searchable lt t (some y) hi)
(hs : is_searchable lt s lo (some y))
(hne : t ≠ leaf . ins_ne_leaf_tac)
: find lt (balance2_node t y s) x = find lt s x :=
begin
cases t; simp [balance2_node],
all_goals { intros, is_searchable_tactic, apply find_balance2_lt, assumption' }
end
lemma find_balance2_gt {l v r t x y lo hi}
(h : lt y x)
(hl : is_searchable lt l (some y) (some v))
(hr : is_searchable lt r (some v) hi)
(ht : is_searchable lt t lo (some y))
: find lt (balance2 l v r y t) x = find lt (red_node l v r) x :=
begin
cases l; cases r; simp [balance2, *]; is_searchable_tactic,
{ have := weak_trichotomous lt x v, blast_disjs; simp [*] },
any_goals {
have h₁ := weak_trichotomous lt x val, blast_disjs,
{ have := trans h₁ (lo_lt_hi hs₂), simp [*] },
{ have := lt_of_incomp_of_lt h₁ (lo_lt_hi hs₂), simp [*] },
{ have := weak_trichotomous lt x v, blast_disjs; simp [*] } }
end
lemma find_balance2_node_gt {s t x y lo hi}
(h : lt y x)
(ht : is_searchable lt t (some y) hi)
(hs : is_searchable lt s lo (some y))
(hne : t ≠ leaf . ins_ne_leaf_tac)
: find lt (balance2_node t y s) x = find lt t x :=
begin
cases t; simp [balance2_node],
{ contradiction },
all_goals { intros, is_searchable_tactic, apply find_balance2_gt, assumption' }
end
lemma find_balance2_eqv {l v r t x y lo hi}
(h : ¬ lt x y ∧ ¬ lt y x)
(hl : is_searchable lt l (some y) (some v))
(hr : is_searchable lt r (some v) hi)
(ht : is_searchable lt t lo (some y))
: find lt (balance2 l v r y t) x = some y :=
begin
cases l; cases r; simp [balance2, *]; is_searchable_tactic,
{ have : lt x v := lt_of_incomp_of_lt h a, simp [*] },
any_goals { have : lt x val := lt_of_incomp_of_lt h (lo_lt_hi hs₁), simp [*] },
{ have : lt x v := lt_of_incomp_of_lt h (trans (lo_lt_hi hs₁) (lo_lt_hi hs₂)), simp [*] }
end
lemma find_balance2_node_eqv {t s x y lo hi}
(h : ¬ lt x y ∧ ¬ lt y x)
(ht : is_searchable lt t (some y) hi)
(hs : is_searchable lt s lo (some y))
(hne : t ≠ leaf . ins_ne_leaf_tac)
: find lt (balance2_node t y s) x = some y :=
begin
cases t; simp [balance2_node],
{ contradiction },
all_goals { intros, is_searchable_tactic, apply find_balance2_eqv, assumption' }
end
lemma find_ins_of_disj {x y : α} {t : rbnode α} (hn : lt x y lt y x)
: ∀ {lo hi}
(hs : is_searchable lt t lo hi)
(hlt₁ : lift lt lo (some x))
(hlt₂ : lift lt (some x) hi),
find lt (ins lt t x) y = find lt t y :=
begin
apply ins.induction lt t x; intros,
{ cases hn with hn hn,
all_goals { simp [find, ins, cmp_using, *] } },
all_goals { simp at hc, cases hs },
{ have := ih hs₁ hlt₁ hc, simp_fi },
{ cases hn with hn hn,
{ have := lt_of_incomp_of_lt hc.symm hn,
simp_fi },
{ have := lt_of_lt_of_incomp hn hc,
simp_fi } },
{ have := ih hs₂ hc hlt₂,
cases hn with hn hn,
{ have := trans hc hn, simp_fi },
{ simp_fi } },
{ have ih := ih hs₁ hlt₁ hc,
cases hn with hn hn,
{ generalize hc' : cmp_using lt y y_1 = cyy,
cases cyy; simp at hc',
{ have hsi := is_searchable_ins lt hs₁ hlt₁ (trans_of lt hn hc'),
have := find_balance1_node_lt lt hc' hsi hs₂,
simp_fi },
{ have hlt := lt_of_lt_of_incomp hn hc',
have hsi := is_searchable_ins lt hs₁ hlt₁ hlt,
have := find_balance1_node_eqv lt hc' hsi hs₂,
simp_fi },
{ have hsi := is_searchable_ins lt hs₁ hlt₁ hc,
have := find_balance1_node_gt lt hc' hsi hs₂,
simp [*], simp_fi } },
{ have hlt := trans hn hc,
have hsi := is_searchable_ins lt hs₁ hlt₁ hc,
have := find_balance1_node_lt lt hlt hsi hs₂,
simp_fi } },
{ have := ih hs₁ hlt₁ hc, simp_fi },
{ cases hn with hn hn,
{ have := lt_of_incomp_of_lt hc.swap hn, simp_fi },
{ have := lt_of_lt_of_incomp hn hc, simp_fi } },
{ have ih := ih hs₂ hc hlt₂,
cases hn with hn hn,
{ have hlt := trans hc hn, simp_fi,
have hsi := is_searchable_ins lt hs₂ hc hlt₂,
have := find_balance2_node_gt lt hlt hsi hs₁,
simp_fi },
{ simp_fi,
generalize hc' : cmp_using lt y y_1 = cyy,
cases cyy; simp at hc',
{ have hsi := is_searchable_ins lt hs₂ hc hlt₂,
have := find_balance2_node_lt lt hc' hsi hs₁,
simp_fi },
{ have hlt := lt_of_incomp_of_lt hc'.swap hn,
have hsi := is_searchable_ins lt hs₂ hlt hlt₂,
have := find_balance2_node_eqv lt hc' hsi hs₁,
simp_fi },
{ have hsi := is_searchable_ins lt hs₂ hc hlt₂,
have := find_balance2_node_gt lt hc' hsi hs₁,
simp_fi } } },
{ cases hn with hn hn,
{ have := trans hc hn,
have := ih hs₂ hc hlt₂,
simp_fi },
{ have ih := ih hs₂ hc hlt₂,
simp_fi } }
end
end find_ins_of_not_eqv
lemma find_insert_of_disj [is_strict_weak_order α lt] {x y : α} {t : rbnode α} (hd : lt x y lt y x) : is_searchable lt t none none → find lt (insert lt t x) y = find lt t y :=
begin
intro hs,
simp [insert, find_mk_insert_result],
apply find_ins_of_disj lt hd hs; simp [lift]
end
lemma find_insert_of_not_eqv [is_strict_weak_order α lt] {x y : α} {t : rbnode α} (hn : ¬ x ≈[lt] y) : is_searchable lt t none none → find lt (insert lt t x) y = find lt t y :=
begin
intro hs,
simp [insert, find_mk_insert_result],
have he : lt x y lt y x, {
simp [strict_weak_order.equiv, decidable.not_and_iff_or_not, decidable.not_not_iff] at hn,
assumption },
apply find_ins_of_disj lt he hs; simp [lift]
end
end membership_lemmas
section is_red_black
variables {α : Type u}
open nat color
inductive is_bad_red_black : rbnode α → nat → Prop
| bad_red {c₁ c₂ n l r v} (rb_l : is_red_black l c₁ n) (rb_r : is_red_black r c₂ n) : is_bad_red_black (red_node l v r) n
lemma balance1_rb {l r t : rbnode α} {y v : α} {c_l c_r c_t n} : is_red_black l c_l n → is_red_black r c_r n → is_red_black t c_t n → ∃ c, is_red_black (balance1 l y r v t) c (succ n) :=
by intros h₁ h₂ h₃; cases h₁; cases h₂; repeat { assumption <|> constructor }
lemma balance2_rb {l r t : rbnode α} {y v : α} {c_l c_r c_t n} : is_red_black l c_l n → is_red_black r c_r n → is_red_black t c_t n → ∃ c, is_red_black (balance2 l y r v t) c (succ n) :=
by intros h₁ h₂ h₃; cases h₁; cases h₂; repeat { assumption <|> constructor }
lemma balance1_node_rb {t s : rbnode α} {y : α} {c n} : is_bad_red_black t n → is_red_black s c n → ∃ c, is_red_black (balance1_node t y s) c (succ n) :=
by intros h _; cases h; simp [balance1_node]; apply balance1_rb; assumption'
lemma balance2_node_rb {t s : rbnode α} {y : α} {c n} : is_bad_red_black t n → is_red_black s c n → ∃ c, is_red_black (balance2_node t y s) c (succ n) :=
by intros h _; cases h; simp [balance2_node]; apply balance2_rb; assumption'
def ins_rb_result : rbnode α → color → nat → Prop
| t red n := is_bad_red_black t n
| t black n := ∃ c, is_red_black t c n
variables {lt : αα → Prop} [decidable_rel lt]
lemma of_get_color_eq_red {t : rbnode α} {c n} : get_color t = red → is_red_black t c n → c = red :=
begin intros h₁ h₂, cases h₂; simp [get_color] at h₁; contradiction end
lemma of_get_color_ne_red {t : rbnode α} {c n} : get_color t ≠ red → is_red_black t c n → c = black :=
begin intros h₁ h₂, cases h₂; simp [get_color] at h₁; contradiction end
variable (lt)
lemma ins_rb {t : rbnode α} (x) : ∀ {c n} (h : is_red_black t c n), ins_rb_result (ins lt t x) c n :=
begin
apply ins.induction lt t x; intros; cases h; simp [ins, *, ins_rb_result],
{ repeat { constructor } },
{ specialize ih rb_l, cases ih, constructor; assumption },
{ constructor, assumption' },
{ specialize ih rb_r, cases ih, constructor; assumption },
{ specialize ih rb_l,
have := of_get_color_eq_red hr rb_l, subst c₁,
simp [ins_rb_result] at ih,
apply balance1_node_rb; assumption },
{ specialize ih rb_l,
have := of_get_color_ne_red hnr rb_l, subst c₁,
simp [ins_rb_result] at ih, cases ih,
constructor, constructor; assumption },
{ constructor, constructor; assumption },
{ specialize ih rb_r,
have := of_get_color_eq_red hr rb_r, subst c₂,
simp [ins_rb_result] at ih,
apply balance2_node_rb; assumption },
{ specialize ih rb_r,
have := of_get_color_ne_red hnr rb_r, subst c₂,
simp [ins_rb_result] at ih, cases ih,
constructor, constructor; assumption }
end
def insert_rb_result : rbnode α → color → nat → Prop
| t red n := is_red_black t black (succ n)
| t black n := ∃ c, is_red_black t c n
lemma insert_rb {t : rbnode α} (x) {c n} (h : is_red_black t c n) : insert_rb_result (insert lt t x) c n :=
begin
simp [insert],
have hi := ins_rb lt x h,
generalize he : ins lt t x = r,
simp [he] at hi, clear he,
cases h; simp [get_color, ins_rb_result, insert_rb_result, mk_insert_result] at *,
assumption',
{ cases hi, simp [mk_insert_result], constructor; assumption }
end
lemma insert_is_red_black {t : rbnode α} {c n} (x) : is_red_black t c n → ∃ c n, is_red_black (insert lt t x) c n :=
begin
intro h,
have := insert_rb lt x h,
cases c; simp [insert_rb_result] at this,
{ constructor, constructor, assumption },
{ cases this, constructor, constructor, assumption }
end
end is_red_black
end rbnode