# HG changeset patch # User Cezary Kaliszyk # Date 1272009653 -7200 # Node ID c4f5823f282d5f5eff26544db9c6f56897b883bb # Parent 8e58a63ac975d736fd8badb56c9b3d87ee3d445c Finite set theory diff -r 8e58a63ac975 -r c4f5823f282d src/HOL/IsaMakefile --- a/src/HOL/IsaMakefile Thu Apr 22 22:12:12 2010 +0200 +++ b/src/HOL/IsaMakefile Fri Apr 23 10:00:53 2010 +0200 @@ -1294,6 +1294,7 @@ HOL-Quotient_Examples: HOL $(LOG)/HOL-Quotient_Examples.gz $(LOG)/HOL-Quotient_Examples.gz: $(OUT)/HOL \ + Quotient_Examples/FSet.thy \ Quotient_Examples/LarryInt.thy Quotient_Examples/LarryDatatype.thy @$(ISABELLE_TOOL) usedir $(OUT)/HOL Quotient_Examples diff -r 8e58a63ac975 -r c4f5823f282d src/HOL/Quotient_Examples/FSet.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Quotient_Examples/FSet.thy Fri Apr 23 10:00:53 2010 +0200 @@ -0,0 +1,1113 @@ +(* Title: Quotient.thy + Author: Cezary Kaliszyk + Author: Christian Urban + + provides a reasoning infrastructure for the type of finite sets +*) +theory FSet +imports Quotient Quotient_List List +begin + +text {* Definiton of List relation and the quotient type *} + +fun + list_eq :: "'a list \ 'a list \ bool" (infix "\" 50) +where + "list_eq xs ys = (\x. x \ set xs \ x \ set ys)" + +lemma list_eq_equivp: + shows "equivp list_eq" + unfolding equivp_reflp_symp_transp + unfolding reflp_def symp_def transp_def + by auto + +quotient_type + 'a fset = "'a list" / "list_eq" + by (rule list_eq_equivp) + +text {* Raw definitions *} + +definition + memb :: "'a \ 'a list \ bool" +where + "memb x xs \ x \ set xs" + +definition + sub_list :: "'a list \ 'a list \ bool" +where + "sub_list xs ys \ (\x. x \ set xs \ x \ set ys)" + +fun + fcard_raw :: "'a list \ nat" +where + fcard_raw_nil: "fcard_raw [] = 0" +| fcard_raw_cons: "fcard_raw (x # xs) = (if memb x xs then fcard_raw xs else Suc (fcard_raw xs))" + +primrec + finter_raw :: "'a list \ 'a list \ 'a list" +where + "finter_raw [] l = []" +| "finter_raw (h # t) l = + (if memb h l then h # (finter_raw t l) else finter_raw t l)" + +fun + delete_raw :: "'a list \ 'a \ 'a list" +where + "delete_raw [] x = []" +| "delete_raw (a # A) x = (if (a = x) then delete_raw A x else a # (delete_raw A x))" + +definition + rsp_fold +where + "rsp_fold f = (\u v w. (f u (f v w) = f v (f u w)))" + +primrec + ffold_raw :: "('a \ 'b \ 'b) \ 'b \ 'a list \ 'b" +where + "ffold_raw f z [] = z" +| "ffold_raw f z (a # A) = + (if (rsp_fold f) then + if memb a A then ffold_raw f z A + else f a (ffold_raw f z A) + else z)" + +text {* Composition Quotient *} + +lemma list_rel_refl: + shows "(list_rel op \) r r" + by (rule list_rel_refl) (metis equivp_def fset_equivp) + +lemma compose_list_refl: + shows "(list_rel op \ OOO op \) r r" +proof + show c: "list_rel op \ r r" by (rule list_rel_refl) + have d: "r \ r" by (rule equivp_reflp[OF fset_equivp]) + show b: "(op \ OO list_rel op \) r r" by (rule pred_compI) (rule d, rule c) +qed + +lemma Quotient_fset_list: + shows "Quotient (list_rel op \) (map abs_fset) (map rep_fset)" + by (fact list_quotient[OF Quotient_fset]) + +lemma set_in_eq: "(\e. ((e \ A) \ (e \ B))) \ A = B" + by (rule eq_reflection) auto + +lemma map_rel_cong: "b \ ba \ map f b \ map f ba" + unfolding list_eq.simps + by (simp only: set_map set_in_eq) + +lemma quotient_compose_list[quot_thm]: + shows "Quotient ((list_rel op \) OOO (op \)) + (abs_fset \ (map abs_fset)) ((map rep_fset) \ rep_fset)" + unfolding Quotient_def comp_def +proof (intro conjI allI) + fix a r s + show "abs_fset (map abs_fset (map rep_fset (rep_fset a))) = a" + by (simp add: abs_o_rep[OF Quotient_fset] Quotient_abs_rep[OF Quotient_fset] map_id) + have b: "list_rel op \ (map rep_fset (rep_fset a)) (map rep_fset (rep_fset a))" + by (rule list_rel_refl) + have c: "(op \ OO list_rel op \) (map rep_fset (rep_fset a)) (map rep_fset (rep_fset a))" + by (rule, rule equivp_reflp[OF fset_equivp]) (rule b) + show "(list_rel op \ OOO op \) (map rep_fset (rep_fset a)) (map rep_fset (rep_fset a))" + by (rule, rule list_rel_refl) (rule c) + show "(list_rel op \ OOO op \) r s = ((list_rel op \ OOO op \) r r \ + (list_rel op \ OOO op \) s s \ abs_fset (map abs_fset r) = abs_fset (map abs_fset s))" + proof (intro iffI conjI) + show "(list_rel op \ OOO op \) r r" by (rule compose_list_refl) + show "(list_rel op \ OOO op \) s s" by (rule compose_list_refl) + next + assume a: "(list_rel op \ OOO op \) r s" + then have b: "map abs_fset r \ map abs_fset s" proof (elim pred_compE) + fix b ba + assume c: "list_rel op \ r b" + assume d: "b \ ba" + assume e: "list_rel op \ ba s" + have f: "map abs_fset r = map abs_fset b" + using Quotient_rel[OF Quotient_fset_list] c by blast + have "map abs_fset ba = map abs_fset s" + using Quotient_rel[OF Quotient_fset_list] e by blast + then have g: "map abs_fset s = map abs_fset ba" by simp + then show "map abs_fset r \ map abs_fset s" using d f map_rel_cong by simp + qed + then show "abs_fset (map abs_fset r) = abs_fset (map abs_fset s)" + using Quotient_rel[OF Quotient_fset] by blast + next + assume a: "(list_rel op \ OOO op \) r r \ (list_rel op \ OOO op \) s s + \ abs_fset (map abs_fset r) = abs_fset (map abs_fset s)" + then have s: "(list_rel op \ OOO op \) s s" by simp + have d: "map abs_fset r \ map abs_fset s" + by (subst Quotient_rel[OF Quotient_fset]) (simp add: a) + have b: "map rep_fset (map abs_fset r) \ map rep_fset (map abs_fset s)" + by (rule map_rel_cong[OF d]) + have y: "list_rel op \ (map rep_fset (map abs_fset s)) s" + by (fact rep_abs_rsp_left[OF Quotient_fset_list, OF list_rel_refl[of s]]) + have c: "(op \ OO list_rel op \) (map rep_fset (map abs_fset r)) s" + by (rule pred_compI) (rule b, rule y) + have z: "list_rel op \ r (map rep_fset (map abs_fset r))" + by (fact rep_abs_rsp[OF Quotient_fset_list, OF list_rel_refl[of r]]) + then show "(list_rel op \ OOO op \) r s" + using a c pred_compI by simp + qed +qed + +text {* Respectfullness *} + +lemma [quot_respect]: + shows "(op \ ===> op \ ===> op \) op @ op @" + by auto + +lemma [quot_respect]: + shows "(op \ ===> op \ ===> op =) sub_list sub_list" + by (auto simp add: sub_list_def) + +lemma memb_rsp[quot_respect]: + shows "(op = ===> op \ ===> op =) memb memb" + by (auto simp add: memb_def) + +lemma nil_rsp[quot_respect]: + shows "[] \ []" + by simp + +lemma cons_rsp[quot_respect]: + shows "(op = ===> op \ ===> op \) op # op #" + by simp + +lemma map_rsp[quot_respect]: + shows "(op = ===> op \ ===> op \) map map" + by auto + +lemma set_rsp[quot_respect]: + "(op \ ===> op =) set set" + by auto + +lemma list_equiv_rsp[quot_respect]: + shows "(op \ ===> op \ ===> op =) op \ op \" + by auto + +lemma not_memb_nil: + shows "\ memb x []" + by (simp add: memb_def) + +lemma memb_cons_iff: + shows "memb x (y # xs) = (x = y \ memb x xs)" + by (induct xs) (auto simp add: memb_def) + +lemma memb_finter_raw: + "memb x (finter_raw xs ys) \ memb x xs \ memb x ys" + by (induct xs) (auto simp add: not_memb_nil memb_cons_iff) + +lemma [quot_respect]: + "(op \ ===> op \ ===> op \) finter_raw finter_raw" + by (simp add: memb_def[symmetric] memb_finter_raw) + +lemma memb_delete_raw: + "memb x (delete_raw xs y) = (memb x xs \ x \ y)" + by (induct xs arbitrary: x y) (auto simp add: memb_def) + +lemma [quot_respect]: + "(op \ ===> op = ===> op \) delete_raw delete_raw" + by (simp add: memb_def[symmetric] memb_delete_raw) + +lemma fcard_raw_gt_0: + assumes a: "x \ set xs" + shows "0 < fcard_raw xs" + using a by (induct xs) (auto simp add: memb_def) + +lemma fcard_raw_delete_one: + shows "fcard_raw ([x \ xs. x \ y]) = (if memb y xs then fcard_raw xs - 1 else fcard_raw xs)" + by (induct xs) (auto dest: fcard_raw_gt_0 simp add: memb_def) + +lemma fcard_raw_rsp_aux: + assumes a: "xs \ ys" + shows "fcard_raw xs = fcard_raw ys" + using a + apply (induct xs arbitrary: ys) + apply (auto simp add: memb_def) + apply (subgoal_tac "\x. (x \ set xs) = (x \ set ys)") + apply (auto) + apply (drule_tac x="x" in spec) + apply (blast) + apply (drule_tac x="[x \ ys. x \ a]" in meta_spec) + apply (simp add: fcard_raw_delete_one memb_def) + apply (case_tac "a \ set ys") + apply (simp only: if_True) + apply (subgoal_tac "\x. (x \ set xs) = (x \ set ys \ x \ a)") + apply (drule Suc_pred'[OF fcard_raw_gt_0]) + apply (auto) + done + +lemma fcard_raw_rsp[quot_respect]: + shows "(op \ ===> op =) fcard_raw fcard_raw" + by (simp add: fcard_raw_rsp_aux) + +lemma memb_absorb: + shows "memb x xs \ x # xs \ xs" + by (induct xs) (auto simp add: memb_def) + +lemma none_memb_nil: + "(\x. \ memb x xs) = (xs \ [])" + by (simp add: memb_def) + +lemma not_memb_delete_raw_ident: + shows "\ memb x xs \ delete_raw xs x = xs" + by (induct xs) (auto simp add: memb_def) + +lemma memb_commute_ffold_raw: + "rsp_fold f \ memb h b \ ffold_raw f z b = f h (ffold_raw f z (delete_raw b h))" + apply (induct b) + apply (simp_all add: not_memb_nil) + apply (auto) + apply (simp_all add: memb_delete_raw not_memb_delete_raw_ident rsp_fold_def memb_cons_iff) + done + +lemma ffold_raw_rsp_pre: + "\e. memb e a = memb e b \ ffold_raw f z a = ffold_raw f z b" + apply (induct a arbitrary: b) + apply (simp add: memb_absorb memb_def none_memb_nil) + apply (simp) + apply (rule conjI) + apply (rule_tac [!] impI) + apply (rule_tac [!] conjI) + apply (rule_tac [!] impI) + apply (subgoal_tac "\e. memb e a2 = memb e b") + apply (simp) + apply (simp add: memb_cons_iff memb_def) + apply (auto)[1] + apply (drule_tac x="e" in spec) + apply (blast) + apply (case_tac b) + apply (simp_all) + apply (subgoal_tac "ffold_raw f z b = f a1 (ffold_raw f z (delete_raw b a1))") + apply (simp only:) + apply (rule_tac f="f a1" in arg_cong) + apply (subgoal_tac "\e. memb e a2 = memb e (delete_raw b a1)") + apply (simp) + apply (simp add: memb_delete_raw) + apply (auto simp add: memb_cons_iff)[1] + apply (erule memb_commute_ffold_raw) + apply (drule_tac x="a1" in spec) + apply (simp add: memb_cons_iff) + apply (simp add: memb_cons_iff) + apply (case_tac b) + apply (simp_all) + done + +lemma [quot_respect]: + "(op = ===> op = ===> op \ ===> op =) ffold_raw ffold_raw" + by (simp add: memb_def[symmetric] ffold_raw_rsp_pre) + +lemma concat_rsp_pre: + assumes a: "list_rel op \ x x'" + and b: "x' \ y'" + and c: "list_rel op \ y' y" + and d: "\x\set x. xa \ set x" + shows "\x\set y. xa \ set x" +proof - + obtain xb where e: "xb \ set x" and f: "xa \ set xb" using d by auto + have "\y. y \ set x' \ xb \ y" by (rule list_rel_find_element[OF e a]) + then obtain ya where h: "ya \ set x'" and i: "xb \ ya" by auto + have j: "ya \ set y'" using b h by simp + have "\yb. yb \ set y \ ya \ yb" by (rule list_rel_find_element[OF j c]) + then show ?thesis using f i by auto +qed + +lemma [quot_respect]: + shows "(list_rel op \ OOO op \ ===> op \) concat concat" +proof (rule fun_relI, elim pred_compE) + fix a b ba bb + assume a: "list_rel op \ a ba" + assume b: "ba \ bb" + assume c: "list_rel op \ bb b" + have "\x. (\xa\set a. x \ set xa) = (\xa\set b. x \ set xa)" proof + fix x + show "(\xa\set a. x \ set xa) = (\xa\set b. x \ set xa)" proof + assume d: "\xa\set a. x \ set xa" + show "\xa\set b. x \ set xa" by (rule concat_rsp_pre[OF a b c d]) + next + assume e: "\xa\set b. x \ set xa" + have a': "list_rel op \ ba a" by (rule list_rel_symp[OF list_eq_equivp, OF a]) + have b': "bb \ ba" by (rule equivp_symp[OF list_eq_equivp, OF b]) + have c': "list_rel op \ b bb" by (rule list_rel_symp[OF list_eq_equivp, OF c]) + show "\xa\set a. x \ set xa" by (rule concat_rsp_pre[OF c' b' a' e]) + qed + qed + then show "concat a \ concat b" by simp +qed + +text {* Distributive lattice with bot *} + +lemma sub_list_not_eq: + "(sub_list x y \ \ list_eq x y) = (sub_list x y \ \ sub_list y x)" + by (auto simp add: sub_list_def) + +lemma sub_list_refl: + "sub_list x x" + by (simp add: sub_list_def) + +lemma sub_list_trans: + "sub_list x y \ sub_list y z \ sub_list x z" + by (simp add: sub_list_def) + +lemma sub_list_empty: + "sub_list [] x" + by (simp add: sub_list_def) + +lemma sub_list_append_left: + "sub_list x (x @ y)" + by (simp add: sub_list_def) + +lemma sub_list_append_right: + "sub_list y (x @ y)" + by (simp add: sub_list_def) + +lemma sub_list_inter_left: + shows "sub_list (finter_raw x y) x" + by (simp add: sub_list_def memb_def[symmetric] memb_finter_raw) + +lemma sub_list_inter_right: + shows "sub_list (finter_raw x y) y" + by (simp add: sub_list_def memb_def[symmetric] memb_finter_raw) + +lemma sub_list_list_eq: + "sub_list x y \ sub_list y x \ list_eq x y" + unfolding sub_list_def list_eq.simps by blast + +lemma sub_list_append: + "sub_list y x \ sub_list z x \ sub_list (y @ z) x" + unfolding sub_list_def by auto + +lemma sub_list_inter: + "sub_list x y \ sub_list x z \ sub_list x (finter_raw y z)" + by (simp add: sub_list_def memb_def[symmetric] memb_finter_raw) + +lemma append_inter_distrib: + "x @ (finter_raw y z) \ finter_raw (x @ y) (x @ z)" + apply (induct x) + apply (simp_all add: memb_def) + apply (simp add: memb_def[symmetric] memb_finter_raw) + by (auto simp add: memb_def) + +instantiation fset :: (type) "{bot,distrib_lattice}" +begin + +quotient_definition + "bot :: 'a fset" is "[] :: 'a list" + +abbreviation + fempty ("{||}") +where + "{||} \ bot :: 'a fset" + +quotient_definition + "less_eq_fset \ ('a fset \ 'a fset \ bool)" +is + "sub_list \ ('a list \ 'a list \ bool)" + +abbreviation + f_subset_eq :: "'a fset \ 'a fset \ bool" (infix "|\|" 50) +where + "xs |\| ys \ xs \ ys" + +definition + less_fset: + "(xs :: 'a fset) < ys \ xs \ ys \ xs \ ys" + +abbreviation + f_subset :: "'a fset \ 'a fset \ bool" (infix "|\|" 50) +where + "xs |\| ys \ xs < ys" + +quotient_definition + "sup \ ('a fset \ 'a fset \ 'a fset)" +is + "(op @) \ ('a list \ 'a list \ 'a list)" + +abbreviation + funion (infixl "|\|" 65) +where + "xs |\| ys \ sup (xs :: 'a fset) ys" + +quotient_definition + "inf \ ('a fset \ 'a fset \ 'a fset)" +is + "finter_raw \ ('a list \ 'a list \ 'a list)" + +abbreviation + finter (infixl "|\|" 65) +where + "xs |\| ys \ inf (xs :: 'a fset) ys" + +instance +proof + fix x y z :: "'a fset" + show "(x |\| y) = (x |\| y \ \ y |\| x)" + unfolding less_fset by (lifting sub_list_not_eq) + show "x |\| x" by (lifting sub_list_refl) + show "{||} |\| x" by (lifting sub_list_empty) + show "x |\| x |\| y" by (lifting sub_list_append_left) + show "y |\| x |\| y" by (lifting sub_list_append_right) + show "x |\| y |\| x" by (lifting sub_list_inter_left) + show "x |\| y |\| y" by (lifting sub_list_inter_right) + show "x |\| (y |\| z) = x |\| y |\| (x |\| z)" by (lifting append_inter_distrib) +next + fix x y z :: "'a fset" + assume a: "x |\| y" + assume b: "y |\| z" + show "x |\| z" using a b by (lifting sub_list_trans) +next + fix x y :: "'a fset" + assume a: "x |\| y" + assume b: "y |\| x" + show "x = y" using a b by (lifting sub_list_list_eq) +next + fix x y z :: "'a fset" + assume a: "y |\| x" + assume b: "z |\| x" + show "y |\| z |\| x" using a b by (lifting sub_list_append) +next + fix x y z :: "'a fset" + assume a: "x |\| y" + assume b: "x |\| z" + show "x |\| y |\| z" using a b by (lifting sub_list_inter) +qed + +end + +section {* Finsert and Membership *} + +quotient_definition + "finsert :: 'a \ 'a fset \ 'a fset" +is "op #" + +syntax + "@Finset" :: "args => 'a fset" ("{|(_)|}") + +translations + "{|x, xs|}" == "CONST finsert x {|xs|}" + "{|x|}" == "CONST finsert x {||}" + +quotient_definition + fin (infix "|\|" 50) +where + "fin :: 'a \ 'a fset \ bool" is "memb" + +abbreviation + fnotin :: "'a \ 'a fset \ bool" (infix "|\|" 50) +where + "x |\| S \ \ (x |\| S)" + +section {* Other constants on the Quotient Type *} + +quotient_definition + "fcard :: 'a fset \ nat" +is + "fcard_raw" + +quotient_definition + "fmap :: ('a \ 'b) \ 'a fset \ 'b fset" +is + "map" + +quotient_definition + "fdelete :: 'a fset \ 'a \ 'a fset" + is "delete_raw" + +quotient_definition + "fset_to_set :: 'a fset \ 'a set" + is "set" + +quotient_definition + "ffold :: ('a \ 'b \ 'b) \ 'b \ 'a fset \ 'b" + is "ffold_raw" + +quotient_definition + "fconcat :: ('a fset) fset \ 'a fset" +is + "concat" + +text {* Compositional Respectfullness and Preservation *} + +lemma [quot_respect]: "(list_rel op \ OOO op \) [] []" + by (fact compose_list_refl) + +lemma [quot_preserve]: "(abs_fset \ map f) [] = abs_fset []" + by simp + +lemma [quot_respect]: + "(op \ ===> list_rel op \ OOO op \ ===> list_rel op \ OOO op \) op # op #" + apply auto + apply (simp add: set_in_eq) + apply (rule_tac b="x # b" in pred_compI) + apply auto + apply (rule_tac b="x # ba" in pred_compI) + apply auto + done + +lemma [quot_preserve]: + "(rep_fset ---> (map rep_fset \ rep_fset) ---> (abs_fset \ map abs_fset)) op # = finsert" + by (simp add: expand_fun_eq Quotient_abs_rep[OF Quotient_fset] + abs_o_rep[OF Quotient_fset] map_id finsert_def) + +lemma [quot_preserve]: + "((map rep_fset \ rep_fset) ---> (map rep_fset \ rep_fset) ---> (abs_fset \ map abs_fset)) op @ = funion" + by (simp add: expand_fun_eq Quotient_abs_rep[OF Quotient_fset] + abs_o_rep[OF Quotient_fset] map_id sup_fset_def) + +lemma list_rel_app_l: + assumes a: "reflp R" + and b: "list_rel R l r" + shows "list_rel R (z @ l) (z @ r)" + by (induct z) (simp_all add: b rev_iffD1[OF a meta_eq_to_obj_eq[OF reflp_def]]) + +lemma append_rsp2_pre0: + assumes a:"list_rel op \ x x'" + shows "list_rel op \ (x @ z) (x' @ z)" + using a apply (induct x x' rule: list_induct2') + by simp_all (rule list_rel_refl) + +lemma append_rsp2_pre1: + assumes a:"list_rel op \ x x'" + shows "list_rel op \ (z @ x) (z @ x')" + using a apply (induct x x' arbitrary: z rule: list_induct2') + apply (rule list_rel_refl) + apply (simp_all del: list_eq.simps) + apply (rule list_rel_app_l) + apply (simp_all add: reflp_def) + done + +lemma append_rsp2_pre: + assumes a:"list_rel op \ x x'" + and b: "list_rel op \ z z'" + shows "list_rel op \ (x @ z) (x' @ z')" + apply (rule list_rel_transp[OF fset_equivp]) + apply (rule append_rsp2_pre0) + apply (rule a) + using b apply (induct z z' rule: list_induct2') + apply (simp_all only: append_Nil2) + apply (rule list_rel_refl) + apply simp_all + apply (rule append_rsp2_pre1) + apply simp + done + +lemma [quot_respect]: + "(list_rel op \ OOO op \ ===> list_rel op \ OOO op \ ===> list_rel op \ OOO op \) op @ op @" +proof (intro fun_relI, elim pred_compE) + fix x y z w x' z' y' w' :: "'a list list" + assume a:"list_rel op \ x x'" + and b: "x' \ y'" + and c: "list_rel op \ y' y" + assume aa: "list_rel op \ z z'" + and bb: "z' \ w'" + and cc: "list_rel op \ w' w" + have a': "list_rel op \ (x @ z) (x' @ z')" using a aa append_rsp2_pre by auto + have b': "x' @ z' \ y' @ w'" using b bb by simp + have c': "list_rel op \ (y' @ w') (y @ w)" using c cc append_rsp2_pre by auto + have d': "(op \ OO list_rel op \) (x' @ z') (y @ w)" + by (rule pred_compI) (rule b', rule c') + show "(list_rel op \ OOO op \) (x @ z) (y @ w)" + by (rule pred_compI) (rule a', rule d') +qed + +text {* Raw theorems. Finsert, memb, singleron, sub_list *} + +lemma nil_not_cons: + shows "\ ([] \ x # xs)" + and "\ (x # xs \ [])" + by auto + +lemma no_memb_nil: + "(\x. \ memb x xs) = (xs = [])" + by (simp add: memb_def) + +lemma memb_consI1: + shows "memb x (x # xs)" + by (simp add: memb_def) + +lemma memb_consI2: + shows "memb x xs \ memb x (y # xs)" + by (simp add: memb_def) + +lemma singleton_list_eq: + shows "[x] \ [y] \ x = y" + by (simp add: id_simps) auto + +lemma sub_list_cons: + "sub_list (x # xs) ys = (memb x ys \ sub_list xs ys)" + by (auto simp add: memb_def sub_list_def) + +text {* Cardinality of finite sets *} + +lemma fcard_raw_0: + shows "fcard_raw xs = 0 \ xs \ []" + by (induct xs) (auto simp add: memb_def) + +lemma fcard_raw_not_memb: + shows "\ memb x xs \ fcard_raw (x # xs) = Suc (fcard_raw xs)" + by auto + +lemma fcard_raw_suc: + assumes a: "fcard_raw xs = Suc n" + shows "\x ys. \ (memb x ys) \ xs \ (x # ys) \ fcard_raw ys = n" + using a + by (induct xs) (auto simp add: memb_def split: if_splits) + +lemma singleton_fcard_1: + shows "set xs = {x} \ fcard_raw xs = 1" + by (induct xs) (auto simp add: memb_def subset_insert) + +lemma fcard_raw_1: + shows "fcard_raw xs = 1 \ (\x. xs \ [x])" + apply (auto dest!: fcard_raw_suc) + apply (simp add: fcard_raw_0) + apply (rule_tac x="x" in exI) + apply simp + apply (subgoal_tac "set xs = {x}") + apply (drule singleton_fcard_1) + apply auto + done + +lemma fcard_raw_suc_memb: + assumes a: "fcard_raw A = Suc n" + shows "\a. memb a A" + using a + by (induct A) (auto simp add: memb_def) + +lemma memb_card_not_0: + assumes a: "memb a A" + shows "\(fcard_raw A = 0)" +proof - + have "\(\x. \ memb x A)" using a by auto + then have "\A \ []" using none_memb_nil[of A] by simp + then show ?thesis using fcard_raw_0[of A] by simp +qed + +text {* fmap *} + +lemma map_append: + "map f (xs @ ys) \ (map f xs) @ (map f ys)" + by simp + +lemma memb_append: + "memb x (xs @ ys) \ memb x xs \ memb x ys" + by (induct xs) (simp_all add: not_memb_nil memb_cons_iff) + +lemma cons_left_comm: + "x # y # xs \ y # x # xs" + by auto + +lemma cons_left_idem: + "x # x # xs \ x # xs" + by auto + +lemma fset_raw_strong_cases: + "(xs = []) \ (\x ys. ((\ memb x ys) \ (xs \ x # ys)))" + apply (induct xs) + apply (simp) + apply (rule disjI2) + apply (erule disjE) + apply (rule_tac x="a" in exI) + apply (rule_tac x="[]" in exI) + apply (simp add: memb_def) + apply (erule exE)+ + apply (case_tac "x = a") + apply (rule_tac x="a" in exI) + apply (rule_tac x="ys" in exI) + apply (simp) + apply (rule_tac x="x" in exI) + apply (rule_tac x="a # ys" in exI) + apply (auto simp add: memb_def) + done + +section {* deletion *} + +lemma memb_delete_raw_ident: + shows "\ memb x (delete_raw xs x)" + by (induct xs) (auto simp add: memb_def) + +lemma fset_raw_delete_raw_cases: + "xs = [] \ (\x. memb x xs \ xs \ x # delete_raw xs x)" + by (induct xs) (auto simp add: memb_def) + +lemma fdelete_raw_filter: + "delete_raw xs y = [x \ xs. x \ y]" + by (induct xs) simp_all + +lemma fcard_raw_delete: + "fcard_raw (delete_raw xs y) = (if memb y xs then fcard_raw xs - 1 else fcard_raw xs)" + by (simp add: fdelete_raw_filter fcard_raw_delete_one) + +lemma finter_raw_empty: + "finter_raw l [] = []" + by (induct l) (simp_all add: not_memb_nil) + +lemma set_cong: + shows "(set x = set y) = (x \ y)" + by auto + +lemma inj_map_eq_iff: + "inj f \ (map f l \ map f m) = (l \ m)" + by (simp add: expand_set_eq[symmetric] inj_image_eq_iff) + +text {* alternate formulation with a different decomposition principle + and a proof of equivalence *} + +inductive + list_eq2 +where + "list_eq2 (a # b # xs) (b # a # xs)" +| "list_eq2 [] []" +| "list_eq2 xs ys \ list_eq2 ys xs" +| "list_eq2 (a # a # xs) (a # xs)" +| "list_eq2 xs ys \ list_eq2 (a # xs) (a # ys)" +| "\list_eq2 xs1 xs2; list_eq2 xs2 xs3\ \ list_eq2 xs1 xs3" + +lemma list_eq2_refl: + shows "list_eq2 xs xs" + by (induct xs) (auto intro: list_eq2.intros) + +lemma cons_delete_list_eq2: + shows "list_eq2 (a # (delete_raw A a)) (if memb a A then A else a # A)" + apply (induct A) + apply (simp add: memb_def list_eq2_refl) + apply (case_tac "memb a (aa # A)") + apply (simp_all only: memb_cons_iff) + apply (case_tac [!] "a = aa") + apply (simp_all) + apply (case_tac "memb a A") + apply (auto simp add: memb_def)[2] + apply (metis list_eq2.intros(3) list_eq2.intros(4) list_eq2.intros(5) list_eq2.intros(6)) + apply (metis list_eq2.intros(1) list_eq2.intros(5) list_eq2.intros(6)) + apply (auto simp add: list_eq2_refl not_memb_delete_raw_ident) + done + +lemma memb_delete_list_eq2: + assumes a: "memb e r" + shows "list_eq2 (e # delete_raw r e) r" + using a cons_delete_list_eq2[of e r] + by simp + +lemma delete_raw_rsp: + "xs \ ys \ delete_raw xs x \ delete_raw ys x" + by (simp add: memb_def[symmetric] memb_delete_raw) + +lemma list_eq2_equiv: + "(l \ r) \ (list_eq2 l r)" +proof + show "list_eq2 l r \ l \ r" by (induct rule: list_eq2.induct) auto +next + { + fix n + assume a: "fcard_raw l = n" and b: "l \ r" + have "list_eq2 l r" + using a b + proof (induct n arbitrary: l r) + case 0 + have "fcard_raw l = 0" by fact + then have "\x. \ memb x l" using memb_card_not_0[of _ l] by auto + then have z: "l = []" using no_memb_nil by auto + then have "r = []" using `l \ r` by simp + then show ?case using z list_eq2_refl by simp + next + case (Suc m) + have b: "l \ r" by fact + have d: "fcard_raw l = Suc m" by fact + have "\a. memb a l" by (rule fcard_raw_suc_memb[OF d]) + then obtain a where e: "memb a l" by auto + then have e': "memb a r" using list_eq.simps[simplified memb_def[symmetric], of l r] b by auto + have f: "fcard_raw (delete_raw l a) = m" using fcard_raw_delete[of l a] e d by simp + have g: "delete_raw l a \ delete_raw r a" using delete_raw_rsp[OF b] by simp + have g': "list_eq2 (delete_raw l a) (delete_raw r a)" by (rule Suc.hyps[OF f g]) + have h: "list_eq2 (a # delete_raw l a) (a # delete_raw r a)" by (rule list_eq2.intros(5)[OF g']) + have i: "list_eq2 l (a # delete_raw l a)" + by (rule list_eq2.intros(3)[OF memb_delete_list_eq2[OF e]]) + have "list_eq2 l (a # delete_raw r a)" by (rule list_eq2.intros(6)[OF i h]) + then show ?case using list_eq2.intros(6)[OF _ memb_delete_list_eq2[OF e']] by simp + qed + } + then show "l \ r \ list_eq2 l r" by blast +qed + +text {* Lifted theorems *} + +lemma not_fin_fnil: "x |\| {||}" + by (lifting not_memb_nil) + +lemma fin_finsert_iff[simp]: + "x |\| finsert y S = (x = y \ x |\| S)" + by (lifting memb_cons_iff) + +lemma + shows finsertI1: "x |\| finsert x S" + and finsertI2: "x |\| S \ x |\| finsert y S" + by (lifting memb_consI1, lifting memb_consI2) + +lemma finsert_absorb[simp]: + shows "x |\| S \ finsert x S = S" + by (lifting memb_absorb) + +lemma fempty_not_finsert[simp]: + "{||} \ finsert x S" + "finsert x S \ {||}" + by (lifting nil_not_cons) + +lemma finsert_left_comm: + "finsert x (finsert y S) = finsert y (finsert x S)" + by (lifting cons_left_comm) + +lemma finsert_left_idem: + "finsert x (finsert x S) = finsert x S" + by (lifting cons_left_idem) + +lemma fsingleton_eq[simp]: + shows "{|x|} = {|y|} \ x = y" + by (lifting singleton_list_eq) + +text {* fset_to_set *} + +lemma fset_to_set_simps[simp]: + "fset_to_set {||} = ({} :: 'a set)" + "fset_to_set (finsert (h :: 'a) t) = insert h (fset_to_set t)" + by (lifting set.simps) + +lemma in_fset_to_set: + "x \ fset_to_set S \ x |\| S" + by (lifting memb_def[symmetric]) + +lemma none_fin_fempty: + "(\x. x |\| S) = (S = {||})" + by (lifting none_memb_nil) + +lemma fset_cong: + "(fset_to_set S = fset_to_set T) = (S = T)" + by (lifting set_cong) + +text {* fcard *} + +lemma fcard_fempty [simp]: + shows "fcard {||} = 0" + by (lifting fcard_raw_nil) + +lemma fcard_finsert_if [simp]: + shows "fcard (finsert x S) = (if x |\| S then fcard S else Suc (fcard S))" + by (lifting fcard_raw_cons) + +lemma fcard_0: "(fcard S = 0) = (S = {||})" + by (lifting fcard_raw_0) + +lemma fcard_1: + shows "(fcard S = 1) = (\x. S = {|x|})" + by (lifting fcard_raw_1) + +lemma fcard_gt_0: + shows "x \ fset_to_set S \ 0 < fcard S" + by (lifting fcard_raw_gt_0) + +lemma fcard_not_fin: + shows "(x |\| S) = (fcard (finsert x S) = Suc (fcard S))" + by (lifting fcard_raw_not_memb) + +lemma fcard_suc: "fcard S = Suc n \ \x T. x |\| T \ S = finsert x T \ fcard T = n" + by (lifting fcard_raw_suc) + +lemma fcard_delete: + "fcard (fdelete S y) = (if y |\| S then fcard S - 1 else fcard S)" + by (lifting fcard_raw_delete) + +lemma fcard_suc_memb: "fcard A = Suc n \ \a. a |\| A" + by (lifting fcard_raw_suc_memb) + +lemma fin_fcard_not_0: "a |\| A \ fcard A \ 0" + by (lifting memb_card_not_0) + +text {* funion *} + +lemma funion_simps[simp]: + shows "{||} |\| S = S" + and "finsert x S |\| T = finsert x (S |\| T)" + by (lifting append.simps) + +lemma funion_empty[simp]: + shows "S |\| {||} = S" + by (lifting append_Nil2) + +lemma singleton_union_left: + "{|a|} |\| S = finsert a S" + by simp + +lemma singleton_union_right: + "S |\| {|a|} = finsert a S" + by (subst sup.commute) simp + +section {* Induction and Cases rules for finite sets *} + +lemma fset_strong_cases: + "S = {||} \ (\x T. x |\| T \ S = finsert x T)" + by (lifting fset_raw_strong_cases) + +lemma fset_exhaust[case_names fempty finsert, cases type: fset]: + shows "\S = {||} \ P; \x S'. S = finsert x S' \ P\ \ P" + by (lifting list.exhaust) + +lemma fset_induct_weak[case_names fempty finsert]: + shows "\P {||}; \x S. P S \ P (finsert x S)\ \ P S" + by (lifting list.induct) + +lemma fset_induct[case_names fempty finsert, induct type: fset]: + assumes prem1: "P {||}" + and prem2: "\x S. \x |\| S; P S\ \ P (finsert x S)" + shows "P S" +proof(induct S rule: fset_induct_weak) + case fempty + show "P {||}" by (rule prem1) +next + case (finsert x S) + have asm: "P S" by fact + show "P (finsert x S)" + by (cases "x |\| S") (simp_all add: asm prem2) +qed + +lemma fset_induct2: + "P {||} {||} \ + (\x xs. x |\| xs \ P (finsert x xs) {||}) \ + (\y ys. y |\| ys \ P {||} (finsert y ys)) \ + (\x xs y ys. \P xs ys; x |\| xs; y |\| ys\ \ P (finsert x xs) (finsert y ys)) \ + P xsa ysa" + apply (induct xsa arbitrary: ysa) + apply (induct_tac x rule: fset_induct) + apply simp_all + apply (induct_tac xa rule: fset_induct) + apply simp_all + done + +text {* fmap *} + +lemma fmap_simps[simp]: + "fmap (f :: 'a \ 'b) {||} = {||}" + "fmap f (finsert x S) = finsert (f x) (fmap f S)" + by (lifting map.simps) + +lemma fmap_set_image: + "fset_to_set (fmap f S) = f ` (fset_to_set S)" + by (induct S) (simp_all) + +lemma inj_fmap_eq_iff: + "inj f \ (fmap f S = fmap f T) = (S = T)" + by (lifting inj_map_eq_iff) + +lemma fmap_funion: "fmap f (S |\| T) = fmap f S |\| fmap f T" + by (lifting map_append) + +lemma fin_funion: + "x |\| S |\| T \ x |\| S \ x |\| T" + by (lifting memb_append) + +text {* ffold *} + +lemma ffold_nil: "ffold f z {||} = z" + by (lifting ffold_raw.simps(1)[where 'a="'b" and 'b="'a"]) + +lemma ffold_finsert: "ffold f z (finsert a A) = + (if rsp_fold f then if a |\| A then ffold f z A else f a (ffold f z A) else z)" + by (lifting ffold_raw.simps(2)[where 'a="'b" and 'b="'a"]) + +lemma fin_commute_ffold: + "\rsp_fold f; h |\| b\ \ ffold f z b = f h (ffold f z (fdelete b h))" + by (lifting memb_commute_ffold_raw) + +text {* fdelete *} + +lemma fin_fdelete: + shows "x |\| fdelete S y \ x |\| S \ x \ y" + by (lifting memb_delete_raw) + +lemma fin_fdelete_ident: + shows "x |\| fdelete S x" + by (lifting memb_delete_raw_ident) + +lemma not_memb_fdelete_ident: + shows "x |\| S \ fdelete S x = S" + by (lifting not_memb_delete_raw_ident) + +lemma fset_fdelete_cases: + shows "S = {||} \ (\x. x |\| S \ S = finsert x (fdelete S x))" + by (lifting fset_raw_delete_raw_cases) + +text {* inter *} + +lemma finter_empty_l: "({||} |\| S) = {||}" + by (lifting finter_raw.simps(1)) + +lemma finter_empty_r: "(S |\| {||}) = {||}" + by (lifting finter_raw_empty) + +lemma finter_finsert: + "finsert x S |\| T = (if x |\| T then finsert x (S |\| T) else S |\| T)" + by (lifting finter_raw.simps(2)) + +lemma fin_finter: + "x |\| (S |\| T) \ x |\| S \ x |\| T" + by (lifting memb_finter_raw) + +lemma fsubset_finsert: + "(finsert x xs |\| ys) = (x |\| ys \ xs |\| ys)" + by (lifting sub_list_cons) + +lemma "xs |\| ys \ \x. x |\| xs \ x |\| ys" + by (lifting sub_list_def[simplified memb_def[symmetric]]) + +lemma fsubset_fin: "xs |\| ys = (\x. x |\| xs \ x |\| ys)" +by (rule meta_eq_to_obj_eq) + (lifting sub_list_def[simplified memb_def[symmetric]]) + +lemma expand_fset_eq: + "(S = T) = (\x. (x |\| S) = (x |\| T))" + by (lifting list_eq.simps[simplified memb_def[symmetric]]) + +(* We cannot write it as "assumes .. shows" since Isabelle changes + the quantifiers to schematic variables and reintroduces them in + a different order *) +lemma fset_eq_cases: + "\a1 = a2; + \a b xs. \a1 = finsert a (finsert b xs); a2 = finsert b (finsert a xs)\ \ P; + \a1 = {||}; a2 = {||}\ \ P; \xs ys. \a1 = ys; a2 = xs; xs = ys\ \ P; + \a xs. \a1 = finsert a (finsert a xs); a2 = finsert a xs\ \ P; + \xs ys a. \a1 = finsert a xs; a2 = finsert a ys; xs = ys\ \ P; + \xs1 xs2 xs3. \a1 = xs1; a2 = xs3; xs1 = xs2; xs2 = xs3\ \ P\ + \ P" + by (lifting list_eq2.cases[simplified list_eq2_equiv[symmetric]]) + +lemma fset_eq_induct: + assumes "x1 = x2" + and "\a b xs. P (finsert a (finsert b xs)) (finsert b (finsert a xs))" + and "P {||} {||}" + and "\xs ys. \xs = ys; P xs ys\ \ P ys xs" + and "\a xs. P (finsert a (finsert a xs)) (finsert a xs)" + and "\xs ys a. \xs = ys; P xs ys\ \ P (finsert a xs) (finsert a ys)" + and "\xs1 xs2 xs3. \xs1 = xs2; P xs1 xs2; xs2 = xs3; P xs2 xs3\ \ P xs1 xs3" + shows "P x1 x2" + using assms + by (lifting list_eq2.induct[simplified list_eq2_equiv[symmetric]]) + +text {* concat *} + +lemma fconcat_empty: + shows "fconcat {||} = {||}" + by (lifting concat.simps(1)) + +lemma fconcat_insert: + shows "fconcat (finsert x S) = x |\| fconcat S" + by (lifting concat.simps(2)) + +lemma "fconcat (xs |\| ys) = fconcat xs |\| fconcat ys" + by (lifting concat_append) + +ML {* +fun dest_fsetT (Type ("FSet.fset", [T])) = T + | dest_fsetT T = raise TYPE ("dest_fsetT: fset type expected", [T], []); +*} + +no_notation + list_eq (infix "\" 50) + +end diff -r 8e58a63ac975 -r c4f5823f282d src/HOL/Quotient_Examples/ROOT.ML --- a/src/HOL/Quotient_Examples/ROOT.ML Thu Apr 22 22:12:12 2010 +0200 +++ b/src/HOL/Quotient_Examples/ROOT.ML Fri Apr 23 10:00:53 2010 +0200 @@ -4,5 +4,5 @@ Testing the quotient package. *) -use_thys ["LarryInt", "LarryDatatype"]; +use_thys ["FSet", "LarryInt", "LarryDatatype"];