25 by (simp add: ratrel_def symp_def) |
25 by (simp add: ratrel_def symp_def) |
26 |
26 |
27 lemma transp_ratrel: "transp ratrel" |
27 lemma transp_ratrel: "transp ratrel" |
28 proof (rule transpI, unfold split_paired_all) |
28 proof (rule transpI, unfold split_paired_all) |
29 fix a b a' b' a'' b'' :: int |
29 fix a b a' b' a'' b'' :: int |
30 assume A: "ratrel (a, b) (a', b')" |
30 assume *: "ratrel (a, b) (a', b')" |
31 assume B: "ratrel (a', b') (a'', b'')" |
31 assume **: "ratrel (a', b') (a'', b'')" |
32 have "b' * (a * b'') = b'' * (a * b')" by simp |
32 have "b' * (a * b'') = b'' * (a * b')" by simp |
33 also from A have "a * b' = a' * b" by auto |
33 also from * have "a * b' = a' * b" by auto |
34 also have "b'' * (a' * b) = b * (a' * b'')" by simp |
34 also have "b'' * (a' * b) = b * (a' * b'')" by simp |
35 also from B have "a' * b'' = a'' * b'" by auto |
35 also from ** have "a' * b'' = a'' * b'" by auto |
36 also have "b * (a'' * b') = b' * (a'' * b)" by simp |
36 also have "b * (a'' * b') = b' * (a'' * b)" by simp |
37 finally have "b' * (a * b'') = b' * (a'' * b)" . |
37 finally have "b' * (a * b'') = b' * (a'' * b)" . |
38 moreover from B have "b' \<noteq> 0" by auto |
38 moreover from ** have "b' \<noteq> 0" by auto |
39 ultimately have "a * b'' = a'' * b" by simp |
39 ultimately have "a * b'' = a'' * b" by simp |
40 with A B show "ratrel (a, b) (a'', b'')" by auto |
40 with * ** show "ratrel (a, b) (a'', b'')" by auto |
41 qed |
41 qed |
42 |
42 |
43 lemma part_equivp_ratrel: "part_equivp ratrel" |
43 lemma part_equivp_ratrel: "part_equivp ratrel" |
44 by (rule part_equivpI [OF exists_ratrel_refl symp_ratrel transp_ratrel]) |
44 by (rule part_equivpI [OF exists_ratrel_refl symp_ratrel transp_ratrel]) |
45 |
45 |
118 lemma One_rat_def: "1 = Fract 1 1" |
118 lemma One_rat_def: "1 = Fract 1 1" |
119 by transfer simp |
119 by transfer simp |
120 |
120 |
121 lift_definition plus_rat :: "rat \<Rightarrow> rat \<Rightarrow> rat" |
121 lift_definition plus_rat :: "rat \<Rightarrow> rat \<Rightarrow> rat" |
122 is "\<lambda>x y. (fst x * snd y + fst y * snd x, snd x * snd y)" |
122 is "\<lambda>x y. (fst x * snd y + fst y * snd x, snd x * snd y)" |
123 by (clarsimp, simp add: distrib_right, simp add: ac_simps) |
123 by (auto simp: distrib_right) (simp add: ac_simps) |
124 |
124 |
125 lemma add_rat [simp]: |
125 lemma add_rat [simp]: |
126 assumes "b \<noteq> 0" and "d \<noteq> 0" |
126 assumes "b \<noteq> 0" and "d \<noteq> 0" |
127 shows "Fract a b + Fract c d = Fract (a * d + c * b) (b * d)" |
127 shows "Fract a b + Fract c d = Fract (a * d + c * b) (b * d)" |
128 using assms by transfer simp |
128 using assms by transfer simp |
137 by (cases "b = 0") (simp_all add: eq_rat) |
137 by (cases "b = 0") (simp_all add: eq_rat) |
138 |
138 |
139 definition diff_rat_def: "q - r = q + - r" for q r :: rat |
139 definition diff_rat_def: "q - r = q + - r" for q r :: rat |
140 |
140 |
141 lemma diff_rat [simp]: |
141 lemma diff_rat [simp]: |
142 assumes "b \<noteq> 0" and "d \<noteq> 0" |
142 "b \<noteq> 0 \<Longrightarrow> d \<noteq> 0 \<Longrightarrow> Fract a b - Fract c d = Fract (a * d - c * b) (b * d)" |
143 shows "Fract a b - Fract c d = Fract (a * d - c * b) (b * d)" |
143 by (simp add: diff_rat_def) |
144 using assms by (simp add: diff_rat_def) |
|
145 |
144 |
146 lift_definition times_rat :: "rat \<Rightarrow> rat \<Rightarrow> rat" |
145 lift_definition times_rat :: "rat \<Rightarrow> rat \<Rightarrow> rat" |
147 is "\<lambda>x y. (fst x * fst y, snd x * snd y)" |
146 is "\<lambda>x y. (fst x * fst y, snd x * snd y)" |
148 by (simp add: ac_simps) |
147 by (simp add: ac_simps) |
149 |
148 |
150 lemma mult_rat [simp]: "Fract a b * Fract c d = Fract (a * c) (b * d)" |
149 lemma mult_rat [simp]: "Fract a b * Fract c d = Fract (a * c) (b * d)" |
151 by transfer simp |
150 by transfer simp |
152 |
151 |
153 lemma mult_rat_cancel: |
152 lemma mult_rat_cancel: "c \<noteq> 0 \<Longrightarrow> Fract (c * a) (c * b) = Fract a b" |
154 assumes "c \<noteq> 0" |
153 by transfer simp |
155 shows "Fract (c * a) (c * b) = Fract a b" |
|
156 using assms by transfer simp |
|
157 |
154 |
158 lift_definition inverse_rat :: "rat \<Rightarrow> rat" |
155 lift_definition inverse_rat :: "rat \<Rightarrow> rat" |
159 is "\<lambda>x. if fst x = 0 then (0, 1) else (snd x, fst x)" |
156 is "\<lambda>x. if fst x = 0 then (0, 1) else (snd x, fst x)" |
160 by (auto simp add: mult.commute) |
157 by (auto simp add: mult.commute) |
161 |
158 |
253 subsubsection \<open>Function \<open>normalize\<close>\<close> |
250 subsubsection \<open>Function \<open>normalize\<close>\<close> |
254 |
251 |
255 lemma Fract_coprime: "Fract (a div gcd a b) (b div gcd a b) = Fract a b" |
252 lemma Fract_coprime: "Fract (a div gcd a b) (b div gcd a b) = Fract a b" |
256 proof (cases "b = 0") |
253 proof (cases "b = 0") |
257 case True |
254 case True |
258 then show ?thesis by (simp add: eq_rat) |
255 then show ?thesis |
|
256 by (simp add: eq_rat) |
259 next |
257 next |
260 case False |
258 case False |
261 moreover have "b div gcd a b * gcd a b = b" |
259 moreover have "b div gcd a b * gcd a b = b" |
262 by (rule dvd_div_mult_self) simp |
260 by (rule dvd_div_mult_self) simp |
263 ultimately have "b div gcd a b * gcd a b \<noteq> 0" |
261 ultimately have "b div gcd a b * gcd a b \<noteq> 0" |
280 shows "p * s = r * q" |
278 shows "p * s = r * q" |
281 proof - |
279 proof - |
282 have *: "p * s = q * r" |
280 have *: "p * s = q * r" |
283 if "p * gcd r s = sgn (q * s) * r * gcd p q" and "q * gcd r s = sgn (q * s) * s * gcd p q" |
281 if "p * gcd r s = sgn (q * s) * r * gcd p q" and "q * gcd r s = sgn (q * s) * s * gcd p q" |
284 proof - |
282 proof - |
285 from that |
283 from that have "(p * gcd r s) * (sgn (q * s) * s * gcd p q) = |
286 have "(p * gcd r s) * (sgn (q * s) * s * gcd p q) = (q * gcd r s) * (sgn (q * s) * r * gcd p q)" |
284 (q * gcd r s) * (sgn (q * s) * r * gcd p q)" |
287 by simp |
285 by simp |
288 with assms show ?thesis |
286 with assms show ?thesis |
289 by (auto simp add: ac_simps sgn_times sgn_0_0) |
287 by (auto simp add: ac_simps sgn_times sgn_0_0) |
290 qed |
288 qed |
291 from assms show ?thesis |
289 from assms show ?thesis |
292 by (auto simp add: normalize_def Let_def dvd_div_div_eq_mult mult.commute sgn_times |
290 by (auto simp: normalize_def Let_def dvd_div_div_eq_mult mult.commute sgn_times |
293 split: if_splits intro: *) |
291 split: if_splits intro: *) |
294 qed |
292 qed |
295 |
293 |
296 lemma normalize_eq: "normalize (a, b) = (p, q) \<Longrightarrow> Fract p q = Fract a b" |
294 lemma normalize_eq: "normalize (a, b) = (p, q) \<Longrightarrow> Fract p q = Fract a b" |
297 by (auto simp add: normalize_def Let_def Fract_coprime dvd_div_neg rat_number_collapse |
295 by (auto simp: normalize_def Let_def Fract_coprime dvd_div_neg rat_number_collapse |
298 split: if_split_asm) |
296 split: if_split_asm) |
299 |
297 |
300 lemma normalize_denom_pos: "normalize r = (p, q) \<Longrightarrow> q > 0" |
298 lemma normalize_denom_pos: "normalize r = (p, q) \<Longrightarrow> q > 0" |
301 by (auto simp add: normalize_def Let_def dvd_div_neg pos_imp_zdiv_neg_iff nonneg1_imp_zdiv_pos_iff |
299 by (auto simp: normalize_def Let_def dvd_div_neg pos_imp_zdiv_neg_iff nonneg1_imp_zdiv_pos_iff |
302 split: if_split_asm) |
300 split: if_split_asm) |
303 |
301 |
304 lemma normalize_coprime: "normalize r = (p, q) \<Longrightarrow> coprime p q" |
302 lemma normalize_coprime: "normalize r = (p, q) \<Longrightarrow> coprime p q" |
305 by (auto simp add: normalize_def Let_def dvd_div_neg div_gcd_coprime |
303 by (auto simp: normalize_def Let_def dvd_div_neg div_gcd_coprime split: if_split_asm) |
306 split: if_split_asm) |
|
307 |
304 |
308 lemma normalize_stable [simp]: "q > 0 \<Longrightarrow> coprime p q \<Longrightarrow> normalize (p, q) = (p, q)" |
305 lemma normalize_stable [simp]: "q > 0 \<Longrightarrow> coprime p q \<Longrightarrow> normalize (p, q) = (p, q)" |
309 by (simp add: normalize_def) |
306 by (simp add: normalize_def) |
310 |
307 |
311 lemma normalize_denom_zero [simp]: "normalize (p, 0) = (0, 1)" |
308 lemma normalize_denom_zero [simp]: "normalize (p, 0) = (0, 1)" |
323 (THE pair. x = Fract (fst pair) (snd pair) \<and> snd pair > 0 \<and> coprime (fst pair) (snd pair))" |
320 (THE pair. x = Fract (fst pair) (snd pair) \<and> snd pair > 0 \<and> coprime (fst pair) (snd pair))" |
324 |
321 |
325 lemma quotient_of_unique: "\<exists>!p. r = Fract (fst p) (snd p) \<and> snd p > 0 \<and> coprime (fst p) (snd p)" |
322 lemma quotient_of_unique: "\<exists>!p. r = Fract (fst p) (snd p) \<and> snd p > 0 \<and> coprime (fst p) (snd p)" |
326 proof (cases r) |
323 proof (cases r) |
327 case (Fract a b) |
324 case (Fract a b) |
328 then have "r = Fract (fst (a, b)) (snd (a, b)) \<and> snd (a, b) > 0 \<and> coprime (fst (a, b)) (snd (a, b))" |
325 then have "r = Fract (fst (a, b)) (snd (a, b)) \<and> |
|
326 snd (a, b) > 0 \<and> coprime (fst (a, b)) (snd (a, b))" |
329 by auto |
327 by auto |
330 then show ?thesis |
328 then show ?thesis |
331 proof (rule ex1I) |
329 proof (rule ex1I) |
332 fix p |
330 fix p |
333 obtain c d :: int where p: "p = (c, d)" |
331 obtain c d :: int where p: "p = (c, d)" |
482 show "\<bar>a\<bar> = (if a < 0 then - a else a)" |
481 show "\<bar>a\<bar> = (if a < 0 then - a else a)" |
483 by (rule abs_rat_def) |
482 by (rule abs_rat_def) |
484 show "a < b \<longleftrightarrow> a \<le> b \<and> \<not> b \<le> a" |
483 show "a < b \<longleftrightarrow> a \<le> b \<and> \<not> b \<le> a" |
485 unfolding less_eq_rat_def less_rat_def |
484 unfolding less_eq_rat_def less_rat_def |
486 apply auto |
485 apply auto |
487 apply (drule (1) positive_add) |
486 apply (drule (1) positive_add) |
488 apply (simp_all add: positive_zero) |
487 apply (simp_all add: positive_zero) |
489 done |
488 done |
490 show "a \<le> a" |
489 show "a \<le> a" |
491 unfolding less_eq_rat_def by simp |
490 unfolding less_eq_rat_def by simp |
492 show "a \<le> b \<Longrightarrow> b \<le> c \<Longrightarrow> a \<le> c" |
491 show "a \<le> b \<Longrightarrow> b \<le> c \<Longrightarrow> a \<le> c" |
493 unfolding less_eq_rat_def less_rat_def |
492 unfolding less_eq_rat_def less_rat_def |
531 |
530 |
532 lemma positive_rat: "positive (Fract a b) \<longleftrightarrow> 0 < a * b" |
531 lemma positive_rat: "positive (Fract a b) \<longleftrightarrow> 0 < a * b" |
533 by transfer simp |
532 by transfer simp |
534 |
533 |
535 lemma less_rat [simp]: |
534 lemma less_rat [simp]: |
536 assumes "b \<noteq> 0" and "d \<noteq> 0" |
535 "b \<noteq> 0 \<Longrightarrow> d \<noteq> 0 \<Longrightarrow> Fract a b < Fract c d \<longleftrightarrow> (a * d) * (b * d) < (c * b) * (b * d)" |
537 shows "Fract a b < Fract c d \<longleftrightarrow> (a * d) * (b * d) < (c * b) * (b * d)" |
536 by (simp add: less_rat_def positive_rat algebra_simps) |
538 using assms unfolding less_rat_def |
|
539 by (simp add: positive_rat algebra_simps) |
|
540 |
537 |
541 lemma le_rat [simp]: |
538 lemma le_rat [simp]: |
542 assumes "b \<noteq> 0" and "d \<noteq> 0" |
539 "b \<noteq> 0 \<Longrightarrow> d \<noteq> 0 \<Longrightarrow> Fract a b \<le> Fract c d \<longleftrightarrow> (a * d) * (b * d) \<le> (c * b) * (b * d)" |
543 shows "Fract a b \<le> Fract c d \<longleftrightarrow> (a * d) * (b * d) \<le> (c * b) * (b * d)" |
540 by (simp add: le_less eq_rat) |
544 using assms unfolding le_less by (simp add: eq_rat) |
|
545 |
541 |
546 lemma abs_rat [simp, code]: "\<bar>Fract a b\<bar> = Fract \<bar>a\<bar> \<bar>b\<bar>" |
542 lemma abs_rat [simp, code]: "\<bar>Fract a b\<bar> = Fract \<bar>a\<bar> \<bar>b\<bar>" |
547 by (auto simp add: abs_rat_def zabs_def Zero_rat_def not_less le_less eq_rat zero_less_mult_iff) |
543 by (auto simp add: abs_rat_def zabs_def Zero_rat_def not_less le_less eq_rat zero_less_mult_iff) |
548 |
544 |
549 lemma sgn_rat [simp, code]: "sgn (Fract a b) = of_int (sgn a * sgn b)" |
545 lemma sgn_rat [simp, code]: "sgn (Fract a b) = of_int (sgn a * sgn b)" |
777 proof |
772 proof |
778 show "of_rat a = id a" for a |
773 show "of_rat a = id a" for a |
779 by (induct a) (simp add: of_rat_rat Fract_of_int_eq [symmetric]) |
774 by (induct a) (simp add: of_rat_rat Fract_of_int_eq [symmetric]) |
780 qed |
775 qed |
781 |
776 |
782 text \<open>Collapse nested embeddings\<close> |
777 text \<open>Collapse nested embeddings.\<close> |
783 lemma of_rat_of_nat_eq [simp]: "of_rat (of_nat n) = of_nat n" |
778 lemma of_rat_of_nat_eq [simp]: "of_rat (of_nat n) = of_nat n" |
784 by (induct n) (simp_all add: of_rat_add) |
779 by (induct n) (simp_all add: of_rat_add) |
785 |
780 |
786 lemma of_rat_of_int_eq [simp]: "of_rat (of_int z) = of_int z" |
781 lemma of_rat_of_int_eq [simp]: "of_rat (of_int z) = of_int z" |
787 by (cases z rule: int_diff_cases) (simp add: of_rat_diff) |
782 by (cases z rule: int_diff_cases) (simp add: of_rat_diff) |
852 apply (auto simp add: Rats_def) |
847 apply (auto simp add: Rats_def) |
853 apply (rule range_eqI) |
848 apply (rule range_eqI) |
854 apply (rule of_rat_mult [symmetric]) |
849 apply (rule of_rat_mult [symmetric]) |
855 done |
850 done |
856 |
851 |
857 lemma nonzero_Rats_inverse: "a \<in> \<rat> \<Longrightarrow> a \<noteq> 0 \<Longrightarrow> inverse a \<in> \<rat>" for a :: "'a::field_char_0" |
852 lemma nonzero_Rats_inverse: "a \<in> \<rat> \<Longrightarrow> a \<noteq> 0 \<Longrightarrow> inverse a \<in> \<rat>" |
|
853 for a :: "'a::field_char_0" |
858 apply (auto simp add: Rats_def) |
854 apply (auto simp add: Rats_def) |
859 apply (rule range_eqI) |
855 apply (rule range_eqI) |
860 apply (erule nonzero_of_rat_inverse [symmetric]) |
856 apply (erule nonzero_of_rat_inverse [symmetric]) |
861 done |
857 done |
862 |
858 |
863 lemma Rats_inverse [simp]: "a \<in> \<rat> \<Longrightarrow> inverse a \<in> \<rat>" for a :: "'a::{field_char_0,field}" |
859 lemma Rats_inverse [simp]: "a \<in> \<rat> \<Longrightarrow> inverse a \<in> \<rat>" |
|
860 for a :: "'a::{field_char_0,field}" |
864 apply (auto simp add: Rats_def) |
861 apply (auto simp add: Rats_def) |
865 apply (rule range_eqI) |
862 apply (rule range_eqI) |
866 apply (rule of_rat_inverse [symmetric]) |
863 apply (rule of_rat_inverse [symmetric]) |
867 done |
864 done |
868 |
865 |
869 lemma nonzero_Rats_divide: "a \<in> \<rat> \<Longrightarrow> b \<in> \<rat> \<Longrightarrow> b \<noteq> 0 \<Longrightarrow> a / b \<in> \<rat>" for a b :: "'a::field_char_0" |
866 lemma nonzero_Rats_divide: "a \<in> \<rat> \<Longrightarrow> b \<in> \<rat> \<Longrightarrow> b \<noteq> 0 \<Longrightarrow> a / b \<in> \<rat>" |
|
867 for a b :: "'a::field_char_0" |
870 apply (auto simp add: Rats_def) |
868 apply (auto simp add: Rats_def) |
871 apply (rule range_eqI) |
869 apply (rule range_eqI) |
872 apply (erule nonzero_of_rat_divide [symmetric]) |
870 apply (erule nonzero_of_rat_divide [symmetric]) |
873 done |
871 done |
874 |
872 |
875 lemma Rats_divide [simp]: "a \<in> \<rat> \<Longrightarrow> b \<in> \<rat> \<Longrightarrow> a / b \<in> \<rat>" for a b :: "'a::{field_char_0, field}" |
873 lemma Rats_divide [simp]: "a \<in> \<rat> \<Longrightarrow> b \<in> \<rat> \<Longrightarrow> a / b \<in> \<rat>" |
|
874 for a b :: "'a::{field_char_0, field}" |
876 apply (auto simp add: Rats_def) |
875 apply (auto simp add: Rats_def) |
877 apply (rule range_eqI) |
876 apply (rule range_eqI) |
878 apply (rule of_rat_divide [symmetric]) |
877 apply (rule of_rat_divide [symmetric]) |
879 done |
878 done |
880 |
879 |
881 lemma Rats_power [simp]: "a \<in> \<rat> \<Longrightarrow> a ^ n \<in> \<rat>" for a :: "'a::field_char_0" |
880 lemma Rats_power [simp]: "a \<in> \<rat> \<Longrightarrow> a ^ n \<in> \<rat>" |
|
881 for a :: "'a::field_char_0" |
882 apply (auto simp add: Rats_def) |
882 apply (auto simp add: Rats_def) |
883 apply (rule range_eqI) |
883 apply (rule range_eqI) |
884 apply (rule of_rat_power [symmetric]) |
884 apply (rule of_rat_power [symmetric]) |
885 done |
885 done |
886 |
886 |
887 lemma Rats_cases [cases set: Rats]: |
887 lemma Rats_cases [cases set: Rats]: |
888 assumes "q \<in> \<rat>" |
888 assumes "q \<in> \<rat>" |
889 obtains (of_rat) r where "q = of_rat r" |
889 obtains (of_rat) r where "q = of_rat r" |
890 proof - |
890 proof - |
891 from \<open>q \<in> \<rat>\<close> have "q \<in> range of_rat" unfolding Rats_def . |
891 from \<open>q \<in> \<rat>\<close> have "q \<in> range of_rat" |
|
892 by (simp only: Rats_def) |
892 then obtain r where "q = of_rat r" .. |
893 then obtain r where "q = of_rat r" .. |
893 then show thesis .. |
894 then show thesis .. |
894 qed |
895 qed |
895 |
896 |
896 lemma Rats_induct [case_names of_rat, induct set: Rats]: "q \<in> \<rat> \<Longrightarrow> (\<And>r. P (of_rat r)) \<Longrightarrow> P q" |
897 lemma Rats_induct [case_names of_rat, induct set: Rats]: "q \<in> \<rat> \<Longrightarrow> (\<And>r. P (of_rat r)) \<Longrightarrow> P q" |
1026 |
1027 |
1027 |
1028 |
1028 text \<open>Quickcheck\<close> |
1029 text \<open>Quickcheck\<close> |
1029 |
1030 |
1030 definition (in term_syntax) |
1031 definition (in term_syntax) |
1031 valterm_fract :: "int \<times> (unit \<Rightarrow> Code_Evaluation.term) \<Rightarrow> int \<times> (unit \<Rightarrow> Code_Evaluation.term) \<Rightarrow> |
1032 valterm_fract :: "int \<times> (unit \<Rightarrow> Code_Evaluation.term) \<Rightarrow> |
|
1033 int \<times> (unit \<Rightarrow> Code_Evaluation.term) \<Rightarrow> |
1032 rat \<times> (unit \<Rightarrow> Code_Evaluation.term)" |
1034 rat \<times> (unit \<Rightarrow> Code_Evaluation.term)" |
1033 where [code_unfold]: "valterm_fract k l = Code_Evaluation.valtermify Fract {\<cdot>} k {\<cdot>} l" |
1035 where [code_unfold]: "valterm_fract k l = Code_Evaluation.valtermify Fract {\<cdot>} k {\<cdot>} l" |
1034 |
1036 |
1035 notation fcomp (infixl "\<circ>>" 60) |
1037 notation fcomp (infixl "\<circ>>" 60) |
1036 notation scomp (infixl "\<circ>\<rightarrow>" 60) |
1038 notation scomp (infixl "\<circ>\<rightarrow>" 60) |