68 | "ffold_raw f z (a # A) = |
68 | "ffold_raw f z (a # A) = |
69 (if (rsp_fold f) then |
69 (if (rsp_fold f) then |
70 if memb a A then ffold_raw f z A |
70 if memb a A then ffold_raw f z A |
71 else f a (ffold_raw f z A) |
71 else f a (ffold_raw f z A) |
72 else z)" |
72 else z)" |
|
73 |
|
74 text {* Composition Quotient *} |
|
75 |
|
76 lemma compose_list_refl: |
|
77 shows "(list_rel op \<approx> OOO op \<approx>) r r" |
|
78 proof |
|
79 show c: "list_rel op \<approx> r r" by (rule list_rel_refl) (metis equivp_def fset_equivp) |
|
80 have d: "r \<approx> r" by (rule equivp_reflp[OF fset_equivp]) |
|
81 show b: "(op \<approx> OO list_rel op \<approx>) r r" by (rule pred_compI) (rule d, rule c) |
|
82 qed |
|
83 |
|
84 lemma list_rel_refl: |
|
85 shows "(list_rel op \<approx>) r r" |
|
86 by (rule list_rel_refl)(metis equivp_def fset_equivp) |
|
87 |
|
88 lemma Quotient_fset_list: |
|
89 shows "Quotient (list_rel op \<approx>) (map abs_fset) (map rep_fset)" |
|
90 by (fact list_quotient[OF Quotient_fset]) |
|
91 |
|
92 lemma set_in_eq: "(\<forall>e. ((e \<in> A) \<longleftrightarrow> (e \<in> B))) \<equiv> A = B" |
|
93 by (rule eq_reflection) auto |
|
94 |
|
95 lemma map_rel_cong: "b \<approx> ba \<Longrightarrow> map f b \<approx> map f ba" |
|
96 unfolding list_eq.simps |
|
97 by (simp only: set_map set_in_eq) |
|
98 |
|
99 lemma quotient_compose_list[quot_thm]: |
|
100 shows "Quotient ((list_rel op \<approx>) OOO (op \<approx>)) |
|
101 (abs_fset \<circ> (map abs_fset)) ((map rep_fset) \<circ> rep_fset)" |
|
102 unfolding Quotient_def comp_def |
|
103 proof (intro conjI allI) |
|
104 fix a r s |
|
105 show "abs_fset (map abs_fset (map rep_fset (rep_fset a))) = a" |
|
106 by (simp add: abs_o_rep[OF Quotient_fset] Quotient_abs_rep[OF Quotient_fset] map_id) |
|
107 have b: "list_rel op \<approx> (map rep_fset (rep_fset a)) (map rep_fset (rep_fset a))" |
|
108 by (rule list_rel_refl) |
|
109 have c: "(op \<approx> OO list_rel op \<approx>) (map rep_fset (rep_fset a)) (map rep_fset (rep_fset a))" |
|
110 by (rule, rule equivp_reflp[OF fset_equivp]) (rule b) |
|
111 show "(list_rel op \<approx> OOO op \<approx>) (map rep_fset (rep_fset a)) (map rep_fset (rep_fset a))" |
|
112 by (rule, rule list_rel_refl) (rule c) |
|
113 show "(list_rel op \<approx> OOO op \<approx>) r s = ((list_rel op \<approx> OOO op \<approx>) r r \<and> |
|
114 (list_rel op \<approx> OOO op \<approx>) s s \<and> abs_fset (map abs_fset r) = abs_fset (map abs_fset s))" |
|
115 proof (intro iffI conjI) |
|
116 show "(list_rel op \<approx> OOO op \<approx>) r r" by (rule compose_list_refl) |
|
117 show "(list_rel op \<approx> OOO op \<approx>) s s" by (rule compose_list_refl) |
|
118 next |
|
119 assume a: "(list_rel op \<approx> OOO op \<approx>) r s" |
|
120 then have b: "map abs_fset r \<approx> map abs_fset s" proof (elim pred_compE) |
|
121 fix b ba |
|
122 assume c: "list_rel op \<approx> r b" |
|
123 assume d: "b \<approx> ba" |
|
124 assume e: "list_rel op \<approx> ba s" |
|
125 have f: "map abs_fset r = map abs_fset b" |
|
126 by (metis Quotient_rel[OF Quotient_fset_list] c) |
|
127 have g: "map abs_fset s = map abs_fset ba" |
|
128 by (metis Quotient_rel[OF Quotient_fset_list] e) |
|
129 show "map abs_fset r \<approx> map abs_fset s" using d f g map_rel_cong by simp |
|
130 qed |
|
131 then show "abs_fset (map abs_fset r) = abs_fset (map abs_fset s)" |
|
132 by (metis Quotient_rel[OF Quotient_fset]) |
|
133 next |
|
134 assume a: "(list_rel op \<approx> OOO op \<approx>) r r \<and> (list_rel op \<approx> OOO op \<approx>) s s |
|
135 \<and> abs_fset (map abs_fset r) = abs_fset (map abs_fset s)" |
|
136 then have s: "(list_rel op \<approx> OOO op \<approx>) s s" by simp |
|
137 have d: "map abs_fset r \<approx> map abs_fset s" |
|
138 by (subst Quotient_rel[OF Quotient_fset]) (simp add: a) |
|
139 have b: "map rep_fset (map abs_fset r) \<approx> map rep_fset (map abs_fset s)" |
|
140 by (rule map_rel_cong[OF d]) |
|
141 have y: "list_rel op \<approx> (map rep_fset (map abs_fset s)) s" |
|
142 by (fact rep_abs_rsp_left[OF Quotient_fset_list, OF list_rel_refl[of s]]) |
|
143 have c: "(op \<approx> OO list_rel op \<approx>) (map rep_fset (map abs_fset r)) s" |
|
144 by (rule pred_compI) (rule b, rule y) |
|
145 have z: "list_rel op \<approx> r (map rep_fset (map abs_fset r))" |
|
146 by (fact rep_abs_rsp[OF Quotient_fset_list, OF list_rel_refl[of r]]) |
|
147 then show "(list_rel op \<approx> OOO op \<approx>) r s" |
|
148 using a c pred_compI by simp |
|
149 qed |
|
150 qed |
73 |
151 |
74 text {* Respectfullness *} |
152 text {* Respectfullness *} |
75 |
153 |
76 lemma [quot_respect]: |
154 lemma [quot_respect]: |
77 shows "(op \<approx> ===> op \<approx> ===> op \<approx>) op @ op @" |
155 shows "(op \<approx> ===> op \<approx> ===> op \<approx>) op @ op @" |
214 done |
292 done |
215 |
293 |
216 lemma [quot_respect]: |
294 lemma [quot_respect]: |
217 "(op = ===> op = ===> op \<approx> ===> op =) ffold_raw ffold_raw" |
295 "(op = ===> op = ===> op \<approx> ===> op =) ffold_raw ffold_raw" |
218 by (simp add: memb_def[symmetric] ffold_raw_rsp_pre) |
296 by (simp add: memb_def[symmetric] ffold_raw_rsp_pre) |
|
297 |
|
298 lemma concat_rsp_pre: |
|
299 assumes a: "list_rel op \<approx> x x'" |
|
300 and b: "x' \<approx> y'" |
|
301 and c: "list_rel op \<approx> y' y" |
|
302 and d: "\<exists>x\<in>set x. xa \<in> set x" |
|
303 shows "\<exists>x\<in>set y. xa \<in> set x" |
|
304 proof - |
|
305 obtain xb where e: "xb \<in> set x" and f: "xa \<in> set xb" using d by auto |
|
306 have "\<exists>y. y \<in> set x' \<and> xb \<approx> y" by (rule list_rel_find_element[OF e a]) |
|
307 then obtain ya where h: "ya \<in> set x'" and i: "xb \<approx> ya" by auto |
|
308 have j: "ya \<in> set y'" using b h by simp |
|
309 have "\<exists>yb. yb \<in> set y \<and> ya \<approx> yb" by (rule list_rel_find_element[OF j c]) |
|
310 then show ?thesis using f i by auto |
|
311 qed |
|
312 |
|
313 lemma [quot_respect]: |
|
314 shows "(list_rel op \<approx> OOO op \<approx> ===> op \<approx>) concat concat" |
|
315 proof (rule fun_relI, elim pred_compE) |
|
316 fix a b ba bb |
|
317 assume a: "list_rel op \<approx> a ba" |
|
318 assume b: "ba \<approx> bb" |
|
319 assume c: "list_rel op \<approx> bb b" |
|
320 have "\<forall>x. (\<exists>xa\<in>set a. x \<in> set xa) = (\<exists>xa\<in>set b. x \<in> set xa)" proof |
|
321 fix x |
|
322 show "(\<exists>xa\<in>set a. x \<in> set xa) = (\<exists>xa\<in>set b. x \<in> set xa)" proof |
|
323 assume d: "\<exists>xa\<in>set a. x \<in> set xa" |
|
324 show "\<exists>xa\<in>set b. x \<in> set xa" by (rule concat_rsp_pre[OF a b c d]) |
|
325 next |
|
326 assume e: "\<exists>xa\<in>set b. x \<in> set xa" |
|
327 have a': "list_rel op \<approx> ba a" by (rule list_rel_symp[OF list_eq_equivp, OF a]) |
|
328 have b': "bb \<approx> ba" by (rule equivp_symp[OF list_eq_equivp, OF b]) |
|
329 have c': "list_rel op \<approx> b bb" by (rule list_rel_symp[OF list_eq_equivp, OF c]) |
|
330 show "\<exists>xa\<in>set a. x \<in> set xa" by (rule concat_rsp_pre[OF c' b' a' e]) |
|
331 qed |
|
332 qed |
|
333 then show "concat a \<approx> concat b" by simp |
|
334 qed |
219 |
335 |
220 text {* Distributive lattice with bot *} |
336 text {* Distributive lattice with bot *} |
221 |
337 |
222 lemma sub_list_not_eq: |
338 lemma sub_list_not_eq: |
223 "(sub_list x y \<and> \<not> list_eq x y) = (sub_list x y \<and> \<not> sub_list y x)" |
339 "(sub_list x y \<and> \<not> list_eq x y) = (sub_list x y \<and> \<not> sub_list y x)" |
377 abbreviation |
493 abbreviation |
378 fnotin :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" ("_ |\<notin>| _" [50, 51] 50) |
494 fnotin :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" ("_ |\<notin>| _" [50, 51] 50) |
379 where |
495 where |
380 "x |\<notin>| S \<equiv> \<not> (x |\<in>| S)" |
496 "x |\<notin>| S \<equiv> \<not> (x |\<in>| S)" |
381 |
497 |
382 section {* Augmenting an fset -- @{const finsert} *} |
498 section {* Other constants on the Quotient Type *} |
|
499 |
|
500 quotient_definition |
|
501 "fcard :: 'a fset \<Rightarrow> nat" |
|
502 is |
|
503 "fcard_raw" |
|
504 |
|
505 quotient_definition |
|
506 "fmap :: ('a \<Rightarrow> 'b) \<Rightarrow> 'a fset \<Rightarrow> 'b fset" |
|
507 is |
|
508 "map" |
|
509 |
|
510 quotient_definition |
|
511 "fdelete :: 'a fset \<Rightarrow> 'a \<Rightarrow> 'a fset" |
|
512 is "delete_raw" |
|
513 |
|
514 quotient_definition |
|
515 "fset_to_set :: 'a fset \<Rightarrow> 'a set" |
|
516 is "set" |
|
517 |
|
518 quotient_definition |
|
519 "ffold :: ('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a fset \<Rightarrow> 'b" |
|
520 is "ffold_raw" |
|
521 |
|
522 quotient_definition |
|
523 "fconcat :: ('a fset) fset \<Rightarrow> 'a fset" |
|
524 is |
|
525 "concat" |
|
526 |
|
527 text {* Compositional Respectfullness and Preservation *} |
|
528 |
|
529 lemma [quot_respect]: "(list_rel op \<approx> OOO op \<approx>) [] []" |
|
530 by (metis nil_rsp list_rel.simps(1) pred_compI) |
|
531 |
|
532 lemma [quot_preserve]: "(abs_fset \<circ> map f) [] = abs_fset []" |
|
533 by simp |
|
534 |
|
535 lemma [quot_respect]: |
|
536 "(op \<approx> ===> list_rel op \<approx> OOO op \<approx> ===> list_rel op \<approx> OOO op \<approx>) op # op #" |
|
537 apply auto |
|
538 apply (simp add: set_in_eq) |
|
539 apply (rule_tac b="x # b" in pred_compI) |
|
540 apply auto |
|
541 apply (rule_tac b="x # ba" in pred_compI) |
|
542 apply auto |
|
543 done |
|
544 |
|
545 lemma [quot_preserve]: |
|
546 "(rep_fset ---> (map rep_fset \<circ> rep_fset) ---> (abs_fset \<circ> map abs_fset)) op # = finsert" |
|
547 by (simp add: expand_fun_eq Quotient_abs_rep[OF Quotient_fset] |
|
548 abs_o_rep[OF Quotient_fset] map_id finsert_def) |
|
549 |
|
550 lemma [quot_preserve]: |
|
551 "((map rep_fset \<circ> rep_fset) ---> (map rep_fset \<circ> rep_fset) ---> abs_fset \<circ> map abs_fset) op @ = funion" |
|
552 by (simp add: expand_fun_eq Quotient_abs_rep[OF Quotient_fset] |
|
553 abs_o_rep[OF Quotient_fset] map_id sup_fset_def) |
|
554 |
|
555 lemma list_rel_app_l: |
|
556 assumes a: "reflp R" |
|
557 and b: "list_rel R l r" |
|
558 shows "list_rel R (z @ l) (z @ r)" |
|
559 by (induct z) (simp_all add: b, metis a reflp_def) |
|
560 |
|
561 lemma append_rsp2_pre0: |
|
562 assumes a:"list_rel op \<approx> x x'" |
|
563 shows "list_rel op \<approx> (x @ z) (x' @ z)" |
|
564 using a apply (induct x x' rule: list_induct2') |
|
565 apply simp_all |
|
566 apply (rule list_rel_refl) |
|
567 done |
|
568 |
|
569 lemma append_rsp2_pre1: |
|
570 assumes a:"list_rel op \<approx> x x'" |
|
571 shows "list_rel op \<approx> (z @ x) (z @ x')" |
|
572 using a apply (induct x x' arbitrary: z rule: list_induct2') |
|
573 apply (rule list_rel_refl) |
|
574 apply (simp_all del: list_eq.simps) |
|
575 apply (rule list_rel_app_l) |
|
576 apply (simp_all add: reflp_def) |
|
577 done |
|
578 |
|
579 lemma append_rsp2_pre: |
|
580 assumes a:"list_rel op \<approx> x x'" |
|
581 and b: "list_rel op \<approx> z z'" |
|
582 shows "list_rel op \<approx> (x @ z) (x' @ z')" |
|
583 apply (rule list_rel_transp[OF fset_equivp]) |
|
584 apply (rule append_rsp2_pre0) |
|
585 apply (rule a) |
|
586 using b apply (induct z z' rule: list_induct2') |
|
587 apply (simp_all only: append_Nil2) |
|
588 apply (rule list_rel_refl) |
|
589 apply simp_all |
|
590 apply (rule append_rsp2_pre1) |
|
591 apply simp |
|
592 done |
|
593 |
|
594 lemma [quot_respect]: |
|
595 "(list_rel op \<approx> OOO op \<approx> ===> list_rel op \<approx> OOO op \<approx> ===> list_rel op \<approx> OOO op \<approx>) op @ op @" |
|
596 proof (intro fun_relI, elim pred_compE) |
|
597 fix x y z w x' z' y' w' :: "'a list list" |
|
598 assume a:"list_rel op \<approx> x x'" |
|
599 and b: "x' \<approx> y'" |
|
600 and c: "list_rel op \<approx> y' y" |
|
601 assume aa: "list_rel op \<approx> z z'" |
|
602 and bb: "z' \<approx> w'" |
|
603 and cc: "list_rel op \<approx> w' w" |
|
604 have a': "list_rel op \<approx> (x @ z) (x' @ z')" using a aa append_rsp2_pre by auto |
|
605 have b': "x' @ z' \<approx> y' @ w'" using b bb by simp |
|
606 have c': "list_rel op \<approx> (y' @ w') (y @ w)" using c cc append_rsp2_pre by auto |
|
607 have d': "(op \<approx> OO list_rel op \<approx>) (x' @ z') (y @ w)" |
|
608 by (rule pred_compI) (rule b', rule c') |
|
609 show "(list_rel op \<approx> OOO op \<approx>) (x @ z) (y @ w)" |
|
610 by (rule pred_compI) (rule a', rule d') |
|
611 qed |
|
612 |
|
613 text {* Raw theorems. Finsert, memb, singleron, sub_list *} |
383 |
614 |
384 lemma nil_not_cons: |
615 lemma nil_not_cons: |
385 shows "\<not> ([] \<approx> x # xs)" |
616 shows "\<not> ([] \<approx> x # xs)" |
386 and "\<not> (x # xs \<approx> [])" |
617 and "\<not> (x # xs \<approx> [])" |
387 by auto |
618 by auto |
396 |
627 |
397 lemma memb_consI2: |
628 lemma memb_consI2: |
398 shows "memb x xs \<Longrightarrow> memb x (y # xs)" |
629 shows "memb x xs \<Longrightarrow> memb x (y # xs)" |
399 by (simp add: memb_def) |
630 by (simp add: memb_def) |
400 |
631 |
401 section {* Singletons *} |
|
402 |
|
403 lemma singleton_list_eq: |
632 lemma singleton_list_eq: |
404 shows "[x] \<approx> [y] \<longleftrightarrow> x = y" |
633 shows "[x] \<approx> [y] \<longleftrightarrow> x = y" |
405 by (simp add: id_simps) auto |
634 by (simp add: id_simps) auto |
406 |
635 |
407 section {* sub_list *} |
|
408 |
|
409 lemma sub_list_cons: |
636 lemma sub_list_cons: |
410 "sub_list (x # xs) ys = (memb x ys \<and> sub_list xs ys)" |
637 "sub_list (x # xs) ys = (memb x ys \<and> sub_list xs ys)" |
411 by (auto simp add: memb_def sub_list_def) |
638 by (auto simp add: memb_def sub_list_def) |
412 |
639 |
413 section {* Cardinality of finite sets *} |
640 text {* Cardinality of finite sets *} |
414 |
|
415 quotient_definition |
|
416 "fcard :: 'a fset \<Rightarrow> nat" |
|
417 is |
|
418 "fcard_raw" |
|
419 |
641 |
420 lemma fcard_raw_0: |
642 lemma fcard_raw_0: |
421 shows "fcard_raw xs = 0 \<longleftrightarrow> xs \<approx> []" |
643 shows "fcard_raw xs = 0 \<longleftrightarrow> xs \<approx> []" |
422 by (induct xs) (auto simp add: memb_def) |
644 by (induct xs) (auto simp add: memb_def) |
423 |
|
424 |
645 |
425 lemma fcard_raw_not_memb: |
646 lemma fcard_raw_not_memb: |
426 shows "\<not> memb x xs \<longleftrightarrow> fcard_raw (x # xs) = Suc (fcard_raw xs)" |
647 shows "\<not> memb x xs \<longleftrightarrow> fcard_raw (x # xs) = Suc (fcard_raw xs)" |
427 by auto |
648 by auto |
428 |
649 |
524 |
740 |
525 lemma fcard_raw_delete: |
741 lemma fcard_raw_delete: |
526 "fcard_raw (delete_raw xs y) = (if memb y xs then fcard_raw xs - 1 else fcard_raw xs)" |
742 "fcard_raw (delete_raw xs y) = (if memb y xs then fcard_raw xs - 1 else fcard_raw xs)" |
527 by (simp add: fdelete_raw_filter fcard_raw_delete_one) |
743 by (simp add: fdelete_raw_filter fcard_raw_delete_one) |
528 |
744 |
529 |
|
530 |
|
531 |
|
532 |
|
533 lemma finter_raw_empty: |
745 lemma finter_raw_empty: |
534 "finter_raw l [] = []" |
746 "finter_raw l [] = []" |
535 by (induct l) (simp_all add: not_memb_nil) |
747 by (induct l) (simp_all add: not_memb_nil) |
536 |
748 |
537 section {* Constants on the Quotient Type *} |
|
538 |
|
539 quotient_definition |
|
540 "fdelete :: 'a fset \<Rightarrow> 'a \<Rightarrow> 'a fset" |
|
541 is "delete_raw" |
|
542 |
|
543 quotient_definition |
|
544 "fset_to_set :: 'a fset \<Rightarrow> 'a set" |
|
545 is "set" |
|
546 |
|
547 quotient_definition |
|
548 "ffold :: ('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a fset \<Rightarrow> 'b" |
|
549 is "ffold_raw" |
|
550 |
|
551 lemma set_cong: |
749 lemma set_cong: |
552 shows "(set x = set y) = (x \<approx> y)" |
750 shows "(set x = set y) = (x \<approx> y)" |
553 by auto |
751 by auto |
554 |
752 |
555 lemma inj_map_eq_iff: |
753 lemma inj_map_eq_iff: |
556 "inj f \<Longrightarrow> (map f l \<approx> map f m) = (l \<approx> m)" |
754 "inj f \<Longrightarrow> (map f l \<approx> map f m) = (l \<approx> m)" |
557 by (simp add: expand_set_eq[symmetric] inj_image_eq_iff) |
755 by (simp add: expand_set_eq[symmetric] inj_image_eq_iff) |
558 |
|
559 quotient_definition |
|
560 "fconcat :: ('a fset) fset \<Rightarrow> 'a fset" |
|
561 is |
|
562 "concat" |
|
563 |
|
564 |
756 |
565 text {* alternate formulation with a different decomposition principle |
757 text {* alternate formulation with a different decomposition principle |
566 and a proof of equivalence *} |
758 and a proof of equivalence *} |
567 |
759 |
568 inductive |
760 inductive |
911 and "\<And>xs1 xs2 xs3. \<lbrakk>xs1 = xs2; P xs1 xs2; xs2 = xs3; P xs2 xs3\<rbrakk> \<Longrightarrow> P xs1 xs3" |
1103 and "\<And>xs1 xs2 xs3. \<lbrakk>xs1 = xs2; P xs1 xs2; xs2 = xs3; P xs2 xs3\<rbrakk> \<Longrightarrow> P xs1 xs3" |
912 shows "P x1 x2" |
1104 shows "P x1 x2" |
913 using assms |
1105 using assms |
914 by (lifting list_eq2.induct[simplified list_eq2_equiv[symmetric]]) |
1106 by (lifting list_eq2.induct[simplified list_eq2_equiv[symmetric]]) |
915 |
1107 |
|
1108 text {* concat *} |
|
1109 |
|
1110 lemma fconcat_empty: |
|
1111 shows "fconcat {||} = {||}" |
|
1112 by (lifting concat.simps(1)) |
|
1113 |
|
1114 lemma fconcat_insert: |
|
1115 shows "fconcat (finsert x S) = x |\<union>| fconcat S" |
|
1116 by (lifting concat.simps(2)) |
|
1117 |
|
1118 lemma "fconcat (xs |\<union>| ys) = fconcat xs |\<union>| fconcat ys" |
|
1119 by (lifting concat_append) |
|
1120 |
916 ML {* |
1121 ML {* |
917 fun dest_fsetT (Type ("FSet.fset", [T])) = T |
1122 fun dest_fsetT (Type ("FSet.fset", [T])) = T |
918 | dest_fsetT T = raise TYPE ("dest_fsetT: fset type expected", [T], []); |
1123 | dest_fsetT T = raise TYPE ("dest_fsetT: fset type expected", [T], []); |
919 *} |
1124 *} |
920 |
1125 |