77 termination by lexicographic_order |
77 termination by lexicographic_order |
78 |
78 |
79 fun |
79 fun |
80 restrict :: "'key set \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list" |
80 restrict :: "'key set \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list" |
81 where |
81 where |
82 "restrict A [] = []" |
82 "restrict A [] = []" |
83 | "restrict A (p#ps) = (if fst p \<in> A then p#restrict A ps else restrict A ps)" |
83 | "restrict A (p#ps) = (if fst p \<in> A then p#restrict A ps else restrict A ps)" |
84 |
84 |
85 fun |
85 fun |
86 map_ran :: "('key \<Rightarrow> 'val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list" |
86 map_ran :: "('key \<Rightarrow> 'val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list" |
87 where |
87 where |
88 "map_ran f [] = []" |
88 "map_ran f [] = []" |
89 | "map_ran f (p#ps) = (fst p, f (fst p) (snd p)) # map_ran f ps" |
89 | "map_ran f (p#ps) = (fst p, f (fst p) (snd p)) # map_ran f ps" |
90 |
90 |
91 fun |
91 fun |
92 clearjunk :: "('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list" |
92 clearjunk :: "('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list" |
93 where |
93 where |
94 "clearjunk [] = []" |
94 "clearjunk [] = []" |
95 | "clearjunk (p#ps) = p # clearjunk (delete (fst p) ps)" |
95 | "clearjunk (p#ps) = p # clearjunk (delete (fst p) ps)" |
96 |
96 |
97 lemmas [simp del] = compose_hint |
97 lemmas [simp del] = compose_hint |
98 |
98 |
99 |
99 |
100 (* ******************************************************************************** *) |
|
101 subsection {* Lookup *} |
100 subsection {* Lookup *} |
102 (* ******************************************************************************** *) |
|
103 |
101 |
104 lemma lookup_simps [code func]: |
102 lemma lookup_simps [code func]: |
105 "map_of [] k = None" |
103 "map_of [] k = None" |
106 "map_of (p#ps) k = (if fst p = k then Some (snd p) else map_of ps k)" |
104 "map_of (p#ps) k = (if fst p = k then Some (snd p) else map_of ps k)" |
107 by simp_all |
105 by simp_all |
108 |
106 |
109 |
107 |
110 (* ******************************************************************************** *) |
|
111 subsection {* @{const delete} *} |
108 subsection {* @{const delete} *} |
112 (* ******************************************************************************** *) |
|
113 |
109 |
114 lemma delete_def: |
110 lemma delete_def: |
115 "delete k xs = filter (\<lambda>p. fst p \<noteq> k) xs" |
111 "delete k xs = filter (\<lambda>p. fst p \<noteq> k) xs" |
116 by (induct xs) auto |
112 by (induct xs) auto |
117 |
113 |
138 by (induct al) auto |
134 by (induct al) auto |
139 |
135 |
140 lemma distinct_delete: |
136 lemma distinct_delete: |
141 assumes "distinct (map fst al)" |
137 assumes "distinct (map fst al)" |
142 shows "distinct (map fst (delete k al))" |
138 shows "distinct (map fst (delete k al))" |
143 using prems |
139 using assms |
144 proof (induct al) |
140 proof (induct al) |
145 case Nil thus ?case by simp |
141 case Nil thus ?case by simp |
146 next |
142 next |
147 case (Cons a al) |
143 case (Cons a al) |
148 from Cons.prems obtain |
144 from Cons.prems obtain |
169 by (induct al) auto |
165 by (induct al) auto |
170 |
166 |
171 lemma clearjunk_delete: "clearjunk (delete x al) = delete x (clearjunk al)" |
167 lemma clearjunk_delete: "clearjunk (delete x al) = delete x (clearjunk al)" |
172 by (induct al rule: clearjunk.induct) (auto simp add: delete_idem delete_twist) |
168 by (induct al rule: clearjunk.induct) (auto simp add: delete_idem delete_twist) |
173 |
169 |
174 (* ******************************************************************************** *) |
170 |
175 subsection {* @{const clearjunk} *} |
171 subsection {* @{const clearjunk} *} |
176 (* ******************************************************************************** *) |
|
177 |
172 |
178 lemma insert_fst_filter: |
173 lemma insert_fst_filter: |
179 "insert a(fst ` {x \<in> set ps. fst x \<noteq> a}) = insert a (fst ` set ps)" |
174 "insert a(fst ` {x \<in> set ps. fst x \<noteq> a}) = insert a (fst ` set ps)" |
180 by (induct ps) auto |
175 by (induct ps) auto |
181 |
176 |
219 by (induct al rule: clearjunk.induct) (auto simp add: notin_fst_filter) |
214 by (induct al rule: clearjunk.induct) (auto simp add: notin_fst_filter) |
220 |
215 |
221 lemma clearjunk_idem: "clearjunk (clearjunk al) = clearjunk al" |
216 lemma clearjunk_idem: "clearjunk (clearjunk al) = clearjunk al" |
222 by simp |
217 by simp |
223 |
218 |
224 (* ******************************************************************************** *) |
219 |
225 subsection {* @{const dom} and @{term "ran"} *} |
220 subsection {* @{const dom} and @{term "ran"} *} |
226 (* ******************************************************************************** *) |
|
227 |
221 |
228 lemma dom_map_of': "fst ` set al = dom (map_of al)" |
222 lemma dom_map_of': "fst ` set al = dom (map_of al)" |
229 by (induct al) auto |
223 by (induct al) auto |
230 |
224 |
231 lemmas dom_map_of = dom_map_of' [symmetric] |
225 lemmas dom_map_of = dom_map_of' [symmetric] |
293 also have "\<dots> = snd ` set (clearjunk al)" |
287 also have "\<dots> = snd ` set (clearjunk al)" |
294 by (simp add: ran_distinct) |
288 by (simp add: ran_distinct) |
295 finally show ?thesis . |
289 finally show ?thesis . |
296 qed |
290 qed |
297 |
291 |
298 (* ******************************************************************************** *) |
292 |
299 subsection {* @{const update} *} |
293 subsection {* @{const update} *} |
300 (* ******************************************************************************** *) |
|
301 |
294 |
302 lemma update_conv: "map_of (update k v al) k' = ((map_of al)(k\<mapsto>v)) k'" |
295 lemma update_conv: "map_of (update k v al) k' = ((map_of al)(k\<mapsto>v)) k'" |
303 by (induct al) auto |
296 by (induct al) auto |
304 |
297 |
305 lemma update_conv': "map_of (update k v al) = ((map_of al)(k\<mapsto>v))" |
298 lemma update_conv': "map_of (update k v al) = ((map_of al)(k\<mapsto>v))" |
309 by (induct al) auto |
302 by (induct al) auto |
310 |
303 |
311 lemma distinct_update: |
304 lemma distinct_update: |
312 assumes "distinct (map fst al)" |
305 assumes "distinct (map fst al)" |
313 shows "distinct (map fst (update k v al))" |
306 shows "distinct (map fst (update k v al))" |
314 using prems |
307 using assms |
315 proof (induct al) |
308 proof (induct al) |
316 case Nil thus ?case by simp |
309 case Nil thus ?case by simp |
317 next |
310 next |
318 case (Cons a al) |
311 case (Cons a al) |
319 from Cons.prems obtain |
312 from Cons.prems obtain |
372 |
365 |
373 lemma image_update[simp]: "x \<notin> A \<Longrightarrow> map_of (update x y al) ` A = map_of al ` A" |
366 lemma image_update[simp]: "x \<notin> A \<Longrightarrow> map_of (update x y al) ` A = map_of al ` A" |
374 by (simp add: update_conv' image_map_upd) |
367 by (simp add: update_conv' image_map_upd) |
375 |
368 |
376 |
369 |
377 (* ******************************************************************************** *) |
|
378 subsection {* @{const updates} *} |
370 subsection {* @{const updates} *} |
379 (* ******************************************************************************** *) |
|
380 |
371 |
381 lemma updates_conv: "map_of (updates ks vs al) k = ((map_of al)(ks[\<mapsto>]vs)) k" |
372 lemma updates_conv: "map_of (updates ks vs al) k = ((map_of al)(ks[\<mapsto>]vs)) k" |
382 proof (induct ks arbitrary: vs al) |
373 proof (induct ks arbitrary: vs al) |
383 case Nil |
374 case Nil |
384 thus ?case by simp |
375 thus ?case by simp |
399 by (rule ext) (rule updates_conv) |
390 by (rule ext) (rule updates_conv) |
400 |
391 |
401 lemma distinct_updates: |
392 lemma distinct_updates: |
402 assumes "distinct (map fst al)" |
393 assumes "distinct (map fst al)" |
403 shows "distinct (map fst (updates ks vs al))" |
394 shows "distinct (map fst (updates ks vs al))" |
404 using prems |
395 using assms |
405 by (induct ks arbitrary: vs al) |
396 by (induct ks arbitrary: vs al) |
406 (auto simp add: distinct_update split: list.splits) |
397 (auto simp add: distinct_update split: list.splits) |
407 |
398 |
408 lemma clearjunk_updates: |
399 lemma clearjunk_updates: |
409 "clearjunk (updates ks vs al) = updates ks vs (clearjunk al)" |
400 "clearjunk (updates ks vs al) = updates ks vs (clearjunk al)" |
445 |
436 |
446 lemma updates_append2_drop[simp]: |
437 lemma updates_append2_drop[simp]: |
447 "size xs = size ys \<Longrightarrow> updates xs (ys@zs) al = updates xs ys al" |
438 "size xs = size ys \<Longrightarrow> updates xs (ys@zs) al = updates xs ys al" |
448 by (induct xs arbitrary: ys al) (auto split: list.splits) |
439 by (induct xs arbitrary: ys al) (auto split: list.splits) |
449 |
440 |
450 (* ******************************************************************************** *) |
441 |
451 subsection {* @{const map_ran} *} |
442 subsection {* @{const map_ran} *} |
452 (* ******************************************************************************** *) |
|
453 |
443 |
454 lemma map_ran_conv: "map_of (map_ran f al) k = option_map (f k) (map_of al k)" |
444 lemma map_ran_conv: "map_of (map_ran f al) k = option_map (f k) (map_of al k)" |
455 by (induct al) auto |
445 by (induct al) auto |
456 |
446 |
457 lemma dom_map_ran: "fst ` set (map_ran f al) = fst ` set al" |
447 lemma dom_map_ran: "fst ` set (map_ran f al) = fst ` set al" |
464 by (induct ps) auto |
454 by (induct ps) auto |
465 |
455 |
466 lemma clearjunk_map_ran: "clearjunk (map_ran f al) = map_ran f (clearjunk al)" |
456 lemma clearjunk_map_ran: "clearjunk (map_ran f al) = map_ran f (clearjunk al)" |
467 by (induct al rule: clearjunk.induct) (auto simp add: delete_def map_ran_filter) |
457 by (induct al rule: clearjunk.induct) (auto simp add: delete_def map_ran_filter) |
468 |
458 |
469 (* ******************************************************************************** *) |
459 |
470 subsection {* @{const merge} *} |
460 subsection {* @{const merge} *} |
471 (* ******************************************************************************** *) |
|
472 |
461 |
473 lemma dom_merge: "fst ` set (merge xs ys) = fst ` set xs \<union> fst ` set ys" |
462 lemma dom_merge: "fst ` set (merge xs ys) = fst ` set xs \<union> fst ` set ys" |
474 by (induct ys arbitrary: xs) (auto simp add: dom_update) |
463 by (induct ys arbitrary: xs) (auto simp add: dom_update) |
475 |
464 |
476 lemma distinct_merge: |
465 lemma distinct_merge: |
477 assumes "distinct (map fst xs)" |
466 assumes "distinct (map fst xs)" |
478 shows "distinct (map fst (merge xs ys))" |
467 shows "distinct (map fst (merge xs ys))" |
479 using prems |
468 using assms |
480 by (induct ys arbitrary: xs) (auto simp add: dom_merge distinct_update) |
469 by (induct ys arbitrary: xs) (auto simp add: dom_merge distinct_update) |
481 |
470 |
482 lemma clearjunk_merge: |
471 lemma clearjunk_merge: |
483 "clearjunk (merge xs ys) = merge (clearjunk xs) ys" |
472 "clearjunk (merge xs ys) = merge (clearjunk xs) ys" |
484 by (induct ys) (auto simp add: clearjunk_update) |
473 by (induct ys) (auto simp add: clearjunk_update) |
534 by (simp add: updates_conv' merge_conv') |
523 by (simp add: updates_conv' merge_conv') |
535 |
524 |
536 lemma merge_append: "map_of (xs@ys) = map_of (merge ys xs)" |
525 lemma merge_append: "map_of (xs@ys) = map_of (merge ys xs)" |
537 by (simp add: merge_conv') |
526 by (simp add: merge_conv') |
538 |
527 |
539 (* ******************************************************************************** *) |
528 |
540 subsection {* @{const compose} *} |
529 subsection {* @{const compose} *} |
541 (* ******************************************************************************** *) |
|
542 |
530 |
543 lemma compose_first_None [simp]: |
531 lemma compose_first_None [simp]: |
544 assumes "map_of xs k = None" |
532 assumes "map_of xs k = None" |
545 shows "map_of (compose xs ys) k = None" |
533 shows "map_of (compose xs ys) k = None" |
546 using prems by (induct xs ys rule: compose.induct) |
534 using assms by (induct xs ys rule: compose.induct) |
547 (auto split: option.splits split_if_asm) |
535 (auto split: option.splits split_if_asm) |
548 |
536 |
549 lemma compose_conv: |
537 lemma compose_conv: |
550 shows "map_of (compose xs ys) k = (map_of ys \<circ>\<^sub>m map_of xs) k" |
538 shows "map_of (compose xs ys) k = (map_of ys \<circ>\<^sub>m map_of xs) k" |
551 proof (induct xs ys rule: compose.induct) |
539 proof (induct xs ys rule: compose.induct) |
589 by (rule ext) (rule compose_conv) |
577 by (rule ext) (rule compose_conv) |
590 |
578 |
591 lemma compose_first_Some [simp]: |
579 lemma compose_first_Some [simp]: |
592 assumes "map_of xs k = Some v" |
580 assumes "map_of xs k = Some v" |
593 shows "map_of (compose xs ys) k = map_of ys v" |
581 shows "map_of (compose xs ys) k = map_of ys v" |
594 using prems by (simp add: compose_conv) |
582 using assms by (simp add: compose_conv) |
595 |
583 |
596 lemma dom_compose: "fst ` set (compose xs ys) \<subseteq> fst ` set xs" |
584 lemma dom_compose: "fst ` set (compose xs ys) \<subseteq> fst ` set xs" |
597 proof (induct xs ys rule: compose.induct) |
585 proof (induct xs ys rule: compose.induct) |
598 case 1 thus ?case by simp |
586 case 1 thus ?case by simp |
599 next |
587 next |
621 qed |
609 qed |
622 |
610 |
623 lemma distinct_compose: |
611 lemma distinct_compose: |
624 assumes "distinct (map fst xs)" |
612 assumes "distinct (map fst xs)" |
625 shows "distinct (map fst (compose xs ys))" |
613 shows "distinct (map fst (compose xs ys))" |
626 using prems |
614 using assms |
627 proof (induct xs ys rule: compose.induct) |
615 proof (induct xs ys rule: compose.induct) |
628 case 1 thus ?case by simp |
616 case 1 thus ?case by simp |
629 next |
617 next |
630 case (2 x xs ys) |
618 case (2 x xs ys) |
631 show ?case |
619 show ?case |
693 "(map_of (compose xs ys) k = None) = |
681 "(map_of (compose xs ys) k = None) = |
694 (map_of xs k = None \<or> (\<exists>k'. map_of xs k = Some k' \<and> map_of ys k' = None)) " |
682 (map_of xs k = None \<or> (\<exists>k'. map_of xs k = Some k' \<and> map_of ys k' = None)) " |
695 by (simp add: compose_conv map_comp_None_iff) |
683 by (simp add: compose_conv map_comp_None_iff) |
696 |
684 |
697 |
685 |
698 (* ******************************************************************************** *) |
|
699 subsection {* @{const restrict} *} |
686 subsection {* @{const restrict} *} |
700 (* ******************************************************************************** *) |
|
701 |
687 |
702 lemma restrict_def: |
688 lemma restrict_def: |
703 "restrict A = filter (\<lambda>p. fst p \<in> A)" |
689 "restrict A = filter (\<lambda>p. fst p \<in> A)" |
704 proof |
690 proof |
705 fix xs |
691 fix xs |