Theory Treap
section ‹Treaps›
theory Treap
imports
"HOL-Library.Tree"
begin
definition treap :: "('k::linorder * 'p::linorder) tree ⇒ bool" where
"treap t = (bst (map_tree fst t) ∧ heap (map_tree snd t))"
abbreviation "keys t ≡ set_tree (map_tree fst t)"
abbreviation "prios t ≡ set_tree (map_tree snd t)"
function treap_of :: "('k::linorder * 'p::linorder) set ⇒ ('k * 'p) tree" where
"treap_of KP = (if infinite KP ∨ KP = {} then Leaf else
let m = arg_min_on snd KP;
L = {p ∈ KP. fst p < fst m};
R = {p ∈ KP. fst p > fst m}
in Node (treap_of L) m (treap_of R))"
by pat_completeness auto
termination
proof (relation "measure card")
show "wf (measure card)" by simp
next
fix KP :: "('a × 'b) set" and m L
assume KP: "¬ (infinite KP ∨ KP = {})"
and m: "m = arg_min_on snd KP"
and L: "L = {p ∈ KP. fst p < fst m}"
have "m ∈ KP" using KP arg_min_if_finite(1) m by blast
thus "(L, KP) ∈ measure card" using KP L by(auto intro!: psubset_card_mono)
next
fix KP :: "('a × 'b) set" and m R
assume KP: "¬ (infinite KP ∨ KP = {})"
and m: "m = arg_min_on snd KP"
and R: "R = {p ∈ KP. fst m < fst p}"
have "m ∈ KP" using KP arg_min_if_finite(1) m by blast
thus "(R, KP) ∈ measure card" using KP R by(auto intro!: psubset_card_mono)
qed
declare treap_of.simps [simp del]
lemma treap_of_unique:
"⟦ treap t; inj_on snd (set_tree t) ⟧
⟹ treap_of (set_tree t) = t"
proof(induction "set_tree t" arbitrary: t rule: treap_of.induct)
case (1 t)
show ?case
proof (cases "infinite (set_tree t) ∨ set_tree t = {}")
case True
thus ?thesis by(simp add: treap_of.simps)
next
case False
let ?m = "arg_min_on snd (set_tree t)"
let ?L = "{p ∈ set_tree t. fst p < fst ?m}"
let ?R = "{p ∈ set_tree t. fst p > fst ?m}"
obtain l a r where t: "t = Node l a r"
using False by (cases t) auto
have "∀kp ∈ set_tree t. snd a ≤ snd kp"
using "1.prems"(1)
by(auto simp add: t treap_def ball_Un)
(metis image_eqI snd_conv tree.set_map)+
hence "a = ?m"
by (metis "1.prems"(2) False arg_min_if_finite(1) arg_min_if_finite(2) inj_on_def
le_neq_trans t tree.set_intros(2))
have "treap l" "treap r" using "1.prems"(1) by(auto simp: treap_def t)
have l: "set_tree l = {p ∈ set_tree t. fst p < fst a}"
using "1.prems"(1) by(auto simp add: treap_def t ball_Un tree.set_map)
have r: "set_tree r = {p ∈ set_tree t. fst p > fst a}"
using "1.prems"(1) by(auto simp add: treap_def t ball_Un tree.set_map)
have "l = treap_of ?L"
using "1.hyps"(1)[OF False ‹a = ?m› l r ‹treap l›]
l ‹a = ?m› "1.prems"(2)
by (fastforce simp add: inj_on_def)
have "r = treap_of ?R"
using "1.hyps"(2)[OF False ‹a = ?m› l r ‹treap r›]
r ‹a = ?m› "1.prems"(2)
by (fastforce simp add: inj_on_def)
have "t = Node (treap_of ?L) ?m (treap_of ?R)"
using ‹a = ?m› ‹l = treap_of ?L› ‹r = treap_of ?R› by(subst t) simp
thus ?thesis using False
by (subst treap_of.simps) simp
qed
qed
lemma treap_unique:
"⟦ treap t1; treap t2; set_tree t1 = set_tree t2; inj_on snd (set_tree t1) ⟧
⟹ t1 = t2"
for t1 t2 :: "('k::linorder * 'p::linorder) tree"
by (metis treap_of_unique)
fun ins :: "'k::linorder ⇒ 'p::linorder ⇒ ('k × 'p) tree ⇒ ('k × 'p) tree" where
"ins k p Leaf = ⟨Leaf, (k,p), Leaf⟩" |
"ins k p ⟨l, (k1,p1), r⟩ =
(if k < k1 then
(case ins k p l of
⟨l2, (k2,p2), r2⟩ ⇒
if p1 ≤ p2 then ⟨⟨l2, (k2,p2), r2⟩, (k1,p1), r⟩
else ⟨l2, (k2,p2), ⟨r2, (k1,p1), r⟩⟩)
else
if k > k1 then
(case ins k p r of
⟨l2, (k2,p2), r2⟩ ⇒
if p1 ≤ p2 then ⟨l, (k1,p1), ⟨l2, (k2,p2), r2⟩⟩
else ⟨⟨l, (k1,p1), l2⟩, (k2,p2), r2⟩)
else ⟨l, (k1,p1), r⟩)"
lemma ins_neq_Leaf: "ins k p t ≠ ⟨⟩"
by (induction t rule: ins.induct) (auto split: tree.split)
lemma keys_ins: "keys (ins k p t) = Set.insert k (keys t)"
proof (induction t rule: ins.induct)
case 2
then show ?case
by (simp add: ins_neq_Leaf split: tree.split prod.split) (safe; fastforce)
qed (simp)
lemma prios_ins: "prios (ins k p t) ⊆ {p} ∪ prios t"
apply(induction t rule: ins.induct)
apply simp
apply (simp add: ins_neq_Leaf split: tree.split prod.split)
by (safe; fastforce)
lemma prios_ins': "k ∉ keys t ⟹ prios (ins k p t) = {p} ∪ prios t"
apply(induction t rule: ins.induct)
apply simp
apply (simp add: ins_neq_Leaf split: tree.split prod.split)
by (safe; fastforce)
lemma set_tree_ins: "set_tree (ins k p t) ⊆ {(k,p)} ∪ set_tree t"
by (induction t rule: ins.induct) (auto simp add: ins_neq_Leaf split: tree.split prod.split)
lemma set_tree_ins': "k ∉ keys t ⟹ {(k,p)} ∪ set_tree t ⊆ set_tree (ins k p t)"
by (induction t rule: ins.induct) (auto simp add: ins_neq_Leaf split: tree.split prod.split)
lemma set_tree_ins_eq: "k ∉ keys t ⟹ set_tree (ins k p t) = {(k,p)} ∪ set_tree t"
using set_tree_ins set_tree_ins' by blast
lemma prios_ins_special:
"⟦ ins k p t = Node l (k',p') r; p' = p; p ∈ prios r ∪ prios l ⟧
⟹ p ∈ prios t"
by (induction k p t arbitrary: l k' p' r rule: ins.induct)
(fastforce simp add: ins_neq_Leaf split: tree.splits prod.splits if_splits)+
lemma treap_NodeI:
"⟦ treap l; treap r;
∀k' ∈ keys l. k' < k; ∀k' ∈ keys r. k < k';
∀p' ∈ prios l. p ≤ p'; ∀p' ∈ prios r. p ≤ p' ⟧
⟹ treap (Node l (k,p) r)"
by (auto simp: treap_def)
lemma treap_rotate1:
assumes "treap l2" "treap r2" "treap r" "¬ p1 ≤ p2" "k < k1" and
ins: "ins k p l = Node l2 (k2,p2) r2" and treap_ins: "treap (ins k p l)"
and treap: "treap ⟨l, (k1, p1), r⟩"
shows "treap (Node l2 (k2,p2) (Node r2 (k1,p1) r))"
proof(rule treap_NodeI[OF ‹treap l2› treap_NodeI[OF ‹treap r2› ‹treap r›]])
from keys_ins[of k p l] have 1: "keys r2 ⊆ {k} ∪ keys l" by(auto simp: ins)
from treap have 2: "∀k'∈keys l. k' < k1" by (simp add: treap_def)
show "∀k'∈keys r2. k' < k1" using 1 2 ‹k < k1› by blast
next
from treap have 2: "∀p'∈prios l. p1 ≤ p'" by (simp add: treap_def)
show "∀p'∈prios r2. p1 ≤ p'"
proof
fix p' assume "p' ∈ prios r2"
hence "p' = p ∨ p' ∈ prios l" using prios_ins[of k p l] ins by auto
thus "p1 ≤ p'"
proof
assume [simp]: "p' = p"
have "p2 = p ∨ p2 ∈ prios l" using prios_ins[of k p l] ins by simp
thus "p1 ≤ p'"
proof
assume "p2 = p"
thus "p1 ≤ p'"
using prios_ins_special[OF ins] ‹p' ∈ prios r2› 2 by auto
next
assume "p2 ∈ prios l"
thus "p1 ≤ p'" using 2 ‹¬ p1 ≤ p2› by blast
qed
next
assume "p' ∈ prios l"
thus "p1 ≤ p'" using 2 by blast
qed
qed
next
have "k2 = k ∨ k2 ∈ keys l" using keys_ins[of k p l] ins by (auto)
hence 1: "k2 < k1"
proof
assume "k2 = k" thus "k2 < k1" using ‹k < k1› by simp
next
assume "k2 ∈ keys l"
thus "k2 < k1" using treap by (auto simp: treap_def)
qed
have 2: "∀k'∈keys r2. k2 < k'"
using treap_ins by(simp add: ins treap_def)
have 3: "∀k'∈keys r. k2 < k'"
using 1 treap by(auto simp: treap_def)
show "∀k'∈keys ⟨r2, (k1, p1), r⟩. k2 < k'" using 1 2 3 by auto
next
show "∀p'∈prios ⟨r2, (k1, p1), r⟩. p2 ≤ p'"
using ins treap_ins treap ‹¬ p1 ≤ p2› by (auto simp: treap_def ball_Un)
qed (use ins treap_ins treap in ‹auto simp: treap_def ball_Un›)
lemma treap_rotate2:
assumes "treap l" "treap l2" "treap r2" "¬ p1 ≤ p2" "k1 < k" and
ins: "ins k p r = Node l2 (k2,p2) r2" and treap_ins: "treap (ins k p r)"
and treap: "treap ⟨l, (k1, p1), r⟩"
shows "treap (Node (Node l (k1,p1) l2) (k2,p2) r2)"
proof(rule treap_NodeI[OF treap_NodeI[OF ‹treap l› ‹treap l2›] ‹treap r2›])
from keys_ins[of k p r] have 1: "keys l2 ⊆ {k} ∪ keys r" by(auto simp: ins)
from treap have 2: "∀k'∈keys r. k1 < k'" by (simp add: treap_def)
show "∀k'∈keys l2. k1 < k'" using 1 2 ‹k1 < k› by blast
next
from treap have 2: "∀p'∈prios r. p1 ≤ p'" by (simp add: treap_def)
show "∀p'∈prios l2. p1 ≤ p'"
proof
fix p' assume "p' ∈ prios l2"
hence "p' = p ∨ p' ∈ prios r" using prios_ins[of k p r] ins by auto
thus "p1 ≤ p'"
proof
assume [simp]: "p' = p"
have "p2 = p ∨ p2 ∈ prios r" using prios_ins[of k p r] ins by simp
thus "p1 ≤ p'"
proof
assume "p2 = p"
thus "p1 ≤ p'"
using prios_ins_special[OF ins] ‹p' ∈ prios l2› 2 by auto
next
assume "p2 ∈ prios r"
thus "p1 ≤ p'" using 2 ‹¬ p1 ≤ p2› by blast
qed
next
assume "p' ∈ prios r"
thus "p1 ≤ p'" using 2 by blast
qed
qed
next
have "k2 = k ∨ k2 ∈ keys r" using keys_ins[of k p r] ins by (auto)
hence 1: "k1 < k2"
proof
assume "k2 = k" thus "k1 < k2" using ‹k1 < k› by simp
next
assume "k2 ∈ keys r"
thus "k1 < k2" using treap by (auto simp: treap_def)
qed
have 2: "∀k'∈keys l. k' < k2" using 1 treap by(auto simp: treap_def)
have 3: "∀k'∈keys l2. k' < k2"
using treap_ins by(auto simp: ins treap_def)
show "∀k'∈keys ⟨l, (k1, p1), l2⟩. k' < k2" using 1 2 3 by auto
next
show "∀p'∈prios ⟨l, (k1, p1), l2⟩. p2 ≤ p'"
using ins treap_ins treap ‹¬ p1 ≤ p2› by (auto simp: treap_def ball_Un)
qed (use ins treap_ins treap in ‹auto simp: treap_def ball_Un›)
lemma treap_ins: "treap t ⟹ treap (ins k p t)"
proof(induction t rule: ins.induct)
case 1 thus ?case by (simp add: treap_def)
next
case (2 k p l k1 p1 r)
have "treap l" "treap r"
using "2.prems" by(auto simp: treap_def tree.set_map)
show ?case
proof cases
assume "k < k1"
obtain l2 k2 p2 r2 where ins: "ins k p l = Node l2 (k2,p2) r2"
by (metis ins_neq_Leaf neq_Leaf_iff prod.collapse)
note treap_ins = "2.IH"(1)[OF ‹k < k1› ‹treap l›]
hence "treap l2" "treap r2" using ins by (auto simp add: treap_def)
show ?thesis
proof cases
assume "p1 ≤ p2"
have "treap (Node (Node l2 (k2,p2) r2) (k1,p1) r)"
apply(rule treap_NodeI[OF treap_ins[unfolded ins] ‹treap r›])
using ins treap_ins ‹k < k1› "2.prems" keys_ins[of k p l]
by (auto simp add: treap_def ball_Un order_trans[OF ‹p1 ≤ p2›])
thus ?thesis using ‹k < k1› ins ‹p1 ≤ p2› by simp
next
assume "¬ p1 ≤ p2"
have "treap (Node l2 (k2,p2) (Node r2 (k1,p1) r))"
by(rule treap_rotate1[OF ‹treap l2› ‹treap r2› ‹treap r› ‹¬ p1 ≤ p2›
‹k < k1› ins treap_ins "2.prems"])
thus ?thesis using ‹k < k1› ins ‹¬ p1 ≤ p2› by simp
qed
next
assume "¬ k < k1"
show ?thesis
proof cases
assume "k > k1"
obtain l2 k2 p2 r2 where ins: "ins k p r = Node l2 (k2,p2) r2"
by (metis ins_neq_Leaf neq_Leaf_iff prod.collapse)
note treap_ins = "2.IH"(2)[OF ‹¬ k < k1› ‹k > k1› ‹treap r›]
hence "treap l2" "treap r2" using ins by (auto simp add: treap_def)
have fst: "∀k' ∈ set_tree (map_tree fst (ins k p r)).
k' = k ∨ k' ∈ set_tree (map_tree fst r)"
by(simp add: keys_ins)
show ?thesis
proof cases
assume "p1 ≤ p2"
have "treap (Node l (k1,p1) (ins k p r))"
apply(rule treap_NodeI[OF ‹treap l› treap_ins])
using ins treap_ins ‹k > k1› "2.prems" keys_ins[of k p r]
by (auto simp: treap_def ball_Un order_trans[OF ‹p1 ≤ p2›])
thus ?thesis using ‹¬ k < k1› ‹k > k1› ins ‹p1 ≤ p2› by simp
next
assume "¬ p1 ≤ p2"
have "treap (Node (Node l (k1,p1) l2) (k2,p2) r2)"
by(rule treap_rotate2[OF ‹treap l› ‹treap l2› ‹treap r2› ‹¬ p1 ≤ p2›
‹k1 < k› ins treap_ins "2.prems"])
thus ?thesis using ‹¬ k < k1› ‹k > k1› ins ‹¬ p1 ≤ p2› by simp
qed
next
assume "¬ k > k1"
hence "k = k1" using ‹¬ k < k1› by auto
thus ?thesis using "2.prems" by(simp)
qed
qed
qed
lemma treap_of_set_tree_unique:
"⟦ finite A; inj_on fst A; inj_on snd A ⟧
⟹ set_tree (treap_of A) = A"
proof(induction "A" rule: treap_of.induct)
case (1 A)
note IH = 1
show ?case
proof (cases "infinite A ∨ A = {}")
assume "infinite A ∨ A = {}"
with IH show ?thesis by (simp add: treap_of.simps)
next
assume not_inf_or_empty: "¬ (infinite A ∨ A = {})"
let ?m = "arg_min_on snd A"
let ?L = "{p ∈ A. fst p < fst ?m}"
let ?R = "{p ∈ A. fst p > fst ?m}"
obtain l a r where t: "treap_of A = Node l a r"
using not_inf_or_empty
by (cases "treap_of A") (auto simp: Let_def elim!: treap_of.elims split: if_splits)
have [simp]: "inj_on fst {p ∈ A. fst p < fst (arg_min_on snd A)}"
"inj_on snd {p ∈ A. fst p < fst (arg_min_on snd A)}"
"inj_on fst {p ∈ A. fst (arg_min_on snd A) < fst p}"
"inj_on snd {p ∈ A. fst (arg_min_on snd A) < fst p}"
using IH by (auto intro: inj_on_subset)
have lr: "l = treap_of ?L" "r = treap_of ?R"
using t by (auto simp: Let_def elim: treap_of.elims split: if_splits)
then have l: "set_tree l = ?L"
using not_inf_or_empty IH by auto
have "r = treap_of ?R"
using t by (auto simp: Let_def elim: treap_of.elims split: if_splits)
then have r: "set_tree r = ?R"
using not_inf_or_empty IH(2) by (auto)
have a: "a = ?m"
using t by (elim treap_of.elims) (simp add: Let_def split: if_splits)
have "a ≠ fst (arg_min_on snd A)" if "(a,b) ∈ A" "(a, b) ≠ arg_min_on snd A" for a b
using IH(4,5) that not_inf_or_empty arg_min_if_finite(1) inj_on_eq_iff by fastforce
then have "a < fst (arg_min_on snd A)"
if "(a,b) ∈ A" "(a, b) ≠ arg_min_on snd A" "fst (arg_min_on snd A) ≥ a" for a b
using le_neq_trans that by auto
moreover have "arg_min_on snd A ∈ A"
using not_inf_or_empty arg_min_if_finite by auto
ultimately have A: "A = {?m} ∪ ?L ∪ ?R"
by auto
show ?thesis using l r a A t by force
qed
qed
lemma treap_of_subset: "set_tree (treap_of A) ⊆ A"
proof(induction "A" rule: treap_of.induct)
case (1 A)
note IH = 1
show ?case
proof (cases "infinite A ∨ A = {}")
assume "infinite A ∨ A = {}"
with IH show ?thesis by (simp add: treap_of.simps)
next
assume not_inf_or_empty: "¬ (infinite A ∨ A = {})"
let ?m = "arg_min_on snd A"
let ?L = "{p ∈ A. fst p < fst ?m}"
let ?R = "{p ∈ A. fst p > fst ?m}"
obtain l a r where t: "treap_of A = Node l a r"
using not_inf_or_empty by (cases "treap_of A")
(auto simp add: Let_def elim!: treap_of.elims split: if_splits)
have "l = treap_of ?L" "r = treap_of ?R"
using t by (auto simp: Let_def elim: treap_of.elims split: if_splits)
have "set_tree l ⊆ ?L" "set_tree r ⊆ ?R"
proof -
have "set_tree (treap_of {p ∈ A. fst p < fst (arg_min_on snd A)})
⊆ {p ∈ A. fst p < fst (arg_min_on snd A)}"
by (rule IH) (use not_inf_or_empty in auto)
then show "set_tree l ⊆ ?L"
using ‹l = treap_of ?L› by auto
next
have "set_tree (treap_of {p ∈ A. fst (arg_min_on snd A) < fst p})
⊆ {p ∈ A. fst (arg_min_on snd A) < fst p}"
by (rule IH) (use not_inf_or_empty in auto)
then show "set_tree r ⊆ ?R"
using ‹r = treap_of ?R› by auto
qed
moreover have "a = ?m"
using t by (auto elim!: treap_of.elims simp add: Let_def split: if_splits)
moreover have "{?m} ∪ ?L ∪ ?R ⊆ A"
using not_inf_or_empty arg_min_if_finite by auto
ultimately show ?thesis by (auto simp add: t)
qed
qed
lemma treap_treap_of:
"treap (treap_of A)"
proof(induction "A" rule: treap_of.induct)
case (1 A)
show ?case
proof (cases "infinite A ∨ A = {}")
case True
with 1 show ?thesis by (simp add: treap_of.simps treap_def)
next
case False
let ?m = "arg_min_on snd A"
let ?L = "{p ∈ A. fst p < fst ?m}"
let ?R = "{p ∈ A. fst p > fst ?m}"
obtain l a r where t: "treap_of A = Node l a r"
using False by (cases "treap_of A") (auto simp: Let_def elim!: treap_of.elims split: if_splits)
have l: "l = treap_of ?L"
using t by (auto simp: Let_def elim: treap_of.elims split: if_splits)
then have treap_l: "treap l"
using False by (auto intro: 1)
from l have keys_l: "keys l ⊆ fst ` ?L"
by (auto simp add: tree.set_map intro!: image_mono treap_of_subset)
have r: "r = treap_of ?R"
using t by (auto simp: Let_def elim: treap_of.elims split: if_splits)
then have treap_r: "treap r"
using False by (auto intro: 1)
from r have keys_r: "keys r ⊆ fst ` ?R"
by (auto simp add: tree.set_map intro!: image_mono treap_of_subset)
have prios: "prios l ⊆ snd ` A" "prios r ⊆ snd ` A"
using l r treap_of_subset image_mono by (auto simp add: tree.set_map)
have a: "a = ?m"
using t by(auto simp: Let_def elim: treap_of.elims split: if_splits)
have prios_l: "⋀x. x ∈ prios l ⟹ snd a ≤ x"
by (drule rev_subsetD[OF _ prios(1)]) (use arg_min_least a False in fast)
have prios_r: "⋀x. x ∈ prios r ⟹ snd a ≤ x"
by (drule rev_subsetD[OF _ prios(2)]) (use arg_min_least a False in fast)
show ?thesis
using prios_r prios_l treap_l treap_r keys_l keys_r a
by (auto simp add: t treap_def dest: rev_subsetD[OF _ keys_l] rev_subsetD[OF _ keys_r])
qed
qed
lemma treap_Leaf: "treap ⟨⟩"
by (simp add: treap_def)
lemma foldl_ins_treap: "treap t ⟹ treap (foldl (λt' (x, p). ins x p t') t xs)"
using treap_ins by (induction xs arbitrary: t) auto
lemma foldl_ins_set_tree:
assumes "inj_on fst (set ys)" "inj_on snd (set ys)" "distinct ys" "fst ` (set ys) ∩ keys t = {}"
shows "set_tree (foldl (λt' (x, p). ins x p t') t ys) = set ys ∪ set_tree t"
using assms
by (induction ys arbitrary: t) (auto simp add: case_prod_beta' set_tree_ins_eq keys_ins)
lemma foldl_ins_treap_of:
assumes "distinct ys" "inj_on fst (set ys)" "inj_on snd (set ys)"
shows "(foldl (λt' (x, p). ins x p t') Leaf ys) = treap_of (set ys)"
using assms by (intro treap_unique) (auto simp: treap_Leaf foldl_ins_treap foldl_ins_set_tree
treap_treap_of treap_of_set_tree_unique)
end