78231
|
1 |
(* Author: Tobias Nipkow *)
|
|
2 |
|
|
3 |
theory Leftist_Heap_List
|
|
4 |
imports
|
|
5 |
Leftist_Heap
|
|
6 |
Complex_Main
|
|
7 |
begin
|
|
8 |
|
|
9 |
subsection "Converting a list into a leftist heap"
|
|
10 |
|
|
11 |
fun merge_adj :: "('a::ord) lheap list \<Rightarrow> 'a lheap list" where
|
|
12 |
"merge_adj [] = []" |
|
|
13 |
"merge_adj [t] = [t]" |
|
|
14 |
"merge_adj (t1 # t2 # ts) = merge t1 t2 # merge_adj ts"
|
|
15 |
|
|
16 |
text \<open>For the termination proof of \<open>merge_all\<close> below.\<close>
|
82010
|
17 |
lemma length_merge_adjacent[termination_simp]: "length (merge_adj ts) = (length ts + 1) div 2"
|
78231
|
18 |
by (induction ts rule: merge_adj.induct) auto
|
|
19 |
|
|
20 |
fun merge_all :: "('a::ord) lheap list \<Rightarrow> 'a lheap" where
|
|
21 |
"merge_all [] = Leaf" |
|
|
22 |
"merge_all [t] = t" |
|
|
23 |
"merge_all ts = merge_all (merge_adj ts)"
|
|
24 |
|
|
25 |
|
|
26 |
subsubsection \<open>Functional correctness\<close>
|
|
27 |
|
|
28 |
lemma heap_merge_adj: "\<forall>t \<in> set ts. heap t \<Longrightarrow> \<forall>t \<in> set (merge_adj ts). heap t"
|
|
29 |
by(induction ts rule: merge_adj.induct) (auto simp: heap_merge)
|
|
30 |
|
|
31 |
lemma ltree_merge_adj: "\<forall>t \<in> set ts. ltree t \<Longrightarrow> \<forall>t \<in> set (merge_adj ts). ltree t"
|
|
32 |
by(induction ts rule: merge_adj.induct) (auto simp: ltree_merge)
|
|
33 |
|
|
34 |
lemma heap_merge_all: "\<forall>t \<in> set ts. heap t \<Longrightarrow> heap (merge_all ts)"
|
|
35 |
apply(induction ts rule: merge_all.induct)
|
|
36 |
using [[simp_depth_limit=3]] by (auto simp add: heap_merge_adj)
|
|
37 |
|
|
38 |
lemma ltree_merge_all: "\<forall>t \<in> set ts. ltree t \<Longrightarrow> ltree (merge_all ts)"
|
|
39 |
apply(induction ts rule: merge_all.induct)
|
|
40 |
using [[simp_depth_limit=3]] by (auto simp add: ltree_merge_adj)
|
|
41 |
|
|
42 |
lemma mset_merge_adj:
|
|
43 |
"\<Sum>\<^sub># (image_mset mset_tree (mset (merge_adj ts))) =
|
|
44 |
\<Sum>\<^sub># (image_mset mset_tree (mset ts))"
|
|
45 |
by(induction ts rule: merge_adj.induct) (auto simp: mset_merge)
|
|
46 |
|
|
47 |
lemma mset_merge_all:
|
|
48 |
"mset_tree (merge_all ts) = \<Sum>\<^sub># (mset (map mset_tree ts))"
|
|
49 |
by(induction ts rule: merge_all.induct) (auto simp: mset_merge mset_merge_adj)
|
|
50 |
|
|
51 |
fun lheap_list :: "'a::ord list \<Rightarrow> 'a lheap" where
|
|
52 |
"lheap_list xs = merge_all (map (\<lambda>x. Node Leaf (x,1) Leaf) xs)"
|
|
53 |
|
|
54 |
lemma mset_lheap_list: "mset_tree (lheap_list xs) = mset xs"
|
|
55 |
by (simp add: mset_merge_all o_def)
|
|
56 |
|
|
57 |
lemma ltree_lheap_list: "ltree (lheap_list ts)"
|
|
58 |
by(simp add: ltree_merge_all)
|
|
59 |
|
|
60 |
lemma heap_lheap_list: "heap (lheap_list ts)"
|
|
61 |
by(simp add: heap_merge_all)
|
|
62 |
|
|
63 |
lemma size_merge: "size(merge t1 t2) = size t1 + size t2"
|
|
64 |
by(induction t1 t2 rule: merge.induct) (auto simp: node_def)
|
|
65 |
|
|
66 |
|
|
67 |
subsubsection \<open>Running time\<close>
|
|
68 |
|
79984
|
69 |
text \<open>Not defined automatically because we only count the time for @{const merge}.\<close>
|
|
70 |
|
78231
|
71 |
fun T_merge_adj :: "('a::ord) lheap list \<Rightarrow> nat" where
|
|
72 |
"T_merge_adj [] = 0" |
|
|
73 |
"T_merge_adj [t] = 0" |
|
|
74 |
"T_merge_adj (t1 # t2 # ts) = T_merge t1 t2 + T_merge_adj ts"
|
|
75 |
|
|
76 |
fun T_merge_all :: "('a::ord) lheap list \<Rightarrow> nat" where
|
|
77 |
"T_merge_all [] = 0" |
|
|
78 |
"T_merge_all [t] = 0" |
|
|
79 |
"T_merge_all ts = T_merge_adj ts + T_merge_all (merge_adj ts)"
|
|
80 |
|
|
81 |
fun T_lheap_list :: "'a::ord list \<Rightarrow> nat" where
|
|
82 |
"T_lheap_list xs = T_merge_all (map (\<lambda>x. Node Leaf (x,1) Leaf) xs)"
|
|
83 |
|
|
84 |
abbreviation Tm where
|
|
85 |
"Tm n == 2 * log 2 (n+1) + 1"
|
|
86 |
|
|
87 |
lemma T_merge_adj: "\<lbrakk> \<forall>t \<in> set ts. ltree t; \<forall>t \<in> set ts. size t = n \<rbrakk>
|
|
88 |
\<Longrightarrow> T_merge_adj ts \<le> (length ts div 2) * Tm n"
|
|
89 |
proof(induction ts rule: T_merge_adj.induct)
|
|
90 |
case 1 thus ?case by simp
|
|
91 |
next
|
|
92 |
case 2 thus ?case by simp
|
|
93 |
next
|
|
94 |
case (3 t1 t2) thus ?case using T_merge_log[of t1 t2] by (simp add: algebra_simps size1_size)
|
|
95 |
qed
|
|
96 |
|
|
97 |
lemma size_merge_adj:
|
|
98 |
"\<lbrakk> even(length ts); \<forall>t \<in> set ts. ltree t; \<forall>t \<in> set ts. size t = n \<rbrakk>
|
|
99 |
\<Longrightarrow> \<forall>t \<in> set (merge_adj ts). size t = 2*n"
|
|
100 |
by(induction ts rule: merge_adj.induct) (auto simp: size_merge)
|
|
101 |
|
|
102 |
lemma T_merge_all:
|
|
103 |
"\<lbrakk> \<forall>t \<in> set ts. ltree t; \<forall>t \<in> set ts. size t = n; length ts = 2^k \<rbrakk>
|
|
104 |
\<Longrightarrow> T_merge_all ts \<le> (\<Sum>i=1..k. 2^(k-i) * Tm(2 ^ (i-1) * n))"
|
|
105 |
proof (induction ts arbitrary: k n rule: merge_all.induct)
|
|
106 |
case 1 thus ?case by simp
|
|
107 |
next
|
|
108 |
case 2 thus ?case by simp
|
|
109 |
next
|
|
110 |
case (3 t1 t2 ts)
|
|
111 |
let ?ts = "t1 # t2 # ts"
|
|
112 |
let ?ts2 = "merge_adj ?ts"
|
|
113 |
obtain k' where k': "k = Suc k'" using "3.prems"(3)
|
|
114 |
by (metis length_Cons nat.inject nat_power_eq_Suc_0_iff nat.exhaust)
|
|
115 |
have 1: "\<forall>x \<in> set(merge_adj ?ts). ltree x"
|
|
116 |
by(rule ltree_merge_adj[OF "3.prems"(1)])
|
|
117 |
have "even (length ts)" using "3.prems"(3) even_Suc_Suc_iff by fastforce
|
|
118 |
from "3.prems"(2) size_merge_adj[OF this] "3.prems"(1)
|
|
119 |
have 2: "\<forall>x \<in> set(merge_adj ?ts). size x = 2*n" by(auto simp: size_merge)
|
82010
|
120 |
have 3: "length ?ts2 = 2 ^ k'" using "3.prems"(3) k' by (simp add: length_merge_adjacent)
|
78231
|
121 |
have 4: "length ?ts div 2 = 2 ^ k'"
|
|
122 |
using "3.prems"(3) k' by(simp add: power_eq_if[of 2 k] split: if_splits)
|
|
123 |
have "T_merge_all ?ts = T_merge_adj ?ts + T_merge_all ?ts2" by simp
|
|
124 |
also have "\<dots> \<le> 2^k' * Tm n + T_merge_all ?ts2"
|
|
125 |
using 4 T_merge_adj[OF "3.prems"(1,2)] by auto
|
|
126 |
also have "\<dots> \<le> 2^k' * Tm n + (\<Sum>i=1..k'. 2^(k'-i) * Tm(2 ^ (i-1) * (2*n)))"
|
|
127 |
using "3.IH"[OF 1 2 3] by simp
|
|
128 |
also have "\<dots> = 2^k' * Tm n + (\<Sum>i=1..k'. 2^(k'-i) * Tm(2 ^ (Suc(i-1)) * n))"
|
|
129 |
by (simp add: mult_ac cong del: sum.cong)
|
|
130 |
also have "\<dots> = 2^k' * Tm n + (\<Sum>i=1..k'. 2^(k'-i) * Tm(2 ^ i * n))"
|
|
131 |
by (simp)
|
|
132 |
also have "\<dots> = (\<Sum>i=1..k. 2^(k-i) * Tm(2 ^ (i-1) * real n))"
|
|
133 |
by(simp add: sum.atLeast_Suc_atMost[of "Suc 0" "Suc k'"] sum.atLeast_Suc_atMost_Suc_shift[of _ "Suc 0"] k'
|
|
134 |
del: sum.cl_ivl_Suc)
|
|
135 |
finally show ?case .
|
|
136 |
qed
|
|
137 |
|
|
138 |
lemma summation: "(\<Sum>i=1..k. 2^(k-i) * ((2::real)*i+1)) = 5*2^k - (2::real)*k - 5"
|
|
139 |
proof (induction k)
|
|
140 |
case 0 thus ?case by simp
|
|
141 |
next
|
|
142 |
case (Suc k)
|
|
143 |
have "(\<Sum>i=1..Suc k. 2^(Suc k - i) * ((2::real)*i+1))
|
|
144 |
= (\<Sum>i=1..k. 2^(k+1-i) * ((2::real)*i+1)) + 2*k+3"
|
|
145 |
by(simp)
|
|
146 |
also have "\<dots> = (\<Sum>i=1..k. (2::real)*(2^(k-i) * ((2::real)*i+1))) + 2*k+3"
|
|
147 |
by (simp add: Suc_diff_le mult.assoc)
|
|
148 |
also have "\<dots> = 2*(\<Sum>i=1..k. 2^(k-i) * ((2::real)*i+1)) + 2*k+3"
|
|
149 |
by(simp add: sum_distrib_left)
|
|
150 |
also have "\<dots> = (2::real)*(5*2^k - (2::real)*k - 5) + 2*k+3"
|
|
151 |
using Suc.IH by simp
|
|
152 |
also have "\<dots> = 5*2^(Suc k) - (2::real)*(Suc k) - 5"
|
|
153 |
by simp
|
|
154 |
finally show ?case .
|
|
155 |
qed
|
|
156 |
|
|
157 |
lemma T_lheap_list: assumes "length xs = 2 ^ k"
|
80776
|
158 |
shows "T_lheap_list xs \<le> 5 * length xs - 2 * log 2 (length xs)"
|
78231
|
159 |
proof -
|
|
160 |
let ?ts = "map (\<lambda>x. Node Leaf (x,1) Leaf) xs"
|
|
161 |
have "T_lheap_list xs = T_merge_all ?ts" by simp
|
|
162 |
also have "\<dots> \<le> (\<Sum>i = 1..k. 2^(k-i) * (2 * log 2 (2^(i-1) + 1) + 1))"
|
|
163 |
using T_merge_all[of ?ts 1 k] assms by (simp)
|
|
164 |
also have "\<dots> \<le> (\<Sum>i = 1..k. 2^(k-i) * (2 * log 2 (2*2^(i-1)) + 1))"
|
|
165 |
apply(rule sum_mono)
|
|
166 |
using zero_le_power[of "2::real"] by (simp add: add_pos_nonneg)
|
|
167 |
also have "\<dots> = (\<Sum>i = 1..k. 2^(k-i) * (2 * log 2 (2^(1+(i-1))) + 1))"
|
|
168 |
by (simp del: Suc_pred)
|
|
169 |
also have "\<dots> = (\<Sum>i = 1..k. 2^(k-i) * (2 * log 2 (2^i) + 1))"
|
|
170 |
by (simp)
|
|
171 |
also have "\<dots> = (\<Sum>i = 1..k. 2^(k-i) * ((2::real)*i+1))"
|
|
172 |
by (simp add:log_nat_power algebra_simps)
|
|
173 |
also have "\<dots> = 5*(2::real)^k - (2::real)*k - 5"
|
|
174 |
using summation by (simp)
|
|
175 |
finally show ?thesis
|
80776
|
176 |
using assms of_nat_le_iff by simp
|
78231
|
177 |
qed
|
|
178 |
|
|
179 |
end |