# HG changeset patch # User Cezary Kaliszyk # Date 1268932249 -3600 # Node ID de8cbeac0624473ea2dafbf7e80347b6ff51e772 # Parent 62d6f7acc110b4fff4fe971d40198807a4b16333# Parent 212629c9097192c39bb16ee7b678ff0e3b36bad0 merge diff -r 62d6f7acc110 -r de8cbeac0624 Nominal/FSet.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal/FSet.thy Thu Mar 18 18:10:49 2010 +0100 @@ -0,0 +1,376 @@ +theory FSet +imports Quotient Quotient_List List +begin + +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 reflp_def symp_def transp_def +by auto + +quotient_type + 'a fset = "'a list" / "list_eq" +by (rule list_eq_equivp) + +section {* empty fset, finsert and membership *} + +quotient_definition + fempty ("{||}") +where + "fempty :: 'a fset" +is "[]::'a list" + +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 {||}" + +definition + memb :: "'a \ 'a list \ bool" +where + "memb x xs \ x \ set xs" + +quotient_definition + fin ("_ |\| _" [50, 51] 50) +where + "fin :: 'a \ 'a fset \ bool" +is "memb" + +abbreviation + fnotin :: "'a \ 'a fset \ bool" ("_ |\| _" [50, 51] 50) +where + "a |\| S \ \(a |\| S)" + +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 + +section {* Augmenting a set -- @{const finsert} *} + +lemma nil_not_cons: + shows "\[] \ x # xs" + by auto + +lemma memb_cons_iff: + shows "memb x (y # xs) = (x = y \ memb x xs)" + by (induct xs) (auto 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 memb_absorb: + shows "memb x xs \ x # xs \ xs" + by (induct xs) (auto simp add: memb_def id_simps) + +section {* Singletons *} + +lemma singleton_list_eq: + shows "[x] \ [y] \ x = y" + by (simp add: id_simps) auto + +section {* Union *} + +quotient_definition + funion (infixl "|\|" 65) +where + "funion :: 'a fset \ 'a fset \ 'a fset" +is + "op @" + +section {* Cardinality of finite sets *} + +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))" + +quotient_definition + "fcard :: 'a fset \ nat" +is + "fcard_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: + "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: "a \ b" + shows "fcard_raw a = fcard_raw b" + using a + apply(induct a arbitrary: b) + apply(auto simp add: memb_def) + apply(metis) + apply(drule_tac x="[x \ b. x \ a1]" in meta_spec) + apply(simp add: fcard_raw_delete_one) + apply(metis Suc_pred' fcard_raw_gt_0 fcard_raw_delete_one memb_def) + done + +lemma fcard_raw_rsp[quot_respect]: + "(op \ ===> op =) fcard_raw fcard_raw" + by (simp add: fcard_raw_rsp_aux) + + +section {* fmap and fset comprehension *} + +quotient_definition + "fmap :: ('a \ 'b) \ 'a fset \ 'b fset" +is + "map" + +text {* raw section *} + +lemma map_rsp_aux: + assumes a: "a \ b" + shows "map f a \ map f b" + using a + apply(induct a arbitrary: b) + apply(auto) + apply(metis rev_image_eqI) + done + +lemma map_rsp[quot_respect]: + shows "(op = ===> op \ ===> op \) map map" + by (auto simp add: map_rsp_aux) + +lemma cons_left_comm: + "x # y # A \ y # x # A" + by (auto simp add: id_simps) + +lemma cons_left_idem: + "x # x # A \ x # A" + by (auto simp add: id_simps) + +lemma none_mem_nil: + "(\a. a \ set A) = (A \ [])" + by simp + +lemma finite_set_raw_strong_cases: + "(X = []) \ (\a Y. ((a \ set Y) \ (X \ a # Y)))" + apply (induct X) + apply (simp) + apply (rule disjI2) + apply (erule disjE) + apply (rule_tac x="a" in exI) + apply (rule_tac x="[]" in exI) + apply (simp) + apply (erule exE)+ + apply (case_tac "a = aa") + apply (rule_tac x="a" in exI) + apply (rule_tac x="Y" in exI) + apply (simp) + apply (rule_tac x="aa" in exI) + apply (rule_tac x="a # Y" in exI) + apply (auto) + done + +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))" + +lemma mem_delete_raw: + "x \ set (delete_raw A a) = (x \ set A \ \(x = a))" + by (induct A arbitrary: x a) (auto) + +lemma mem_delete_raw_ident: + "\(a \ set (delete_raw A a))" + by (induct A) (auto) + +lemma not_mem_delete_raw_ident: + "b \ set A \ (delete_raw A b = A)" + by (induct A) (auto) + +lemma finite_set_raw_delete_raw_cases: + "X = [] \ (\a. a mem X \ X \ a # delete_raw X a)" + by (induct X) (auto) + +lemma list2set_thm: + shows "set [] = {}" + and "set (h # t) = insert h (set t)" + by (auto) + +lemma list2set_rsp[quot_respect]: + "(op \ ===> op =) set set" + by auto + +definition + rsp_fold +where + "rsp_fold f = (\u v w. (f u (f v w) = f v (f u w)))" + +primrec + fold_raw :: "('a \ 'b \ 'b) \ 'b \ 'a list \ 'b" +where + "fold_raw f z [] = z" +| "fold_raw f z (a # A) = + (if (rsp_fold f) then + if a mem A then fold_raw f z A + else f a (fold_raw f z A) + else z)" + +section {* Constants on the Quotient Type *} + +quotient_definition + "fdelete :: 'a fset \ 'a \ 'a fset" + is "delete_raw" + +quotient_definition + "fset_to_set :: 'a fset \ 'a set" + is "set" + +lemma funion_sym_pre: + "a @ b \ b @ a" + by auto + + +lemma append_rsp[quot_respect]: + shows "(op \ ===> op \ ===> op \) op @ op @" + by (auto) + + + +section {* lifted part *} + + +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]: + shows "{||} \ finsert x S" + by (lifting nil_not_cons) + +lemma finsert_left_comm: + "finsert a (finsert b S) = finsert b (finsert a S)" + by (lifting cons_left_comm) + +lemma finsert_left_idem: + "finsert a (finsert a S) = finsert a 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: + "fset_to_set {||} = {}" + "fset_to_set (finsert (h :: 'b) t) = insert h (fset_to_set t)" + by (lifting list2set_thm) + +lemma in_fset_to_set: + "x \ fset_to_set xs \ x |\| xs" + by (lifting memb_def[symmetric]) + +lemma none_in_fempty: + "(\a. a \ fset_to_set A) = (A = {||})" + by (lifting none_mem_nil) + +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_gt_0: "x \ fset_to_set xs \ 0 < fcard xs" + by (lifting fcard_raw_gt_0) + +text {* funion *} + +lemma funion_simps[simp]: + "{||} |\| ys = ys" + "finsert x xs |\| ys = finsert x (xs |\| ys)" + by (lifting append.simps) + +lemma funion_sym: + "a |\| b = b |\| a" + by (lifting funion_sym_pre) + +lemma funion_assoc: + "x |\| xa |\| xb = x |\| (xa |\| xb)" + by (lifting append_assoc) + +section {* Induction and Cases rules for finite sets *} + +lemma fset_strong_cases: + "X = {||} \ (\a Y. a \ fset_to_set Y \ X = finsert a Y)" + by (lifting finite_set_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[case_names fempty finsert]: + shows "\P {||}; \x S. P S \ P (finsert x S)\ \ P S" + by (lifting list.induct) + +lemma fset_induct2[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) + case fempty + show "P {||}" by (rule prem1) +next + case (finsert x S) + have asm: "P S" by fact + show "P (finsert x S)" + proof(cases "x |\| S") + case True + have "x |\| S" by fact + then show "P (finsert x S)" using asm by simp + next + case False + have "x |\| S" by fact + then show "P (finsert x S)" using prem2 asm by simp + qed +qed + + + +end