Theory Skew_Heap.Skew_Heap

section "Skew Heap"

theory Skew_Heap
imports
  "HOL-Library.Tree_Multiset"
  "HOL-Library.Pattern_Aliases"
  "HOL-Data_Structures.Heaps"
begin

unbundle pattern_aliases

text‹Skew heaps~cite"SleatorT-SIAM86" are possibly the simplest functional
priority queues that have logarithmic (albeit amortized) complexity.

The implementation below could be generalized to separate the elements from
their priorities.›

subsection "Merge"

function merge :: "('a::linorder) tree  'a tree  'a tree" where
"merge Leaf t = t" |
"merge t Leaf = t" |
"merge (Node l1 a1 r1 =: t1) (Node l2 a2 r2 =: t2) =
   (if a1  a2 then Node (merge t2 r1) a1 l1
    else Node (merge t1 r2) a2 l2)" 
by pat_completeness auto
termination
by (relation "measure (λ(x, y). size x + size y)") auto

lemma merge_code: "merge t1 t2 =
  (case t1 of
   Leaf  t2 |
   Node l1 a1 r1  (case t2 of
     Leaf  t1 |
     Node l2 a2 r2  
       (if a1  a2
        then Node (merge t2 r1) a1 l1
        else Node (merge t1 r2) a2 l2)))"
by(auto split: tree.split)

text‹An alternative version that always walks to the Leaf of both heaps:›
function merge2 :: "('a::linorder) tree  'a tree  'a tree" where
"merge2 Leaf Leaf = Leaf" |
"merge2 Leaf (Node l2 a2 r2) = Node (merge2 r2 Leaf) a2 l2" |
"merge2 (Node l1 a1 r1) Leaf = Node (merge2 r1 Leaf) a1 l1" |
"merge2 (Node l1 a1 r1) (Node l2 a2 r2) =
   (if a1  a2
    then Node (merge2 (Node l2 a2 r2) r1) a1 l1
    else Node (merge2 (Node l1 a1 r1) r2) a2 l2)"
by pat_completeness auto
termination
by (relation "measure (λ(x, y). size x + size y)") auto

lemma size_merge: "size(merge t1 t2) = size t1 + size t2"
by(induction t1 t2 rule: merge.induct) auto

lemma size_merge2: "size(merge2 t1 t2) = size t1 + size t2"
by(induction t1 t2 rule: merge2.induct) auto

lemma mset_merge: "mset_tree (merge t1 t2) = mset_tree t1 + mset_tree t2"
by (induction t1 t2 rule: merge.induct) (auto simp add: ac_simps)

lemma set_merge: "set_tree (merge t1 t2) = set_tree t1  set_tree t2"
by (metis mset_merge set_mset_tree set_mset_union)

lemma heap_merge:
  " heap t1;  heap t2   heap (merge t1 t2)"
by (induction t1 t2 rule: merge.induct)(auto simp: ball_Un set_merge)

interpretation skew_heap: Heap_Merge
where merge = merge
proof(standard, goal_cases)
  case 1 thus ?case by(simp add: mset_merge)
next
  case 2 thus ?case by(simp add: heap_merge)
qed


end