Theory Treap

theory Treap
imports Tree
(*
  File:      Treap.thy
  Authors:   Tobias Nipkow, Max Haslbeck
*)
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