(* Title: HOL/Types_To_Sets/Examples/Group_On_With.thy Author: Fabian Immler, TU München *) theory Group_On_With imports Prerequisites "../Types_To_Sets" begin subsection \\<^emph>\on\ carrier set \<^emph>\with\ explicit group operations\ locale semigroup_add_on_with = fixes S::"'a set" and pls::"'a\'a\'a" assumes add_assoc: "a \ S \ b \ S \ c \ S \ pls (pls a b) c = pls a (pls b c)" assumes add_mem: "a \ S \ b \ S \ pls a b \ S" locale ab_semigroup_add_on_with = semigroup_add_on_with + assumes add_commute: "a \ S \ b \ S \ pls a b = pls b a" locale comm_monoid_add_on_with = ab_semigroup_add_on_with + fixes z assumes add_zero: "a \ S \ pls z a = a" assumes zero_mem: "z \ S" begin lemma carrier_ne: "S \ {}" using zero_mem by auto end definition "sum_with pls z f S = (if \C. f ` S \ C \ comm_monoid_add_on_with C pls z then Finite_Set.fold (pls o f) z S else z)" lemma sum_with_empty[simp]: "sum_with pls z f {} = z" by (auto simp: sum_with_def) lemma sum_with_cases[case_names comm zero]: "P (sum_with pls z f S)" if "\C. f ` S \ C \ comm_monoid_add_on_with C pls z \ P (Finite_Set.fold (pls o f) z S)" "(\C. comm_monoid_add_on_with C pls z \ (\s\S. f s \ C)) \ P z" using that by (auto simp: sum_with_def) context comm_monoid_add_on_with begin lemma sum_with_infinite: "infinite A \ sum_with pls z g A = z" by (induction rule: sum_with_cases) auto context begin private abbreviation "pls' \ \x y. pls (if x \ S then x else z) (if y \ S then y else z)" lemma fold_pls'_mem: "Finite_Set.fold (pls' \ g) z A \ S" if "g ` A \ S" proof cases assume A: "finite A" interpret comp_fun_commute "pls' o g" using that using add_assoc add_commute add_mem zero_mem by unfold_locales auto from fold_graph_fold[OF A] have "fold_graph (pls' \ g) z A (Finite_Set.fold (pls' \ g) z A)" . from fold_graph_closed_lemma[OF this, of S "pls' \ g"] add_assoc add_commute add_mem zero_mem show ?thesis by auto qed (use add_assoc add_commute add_mem zero_mem in simp) lemma fold_pls'_eq: "Finite_Set.fold (pls' \ g) z A = Finite_Set.fold (pls \ g) z A" if "g ` A \ S" using add_assoc add_commute add_mem zero_mem that by (intro fold_closed_eq[where B=S]) auto lemma sum_with_mem: "sum_with pls z g A \ S" if "g ` A \ S" proof - interpret comp_fun_commute "pls' o g" using add_assoc add_commute add_mem zero_mem that by unfold_locales auto have "\C. g ` A \ C \ comm_monoid_add_on_with C pls z" using that comm_monoid_add_on_with_axioms by auto then show ?thesis using fold_pls'_mem[OF that] by (simp add: sum_with_def fold_pls'_eq that) qed lemma sum_with_insert: "sum_with pls z g (insert x A) = pls (g x) (sum_with pls z g A)" if g_into: "g x \ S" "g ` A \ S" and A: "finite A" and x: "x \ A" proof - interpret comp_fun_commute "pls' o g" using add_assoc add_commute add_mem zero_mem g_into by unfold_locales auto have "Finite_Set.fold (pls \ g) z (insert x A) = Finite_Set.fold (pls' \ g) z (insert x A)" using g_into by (subst fold_pls'_eq) auto also have "\ = pls' (g x) (Finite_Set.fold (pls' \ g) z A)" unfolding fold_insert[OF A x] by (auto simp: o_def) also have "\ = pls (g x) (Finite_Set.fold (pls' \ g) z A)" proof - from fold_graph_fold[OF A] have "fold_graph (pls' \ g) z A (Finite_Set.fold (pls' \ g) z A)" . from fold_graph_closed_lemma[OF this, of S "pls' \ g"] add_assoc add_commute add_mem zero_mem have "Finite_Set.fold (pls' \ g) z A \ S" by auto then show ?thesis using g_into by auto qed also have "Finite_Set.fold (pls' \ g) z A = Finite_Set.fold (pls \ g) z A" using g_into by (subst fold_pls'_eq) auto finally have "Finite_Set.fold (pls \ g) z (insert x A) = pls (g x) (Finite_Set.fold (pls \ g) z A)" . moreover have "\C. g ` insert x A \ C \ comm_monoid_add_on_with C pls z" "\C. g ` A \ C \ comm_monoid_add_on_with C pls z" using that (1,2) comm_monoid_add_on_with_axioms by auto ultimately show ?thesis by (simp add: sum_with_def) qed end end locale ab_group_add_on_with = comm_monoid_add_on_with + fixes mns um assumes ab_left_minus: "a \ S \ pls (um a) a = z" assumes ab_diff_conv_add_uminus: "a \ S \ b \ S \ mns a b = pls a (um b)" assumes uminus_mem: "a \ S \ um a \ S" subsection \obvious instances (by type class constraints)\ lemma semigroup_add_on_with[simp]: "semigroup_add_on_with (UNIV::'a::semigroup_add set) (+)" by (auto simp: semigroup_add_on_with_def ac_simps) lemma semigroup_add_on_with_Ball_def: "semigroup_add_on_with S pls \ (\a\S. \b\S. \c\S. pls (pls a b) c = pls a (pls b c)) \ (\a\S. \b\S. pls a b \ S)" by (auto simp: semigroup_add_on_with_def) lemma ab_semigroup_add_on_with_Ball_def: "ab_semigroup_add_on_with S pls \ semigroup_add_on_with S pls \ (\a\S. \b\S. pls a b = pls b a)" by (auto simp: ab_semigroup_add_on_with_def ab_semigroup_add_on_with_axioms_def) lemma ab_semigroup_add_on_with[simp]: "ab_semigroup_add_on_with (UNIV::'a::ab_semigroup_add set) (+)" by (auto simp: ab_semigroup_add_on_with_Ball_def ac_simps) lemma comm_monoid_add_on_with_Ball_def: "comm_monoid_add_on_with S pls z \ ab_semigroup_add_on_with S pls \ (\a\S. pls z a = a) \ z \ S" by (auto simp: comm_monoid_add_on_with_def comm_monoid_add_on_with_axioms_def) lemma comm_monoid_add_on_with[simp]: "comm_monoid_add_on_with UNIV (+) (0::'a::comm_monoid_add)" by (auto simp: comm_monoid_add_on_with_Ball_def ab_semigroup_add_on_with_Ball_def semigroup_add_on_with_Ball_def ac_simps) lemma ab_group_add_on_with_Ball_def: "ab_group_add_on_with S pls z mns um \ comm_monoid_add_on_with S pls z \ (\a\S. pls (um a) a = z) \ (\a\S. \b\S. mns a b = pls a (um b)) \ (\a\S. um a \ S)" by (auto simp: ab_group_add_on_with_def ab_group_add_on_with_axioms_def) lemma ab_group_add_on_with[simp]: "ab_group_add_on_with (UNIV::'a::ab_group_add set) (+) 0 (-) uminus" by (auto simp: ab_group_add_on_with_Ball_def) lemma sum_with: "sum f S = sum_with (+) 0 f S" proof (induction rule: sum_with_cases) case (comm C) then show ?case unfolding sum.eq_fold by simp next case zero from zero[OF comm_monoid_add_on_with] show ?case by simp qed subsection \transfer rules\ lemma semigroup_add_on_with_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "bi_unique A" shows "(rel_set A ===> (A ===> A ===> A) ===> (=)) semigroup_add_on_with semigroup_add_on_with" unfolding semigroup_add_on_with_Ball_def by transfer_prover lemma Domainp_applyI: includes lifting_syntax shows "(A ===> B) f g \ A x y \ Domainp B (f x)" by (auto simp: rel_fun_def) lemma Domainp_apply2I: includes lifting_syntax shows "(A ===> B ===> C) f g \ A x y \ B x' y' \ Domainp C (f x x')" by (force simp: rel_fun_def) lemma right_total_semigroup_add_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" shows "((A ===> A ===> A) ===> (=)) (semigroup_add_on_with (Collect (Domainp A))) class.semigroup_add" proof (intro rel_funI) fix x y assume xy[transfer_rule]: "(A ===> A ===> A) x y" show "semigroup_add_on_with (Collect (Domainp A)) x = class.semigroup_add y" unfolding semigroup_add_on_with_def class.semigroup_add_def by transfer (auto intro!: Domainp_apply2I[OF xy]) qed lemma ab_semigroup_add_on_with_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "bi_unique A" shows "(rel_set A ===> (A ===> A ===> A) ===> (=)) ab_semigroup_add_on_with ab_semigroup_add_on_with" unfolding ab_semigroup_add_on_with_Ball_def by transfer_prover lemma right_total_ab_semigroup_add_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" shows "((A ===> A ===> A) ===> (=)) (ab_semigroup_add_on_with (Collect (Domainp A))) class.ab_semigroup_add" unfolding class.ab_semigroup_add_def class.ab_semigroup_add_axioms_def ab_semigroup_add_on_with_Ball_def by transfer_prover lemma comm_monoid_add_on_with_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "bi_unique A" shows "(rel_set A ===> (A ===> A ===> A) ===> A ===> (=)) comm_monoid_add_on_with comm_monoid_add_on_with" unfolding comm_monoid_add_on_with_Ball_def by transfer_prover lemma right_total_comm_monoid_add_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" shows "((A ===> A ===> A) ===> A ===> (=)) (comm_monoid_add_on_with (Collect (Domainp A))) class.comm_monoid_add" proof (intro rel_funI) fix p p' z z' assume [transfer_rule]: "(A ===> A ===> A) p p'" "A z z'" show "comm_monoid_add_on_with (Collect (Domainp A)) p z = class.comm_monoid_add p' z'" unfolding class.comm_monoid_add_def class.comm_monoid_add_axioms_def comm_monoid_add_on_with_Ball_def apply transfer using \A z z'\ by auto qed lemma ab_group_add_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" shows "((A ===> A ===> A) ===> A ===> (A ===> A ===> A) ===> (A ===> A)===> (=)) (ab_group_add_on_with (Collect (Domainp A))) class.ab_group_add" proof (intro rel_funI) fix p p' z z' m m' um um' assume [transfer_rule]: "(A ===> A ===> A) p p'" "A z z'" "(A ===> A ===> A) m m'" and um[transfer_rule]: "(A ===> A) um um'" show "ab_group_add_on_with (Collect (Domainp A)) p z m um = class.ab_group_add p' z' m' um'" unfolding class.ab_group_add_def class.ab_group_add_axioms_def ab_group_add_on_with_Ball_def by transfer (use um in \auto simp: rel_fun_def\) qed lemma ab_group_add_on_with_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" shows "(rel_set A ===> (A ===> A ===> A) ===> A ===> (A ===> A ===> A) ===> (A ===> A)===> (=)) ab_group_add_on_with ab_group_add_on_with" unfolding class.ab_group_add_def class.ab_group_add_axioms_def ab_group_add_on_with_Ball_def by transfer_prover lemma ex_comm_monoid_add_around_imageE: includes lifting_syntax assumes ex_comm: "\C. f ` S \ C \ comm_monoid_add_on_with C pls zero" assumes transfers: "(A ===> A ===> A) pls pls'" "A zero zero'" "Domainp (rel_set B) S" and in_dom: "\x. x \ S \ Domainp A (f x)" obtains C where "comm_monoid_add_on_with C pls zero" "f ` S \ C" "Domainp (rel_set A) C" proof - from ex_comm obtain C0 where C0: "f ` S \ C0" and comm: "comm_monoid_add_on_with C0 pls zero" by auto define C where "C = C0 \ Collect (Domainp A)" have "comm_monoid_add_on_with C pls zero" using comm Domainp_apply2I[OF \(A ===> A ===> A) pls pls'\] \A zero zero'\ by (auto simp: comm_monoid_add_on_with_Ball_def ab_semigroup_add_on_with_Ball_def semigroup_add_on_with_def C_def) moreover have "f ` S \ C" using C0 by (auto simp: C_def in_dom) moreover have "Domainp (rel_set A) C" by (auto simp: C_def Domainp_set) ultimately show ?thesis .. qed lemma sum_with_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" "bi_unique B" shows "((A ===> A ===> A) ===> A ===> (B ===> A) ===> rel_set B ===> A) sum_with sum_with" proof (safe intro!: rel_funI) fix pls pls' zero zero' f g S T assume transfer_pls[transfer_rule]: "(A ===> A ===> A) pls pls'" and transfer_zero[transfer_rule]: "A zero zero'" assume transfer_g[transfer_rule]: "(B ===> A) f g" and transfer_T[transfer_rule]: "rel_set B S T" show "A (sum_with pls zero f S) (sum_with pls' zero' g T)" proof cases assume ex_comm: "\C. f ` S \ C \ comm_monoid_add_on_with C pls zero" have Domains: "Domainp (rel_set B) S" "(\x. x \ S \ Domainp A (f x))" using transfer_T transfer_g by auto (meson Domainp_applyI rel_set_def) from ex_comm_monoid_add_around_imageE[OF ex_comm transfer_pls transfer_zero Domains] obtain C where comm: "comm_monoid_add_on_with C pls zero" and C: "f ` S \ C" and "Domainp (rel_set A) C" by auto then obtain C' where [transfer_rule]: "rel_set A C C'" by auto interpret comm: comm_monoid_add_on_with C pls zero by fact have C': "g ` T \ C'" by transfer (rule C) have comm': "comm_monoid_add_on_with C' pls' zero'" by transfer (rule comm) then interpret comm': comm_monoid_add_on_with C' pls' zero' . from C' comm' have ex_comm': "\C. g ` T \ C \ comm_monoid_add_on_with C pls' zero'" by auto show ?thesis using transfer_T C C' proof (induction S arbitrary: T rule: infinite_finite_induct) case (infinite S) note [transfer_rule] = infinite.prems from infinite.hyps have "infinite T" by transfer then show ?case by (simp add: sum_with_def infinite.hyps \A zero zero'\) next case [transfer_rule]: empty have "T = {}" by transfer rule then show ?case by (simp add: sum_with_def \A zero zero'\) next case (insert x F) note [transfer_rule] = insert.prems(1) have [simp]: "finite T" by transfer (simp add: insert.hyps) obtain y where [transfer_rule]: "B x y" and y: "y \ T" by (meson insert.prems insertI1 rel_setD1) define T' where "T' = T - {y}" have T_def: "T = insert y T'" by (auto simp: T'_def y) define sF where "sF = sum_with pls zero f F" define sT where "sT = sum_with pls' zero' g T'" have [simp]: "y \ T'" "finite T'" by (auto simp: y T'_def) have "rel_set B (insert x F - {x}) T'" unfolding T'_def by transfer_prover then have transfer_T'[transfer_rule]: "rel_set B F T'" using insert.hyps by simp from insert.prems have "f ` F \ C" "g ` T' \ C'" by (auto simp: T'_def) from insert.IH[OF transfer_T' this] have [transfer_rule]: "A sF sT" by (auto simp: sF_def sT_def o_def) have rew: "(sum_with pls zero f (insert x F)) = pls (f x) (sum_with pls zero f F)" apply (subst comm.sum_with_insert) subgoal using insert.prems by auto subgoal using insert.prems by auto subgoal by fact subgoal by fact subgoal by auto done have rew': "(sum_with pls' zero' g (insert y T')) = pls' (g y) (sum_with pls' zero' g T')" apply (subst comm'.sum_with_insert) subgoal apply transfer using insert.prems by auto subgoal apply transfer using insert.prems by auto subgoal by fact subgoal by fact subgoal by auto done have "A (sum_with pls zero f (insert x F)) (sum_with pls' zero' g (insert y T'))" unfolding sT_def[symmetric] sF_def[symmetric] rew rew' by transfer_prover then show ?case by (simp add: T_def) qed next assume *: "\C. f ` S \ C \ comm_monoid_add_on_with C pls zero" then have **: "\C'. g ` T \ C' \ comm_monoid_add_on_with C' pls' zero'" by transfer simp show ?thesis by (simp add: sum_with_def * ** \A zero zero'\) qed qed subsection \Rewrite rules to make \ab_group_add\ operations explicit\ named_theorems explicit_ab_group_add lemmas [explicit_ab_group_add] = sum_with subsection \Locale defining \ab_group_add\-Operations in a local type\ locale local_typedef_ab_group_add_on_with = local_typedef S s + ab_group_add_on_with S for S ::"'b set" and s::"'s itself" begin lemma mem_minus_lt: "x \ S \ y \ S \ mns x y \ S" using ab_diff_conv_add_uminus[of x y] add_mem[of x "um y"] uminus_mem[of y] by auto context includes lifting_syntax begin definition plus_S::"'s \ 's \ 's" where "plus_S = (rep ---> rep ---> Abs) pls" definition minus_S::"'s \ 's \ 's" where "minus_S = (rep ---> rep ---> Abs) mns" definition uminus_S::"'s \ 's" where "uminus_S = (rep ---> Abs) um" definition zero_S::"'s" where "zero_S = Abs z" lemma plus_S_transfer[transfer_rule]: "(cr_S ===> cr_S ===> cr_S) pls plus_S" unfolding plus_S_def by (auto simp: cr_S_def add_mem intro!: rel_funI) lemma minus_S_transfer[transfer_rule]: "(cr_S ===> cr_S ===> cr_S) mns minus_S" unfolding minus_S_def by (auto simp: cr_S_def mem_minus_lt intro!: rel_funI) lemma uminus_S_transfer[transfer_rule]: "(cr_S ===> cr_S) um uminus_S" unfolding uminus_S_def by (auto simp: cr_S_def uminus_mem intro!: rel_funI) lemma zero_S_transfer[transfer_rule]: "cr_S z zero_S" unfolding zero_S_def by (auto simp: cr_S_def zero_mem intro!: rel_funI) end sublocale type: ab_group_add plus_S "zero_S::'s" minus_S uminus_S apply unfold_locales subgoal by transfer (rule add_assoc) subgoal by transfer (rule add_commute) subgoal by transfer (rule add_zero) subgoal by transfer (rule ab_left_minus) subgoal by transfer (rule ab_diff_conv_add_uminus) done context includes lifting_syntax begin lemma sum_transfer[transfer_rule]: "((A===>cr_S) ===> rel_set A ===> cr_S) (sum_with pls z) type.sum" if [transfer_rule]: "bi_unique A" proof (safe intro!: rel_funI) fix f g I J assume fg[transfer_rule]: "(A ===> cr_S) f g" and rel_set: "rel_set A I J" show "cr_S (sum_with pls z f I) (type.sum g J)" using rel_set proof (induction I arbitrary: J rule: infinite_finite_induct) case (infinite I) note [transfer_rule] = infinite.prems from infinite.hyps have "infinite J" by transfer with infinite.hyps show ?case by (simp add: zero_S_transfer sum_with_infinite) next case [transfer_rule]: empty have "J = {}" by transfer rule then show ?case by (simp add: zero_S_transfer) next case (insert x F) note [transfer_rule] = insert.prems have [simp]: "finite J" by transfer (simp add: insert.hyps) obtain y where [transfer_rule]: "A x y" and y: "y \ J" by (meson insert.prems insertI1 rel_setD1) define J' where "J' = J - {y}" have T_def: "J = insert y J'" by (auto simp: J'_def y) define sF where "sF = sum_with pls z f F" define sT where "sT = type.sum g J'" have [simp]: "y \ J'" "finite J'" by (auto simp: y J'_def) have "rel_set A (insert x F - {x}) J'" unfolding J'_def by transfer_prover then have "rel_set A F J'" using insert.hyps by simp from insert.IH[OF this] have [transfer_rule]: "cr_S sF sT" by (auto simp: sF_def sT_def) have f_S: "f x \ S" "f ` F \ S" using \A x y\ fg insert.prems by (auto simp: rel_fun_def cr_S_def rel_set_def) have "cr_S (pls (f x) sF) (plus_S (g y) sT)" by transfer_prover then have "cr_S (sum_with pls z f (insert x F)) (type.sum g (insert y J'))" by (simp add: sum_with_insert insert.hyps type.sum.insert_remove sF_def[symmetric] sT_def[symmetric] f_S) then show ?case by (simp add: T_def) qed qed end end subsection \transfer theorems from \<^term>\class.ab_group_add\ to \<^term>\ab_group_add_on_with\\ context ab_group_add_on_with begin context includes lifting_syntax assumes ltd: "\(Rep::'s \ 'a) (Abs::'a \ 's). type_definition Rep Abs S" begin interpretation local_typedef_ab_group_add_on_with pls z mns um S "TYPE('s)" by unfold_locales fact text\Get theorem names:\ print_locale! ab_group_add lemmas lt_sum_mono_neutral_cong_left = sum.mono_neutral_cong_left [var_simplified explicit_ab_group_add, unoverload_type 'c, OF type.comm_monoid_add_axioms, untransferred] end lemmas sum_mono_neutral_cong_left = lt_sum_mono_neutral_cong_left [cancel_type_definition, OF carrier_ne, simplified pred_fun_def, simplified] end end