diff -r a4abccde0929 -r af871d13e320 src/HOL/ex/LocaleTest2.thy --- a/src/HOL/ex/LocaleTest2.thy Mon Jul 23 13:47:48 2007 +0200 +++ b/src/HOL/ex/LocaleTest2.thy Mon Jul 23 13:48:30 2007 +0200 @@ -5,26 +5,635 @@ More regression tests for locales. Definitions are less natural in FOL, since there is no selection operator. -Hence we do them in HOL, not in the main test suite for locales: -FOL/ex/LocaleTest.thy +Hence we do them here in HOL, not in the main test suite for locales, +which is FOL/ex/LocaleTest.thy *) header {* Test of Locale Interpretation *} theory LocaleTest2 -imports Main +imports GCD begin -ML {* set quick_and_dirty *} (* allow for thm command in batch mode *) -ML {* set show_hyps *} -ML {* set show_sorts *} - - -subsection {* Interpretation of Defined Concepts *} +section {* Interpretation of Defined Concepts *} text {* Naming convention for global objects: prefixes D and d *} -(* Group example with defined operation inv *) + +subsection {* Lattices *} + +text {* Much of the lattice proofs are from HOL/Lattice. *} + + +subsubsection {* Definitions *} + +locale dpo = + fixes le :: "['a, 'a] => bool" (infixl "\" 50) + assumes refl [intro, simp]: "x \ x" + and anti_sym [intro]: "[| x \ y; y \ x |] ==> x = y" + and trans [trans]: "[| x \ y; y \ z |] ==> x \ z" + +begin + +theorem circular: + "[| x \ y; y \ z; z \ x |] ==> x = y & y = z" + by (blast intro: trans) + +definition + less :: "['a, 'a] => bool" (infixl "\" 50) + where "(x \ y) = (x \ y & x ~= y)" + +theorem abs_test: + "op \ = (%x y. x \ y)" + by simp + +definition + is_inf :: "['a, 'a, 'a] => bool" + where "is_inf x y i = (i \ x \ i \ y \ (\z. z \ x \ z \ y \ z \ i))" + +definition + is_sup :: "['a, 'a, 'a] => bool" + where "is_sup x y s = (x \ s \ y \ s \ (\z. x \ z \ y \ z \ s \ z))" + +end + +locale dlat = dpo + + assumes ex_inf: "EX inf. dpo.is_inf le x y inf" + and ex_sup: "EX sup. dpo.is_sup le x y sup" + +begin + +definition + meet :: "['a, 'a] => 'a" (infixl "\" 70) + where "x \ y = (THE inf. is_inf x y inf)" + +definition + join :: "['a, 'a] => 'a" (infixl "\" 65) + where "x \ y = (THE sup. is_sup x y sup)" + +lemma is_infI [intro?]: "i \ x \ i \ y \ + (\z. z \ x \ z \ y \ z \ i) \ is_inf x y i" + by (unfold is_inf_def) blast + +lemma is_inf_lower [elim?]: + "is_inf x y i \ (i \ x \ i \ y \ C) \ C" + by (unfold is_inf_def) blast + +lemma is_inf_greatest [elim?]: + "is_inf x y i \ z \ x \ z \ y \ z \ i" + by (unfold is_inf_def) blast + +theorem is_inf_uniq: "is_inf x y i \ is_inf x y i' \ i = i'" +proof - + assume inf: "is_inf x y i" + assume inf': "is_inf x y i'" + show ?thesis + proof (rule anti_sym) + from inf' show "i \ i'" + proof (rule is_inf_greatest) + from inf show "i \ x" .. + from inf show "i \ y" .. + qed + from inf show "i' \ i" + proof (rule is_inf_greatest) + from inf' show "i' \ x" .. + from inf' show "i' \ y" .. + qed + qed +qed + +theorem is_inf_related [elim?]: "x \ y \ is_inf x y x" +proof - + assume "x \ y" + show ?thesis + proof + show "x \ x" .. + show "x \ y" by fact + fix z assume "z \ x" and "z \ y" show "z \ x" by fact + qed +qed + +lemma meet_equality [elim?]: "is_inf x y i \ x \ y = i" +proof (unfold meet_def) + assume "is_inf x y i" + then show "(THE i. is_inf x y i) = i" + by (rule the_equality) (rule is_inf_uniq [OF _ `is_inf x y i`]) +qed + +lemma meetI [intro?]: + "i \ x \ i \ y \ (\z. z \ x \ z \ y \ z \ i) \ x \ y = i" + by (rule meet_equality, rule is_infI) blast+ + +lemma is_inf_meet [intro?]: "is_inf x y (x \ y)" +proof (unfold meet_def) + from ex_inf obtain i where "is_inf x y i" .. + then show "is_inf x y (THE i. is_inf x y i)" + by (rule theI) (rule is_inf_uniq [OF _ `is_inf x y i`]) +qed + +lemma meet_left [intro?]: + "x \ y \ x" + by (rule is_inf_lower) (rule is_inf_meet) + +lemma meet_right [intro?]: + "x \ y \ y" + by (rule is_inf_lower) (rule is_inf_meet) + +lemma meet_le [intro?]: + "[| z \ x; z \ y |] ==> z \ x \ y" + by (rule is_inf_greatest) (rule is_inf_meet) + +lemma is_supI [intro?]: "x \ s \ y \ s \ + (\z. x \ z \ y \ z \ s \ z) \ is_sup x y s" + by (unfold is_sup_def) blast + +lemma is_sup_least [elim?]: + "is_sup x y s \ x \ z \ y \ z \ s \ z" + by (unfold is_sup_def) blast + +lemma is_sup_upper [elim?]: + "is_sup x y s \ (x \ s \ y \ s \ C) \ C" + by (unfold is_sup_def) blast + +theorem is_sup_uniq: "is_sup x y s \ is_sup x y s' \ s = s'" +proof - + assume sup: "is_sup x y s" + assume sup': "is_sup x y s'" + show ?thesis + proof (rule anti_sym) + from sup show "s \ s'" + proof (rule is_sup_least) + from sup' show "x \ s'" .. + from sup' show "y \ s'" .. + qed + from sup' show "s' \ s" + proof (rule is_sup_least) + from sup show "x \ s" .. + from sup show "y \ s" .. + qed + qed +qed + +theorem is_sup_related [elim?]: "x \ y \ is_sup x y y" +proof - + assume "x \ y" + show ?thesis + proof + show "x \ y" by fact + show "y \ y" .. + fix z assume "x \ z" and "y \ z" + show "y \ z" by fact + qed +qed + +lemma join_equality [elim?]: "is_sup x y s \ x \ y = s" +proof (unfold join_def) + assume "is_sup x y s" + then show "(THE s. is_sup x y s) = s" + by (rule the_equality) (rule is_sup_uniq [OF _ `is_sup x y s`]) +qed + +lemma joinI [intro?]: "x \ s \ y \ s \ + (\z. x \ z \ y \ z \ s \ z) \ x \ y = s" + by (rule join_equality, rule is_supI) blast+ + +lemma is_sup_join [intro?]: "is_sup x y (x \ y)" +proof (unfold join_def) + from ex_sup obtain s where "is_sup x y s" .. + then show "is_sup x y (THE s. is_sup x y s)" + by (rule theI) (rule is_sup_uniq [OF _ `is_sup x y s`]) +qed + +lemma join_left [intro?]: + "x \ x \ y" + by (rule is_sup_upper) (rule is_sup_join) + +lemma join_right [intro?]: + "y \ x \ y" + by (rule is_sup_upper) (rule is_sup_join) + +lemma join_le [intro?]: + "[| x \ z; y \ z |] ==> x \ y \ z" + by (rule is_sup_least) (rule is_sup_join) + +theorem meet_assoc: "(x \ y) \ z = x \ (y \ z)" +proof (rule meetI) + show "x \ (y \ z) \ x \ y" + proof + show "x \ (y \ z) \ x" .. + show "x \ (y \ z) \ y" + proof - + have "x \ (y \ z) \ y \ z" .. + also have "\ \ y" .. + finally show ?thesis . + qed + qed + show "x \ (y \ z) \ z" + proof - + have "x \ (y \ z) \ y \ z" .. + also have "\ \ z" .. + finally show ?thesis . + qed + fix w assume "w \ x \ y" and "w \ z" + show "w \ x \ (y \ z)" + proof + show "w \ x" + proof - + have "w \ x \ y" by fact + also have "\ \ x" .. + finally show ?thesis . + qed + show "w \ y \ z" + proof + show "w \ y" + proof - + have "w \ x \ y" by fact + also have "\ \ y" .. + finally show ?thesis . + qed + show "w \ z" by fact + qed + qed +qed + +theorem meet_commute: "x \ y = y \ x" +proof (rule meetI) + show "y \ x \ x" .. + show "y \ x \ y" .. + fix z assume "z \ y" and "z \ x" + then show "z \ y \ x" .. +qed + +theorem meet_join_absorb: "x \ (x \ y) = x" +proof (rule meetI) + show "x \ x" .. + show "x \ x \ y" .. + fix z assume "z \ x" and "z \ x \ y" + show "z \ x" by fact +qed + +theorem join_assoc: "(x \ y) \ z = x \ (y \ z)" +proof (rule joinI) + show "x \ y \ x \ (y \ z)" + proof + show "x \ x \ (y \ z)" .. + show "y \ x \ (y \ z)" + proof - + have "y \ y \ z" .. + also have "... \ x \ (y \ z)" .. + finally show ?thesis . + qed + qed + show "z \ x \ (y \ z)" + proof - + have "z \ y \ z" .. + also have "... \ x \ (y \ z)" .. + finally show ?thesis . + qed + fix w assume "x \ y \ w" and "z \ w" + show "x \ (y \ z) \ w" + proof + show "x \ w" + proof - + have "x \ x \ y" .. + also have "\ \ w" by fact + finally show ?thesis . + qed + show "y \ z \ w" + proof + show "y \ w" + proof - + have "y \ x \ y" .. + also have "... \ w" by fact + finally show ?thesis . + qed + show "z \ w" by fact + qed + qed +qed + +theorem join_commute: "x \ y = y \ x" +proof (rule joinI) + show "x \ y \ x" .. + show "y \ y \ x" .. + fix z assume "y \ z" and "x \ z" + then show "y \ x \ z" .. +qed + +theorem join_meet_absorb: "x \ (x \ y) = x" +proof (rule joinI) + show "x \ x" .. + show "x \ y \ x" .. + fix z assume "x \ z" and "x \ y \ z" + show "x \ z" by fact +qed + +theorem meet_idem: "x \ x = x" +proof - + have "x \ (x \ (x \ x)) = x" by (rule meet_join_absorb) + also have "x \ (x \ x) = x" by (rule join_meet_absorb) + finally show ?thesis . +qed + +theorem meet_related [elim?]: "x \ y \ x \ y = x" +proof (rule meetI) + assume "x \ y" + show "x \ x" .. + show "x \ y" by fact + fix z assume "z \ x" and "z \ y" + show "z \ x" by fact +qed + +theorem meet_related2 [elim?]: "y \ x \ x \ y = y" + by (drule meet_related) (simp add: meet_commute) + +theorem join_related [elim?]: "x \ y \ x \ y = y" +proof (rule joinI) + assume "x \ y" + show "y \ y" .. + show "x \ y" by fact + fix z assume "x \ z" and "y \ z" + show "y \ z" by fact +qed + +theorem join_related2 [elim?]: "y \ x \ x \ y = x" + by (drule join_related) (simp add: join_commute) + + +text {* Additional theorems *} + +theorem meet_connection: "(x \ y) = (x \ y = x)" +proof + assume "x \ y" + then have "is_inf x y x" .. + then show "x \ y = x" .. +next + have "x \ y \ y" .. + also assume "x \ y = x" + finally show "x \ y" . +qed + +theorem meet_connection2: "(x \ y) = (y \ x = x)" + using meet_commute meet_connection by simp + +theorem join_connection: "(x \ y) = (x \ y = y)" +proof + assume "x \ y" + then have "is_sup x y y" .. + then show "x \ y = y" .. +next + have "x \ x \ y" .. + also assume "x \ y = y" + finally show "x \ y" . +qed + +theorem join_connection2: "(x \ y) = (x \ y = y)" + using join_commute join_connection by simp + + +text {* Naming according to Jacobson I, p.\ 459. *} + +lemmas L1 = join_commute meet_commute +lemmas L2 = join_assoc meet_assoc +(*lemmas L3 = join_idem meet_idem*) +lemmas L4 = join_meet_absorb meet_join_absorb + +end + +locale ddlat = dlat + + assumes meet_distr: + "dlat.meet le x (dlat.join le y z) = + dlat.join le (dlat.meet le x y) (dlat.meet le x z)" + +begin + +lemma join_distr: + "x \ (y \ z) = (x \ y) \ (x \ z)" + txt {* Jacobson I, p.\ 462 *} +proof - + have "x \ (y \ z) = (x \ (x \ z)) \ (y \ z)" by (simp add: L4) + also have "... = x \ ((x \ z) \ (y \ z))" by (simp add: L2) + also have "... = x \ ((x \ y) \ z)" by (simp add: L1 meet_distr) + also have "... = ((x \ y) \ x) \ ((x \ y) \ z)" by (simp add: L1 L4) + also have "... = (x \ y) \ (x \ z)" by (simp add: meet_distr) + finally show ?thesis . +qed + +end + +locale dlo = dpo + + assumes total: "x \ y | y \ x" + +begin + +lemma less_total: "x \ y | x = y | y \ x" + using total + by (unfold less_def) blast + +end + + +interpretation dlo < dlat +(* TODO: definition syntax is unavailable *) +proof unfold_locales + fix x y + from total have "is_inf x y (if x \ y then x else y)" by (auto simp: is_inf_def) + then show "EX inf. is_inf x y inf" by blast +next + fix x y + from total have "is_sup x y (if x \ y then y else x)" by (auto simp: is_sup_def) + then show "EX sup. is_sup x y sup" by blast +qed + +interpretation dlo < ddlat +proof unfold_locales + fix x y z + show "x \ (y \ z) = x \ y \ x \ z" (is "?l = ?r") + txt {* Jacobson I, p.\ 462 *} + proof - + { assume c: "y \ x" "z \ x" + from c have "?l = y \ z" + by (metis c (*join_commute*) join_connection2 join_related2 (*meet_commute*) meet_connection meet_related2 total) + also from c have "... = ?r" by (metis (*c*) (*join_commute*) meet_related2) + finally have "?l = ?r" . } + moreover + { assume c: "x \ y | x \ z" + from c have "?l = x" + by (metis (*anti_sym*) (*c*) (*circular*) (*join_assoc*)(* join_commute *) join_connection2 (*join_left*) join_related2 meet_connection(* meet_related2*) total trans) + also from c have "... = ?r" + by (metis join_commute join_related2 meet_connection meet_related2 total) + finally have "?l = ?r" . } + moreover note total + ultimately show ?thesis by blast + qed +qed + +subsubsection {* Total order @{text "<="} on @{typ int} *} + +interpretation int: dpo ["op <= :: [int, int] => bool"] + where "(dpo.less (op <=) (x::int) y) = (x < y)" + txt {* We give interpretation for less, but not is\_inf and is\_sub. *} +proof - + show "dpo (op <= :: [int, int] => bool)" + by unfold_locales auto + then interpret int: dpo ["op <= :: [int, int] => bool"] . + txt {* Gives interpreted version of less\_def (without condition). *} + show "(dpo.less (op <=) (x::int) y) = (x < y)" + by (unfold int.less_def) auto +qed + +thm int.circular +lemma "\ (x::int) \ y; y \ z; z \ x\ \ x = y \ y = z" + apply (rule int.circular) apply assumption apply assumption apply assumption done +thm int.abs_test +lemma "(op < :: [int, int] => bool) = op <" + apply (rule int.abs_test) done + +interpretation int: dlat ["op <= :: [int, int] => bool"] + where "dlat.meet (op <=) (x::int) y = min x y" + and "dlat.join (op <=) (x::int) y = max x y" +proof - + show "dlat (op <= :: [int, int] => bool)" + apply unfold_locales + apply (unfold int.is_inf_def int.is_sup_def) + apply arith+ + done + then interpret int: dlat ["op <= :: [int, int] => bool"] . + txt {* Interpretation to ease use of definitions, which are + conditional in general but unconditional after interpretation. *} + show "dlat.meet (op <=) (x::int) y = min x y" + apply (unfold int.meet_def) + apply (rule the_equality) + apply (unfold int.is_inf_def) + by auto + show "dlat.join (op <=) (x::int) y = max x y" + apply (unfold int.join_def) + apply (rule the_equality) + apply (unfold int.is_sup_def) + by auto +qed + +interpretation int: dlo ["op <= :: [int, int] => bool"] + by unfold_locales arith + +text {* Interpreted theorems from the locales, involving defined terms. *} + +thm int.less_def text {* from dpo *} +thm int.meet_left text {* from dlat *} +thm int.meet_distr text {* from ddlat *} +thm int.less_total text {* from dlo *} + + +subsubsection {* Total order @{text "<="} on @{typ nat} *} + +interpretation nat: dpo ["op <= :: [nat, nat] => bool"] + where "dpo.less (op <=) (x::nat) y = (x < y)" + txt {* We give interpretation for less, but not is\_inf and is\_sub. *} +proof - + show "dpo (op <= :: [nat, nat] => bool)" + by unfold_locales auto + then interpret nat: dpo ["op <= :: [nat, nat] => bool"] . + txt {* Gives interpreted version of less\_def (without condition). *} + show "dpo.less (op <=) (x::nat) y = (x < y)" + apply (unfold nat.less_def) + apply auto + done +qed + +interpretation nat: dlat ["op <= :: [nat, nat] => bool"] + where "dlat.meet (op <=) (x::nat) y = min x y" + and "dlat.join (op <=) (x::nat) y = max x y" +proof - + show "dlat (op <= :: [nat, nat] => bool)" + apply unfold_locales + apply (unfold nat.is_inf_def nat.is_sup_def) + apply arith+ + done + then interpret nat: dlat ["op <= :: [nat, nat] => bool"] . + txt {* Interpretation to ease use of definitions, which are + conditional in general but unconditional after interpretation. *} + show "dlat.meet (op <=) (x::nat) y = min x y" + apply (unfold nat.meet_def) + apply (rule the_equality) + apply (unfold nat.is_inf_def) + by auto + show "dlat.join (op <=) (x::nat) y = max x y" + apply (unfold nat.join_def) + apply (rule the_equality) + apply (unfold nat.is_sup_def) + by auto +qed + +interpretation nat: dlo ["op <= :: [nat, nat] => bool"] + by unfold_locales arith + +text {* Interpreted theorems from the locales, involving defined terms. *} + +thm nat.less_def text {* from dpo *} +thm nat.meet_left text {* from dlat *} +thm nat.meet_distr text {* from ddlat *} +thm nat.less_total text {* from ldo *} + + +subsubsection {* Lattice @{text "dvd"} on @{typ nat} *} + +interpretation nat_dvd: dpo ["op dvd :: [nat, nat] => bool"] + where "dpo.less (op dvd) (x::nat) y = (x dvd y & x ~= y)" + txt {* We give interpretation for less, but not is\_inf and is\_sub. *} +proof - + show "dpo (op dvd :: [nat, nat] => bool)" + by unfold_locales (auto simp: dvd_def) + then interpret nat_dvd: dpo ["op dvd :: [nat, nat] => bool"] . + txt {* Gives interpreted version of less\_def (without condition). *} + show "dpo.less (op dvd) (x::nat) y = (x dvd y & x ~= y)" + apply (unfold nat_dvd.less_def) + apply auto + done +qed + +interpretation nat_dvd: dlat ["op dvd :: [nat, nat] => bool"] + where "dlat.meet (op dvd) (x::nat) y = gcd (x, y)" + and "dlat.join (op dvd) (x::nat) y = lcm (x, y)" +proof - + show "dlat (op dvd :: [nat, nat] => bool)" + apply unfold_locales + apply (unfold nat_dvd.is_inf_def nat_dvd.is_sup_def) + apply (rule_tac x = "gcd (x, y)" in exI) + apply auto [1] + apply (rule_tac x = "lcm (x, y)" in exI) + apply (auto intro: lcm_dvd1 lcm_dvd2 lcm_lowest) + done + then interpret nat_dvd: dlat ["op dvd :: [nat, nat] => bool"] . + txt {* Interpretation to ease use of definitions, which are + conditional in general but unconditional after interpretation. *} + show "dlat.meet (op dvd) (x::nat) y = gcd (x, y)" + apply (unfold nat_dvd.meet_def) + apply (rule the_equality) + apply (unfold nat_dvd.is_inf_def) + by auto + show "dlat.join (op dvd) (x::nat) y = lcm (x, y)" + apply (unfold nat_dvd.join_def) + apply (rule the_equality) + apply (unfold nat_dvd.is_sup_def) + by (auto intro: lcm_dvd1 lcm_dvd2 lcm_lowest) +qed + +text {* Interpreted theorems from the locales, involving defined terms. *} + +thm nat_dvd.less_def text {* from dpo *} +lemma "((x::nat) dvd y & x ~= y) = (x dvd y & x ~= y)" + apply (rule nat_dvd.less_def) done +thm nat_dvd.meet_left text {* from dlat *} +lemma "gcd (x, y) dvd x" + apply (rule nat_dvd.meet_left) done + +print_interps dpo +print_interps dlat + + +subsection {* Group example with defined operations @{text inv} and @{text unit} *} + +subsubsection {* Locale declarations and lemmas *} locale Dsemi = fixes prod (infixl "**" 65) @@ -32,128 +641,279 @@ locale Dmonoid = Dsemi + fixes one - assumes lone: "one ** x = x" - and rone: "x ** one = x" + assumes l_one [simp]: "one ** x = x" + and r_one [simp]: "x ** one = x" + +begin -definition (in Dmonoid) - inv where "inv(x) == THE y. x ** y = one & y ** x = one" +definition + inv where "inv x = (THE y. x ** y = one & y ** x = one)" +definition + unit where "unit x = (EX y. x ** y = one & y ** x = one)" -lemma (in Dmonoid) inv_unique: +lemma inv_unique: assumes eq: "y ** x = one" "x ** y' = one" shows "y = y'" proof - - from eq have "y = y ** (x ** y')" by (simp add: rone) + from eq have "y = y ** (x ** y')" by (simp add: r_one) also have "... = (y ** x) ** y'" by (simp add: assoc) - also from eq have "... = y'" by (simp add: lone) + also from eq have "... = y'" by (simp add: l_one) finally show ?thesis . qed -locale Dgrp = Dmonoid + - assumes linv_ex: "EX y. y ** x = one" - and rinv_ex: "EX y. x ** y = one" +lemma unit_one [intro, simp]: + "unit one" + by (unfold unit_def) auto + +lemma unit_l_inv_ex: + "unit x ==> \y. y ** x = one" + by (unfold unit_def) auto + +lemma unit_r_inv_ex: + "unit x ==> \y. x ** y = one" + by (unfold unit_def) auto + +lemma unit_l_inv: + "unit x ==> inv x ** x = one" + apply (simp add: unit_def inv_def) apply (erule exE) + apply (rule theI2, fast) + apply (rule inv_unique) + apply fast+ + done -lemma (in Dgrp) linv: - "inv x ** x = one" -apply (unfold inv_def) -apply (insert rinv_ex [where x = x]) -apply (insert linv_ex [where x = x]) -apply (erule exE) apply (erule exE) -apply (rule theI2) -apply rule apply assumption -apply (frule inv_unique, assumption) -apply simp -apply (rule inv_unique) -apply fast+ -done +lemma unit_r_inv: + "unit x ==> x ** inv x = one" + apply (simp add: unit_def inv_def) apply (erule exE) + apply (rule theI2, fast) + apply (rule inv_unique) + apply fast+ + done + +lemma unit_inv_unit [intro, simp]: + "unit x ==> unit (inv x)" +proof - + assume x: "unit x" + show "unit (inv x)" + by (auto simp add: unit_def + intro: unit_l_inv unit_r_inv x) +qed + +lemma unit_l_cancel [simp]: + "unit x ==> (x ** y = x ** z) = (y = z)" +proof + assume eq: "x ** y = x ** z" + and G: "unit x" + then have "(inv x ** x) ** y = (inv x ** x) ** z" + by (simp add: assoc) + with G show "y = z" by (simp add: unit_l_inv) +next + assume eq: "y = z" + and G: "unit x" + then show "x ** y = x ** z" by simp +qed -lemma (in Dgrp) rinv: +lemma unit_inv_inv [simp]: + "unit x ==> inv (inv x) = x" +proof - + assume x: "unit x" + then have "inv x ** inv (inv x) = inv x ** x" + by (simp add: unit_l_inv unit_r_inv) + with x show ?thesis by simp +qed + +lemma inv_inj_on_unit: + "inj_on inv {x. unit x}" +proof (rule inj_onI, simp) + fix x y + assume G: "unit x" "unit y" and eq: "inv x = inv y" + then have "inv (inv x) = inv (inv y)" by simp + with G show "x = y" by simp +qed + +lemma unit_inv_comm: + assumes inv: "x ** y = one" + and G: "unit x" "unit y" + shows "y ** x = one" +proof - + from G have "x ** y ** x = x ** one" by (auto simp add: inv) + with G show ?thesis by (simp del: r_one add: assoc) +qed + +end + + +locale Dgrp = Dmonoid + + assumes unit [intro, simp]: "Dmonoid.unit (op **) one x" + +begin + +lemma l_inv_ex [simp]: + "\y. y ** x = one" + using unit_l_inv_ex by simp + +lemma r_inv_ex [simp]: + "\y. x ** y = one" + using unit_r_inv_ex by simp + +lemma l_inv [simp]: + "inv x ** x = one" + using unit_l_inv by simp + +lemma l_cancel [simp]: + "(x ** y = x ** z) = (y = z)" + using unit_l_inv by simp + +lemma r_inv [simp]: "x ** inv x = one" -apply (unfold inv_def) -apply (insert rinv_ex [where x = x]) -apply (insert linv_ex [where x = x]) -apply (erule exE) apply (erule exE) -apply (rule theI2) -apply rule apply assumption -apply (frule inv_unique, assumption) -apply simp -apply (rule inv_unique) -apply fast+ -done +proof - + have "inv x ** (x ** inv x) = inv x ** one" + by (simp add: assoc [symmetric] l_inv) + then show ?thesis by (simp del: r_one) +qed -lemma (in Dgrp) lcancel: - "x ** y = x ** z <-> y = z" +lemma r_cancel [simp]: + "(y ** x = z ** x) = (y = z)" proof - assume "x ** y = x ** z" - then have "inv(x) ** x ** y = inv(x) ** x ** z" by (simp add: assoc) - then show "y = z" by (simp add: lone linv) + assume eq: "y ** x = z ** x" + then have "y ** (x ** inv x) = z ** (x ** inv x)" + by (simp add: assoc [symmetric] del: r_inv) + then show "y = z" by simp qed simp -interpretation Dint: Dmonoid ["op +" "0::int"] - where "Dmonoid.inv (op +) (0::int)" = "uminus" +lemma inv_one [simp]: + "inv one = one" proof - - show "Dmonoid (op +) (0::int)" by unfold_locales auto - note Dint = this (* should have this as an assumption in further goals *) - { - fix x - have "Dmonoid.inv (op +) (0::int) x = - x" - by (auto simp: Dmonoid.inv_def [OF Dint]) - } - then show "Dmonoid.inv (op +) (0::int) == uminus" - by (rule_tac eq_reflection) (fast intro: ext) + have "inv one = one ** (inv one)" by (simp del: r_inv) + moreover have "... = one" by simp + finally show ?thesis . qed -thm Dmonoid.inv_def Dint.inv_def +lemma inv_inv [simp]: + "inv (inv x) = x" + using unit_inv_inv by simp -lemma "- x \ THE y. x + y = 0 \ y + x = (0::int)" - apply (rule Dint.inv_def) done +lemma inv_inj: + "inj_on inv UNIV" + using inv_inj_on_unit by simp -interpretation Dclass: Dmonoid ["op +" "0::'a::ab_group_add"] - where "Dmonoid.inv (op +) (0::'a::ab_group_add)" = "uminus" +lemma inv_mult_group: + "inv (x ** y) = inv y ** inv x" proof - - show "Dmonoid (op +) (0::'a::ab_group_add)" by unfold_locales auto - note Dclass = this (* should have this as an assumption in further goals *) - { - fix x - have "Dmonoid.inv (op +) (0::'a::ab_group_add) x = - x" - by (auto simp: Dmonoid.inv_def [OF Dclass] equals_zero_I [symmetric]) - } - then show "Dmonoid.inv (op +) (0::'a::ab_group_add) == uminus" - by (rule_tac eq_reflection) (fast intro: ext) + have "inv (x ** y) ** (x ** y) = (inv y ** inv x) ** (x ** y)" + by (simp add: assoc l_inv) (simp add: assoc [symmetric]) + then show ?thesis by (simp del: l_inv) +qed + +lemma inv_comm: + "x ** y = one ==> y ** x = one" + by (rule unit_inv_comm) auto + +lemma inv_equality: + "y ** x = one ==> inv x = y" + apply (simp add: inv_def) + apply (rule the_equality) + apply (simp add: inv_comm [of y x]) + apply (rule r_cancel [THEN iffD1], auto) + done + +end + + +locale Dhom = Dgrp prod (infixl "**" 65) one + Dgrp sum (infixl "+++" 60) zero + + fixes hom + assumes hom_mult [simp]: "hom (x ** y) = hom x +++ hom y" + +begin + +lemma hom_one [simp]: + "hom one = zero" +proof - + have "hom one +++ zero = hom one +++ hom one" + by (simp add: hom_mult [symmetric] del: hom_mult) + then show ?thesis by (simp del: r_one) qed -interpretation Dclass: Dgrp ["op +" "0::'a::ring"] -apply unfold_locales -apply (rule_tac x="-x" in exI) apply simp -apply (rule_tac x="-x" in exI) apply simp -done +end -(* Equation for inverse from Dclass: Dmonoid effective. *) -thm Dclass.linv -lemma "-x + x = (0::'a::ring)" apply (rule Dclass.linv) done - -(* Equations have effect in "subscriptions" *) - -(* In the same module *) +subsubsection {* Interpretation of Functions *} -lemma (in Dmonoid) trivial: - "inv one = inv one" - by rule - -thm Dclass.trivial - -(* Inherited: interpretation *) - -lemma (in Dgrp) inv_inv: - "inv (inv x) = x" +interpretation Dfun: Dmonoid ["op o" "id :: 'a => 'a"] + where "Dmonoid.unit (op o) id f = bij (f::'a => 'a)" +(* and "Dmonoid.inv (op o) id" = "inv :: ('a => 'a) => ('a => 'a)" *) proof - - have "inv x ** inv (inv x) = inv x ** x" - by (simp add: linv rinv) - then show ?thesis by (simp add: lcancel) + show "Dmonoid op o (id :: 'a => 'a)" by unfold_locales (simp_all add: o_assoc) + note Dmonoid = this +(* + from this interpret Dmonoid ["op o" "id :: 'a => 'a"] . +*) + show "Dmonoid.unit (op o) (id :: 'a => 'a) f = bij f" + apply (unfold Dmonoid.unit_def [OF Dmonoid]) + apply rule apply clarify + proof - + fix f g + assume id1: "f o g = id" and id2: "g o f = id" + show "bij f" + proof (rule bijI) + show "inj f" + proof (rule inj_onI) + fix x y + assume "f x = f y" + then have "(g o f) x = (g o f) y" by simp + with id2 show "x = y" by simp + qed + next + show "surj f" + proof (rule surjI) + fix x + from id1 have "(f o g) x = x" by simp + then show "f (g x) = x" by simp + qed + qed + next + fix f + assume bij: "bij f" + then + have inv: "f o Hilbert_Choice.inv f = id & Hilbert_Choice.inv f o f = id" + by (simp add: bij_def surj_iff inj_iff) + show "EX g. f o g = id & g o f = id" by rule (rule inv) + qed qed -thm Dclass.inv_inv -lemma "- (- x) = (x::'a::ring)" - apply (rule Dclass.inv_inv) done +thm Dmonoid.unit_def Dfun.unit_def + +thm Dmonoid.inv_inj_on_unit Dfun.inv_inj_on_unit + +lemma unit_id: + "(f :: unit => unit) = id" + by rule simp + +interpretation Dfun: Dgrp ["op o" "id :: unit => unit"] + where "Dmonoid.inv (op o) id f = inv (f :: unit => unit)" +proof - + have "Dmonoid op o (id :: 'a => 'a)" by unfold_locales (simp_all add: o_assoc) + note Dmonoid = this + + show "Dgrp (op o) (id :: unit => unit)" +apply unfold_locales +apply (unfold Dmonoid.unit_def [OF Dmonoid]) +apply (insert unit_id) +apply simp +done + show "Dmonoid.inv (op o) id f = inv (f :: unit => unit)" +apply (unfold Dmonoid.inv_def [OF Dmonoid] inv_def) +apply (insert unit_id) +apply simp +apply (rule the_equality) +apply rule +apply rule +apply simp +done +qed + +thm Dfun.unit_l_inv Dfun.l_inv + +thm Dfun.inv_equality +thm Dfun.inv_equality end