# HG changeset patch # User Cezary Kaliszyk # Date 1323671574 -32400 # Node ID 2b7eb46e70f9e8d381736d00894317a979de50cc # Parent a644ba1d7cf9d247a4a4db569410f57375b8d2f9 Add Quotient_Rat: an example of using the quotient package with partial equivalence relations, defining rational numbers. diff -r a644ba1d7cf9 -r 2b7eb46e70f9 src/HOL/Quotient_Examples/Quotient_Rat.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Quotient_Examples/Quotient_Rat.thy Mon Dec 12 15:32:54 2011 +0900 @@ -0,0 +1,287 @@ +(* Title: HOL/Quotient_Examples/Quotient_Rat.thy + Author: Cezary Kaliszyk + +Rational numbers defined with the quotient package, based on 'HOL/Rat.thy' by Makarius. +*) + +theory Quotient_Rat imports Archimedean_Field + "~~/src/HOL/Library/Quotient_Product" +begin + +definition + ratrel :: "(int \ int) \ (int \ int) \ bool" (infix "\" 50) +where + [simp]: "x \ y \ snd x \ 0 \ snd y \ 0 \ fst x * snd y = fst y * snd x" + +lemma ratrel_equivp: + "part_equivp ratrel" +proof (auto intro!: part_equivpI reflpI sympI transpI exI[of _ "1 :: int"]) + fix a b c d e f :: int + assume nz: "d \ 0" "b \ 0" + assume y: "a * d = c * b" + assume x: "c * f = e * d" + then have "c * b * f = e * d * b" using nz by simp + then have "a * d * f = e * d * b" using y by simp + then show "a * f = e * b" using nz by simp +qed + +quotient_type rat = "int \ int" / partial: ratrel + using ratrel_equivp . + +instantiation rat :: "{zero, one, plus, uminus, minus, times, ord, abs_if, sgn_if}" +begin + +quotient_definition + "0 \ rat" is "(0\int, 1\int)" + +quotient_definition + "1 \ rat" is "(1\int, 1\int)" + +fun times_rat_raw where + "times_rat_raw (a :: int, b :: int) (c, d) = (a * c, b * d)" + +quotient_definition + "(op *) :: (rat \ rat \ rat)" is times_rat_raw + +fun plus_rat_raw where + "plus_rat_raw (a :: int, b :: int) (c, d) = (a * d + c * b, b * d)" + +quotient_definition + "(op +) :: (rat \ rat \ rat)" is plus_rat_raw + +fun uminus_rat_raw where + "uminus_rat_raw (a :: int, b :: int) = (-a, b)" + +quotient_definition + "(uminus \ (rat \ rat))" is "uminus_rat_raw" + +definition + minus_rat_def: "a - b = a + (-b\rat)" + +fun le_rat_raw where + "le_rat_raw (a :: int, b) (c, d) \ (a * d) * (b * d) \ (c * b) * (b * d)" + +quotient_definition + "(op \) :: rat \ rat \ bool" is "le_rat_raw" + +definition + less_rat_def: "(z\rat) < w = (z \ w \ z \ w)" + +definition + rabs_rat_def: "\i\rat\ = (if i < 0 then - i else i)" + +definition + sgn_rat_def: "sgn (i\rat) = (if i = 0 then 0 else if 0 < i then 1 else - 1)" + +instance by intro_classes + (auto simp add: rabs_rat_def sgn_rat_def) + +end + +definition + Fract_raw :: "int \ int \ (int \ int)" +where [simp]: "Fract_raw a b = (if b = 0 then (0, 1) else (a, b))" + +quotient_definition "Fract :: int \ int \ rat" is + Fract_raw + +lemma [quot_respect]: + "(op \ ===> op \ ===> op \) times_rat_raw times_rat_raw" + "(op \ ===> op \ ===> op \) plus_rat_raw plus_rat_raw" + "(op \ ===> op \) uminus_rat_raw uminus_rat_raw" + "(op = ===> op = ===> op \) Fract_raw Fract_raw" + by (auto intro!: fun_relI simp add: mult_assoc mult_commute mult_left_commute int_distrib(2)) + +lemmas [simp] = Respects_def + +instantiation rat :: comm_ring_1 +begin + +instance proof + fix a b c :: rat + show "a * b * c = a * (b * c)" + by partiality_descending auto + show "a * b = b * a" + by partiality_descending auto + show "1 * a = a" + by partiality_descending auto + show "a + b + c = a + (b + c)" + by partiality_descending (auto simp add: mult_commute right_distrib) + show "a + b = b + a" + by partiality_descending auto + show "0 + a = a" + by partiality_descending auto + show "- a + a = 0" + by partiality_descending auto + show "a - b = a + - b" + by (simp add: minus_rat_def) + show "(a + b) * c = a * c + b * c" + by partiality_descending (auto simp add: mult_commute right_distrib) + show "(0 :: rat) \ (1 :: rat)" + by partiality_descending auto +qed + +end + +lemma add_one_Fract: "1 + Fract (int k) 1 = Fract (1 + int k) 1" + by descending auto + +lemma of_nat_rat: "of_nat k = Fract (of_nat k) 1" + apply (induct k) + apply (simp add: zero_rat_def Fract_def) + apply (simp add: add_one_Fract) + done + +lemma of_int_rat: "of_int k = Fract k 1" + apply (cases k rule: int_diff_cases) + apply (auto simp add: of_nat_rat minus_rat_def) + apply descending + apply auto + done + +instantiation rat :: number_ring +begin + +definition + rat_number_of_def: "number_of w = Fract w 1" + +instance apply default + unfolding rat_number_of_def of_int_rat .. + +end + +instantiation rat :: field_inverse_zero begin + +fun rat_inverse_raw where + "rat_inverse_raw (a :: int, b :: int) = (if a = 0 then (0, 1) else (b, a))" + +quotient_definition + "inverse :: rat \ rat" is rat_inverse_raw + +definition + divide_rat_def: "q / r = q * inverse (r::rat)" + +lemma [quot_respect]: + "(op \ ===> op \) rat_inverse_raw rat_inverse_raw" + by (auto intro!: fun_relI simp add: mult_commute) + +instance proof + fix q :: rat + assume "q \ 0" + then show "inverse q * q = 1" + by partiality_descending auto +next + fix q r :: rat + show "q / r = q * inverse r" by (simp add: divide_rat_def) +next + show "inverse 0 = (0::rat)" by partiality_descending auto +qed + +end + +lemma [quot_respect]: "(op \ ===> op \ ===> op =) le_rat_raw le_rat_raw" +proof - + { + fix a b c d e f g h :: int + assume "a * f * (b * f) \ e * b * (b * f)" + then have le: "a * f * b * f \ e * b * b * f" by simp + assume nz: "b \ 0" "d \ 0" "f \ 0" "h \ 0" + then have b2: "b * b > 0" + by (metis linorder_neqE_linordered_idom mult_eq_0_iff not_square_less_zero) + have f2: "f * f > 0" using nz(3) + by (metis linorder_neqE_linordered_idom mult_eq_0_iff not_square_less_zero) + assume eq: "a * d = c * b" "e * h = g * f" + have "a * f * b * f * d * d \ e * b * b * f * d * d" using le nz(2) + by (metis linorder_le_cases mult_right_mono mult_right_mono_neg) + then have "c * f * f * d * (b * b) \ e * f * d * d * (b * b)" using eq + by (metis (no_types) mult_assoc mult_commute) + then have "c * f * f * d \ e * f * d * d" using b2 + by (metis leD linorder_le_less_linear mult_strict_right_mono) + then have "c * f * f * d * h * h \ e * f * d * d * h * h" using nz(4) + by (metis linorder_le_cases mult_right_mono mult_right_mono_neg) + then have "c * h * (d * h) * (f * f) \ g * d * (d * h) * (f * f)" using eq + by (metis (no_types) mult_assoc mult_commute) + then have "c * h * (d * h) \ g * d * (d * h)" using f2 + by (metis leD linorder_le_less_linear mult_strict_right_mono) + } + then show ?thesis by (auto intro!: fun_relI) +qed + +instantiation rat :: linorder +begin + +instance proof + fix q r s :: rat + { + assume "q \ r" and "r \ s" + then show "q \ s" + proof (partiality_descending, auto simp add: mult_assoc[symmetric]) + fix a b c d e f :: int + assume nz: "b \ 0" "d \ 0" "f \ 0" + then have d2: "d * d > 0" + by (metis linorder_neqE_linordered_idom mult_eq_0_iff not_square_less_zero) + assume le: "a * d * b * d \ c * b * b * d" "c * f * d * f \ e * d * d * f" + then have a: "a * d * b * d * f * f \ c * b * b * d * f * f" using nz(3) + by (metis linorder_le_cases mult_right_mono mult_right_mono_neg) + have "c * f * d * f * b * b \ e * d * d * f * b * b" using nz(1) le + by (metis linorder_le_cases mult_right_mono mult_right_mono_neg) + then have "a * f * b * f * (d * d) \ e * b * b * f * (d * d)" using a + by (simp add: algebra_simps) + then show "a * f * b * f \ e * b * b * f" using d2 + by (metis leD linorder_le_less_linear mult_strict_right_mono) + qed + next + assume "q \ r" and "r \ q" + then show "q = r" + apply (partiality_descending, auto) + apply (case_tac "b > 0", case_tac [!] "ba > 0") + apply simp_all + done + next + show "q \ q" by partiality_descending auto + show "(q < r) = (q \ r \ \ r \ q)" + unfolding less_rat_def + by partiality_descending (auto simp add: le_less mult_commute) + show "q \ r \ r \ q" + by partiality_descending (auto simp add: mult_commute linorder_linear) + } +qed + +end + +instance rat :: archimedean_field +proof + fix q r s :: rat + show "q \ r ==> s + q \ s + r" + proof (partiality_descending, auto simp add: algebra_simps, simp add: mult_assoc[symmetric]) + fix a b c d e :: int + assume "e \ 0" + then have e2: "e * e > 0" + by (metis linorder_neqE_linordered_idom mult_eq_0_iff not_square_less_zero) + assume "a * b * d * d \ b * b * c * d" + then show "a * b * d * d * e * e * e * e \ b * b * c * d * e * e * e * e" + using e2 by (metis comm_mult_left_mono mult_commute linorder_le_cases + mult_left_mono_neg) + qed + show "q < r ==> 0 < s ==> s * q < s * r" unfolding less_rat_def + proof (partiality_descending, auto simp add: algebra_simps, simp add: mult_assoc[symmetric]) + fix a b c d e f :: int + assume a: "e \ 0" "f \ 0" "0 \ e * f" "a * b * d * d \ b * b * c * d" + have "a * b * d * d * (e * f) \ b * b * c * d * (e * f)" using a + by (simp add: mult_right_mono) + then show "a * b * d * d * e * f * f * f \ b * b * c * d * e * f * f * f" + by (simp add: mult_assoc[symmetric]) (metis a(3) comm_mult_left_mono + mult_commute mult_left_mono_neg zero_le_mult_iff) + qed + show "\z. r \ of_int z" + unfolding of_int_rat + proof (partiality_descending, auto) + fix a b :: int + assume "b \ 0" + then have "a * b \ (a div b + 1) * b * b" + by (metis mult_commute div_mult_self1_is_id less_int_def linorder_le_cases zdiv_mono1 zdiv_mono1_neg zle_add1_eq_le) + then show "\z\int. a * b \ z * b * b" by auto + qed +qed + +end diff -r a644ba1d7cf9 -r 2b7eb46e70f9 src/HOL/Quotient_Examples/ROOT.ML --- a/src/HOL/Quotient_Examples/ROOT.ML Sun Dec 11 21:57:22 2011 +0100 +++ b/src/HOL/Quotient_Examples/ROOT.ML Mon Dec 12 15:32:54 2011 +0900 @@ -5,5 +5,5 @@ *) use_thys ["DList", "FSet", "Quotient_Int", "Quotient_Message", "Quotient_Cset", - "List_Quotient_Cset", "Lift_Set", "Lift_RBT", "Lift_Fun"]; + "List_Quotient_Cset", "Lift_Set", "Lift_RBT", "Lift_Fun", "Quotient_Rat"];