diff --git a/src/HOL/Library/FSet.thy b/src/HOL/Library/FSet.thy --- a/src/HOL/Library/FSet.thy +++ b/src/HOL/Library/FSet.thy @@ -1,1951 +1,1973 @@ (* Title: HOL/Library/FSet.thy Author: Ondrej Kuncar, TU Muenchen Author: Cezary Kaliszyk and Christian Urban Author: Andrei Popescu, TU Muenchen Author: Martin Desharnais, MPI-INF Saarbruecken *) section \Type of finite sets defined as a subtype of sets\ theory FSet imports Main Countable begin subsection \Definition of the type\ typedef 'a fset = "{A :: 'a set. finite A}" morphisms fset Abs_fset by auto setup_lifting type_definition_fset subsection \Basic operations and type class instantiations\ (* FIXME transfer and right_total vs. bi_total *) instantiation fset :: (finite) finite begin instance by (standard; transfer; simp) end instantiation fset :: (type) "{bounded_lattice_bot, distrib_lattice, minus}" begin lift_definition bot_fset :: "'a fset" is "{}" parametric empty_transfer by simp lift_definition less_eq_fset :: "'a fset \ 'a fset \ bool" is subset_eq parametric subset_transfer . definition less_fset :: "'a fset \ 'a fset \ bool" where "xs < ys \ xs \ ys \ xs \ (ys::'a fset)" lemma less_fset_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "bi_unique A" shows "((pcr_fset A) ===> (pcr_fset A) ===> (=)) (\) (<)" unfolding less_fset_def[abs_def] psubset_eq[abs_def] by transfer_prover lift_definition sup_fset :: "'a fset \ 'a fset \ 'a fset" is union parametric union_transfer by simp lift_definition inf_fset :: "'a fset \ 'a fset \ 'a fset" is inter parametric inter_transfer by simp lift_definition minus_fset :: "'a fset \ 'a fset \ 'a fset" is minus parametric Diff_transfer by simp instance by (standard; transfer; auto)+ end abbreviation fempty :: "'a fset" ("{||}") where "{||} \ bot" abbreviation fsubset_eq :: "'a fset \ 'a fset \ bool" (infix "|\|" 50) where "xs |\| ys \ xs \ ys" abbreviation fsubset :: "'a fset \ 'a fset \ bool" (infix "|\|" 50) where "xs |\| ys \ xs < ys" abbreviation funion :: "'a fset \ 'a fset \ 'a fset" (infixl "|\|" 65) where "xs |\| ys \ sup xs ys" abbreviation finter :: "'a fset \ 'a fset \ 'a fset" (infixl "|\|" 65) where "xs |\| ys \ inf xs ys" abbreviation fminus :: "'a fset \ 'a fset \ 'a fset" (infixl "|-|" 65) where "xs |-| ys \ minus xs ys" instantiation fset :: (equal) equal begin definition "HOL.equal A B \ A |\| B \ B |\| A" instance by intro_classes (auto simp add: equal_fset_def) end instantiation fset :: (type) conditionally_complete_lattice begin context includes lifting_syntax begin lemma right_total_Inf_fset_transfer: assumes [transfer_rule]: "bi_unique A" and [transfer_rule]: "right_total A" shows "(rel_set (rel_set A) ===> rel_set A) (\S. if finite (\S \ Collect (Domainp A)) then \S \ Collect (Domainp A) else {}) (\S. if finite (Inf S) then Inf S else {})" by transfer_prover lemma Inf_fset_transfer: assumes [transfer_rule]: "bi_unique A" and [transfer_rule]: "bi_total A" shows "(rel_set (rel_set A) ===> rel_set A) (\A. if finite (Inf A) then Inf A else {}) (\A. if finite (Inf A) then Inf A else {})" by transfer_prover lift_definition Inf_fset :: "'a fset set \ 'a fset" is "\A. if finite (Inf A) then Inf A else {}" parametric right_total_Inf_fset_transfer Inf_fset_transfer by simp lemma Sup_fset_transfer: assumes [transfer_rule]: "bi_unique A" shows "(rel_set (rel_set A) ===> rel_set A) (\A. if finite (Sup A) then Sup A else {}) (\A. if finite (Sup A) then Sup A else {})" by transfer_prover lift_definition Sup_fset :: "'a fset set \ 'a fset" is "\A. if finite (Sup A) then Sup A else {}" parametric Sup_fset_transfer by simp lemma finite_Sup: "\z. finite z \ (\a. a \ X \ a \ z) \ finite (Sup X)" by (auto intro: finite_subset) lemma transfer_bdd_below[transfer_rule]: "(rel_set (pcr_fset (=)) ===> (=)) bdd_below bdd_below" by auto end instance proof fix x z :: "'a fset" fix X :: "'a fset set" { assume "x \ X" "bdd_below X" then show "Inf X |\| x" by transfer auto next assume "X \ {}" "(\x. x \ X \ z |\| x)" then show "z |\| Inf X" by transfer (clarsimp, blast) next assume "x \ X" "bdd_above X" then obtain z where "x \ X" "(\x. x \ X \ x |\| z)" by (auto simp: bdd_above_def) then show "x |\| Sup X" by transfer (auto intro!: finite_Sup) next assume "X \ {}" "(\x. x \ X \ x |\| z)" then show "Sup X |\| z" by transfer (clarsimp, blast) } qed end instantiation fset :: (finite) complete_lattice begin lift_definition top_fset :: "'a fset" is UNIV parametric right_total_UNIV_transfer UNIV_transfer by simp instance by (standard; transfer; auto) end instantiation fset :: (finite) complete_boolean_algebra begin lift_definition uminus_fset :: "'a fset \ 'a fset" is uminus parametric right_total_Compl_transfer Compl_transfer by simp instance by (standard; transfer) (simp_all add: Inf_Sup Diff_eq) end abbreviation fUNIV :: "'a::finite fset" where "fUNIV \ top" abbreviation fuminus :: "'a::finite fset \ 'a fset" ("|-| _" [81] 80) where "|-| x \ uminus x" declare top_fset.rep_eq[simp] subsection \Other operations\ lift_definition finsert :: "'a \ 'a fset \ 'a fset" is insert parametric Lifting_Set.insert_transfer by simp syntax "_insert_fset" :: "args => 'a fset" ("{|(_)|}") translations "{|x, xs|}" == "CONST finsert x {|xs|}" "{|x|}" == "CONST finsert x {||}" abbreviation fmember :: "'a \ 'a fset \ bool" (infix "|\|" 50) where "x |\| X \ x \ fset X" abbreviation not_fmember :: "'a \ 'a fset \ bool" (infix "|\|" 50) where "x |\| X \ x \ fset X" +context +begin + +qualified abbreviation Ball :: "'a fset \ ('a \ bool) \ bool" where + "Ball X \ Set.Ball (fset X)" + +alias fBall = FSet.Ball + +qualified abbreviation Bex :: "'a fset \ ('a \ bool) \ bool" where + "Bex X \ Set.Bex (fset X)" + +alias fBex = FSet.Bex + +end + context includes lifting_syntax begin lemma fmember_transfer0[transfer_rule]: assumes [transfer_rule]: "bi_unique A" shows "(A ===> pcr_fset A ===> (=)) (\) (|\|)" by transfer_prover +lemma fBall_transfer0[transfer_rule]: + assumes [transfer_rule]: "bi_unique A" + shows "(pcr_fset A ===> (A ===> (=)) ===> (=)) (Ball) (fBall)" + by transfer_prover + +lemma fBex_transfer0[transfer_rule]: + assumes [transfer_rule]: "bi_unique A" + shows "(pcr_fset A ===> (A ===> (=)) ===> (=)) (Bex) (fBex)" + by transfer_prover + lift_definition ffilter :: "('a \ bool) \ 'a fset \ 'a fset" is Set.filter parametric Lifting_Set.filter_transfer unfolding Set.filter_def by simp lift_definition fPow :: "'a fset \ 'a fset fset" is Pow parametric Pow_transfer by (simp add: finite_subset) lift_definition fcard :: "'a fset \ nat" is card parametric card_transfer . lift_definition fimage :: "('a \ 'b) \ 'a fset \ 'b fset" (infixr "|`|" 90) is image parametric image_transfer by simp lift_definition fthe_elem :: "'a fset \ 'a" is the_elem . lift_definition fbind :: "'a fset \ ('a \ 'b fset) \ 'b fset" is Set.bind parametric bind_transfer by (simp add: Set.bind_def) lift_definition ffUnion :: "'a fset fset \ 'a fset" is Union parametric Union_transfer by simp -lift_definition fBall :: "'a fset \ ('a \ bool) \ bool" is Ball parametric Ball_transfer . -lift_definition fBex :: "'a fset \ ('a \ bool) \ bool" is Bex parametric Bex_transfer . - lift_definition ffold :: "('a \ 'b \ 'b) \ 'b \ 'a fset \ 'b" is Finite_Set.fold . lift_definition fset_of_list :: "'a list \ 'a fset" is set by (rule finite_set) lift_definition sorted_list_of_fset :: "'a::linorder fset \ 'a list" is sorted_list_of_set . subsection \Transferred lemmas from Set.thy\ lemma fset_eqI: "(\x. (x |\| A) = (x |\| B)) \ A = B" by (rule set_eqI[Transfer.transferred]) lemma fset_eq_iff[no_atp]: "(A = B) = (\x. (x |\| A) = (x |\| B))" by (rule set_eq_iff[Transfer.transferred]) lemma fBallI[intro!]: "(\x. x |\| A \ P x) \ fBall A P" by (rule ballI[Transfer.transferred]) lemma fbspec[dest?]: "fBall A P \ x |\| A \ P x" by (rule bspec[Transfer.transferred]) lemma fBallE[elim]: "fBall A P \ (P x \ Q) \ (x |\| A \ Q) \ Q" by (rule ballE[Transfer.transferred]) lemma fBexI[intro]: "P x \ x |\| A \ fBex A P" by (rule bexI[Transfer.transferred]) lemma rev_fBexI[intro?]: "x |\| A \ P x \ fBex A P" by (rule rev_bexI[Transfer.transferred]) lemma fBexCI: "(fBall A (\x. \ P x) \ P a) \ a |\| A \ fBex A P" by (rule bexCI[Transfer.transferred]) lemma fBexE[elim!]: "fBex A P \ (\x. x |\| A \ P x \ Q) \ Q" by (rule bexE[Transfer.transferred]) lemma fBall_triv[simp]: "fBall A (\x. P) = ((\x. x |\| A) \ P)" by (rule ball_triv[Transfer.transferred]) lemma fBex_triv[simp]: "fBex A (\x. P) = ((\x. x |\| A) \ P)" by (rule bex_triv[Transfer.transferred]) lemma fBex_triv_one_point1[simp]: "fBex A (\x. x = a) = (a |\| A)" by (rule bex_triv_one_point1[Transfer.transferred]) lemma fBex_triv_one_point2[simp]: "fBex A ((=) a) = (a |\| A)" by (rule bex_triv_one_point2[Transfer.transferred]) lemma fBex_one_point1[simp]: "fBex A (\x. x = a \ P x) = (a |\| A \ P a)" by (rule bex_one_point1[Transfer.transferred]) lemma fBex_one_point2[simp]: "fBex A (\x. a = x \ P x) = (a |\| A \ P a)" by (rule bex_one_point2[Transfer.transferred]) lemma fBall_one_point1[simp]: "fBall A (\x. x = a \ P x) = (a |\| A \ P a)" by (rule ball_one_point1[Transfer.transferred]) lemma fBall_one_point2[simp]: "fBall A (\x. a = x \ P x) = (a |\| A \ P a)" by (rule ball_one_point2[Transfer.transferred]) lemma fBall_conj_distrib: "fBall A (\x. P x \ Q x) = (fBall A P \ fBall A Q)" by (rule ball_conj_distrib[Transfer.transferred]) lemma fBex_disj_distrib: "fBex A (\x. P x \ Q x) = (fBex A P \ fBex A Q)" by (rule bex_disj_distrib[Transfer.transferred]) lemma fBall_cong[fundef_cong]: "A = B \ (\x. x |\| B \ P x = Q x) \ fBall A P = fBall B Q" by (rule ball_cong[Transfer.transferred]) lemma fBex_cong[fundef_cong]: "A = B \ (\x. x |\| B \ P x = Q x) \ fBex A P = fBex B Q" by (rule bex_cong[Transfer.transferred]) lemma fsubsetI[intro!]: "(\x. x |\| A \ x |\| B) \ A |\| B" by (rule subsetI[Transfer.transferred]) lemma fsubsetD[elim, intro?]: "A |\| B \ c |\| A \ c |\| B" by (rule subsetD[Transfer.transferred]) lemma rev_fsubsetD[no_atp,intro?]: "c |\| A \ A |\| B \ c |\| B" by (rule rev_subsetD[Transfer.transferred]) lemma fsubsetCE[no_atp,elim]: "A |\| B \ (c |\| A \ P) \ (c |\| B \ P) \ P" by (rule subsetCE[Transfer.transferred]) lemma fsubset_eq[no_atp]: "(A |\| B) = fBall A (\x. x |\| B)" by (rule subset_eq[Transfer.transferred]) lemma contra_fsubsetD[no_atp]: "A |\| B \ c |\| B \ c |\| A" by (rule contra_subsetD[Transfer.transferred]) lemma fsubset_refl: "A |\| A" by (rule subset_refl[Transfer.transferred]) lemma fsubset_trans: "A |\| B \ B |\| C \ A |\| C" by (rule subset_trans[Transfer.transferred]) lemma fset_rev_mp: "c |\| A \ A |\| B \ c |\| B" by (rule rev_subsetD[Transfer.transferred]) lemma fset_mp: "A |\| B \ c |\| A \ c |\| B" by (rule subsetD[Transfer.transferred]) lemma fsubset_not_fsubset_eq[code]: "(A |\| B) = (A |\| B \ \ B |\| A)" by (rule subset_not_subset_eq[Transfer.transferred]) lemma eq_fmem_trans: "a = b \ b |\| A \ a |\| A" by (rule eq_mem_trans[Transfer.transferred]) lemma fsubset_antisym[intro!]: "A |\| B \ B |\| A \ A = B" by (rule subset_antisym[Transfer.transferred]) lemma fequalityD1: "A = B \ A |\| B" by (rule equalityD1[Transfer.transferred]) lemma fequalityD2: "A = B \ B |\| A" by (rule equalityD2[Transfer.transferred]) lemma fequalityE: "A = B \ (A |\| B \ B |\| A \ P) \ P" by (rule equalityE[Transfer.transferred]) lemma fequalityCE[elim]: "A = B \ (c |\| A \ c |\| B \ P) \ (c |\| A \ c |\| B \ P) \ P" by (rule equalityCE[Transfer.transferred]) lemma eqfset_imp_iff: "A = B \ (x |\| A) = (x |\| B)" by (rule eqset_imp_iff[Transfer.transferred]) lemma eqfelem_imp_iff: "x = y \ (x |\| A) = (y |\| A)" by (rule eqelem_imp_iff[Transfer.transferred]) lemma fempty_iff[simp]: "(c |\| {||}) = False" by (rule empty_iff[Transfer.transferred]) lemma fempty_fsubsetI[iff]: "{||} |\| x" by (rule empty_subsetI[Transfer.transferred]) lemma equalsffemptyI: "(\y. y |\| A \ False) \ A = {||}" by (rule equals0I[Transfer.transferred]) lemma equalsffemptyD: "A = {||} \ a |\| A" by (rule equals0D[Transfer.transferred]) lemma fBall_fempty[simp]: "fBall {||} P = True" by (rule ball_empty[Transfer.transferred]) lemma fBex_fempty[simp]: "fBex {||} P = False" by (rule bex_empty[Transfer.transferred]) lemma fPow_iff[iff]: "(A |\| fPow B) = (A |\| B)" by (rule Pow_iff[Transfer.transferred]) lemma fPowI: "A |\| B \ A |\| fPow B" by (rule PowI[Transfer.transferred]) lemma fPowD: "A |\| fPow B \ A |\| B" by (rule PowD[Transfer.transferred]) lemma fPow_bottom: "{||} |\| fPow B" by (rule Pow_bottom[Transfer.transferred]) lemma fPow_top: "A |\| fPow A" by (rule Pow_top[Transfer.transferred]) lemma fPow_not_fempty: "fPow A \ {||}" by (rule Pow_not_empty[Transfer.transferred]) lemma finter_iff[simp]: "(c |\| A |\| B) = (c |\| A \ c |\| B)" by (rule Int_iff[Transfer.transferred]) lemma finterI[intro!]: "c |\| A \ c |\| B \ c |\| A |\| B" by (rule IntI[Transfer.transferred]) lemma finterD1: "c |\| A |\| B \ c |\| A" by (rule IntD1[Transfer.transferred]) lemma finterD2: "c |\| A |\| B \ c |\| B" by (rule IntD2[Transfer.transferred]) lemma finterE[elim!]: "c |\| A |\| B \ (c |\| A \ c |\| B \ P) \ P" by (rule IntE[Transfer.transferred]) lemma funion_iff[simp]: "(c |\| A |\| B) = (c |\| A \ c |\| B)" by (rule Un_iff[Transfer.transferred]) lemma funionI1[elim?]: "c |\| A \ c |\| A |\| B" by (rule UnI1[Transfer.transferred]) lemma funionI2[elim?]: "c |\| B \ c |\| A |\| B" by (rule UnI2[Transfer.transferred]) lemma funionCI[intro!]: "(c |\| B \ c |\| A) \ c |\| A |\| B" by (rule UnCI[Transfer.transferred]) lemma funionE[elim!]: "c |\| A |\| B \ (c |\| A \ P) \ (c |\| B \ P) \ P" by (rule UnE[Transfer.transferred]) lemma fminus_iff[simp]: "(c |\| A |-| B) = (c |\| A \ c |\| B)" by (rule Diff_iff[Transfer.transferred]) lemma fminusI[intro!]: "c |\| A \ c |\| B \ c |\| A |-| B" by (rule DiffI[Transfer.transferred]) lemma fminusD1: "c |\| A |-| B \ c |\| A" by (rule DiffD1[Transfer.transferred]) lemma fminusD2: "c |\| A |-| B \ c |\| B \ P" by (rule DiffD2[Transfer.transferred]) lemma fminusE[elim!]: "c |\| A |-| B \ (c |\| A \ c |\| B \ P) \ P" by (rule DiffE[Transfer.transferred]) lemma finsert_iff[simp]: "(a |\| finsert b A) = (a = b \ a |\| A)" by (rule insert_iff[Transfer.transferred]) lemma finsertI1: "a |\| finsert a B" by (rule insertI1[Transfer.transferred]) lemma finsertI2: "a |\| B \ a |\| finsert b B" by (rule insertI2[Transfer.transferred]) lemma finsertE[elim!]: "a |\| finsert b A \ (a = b \ P) \ (a |\| A \ P) \ P" by (rule insertE[Transfer.transferred]) lemma finsertCI[intro!]: "(a |\| B \ a = b) \ a |\| finsert b B" by (rule insertCI[Transfer.transferred]) lemma fsubset_finsert_iff: "(A |\| finsert x B) = (if x |\| A then A |-| {|x|} |\| B else A |\| B)" by (rule subset_insert_iff[Transfer.transferred]) lemma finsert_ident: "x |\| A \ x |\| B \ (finsert x A = finsert x B) = (A = B)" by (rule insert_ident[Transfer.transferred]) lemma fsingletonI[intro!,no_atp]: "a |\| {|a|}" by (rule singletonI[Transfer.transferred]) lemma fsingletonD[dest!,no_atp]: "b |\| {|a|} \ b = a" by (rule singletonD[Transfer.transferred]) lemma fsingleton_iff: "(b |\| {|a|}) = (b = a)" by (rule singleton_iff[Transfer.transferred]) lemma fsingleton_inject[dest!]: "{|a|} = {|b|} \ a = b" by (rule singleton_inject[Transfer.transferred]) lemma fsingleton_finsert_inj_eq[iff,no_atp]: "({|b|} = finsert a A) = (a = b \ A |\| {|b|})" by (rule singleton_insert_inj_eq[Transfer.transferred]) lemma fsingleton_finsert_inj_eq'[iff,no_atp]: "(finsert a A = {|b|}) = (a = b \ A |\| {|b|})" by (rule singleton_insert_inj_eq'[Transfer.transferred]) lemma fsubset_fsingletonD: "A |\| {|x|} \ A = {||} \ A = {|x|}" by (rule subset_singletonD[Transfer.transferred]) lemma fminus_single_finsert: "A |-| {|x|} |\| B \ A |\| finsert x B" by (rule Diff_single_insert[Transfer.transferred]) lemma fdoubleton_eq_iff: "({|a, b|} = {|c, d|}) = (a = c \ b = d \ a = d \ b = c)" by (rule doubleton_eq_iff[Transfer.transferred]) lemma funion_fsingleton_iff: "(A |\| B = {|x|}) = (A = {||} \ B = {|x|} \ A = {|x|} \ B = {||} \ A = {|x|} \ B = {|x|})" by (rule Un_singleton_iff[Transfer.transferred]) lemma fsingleton_funion_iff: "({|x|} = A |\| B) = (A = {||} \ B = {|x|} \ A = {|x|} \ B = {||} \ A = {|x|} \ B = {|x|})" by (rule singleton_Un_iff[Transfer.transferred]) lemma fimage_eqI[simp, intro]: "b = f x \ x |\| A \ b |\| f |`| A" by (rule image_eqI[Transfer.transferred]) lemma fimageI: "x |\| A \ f x |\| f |`| A" by (rule imageI[Transfer.transferred]) lemma rev_fimage_eqI: "x |\| A \ b = f x \ b |\| f |`| A" by (rule rev_image_eqI[Transfer.transferred]) lemma fimageE[elim!]: "b |\| f |`| A \ (\x. b = f x \ x |\| A \ thesis) \ thesis" by (rule imageE[Transfer.transferred]) lemma Compr_fimage_eq: "{x. x |\| f |`| A \ P x} = f ` {x. x |\| A \ P (f x)}" by (rule Compr_image_eq[Transfer.transferred]) lemma fimage_funion: "f |`| (A |\| B) = f |`| A |\| f |`| B" by (rule image_Un[Transfer.transferred]) lemma fimage_iff: "(z |\| f |`| A) = fBex A (\x. z = f x)" by (rule image_iff[Transfer.transferred]) lemma fimage_fsubset_iff[no_atp]: "(f |`| A |\| B) = fBall A (\x. f x |\| B)" by (rule image_subset_iff[Transfer.transferred]) lemma fimage_fsubsetI: "(\x. x |\| A \ f x |\| B) \ f |`| A |\| B" by (rule image_subsetI[Transfer.transferred]) lemma fimage_ident[simp]: "(\x. x) |`| Y = Y" by (rule image_ident[Transfer.transferred]) lemma if_split_fmem1: "((if Q then x else y) |\| b) = ((Q \ x |\| b) \ (\ Q \ y |\| b))" by (rule if_split_mem1[Transfer.transferred]) lemma if_split_fmem2: "(a |\| (if Q then x else y)) = ((Q \ a |\| x) \ (\ Q \ a |\| y))" by (rule if_split_mem2[Transfer.transferred]) lemma pfsubsetI[intro!,no_atp]: "A |\| B \ A \ B \ A |\| B" by (rule psubsetI[Transfer.transferred]) lemma pfsubsetE[elim!,no_atp]: "A |\| B \ (A |\| B \ \ B |\| A \ R) \ R" by (rule psubsetE[Transfer.transferred]) lemma pfsubset_finsert_iff: "(A |\| finsert x B) = (if x |\| B then A |\| B else if x |\| A then A |-| {|x|} |\| B else A |\| B)" by (rule psubset_insert_iff[Transfer.transferred]) lemma pfsubset_eq: "(A |\| B) = (A |\| B \ A \ B)" by (rule psubset_eq[Transfer.transferred]) lemma pfsubset_imp_fsubset: "A |\| B \ A |\| B" by (rule psubset_imp_subset[Transfer.transferred]) lemma pfsubset_trans: "A |\| B \ B |\| C \ A |\| C" by (rule psubset_trans[Transfer.transferred]) lemma pfsubsetD: "A |\| B \ c |\| A \ c |\| B" by (rule psubsetD[Transfer.transferred]) lemma pfsubset_fsubset_trans: "A |\| B \ B |\| C \ A |\| C" by (rule psubset_subset_trans[Transfer.transferred]) lemma fsubset_pfsubset_trans: "A |\| B \ B |\| C \ A |\| C" by (rule subset_psubset_trans[Transfer.transferred]) lemma pfsubset_imp_ex_fmem: "A |\| B \ \b. b |\| B |-| A" by (rule psubset_imp_ex_mem[Transfer.transferred]) lemma fimage_fPow_mono: "f |`| A |\| B \ (|`|) f |`| fPow A |\| fPow B" by (rule image_Pow_mono[Transfer.transferred]) lemma fimage_fPow_surj: "f |`| A = B \ (|`|) f |`| fPow A = fPow B" by (rule image_Pow_surj[Transfer.transferred]) lemma fsubset_finsertI: "B |\| finsert a B" by (rule subset_insertI[Transfer.transferred]) lemma fsubset_finsertI2: "A |\| B \ A |\| finsert b B" by (rule subset_insertI2[Transfer.transferred]) lemma fsubset_finsert: "x |\| A \ (A |\| finsert x B) = (A |\| B)" by (rule subset_insert[Transfer.transferred]) lemma funion_upper1: "A |\| A |\| B" by (rule Un_upper1[Transfer.transferred]) lemma funion_upper2: "B |\| A |\| B" by (rule Un_upper2[Transfer.transferred]) lemma funion_least: "A |\| C \ B |\| C \ A |\| B |\| C" by (rule Un_least[Transfer.transferred]) lemma finter_lower1: "A |\| B |\| A" by (rule Int_lower1[Transfer.transferred]) lemma finter_lower2: "A |\| B |\| B" by (rule Int_lower2[Transfer.transferred]) lemma finter_greatest: "C |\| A \ C |\| B \ C |\| A |\| B" by (rule Int_greatest[Transfer.transferred]) lemma fminus_fsubset: "A |-| B |\| A" by (rule Diff_subset[Transfer.transferred]) lemma fminus_fsubset_conv: "(A |-| B |\| C) = (A |\| B |\| C)" by (rule Diff_subset_conv[Transfer.transferred]) lemma fsubset_fempty[simp]: "(A |\| {||}) = (A = {||})" by (rule subset_empty[Transfer.transferred]) lemma not_pfsubset_fempty[iff]: "\ A |\| {||}" by (rule not_psubset_empty[Transfer.transferred]) lemma finsert_is_funion: "finsert a A = {|a|} |\| A" by (rule insert_is_Un[Transfer.transferred]) lemma finsert_not_fempty[simp]: "finsert a A \ {||}" by (rule insert_not_empty[Transfer.transferred]) lemma fempty_not_finsert: "{||} \ finsert a A" by (rule empty_not_insert[Transfer.transferred]) lemma finsert_absorb: "a |\| A \ finsert a A = A" by (rule insert_absorb[Transfer.transferred]) lemma finsert_absorb2[simp]: "finsert x (finsert x A) = finsert x A" by (rule insert_absorb2[Transfer.transferred]) lemma finsert_commute: "finsert x (finsert y A) = finsert y (finsert x A)" by (rule insert_commute[Transfer.transferred]) lemma finsert_fsubset[simp]: "(finsert x A |\| B) = (x |\| B \ A |\| B)" by (rule insert_subset[Transfer.transferred]) lemma finsert_inter_finsert[simp]: "finsert a A |\| finsert a B = finsert a (A |\| B)" by (rule insert_inter_insert[Transfer.transferred]) lemma finsert_disjoint[simp,no_atp]: "(finsert a A |\| B = {||}) = (a |\| B \ A |\| B = {||})" "({||} = finsert a A |\| B) = (a |\| B \ {||} = A |\| B)" by (rule insert_disjoint[Transfer.transferred])+ lemma disjoint_finsert[simp,no_atp]: "(B |\| finsert a A = {||}) = (a |\| B \ B |\| A = {||})" "({||} = A |\| finsert b B) = (b |\| A \ {||} = A |\| B)" by (rule disjoint_insert[Transfer.transferred])+ lemma fimage_fempty[simp]: "f |`| {||} = {||}" by (rule image_empty[Transfer.transferred]) lemma fimage_finsert[simp]: "f |`| finsert a B = finsert (f a) (f |`| B)" by (rule image_insert[Transfer.transferred]) lemma fimage_constant: "x |\| A \ (\x. c) |`| A = {|c|}" by (rule image_constant[Transfer.transferred]) lemma fimage_constant_conv: "(\x. c) |`| A = (if A = {||} then {||} else {|c|})" by (rule image_constant_conv[Transfer.transferred]) lemma fimage_fimage: "f |`| g |`| A = (\x. f (g x)) |`| A" by (rule image_image[Transfer.transferred]) lemma finsert_fimage[simp]: "x |\| A \ finsert (f x) (f |`| A) = f |`| A" by (rule insert_image[Transfer.transferred]) lemma fimage_is_fempty[iff]: "(f |`| A = {||}) = (A = {||})" by (rule image_is_empty[Transfer.transferred]) lemma fempty_is_fimage[iff]: "({||} = f |`| A) = (A = {||})" by (rule empty_is_image[Transfer.transferred]) lemma fimage_cong: "M = N \ (\x. x |\| N \ f x = g x) \ f |`| M = g |`| N" by (rule image_cong[Transfer.transferred]) lemma fimage_finter_fsubset: "f |`| (A |\| B) |\| f |`| A |\| f |`| B" by (rule image_Int_subset[Transfer.transferred]) lemma fimage_fminus_fsubset: "f |`| A |-| f |`| B |\| f |`| (A |-| B)" by (rule image_diff_subset[Transfer.transferred]) lemma finter_absorb: "A |\| A = A" by (rule Int_absorb[Transfer.transferred]) lemma finter_left_absorb: "A |\| (A |\| B) = A |\| B" by (rule Int_left_absorb[Transfer.transferred]) lemma finter_commute: "A |\| B = B |\| A" by (rule Int_commute[Transfer.transferred]) lemma finter_left_commute: "A |\| (B |\| C) = B |\| (A |\| C)" by (rule Int_left_commute[Transfer.transferred]) lemma finter_assoc: "A |\| B |\| C = A |\| (B |\| C)" by (rule Int_assoc[Transfer.transferred]) lemma finter_ac: "A |\| B |\| C = A |\| (B |\| C)" "A |\| (A |\| B) = A |\| B" "A |\| B = B |\| A" "A |\| (B |\| C) = B |\| (A |\| C)" by (rule Int_ac[Transfer.transferred])+ lemma finter_absorb1: "B |\| A \ A |\| B = B" by (rule Int_absorb1[Transfer.transferred]) lemma finter_absorb2: "A |\| B \ A |\| B = A" by (rule Int_absorb2[Transfer.transferred]) lemma finter_fempty_left: "{||} |\| B = {||}" by (rule Int_empty_left[Transfer.transferred]) lemma finter_fempty_right: "A |\| {||} = {||}" by (rule Int_empty_right[Transfer.transferred]) lemma disjoint_iff_fnot_equal: "(A |\| B = {||}) = fBall A (\x. fBall B ((\) x))" by (rule disjoint_iff_not_equal[Transfer.transferred]) lemma finter_funion_distrib: "A |\| (B |\| C) = A |\| B |\| (A |\| C)" by (rule Int_Un_distrib[Transfer.transferred]) lemma finter_funion_distrib2: "B |\| C |\| A = B |\| A |\| (C |\| A)" by (rule Int_Un_distrib2[Transfer.transferred]) lemma finter_fsubset_iff[no_atp, simp]: "(C |\| A |\| B) = (C |\| A \ C |\| B)" by (rule Int_subset_iff[Transfer.transferred]) lemma funion_absorb: "A |\| A = A" by (rule Un_absorb[Transfer.transferred]) lemma funion_left_absorb: "A |\| (A |\| B) = A |\| B" by (rule Un_left_absorb[Transfer.transferred]) lemma funion_commute: "A |\| B = B |\| A" by (rule Un_commute[Transfer.transferred]) lemma funion_left_commute: "A |\| (B |\| C) = B |\| (A |\| C)" by (rule Un_left_commute[Transfer.transferred]) lemma funion_assoc: "A |\| B |\| C = A |\| (B |\| C)" by (rule Un_assoc[Transfer.transferred]) lemma funion_ac: "A |\| B |\| C = A |\| (B |\| C)" "A |\| (A |\| B) = A |\| B" "A |\| B = B |\| A" "A |\| (B |\| C) = B |\| (A |\| C)" by (rule Un_ac[Transfer.transferred])+ lemma funion_absorb1: "A |\| B \ A |\| B = B" by (rule Un_absorb1[Transfer.transferred]) lemma funion_absorb2: "B |\| A \ A |\| B = A" by (rule Un_absorb2[Transfer.transferred]) lemma funion_fempty_left: "{||} |\| B = B" by (rule Un_empty_left[Transfer.transferred]) lemma funion_fempty_right: "A |\| {||} = A" by (rule Un_empty_right[Transfer.transferred]) lemma funion_finsert_left[simp]: "finsert a B |\| C = finsert a (B |\| C)" by (rule Un_insert_left[Transfer.transferred]) lemma funion_finsert_right[simp]: "A |\| finsert a B = finsert a (A |\| B)" by (rule Un_insert_right[Transfer.transferred]) lemma finter_finsert_left: "finsert a B |\| C = (if a |\| C then finsert a (B |\| C) else B |\| C)" by (rule Int_insert_left[Transfer.transferred]) lemma finter_finsert_left_ifffempty[simp]: "a |\| C \ finsert a B |\| C = B |\| C" by (rule Int_insert_left_if0[Transfer.transferred]) lemma finter_finsert_left_if1[simp]: "a |\| C \ finsert a B |\| C = finsert a (B |\| C)" by (rule Int_insert_left_if1[Transfer.transferred]) lemma finter_finsert_right: "A |\| finsert a B = (if a |\| A then finsert a (A |\| B) else A |\| B)" by (rule Int_insert_right[Transfer.transferred]) lemma finter_finsert_right_ifffempty[simp]: "a |\| A \ A |\| finsert a B = A |\| B" by (rule Int_insert_right_if0[Transfer.transferred]) lemma finter_finsert_right_if1[simp]: "a |\| A \ A |\| finsert a B = finsert a (A |\| B)" by (rule Int_insert_right_if1[Transfer.transferred]) lemma funion_finter_distrib: "A |\| (B |\| C) = A |\| B |\| (A |\| C)" by (rule Un_Int_distrib[Transfer.transferred]) lemma funion_finter_distrib2: "B |\| C |\| A = B |\| A |\| (C |\| A)" by (rule Un_Int_distrib2[Transfer.transferred]) lemma funion_finter_crazy: "A |\| B |\| (B |\| C) |\| (C |\| A) = A |\| B |\| (B |\| C) |\| (C |\| A)" by (rule Un_Int_crazy[Transfer.transferred]) lemma fsubset_funion_eq: "(A |\| B) = (A |\| B = B)" by (rule subset_Un_eq[Transfer.transferred]) lemma funion_fempty[iff]: "(A |\| B = {||}) = (A = {||} \ B = {||})" by (rule Un_empty[Transfer.transferred]) lemma funion_fsubset_iff[no_atp, simp]: "(A |\| B |\| C) = (A |\| C \ B |\| C)" by (rule Un_subset_iff[Transfer.transferred]) lemma funion_fminus_finter: "A |-| B |\| (A |\| B) = A" by (rule Un_Diff_Int[Transfer.transferred]) lemma ffunion_empty[simp]: "ffUnion {||} = {||}" by (rule Union_empty[Transfer.transferred]) lemma ffunion_mono: "A |\| B \ ffUnion A |\| ffUnion B" by (rule Union_mono[Transfer.transferred]) lemma ffunion_insert[simp]: "ffUnion (finsert a B) = a |\| ffUnion B" by (rule Union_insert[Transfer.transferred]) lemma fminus_finter2: "A |\| C |-| (B |\| C) = A |\| C |-| B" by (rule Diff_Int2[Transfer.transferred]) lemma funion_finter_assoc_eq: "(A |\| B |\| C = A |\| (B |\| C)) = (C |\| A)" by (rule Un_Int_assoc_eq[Transfer.transferred]) lemma fBall_funion: "fBall (A |\| B) P = (fBall A P \ fBall B P)" by (rule ball_Un[Transfer.transferred]) lemma fBex_funion: "fBex (A |\| B) P = (fBex A P \ fBex B P)" by (rule bex_Un[Transfer.transferred]) lemma fminus_eq_fempty_iff[simp,no_atp]: "(A |-| B = {||}) = (A |\| B)" by (rule Diff_eq_empty_iff[Transfer.transferred]) lemma fminus_cancel[simp]: "A |-| A = {||}" by (rule Diff_cancel[Transfer.transferred]) lemma fminus_idemp[simp]: "A |-| B |-| B = A |-| B" by (rule Diff_idemp[Transfer.transferred]) lemma fminus_triv: "A |\| B = {||} \ A |-| B = A" by (rule Diff_triv[Transfer.transferred]) lemma fempty_fminus[simp]: "{||} |-| A = {||}" by (rule empty_Diff[Transfer.transferred]) lemma fminus_fempty[simp]: "A |-| {||} = A" by (rule Diff_empty[Transfer.transferred]) lemma fminus_finsertffempty[simp,no_atp]: "x |\| A \ A |-| finsert x B = A |-| B" by (rule Diff_insert0[Transfer.transferred]) lemma fminus_finsert: "A |-| finsert a B = A |-| B |-| {|a|}" by (rule Diff_insert[Transfer.transferred]) lemma fminus_finsert2: "A |-| finsert a B = A |-| {|a|} |-| B" by (rule Diff_insert2[Transfer.transferred]) lemma finsert_fminus_if: "finsert x A |-| B = (if x |\| B then A |-| B else finsert x (A |-| B))" by (rule insert_Diff_if[Transfer.transferred]) lemma finsert_fminus1[simp]: "x |\| B \ finsert x A |-| B = A |-| B" by (rule insert_Diff1[Transfer.transferred]) lemma finsert_fminus_single[simp]: "finsert a (A |-| {|a|}) = finsert a A" by (rule insert_Diff_single[Transfer.transferred]) lemma finsert_fminus: "a |\| A \ finsert a (A |-| {|a|}) = A" by (rule insert_Diff[Transfer.transferred]) lemma fminus_finsert_absorb: "x |\| A \ finsert x A |-| {|x|} = A" by (rule Diff_insert_absorb[Transfer.transferred]) lemma fminus_disjoint[simp]: "A |\| (B |-| A) = {||}" by (rule Diff_disjoint[Transfer.transferred]) lemma fminus_partition: "A |\| B \ A |\| (B |-| A) = B" by (rule Diff_partition[Transfer.transferred]) lemma double_fminus: "A |\| B \ B |\| C \ B |-| (C |-| A) = A" by (rule double_diff[Transfer.transferred]) lemma funion_fminus_cancel[simp]: "A |\| (B |-| A) = A |\| B" by (rule Un_Diff_cancel[Transfer.transferred]) lemma funion_fminus_cancel2[simp]: "B |-| A |\| A = B |\| A" by (rule Un_Diff_cancel2[Transfer.transferred]) lemma fminus_funion: "A |-| (B |\| C) = A |-| B |\| (A |-| C)" by (rule Diff_Un[Transfer.transferred]) lemma fminus_finter: "A |-| (B |\| C) = A |-| B |\| (A |-| C)" by (rule Diff_Int[Transfer.transferred]) lemma funion_fminus: "A |\| B |-| C = A |-| C |\| (B |-| C)" by (rule Un_Diff[Transfer.transferred]) lemma finter_fminus: "A |\| B |-| C = A |\| (B |-| C)" by (rule Int_Diff[Transfer.transferred]) lemma fminus_finter_distrib: "C |\| (A |-| B) = C |\| A |-| (C |\| B)" by (rule Diff_Int_distrib[Transfer.transferred]) lemma fminus_finter_distrib2: "A |-| B |\| C = A |\| C |-| (B |\| C)" by (rule Diff_Int_distrib2[Transfer.transferred]) lemma fUNIV_bool[no_atp]: "fUNIV = {|False, True|}" by (rule UNIV_bool[Transfer.transferred]) lemma fPow_fempty[simp]: "fPow {||} = {|{||}|}" by (rule Pow_empty[Transfer.transferred]) lemma fPow_finsert: "fPow (finsert a A) = fPow A |\| finsert a |`| fPow A" by (rule Pow_insert[Transfer.transferred]) lemma funion_fPow_fsubset: "fPow A |\| fPow B |\| fPow (A |\| B)" by (rule Un_Pow_subset[Transfer.transferred]) lemma fPow_finter_eq[simp]: "fPow (A |\| B) = fPow A |\| fPow B" by (rule Pow_Int_eq[Transfer.transferred]) lemma fset_eq_fsubset: "(A = B) = (A |\| B \ B |\| A)" by (rule set_eq_subset[Transfer.transferred]) lemma fsubset_iff[no_atp]: "(A |\| B) = (\t. t |\| A \ t |\| B)" by (rule subset_iff[Transfer.transferred]) lemma fsubset_iff_pfsubset_eq: "(A |\| B) = (A |\| B \ A = B)" by (rule subset_iff_psubset_eq[Transfer.transferred]) lemma all_not_fin_conv[simp]: "(\x. x |\| A) = (A = {||})" by (rule all_not_in_conv[Transfer.transferred]) lemma ex_fin_conv: "(\x. x |\| A) = (A \ {||})" by (rule ex_in_conv[Transfer.transferred]) lemma fimage_mono: "A |\| B \ f |`| A |\| f |`| B" by (rule image_mono[Transfer.transferred]) lemma fPow_mono: "A |\| B \ fPow A |\| fPow B" by (rule Pow_mono[Transfer.transferred]) lemma finsert_mono: "C |\| D \ finsert a C |\| finsert a D" by (rule insert_mono[Transfer.transferred]) lemma funion_mono: "A |\| C \ B |\| D \ A |\| B |\| C |\| D" by (rule Un_mono[Transfer.transferred]) lemma finter_mono: "A |\| C \ B |\| D \ A |\| B |\| C |\| D" by (rule Int_mono[Transfer.transferred]) lemma fminus_mono: "A |\| C \ D |\| B \ A |-| B |\| C |-| D" by (rule Diff_mono[Transfer.transferred]) lemma fin_mono: "A |\| B \ x |\| A \ x |\| B" by (rule in_mono[Transfer.transferred]) lemma fthe_felem_eq[simp]: "fthe_elem {|x|} = x" by (rule the_elem_eq[Transfer.transferred]) lemma fLeast_mono: "mono f \ fBex S (\x. fBall S ((\) x)) \ (LEAST y. y |\| f |`| S) = f (LEAST x. x |\| S)" by (rule Least_mono[Transfer.transferred]) lemma fbind_fbind: "fbind (fbind A B) C = fbind A (\x. fbind (B x) C)" by (rule Set.bind_bind[Transfer.transferred]) lemma fempty_fbind[simp]: "fbind {||} f = {||}" by (rule empty_bind[Transfer.transferred]) lemma nonfempty_fbind_const: "A \ {||} \ fbind A (\_. B) = B" by (rule nonempty_bind_const[Transfer.transferred]) lemma fbind_const: "fbind A (\_. B) = (if A = {||} then {||} else B)" by (rule bind_const[Transfer.transferred]) lemma ffmember_filter[simp]: "(x |\| ffilter P A) = (x |\| A \ P x)" by (rule member_filter[Transfer.transferred]) lemma fequalityI: "A |\| B \ B |\| A \ A = B" by (rule equalityI[Transfer.transferred]) lemma fset_of_list_simps[simp]: "fset_of_list [] = {||}" "fset_of_list (x21 # x22) = finsert x21 (fset_of_list x22)" by (rule set_simps[Transfer.transferred])+ lemma fset_of_list_append[simp]: "fset_of_list (xs @ ys) = fset_of_list xs |\| fset_of_list ys" by (rule set_append[Transfer.transferred]) lemma fset_of_list_rev[simp]: "fset_of_list (rev xs) = fset_of_list xs" by (rule set_rev[Transfer.transferred]) lemma fset_of_list_map[simp]: "fset_of_list (map f xs) = f |`| fset_of_list xs" by (rule set_map[Transfer.transferred]) subsection \Additional lemmas\ subsubsection \\ffUnion\\ lemma ffUnion_funion_distrib[simp]: "ffUnion (A |\| B) = ffUnion A |\| ffUnion B" by (rule Union_Un_distrib[Transfer.transferred]) subsubsection \\fbind\\ lemma fbind_cong[fundef_cong]: "A = B \ (\x. x |\| B \ f x = g x) \ fbind A f = fbind B g" by transfer force subsubsection \\fsingleton\\ lemma fsingletonE: " b |\| {|a|} \ (b = a \ thesis) \ thesis" by (rule fsingletonD [elim_format]) subsubsection \\femepty\\ lemma fempty_ffilter[simp]: "ffilter (\_. False) A = {||}" by transfer auto (* FIXME, transferred doesn't work here *) lemma femptyE [elim!]: "a |\| {||} \ P" by simp subsubsection \\fset\\ lemma fset_simps[simp]: "fset {||} = {}" "fset (finsert x X) = insert x (fset X)" by (rule bot_fset.rep_eq finsert.rep_eq)+ lemma finite_fset [simp]: shows "finite (fset S)" by transfer simp lemmas fset_cong = fset_inject lemma filter_fset [simp]: shows "fset (ffilter P xs) = Collect P \ fset xs" by transfer auto lemma inter_fset[simp]: "fset (A |\| B) = fset A \ fset B" by (rule inf_fset.rep_eq) lemma union_fset[simp]: "fset (A |\| B) = fset A \ fset B" by (rule sup_fset.rep_eq) lemma minus_fset[simp]: "fset (A |-| B) = fset A - fset B" by (rule minus_fset.rep_eq) subsubsection \\ffilter\\ lemma subset_ffilter: "ffilter P A |\| ffilter Q A = (\ x. x |\| A \ P x \ Q x)" by transfer auto lemma eq_ffilter: "(ffilter P A = ffilter Q A) = (\x. x |\| A \ P x = Q x)" by transfer auto lemma pfsubset_ffilter: "(\x. x |\| A \ P x \ Q x) \ (x |\| A \ \ P x \ Q x) \ ffilter P A |\| ffilter Q A" unfolding less_fset_def by (auto simp add: subset_ffilter eq_ffilter) subsubsection \\fset_of_list\\ lemma fset_of_list_filter[simp]: "fset_of_list (filter P xs) = ffilter P (fset_of_list xs)" by transfer (auto simp: Set.filter_def) lemma fset_of_list_subset[intro]: "set xs \ set ys \ fset_of_list xs |\| fset_of_list ys" by transfer simp lemma fset_of_list_elem: "(x |\| fset_of_list xs) \ (x \ set xs)" by transfer simp subsubsection \\finsert\\ (* FIXME, transferred doesn't work here *) lemma set_finsert: assumes "x |\| A" obtains B where "A = finsert x B" and "x |\| B" using assms by transfer (metis Set.set_insert finite_insert) lemma mk_disjoint_finsert: "a |\| A \ \B. A = finsert a B \ a |\| B" by (rule exI [where x = "A |-| {|a|}"]) blast lemma finsert_eq_iff: assumes "a |\| A" and "b |\| B" shows "(finsert a A = finsert b B) = (if a = b then A = B else \C. A = finsert b C \ b |\| C \ B = finsert a C \ a |\| C)" using assms by transfer (force simp: insert_eq_iff) subsubsection \\fimage\\ lemma subset_fimage_iff: "(B |\| f|`|A) = (\ AA. AA |\| A \ B = f|`|AA)" by transfer (metis mem_Collect_eq rev_finite_subset subset_image_iff) lemma fimage_strict_mono: assumes "inj_on f (fset B)" and "A |\| B" shows "f |`| A |\| f |`| B" \ \TODO: Configure transfer framework to lift @{thm Fun.image_strict_mono}.\ proof (rule pfsubsetI) from \A |\| B\ have "A |\| B" by (rule pfsubset_imp_fsubset) thus "f |`| A |\| f |`| B" by (rule fimage_mono) next from \A |\| B\ have "A |\| B" and "A \ B" by (simp_all add: pfsubset_eq) have "fset A \ fset B" using \A \ B\ by (simp add: fset_cong) hence "f ` fset A \ f ` fset B" using \A |\| B\ by (simp add: inj_on_image_eq_iff[OF \inj_on f (fset B)\] less_eq_fset.rep_eq) hence "fset (f |`| A) \ fset (f |`| B)" by (simp add: fimage.rep_eq) thus "f |`| A \ f |`| B" by (simp add: fset_cong) qed subsubsection \bounded quantification\ lemma bex_simps [simp, no_atp]: "\A P Q. fBex A (\x. P x \ Q) = (fBex A P \ Q)" "\A P Q. fBex A (\x. P \ Q x) = (P \ fBex A Q)" "\P. fBex {||} P = False" "\a B P. fBex (finsert a B) P = (P a \ fBex B P)" "\A P f. fBex (f |`| A) P = fBex A (\x. P (f x))" "\A P. (\ fBex A P) = fBall A (\x. \ P x)" by auto lemma ball_simps [simp, no_atp]: "\A P Q. fBall A (\x. P x \ Q) = (fBall A P \ Q)" "\A P Q. fBall A (\x. P \ Q x) = (P \ fBall A Q)" "\A P Q. fBall A (\x. P \ Q x) = (P \ fBall A Q)" "\A P Q. fBall A (\x. P x \ Q) = (fBex A P \ Q)" "\P. fBall {||} P = True" "\a B P. fBall (finsert a B) P = (P a \ fBall B P)" "\A P f. fBall (f |`| A) P = fBall A (\x. P (f x))" "\A P. (\ fBall A P) = fBex A (\x. \ P x)" by auto lemma atomize_fBall: "(\x. x |\| A ==> P x) == Trueprop (fBall A (\x. P x))" apply (simp only: atomize_all atomize_imp) apply (rule equal_intr_rule) by (transfer, simp)+ lemma fBall_mono[mono]: "P \ Q \ fBall S P \ fBall S Q" by auto lemma fBex_mono[mono]: "P \ Q \ fBex S P \ fBex S Q" by auto end subsubsection \\fcard\\ (* FIXME: improve transferred to handle bounded meta quantification *) lemma fcard_fempty: "fcard {||} = 0" by transfer (rule card.empty) lemma fcard_finsert_disjoint: "x |\| A \ fcard (finsert x A) = Suc (fcard A)" by transfer (rule card_insert_disjoint) lemma fcard_finsert_if: "fcard (finsert x A) = (if x |\| A then fcard A else Suc (fcard A))" by transfer (rule card_insert_if) lemma fcard_0_eq [simp, no_atp]: "fcard A = 0 \ A = {||}" by transfer (rule card_0_eq) lemma fcard_Suc_fminus1: "x |\| A \ Suc (fcard (A |-| {|x|})) = fcard A" by transfer (rule card_Suc_Diff1) lemma fcard_fminus_fsingleton: "x |\| A \ fcard (A |-| {|x|}) = fcard A - 1" by transfer (rule card_Diff_singleton) lemma fcard_fminus_fsingleton_if: "fcard (A |-| {|x|}) = (if x |\| A then fcard A - 1 else fcard A)" by transfer (rule card_Diff_singleton_if) lemma fcard_fminus_finsert[simp]: assumes "a |\| A" and "a |\| B" shows "fcard (A |-| finsert a B) = fcard (A |-| B) - 1" using assms by transfer (rule card_Diff_insert) lemma fcard_finsert: "fcard (finsert x A) = Suc (fcard (A |-| {|x|}))" by transfer (rule card.insert_remove) lemma fcard_finsert_le: "fcard A \ fcard (finsert x A)" by transfer (rule card_insert_le) lemma fcard_mono: "A |\| B \ fcard A \ fcard B" by transfer (rule card_mono) lemma fcard_seteq: "A |\| B \ fcard B \ fcard A \ A = B" by transfer (rule card_seteq) lemma pfsubset_fcard_mono: "A |\| B \ fcard A < fcard B" by transfer (rule psubset_card_mono) lemma fcard_funion_finter: "fcard A + fcard B = fcard (A |\| B) + fcard (A |\| B)" by transfer (rule card_Un_Int) lemma fcard_funion_disjoint: "A |\| B = {||} \ fcard (A |\| B) = fcard A + fcard B" by transfer (rule card_Un_disjoint) lemma fcard_funion_fsubset: "B |\| A \ fcard (A |-| B) = fcard A - fcard B" by transfer (rule card_Diff_subset) lemma diff_fcard_le_fcard_fminus: "fcard A - fcard B \ fcard(A |-| B)" by transfer (rule diff_card_le_card_Diff) lemma fcard_fminus1_less: "x |\| A \ fcard (A |-| {|x|}) < fcard A" by transfer (rule card_Diff1_less) lemma fcard_fminus2_less: "x |\| A \ y |\| A \ fcard (A |-| {|x|} |-| {|y|}) < fcard A" by transfer (rule card_Diff2_less) lemma fcard_fminus1_le: "fcard (A |-| {|x|}) \ fcard A" by transfer (rule card_Diff1_le) lemma fcard_pfsubset: "A |\| B \ fcard A < fcard B \ A < B" by transfer (rule card_psubset) subsubsection \\sorted_list_of_fset\\ lemma sorted_list_of_fset_simps[simp]: "set (sorted_list_of_fset S) = fset S" "fset_of_list (sorted_list_of_fset S) = S" by (transfer, simp)+ subsubsection \\ffold\\ (* FIXME: improve transferred to handle bounded meta quantification *) context comp_fun_commute begin lemma ffold_empty[simp]: "ffold f z {||} = z" by (rule fold_empty[Transfer.transferred]) lemma ffold_finsert [simp]: assumes "x |\| A" shows "ffold f z (finsert x A) = f x (ffold f z A)" using assms by (transfer fixing: f) (rule fold_insert) lemma ffold_fun_left_comm: "f x (ffold f z A) = ffold f (f x z) A" by (transfer fixing: f) (rule fold_fun_left_comm) lemma ffold_finsert2: "x |\| A \ ffold f z (finsert x A) = ffold f (f x z) A" by (transfer fixing: f) (rule fold_insert2) lemma ffold_rec: assumes "x |\| A" shows "ffold f z A = f x (ffold f z (A |-| {|x|}))" using assms by (transfer fixing: f) (rule fold_rec) lemma ffold_finsert_fremove: "ffold f z (finsert x A) = f x (ffold f z (A |-| {|x|}))" by (transfer fixing: f) (rule fold_insert_remove) end lemma ffold_fimage: assumes "inj_on g (fset A)" shows "ffold f z (g |`| A) = ffold (f \ g) z A" using assms by transfer' (rule fold_image) lemma ffold_cong: assumes "comp_fun_commute f" "comp_fun_commute g" "\x. x |\| A \ f x = g x" and "s = t" and "A = B" shows "ffold f s A = ffold g t B" using assms[unfolded comp_fun_commute_def'] by transfer (meson Finite_Set.fold_cong subset_UNIV) context comp_fun_idem begin lemma ffold_finsert_idem: "ffold f z (finsert x A) = f x (ffold f z A)" by (transfer fixing: f) (rule fold_insert_idem) declare ffold_finsert [simp del] ffold_finsert_idem [simp] lemma ffold_finsert_idem2: "ffold f z (finsert x A) = ffold f (f x z) A" by (transfer fixing: f) (rule fold_insert_idem2) end subsubsection \@{term fsubset}\ lemma wfP_pfsubset: "wfP (|\|)" proof (rule wfP_if_convertible_to_nat) show "\x y. x |\| y \ fcard x < fcard y" by (rule pfsubset_fcard_mono) qed subsubsection \Group operations\ locale comm_monoid_fset = comm_monoid begin sublocale set: comm_monoid_set .. lift_definition F :: "('b \ 'a) \ 'b fset \ 'a" is set.F . lemma cong[fundef_cong]: "A = B \ (\x. x |\| B \ g x = h x) \ F g A = F h B" by (rule set.cong[Transfer.transferred]) lemma cong_simp[cong]: "\ A = B; \x. x |\| B =simp=> g x = h x \ \ F g A = F h B" unfolding simp_implies_def by (auto cong: cong) end context comm_monoid_add begin sublocale fsum: comm_monoid_fset plus 0 rewrites "comm_monoid_set.F plus 0 = sum" defines fsum = fsum.F proof - show "comm_monoid_fset (+) 0" by standard show "comm_monoid_set.F (+) 0 = sum" unfolding sum_def .. qed end subsubsection \Semilattice operations\ locale semilattice_fset = semilattice begin sublocale set: semilattice_set .. lift_definition F :: "'a fset \ 'a" is set.F . lemma eq_fold: "F (finsert x A) = ffold f x A" by transfer (rule set.eq_fold) lemma singleton [simp]: "F {|x|} = x" by transfer (rule set.singleton) lemma insert_not_elem: "x |\| A \ A \ {||} \ F (finsert x A) = x \<^bold>* F A" by transfer (rule set.insert_not_elem) lemma in_idem: "x |\| A \ x \<^bold>* F A = F A" by transfer (rule set.in_idem) lemma insert [simp]: "A \ {||} \ F (finsert x A) = x \<^bold>* F A" by transfer (rule set.insert) end locale semilattice_order_fset = binary?: semilattice_order + semilattice_fset begin end context linorder begin sublocale fMin: semilattice_order_fset min less_eq less rewrites "semilattice_set.F min = Min" defines fMin = fMin.F proof - show "semilattice_order_fset min (\) (<)" by standard show "semilattice_set.F min = Min" unfolding Min_def .. qed sublocale fMax: semilattice_order_fset max greater_eq greater rewrites "semilattice_set.F max = Max" defines fMax = fMax.F proof - show "semilattice_order_fset max (\) (>)" by standard show "semilattice_set.F max = Max" unfolding Max_def .. qed end lemma mono_fMax_commute: "mono f \ A \ {||} \ f (fMax A) = fMax (f |`| A)" by transfer (rule mono_Max_commute) lemma mono_fMin_commute: "mono f \ A \ {||} \ f (fMin A) = fMin (f |`| A)" by transfer (rule mono_Min_commute) lemma fMax_in[simp]: "A \ {||} \ fMax A |\| A" by transfer (rule Max_in) lemma fMin_in[simp]: "A \ {||} \ fMin A |\| A" by transfer (rule Min_in) lemma fMax_ge[simp]: "x |\| A \ x \ fMax A" by transfer (rule Max_ge) lemma fMin_le[simp]: "x |\| A \ fMin A \ x" by transfer (rule Min_le) lemma fMax_eqI: "(\y. y |\| A \ y \ x) \ x |\| A \ fMax A = x" by transfer (rule Max_eqI) lemma fMin_eqI: "(\y. y |\| A \ x \ y) \ x |\| A \ fMin A = x" by transfer (rule Min_eqI) lemma fMax_finsert[simp]: "fMax (finsert x A) = (if A = {||} then x else max x (fMax A))" by transfer simp lemma fMin_finsert[simp]: "fMin (finsert x A) = (if A = {||} then x else min x (fMin A))" by transfer simp context linorder begin lemma fset_linorder_max_induct[case_names fempty finsert]: assumes "P {||}" and "\x S. \\y. y |\| S \ y < x; P S\ \ P (finsert x S)" shows "P S" proof - (* FIXME transfer and right_total vs. bi_total *) note Domainp_forall_transfer[transfer_rule] show ?thesis using assms by (transfer fixing: less) (auto intro: finite_linorder_max_induct) qed lemma fset_linorder_min_induct[case_names fempty finsert]: assumes "P {||}" and "\x S. \\y. y |\| S \ y > x; P S\ \ P (finsert x S)" shows "P S" proof - (* FIXME transfer and right_total vs. bi_total *) note Domainp_forall_transfer[transfer_rule] show ?thesis using assms by (transfer fixing: less) (auto intro: finite_linorder_min_induct) qed end subsection \Choice in fsets\ lemma fset_choice: assumes "\x. x |\| A \ (\y. P x y)" shows "\f. \x. x |\| A \ P x (f x)" using assms by transfer metis subsection \Induction and Cases rules for fsets\ lemma fset_exhaust [case_names empty insert, cases type: fset]: assumes fempty_case: "S = {||} \ P" and finsert_case: "\x S'. S = finsert x S' \ P" shows "P" using assms by transfer blast lemma fset_induct [case_names empty insert]: assumes fempty_case: "P {||}" and finsert_case: "\x S. P S \ P (finsert x S)" shows "P S" proof - (* FIXME transfer and right_total vs. bi_total *) note Domainp_forall_transfer[transfer_rule] show ?thesis using assms by transfer (auto intro: finite_induct) qed lemma fset_induct_stronger [case_names empty insert, induct type: fset]: assumes empty_fset_case: "P {||}" and insert_fset_case: "\x S. \x |\| S; P S\ \ P (finsert x S)" shows "P S" proof - (* FIXME transfer and right_total vs. bi_total *) note Domainp_forall_transfer[transfer_rule] show ?thesis using assms by transfer (auto intro: finite_induct) qed lemma fset_card_induct: assumes empty_fset_case: "P {||}" and card_fset_Suc_case: "\S T. Suc (fcard S) = (fcard T) \ P S \ P T" shows "P S" proof (induct S) case empty show "P {||}" by (rule empty_fset_case) next case (insert x S) have h: "P S" by fact have "x |\| S" by fact then have "Suc (fcard S) = fcard (finsert x S)" by transfer auto then show "P (finsert x S)" using h card_fset_Suc_case by simp qed lemma fset_strong_cases: obtains "xs = {||}" | ys x where "x |\| ys" and "xs = finsert x ys" by transfer blast 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_stronger) apply simp_all apply (induct_tac xa rule: fset_induct_stronger) apply simp_all done subsection \Setup for Lifting/Transfer\ subsubsection \Relator and predicator properties\ lift_definition rel_fset :: "('a \ 'b \ bool) \ 'a fset \ 'b fset \ bool" is rel_set parametric rel_set_transfer . lemma rel_fset_alt_def: "rel_fset R = (\A B. (\x.\y. x|\|A \ y|\|B \ R x y) \ (\y. \x. y|\|B \ x|\|A \ R x y))" apply (rule ext)+ apply transfer' apply (subst rel_set_def[unfolded fun_eq_iff]) by blast lemma finite_rel_set: assumes fin: "finite X" "finite Z" assumes R_S: "rel_set (R OO S) X Z" shows "\Y. finite Y \ rel_set R X Y \ rel_set S Y Z" proof - obtain f where f: "\x\X. R x (f x) \ (\z\Z. S (f x) z)" apply atomize_elim apply (subst bchoice_iff[symmetric]) using R_S[unfolded rel_set_def OO_def] by blast obtain g where g: "\z\Z. S (g z) z \ (\x\X. R x (g z))" apply atomize_elim apply (subst bchoice_iff[symmetric]) using R_S[unfolded rel_set_def OO_def] by blast let ?Y = "f ` X \ g ` Z" have "finite ?Y" by (simp add: fin) moreover have "rel_set R X ?Y" unfolding rel_set_def using f g by clarsimp blast moreover have "rel_set S ?Y Z" unfolding rel_set_def using f g by clarsimp blast ultimately show ?thesis by metis qed subsubsection \Transfer rules for the Transfer package\ text \Unconditional transfer rules\ context includes lifting_syntax begin lemma fempty_transfer [transfer_rule]: "rel_fset A {||} {||}" by (rule empty_transfer[Transfer.transferred]) lemma finsert_transfer [transfer_rule]: "(A ===> rel_fset A ===> rel_fset A) finsert finsert" unfolding rel_fun_def rel_fset_alt_def by blast lemma funion_transfer [transfer_rule]: "(rel_fset A ===> rel_fset A ===> rel_fset A) funion funion" unfolding rel_fun_def rel_fset_alt_def by blast lemma ffUnion_transfer [transfer_rule]: "(rel_fset (rel_fset A) ===> rel_fset A) ffUnion ffUnion" unfolding rel_fun_def rel_fset_alt_def by transfer (simp, fast) lemma fimage_transfer [transfer_rule]: "((A ===> B) ===> rel_fset A ===> rel_fset B) fimage fimage" unfolding rel_fun_def rel_fset_alt_def by simp blast lemma fBall_transfer [transfer_rule]: "(rel_fset A ===> (A ===> (=)) ===> (=)) fBall fBall" unfolding rel_fset_alt_def rel_fun_def by blast lemma fBex_transfer [transfer_rule]: "(rel_fset A ===> (A ===> (=)) ===> (=)) fBex fBex" unfolding rel_fset_alt_def rel_fun_def by blast (* FIXME transfer doesn't work here *) lemma fPow_transfer [transfer_rule]: "(rel_fset A ===> rel_fset (rel_fset A)) fPow fPow" unfolding rel_fun_def using Pow_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast lemma rel_fset_transfer [transfer_rule]: "((A ===> B ===> (=)) ===> rel_fset A ===> rel_fset B ===> (=)) rel_fset rel_fset" unfolding rel_fun_def using rel_set_transfer[unfolded rel_fun_def,rule_format, Transfer.transferred, where A = A and B = B] by simp lemma bind_transfer [transfer_rule]: "(rel_fset A ===> (A ===> rel_fset B) ===> rel_fset B) fbind fbind" unfolding rel_fun_def using bind_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast text \Rules requiring bi-unique, bi-total or right-total relations\ lemma fmember_transfer [transfer_rule]: assumes "bi_unique A" shows "(A ===> rel_fset A ===> (=)) (|\|) (|\|)" using assms unfolding rel_fun_def rel_fset_alt_def bi_unique_def by metis lemma finter_transfer [transfer_rule]: assumes "bi_unique A" shows "(rel_fset A ===> rel_fset A ===> rel_fset A) finter finter" using assms unfolding rel_fun_def using inter_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast lemma fminus_transfer [transfer_rule]: assumes "bi_unique A" shows "(rel_fset A ===> rel_fset A ===> rel_fset A) (|-|) (|-|)" using assms unfolding rel_fun_def using Diff_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast lemma fsubset_transfer [transfer_rule]: assumes "bi_unique A" shows "(rel_fset A ===> rel_fset A ===> (=)) (|\|) (|\|)" using assms unfolding rel_fun_def using subset_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast lemma fSup_transfer [transfer_rule]: "bi_unique A \ (rel_set (rel_fset A) ===> rel_fset A) Sup Sup" unfolding rel_fun_def apply clarify apply transfer' using Sup_fset_transfer[unfolded rel_fun_def] by blast (* FIXME: add right_total_fInf_transfer *) lemma fInf_transfer [transfer_rule]: assumes "bi_unique A" and "bi_total A" shows "(rel_set (rel_fset A) ===> rel_fset A) Inf Inf" using assms unfolding rel_fun_def apply clarify apply transfer' using Inf_fset_transfer[unfolded rel_fun_def] by blast lemma ffilter_transfer [transfer_rule]: assumes "bi_unique A" shows "((A ===> (=)) ===> rel_fset A ===> rel_fset A) ffilter ffilter" using assms unfolding rel_fun_def using Lifting_Set.filter_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast lemma card_transfer [transfer_rule]: "bi_unique A \ (rel_fset A ===> (=)) fcard fcard" unfolding rel_fun_def using card_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast end lifting_update fset.lifting lifting_forget fset.lifting subsection \BNF setup\ context includes fset.lifting begin lemma rel_fset_alt: "rel_fset R a b \ (\t \ fset a. \u \ fset b. R t u) \ (\t \ fset b. \u \ fset a. R u t)" by transfer (simp add: rel_set_def) lemma fset_to_fset: "finite A \ fset (the_inv fset A) = A" apply (rule f_the_inv_into_f[unfolded inj_on_def]) apply (simp add: fset_inject) apply (rule range_eqI Abs_fset_inverse[symmetric] CollectI)+ . lemma rel_fset_aux: "(\t \ fset a. \u \ fset b. R t u) \ (\u \ fset b. \t \ fset a. R t u) \ ((BNF_Def.Grp {a. fset a \ {(a, b). R a b}} (fimage fst))\\ OO BNF_Def.Grp {a. fset a \ {(a, b). R a b}} (fimage snd)) a b" (is "?L = ?R") proof assume ?L define R' where "R' = the_inv fset (Collect (case_prod R) \ (fset a \ fset b))" (is "_ = the_inv fset ?L'") have "finite ?L'" by (intro finite_Int[OF disjI2] finite_cartesian_product) (transfer, simp)+ hence *: "fset R' = ?L'" unfolding R'_def by (intro fset_to_fset) show ?R unfolding Grp_def relcompp.simps conversep.simps proof (intro CollectI case_prodI exI[of _ a] exI[of _ b] exI[of _ R'] conjI refl) from * show "a = fimage fst R'" using conjunct1[OF \?L\] by (transfer, auto simp add: image_def Int_def split: prod.splits) from * show "b = fimage snd R'" using conjunct2[OF \?L\] by (transfer, auto simp add: image_def Int_def split: prod.splits) qed (auto simp add: *) next assume ?R thus ?L unfolding Grp_def relcompp.simps conversep.simps apply (simp add: subset_eq Ball_def) apply (rule conjI) apply (transfer, clarsimp, metis snd_conv) by (transfer, clarsimp, metis fst_conv) qed bnf "'a fset" map: fimage sets: fset bd: natLeq wits: "{||}" rel: rel_fset apply - apply transfer' apply simp apply transfer' apply force apply transfer apply force apply transfer' apply force apply (rule natLeq_card_order) apply (rule natLeq_cinfinite) apply (rule regularCard_natLeq) apply transfer apply (metis finite_iff_ordLess_natLeq) apply (fastforce simp: rel_fset_alt) apply (simp add: Grp_def relcompp.simps conversep.simps fun_eq_iff rel_fset_alt rel_fset_aux[unfolded OO_Grp_alt]) apply transfer apply simp done lemma rel_fset_fset: "rel_set \ (fset A1) (fset A2) = rel_fset \ A1 A2" by transfer (rule refl) end declare fset.map_comp[simp] fset.map_id[simp] fset.set_map[simp] subsection \Size setup\ context includes fset.lifting begin lift_definition size_fset :: "('a \ nat) \ 'a fset \ nat" is "\f. sum (Suc \ f)" . end instantiation fset :: (type) size begin definition size_fset where size_fset_overloaded_def: "size_fset = FSet.size_fset (\_. 0)" instance .. end lemma size_fset_simps[simp]: "size_fset f X = (\x \ fset X. Suc (f x))" by (rule size_fset_def[THEN meta_eq_to_obj_eq, THEN fun_cong, THEN fun_cong, unfolded map_fun_def comp_def id_apply]) lemma size_fset_overloaded_simps[simp]: "size X = (\x \ fset X. Suc 0)" by (rule size_fset_simps[of "\_. 0", unfolded add_0_left add_0_right, folded size_fset_overloaded_def]) lemma fset_size_o_map: "inj f \ size_fset g \ fimage f = size_fset (g \ f)" apply (subst fun_eq_iff) including fset.lifting by transfer (auto intro: sum.reindex_cong subset_inj_on) setup \ BNF_LFP_Size.register_size_global \<^type_name>\fset\ \<^const_name>\size_fset\ @{thm size_fset_overloaded_def} @{thms size_fset_simps size_fset_overloaded_simps} @{thms fset_size_o_map} \ lifting_update fset.lifting lifting_forget fset.lifting subsection \Advanced relator customization\ text \Set vs. sum relators:\ lemma rel_set_rel_sum[simp]: "rel_set (rel_sum \ \) A1 A2 \ rel_set \ (Inl -` A1) (Inl -` A2) \ rel_set \ (Inr -` A1) (Inr -` A2)" (is "?L \ ?Rl \ ?Rr") proof safe assume L: "?L" show ?Rl unfolding rel_set_def Bex_def vimage_eq proof safe fix l1 assume "Inl l1 \ A1" then obtain a2 where a2: "a2 \ A2" and "rel_sum \ \ (Inl l1) a2" using L unfolding rel_set_def by auto then obtain l2 where "a2 = Inl l2 \ \ l1 l2" by (cases a2, auto) thus "\ l2. Inl l2 \ A2 \ \ l1 l2" using a2 by auto next fix l2 assume "Inl l2 \ A2" then obtain a1 where a1: "a1 \ A1" and "rel_sum \ \ a1 (Inl l2)" using L unfolding rel_set_def by auto then obtain l1 where "a1 = Inl l1 \ \ l1 l2" by (cases a1, auto) thus "\ l1. Inl l1 \ A1 \ \ l1 l2" using a1 by auto qed show ?Rr unfolding rel_set_def Bex_def vimage_eq proof safe fix r1 assume "Inr r1 \ A1" then obtain a2 where a2: "a2 \ A2" and "rel_sum \ \ (Inr r1) a2" using L unfolding rel_set_def by auto then obtain r2 where "a2 = Inr r2 \ \ r1 r2" by (cases a2, auto) thus "\ r2. Inr r2 \ A2 \ \ r1 r2" using a2 by auto next fix r2 assume "Inr r2 \ A2" then obtain a1 where a1: "a1 \ A1" and "rel_sum \ \ a1 (Inr r2)" using L unfolding rel_set_def by auto then obtain r1 where "a1 = Inr r1 \ \ r1 r2" by (cases a1, auto) thus "\ r1. Inr r1 \ A1 \ \ r1 r2" using a1 by auto qed next assume Rl: "?Rl" and Rr: "?Rr" show ?L unfolding rel_set_def Bex_def vimage_eq proof safe fix a1 assume a1: "a1 \ A1" show "\ a2. a2 \ A2 \ rel_sum \ \ a1 a2" proof(cases a1) case (Inl l1) then obtain l2 where "Inl l2 \ A2 \ \ l1 l2" using Rl a1 unfolding rel_set_def by blast thus ?thesis unfolding Inl by auto next case (Inr r1) then obtain r2 where "Inr r2 \ A2 \ \ r1 r2" using Rr a1 unfolding rel_set_def by blast thus ?thesis unfolding Inr by auto qed next fix a2 assume a2: "a2 \ A2" show "\ a1. a1 \ A1 \ rel_sum \ \ a1 a2" proof(cases a2) case (Inl l2) then obtain l1 where "Inl l1 \ A1 \ \ l1 l2" using Rl a2 unfolding rel_set_def by blast thus ?thesis unfolding Inl by auto next case (Inr r2) then obtain r1 where "Inr r1 \ A1 \ \ r1 r2" using Rr a2 unfolding rel_set_def by blast thus ?thesis unfolding Inr by auto qed qed qed subsubsection \Countability\ lemma exists_fset_of_list: "\xs. fset_of_list xs = S" including fset.lifting by transfer (rule finite_list) lemma fset_of_list_surj[simp, intro]: "surj fset_of_list" proof - have "x \ range fset_of_list" for x :: "'a fset" unfolding image_iff using exists_fset_of_list by fastforce thus ?thesis by auto qed instance fset :: (countable) countable proof obtain to_nat :: "'a list \ nat" where "inj to_nat" by (metis ex_inj) moreover have "inj (inv fset_of_list)" using fset_of_list_surj by (rule surj_imp_inj_inv) ultimately have "inj (to_nat \ inv fset_of_list)" by (rule inj_compose) thus "\to_nat::'a fset \ nat. inj to_nat" by auto qed subsection \Quickcheck setup\ text \Setup adapted from sets.\ notation Quickcheck_Exhaustive.orelse (infixr "orelse" 55) context includes term_syntax begin definition [code_unfold]: "valterm_femptyset = Code_Evaluation.valtermify ({||} :: ('a :: typerep) fset)" definition [code_unfold]: "valtermify_finsert x s = Code_Evaluation.valtermify finsert {\} (x :: ('a :: typerep * _)) {\} s" end instantiation fset :: (exhaustive) exhaustive begin fun exhaustive_fset where "exhaustive_fset f i = (if i = 0 then None else (f {||} orelse exhaustive_fset (\A. f A orelse Quickcheck_Exhaustive.exhaustive (\x. if x |\| A then None else f (finsert x A)) (i - 1)) (i - 1)))" instance .. end instantiation fset :: (full_exhaustive) full_exhaustive begin fun full_exhaustive_fset where "full_exhaustive_fset f i = (if i = 0 then None else (f valterm_femptyset orelse full_exhaustive_fset (\A. f A orelse Quickcheck_Exhaustive.full_exhaustive (\x. if fst x |\| fst A then None else f (valtermify_finsert x A)) (i - 1)) (i - 1)))" instance .. end no_notation Quickcheck_Exhaustive.orelse (infixr "orelse" 55) instantiation fset :: (random) random begin context includes state_combinator_syntax begin fun random_aux_fset :: "natural \ natural \ natural \ natural \ ('a fset \ (unit \ term)) \ natural \ natural" where "random_aux_fset 0 j = Quickcheck_Random.collapse (Random.select_weight [(1, Pair valterm_femptyset)])" | "random_aux_fset (Code_Numeral.Suc i) j = Quickcheck_Random.collapse (Random.select_weight [(1, Pair valterm_femptyset), (Code_Numeral.Suc i, Quickcheck_Random.random j \\ (\x. random_aux_fset i j \\ (\s. Pair (valtermify_finsert x s))))])" lemma [code]: "random_aux_fset i j = Quickcheck_Random.collapse (Random.select_weight [(1, Pair valterm_femptyset), (i, Quickcheck_Random.random j \\ (\x. random_aux_fset (i - 1) j \\ (\s. Pair (valtermify_finsert x s))))])" proof (induct i rule: natural.induct) case zero show ?case by (subst select_weight_drop_zero[symmetric]) (simp add: less_natural_def) next case (Suc i) show ?case by (simp only: random_aux_fset.simps Suc_natural_minus_one) qed definition "random_fset i = random_aux_fset i i" instance .. end end end diff --git a/src/HOL/Library/Finite_Map.thy b/src/HOL/Library/Finite_Map.thy --- a/src/HOL/Library/Finite_Map.thy +++ b/src/HOL/Library/Finite_Map.thy @@ -1,1462 +1,1462 @@ (* Title: HOL/Library/Finite_Map.thy Author: Lars Hupel, TU München *) section \Type of finite maps defined as a subtype of maps\ theory Finite_Map imports FSet AList Conditional_Parametricity abbrevs "(=" = "\\<^sub>f" begin subsection \Auxiliary constants and lemmas over \<^type>\map\\ parametric_constant map_add_transfer[transfer_rule]: map_add_def parametric_constant map_of_transfer[transfer_rule]: map_of_def context includes lifting_syntax begin abbreviation rel_map :: "('b \ 'c \ bool) \ ('a \ 'b) \ ('a \ 'c) \ bool" where "rel_map f \ (=) ===> rel_option f" lemma ran_transfer[transfer_rule]: "(rel_map A ===> rel_set A) ran ran" proof fix m n assume "rel_map A m n" show "rel_set A (ran m) (ran n)" proof (rule rel_setI) fix x assume "x \ ran m" then obtain a where "m a = Some x" unfolding ran_def by auto have "rel_option A (m a) (n a)" using \rel_map A m n\ by (auto dest: rel_funD) then obtain y where "n a = Some y" "A x y" unfolding \m a = _\ by cases auto then show "\y \ ran n. A x y" unfolding ran_def by blast next fix y assume "y \ ran n" then obtain a where "n a = Some y" unfolding ran_def by auto have "rel_option A (m a) (n a)" using \rel_map A m n\ by (auto dest: rel_funD) then obtain x where "m a = Some x" "A x y" unfolding \n a = _\ by cases auto then show "\x \ ran m. A x y" unfolding ran_def by blast qed qed lemma ran_alt_def: "ran m = (the \ m) ` dom m" unfolding ran_def dom_def by force parametric_constant dom_transfer[transfer_rule]: dom_def definition map_upd :: "'a \ 'b \ ('a \ 'b) \ ('a \ 'b)" where "map_upd k v m = m(k \ v)" parametric_constant map_upd_transfer[transfer_rule]: map_upd_def definition map_filter :: "('a \ bool) \ ('a \ 'b) \ ('a \ 'b)" where "map_filter P m = (\x. if P x then m x else None)" parametric_constant map_filter_transfer[transfer_rule]: map_filter_def lemma map_filter_map_of[simp]: "map_filter P (map_of m) = map_of [(k, _) \ m. P k]" proof fix x show "map_filter P (map_of m) x = map_of [(k, _) \ m. P k] x" by (induct m) (auto simp: map_filter_def) qed lemma map_filter_finite[intro]: assumes "finite (dom m)" shows "finite (dom (map_filter P m))" proof - have "dom (map_filter P m) = Set.filter P (dom m)" unfolding map_filter_def Set.filter_def dom_def by auto then show ?thesis using assms by (simp add: Set.filter_def) qed definition map_drop :: "'a \ ('a \ 'b) \ ('a \ 'b)" where "map_drop a = map_filter (\a'. a' \ a)" parametric_constant map_drop_transfer[transfer_rule]: map_drop_def definition map_drop_set :: "'a set \ ('a \ 'b) \ ('a \ 'b)" where "map_drop_set A = map_filter (\a. a \ A)" parametric_constant map_drop_set_transfer[transfer_rule]: map_drop_set_def definition map_restrict_set :: "'a set \ ('a \ 'b) \ ('a \ 'b)" where "map_restrict_set A = map_filter (\a. a \ A)" parametric_constant map_restrict_set_transfer[transfer_rule]: map_restrict_set_def definition map_pred :: "('a \ 'b \ bool) \ ('a \ 'b) \ bool" where "map_pred P m \ (\x. case m x of None \ True | Some y \ P x y)" parametric_constant map_pred_transfer[transfer_rule]: map_pred_def definition rel_map_on_set :: "'a set \ ('b \ 'c \ bool) \ ('a \ 'b) \ ('a \ 'c) \ bool" where "rel_map_on_set S P = eq_onp (\x. x \ S) ===> rel_option P" definition set_of_map :: "('a \ 'b) \ ('a \ 'b) set" where "set_of_map m = {(k, v)|k v. m k = Some v}" lemma set_of_map_alt_def: "set_of_map m = (\k. (k, the (m k))) ` dom m" unfolding set_of_map_def dom_def by auto lemma set_of_map_finite: "finite (dom m) \ finite (set_of_map m)" unfolding set_of_map_alt_def by auto lemma set_of_map_inj: "inj set_of_map" proof fix x y assume "set_of_map x = set_of_map y" hence "(x a = Some b) = (y a = Some b)" for a b unfolding set_of_map_def by auto hence "x k = y k" for k by (metis not_None_eq) thus "x = y" .. qed lemma dom_comp: "dom (m \\<^sub>m n) \ dom n" unfolding map_comp_def dom_def by (auto split: option.splits) lemma dom_comp_finite: "finite (dom n) \ finite (dom (map_comp m n))" by (metis finite_subset dom_comp) parametric_constant map_comp_transfer[transfer_rule]: map_comp_def end subsection \Abstract characterisation\ typedef ('a, 'b) fmap = "{m. finite (dom m)} :: ('a \ 'b) set" morphisms fmlookup Abs_fmap proof show "Map.empty \ {m. finite (dom m)}" by auto qed setup_lifting type_definition_fmap lemma dom_fmlookup_finite[intro, simp]: "finite (dom (fmlookup m))" using fmap.fmlookup by auto lemma fmap_ext: assumes "\x. fmlookup m x = fmlookup n x" shows "m = n" using assms by transfer' auto subsection \Operations\ context includes fset.lifting begin lift_definition fmran :: "('a, 'b) fmap \ 'b fset" is ran parametric ran_transfer by (rule finite_ran) lemma fmlookup_ran_iff: "y |\| fmran m \ (\x. fmlookup m x = Some y)" by transfer' (auto simp: ran_def) lemma fmranI: "fmlookup m x = Some y \ y |\| fmran m" by (auto simp: fmlookup_ran_iff) lemma fmranE[elim]: assumes "y |\| fmran m" obtains x where "fmlookup m x = Some y" using assms by (auto simp: fmlookup_ran_iff) lift_definition fmdom :: "('a, 'b) fmap \ 'a fset" is dom parametric dom_transfer . lemma fmlookup_dom_iff: "x |\| fmdom m \ (\a. fmlookup m x = Some a)" by transfer' auto lemma fmdom_notI: "fmlookup m x = None \ x |\| fmdom m" by (simp add: fmlookup_dom_iff) lemma fmdomI: "fmlookup m x = Some y \ x |\| fmdom m" by (simp add: fmlookup_dom_iff) lemma fmdom_notD[dest]: "x |\| fmdom m \ fmlookup m x = None" by (simp add: fmlookup_dom_iff) lemma fmdomE[elim]: assumes "x |\| fmdom m" obtains y where "fmlookup m x = Some y" using assms by (auto simp: fmlookup_dom_iff) lift_definition fmdom' :: "('a, 'b) fmap \ 'a set" is dom parametric dom_transfer . lemma fmlookup_dom'_iff: "x \ fmdom' m \ (\a. fmlookup m x = Some a)" by transfer' auto lemma fmdom'_notI: "fmlookup m x = None \ x \ fmdom' m" by (simp add: fmlookup_dom'_iff) lemma fmdom'I: "fmlookup m x = Some y \ x \ fmdom' m" by (simp add: fmlookup_dom'_iff) lemma fmdom'_notD[dest]: "x \ fmdom' m \ fmlookup m x = None" by (simp add: fmlookup_dom'_iff) lemma fmdom'E[elim]: assumes "x \ fmdom' m" obtains x y where "fmlookup m x = Some y" using assms by (auto simp: fmlookup_dom'_iff) lemma fmdom'_alt_def: "fmdom' m = fset (fmdom m)" by transfer' force lemma finite_fmdom'[simp]: "finite (fmdom' m)" unfolding fmdom'_alt_def by simp lemma dom_fmlookup[simp]: "dom (fmlookup m) = fmdom' m" by transfer' simp lift_definition fmempty :: "('a, 'b) fmap" is Map.empty by simp lemma fmempty_lookup[simp]: "fmlookup fmempty x = None" by transfer' simp lemma fmdom_empty[simp]: "fmdom fmempty = {||}" by transfer' simp lemma fmdom'_empty[simp]: "fmdom' fmempty = {}" by transfer' simp lemma fmran_empty[simp]: "fmran fmempty = fempty" by transfer' (auto simp: ran_def map_filter_def) lift_definition fmupd :: "'a \ 'b \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_upd parametric map_upd_transfer unfolding map_upd_def[abs_def] by simp lemma fmupd_lookup[simp]: "fmlookup (fmupd a b m) a' = (if a = a' then Some b else fmlookup m a')" by transfer' (auto simp: map_upd_def) lemma fmdom_fmupd[simp]: "fmdom (fmupd a b m) = finsert a (fmdom m)" by transfer (simp add: map_upd_def) lemma fmdom'_fmupd[simp]: "fmdom' (fmupd a b m) = insert a (fmdom' m)" by transfer (simp add: map_upd_def) lemma fmupd_reorder_neq: assumes "a \ b" shows "fmupd a x (fmupd b y m) = fmupd b y (fmupd a x m)" using assms by transfer' (auto simp: map_upd_def) lemma fmupd_idem[simp]: "fmupd a x (fmupd a y m) = fmupd a x m" by transfer' (auto simp: map_upd_def) lift_definition fmfilter :: "('a \ bool) \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_filter parametric map_filter_transfer by auto lemma fmdom_filter[simp]: "fmdom (fmfilter P m) = ffilter P (fmdom m)" by transfer' (auto simp: map_filter_def Set.filter_def split: if_splits) lemma fmdom'_filter[simp]: "fmdom' (fmfilter P m) = Set.filter P (fmdom' m)" by transfer' (auto simp: map_filter_def Set.filter_def split: if_splits) lemma fmlookup_filter[simp]: "fmlookup (fmfilter P m) x = (if P x then fmlookup m x else None)" by transfer' (auto simp: map_filter_def) lemma fmfilter_empty[simp]: "fmfilter P fmempty = fmempty" by transfer' (auto simp: map_filter_def) lemma fmfilter_true[simp]: assumes "\x y. fmlookup m x = Some y \ P x" shows "fmfilter P m = m" proof (rule fmap_ext) fix x have "fmlookup m x = None" if "\ P x" using that assms by fastforce then show "fmlookup (fmfilter P m) x = fmlookup m x" by simp qed lemma fmfilter_false[simp]: assumes "\x y. fmlookup m x = Some y \ \ P x" shows "fmfilter P m = fmempty" using assms by transfer' (fastforce simp: map_filter_def) lemma fmfilter_comp[simp]: "fmfilter P (fmfilter Q m) = fmfilter (\x. P x \ Q x) m" by transfer' (auto simp: map_filter_def) lemma fmfilter_comm: "fmfilter P (fmfilter Q m) = fmfilter Q (fmfilter P m)" unfolding fmfilter_comp by meson lemma fmfilter_cong[cong]: assumes "\x y. fmlookup m x = Some y \ P x = Q x" shows "fmfilter P m = fmfilter Q m" proof (rule fmap_ext) fix x have "fmlookup m x = None" if "P x \ Q x" using that assms by fastforce then show "fmlookup (fmfilter P m) x = fmlookup (fmfilter Q m) x" by auto qed lemma fmfilter_cong'[fundef_cong]: assumes "m = n" "\x. x \ fmdom' m \ P x = Q x" shows "fmfilter P m = fmfilter Q n" using assms(2) unfolding assms(1) by (rule fmfilter_cong) (metis fmdom'I) lemma fmfilter_upd[simp]: "fmfilter P (fmupd x y m) = (if P x then fmupd x y (fmfilter P m) else fmfilter P m)" by transfer' (auto simp: map_upd_def map_filter_def) lift_definition fmdrop :: "'a \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_drop parametric map_drop_transfer unfolding map_drop_def by auto lemma fmdrop_lookup[simp]: "fmlookup (fmdrop a m) a = None" by transfer' (auto simp: map_drop_def map_filter_def) lift_definition fmdrop_set :: "'a set \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_drop_set parametric map_drop_set_transfer unfolding map_drop_set_def by auto lift_definition fmdrop_fset :: "'a fset \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_drop_set parametric map_drop_set_transfer unfolding map_drop_set_def by auto lift_definition fmrestrict_set :: "'a set \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_restrict_set parametric map_restrict_set_transfer unfolding map_restrict_set_def by auto lift_definition fmrestrict_fset :: "'a fset \ ('a, 'b) fmap \ ('a, 'b) fmap" is map_restrict_set parametric map_restrict_set_transfer unfolding map_restrict_set_def by auto lemma fmfilter_alt_defs: "fmdrop a = fmfilter (\a'. a' \ a)" "fmdrop_set A = fmfilter (\a. a \ A)" "fmdrop_fset B = fmfilter (\a. a |\| B)" "fmrestrict_set A = fmfilter (\a. a \ A)" "fmrestrict_fset B = fmfilter (\a. a |\| B)" by (transfer'; simp add: map_drop_def map_drop_set_def map_restrict_set_def)+ lemma fmdom_drop[simp]: "fmdom (fmdrop a m) = fmdom m - {|a|}" unfolding fmfilter_alt_defs by auto lemma fmdom'_drop[simp]: "fmdom' (fmdrop a m) = fmdom' m - {a}" unfolding fmfilter_alt_defs by auto lemma fmdom'_drop_set[simp]: "fmdom' (fmdrop_set A m) = fmdom' m - A" unfolding fmfilter_alt_defs by auto lemma fmdom_drop_fset[simp]: "fmdom (fmdrop_fset A m) = fmdom m - A" unfolding fmfilter_alt_defs by auto lemma fmdom'_restrict_set: "fmdom' (fmrestrict_set A m) \ A" unfolding fmfilter_alt_defs by auto lemma fmdom_restrict_fset: "fmdom (fmrestrict_fset A m) |\| A" unfolding fmfilter_alt_defs by auto lemma fmdrop_fmupd: "fmdrop x (fmupd y z m) = (if x = y then fmdrop x m else fmupd y z (fmdrop x m))" by transfer' (auto simp: map_drop_def map_filter_def map_upd_def) lemma fmdrop_idle: "x |\| fmdom B \ fmdrop x B = B" by transfer' (auto simp: map_drop_def map_filter_def) lemma fmdrop_idle': "x \ fmdom' B \ fmdrop x B = B" by transfer' (auto simp: map_drop_def map_filter_def) lemma fmdrop_fmupd_same: "fmdrop x (fmupd x y m) = fmdrop x m" by transfer' (auto simp: map_drop_def map_filter_def map_upd_def) lemma fmdom'_restrict_set_precise: "fmdom' (fmrestrict_set A m) = fmdom' m \ A" unfolding fmfilter_alt_defs by auto lemma fmdom'_restrict_fset_precise: "fmdom (fmrestrict_fset A m) = fmdom m |\| A" unfolding fmfilter_alt_defs by auto lemma fmdom'_drop_fset[simp]: "fmdom' (fmdrop_fset A m) = fmdom' m - fset A" unfolding fmfilter_alt_defs by transfer' (auto simp: map_filter_def split: if_splits) lemma fmdom'_restrict_fset: "fmdom' (fmrestrict_fset A m) \ fset A" unfolding fmfilter_alt_defs by transfer' (auto simp: map_filter_def) lemma fmlookup_drop[simp]: "fmlookup (fmdrop a m) x = (if x \ a then fmlookup m x else None)" unfolding fmfilter_alt_defs by simp lemma fmlookup_drop_set[simp]: "fmlookup (fmdrop_set A m) x = (if x \ A then fmlookup m x else None)" unfolding fmfilter_alt_defs by simp lemma fmlookup_drop_fset[simp]: "fmlookup (fmdrop_fset A m) x = (if x |\| A then fmlookup m x else None)" unfolding fmfilter_alt_defs by simp lemma fmlookup_restrict_set[simp]: "fmlookup (fmrestrict_set A m) x = (if x \ A then fmlookup m x else None)" unfolding fmfilter_alt_defs by simp lemma fmlookup_restrict_fset[simp]: "fmlookup (fmrestrict_fset A m) x = (if x |\| A then fmlookup m x else None)" unfolding fmfilter_alt_defs by simp lemma fmrestrict_set_dom[simp]: "fmrestrict_set (fmdom' m) m = m" by (rule fmap_ext) auto lemma fmrestrict_fset_dom[simp]: "fmrestrict_fset (fmdom m) m = m" by (rule fmap_ext) auto lemma fmdrop_empty[simp]: "fmdrop a fmempty = fmempty" unfolding fmfilter_alt_defs by simp lemma fmdrop_set_empty[simp]: "fmdrop_set A fmempty = fmempty" unfolding fmfilter_alt_defs by simp lemma fmdrop_fset_empty[simp]: "fmdrop_fset A fmempty = fmempty" unfolding fmfilter_alt_defs by simp lemma fmdrop_fset_fmdom[simp]: "fmdrop_fset (fmdom A) A = fmempty" by transfer' (auto simp: map_drop_set_def map_filter_def) lemma fmdrop_set_fmdom[simp]: "fmdrop_set (fmdom' A) A = fmempty" by transfer' (auto simp: map_drop_set_def map_filter_def) lemma fmrestrict_set_empty[simp]: "fmrestrict_set A fmempty = fmempty" unfolding fmfilter_alt_defs by simp lemma fmrestrict_fset_empty[simp]: "fmrestrict_fset A fmempty = fmempty" unfolding fmfilter_alt_defs by simp lemma fmdrop_set_null[simp]: "fmdrop_set {} m = m" by (rule fmap_ext) auto lemma fmdrop_fset_null[simp]: "fmdrop_fset {||} m = m" by (rule fmap_ext) auto lemma fmdrop_set_single[simp]: "fmdrop_set {a} m = fmdrop a m" unfolding fmfilter_alt_defs by simp lemma fmdrop_fset_single[simp]: "fmdrop_fset {|a|} m = fmdrop a m" unfolding fmfilter_alt_defs by simp lemma fmrestrict_set_null[simp]: "fmrestrict_set {} m = fmempty" unfolding fmfilter_alt_defs by simp lemma fmrestrict_fset_null[simp]: "fmrestrict_fset {||} m = fmempty" unfolding fmfilter_alt_defs by simp lemma fmdrop_comm: "fmdrop a (fmdrop b m) = fmdrop b (fmdrop a m)" unfolding fmfilter_alt_defs by (rule fmfilter_comm) lemma fmdrop_set_insert[simp]: "fmdrop_set (insert x S) m = fmdrop x (fmdrop_set S m)" by (rule fmap_ext) auto lemma fmdrop_fset_insert[simp]: "fmdrop_fset (finsert x S) m = fmdrop x (fmdrop_fset S m)" by (rule fmap_ext) auto lemma fmrestrict_set_twice[simp]: "fmrestrict_set S (fmrestrict_set T m) = fmrestrict_set (S \ T) m" unfolding fmfilter_alt_defs by auto lemma fmrestrict_fset_twice[simp]: "fmrestrict_fset S (fmrestrict_fset T m) = fmrestrict_fset (S |\| T) m" unfolding fmfilter_alt_defs by auto lemma fmrestrict_set_drop[simp]: "fmrestrict_set S (fmdrop b m) = fmrestrict_set (S - {b}) m" unfolding fmfilter_alt_defs by auto lemma fmrestrict_fset_drop[simp]: "fmrestrict_fset S (fmdrop b m) = fmrestrict_fset (S - {| b |}) m" unfolding fmfilter_alt_defs by auto lemma fmdrop_fmrestrict_set[simp]: "fmdrop b (fmrestrict_set S m) = fmrestrict_set (S - {b}) m" by (rule fmap_ext) auto lemma fmdrop_fmrestrict_fset[simp]: "fmdrop b (fmrestrict_fset S m) = fmrestrict_fset (S - {| b |}) m" by (rule fmap_ext) auto lemma fmdrop_idem[simp]: "fmdrop a (fmdrop a m) = fmdrop a m" unfolding fmfilter_alt_defs by auto lemma fmdrop_set_twice[simp]: "fmdrop_set S (fmdrop_set T m) = fmdrop_set (S \ T) m" unfolding fmfilter_alt_defs by auto lemma fmdrop_fset_twice[simp]: "fmdrop_fset S (fmdrop_fset T m) = fmdrop_fset (S |\| T) m" unfolding fmfilter_alt_defs by auto lemma fmdrop_set_fmdrop[simp]: "fmdrop_set S (fmdrop b m) = fmdrop_set (insert b S) m" by (rule fmap_ext) auto lemma fmdrop_fset_fmdrop[simp]: "fmdrop_fset S (fmdrop b m) = fmdrop_fset (finsert b S) m" by (rule fmap_ext) auto lift_definition fmadd :: "('a, 'b) fmap \ ('a, 'b) fmap \ ('a, 'b) fmap" (infixl "++\<^sub>f" 100) is map_add parametric map_add_transfer by simp lemma fmlookup_add[simp]: "fmlookup (m ++\<^sub>f n) x = (if x |\| fmdom n then fmlookup n x else fmlookup m x)" by transfer' (auto simp: map_add_def split: option.splits) lemma fmdom_add[simp]: "fmdom (m ++\<^sub>f n) = fmdom m |\| fmdom n" by transfer' auto lemma fmdom'_add[simp]: "fmdom' (m ++\<^sub>f n) = fmdom' m \ fmdom' n" by transfer' auto lemma fmadd_drop_left_dom: "fmdrop_fset (fmdom n) m ++\<^sub>f n = m ++\<^sub>f n" by (rule fmap_ext) auto lemma fmadd_restrict_right_dom: "fmrestrict_fset (fmdom n) (m ++\<^sub>f n) = n" by (rule fmap_ext) auto lemma fmfilter_add_distrib[simp]: "fmfilter P (m ++\<^sub>f n) = fmfilter P m ++\<^sub>f fmfilter P n" by transfer' (auto simp: map_filter_def map_add_def) lemma fmdrop_add_distrib[simp]: "fmdrop a (m ++\<^sub>f n) = fmdrop a m ++\<^sub>f fmdrop a n" unfolding fmfilter_alt_defs by simp lemma fmdrop_set_add_distrib[simp]: "fmdrop_set A (m ++\<^sub>f n) = fmdrop_set A m ++\<^sub>f fmdrop_set A n" unfolding fmfilter_alt_defs by simp lemma fmdrop_fset_add_distrib[simp]: "fmdrop_fset A (m ++\<^sub>f n) = fmdrop_fset A m ++\<^sub>f fmdrop_fset A n" unfolding fmfilter_alt_defs by simp lemma fmrestrict_set_add_distrib[simp]: "fmrestrict_set A (m ++\<^sub>f n) = fmrestrict_set A m ++\<^sub>f fmrestrict_set A n" unfolding fmfilter_alt_defs by simp lemma fmrestrict_fset_add_distrib[simp]: "fmrestrict_fset A (m ++\<^sub>f n) = fmrestrict_fset A m ++\<^sub>f fmrestrict_fset A n" unfolding fmfilter_alt_defs by simp lemma fmadd_empty[simp]: "fmempty ++\<^sub>f m = m" "m ++\<^sub>f fmempty = m" by (transfer'; auto)+ lemma fmadd_idempotent[simp]: "m ++\<^sub>f m = m" by transfer' (auto simp: map_add_def split: option.splits) lemma fmadd_assoc[simp]: "m ++\<^sub>f (n ++\<^sub>f p) = m ++\<^sub>f n ++\<^sub>f p" by transfer' simp lemma fmadd_fmupd[simp]: "m ++\<^sub>f fmupd a b n = fmupd a b (m ++\<^sub>f n)" by (rule fmap_ext) simp lift_definition fmpred :: "('a \ 'b \ bool) \ ('a, 'b) fmap \ bool" is map_pred parametric map_pred_transfer . lemma fmpredI[intro]: assumes "\x y. fmlookup m x = Some y \ P x y" shows "fmpred P m" using assms by transfer' (auto simp: map_pred_def split: option.splits) lemma fmpredD[dest]: "fmpred P m \ fmlookup m x = Some y \ P x y" by transfer' (auto simp: map_pred_def split: option.split_asm) lemma fmpred_iff: "fmpred P m \ (\x y. fmlookup m x = Some y \ P x y)" by auto lemma fmpred_alt_def: "fmpred P m \ fBall (fmdom m) (\x. P x (the (fmlookup m x)))" unfolding fmpred_iff apply auto apply (rename_tac x y) apply (erule_tac x = x in fBallE) apply simp by (simp add: fmlookup_dom_iff) lemma fmpred_mono_strong: assumes "\x y. fmlookup m x = Some y \ P x y \ Q x y" shows "fmpred P m \ fmpred Q m" using assms unfolding fmpred_iff by auto lemma fmpred_mono[mono]: "P \ Q \ fmpred P \ fmpred Q" apply rule apply (rule fmpred_mono_strong[where P = P and Q = Q]) apply auto done lemma fmpred_empty[intro!, simp]: "fmpred P fmempty" by auto lemma fmpred_upd[intro]: "fmpred P m \ P x y \ fmpred P (fmupd x y m)" by transfer' (auto simp: map_pred_def map_upd_def) lemma fmpred_updD[dest]: "fmpred P (fmupd x y m) \ P x y" by auto lemma fmpred_add[intro]: "fmpred P m \ fmpred P n \ fmpred P (m ++\<^sub>f n)" by transfer' (auto simp: map_pred_def map_add_def split: option.splits) lemma fmpred_filter[intro]: "fmpred P m \ fmpred P (fmfilter Q m)" by transfer' (auto simp: map_pred_def map_filter_def) lemma fmpred_drop[intro]: "fmpred P m \ fmpred P (fmdrop a m)" by (auto simp: fmfilter_alt_defs) lemma fmpred_drop_set[intro]: "fmpred P m \ fmpred P (fmdrop_set A m)" by (auto simp: fmfilter_alt_defs) lemma fmpred_drop_fset[intro]: "fmpred P m \ fmpred P (fmdrop_fset A m)" by (auto simp: fmfilter_alt_defs) lemma fmpred_restrict_set[intro]: "fmpred P m \ fmpred P (fmrestrict_set A m)" by (auto simp: fmfilter_alt_defs) lemma fmpred_restrict_fset[intro]: "fmpred P m \ fmpred P (fmrestrict_fset A m)" by (auto simp: fmfilter_alt_defs) lemma fmpred_cases[consumes 1]: assumes "fmpred P m" obtains (none) "fmlookup m x = None" | (some) y where "fmlookup m x = Some y" "P x y" using assms by auto lift_definition fmsubset :: "('a, 'b) fmap \ ('a, 'b) fmap \ bool" (infix "\\<^sub>f" 50) is map_le . lemma fmsubset_alt_def: "m \\<^sub>f n \ fmpred (\k v. fmlookup n k = Some v) m" by transfer' (auto simp: map_pred_def map_le_def dom_def split: option.splits) lemma fmsubset_pred: "fmpred P m \ n \\<^sub>f m \ fmpred P n" unfolding fmsubset_alt_def fmpred_iff by auto lemma fmsubset_filter_mono: "m \\<^sub>f n \ fmfilter P m \\<^sub>f fmfilter P n" unfolding fmsubset_alt_def fmpred_iff by auto lemma fmsubset_drop_mono: "m \\<^sub>f n \ fmdrop a m \\<^sub>f fmdrop a n" unfolding fmfilter_alt_defs by (rule fmsubset_filter_mono) lemma fmsubset_drop_set_mono: "m \\<^sub>f n \ fmdrop_set A m \\<^sub>f fmdrop_set A n" unfolding fmfilter_alt_defs by (rule fmsubset_filter_mono) lemma fmsubset_drop_fset_mono: "m \\<^sub>f n \ fmdrop_fset A m \\<^sub>f fmdrop_fset A n" unfolding fmfilter_alt_defs by (rule fmsubset_filter_mono) lemma fmsubset_restrict_set_mono: "m \\<^sub>f n \ fmrestrict_set A m \\<^sub>f fmrestrict_set A n" unfolding fmfilter_alt_defs by (rule fmsubset_filter_mono) lemma fmsubset_restrict_fset_mono: "m \\<^sub>f n \ fmrestrict_fset A m \\<^sub>f fmrestrict_fset A n" unfolding fmfilter_alt_defs by (rule fmsubset_filter_mono) lemma fmfilter_subset[simp]: "fmfilter P m \\<^sub>f m" unfolding fmsubset_alt_def fmpred_iff by auto lemma fmsubset_drop[simp]: "fmdrop a m \\<^sub>f m" unfolding fmfilter_alt_defs by (rule fmfilter_subset) lemma fmsubset_drop_set[simp]: "fmdrop_set S m \\<^sub>f m" unfolding fmfilter_alt_defs by (rule fmfilter_subset) lemma fmsubset_drop_fset[simp]: "fmdrop_fset S m \\<^sub>f m" unfolding fmfilter_alt_defs by (rule fmfilter_subset) lemma fmsubset_restrict_set[simp]: "fmrestrict_set S m \\<^sub>f m" unfolding fmfilter_alt_defs by (rule fmfilter_subset) lemma fmsubset_restrict_fset[simp]: "fmrestrict_fset S m \\<^sub>f m" unfolding fmfilter_alt_defs by (rule fmfilter_subset) lift_definition fset_of_fmap :: "('a, 'b) fmap \ ('a \ 'b) fset" is set_of_map by (rule set_of_map_finite) lemma fset_of_fmap_inj[intro, simp]: "inj fset_of_fmap" apply rule apply transfer' using set_of_map_inj unfolding inj_def by auto lemma fset_of_fmap_iff[simp]: "(a, b) |\| fset_of_fmap m \ fmlookup m a = Some b" by transfer' (auto simp: set_of_map_def) lemma fset_of_fmap_iff'[simp]: "(a, b) \ fset (fset_of_fmap m) \ fmlookup m a = Some b" by transfer' (auto simp: set_of_map_def) lift_definition fmap_of_list :: "('a \ 'b) list \ ('a, 'b) fmap" is map_of parametric map_of_transfer by (rule finite_dom_map_of) lemma fmap_of_list_simps[simp]: "fmap_of_list [] = fmempty" "fmap_of_list ((k, v) # kvs) = fmupd k v (fmap_of_list kvs)" by (transfer, simp add: map_upd_def)+ lemma fmap_of_list_app[simp]: "fmap_of_list (xs @ ys) = fmap_of_list ys ++\<^sub>f fmap_of_list xs" by transfer' simp lemma fmupd_alt_def: "fmupd k v m = m ++\<^sub>f fmap_of_list [(k, v)]" by transfer' (auto simp: map_upd_def) lemma fmpred_of_list[intro]: assumes "\k v. (k, v) \ set xs \ P k v" shows "fmpred P (fmap_of_list xs)" using assms by (induction xs) (transfer'; auto simp: map_pred_def)+ lemma fmap_of_list_SomeD: "fmlookup (fmap_of_list xs) k = Some v \ (k, v) \ set xs" by transfer' (auto dest: map_of_SomeD) lemma fmdom_fmap_of_list[simp]: "fmdom (fmap_of_list xs) = fset_of_list (map fst xs)" apply transfer' apply (subst dom_map_of_conv_image_fst) apply auto done lift_definition fmrel_on_fset :: "'a fset \ ('b \ 'c \ bool) \ ('a, 'b) fmap \ ('a, 'c) fmap \ bool" is rel_map_on_set . lemma fmrel_on_fset_alt_def: "fmrel_on_fset S P m n \ fBall S (\x. rel_option P (fmlookup m x) (fmlookup n x))" by transfer' (auto simp: rel_map_on_set_def eq_onp_def rel_fun_def) lemma fmrel_on_fsetI[intro]: assumes "\x. x |\| S \ rel_option P (fmlookup m x) (fmlookup n x)" shows "fmrel_on_fset S P m n" using assms unfolding fmrel_on_fset_alt_def by auto lemma fmrel_on_fset_mono[mono]: "R \ Q \ fmrel_on_fset S R \ fmrel_on_fset S Q" unfolding fmrel_on_fset_alt_def[abs_def] apply (intro le_funI fBall_mono) using option.rel_mono by auto lemma fmrel_on_fsetD: "x |\| S \ fmrel_on_fset S P m n \ rel_option P (fmlookup m x) (fmlookup n x)" unfolding fmrel_on_fset_alt_def by auto lemma fmrel_on_fsubset: "fmrel_on_fset S R m n \ T |\| S \ fmrel_on_fset T R m n" unfolding fmrel_on_fset_alt_def by auto lemma fmrel_on_fset_unionI: "fmrel_on_fset A R m n \ fmrel_on_fset B R m n \ fmrel_on_fset (A |\| B) R m n" unfolding fmrel_on_fset_alt_def by auto lemma fmrel_on_fset_updateI: assumes "fmrel_on_fset S P m n" "P v\<^sub>1 v\<^sub>2" shows "fmrel_on_fset (finsert k S) P (fmupd k v\<^sub>1 m) (fmupd k v\<^sub>2 n)" using assms unfolding fmrel_on_fset_alt_def by auto lift_definition fmimage :: "('a, 'b) fmap \ 'a fset \ 'b fset" is "\m S. {b|a b. m a = Some b \ a \ S}" subgoal for m S apply (rule finite_subset[where B = "ran m"]) apply (auto simp: ran_def)[] by (rule finite_ran) done lemma fmimage_alt_def: "fmimage m S = fmran (fmrestrict_fset S m)" by transfer' (auto simp: ran_def map_restrict_set_def map_filter_def) lemma fmimage_empty[simp]: "fmimage m fempty = fempty" by transfer' auto lemma fmimage_subset_ran[simp]: "fmimage m S |\| fmran m" by transfer' (auto simp: ran_def) lemma fmimage_dom[simp]: "fmimage m (fmdom m) = fmran m" by transfer' (auto simp: ran_def) lemma fmimage_inter: "fmimage m (A |\| B) |\| fmimage m A |\| fmimage m B" by transfer' auto lemma fimage_inter_dom[simp]: "fmimage m (fmdom m |\| A) = fmimage m A" "fmimage m (A |\| fmdom m) = fmimage m A" by (transfer'; auto)+ lemma fmimage_union[simp]: "fmimage m (A |\| B) = fmimage m A |\| fmimage m B" by transfer' auto lemma fmimage_Union[simp]: "fmimage m (ffUnion A) = ffUnion (fmimage m |`| A)" by transfer' auto lemma fmimage_filter[simp]: "fmimage (fmfilter P m) A = fmimage m (ffilter P A)" by transfer' (auto simp: map_filter_def) lemma fmimage_drop[simp]: "fmimage (fmdrop a m) A = fmimage m (A - {|a|})" by transfer' (auto simp: map_filter_def map_drop_def) lemma fmimage_drop_fset[simp]: "fmimage (fmdrop_fset B m) A = fmimage m (A - B)" by transfer' (auto simp: map_filter_def map_drop_set_def) lemma fmimage_restrict_fset[simp]: "fmimage (fmrestrict_fset B m) A = fmimage m (A |\| B)" by transfer' (auto simp: map_filter_def map_restrict_set_def) lemma fmfilter_ran[simp]: "fmran (fmfilter P m) = fmimage m (ffilter P (fmdom m))" by transfer' (auto simp: ran_def map_filter_def) lemma fmran_drop[simp]: "fmran (fmdrop a m) = fmimage m (fmdom m - {|a|})" by transfer' (auto simp: ran_def map_drop_def map_filter_def) lemma fmran_drop_fset[simp]: "fmran (fmdrop_fset A m) = fmimage m (fmdom m - A)" by transfer' (auto simp: ran_def map_drop_set_def map_filter_def) lemma fmran_restrict_fset: "fmran (fmrestrict_fset A m) = fmimage m (fmdom m |\| A)" by transfer' (auto simp: ran_def map_restrict_set_def map_filter_def) lemma fmlookup_image_iff: "y |\| fmimage m A \ (\x. fmlookup m x = Some y \ x |\| A)" by transfer' (auto simp: ran_def) lemma fmimageI: "fmlookup m x = Some y \ x |\| A \ y |\| fmimage m A" by (auto simp: fmlookup_image_iff) lemma fmimageE[elim]: assumes "y |\| fmimage m A" obtains x where "fmlookup m x = Some y" "x |\| A" using assms by (auto simp: fmlookup_image_iff) lift_definition fmcomp :: "('b, 'c) fmap \ ('a, 'b) fmap \ ('a, 'c) fmap" (infixl "\\<^sub>f" 55) is map_comp parametric map_comp_transfer by (rule dom_comp_finite) lemma fmlookup_comp[simp]: "fmlookup (m \\<^sub>f n) x = Option.bind (fmlookup n x) (fmlookup m)" by transfer' (auto simp: map_comp_def split: option.splits) end subsection \BNF setup\ lift_bnf ('a, fmran': 'b) fmap [wits: Map.empty] for map: fmmap rel: fmrel by auto declare fmap.pred_mono[mono] lemma fmran'_alt_def: "fmran' m = fset (fmran m)" including fset.lifting by transfer' (auto simp: ran_def fun_eq_iff) lemma fmlookup_ran'_iff: "y \ fmran' m \ (\x. fmlookup m x = Some y)" by transfer' (auto simp: ran_def) lemma fmran'I: "fmlookup m x = Some y \ y \ fmran' m" by (auto simp: fmlookup_ran'_iff) lemma fmran'E[elim]: assumes "y \ fmran' m" obtains x where "fmlookup m x = Some y" using assms by (auto simp: fmlookup_ran'_iff) lemma fmrel_iff: "fmrel R m n \ (\x. rel_option R (fmlookup m x) (fmlookup n x))" by transfer' (auto simp: rel_fun_def) lemma fmrelI[intro]: assumes "\x. rel_option R (fmlookup m x) (fmlookup n x)" shows "fmrel R m n" using assms by transfer' auto lemma fmrel_upd[intro]: "fmrel P m n \ P x y \ fmrel P (fmupd k x m) (fmupd k y n)" by transfer' (auto simp: map_upd_def rel_fun_def) lemma fmrelD[dest]: "fmrel P m n \ rel_option P (fmlookup m x) (fmlookup n x)" by transfer' (auto simp: rel_fun_def) lemma fmrel_addI[intro]: assumes "fmrel P m n" "fmrel P a b" shows "fmrel P (m ++\<^sub>f a) (n ++\<^sub>f b)" using assms apply transfer' apply (auto simp: rel_fun_def map_add_def) by (metis option.case_eq_if option.collapse option.rel_sel) lemma fmrel_cases[consumes 1]: assumes "fmrel P m n" obtains (none) "fmlookup m x = None" "fmlookup n x = None" | (some) a b where "fmlookup m x = Some a" "fmlookup n x = Some b" "P a b" proof - from assms have "rel_option P (fmlookup m x) (fmlookup n x)" by auto then show thesis using none some by (cases rule: option.rel_cases) auto qed lemma fmrel_filter[intro]: "fmrel P m n \ fmrel P (fmfilter Q m) (fmfilter Q n)" unfolding fmrel_iff by auto lemma fmrel_drop[intro]: "fmrel P m n \ fmrel P (fmdrop a m) (fmdrop a n)" unfolding fmfilter_alt_defs by blast lemma fmrel_drop_set[intro]: "fmrel P m n \ fmrel P (fmdrop_set A m) (fmdrop_set A n)" unfolding fmfilter_alt_defs by blast lemma fmrel_drop_fset[intro]: "fmrel P m n \ fmrel P (fmdrop_fset A m) (fmdrop_fset A n)" unfolding fmfilter_alt_defs by blast lemma fmrel_restrict_set[intro]: "fmrel P m n \ fmrel P (fmrestrict_set A m) (fmrestrict_set A n)" unfolding fmfilter_alt_defs by blast lemma fmrel_restrict_fset[intro]: "fmrel P m n \ fmrel P (fmrestrict_fset A m) (fmrestrict_fset A n)" unfolding fmfilter_alt_defs by blast lemma fmrel_on_fset_fmrel_restrict: "fmrel_on_fset S P m n \ fmrel P (fmrestrict_fset S m) (fmrestrict_fset S n)" unfolding fmrel_on_fset_alt_def fmrel_iff by auto lemma fmrel_on_fset_refl_strong: assumes "\x y. x |\| S \ fmlookup m x = Some y \ P y y" shows "fmrel_on_fset S P m m" unfolding fmrel_on_fset_fmrel_restrict fmrel_iff using assms by (simp add: option.rel_sel) lemma fmrel_on_fset_addI: assumes "fmrel_on_fset S P m n" "fmrel_on_fset S P a b" shows "fmrel_on_fset S P (m ++\<^sub>f a) (n ++\<^sub>f b)" using assms unfolding fmrel_on_fset_fmrel_restrict by auto lemma fmrel_fmdom_eq: assumes "fmrel P x y" shows "fmdom x = fmdom y" proof - have "a |\| fmdom x \ a |\| fmdom y" for a proof - have "rel_option P (fmlookup x a) (fmlookup y a)" using assms by (simp add: fmrel_iff) thus ?thesis by cases (auto intro: fmdomI) qed thus ?thesis by auto qed lemma fmrel_fmdom'_eq: "fmrel P x y \ fmdom' x = fmdom' y" unfolding fmdom'_alt_def by (metis fmrel_fmdom_eq) lemma fmrel_rel_fmran: assumes "fmrel P x y" shows "rel_fset P (fmran x) (fmran y)" proof - { fix b assume "b |\| fmran x" then obtain a where "fmlookup x a = Some b" by auto moreover have "rel_option P (fmlookup x a) (fmlookup y a)" using assms by auto ultimately have "\b'. b' |\| fmran y \ P b b'" by (metis option_rel_Some1 fmranI) } moreover { fix b assume "b |\| fmran y" then obtain a where "fmlookup y a = Some b" by auto moreover have "rel_option P (fmlookup x a) (fmlookup y a)" using assms by auto ultimately have "\b'. b' |\| fmran x \ P b' b" by (metis option_rel_Some2 fmranI) } ultimately show ?thesis unfolding rel_fset_alt_def by auto qed lemma fmrel_rel_fmran': "fmrel P x y \ rel_set P (fmran' x) (fmran' y)" unfolding fmran'_alt_def by (metis fmrel_rel_fmran rel_fset_fset) lemma pred_fmap_fmpred[simp]: "pred_fmap P = fmpred (\_. P)" unfolding fmap.pred_set fmran'_alt_def including fset.lifting apply transfer' apply (rule ext) apply (auto simp: map_pred_def ran_def split: option.splits dest: ) done lemma pred_fmap_id[simp]: "pred_fmap id (fmmap f m) \ pred_fmap f m" unfolding fmap.pred_set fmap.set_map by simp lemma pred_fmapD: "pred_fmap P m \ x |\| fmran m \ P x" by auto lemma fmlookup_map[simp]: "fmlookup (fmmap f m) x = map_option f (fmlookup m x)" by transfer' auto lemma fmpred_map[simp]: "fmpred P (fmmap f m) \ fmpred (\k v. P k (f v)) m" unfolding fmpred_iff pred_fmap_def fmap.set_map by auto lemma fmpred_id[simp]: "fmpred (\_. id) (fmmap f m) \ fmpred (\_. f) m" by simp lemma fmmap_add[simp]: "fmmap f (m ++\<^sub>f n) = fmmap f m ++\<^sub>f fmmap f n" by transfer' (auto simp: map_add_def fun_eq_iff split: option.splits) lemma fmmap_empty[simp]: "fmmap f fmempty = fmempty" by transfer auto lemma fmdom_map[simp]: "fmdom (fmmap f m) = fmdom m" including fset.lifting by transfer' simp lemma fmdom'_map[simp]: "fmdom' (fmmap f m) = fmdom' m" by transfer' simp lemma fmran_fmmap[simp]: "fmran (fmmap f m) = f |`| fmran m" including fset.lifting by transfer' (auto simp: ran_def) lemma fmran'_fmmap[simp]: "fmran' (fmmap f m) = f ` fmran' m" by transfer' (auto simp: ran_def) lemma fmfilter_fmmap[simp]: "fmfilter P (fmmap f m) = fmmap f (fmfilter P m)" by transfer' (auto simp: map_filter_def) lemma fmdrop_fmmap[simp]: "fmdrop a (fmmap f m) = fmmap f (fmdrop a m)" unfolding fmfilter_alt_defs by simp lemma fmdrop_set_fmmap[simp]: "fmdrop_set A (fmmap f m) = fmmap f (fmdrop_set A m)" unfolding fmfilter_alt_defs by simp lemma fmdrop_fset_fmmap[simp]: "fmdrop_fset A (fmmap f m) = fmmap f (fmdrop_fset A m)" unfolding fmfilter_alt_defs by simp lemma fmrestrict_set_fmmap[simp]: "fmrestrict_set A (fmmap f m) = fmmap f (fmrestrict_set A m)" unfolding fmfilter_alt_defs by simp lemma fmrestrict_fset_fmmap[simp]: "fmrestrict_fset A (fmmap f m) = fmmap f (fmrestrict_fset A m)" unfolding fmfilter_alt_defs by simp lemma fmmap_subset[intro]: "m \\<^sub>f n \ fmmap f m \\<^sub>f fmmap f n" by transfer' (auto simp: map_le_def) lemma fmmap_fset_of_fmap: "fset_of_fmap (fmmap f m) = (\(k, v). (k, f v)) |`| fset_of_fmap m" including fset.lifting by transfer' (auto simp: set_of_map_def) lemma fmmap_fmupd: "fmmap f (fmupd x y m) = fmupd x (f y) (fmmap f m)" by transfer' (auto simp: fun_eq_iff map_upd_def) subsection \\<^const>\size\ setup\ definition size_fmap :: "('a \ nat) \ ('b \ nat) \ ('a, 'b) fmap \ nat" where [simp]: "size_fmap f g m = size_fset (\(a, b). f a + g b) (fset_of_fmap m)" instantiation fmap :: (type, type) size begin definition size_fmap where size_fmap_overloaded_def: "size_fmap = Finite_Map.size_fmap (\_. 0) (\_. 0)" instance .. end lemma size_fmap_overloaded_simps[simp]: "size x = size (fset_of_fmap x)" unfolding size_fmap_overloaded_def by simp lemma fmap_size_o_map: "inj h \ size_fmap f g \ fmmap h = size_fmap f (g \ h)" unfolding size_fmap_def apply (auto simp: fun_eq_iff fmmap_fset_of_fmap) apply (subst sum.reindex) subgoal for m using prod.inj_map[unfolded map_prod_def, of "\x. x" h] unfolding inj_on_def by auto subgoal by (rule sum.cong) (auto split: prod.splits) done setup \ BNF_LFP_Size.register_size_global \<^type_name>\fmap\ \<^const_name>\size_fmap\ @{thm size_fmap_overloaded_def} @{thms size_fmap_def size_fmap_overloaded_simps} @{thms fmap_size_o_map} \ subsection \Additional operations\ lift_definition fmmap_keys :: "('a \ 'b \ 'c) \ ('a, 'b) fmap \ ('a, 'c) fmap" is "\f m a. map_option (f a) (m a)" unfolding dom_def by simp lemma fmpred_fmmap_keys[simp]: "fmpred P (fmmap_keys f m) = fmpred (\a b. P a (f a b)) m" by transfer' (auto simp: map_pred_def split: option.splits) lemma fmdom_fmmap_keys[simp]: "fmdom (fmmap_keys f m) = fmdom m" including fset.lifting by transfer' auto lemma fmlookup_fmmap_keys[simp]: "fmlookup (fmmap_keys f m) x = map_option (f x) (fmlookup m x)" by transfer' simp lemma fmfilter_fmmap_keys[simp]: "fmfilter P (fmmap_keys f m) = fmmap_keys f (fmfilter P m)" by transfer' (auto simp: map_filter_def) lemma fmdrop_fmmap_keys[simp]: "fmdrop a (fmmap_keys f m) = fmmap_keys f (fmdrop a m)" unfolding fmfilter_alt_defs by simp lemma fmdrop_set_fmmap_keys[simp]: "fmdrop_set A (fmmap_keys f m) = fmmap_keys f (fmdrop_set A m)" unfolding fmfilter_alt_defs by simp lemma fmdrop_fset_fmmap_keys[simp]: "fmdrop_fset A (fmmap_keys f m) = fmmap_keys f (fmdrop_fset A m)" unfolding fmfilter_alt_defs by simp lemma fmrestrict_set_fmmap_keys[simp]: "fmrestrict_set A (fmmap_keys f m) = fmmap_keys f (fmrestrict_set A m)" unfolding fmfilter_alt_defs by simp lemma fmrestrict_fset_fmmap_keys[simp]: "fmrestrict_fset A (fmmap_keys f m) = fmmap_keys f (fmrestrict_fset A m)" unfolding fmfilter_alt_defs by simp lemma fmmap_keys_subset[intro]: "m \\<^sub>f n \ fmmap_keys f m \\<^sub>f fmmap_keys f n" by transfer' (auto simp: map_le_def dom_def) definition sorted_list_of_fmap :: "('a::linorder, 'b) fmap \ ('a \ 'b) list" where "sorted_list_of_fmap m = map (\k. (k, the (fmlookup m k))) (sorted_list_of_fset (fmdom m))" lemma list_all_sorted_list[simp]: "list_all P (sorted_list_of_fmap m) = fmpred (curry P) m" unfolding sorted_list_of_fmap_def curry_def list.pred_map apply (auto simp: list_all_iff) including fset.lifting by (transfer; auto simp: dom_def map_pred_def split: option.splits)+ lemma map_of_sorted_list[simp]: "map_of (sorted_list_of_fmap m) = fmlookup m" unfolding sorted_list_of_fmap_def including fset.lifting by transfer (simp add: map_of_map_keys) subsection \Additional properties\ lemma fmchoice': assumes "finite S" "\x \ S. \y. Q x y" shows "\m. fmdom' m = S \ fmpred Q m" proof - obtain f where f: "Q x (f x)" if "x \ S" for x using assms by (metis bchoice) define f' where "f' x = (if x \ S then Some (f x) else None)" for x have "eq_onp (\m. finite (dom m)) f' f'" unfolding eq_onp_def f'_def dom_def using assms by auto show ?thesis apply (rule exI[where x = "Abs_fmap f'"]) apply (subst fmpred.abs_eq, fact) apply (subst fmdom'.abs_eq, fact) unfolding f'_def dom_def map_pred_def using f by auto qed subsection \Lifting/transfer setup\ context includes lifting_syntax begin lemma fmempty_transfer[simp, intro, transfer_rule]: "fmrel P fmempty fmempty" by transfer auto lemma fmadd_transfer[transfer_rule]: "(fmrel P ===> fmrel P ===> fmrel P) fmadd fmadd" by (intro fmrel_addI rel_funI) lemma fmupd_transfer[transfer_rule]: "((=) ===> P ===> fmrel P ===> fmrel P) fmupd fmupd" by auto end lemma Quotient_fmap_bnf[quot_map]: assumes "Quotient R Abs Rep T" shows "Quotient (fmrel R) (fmmap Abs) (fmmap Rep) (fmrel T)" unfolding Quotient_alt_def4 proof safe fix m n assume "fmrel T m n" then have "fmlookup (fmmap Abs m) x = fmlookup n x" for x apply (cases rule: fmrel_cases[where x = x]) using assms unfolding Quotient_alt_def by auto then show "fmmap Abs m = n" by (rule fmap_ext) next fix m show "fmrel T (fmmap Rep m) m" unfolding fmap.rel_map apply (rule fmap.rel_refl) using assms unfolding Quotient_alt_def by auto next from assms have "R = T OO T\\" unfolding Quotient_alt_def4 by simp then show "fmrel R = fmrel T OO (fmrel T)\\" by (simp add: fmap.rel_compp fmap.rel_conversep) qed subsection \View as datatype\ lemma fmap_distinct[simp]: "fmempty \ fmupd k v m" "fmupd k v m \ fmempty" by (transfer'; auto simp: map_upd_def fun_eq_iff)+ lifting_update fmap.lifting lemma fmap_exhaust[cases type: fmap]: obtains (fmempty) "m = fmempty" | (fmupd) x y m' where "m = fmupd x y m'" "x |\| fmdom m'" using that including fmap.lifting fset.lifting proof transfer fix m P assume "finite (dom m)" assume empty: P if "m = Map.empty" assume map_upd: P if "finite (dom m')" "m = map_upd x y m'" "x \ dom m'" for x y m' show P proof (cases "m = Map.empty") case True thus ?thesis using empty by simp next case False hence "dom m \ {}" by simp then obtain x where "x \ dom m" by blast let ?m' = "map_drop x m" show ?thesis proof (rule map_upd) show "finite (dom ?m')" using \finite (dom m)\ unfolding map_drop_def by auto next show "m = map_upd x (the (m x)) ?m'" using \x \ dom m\ unfolding map_drop_def map_filter_def map_upd_def by auto next show "x \ dom ?m'" unfolding map_drop_def map_filter_def by auto qed qed qed lemma fmap_induct[case_names fmempty fmupd, induct type: fmap]: assumes "P fmempty" assumes "(\x y m. P m \ fmlookup m x = None \ P (fmupd x y m))" shows "P m" proof (induction "fmdom m" arbitrary: m rule: fset_induct_stronger) case empty hence "m = fmempty" by (metis fmrestrict_fset_dom fmrestrict_fset_null) with assms show ?case by simp next case (insert x S) hence "S = fmdom (fmdrop x m)" by auto with insert have "P (fmdrop x m)" by auto have "x |\| fmdom m" using insert by auto then obtain y where "fmlookup m x = Some y" by auto hence "m = fmupd x y (fmdrop x m)" by (auto intro: fmap_ext) show ?case apply (subst \m = _\) apply (rule assms) apply fact apply simp done qed subsection \Code setup\ instantiation fmap :: (type, equal) equal begin definition "equal_fmap \ fmrel HOL.equal" instance proof fix m n :: "('a, 'b) fmap" have "fmrel (=) m n \ (m = n)" by transfer' (simp add: option.rel_eq rel_fun_eq) then show "equal_class.equal m n \ (m = n)" unfolding equal_fmap_def by (simp add: equal_eq[abs_def]) qed end lemma fBall_alt_def: "fBall S P \ (\x. x |\| S \ P x)" by force lemma fmrel_code: "fmrel R m n \ fBall (fmdom m) (\x. rel_option R (fmlookup m x) (fmlookup n x)) \ fBall (fmdom n) (\x. rel_option R (fmlookup m x) (fmlookup n x))" unfolding fmrel_iff fmlookup_dom_iff fBall_alt_def by (metis option.collapse option.rel_sel) lemmas [code] = fmrel_code fmran'_alt_def fmdom'_alt_def fmfilter_alt_defs pred_fmap_fmpred fmsubset_alt_def fmupd_alt_def fmrel_on_fset_alt_def fmpred_alt_def code_datatype fmap_of_list quickcheck_generator fmap constructors: fmap_of_list context includes fset.lifting begin lemma fmlookup_of_list[code]: "fmlookup (fmap_of_list m) = map_of m" by transfer simp lemma fmempty_of_list[code]: "fmempty = fmap_of_list []" by transfer simp lemma fmran_of_list[code]: "fmran (fmap_of_list m) = snd |`| fset_of_list (AList.clearjunk m)" by transfer (auto simp: ran_map_of) lemma fmdom_of_list[code]: "fmdom (fmap_of_list m) = fst |`| fset_of_list m" by transfer (auto simp: dom_map_of_conv_image_fst) lemma fmfilter_of_list[code]: "fmfilter P (fmap_of_list m) = fmap_of_list (filter (\(k, _). P k) m)" by transfer' auto lemma fmadd_of_list[code]: "fmap_of_list m ++\<^sub>f fmap_of_list n = fmap_of_list (AList.merge m n)" by transfer (simp add: merge_conv') lemma fmmap_of_list[code]: "fmmap f (fmap_of_list m) = fmap_of_list (map (apsnd f) m)" apply transfer apply (subst map_of_map[symmetric]) apply (auto simp: apsnd_def map_prod_def) done lemma fmmap_keys_of_list[code]: "fmmap_keys f (fmap_of_list m) = fmap_of_list (map (\(a, b). (a, f a b)) m)" apply transfer subgoal for f m by (induction m) (auto simp: apsnd_def map_prod_def fun_eq_iff) done lemma fmimage_of_list[code]: "fmimage (fmap_of_list m) A = fset_of_list (map snd (filter (\(k, _). k |\| A) (AList.clearjunk m)))" apply (subst fmimage_alt_def) apply (subst fmfilter_alt_defs) apply (subst fmfilter_of_list) apply (subst fmran_of_list) apply transfer' apply (subst AList.restrict_eq[symmetric]) apply (subst clearjunk_restrict) apply (subst AList.restrict_eq) by auto lemma fmcomp_list[code]: "fmap_of_list m \\<^sub>f fmap_of_list n = fmap_of_list (AList.compose n m)" by (rule fmap_ext) (simp add: fmlookup_of_list compose_conv map_comp_def split: option.splits) end subsection \Instances\ lemma exists_map_of: assumes "finite (dom m)" shows "\xs. map_of xs = m" using assms proof (induction "dom m" arbitrary: m) case empty hence "m = Map.empty" by auto moreover have "map_of [] = Map.empty" by simp ultimately show ?case by blast next case (insert x F) hence "F = dom (map_drop x m)" unfolding map_drop_def map_filter_def dom_def by auto with insert have "\xs'. map_of xs' = map_drop x m" by auto then obtain xs' where "map_of xs' = map_drop x m" .. moreover obtain y where "m x = Some y" using insert unfolding dom_def by blast ultimately have "map_of ((x, y) # xs') = m" using \insert x F = dom m\ unfolding map_drop_def map_filter_def by auto thus ?case .. qed lemma exists_fmap_of_list: "\xs. fmap_of_list xs = m" by transfer (rule exists_map_of) lemma fmap_of_list_surj[simp, intro]: "surj fmap_of_list" proof - have "x \ range fmap_of_list" for x :: "('a, 'b) fmap" unfolding image_iff using exists_fmap_of_list by (metis UNIV_I) thus ?thesis by auto qed instance fmap :: (countable, countable) countable proof obtain to_nat :: "('a \ 'b) list \ nat" where "inj to_nat" by (metis ex_inj) moreover have "inj (inv fmap_of_list)" using fmap_of_list_surj by (rule surj_imp_inj_inv) ultimately have "inj (to_nat \ inv fmap_of_list)" by (rule inj_compose) thus "\to_nat::('a, 'b) fmap \ nat. inj to_nat" by auto qed instance fmap :: (finite, finite) finite proof show "finite (UNIV :: ('a, 'b) fmap set)" by (rule finite_imageD) auto qed lifting_update fmap.lifting lifting_forget fmap.lifting subsection \Tests\ \ \Code generation\ export_code - fBall fmrel fmran fmran' fmdom fmdom' fmpred pred_fmap fmsubset fmupd fmrel_on_fset + Ball fset fmrel fmran fmran' fmdom fmdom' fmpred pred_fmap fmsubset fmupd fmrel_on_fset fmdrop fmdrop_set fmdrop_fset fmrestrict_set fmrestrict_fset fmimage fmlookup fmempty fmfilter fmadd fmmap fmmap_keys fmcomp checking SML Scala Haskell? OCaml? \ \\lifting\ through \<^type>\fmap\\ experiment begin context includes fset.lifting begin lift_definition test1 :: "('a, 'b fset) fmap" is "fmempty :: ('a, 'b set) fmap" by auto lift_definition test2 :: "'a \ 'b \ ('a, 'b fset) fmap" is "\a b. fmupd a {b} fmempty" by auto end end end \ No newline at end of file