105 qed (rule TrueI)+ |
105 qed (rule TrueI)+ |
106 |
106 |
107 |
107 |
108 subsection "Patricia Trie" |
108 subsection "Patricia Trie" |
109 |
109 |
110 datatype ptrie = LfP | NdP "bool list" bool "ptrie * ptrie" |
110 datatype trieP = LfP | NdP "bool list" bool "trieP * trieP" |
111 |
111 |
112 fun isinP :: "ptrie \<Rightarrow> bool list \<Rightarrow> bool" where |
112 fun isinP :: "trieP \<Rightarrow> bool list \<Rightarrow> bool" where |
113 "isinP LfP ks = False" | |
113 "isinP LfP ks = False" | |
114 "isinP (NdP ps b lr) ks = |
114 "isinP (NdP ps b lr) ks = |
115 (let n = length ps in |
115 (let n = length ps in |
116 if ps = take n ks |
116 if ps = take n ks |
117 then case drop n ks of [] \<Rightarrow> b | k#ks' \<Rightarrow> isinP (sel2 k lr) ks' |
117 then case drop n ks of [] \<Rightarrow> b | k#ks' \<Rightarrow> isinP (sel2 k lr) ks' |
118 else False)" |
118 else False)" |
119 |
119 |
|
120 definition emptyP :: trieP where |
|
121 [simp]: "emptyP = LfP" |
|
122 |
120 fun split where |
123 fun split where |
121 "split [] ys = ([],[],ys)" | |
124 "split [] ys = ([],[],ys)" | |
122 "split xs [] = ([],xs,[])" | |
125 "split xs [] = ([],xs,[])" | |
123 "split (x#xs) (y#ys) = |
126 "split (x#xs) (y#ys) = |
124 (if x\<noteq>y then ([],x#xs,y#ys) |
127 (if x\<noteq>y then ([],x#xs,y#ys) |
128 lemma mod2_cong[fundef_cong]: |
131 lemma mod2_cong[fundef_cong]: |
129 "\<lbrakk> lr = lr'; k = k'; \<And>a b. lr'=(a,b) \<Longrightarrow> f (a) = f' (a) ; \<And>a b. lr'=(a,b) \<Longrightarrow> f (b) = f' (b) \<rbrakk> |
132 "\<lbrakk> lr = lr'; k = k'; \<And>a b. lr'=(a,b) \<Longrightarrow> f (a) = f' (a) ; \<And>a b. lr'=(a,b) \<Longrightarrow> f (b) = f' (b) \<rbrakk> |
130 \<Longrightarrow> mod2 f k lr= mod2 f' k' lr'" |
133 \<Longrightarrow> mod2 f k lr= mod2 f' k' lr'" |
131 by(cases lr, cases lr', auto) |
134 by(cases lr, cases lr', auto) |
132 |
135 |
133 fun insertP :: "bool list \<Rightarrow> ptrie \<Rightarrow> ptrie" where |
136 |
|
137 fun insertP :: "bool list \<Rightarrow> trieP \<Rightarrow> trieP" where |
134 "insertP ks LfP = NdP ks True (LfP,LfP)" | |
138 "insertP ks LfP = NdP ks True (LfP,LfP)" | |
135 "insertP ks (NdP ps b lr) = |
139 "insertP ks (NdP ps b lr) = |
136 (case split ks ps of |
140 (case split ks ps of |
137 (qs,k#ks',p#ps') \<Rightarrow> |
141 (qs,k#ks',p#ps') \<Rightarrow> |
138 let tp = NdP ps' b lr; tk = NdP ks' True (LfP,LfP) in |
142 let tp = NdP ps' b lr; tk = NdP ks' True (LfP,LfP) in |
143 let t = NdP ps' b lr in |
147 let t = NdP ps' b lr in |
144 NdP qs True (if p then (LfP,t) else (t,LfP)) | |
148 NdP qs True (if p then (LfP,t) else (t,LfP)) | |
145 (qs,[],[]) \<Rightarrow> NdP ps True lr)" |
149 (qs,[],[]) \<Rightarrow> NdP ps True lr)" |
146 |
150 |
147 |
151 |
148 fun nodeP :: "bool list \<Rightarrow> bool \<Rightarrow> ptrie * ptrie \<Rightarrow> ptrie" where |
152 fun nodeP :: "bool list \<Rightarrow> bool \<Rightarrow> trieP * trieP \<Rightarrow> trieP" where |
149 "nodeP ps b lr = (if \<not> b \<and> lr = (LfP,LfP) then LfP else NdP ps b lr)" |
153 "nodeP ps b lr = (if \<not> b \<and> lr = (LfP,LfP) then LfP else NdP ps b lr)" |
150 |
154 |
151 fun deleteP :: "bool list \<Rightarrow> ptrie \<Rightarrow> ptrie" where |
155 fun deleteP :: "bool list \<Rightarrow> trieP \<Rightarrow> trieP" where |
152 "deleteP ks LfP = LfP" | |
156 "deleteP ks LfP = LfP" | |
153 "deleteP ks (NdP ps b lr) = |
157 "deleteP ks (NdP ps b lr) = |
154 (case split ks ps of |
158 (case split ks ps of |
155 (qs,ks',p#ps') \<Rightarrow> NdP ps b lr | |
159 (qs,ks',p#ps') \<Rightarrow> NdP ps b lr | |
156 (qs,k#ks',[]) \<Rightarrow> nodeP ps b (mod2 (deleteP ks') k lr) | |
160 (qs,k#ks',[]) \<Rightarrow> nodeP ps b (mod2 (deleteP ks') k lr) | |
157 (qs,[],[]) \<Rightarrow> nodeP ps False lr)" |
161 (qs,[],[]) \<Rightarrow> nodeP ps False lr)" |
158 |
162 |
159 |
163 |
160 subsubsection \<open>Functional Correctness\<close> |
164 subsubsection \<open>Functional Correctness\<close> |
161 |
165 |
162 text \<open>First step: @{typ ptrie} implements @{typ trie} via the abstraction function \<open>abs_ptrie\<close>:\<close> |
166 text \<open>First step: @{typ trieP} implements @{typ trie} via the abstraction function \<open>abs_trieP\<close>:\<close> |
163 |
167 |
164 fun prefix_trie :: "bool list \<Rightarrow> trie \<Rightarrow> trie" where |
168 fun prefix_trie :: "bool list \<Rightarrow> trie \<Rightarrow> trie" where |
165 "prefix_trie [] t = t" | |
169 "prefix_trie [] t = t" | |
166 "prefix_trie (k#ks) t = |
170 "prefix_trie (k#ks) t = |
167 (let t' = prefix_trie ks t in Nd False (if k then (Lf,t') else (t',Lf)))" |
171 (let t' = prefix_trie ks t in Nd False (if k then (Lf,t') else (t',Lf)))" |
168 |
172 |
169 fun abs_ptrie :: "ptrie \<Rightarrow> trie" where |
173 fun abs_trieP :: "trieP \<Rightarrow> trie" where |
170 "abs_ptrie LfP = Lf" | |
174 "abs_trieP LfP = Lf" | |
171 "abs_ptrie (NdP ps b (l,r)) = prefix_trie ps (Nd b (abs_ptrie l, abs_ptrie r))" |
175 "abs_trieP (NdP ps b (l,r)) = prefix_trie ps (Nd b (abs_trieP l, abs_trieP r))" |
172 |
176 |
173 |
177 |
174 text \<open>Correctness of @{const isinP}:\<close> |
178 text \<open>Correctness of @{const isinP}:\<close> |
175 |
179 |
176 lemma isin_prefix_trie: |
180 lemma isin_prefix_trie: |
179 apply(induction ps arbitrary: ks) |
183 apply(induction ps arbitrary: ks) |
180 apply(auto split: list.split) |
184 apply(auto split: list.split) |
181 done |
185 done |
182 |
186 |
183 lemma isinP: |
187 lemma isinP: |
184 "isinP t ks = isin (abs_ptrie t) ks" |
188 "isinP t ks = isin (abs_trieP t) ks" |
185 apply(induction t arbitrary: ks rule: abs_ptrie.induct) |
189 apply(induction t arbitrary: ks rule: abs_trieP.induct) |
186 apply(auto simp: isin_prefix_trie split: list.split) |
190 apply(auto simp: isin_prefix_trie split: list.split) |
187 done |
191 done |
188 |
192 |
189 |
193 |
190 text \<open>Correctness of @{const insertP}:\<close> |
194 text \<open>Correctness of @{const insertP}:\<close> |
214 ks = qs @ ks' \<and> ps = qs @ ps' \<and> (ks' \<noteq> [] \<and> ps' \<noteq> [] \<longrightarrow> hd ks' \<noteq> hd ps')" |
218 ks = qs @ ks' \<and> ps = qs @ ps' \<and> (ks' \<noteq> [] \<and> ps' \<noteq> [] \<longrightarrow> hd ks' \<noteq> hd ps')" |
215 apply(induction ks ps arbitrary: qs ks' ps' rule: split.induct) |
219 apply(induction ks ps arbitrary: qs ks' ps' rule: split.induct) |
216 apply(auto split: prod.splits if_splits) |
220 apply(auto split: prod.splits if_splits) |
217 done |
221 done |
218 |
222 |
219 lemma abs_ptrie_insertP: |
223 lemma abs_trieP_insertP: |
220 "abs_ptrie (insertP ks t) = insert ks (abs_ptrie t)" |
224 "abs_trieP (insertP ks t) = insert ks (abs_trieP t)" |
221 apply(induction t arbitrary: ks) |
225 apply(induction t arbitrary: ks) |
222 apply(auto simp: prefix_trie_Lfs insert_prefix_trie_same insert_append prefix_trie_append |
226 apply(auto simp: prefix_trie_Lfs insert_prefix_trie_same insert_append prefix_trie_append |
223 dest!: split_if split: list.split prod.split if_splits) |
227 dest!: split_if split: list.split prod.split if_splits) |
224 done |
228 done |
225 |
229 |
227 text \<open>Correctness of @{const deleteP}:\<close> |
231 text \<open>Correctness of @{const deleteP}:\<close> |
228 |
232 |
229 lemma prefix_trie_Lf: "prefix_trie xs t = Lf \<longleftrightarrow> xs = [] \<and> t = Lf" |
233 lemma prefix_trie_Lf: "prefix_trie xs t = Lf \<longleftrightarrow> xs = [] \<and> t = Lf" |
230 by(cases xs)(auto) |
234 by(cases xs)(auto) |
231 |
235 |
232 lemma abs_ptrie_Lf: "abs_ptrie t = Lf \<longleftrightarrow> t = LfP" |
236 lemma abs_trieP_Lf: "abs_trieP t = Lf \<longleftrightarrow> t = LfP" |
233 by(cases t) (auto simp: prefix_trie_Lf) |
237 by(cases t) (auto simp: prefix_trie_Lf) |
234 |
238 |
235 lemma delete_prefix_trie: |
239 lemma delete_prefix_trie: |
236 "delete xs (prefix_trie xs (Nd b (l,r))) |
240 "delete xs (prefix_trie xs (Nd b (l,r))) |
237 = (if (l,r) = (Lf,Lf) then Lf else prefix_trie xs (Nd False (l,r)))" |
241 = (if (l,r) = (Lf,Lf) then Lf else prefix_trie xs (Nd False (l,r)))" |
240 lemma delete_append_prefix_trie: |
244 lemma delete_append_prefix_trie: |
241 "delete (xs @ ys) (prefix_trie xs t) |
245 "delete (xs @ ys) (prefix_trie xs t) |
242 = (if delete ys t = Lf then Lf else prefix_trie xs (delete ys t))" |
246 = (if delete ys t = Lf then Lf else prefix_trie xs (delete ys t))" |
243 by(induction xs)(auto simp: prefix_trie_Lf) |
247 by(induction xs)(auto simp: prefix_trie_Lf) |
244 |
248 |
245 lemma delete_abs_ptrie: |
249 lemma delete_abs_trieP: |
246 "delete ks (abs_ptrie t) = abs_ptrie (deleteP ks t)" |
250 "delete ks (abs_trieP t) = abs_trieP (deleteP ks t)" |
247 apply(induction t arbitrary: ks) |
251 apply(induction t arbitrary: ks) |
248 apply(auto simp: delete_prefix_trie delete_append_prefix_trie |
252 apply(auto simp: delete_prefix_trie delete_append_prefix_trie |
249 prefix_trie_append prefix_trie_Lf abs_ptrie_Lf |
253 prefix_trie_append prefix_trie_Lf abs_trieP_Lf |
250 dest!: split_if split: if_splits list.split prod.split) |
254 dest!: split_if split: if_splits list.split prod.split) |
251 done |
255 done |
252 |
256 |
253 |
257 |
254 text \<open>The overall correctness proof. Simply composes correctness lemmas.\<close> |
258 text \<open>The overall correctness proof. Simply composes correctness lemmas.\<close> |
255 |
259 |
256 definition set_ptrie :: "ptrie \<Rightarrow> bool list set" where |
260 definition set_trieP :: "trieP \<Rightarrow> bool list set" where |
257 "set_ptrie = set_trie o abs_ptrie" |
261 "set_trieP = set_trie o abs_trieP" |
258 |
262 |
259 lemma set_ptrie_insertP: "set_ptrie (insertP xs t) = set_ptrie t \<union> {xs}" |
263 lemma set_trieP_insertP: "set_trieP (insertP xs t) = set_trieP t \<union> {xs}" |
260 by(simp add: abs_ptrie_insertP set_trie_insert set_ptrie_def) |
264 by(simp add: abs_trieP_insertP set_trie_insert set_trieP_def) |
261 |
265 |
262 interpretation SP: Set |
266 interpretation SP: Set |
263 where empty = LfP and isin = isinP and insert = insertP and delete = deleteP |
267 where empty = emptyP and isin = isinP and insert = insertP and delete = deleteP |
264 and set = set_ptrie and invar = "\<lambda>t. True" |
268 and set = set_trieP and invar = "\<lambda>t. True" |
265 proof (standard, goal_cases) |
269 proof (standard, goal_cases) |
266 case 1 show ?case by (simp add: set_ptrie_def set_trie_def) |
270 case 1 show ?case by (simp add: set_trieP_def set_trie_def) |
267 next |
271 next |
268 case 2 thus ?case by(simp add: isinP set_ptrie_def set_trie_def) |
272 case 2 thus ?case by(simp add: isinP set_trieP_def set_trie_def) |
269 next |
273 next |
270 case 3 thus ?case by (auto simp: set_ptrie_insertP) |
274 case 3 thus ?case by (auto simp: set_trieP_insertP) |
271 next |
275 next |
272 case 4 thus ?case |
276 case 4 thus ?case |
273 by(auto simp: isin_delete set_ptrie_def set_trie_def simp flip: delete_abs_ptrie) |
277 by(auto simp: isin_delete set_trieP_def set_trie_def simp flip: delete_abs_trieP) |
274 qed (rule TrueI)+ |
278 qed (rule TrueI)+ |
275 |
279 |
276 end |
280 end |