src/HOL/Data_Structures/Tries_Binary.thy
changeset 70268 81403d7b9038
parent 70267 9fa2cf7142b7
child 70269 40b6bc5a4721
equal deleted inserted replaced
70267:9fa2cf7142b7 70268:81403d7b9038
   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