| 72688 |      1 | (* Author: Tobias Nipkow *)
 | 
|  |      2 | 
 | 
|  |      3 | section \<open>Heaps\<close>
 | 
|  |      4 | 
 | 
|  |      5 | theory Heaps
 | 
|  |      6 | imports
 | 
|  |      7 |   "HOL-Library.Tree_Multiset"
 | 
|  |      8 |   Priority_Queue_Specs
 | 
|  |      9 | begin
 | 
|  |     10 | 
 | 
|  |     11 | text \<open>Heap = priority queue on trees:\<close>
 | 
|  |     12 |     
 | 
|  |     13 | locale Heap =
 | 
|  |     14 | fixes insert :: "('a::linorder) \<Rightarrow> 'a tree \<Rightarrow> 'a tree"
 | 
|  |     15 | and  del_min :: "'a tree \<Rightarrow> 'a tree"
 | 
|  |     16 | assumes mset_insert: "heap q \<Longrightarrow> mset_tree (insert x q) = {#x#} + mset_tree q"
 | 
|  |     17 | and    mset_del_min: "\<lbrakk> heap q;  q \<noteq> Leaf \<rbrakk> \<Longrightarrow> mset_tree (del_min q) = mset_tree q - {#value q#}"
 | 
|  |     18 | and     heap_insert: "heap q \<Longrightarrow> heap(insert x q)"
 | 
|  |     19 | and    heap_del_min: "heap q \<Longrightarrow> heap(del_min q)"
 | 
|  |     20 | begin
 | 
|  |     21 | 
 | 
|  |     22 | definition empty :: "'a tree" where
 | 
|  |     23 | "empty = Leaf"
 | 
|  |     24 | 
 | 
|  |     25 | fun is_empty :: "'a tree \<Rightarrow> bool" where
 | 
|  |     26 | "is_empty t = (t = Leaf)"
 | 
|  |     27 | 
 | 
|  |     28 | sublocale Priority_Queue where empty = empty and is_empty = is_empty and insert = insert
 | 
|  |     29 | and get_min = "value" and del_min = del_min and invar = heap and mset = mset_tree
 | 
|  |     30 | proof (standard, goal_cases)
 | 
|  |     31 |   case 1 thus ?case by (simp add: empty_def)
 | 
|  |     32 | next
 | 
|  |     33 |   case 2 thus ?case by(auto)
 | 
|  |     34 | next
 | 
|  |     35 |   case 3 thus ?case by(simp add: mset_insert)
 | 
|  |     36 | next
 | 
|  |     37 |   case 4 thus ?case by(simp add: mset_del_min)
 | 
|  |     38 | next
 | 
|  |     39 |   case 5 thus ?case by(auto simp: neq_Leaf_iff Min_insert2 simp del: Un_iff)
 | 
|  |     40 | next
 | 
|  |     41 |   case 6 thus ?case by(simp add: empty_def)
 | 
|  |     42 | next
 | 
|  |     43 |   case 7 thus ?case by(simp add: heap_insert)
 | 
|  |     44 | next
 | 
|  |     45 |   case 8 thus ?case by(simp add: heap_del_min)
 | 
|  |     46 | qed
 | 
|  |     47 | 
 | 
|  |     48 | end
 | 
|  |     49 | 
 | 
|  |     50 | 
 | 
|  |     51 | text \<open>Once you have \<open>merge\<close>, \<open>insert\<close> and \<open>del_min\<close> are easy:\<close>
 | 
|  |     52 | 
 | 
|  |     53 | locale Heap_Merge =
 | 
|  |     54 | fixes merge :: "'a::linorder tree \<Rightarrow> 'a tree \<Rightarrow> 'a tree"
 | 
|  |     55 | assumes mset_merge: "\<lbrakk> heap q1; heap q2 \<rbrakk> \<Longrightarrow> mset_tree (merge q1 q2) = mset_tree q1 + mset_tree q2"
 | 
|  |     56 | and invar_merge: "\<lbrakk> heap q1; heap q2 \<rbrakk> \<Longrightarrow> heap (merge q1 q2)"
 | 
|  |     57 | begin
 | 
|  |     58 | 
 | 
|  |     59 | fun insert :: "'a \<Rightarrow> 'a tree \<Rightarrow> 'a tree" where
 | 
|  |     60 | "insert x t = merge (Node Leaf x Leaf) t"
 | 
|  |     61 | 
 | 
|  |     62 | fun del_min :: "'a tree \<Rightarrow> 'a tree" where
 | 
|  |     63 | "del_min Leaf = Leaf" |
 | 
|  |     64 | "del_min (Node l x r) = merge l r"
 | 
|  |     65 | 
 | 
|  |     66 | interpretation Heap insert del_min
 | 
|  |     67 | proof(standard, goal_cases)
 | 
|  |     68 |   case 1 thus ?case by(simp add:mset_merge)
 | 
|  |     69 | next
 | 
|  |     70 |   case (2 q) thus ?case by(cases q)(auto simp: mset_merge)
 | 
|  |     71 | next
 | 
|  |     72 |   case 3 thus ?case by (simp add: invar_merge)
 | 
|  |     73 | next
 | 
|  |     74 |   case (4 q) thus ?case by (cases q)(auto simp: invar_merge)
 | 
|  |     75 | qed
 | 
|  |     76 | 
 | 
|  |     77 | sublocale PQM: Priority_Queue_Merge where empty = empty and is_empty = is_empty and insert = insert
 | 
|  |     78 | and get_min = "value" and del_min = del_min and invar = heap and mset = mset_tree and merge = merge
 | 
|  |     79 | proof(standard, goal_cases)
 | 
|  |     80 |   case 1 thus ?case by (simp add: mset_merge)
 | 
|  |     81 | next
 | 
|  |     82 |   case 2 thus ?case by (simp add: invar_merge)
 | 
|  |     83 | qed
 | 
|  |     84 | 
 | 
|  |     85 | end
 | 
|  |     86 | 
 | 
|  |     87 | end
 |