changeset 60686 | ea5bc46c11e6 |
parent 60597 | 2da9b632069b |
child 60687 | 33dbbcb6a8a3 |
60685:cb21b7022b00 | 60686:ea5bc46c11e6 |
---|---|
29 |
29 |
30 theory GCD |
30 theory GCD |
31 imports Main |
31 imports Main |
32 begin |
32 begin |
33 |
33 |
34 context semidom_divide |
|
35 begin |
|
36 |
|
37 lemma divide_1 [simp]: |
|
38 "a div 1 = a" |
|
39 using nonzero_mult_divide_cancel_left [of 1 a] by simp |
|
40 |
|
41 lemma dvd_mult_cancel_left [simp]: |
|
42 assumes "a \<noteq> 0" |
|
43 shows "a * b dvd a * c \<longleftrightarrow> b dvd c" (is "?P \<longleftrightarrow> ?Q") |
|
44 proof |
|
45 assume ?P then obtain d where "a * c = a * b * d" .. |
|
46 with assms have "c = b * d" by (simp add: ac_simps) |
|
47 then show ?Q .. |
|
48 next |
|
49 assume ?Q then obtain d where "c = b * d" .. |
|
50 then have "a * c = a * b * d" by (simp add: ac_simps) |
|
51 then show ?P .. |
|
52 qed |
|
53 |
|
54 lemma dvd_mult_cancel_right [simp]: |
|
55 assumes "a \<noteq> 0" |
|
56 shows "b * a dvd c * a \<longleftrightarrow> b dvd c" (is "?P \<longleftrightarrow> ?Q") |
|
57 using dvd_mult_cancel_left [of a b c] assms by (simp add: ac_simps) |
|
58 |
|
59 lemma div_dvd_iff_mult: |
|
60 assumes "b \<noteq> 0" and "b dvd a" |
|
61 shows "a div b dvd c \<longleftrightarrow> a dvd c * b" |
|
62 proof - |
|
63 from \<open>b dvd a\<close> obtain d where "a = b * d" .. |
|
64 with \<open>b \<noteq> 0\<close> show ?thesis by (simp add: ac_simps) |
|
65 qed |
|
66 |
|
67 lemma dvd_div_iff_mult: |
|
68 assumes "c \<noteq> 0" and "c dvd b" |
|
69 shows "a dvd b div c \<longleftrightarrow> a * c dvd b" |
|
70 proof - |
|
71 from \<open>c dvd b\<close> obtain d where "b = c * d" .. |
|
72 with \<open>c \<noteq> 0\<close> show ?thesis by (simp add: mult.commute [of a]) |
|
73 qed |
|
74 |
|
75 end |
|
76 |
|
77 context algebraic_semidom |
|
78 begin |
|
79 |
|
80 lemma associated_1 [simp]: |
|
81 "associated 1 a \<longleftrightarrow> is_unit a" |
|
82 "associated a 1 \<longleftrightarrow> is_unit a" |
|
83 by (auto simp add: associated_def) |
|
84 |
|
85 end |
|
86 |
|
34 declare One_nat_def [simp del] |
87 declare One_nat_def [simp del] |
35 |
88 |
36 subsection {* GCD and LCM definitions *} |
89 subsection {* GCD and LCM definitions *} |
37 |
90 |
38 class gcd = zero + one + dvd + |
91 class gcd = zero + one + dvd + |
39 fixes gcd :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" |
92 fixes gcd :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" |
40 and lcm :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" |
93 and lcm :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" |
41 begin |
94 begin |
42 |
95 |
43 abbreviation |
96 abbreviation coprime :: "'a \<Rightarrow> 'a \<Rightarrow> bool" |
44 coprime :: "'a \<Rightarrow> 'a \<Rightarrow> bool" |
97 where "coprime x y \<equiv> gcd x y = 1" |
45 where |
|
46 "coprime x y == (gcd x y = 1)" |
|
47 |
98 |
48 end |
99 end |
49 |
100 |
50 class semiring_gcd = comm_semiring_1 + gcd + |
101 class Gcd = gcd + |
102 fixes Gcd :: "'a set \<Rightarrow> 'a" |
|
103 and Lcm :: "'a set \<Rightarrow> 'a" |
|
104 |
|
105 class semiring_gcd = normalization_semidom + gcd + |
|
51 assumes gcd_dvd1 [iff]: "gcd a b dvd a" |
106 assumes gcd_dvd1 [iff]: "gcd a b dvd a" |
52 and gcd_dvd2 [iff]: "gcd a b dvd b" |
107 and gcd_dvd2 [iff]: "gcd a b dvd b" |
53 and gcd_greatest: "c dvd a \<Longrightarrow> c dvd b \<Longrightarrow> c dvd gcd a b" |
108 and gcd_greatest: "c dvd a \<Longrightarrow> c dvd b \<Longrightarrow> c dvd gcd a b" |
109 and normalize_gcd [simp]: "normalize (gcd a b) = gcd a b" |
|
110 and lcm_gcd: "lcm a b = normalize (a * b) div gcd a b" |
|
111 begin |
|
112 |
|
113 lemma gcd_greatest_iff [iff]: |
|
114 "a dvd gcd b c \<longleftrightarrow> a dvd b \<and> a dvd c" |
|
115 by (blast intro!: gcd_greatest intro: dvd_trans) |
|
116 |
|
117 lemma gcd_0_left [simp]: |
|
118 "gcd 0 a = normalize a" |
|
119 proof (rule associated_eqI) |
|
120 show "associated (gcd 0 a) (normalize a)" |
|
121 by (auto intro!: associatedI gcd_greatest) |
|
122 show "unit_factor (gcd 0 a) = 1" if "gcd 0 a \<noteq> 0" |
|
123 proof - |
|
124 from that have "unit_factor (normalize (gcd 0 a)) = 1" |
|
125 by (rule unit_factor_normalize) |
|
126 then show ?thesis by simp |
|
127 qed |
|
128 qed simp |
|
129 |
|
130 lemma gcd_0_right [simp]: |
|
131 "gcd a 0 = normalize a" |
|
132 proof (rule associated_eqI) |
|
133 show "associated (gcd a 0) (normalize a)" |
|
134 by (auto intro!: associatedI gcd_greatest) |
|
135 show "unit_factor (gcd a 0) = 1" if "gcd a 0 \<noteq> 0" |
|
136 proof - |
|
137 from that have "unit_factor (normalize (gcd a 0)) = 1" |
|
138 by (rule unit_factor_normalize) |
|
139 then show ?thesis by simp |
|
140 qed |
|
141 qed simp |
|
142 |
|
143 lemma gcd_eq_0_iff [simp]: |
|
144 "gcd a b = 0 \<longleftrightarrow> a = 0 \<and> b = 0" (is "?P \<longleftrightarrow> ?Q") |
|
145 proof |
|
146 assume ?P then have "0 dvd gcd a b" by simp |
|
147 then have "0 dvd a" and "0 dvd b" by (blast intro: dvd_trans)+ |
|
148 then show ?Q by simp |
|
149 next |
|
150 assume ?Q then show ?P by simp |
|
151 qed |
|
152 |
|
153 lemma unit_factor_gcd: |
|
154 "unit_factor (gcd a b) = (if a = 0 \<and> b = 0 then 0 else 1)" |
|
155 proof (cases "gcd a b = 0") |
|
156 case True then show ?thesis by simp |
|
157 next |
|
158 case False |
|
159 have "unit_factor (gcd a b) * normalize (gcd a b) = gcd a b" |
|
160 by (rule unit_factor_mult_normalize) |
|
161 then have "unit_factor (gcd a b) * gcd a b = gcd a b" |
|
162 by simp |
|
163 then have "unit_factor (gcd a b) * gcd a b div gcd a b = gcd a b div gcd a b" |
|
164 by simp |
|
165 with False show ?thesis by simp |
|
166 qed |
|
167 |
|
168 sublocale gcd!: abel_semigroup gcd |
|
169 proof |
|
170 fix a b c |
|
171 show "gcd a b = gcd b a" |
|
172 by (rule associated_eqI) (auto intro: associatedI gcd_greatest simp add: unit_factor_gcd) |
|
173 from gcd_dvd1 have "gcd (gcd a b) c dvd a" |
|
174 by (rule dvd_trans) simp |
|
175 moreover from gcd_dvd1 have "gcd (gcd a b) c dvd b" |
|
176 by (rule dvd_trans) simp |
|
177 ultimately have P1: "gcd (gcd a b) c dvd gcd a (gcd b c)" |
|
178 by (auto intro!: gcd_greatest) |
|
179 from gcd_dvd2 have "gcd a (gcd b c) dvd b" |
|
180 by (rule dvd_trans) simp |
|
181 moreover from gcd_dvd2 have "gcd a (gcd b c) dvd c" |
|
182 by (rule dvd_trans) simp |
|
183 ultimately have P2: "gcd a (gcd b c) dvd gcd (gcd a b) c" |
|
184 by (auto intro!: gcd_greatest) |
|
185 from P1 P2 have "associated (gcd (gcd a b) c) (gcd a (gcd b c))" |
|
186 by (rule associatedI) |
|
187 then show "gcd (gcd a b) c = gcd a (gcd b c)" |
|
188 by (rule associated_eqI) (simp_all add: unit_factor_gcd) |
|
189 qed |
|
190 |
|
191 lemma gcd_self [simp]: |
|
192 "gcd a a = normalize a" |
|
193 proof - |
|
194 have "a dvd gcd a a" |
|
195 by (rule gcd_greatest) simp_all |
|
196 then have "associated (gcd a a) (normalize a)" |
|
197 by (auto intro: associatedI) |
|
198 then show ?thesis |
|
199 by (auto intro: associated_eqI simp add: unit_factor_gcd) |
|
200 qed |
|
201 |
|
202 lemma coprime_1_left [simp]: |
|
203 "coprime 1 a" |
|
204 by (rule associated_eqI) (simp_all add: unit_factor_gcd) |
|
205 |
|
206 lemma coprime_1_right [simp]: |
|
207 "coprime a 1" |
|
208 using coprime_1_left [of a] by (simp add: ac_simps) |
|
209 |
|
210 lemma gcd_mult_left: |
|
211 "gcd (c * a) (c * b) = normalize c * gcd a b" |
|
212 proof (cases "c = 0") |
|
213 case True then show ?thesis by simp |
|
214 next |
|
215 case False |
|
216 then have "c * gcd a b dvd gcd (c * a) (c * b)" |
|
217 by (auto intro: gcd_greatest) |
|
218 moreover from calculation False have "gcd (c * a) (c * b) dvd c * gcd a b" |
|
219 by (metis div_dvd_iff_mult dvd_mult_left gcd_dvd1 gcd_dvd2 gcd_greatest mult_commute) |
|
220 ultimately have "normalize (gcd (c * a) (c * b)) = normalize (c * gcd a b)" |
|
221 by - (rule associated_eqI, auto intro: associated_eqI associatedI simp add: unit_factor_gcd) |
|
222 then show ?thesis by (simp add: normalize_mult) |
|
223 qed |
|
224 |
|
225 lemma gcd_mult_right: |
|
226 "gcd (a * c) (b * c) = gcd b a * normalize c" |
|
227 using gcd_mult_left [of c a b] by (simp add: ac_simps) |
|
228 |
|
229 lemma mult_gcd_left: |
|
230 "c * gcd a b = unit_factor c * gcd (c * a) (c * b)" |
|
231 by (simp add: gcd_mult_left mult.assoc [symmetric]) |
|
232 |
|
233 lemma mult_gcd_right: |
|
234 "gcd a b * c = gcd (a * c) (b * c) * unit_factor c" |
|
235 using mult_gcd_left [of c a b] by (simp add: ac_simps) |
|
236 |
|
237 lemma lcm_dvd1 [iff]: |
|
238 "a dvd lcm a b" |
|
239 proof - |
|
240 have "normalize (a * b) div gcd a b = normalize a * (normalize b div gcd a b)" |
|
241 by (simp add: lcm_gcd normalize_mult div_mult_swap) |
|
242 then show ?thesis |
|
243 by (simp add: lcm_gcd) |
|
244 qed |
|
245 |
|
246 lemma lcm_dvd2 [iff]: |
|
247 "b dvd lcm a b" |
|
248 proof - |
|
249 have "normalize (a * b) div gcd a b = normalize b * (normalize a div gcd a b)" |
|
250 by (simp add: lcm_gcd normalize_mult div_mult_swap ac_simps) |
|
251 then show ?thesis |
|
252 by (simp add: lcm_gcd) |
|
253 qed |
|
254 |
|
255 lemma lcm_least: |
|
256 assumes "a dvd c" and "b dvd c" |
|
257 shows "lcm a b dvd c" |
|
258 proof (cases "c = 0") |
|
259 case True then show ?thesis by simp |
|
260 next |
|
261 case False then have U: "is_unit (unit_factor c)" by simp |
|
262 show ?thesis |
|
263 proof (cases "gcd a b = 0") |
|
264 case True with assms show ?thesis by simp |
|
265 next |
|
266 case False then have "a \<noteq> 0 \<or> b \<noteq> 0" by simp |
|
267 with \<open>c \<noteq> 0\<close> assms have "a * b dvd a * c" "a * b dvd c * b" |
|
268 by (simp_all add: mult_dvd_mono) |
|
269 then have "normalize (a * b) dvd gcd (a * c) (b * c)" |
|
270 by (auto intro: gcd_greatest simp add: ac_simps) |
|
271 then have "normalize (a * b) dvd gcd (a * c) (b * c) * unit_factor c" |
|
272 using U by (simp add: dvd_mult_unit_iff) |
|
273 then have "normalize (a * b) dvd gcd a b * c" |
|
274 by (simp add: mult_gcd_right [of a b c]) |
|
275 then have "normalize (a * b) div gcd a b dvd c" |
|
276 using False by (simp add: div_dvd_iff_mult ac_simps) |
|
277 then show ?thesis by (simp add: lcm_gcd) |
|
278 qed |
|
279 qed |
|
280 |
|
281 lemma lcm_least_iff [iff]: |
|
282 "lcm a b dvd c \<longleftrightarrow> a dvd c \<and> b dvd c" |
|
283 by (blast intro!: lcm_least intro: dvd_trans) |
|
284 |
|
285 lemma normalize_lcm [simp]: |
|
286 "normalize (lcm a b) = lcm a b" |
|
287 by (simp add: lcm_gcd dvd_normalize_div) |
|
288 |
|
289 lemma lcm_0_left [simp]: |
|
290 "lcm 0 a = 0" |
|
291 by (simp add: lcm_gcd) |
|
292 |
|
293 lemma lcm_0_right [simp]: |
|
294 "lcm a 0 = 0" |
|
295 by (simp add: lcm_gcd) |
|
296 |
|
297 lemma lcm_eq_0_iff: |
|
298 "lcm a b = 0 \<longleftrightarrow> a = 0 \<or> b = 0" (is "?P \<longleftrightarrow> ?Q") |
|
299 proof |
|
300 assume ?P then have "0 dvd lcm a b" by simp |
|
301 then have "0 dvd normalize (a * b) div gcd a b" |
|
302 by (simp add: lcm_gcd) |
|
303 then have "0 * gcd a b dvd normalize (a * b)" |
|
304 using dvd_div_iff_mult [of "gcd a b" _ 0] by (cases "gcd a b = 0") simp_all |
|
305 then have "normalize (a * b) = 0" |
|
306 by simp |
|
307 then show ?Q by simp |
|
308 next |
|
309 assume ?Q then show ?P by auto |
|
310 qed |
|
311 |
|
312 lemma unit_factor_lcm : |
|
313 "unit_factor (lcm a b) = (if a = 0 \<or> b = 0 then 0 else 1)" |
|
314 by (simp add: unit_factor_gcd dvd_unit_factor_div lcm_gcd) |
|
315 |
|
316 sublocale lcm!: abel_semigroup lcm |
|
317 proof |
|
318 fix a b c |
|
319 show "lcm a b = lcm b a" |
|
320 by (simp add: lcm_gcd ac_simps normalize_mult dvd_normalize_div) |
|
321 have "associated (lcm (lcm a b) c) (lcm a (lcm b c))" |
|
322 by (auto intro!: associatedI lcm_least |
|
323 dvd_trans [of b "lcm b c" "lcm a (lcm b c)"] |
|
324 dvd_trans [of c "lcm b c" "lcm a (lcm b c)"] |
|
325 dvd_trans [of a "lcm a b" "lcm (lcm a b) c"] |
|
326 dvd_trans [of b "lcm a b" "lcm (lcm a b) c"]) |
|
327 then show "lcm (lcm a b) c = lcm a (lcm b c)" |
|
328 by (rule associated_eqI) (simp_all add: unit_factor_lcm lcm_eq_0_iff) |
|
329 qed |
|
330 |
|
331 lemma lcm_self [simp]: |
|
332 "lcm a a = normalize a" |
|
333 proof - |
|
334 have "lcm a a dvd a" |
|
335 by (rule lcm_least) simp_all |
|
336 then have "associated (lcm a a) (normalize a)" |
|
337 by (auto intro: associatedI) |
|
338 then show ?thesis |
|
339 by (rule associated_eqI) (auto simp add: unit_factor_lcm) |
|
340 qed |
|
341 |
|
342 lemma gcd_mult_lcm [simp]: |
|
343 "gcd a b * lcm a b = normalize a * normalize b" |
|
344 by (simp add: lcm_gcd normalize_mult) |
|
345 |
|
346 lemma lcm_mult_gcd [simp]: |
|
347 "lcm a b * gcd a b = normalize a * normalize b" |
|
348 using gcd_mult_lcm [of a b] by (simp add: ac_simps) |
|
349 |
|
350 lemma gcd_lcm: |
|
351 assumes "a \<noteq> 0" and "b \<noteq> 0" |
|
352 shows "gcd a b = normalize (a * b) div lcm a b" |
|
353 proof - |
|
354 from assms have "lcm a b \<noteq> 0" |
|
355 by (simp add: lcm_eq_0_iff) |
|
356 have "gcd a b * lcm a b = normalize a * normalize b" by simp |
|
357 then have "gcd a b * lcm a b div lcm a b = normalize (a * b) div lcm a b" |
|
358 by (simp_all add: normalize_mult) |
|
359 with \<open>lcm a b \<noteq> 0\<close> show ?thesis |
|
360 using nonzero_mult_divide_cancel_right [of "lcm a b" "gcd a b"] by simp |
|
361 qed |
|
362 |
|
363 lemma lcm_1_left [simp]: |
|
364 "lcm 1 a = normalize a" |
|
365 by (simp add: lcm_gcd) |
|
366 |
|
367 lemma lcm_1_right [simp]: |
|
368 "lcm a 1 = normalize a" |
|
369 by (simp add: lcm_gcd) |
|
370 |
|
371 lemma lcm_mult_left: |
|
372 "lcm (c * a) (c * b) = normalize c * lcm a b" |
|
373 by (cases "c = 0") |
|
374 (simp_all add: gcd_mult_right lcm_gcd div_mult_swap normalize_mult ac_simps, |
|
375 simp add: dvd_div_mult2_eq mult.left_commute [of "normalize c", symmetric]) |
|
376 |
|
377 lemma lcm_mult_right: |
|
378 "lcm (a * c) (b * c) = lcm b a * normalize c" |
|
379 using lcm_mult_left [of c a b] by (simp add: ac_simps) |
|
380 |
|
381 lemma mult_lcm_left: |
|
382 "c * lcm a b = unit_factor c * lcm (c * a) (c * b)" |
|
383 by (simp add: lcm_mult_left mult.assoc [symmetric]) |
|
384 |
|
385 lemma mult_lcm_right: |
|
386 "lcm a b * c = lcm (a * c) (b * c) * unit_factor c" |
|
387 using mult_lcm_left [of c a b] by (simp add: ac_simps) |
|
388 |
|
389 end |
|
390 |
|
391 class semiring_Gcd = semiring_gcd + Gcd + |
|
392 assumes Gcd_dvd: "a \<in> A \<Longrightarrow> Gcd A dvd a" |
|
393 and Gcd_greatest: "(\<And>b. b \<in> A \<Longrightarrow> a dvd b) \<Longrightarrow> a dvd Gcd A" |
|
394 and normalize_Gcd [simp]: "normalize (Gcd A) = Gcd A" |
|
395 begin |
|
396 |
|
397 lemma Gcd_empty [simp]: |
|
398 "Gcd {} = 0" |
|
399 by (rule dvd_0_left, rule Gcd_greatest) simp |
|
400 |
|
401 lemma Gcd_0_iff [simp]: |
|
402 "Gcd A = 0 \<longleftrightarrow> (\<forall>a\<in>A. a = 0)" (is "?P \<longleftrightarrow> ?Q") |
|
403 proof |
|
404 assume ?P |
|
405 show ?Q |
|
406 proof |
|
407 fix a |
|
408 assume "a \<in> A" |
|
409 then have "Gcd A dvd a" by (rule Gcd_dvd) |
|
410 with \<open>?P\<close> show "a = 0" by simp |
|
411 qed |
|
412 next |
|
413 assume ?Q |
|
414 have "0 dvd Gcd A" |
|
415 proof (rule Gcd_greatest) |
|
416 fix a |
|
417 assume "a \<in> A" |
|
418 with \<open>?Q\<close> have "a = 0" by simp |
|
419 then show "0 dvd a" by simp |
|
420 qed |
|
421 then show ?P by simp |
|
422 qed |
|
423 |
|
424 lemma unit_factor_Gcd: |
|
425 "unit_factor (Gcd A) = (if \<forall>a\<in>A. a = 0 then 0 else 1)" |
|
426 proof (cases "Gcd A = 0") |
|
427 case True then show ?thesis by simp |
|
428 next |
|
429 case False |
|
430 from unit_factor_mult_normalize |
|
431 have "unit_factor (Gcd A) * normalize (Gcd A) = Gcd A" . |
|
432 then have "unit_factor (Gcd A) * Gcd A = Gcd A" by simp |
|
433 then have "unit_factor (Gcd A) * Gcd A div Gcd A = Gcd A div Gcd A" by simp |
|
434 with False have "unit_factor (Gcd A) = 1" by simp |
|
435 with False show ?thesis by simp |
|
436 qed |
|
437 |
|
438 lemma Gcd_UNIV [simp]: |
|
439 "Gcd UNIV = 1" |
|
440 by (rule associated_eqI) (auto intro: Gcd_dvd simp add: unit_factor_Gcd) |
|
441 |
|
442 lemma Gcd_eq_1_I: |
|
443 assumes "is_unit a" and "a \<in> A" |
|
444 shows "Gcd A = 1" |
|
445 proof - |
|
446 from assms have "is_unit (Gcd A)" |
|
447 by (blast intro: Gcd_dvd dvd_unit_imp_unit) |
|
448 then have "normalize (Gcd A) = 1" |
|
449 by (rule is_unit_normalize) |
|
450 then show ?thesis |
|
451 by simp |
|
452 qed |
|
453 |
|
454 lemma Gcd_insert [simp]: |
|
455 "Gcd (insert a A) = gcd a (Gcd A)" |
|
456 proof - |
|
457 have "Gcd (insert a A) dvd gcd a (Gcd A)" |
|
458 by (auto intro: Gcd_dvd Gcd_greatest) |
|
459 moreover have "gcd a (Gcd A) dvd Gcd (insert a A)" |
|
460 proof (rule Gcd_greatest) |
|
461 fix b |
|
462 assume "b \<in> insert a A" |
|
463 then show "gcd a (Gcd A) dvd b" |
|
464 proof |
|
465 assume "b = a" then show ?thesis by simp |
|
466 next |
|
467 assume "b \<in> A" |
|
468 then have "Gcd A dvd b" by (rule Gcd_dvd) |
|
469 moreover have "gcd a (Gcd A) dvd Gcd A" by simp |
|
470 ultimately show ?thesis by (blast intro: dvd_trans) |
|
471 qed |
|
472 qed |
|
473 ultimately have "associated (Gcd (insert a A)) (gcd a (Gcd A))" |
|
474 by (rule associatedI) |
|
475 then show ?thesis |
|
476 by (rule associated_eqI) (simp_all add: unit_factor_gcd unit_factor_Gcd) |
|
477 qed |
|
478 |
|
479 lemma dvd_Gcd: -- \<open>FIXME remove\<close> |
|
480 "\<forall>b\<in>A. a dvd b \<Longrightarrow> a dvd Gcd A" |
|
481 by (blast intro: Gcd_greatest) |
|
482 |
|
483 lemma Gcd_set [code_unfold]: |
|
484 "Gcd (set as) = foldr gcd as 0" |
|
485 by (induct as) simp_all |
|
486 |
|
487 end |
|
488 |
|
489 class semiring_Lcm = semiring_Gcd + |
|
490 assumes Lcm_Gcd: "Lcm A = Gcd {b. \<forall>a\<in>A. a dvd b}" |
|
491 begin |
|
492 |
|
493 lemma dvd_Lcm: |
|
494 assumes "a \<in> A" |
|
495 shows "a dvd Lcm A" |
|
496 using assms by (auto intro: Gcd_greatest simp add: Lcm_Gcd) |
|
497 |
|
498 lemma Gcd_image_normalize [simp]: |
|
499 "Gcd (normalize ` A) = Gcd A" |
|
500 proof - |
|
501 have "Gcd (normalize ` A) dvd a" if "a \<in> A" for a |
|
502 proof - |
|
503 from that obtain B where "A = insert a B" by blast |
|
504 moreover have " gcd (normalize a) (Gcd (normalize ` B)) dvd normalize a" |
|
505 by (rule gcd_dvd1) |
|
506 ultimately show "Gcd (normalize ` A) dvd a" |
|
507 by simp |
|
508 qed |
|
509 then have "associated (Gcd (normalize ` A)) (Gcd A)" |
|
510 by (auto intro!: associatedI Gcd_greatest intro: Gcd_dvd) |
|
511 then show ?thesis |
|
512 by (rule associated_eqI) (simp_all add: unit_factor_Gcd) |
|
513 qed |
|
514 |
|
515 lemma Lcm_least: |
|
516 assumes "\<And>b. b \<in> A \<Longrightarrow> b dvd a" |
|
517 shows "Lcm A dvd a" |
|
518 using assms by (auto intro: Gcd_dvd simp add: Lcm_Gcd) |
|
519 |
|
520 lemma normalize_Lcm [simp]: |
|
521 "normalize (Lcm A) = Lcm A" |
|
522 by (simp add: Lcm_Gcd) |
|
523 |
|
524 lemma unit_factor_Lcm: |
|
525 "unit_factor (Lcm A) = (if Lcm A = 0 then 0 else 1)" |
|
526 proof (cases "Lcm A = 0") |
|
527 case True then show ?thesis by simp |
|
528 next |
|
529 case False |
|
530 with unit_factor_normalize have "unit_factor (normalize (Lcm A)) = 1" |
|
531 by blast |
|
532 with False show ?thesis |
|
533 by simp |
|
534 qed |
|
535 |
|
536 lemma Lcm_empty [simp]: |
|
537 "Lcm {} = 1" |
|
538 by (simp add: Lcm_Gcd) |
|
539 |
|
540 lemma Lcm_1_iff [simp]: |
|
541 "Lcm A = 1 \<longleftrightarrow> (\<forall>a\<in>A. is_unit a)" (is "?P \<longleftrightarrow> ?Q") |
|
542 proof |
|
543 assume ?P |
|
544 show ?Q |
|
545 proof |
|
546 fix a |
|
547 assume "a \<in> A" |
|
548 then have "a dvd Lcm A" |
|
549 by (rule dvd_Lcm) |
|
550 with \<open>?P\<close> show "is_unit a" |
|
551 by simp |
|
552 qed |
|
553 next |
|
554 assume ?Q |
|
555 then have "is_unit (Lcm A)" |
|
556 by (blast intro: Lcm_least) |
|
557 then have "normalize (Lcm A) = 1" |
|
558 by (rule is_unit_normalize) |
|
559 then show ?P |
|
560 by simp |
|
561 qed |
|
562 |
|
563 lemma Lcm_UNIV [simp]: |
|
564 "Lcm UNIV = 0" |
|
565 proof - |
|
566 have "0 dvd Lcm UNIV" |
|
567 by (rule dvd_Lcm) simp |
|
568 then show ?thesis |
|
569 by simp |
|
570 qed |
|
571 |
|
572 lemma Lcm_eq_0_I: |
|
573 assumes "0 \<in> A" |
|
574 shows "Lcm A = 0" |
|
575 proof - |
|
576 from assms have "0 dvd Lcm A" |
|
577 by (rule dvd_Lcm) |
|
578 then show ?thesis |
|
579 by simp |
|
580 qed |
|
581 |
|
582 lemma Gcd_Lcm: |
|
583 "Gcd A = Lcm {b. \<forall>a\<in>A. b dvd a}" |
|
584 by (rule associated_eqI) (auto intro: associatedI Gcd_dvd dvd_Lcm Gcd_greatest Lcm_least |
|
585 simp add: unit_factor_Gcd unit_factor_Lcm) |
|
586 |
|
587 lemma Lcm_insert [simp]: |
|
588 "Lcm (insert a A) = lcm a (Lcm A)" |
|
589 proof (rule sym) |
|
590 have "lcm a (Lcm A) dvd Lcm (insert a A)" |
|
591 by (auto intro: dvd_Lcm Lcm_least) |
|
592 moreover have "Lcm (insert a A) dvd lcm a (Lcm A)" |
|
593 proof (rule Lcm_least) |
|
594 fix b |
|
595 assume "b \<in> insert a A" |
|
596 then show "b dvd lcm a (Lcm A)" |
|
597 proof |
|
598 assume "b = a" then show ?thesis by simp |
|
599 next |
|
600 assume "b \<in> A" |
|
601 then have "b dvd Lcm A" by (rule dvd_Lcm) |
|
602 moreover have "Lcm A dvd lcm a (Lcm A)" by simp |
|
603 ultimately show ?thesis by (blast intro: dvd_trans) |
|
604 qed |
|
605 qed |
|
606 ultimately have "associated (lcm a (Lcm A)) (Lcm (insert a A))" |
|
607 by (rule associatedI) |
|
608 then show "lcm a (Lcm A) = Lcm (insert a A)" |
|
609 by (rule associated_eqI) (simp_all add: unit_factor_lcm unit_factor_Lcm lcm_eq_0_iff) |
|
610 qed |
|
611 |
|
612 lemma Lcm_set [code_unfold]: |
|
613 "Lcm (set as) = foldr lcm as 1" |
|
614 by (induct as) simp_all |
|
615 |
|
616 end |
|
54 |
617 |
55 class ring_gcd = comm_ring_1 + semiring_gcd |
618 class ring_gcd = comm_ring_1 + semiring_gcd |
56 |
619 |
57 instantiation nat :: gcd |
620 instantiation nat :: gcd |
58 begin |
621 begin |
263 next |
826 next |
264 fix m n k :: nat |
827 fix m n k :: nat |
265 assume "k dvd m" and "k dvd n" |
828 assume "k dvd m" and "k dvd n" |
266 then show "k dvd gcd m n" |
829 then show "k dvd gcd m n" |
267 by (induct m n rule: gcd_nat_induct) (simp_all add: gcd_non_0_nat dvd_mod gcd_0_nat) |
830 by (induct m n rule: gcd_nat_induct) (simp_all add: gcd_non_0_nat dvd_mod gcd_0_nat) |
268 qed |
831 qed (simp_all add: lcm_nat_def) |
269 |
832 |
270 instance int :: ring_gcd |
833 instance int :: ring_gcd |
271 by intro_classes (simp_all add: dvd_int_unfold_dvd_nat gcd_int_def gcd_greatest) |
834 by standard |
835 (simp_all add: dvd_int_unfold_dvd_nat gcd_int_def lcm_int_def zdiv_int nat_abs_mult_distrib [symmetric] lcm_gcd gcd_greatest) |
|
272 |
836 |
273 lemma dvd_gcd_D1_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd m" |
837 lemma dvd_gcd_D1_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd m" |
274 by (metis gcd_dvd1 dvd_trans) |
838 by (metis gcd_dvd1 dvd_trans) |
275 |
839 |
276 lemma dvd_gcd_D2_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd n" |
840 lemma dvd_gcd_D2_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd n" |
330 apply (auto intro: gcd_greatest) |
894 apply (auto intro: gcd_greatest) |
331 done |
895 done |
332 |
896 |
333 interpretation gcd_nat: abel_semigroup "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat" |
897 interpretation gcd_nat: abel_semigroup "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat" |
334 + gcd_nat: semilattice_neutr_order "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat" 0 "op dvd" "(\<lambda>m n. m dvd n \<and> \<not> n dvd m)" |
898 + gcd_nat: semilattice_neutr_order "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat" 0 "op dvd" "(\<lambda>m n. m dvd n \<and> \<not> n dvd m)" |
335 apply default |
899 apply standard |
336 apply (auto intro: dvd_antisym dvd_trans)[4] |
900 apply (auto intro: dvd_antisym dvd_trans)[2] |
337 apply (metis dvd.dual_order.refl gcd_unique_nat)+ |
901 apply (metis dvd.dual_order.refl gcd_unique_nat)+ |
338 done |
902 done |
339 |
903 |
340 interpretation gcd_int: abel_semigroup "gcd :: int \<Rightarrow> int \<Rightarrow> int" |
904 interpretation gcd_int: abel_semigroup "gcd :: int \<Rightarrow> int \<Rightarrow> int" .. |
341 proof |
905 |
342 qed (simp_all add: gcd_int_def gcd_nat.assoc gcd_nat.commute gcd_nat.left_commute) |
906 lemmas gcd_assoc_nat = gcd.assoc [where ?'a = nat] |
343 |
907 lemmas gcd_commute_nat = gcd.commute [where ?'a = nat] |
344 lemmas gcd_assoc_nat = gcd_nat.assoc |
908 lemmas gcd_left_commute_nat = gcd.left_commute [where ?'a = nat] |
345 lemmas gcd_commute_nat = gcd_nat.commute |
909 lemmas gcd_assoc_int = gcd.assoc [where ?'a = int] |
346 lemmas gcd_left_commute_nat = gcd_nat.left_commute |
910 lemmas gcd_commute_int = gcd.commute [where ?'a = int] |
347 lemmas gcd_assoc_int = gcd_int.assoc |
911 lemmas gcd_left_commute_int = gcd.left_commute [where ?'a = int] |
348 lemmas gcd_commute_int = gcd_int.commute |
|
349 lemmas gcd_left_commute_int = gcd_int.left_commute |
|
350 |
912 |
351 lemmas gcd_ac_nat = gcd_assoc_nat gcd_commute_nat gcd_left_commute_nat |
913 lemmas gcd_ac_nat = gcd_assoc_nat gcd_commute_nat gcd_left_commute_nat |
352 |
914 |
353 lemmas gcd_ac_int = gcd_assoc_int gcd_commute_int gcd_left_commute_int |
915 lemmas gcd_ac_int = gcd_assoc_int gcd_commute_int gcd_left_commute_int |
354 |
916 |
760 |
1322 |
761 lemma coprime_exp_int: "coprime (d::int) a \<Longrightarrow> coprime d (a^n)" |
1323 lemma coprime_exp_int: "coprime (d::int) a \<Longrightarrow> coprime d (a^n)" |
762 by (induct n) (simp_all add: coprime_mult_int) |
1324 by (induct n) (simp_all add: coprime_mult_int) |
763 |
1325 |
764 lemma coprime_exp2_nat [intro]: "coprime (a::nat) b \<Longrightarrow> coprime (a^n) (b^m)" |
1326 lemma coprime_exp2_nat [intro]: "coprime (a::nat) b \<Longrightarrow> coprime (a^n) (b^m)" |
765 by (simp add: coprime_exp_nat gcd_nat.commute) |
1327 by (simp add: coprime_exp_nat ac_simps) |
766 |
1328 |
767 lemma coprime_exp2_int [intro]: "coprime (a::int) b \<Longrightarrow> coprime (a^n) (b^m)" |
1329 lemma coprime_exp2_int [intro]: "coprime (a::int) b \<Longrightarrow> coprime (a^n) (b^m)" |
768 by (simp add: coprime_exp_int gcd_int.commute) |
1330 by (simp add: coprime_exp_int ac_simps) |
769 |
1331 |
770 lemma gcd_exp_nat: "gcd ((a::nat)^n) (b^n) = (gcd a b)^n" |
1332 lemma gcd_exp_nat: "gcd ((a::nat)^n) (b^n) = (gcd a b)^n" |
771 proof (cases) |
1333 proof (cases) |
772 assume "a = 0 & b = 0" |
1334 assume "a = 0 & b = 0" |
773 thus ?thesis by simp |
1335 thus ?thesis by simp |
925 then obtain k where k: "n' = m*k" unfolding dvd_def by blast |
1487 then obtain k where k: "n' = m*k" unfolding dvd_def by blast |
926 from n' k show ?thesis unfolding dvd_def by auto |
1488 from n' k show ?thesis unfolding dvd_def by auto |
927 qed |
1489 qed |
928 |
1490 |
929 lemma coprime_plus_one_nat [simp]: "coprime ((n::nat) + 1) n" |
1491 lemma coprime_plus_one_nat [simp]: "coprime ((n::nat) + 1) n" |
930 by (simp add: gcd_nat.commute) |
1492 by (simp add: gcd.commute) |
931 |
1493 |
932 lemma coprime_Suc_nat [simp]: "coprime (Suc n) n" |
1494 lemma coprime_Suc_nat [simp]: "coprime (Suc n) n" |
933 using coprime_plus_one_nat by (simp add: One_nat_def) |
1495 using coprime_plus_one_nat by (simp add: One_nat_def) |
934 |
1496 |
935 lemma coprime_plus_one_int [simp]: "coprime ((n::int) + 1) n" |
1497 lemma coprime_plus_one_int [simp]: "coprime ((n::int) + 1) n" |
936 by (simp add: gcd_int.commute) |
1498 by (simp add: gcd.commute) |
937 |
1499 |
938 lemma coprime_minus_one_nat: "(n::nat) \<noteq> 0 \<Longrightarrow> coprime (n - 1) n" |
1500 lemma coprime_minus_one_nat: "(n::nat) \<noteq> 0 \<Longrightarrow> coprime (n - 1) n" |
939 using coprime_plus_one_nat [of "n - 1"] |
1501 using coprime_plus_one_nat [of "n - 1"] |
940 gcd_commute_nat [of "n - 1" n] by auto |
1502 gcd_commute_nat [of "n - 1" n] by auto |
941 |
1503 |
956 apply (induct set: finite) |
1518 apply (induct set: finite) |
957 apply (auto simp add: gcd_mult_cancel_int) |
1519 apply (auto simp add: gcd_mult_cancel_int) |
958 done |
1520 done |
959 |
1521 |
960 lemma coprime_common_divisor_nat: |
1522 lemma coprime_common_divisor_nat: |
961 "coprime (a::nat) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> x = 1" |
1523 "coprime (a::nat) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> x = 1" |
962 by (metis gcd_greatest_iff_nat nat_dvd_1_iff_1) |
1524 by (metis gcd_greatest_iff_nat nat_dvd_1_iff_1) |
963 |
1525 |
964 lemma coprime_common_divisor_int: |
1526 lemma coprime_common_divisor_int: |
965 "coprime (a::int) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> abs x = 1" |
1527 "coprime (a::int) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> abs x = 1" |
966 using gcd_greatest by fastforce |
1528 using gcd_greatest_iff [of x a b] by auto |
967 |
1529 |
968 lemma coprime_divisors_nat: |
1530 lemma coprime_divisors_nat: |
969 "(d::int) dvd a \<Longrightarrow> e dvd b \<Longrightarrow> coprime a b \<Longrightarrow> coprime d e" |
1531 "(d::int) dvd a \<Longrightarrow> e dvd b \<Longrightarrow> coprime a b \<Longrightarrow> coprime d e" |
970 by (meson coprime_int dvd_trans gcd_dvd1 gcd_dvd2 gcd_ge_0_int) |
1532 by (meson coprime_int dvd_trans gcd_dvd1 gcd_dvd2 gcd_ge_0_int) |
971 |
1533 |
1264 using assms by (cases m) auto |
1826 using assms by (cases m) auto |
1265 |
1827 |
1266 lemma lcm_least_nat: |
1828 lemma lcm_least_nat: |
1267 assumes "(m::nat) dvd k" and "n dvd k" |
1829 assumes "(m::nat) dvd k" and "n dvd k" |
1268 shows "lcm m n dvd k" |
1830 shows "lcm m n dvd k" |
1269 proof (cases k) |
1831 using assms by (rule lcm_least) |
1270 case 0 then show ?thesis by auto |
|
1271 next |
|
1272 case (Suc _) then have pos_k: "k > 0" by auto |
|
1273 from assms dvd_pos_nat [OF this] have pos_mn: "m > 0" "n > 0" by auto |
|
1274 with gcd_zero_nat [of m n] have pos_gcd: "gcd m n > 0" by simp |
|
1275 from assms obtain p where k_m: "k = m * p" using dvd_def by blast |
|
1276 from assms obtain q where k_n: "k = n * q" using dvd_def by blast |
|
1277 from pos_k k_m have pos_p: "p > 0" by auto |
|
1278 from pos_k k_n have pos_q: "q > 0" by auto |
|
1279 have "k * k * gcd q p = k * gcd (k * q) (k * p)" |
|
1280 by (simp add: ac_simps gcd_mult_distrib_nat) |
|
1281 also have "\<dots> = k * gcd (m * p * q) (n * q * p)" |
|
1282 by (simp add: k_m [symmetric] k_n [symmetric]) |
|
1283 also have "\<dots> = k * p * q * gcd m n" |
|
1284 by (simp add: ac_simps gcd_mult_distrib_nat) |
|
1285 finally have "(m * p) * (n * q) * gcd q p = k * p * q * gcd m n" |
|
1286 by (simp only: k_m [symmetric] k_n [symmetric]) |
|
1287 then have "p * q * m * n * gcd q p = p * q * k * gcd m n" |
|
1288 by (simp add: ac_simps) |
|
1289 with pos_p pos_q have "m * n * gcd q p = k * gcd m n" |
|
1290 by simp |
|
1291 with prod_gcd_lcm_nat [of m n] |
|
1292 have "lcm m n * gcd q p * gcd m n = k * gcd m n" |
|
1293 by (simp add: ac_simps) |
|
1294 with pos_gcd have "lcm m n * gcd q p = k" by auto |
|
1295 then show ?thesis using dvd_def by auto |
|
1296 qed |
|
1297 |
1832 |
1298 lemma lcm_least_int: |
1833 lemma lcm_least_int: |
1299 "(m::int) dvd k \<Longrightarrow> n dvd k \<Longrightarrow> lcm m n dvd k" |
1834 "(m::int) dvd k \<Longrightarrow> n dvd k \<Longrightarrow> lcm m n dvd k" |
1300 apply (subst lcm_abs_int) |
1835 by (rule lcm_least) |
1301 apply (rule dvd_trans) |
|
1302 apply (rule lcm_least_nat [transferred, of _ "abs k" _]) |
|
1303 apply auto |
|
1304 done |
|
1305 |
1836 |
1306 lemma lcm_dvd1_nat: "(m::nat) dvd lcm m n" |
1837 lemma lcm_dvd1_nat: "(m::nat) dvd lcm m n" |
1307 proof (cases m) |
1838 proof (cases m) |
1308 case 0 then show ?thesis by simp |
1839 case 0 then show ?thesis by simp |
1309 next |
1840 next |
1331 apply (rule lcm_dvd1_nat [transferred]) |
1862 apply (rule lcm_dvd1_nat [transferred]) |
1332 apply auto |
1863 apply auto |
1333 done |
1864 done |
1334 |
1865 |
1335 lemma lcm_dvd2_nat: "(n::nat) dvd lcm m n" |
1866 lemma lcm_dvd2_nat: "(n::nat) dvd lcm m n" |
1336 using lcm_dvd1_nat [of n m] by (simp only: lcm_nat_def mult.commute gcd_nat.commute) |
1867 by (rule lcm_dvd2) |
1337 |
1868 |
1338 lemma lcm_dvd2_int: "(n::int) dvd lcm m n" |
1869 lemma lcm_dvd2_int: "(n::int) dvd lcm m n" |
1339 using lcm_dvd1_int [of n m] by (simp only: lcm_int_def lcm_nat_def mult.commute gcd_nat.commute) |
1870 by (rule lcm_dvd2) |
1340 |
1871 |
1341 lemma dvd_lcm_I1_nat[simp]: "(k::nat) dvd m \<Longrightarrow> k dvd lcm m n" |
1872 lemma dvd_lcm_I1_nat[simp]: "(k::nat) dvd m \<Longrightarrow> k dvd lcm m n" |
1342 by(metis lcm_dvd1_nat dvd_trans) |
1873 by(metis lcm_dvd1_nat dvd_trans) |
1343 |
1874 |
1344 lemma dvd_lcm_I2_nat[simp]: "(k::nat) dvd n \<Longrightarrow> k dvd lcm m n" |
1875 lemma dvd_lcm_I2_nat[simp]: "(k::nat) dvd n \<Longrightarrow> k dvd lcm m n" |
1358 (\<forall>e. a dvd e \<and> b dvd e \<longrightarrow> d dvd e) \<longleftrightarrow> d = lcm a b" |
1889 (\<forall>e. a dvd e \<and> b dvd e \<longrightarrow> d dvd e) \<longleftrightarrow> d = lcm a b" |
1359 using lcm_least_int zdvd_antisym_nonneg by auto |
1890 using lcm_least_int zdvd_antisym_nonneg by auto |
1360 |
1891 |
1361 interpretation lcm_nat: abel_semigroup "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat" |
1892 interpretation lcm_nat: abel_semigroup "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat" |
1362 + lcm_nat: semilattice_neutr "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat" 1 |
1893 + lcm_nat: semilattice_neutr "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat" 1 |
1363 proof |
1894 by standard simp_all |
1364 fix n m p :: nat |
1895 |
1365 show "lcm (lcm n m) p = lcm n (lcm m p)" |
1896 interpretation lcm_int: abel_semigroup "lcm :: int \<Rightarrow> int \<Rightarrow> int" .. |
1366 by (rule lcm_unique_nat [THEN iffD1]) (metis dvd.order_trans lcm_unique_nat) |
1897 |
1367 show "lcm m n = lcm n m" |
1898 lemmas lcm_assoc_nat = lcm.assoc [where ?'a = nat] |
1368 by (simp add: lcm_nat_def gcd_commute_nat field_simps) |
1899 lemmas lcm_commute_nat = lcm.commute [where ?'a = nat] |
1369 show "lcm m m = m" |
1900 lemmas lcm_left_commute_nat = lcm.left_commute [where ?'a = nat] |
1370 by (metis dvd.order_refl lcm_unique_nat) |
1901 lemmas lcm_assoc_int = lcm.assoc [where ?'a = int] |
1371 show "lcm m 1 = m" |
1902 lemmas lcm_commute_int = lcm.commute [where ?'a = int] |
1372 by (metis dvd.dual_order.refl lcm_unique_nat one_dvd) |
1903 lemmas lcm_left_commute_int = lcm.left_commute [where ?'a = int] |
1373 qed |
|
1374 |
|
1375 interpretation lcm_int: abel_semigroup "lcm :: int \<Rightarrow> int \<Rightarrow> int" |
|
1376 proof |
|
1377 fix n m p :: int |
|
1378 show "lcm (lcm n m) p = lcm n (lcm m p)" |
|
1379 by (rule lcm_unique_int [THEN iffD1]) (metis dvd_trans lcm_unique_int) |
|
1380 show "lcm m n = lcm n m" |
|
1381 by (simp add: lcm_int_def lcm_nat.commute) |
|
1382 qed |
|
1383 |
|
1384 lemmas lcm_assoc_nat = lcm_nat.assoc |
|
1385 lemmas lcm_commute_nat = lcm_nat.commute |
|
1386 lemmas lcm_left_commute_nat = lcm_nat.left_commute |
|
1387 lemmas lcm_assoc_int = lcm_int.assoc |
|
1388 lemmas lcm_commute_int = lcm_int.commute |
|
1389 lemmas lcm_left_commute_int = lcm_int.left_commute |
|
1390 |
1904 |
1391 lemmas lcm_ac_nat = lcm_assoc_nat lcm_commute_nat lcm_left_commute_nat |
1905 lemmas lcm_ac_nat = lcm_assoc_nat lcm_commute_nat lcm_left_commute_nat |
1392 lemmas lcm_ac_int = lcm_assoc_int lcm_commute_int lcm_left_commute_int |
1906 lemmas lcm_ac_int = lcm_assoc_int lcm_commute_int lcm_left_commute_int |
1393 |
1907 |
1394 lemma lcm_proj2_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> lcm x y = y" |
1908 lemma lcm_proj2_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> lcm x y = y" |
1450 |
1964 |
1451 |
1965 |
1452 subsection {* The complete divisibility lattice *} |
1966 subsection {* The complete divisibility lattice *} |
1453 |
1967 |
1454 interpretation gcd_semilattice_nat: semilattice_inf gcd "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)" |
1968 interpretation gcd_semilattice_nat: semilattice_inf gcd "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)" |
1455 proof (default, goals) |
1969 by standard simp_all |
1456 case 3 |
|
1457 thus ?case by(metis gcd_unique_nat) |
|
1458 qed auto |
|
1459 |
1970 |
1460 interpretation lcm_semilattice_nat: semilattice_sup lcm "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)" |
1971 interpretation lcm_semilattice_nat: semilattice_sup lcm "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)" |
1461 proof (default, goals) |
1972 by standard simp_all |
1462 case 3 |
|
1463 thus ?case by(metis lcm_unique_nat) |
|
1464 qed auto |
|
1465 |
1973 |
1466 interpretation gcd_lcm_lattice_nat: lattice gcd "op dvd" "(\<lambda>m n::nat. m dvd n & ~ n dvd m)" lcm .. |
1974 interpretation gcd_lcm_lattice_nat: lattice gcd "op dvd" "(\<lambda>m n::nat. m dvd n & ~ n dvd m)" lcm .. |
1467 |
1975 |
1468 text{* Lifting gcd and lcm to sets (Gcd/Lcm). |
1976 text{* Lifting gcd and lcm to sets (Gcd/Lcm). |
1469 Gcd is defined via Lcm to facilitate the proof that we have a complete lattice. |
1977 Gcd is defined via Lcm to facilitate the proof that we have a complete lattice. |
1470 *} |
1978 *} |
1471 |
1979 |
1472 class Gcd = gcd + |
|
1473 fixes Gcd :: "'a set \<Rightarrow> 'a" |
|
1474 fixes Lcm :: "'a set \<Rightarrow> 'a" |
|
1475 |
|
1476 instantiation nat :: Gcd |
1980 instantiation nat :: Gcd |
1477 begin |
1981 begin |
1478 |
1982 |
1479 definition |
1983 definition |
1480 "Lcm (M::nat set) = (if finite M then semilattice_neutr_set.F lcm 1 M else 0)" |
1984 "Lcm (M::nat set) = (if finite M then semilattice_neutr_set.F lcm 1 M else 0)" |
1496 definition |
2000 definition |
1497 "Gcd (M::nat set) = Lcm {d. \<forall>m\<in>M. d dvd m}" |
2001 "Gcd (M::nat set) = Lcm {d. \<forall>m\<in>M. d dvd m}" |
1498 |
2002 |
1499 instance .. |
2003 instance .. |
1500 |
2004 |
1501 end |
|
1502 |
|
1503 class semiring_Gcd = semiring_gcd + Gcd + |
|
1504 assumes Gcd_dvd: "a \<in> A \<Longrightarrow> Gcd A dvd a" |
|
1505 and dvd_Gcd: "\<forall>b\<in>A. a dvd b \<Longrightarrow> a dvd Gcd A" |
|
1506 and Gcd_insert [simp]: "Gcd (insert a A) = gcd a (Gcd A)" |
|
1507 begin |
|
1508 |
|
1509 lemma Gcd_empty [simp]: |
|
1510 "Gcd {} = 0" |
|
1511 by (rule dvd_0_left, rule dvd_Gcd) simp |
|
1512 |
|
1513 lemma Gcd_set [code_unfold]: |
|
1514 "Gcd (set as) = foldr gcd as 0" |
|
1515 by (induct as) simp_all |
|
1516 |
|
1517 end |
2005 end |
1518 |
2006 |
1519 lemma dvd_Lcm_nat [simp]: |
2007 lemma dvd_Lcm_nat [simp]: |
1520 fixes M :: "nat set" |
2008 fixes M :: "nat set" |
1521 assumes "m \<in> M" |
2009 assumes "m \<in> M" |
1542 complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat" |
2030 complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat" |
1543 where "Inf.INFIMUM Gcd A f = Gcd (f ` A :: nat set)" |
2031 where "Inf.INFIMUM Gcd A f = Gcd (f ` A :: nat set)" |
1544 and "Sup.SUPREMUM Lcm A f = Lcm (f ` A)" |
2032 and "Sup.SUPREMUM Lcm A f = Lcm (f ` A)" |
1545 proof - |
2033 proof - |
1546 show "class.complete_lattice Gcd Lcm gcd Rings.dvd (\<lambda>m n. m dvd n \<and> \<not> n dvd m) lcm 1 (0::nat)" |
2034 show "class.complete_lattice Gcd Lcm gcd Rings.dvd (\<lambda>m n. m dvd n \<and> \<not> n dvd m) lcm 1 (0::nat)" |
1547 proof (default, goals) |
2035 by default (auto simp add: Gcd_nat_def Lcm_nat_empty Lcm_nat_infinite) |
1548 case 1 |
|
1549 thus ?case by (simp add: Gcd_nat_def) |
|
1550 next |
|
1551 case 2 |
|
1552 thus ?case by (simp add: Gcd_nat_def) |
|
1553 next |
|
1554 case 5 |
|
1555 show ?case by (simp add: Gcd_nat_def Lcm_nat_infinite) |
|
1556 next |
|
1557 case 6 |
|
1558 show ?case by (simp add: Lcm_nat_empty) |
|
1559 next |
|
1560 case 3 |
|
1561 thus ?case by simp |
|
1562 next |
|
1563 case 4 |
|
1564 thus ?case by simp |
|
1565 qed |
|
1566 then interpret gcd_lcm_complete_lattice_nat: |
2036 then interpret gcd_lcm_complete_lattice_nat: |
1567 complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat" . |
2037 complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat" . |
1568 from gcd_lcm_complete_lattice_nat.INF_def show "Inf.INFIMUM Gcd A f = Gcd (f ` A)" . |
2038 from gcd_lcm_complete_lattice_nat.INF_def show "Inf.INFIMUM Gcd A f = Gcd (f ` A)" . |
1569 from gcd_lcm_complete_lattice_nat.SUP_def show "Sup.SUPREMUM Lcm A f = Lcm (f ` A)" . |
2039 from gcd_lcm_complete_lattice_nat.SUP_def show "Sup.SUPREMUM Lcm A f = Lcm (f ` A)" . |
1570 qed |
2040 qed |
1588 instance nat :: semiring_Gcd |
2058 instance nat :: semiring_Gcd |
1589 proof |
2059 proof |
1590 show "Gcd N dvd n" if "n \<in> N" for N and n :: nat |
2060 show "Gcd N dvd n" if "n \<in> N" for N and n :: nat |
1591 using that by (fact gcd_lcm_complete_lattice_nat.Inf_lower) |
2061 using that by (fact gcd_lcm_complete_lattice_nat.Inf_lower) |
1592 next |
2062 next |
1593 show "n dvd Gcd N" if "\<forall>m\<in>N. n dvd m" for N and n :: nat |
2063 show "n dvd Gcd N" if "\<And>m. m \<in> N \<Longrightarrow> n dvd m" for N and n :: nat |
1594 using that by (simp only: gcd_lcm_complete_lattice_nat.Inf_greatest) |
2064 using that by (simp only: gcd_lcm_complete_lattice_nat.Inf_greatest) |
1595 next |
2065 next |
1596 show "Gcd (insert n N) = gcd n (Gcd N)" for N and n :: nat |
2066 show "normalize (Gcd N) = Gcd N" for N :: "nat set" |
1597 by simp |
2067 by simp |
2068 qed |
|
2069 |
|
2070 instance nat :: semiring_Lcm |
|
2071 proof |
|
2072 have uf: "unit_factor (Lcm N) = 1" if "0 < Lcm N" for N :: "nat set" |
|
2073 proof (cases "finite N") |
|
2074 case False with that show ?thesis by (simp add: Lcm_nat_infinite) |
|
2075 next |
|
2076 case True then show ?thesis |
|
2077 using that proof (induct N) |
|
2078 case empty then show ?case by simp |
|
2079 next |
|
2080 case (insert n N) |
|
2081 have "lcm n (Lcm N) \<noteq> 0 \<longleftrightarrow> n \<noteq> 0 \<and> Lcm N \<noteq> 0" |
|
2082 using lcm_eq_0_iff [of n "Lcm N"] by simp |
|
2083 then have "lcm n (Lcm N) > 0 \<longleftrightarrow> n > 0 \<and> Lcm N > 0" |
|
2084 unfolding neq0_conv . |
|
2085 with insert show ?case |
|
2086 by (simp add: Lcm_nat_insert unit_factor_lcm) |
|
2087 qed |
|
2088 qed |
|
2089 show "Lcm N = Gcd {m. \<forall>n\<in>N. n dvd m}" for N :: "nat set" |
|
2090 by (rule associated_eqI) (auto intro!: associatedI Gcd_dvd Gcd_greatest |
|
2091 simp add: unit_factor_Gcd uf) |
|
1598 qed |
2092 qed |
1599 |
2093 |
1600 text{* Alternative characterizations of Gcd: *} |
2094 text{* Alternative characterizations of Gcd: *} |
1601 |
2095 |
1602 lemma Gcd_eq_Max: "finite(M::nat set) \<Longrightarrow> M \<noteq> {} \<Longrightarrow> 0 \<notin> M \<Longrightarrow> Gcd M = Max(\<Inter>m\<in>M. {d. d dvd m})" |
2096 lemma Gcd_eq_Max: "finite(M::nat set) \<Longrightarrow> M \<noteq> {} \<Longrightarrow> 0 \<notin> M \<Longrightarrow> Gcd M = Max(\<Inter>m\<in>M. {d. d dvd m})" |
1680 |
2174 |
1681 definition |
2175 definition |
1682 "Gcd M = int (Gcd (nat ` abs ` M))" |
2176 "Gcd M = int (Gcd (nat ` abs ` M))" |
1683 |
2177 |
1684 instance .. |
2178 instance .. |
2179 |
|
1685 end |
2180 end |
2181 |
|
2182 instance int :: semiring_Gcd |
|
2183 by standard (auto intro!: Gcd_dvd Gcd_greatest simp add: Gcd_int_def Lcm_int_def int_dvd_iff dvd_int_iff |
|
2184 dvd_int_unfold_dvd_nat [symmetric]) |
|
2185 |
|
2186 instance int :: semiring_Lcm |
|
2187 proof |
|
2188 fix K :: "int set" |
|
2189 have "{n. \<forall>k\<in>K. nat \<bar>k\<bar> dvd n} = ((\<lambda>k. nat \<bar>k\<bar>) ` {l. \<forall>k\<in>K. k dvd l})" |
|
2190 proof (rule set_eqI) |
|
2191 fix n |
|
2192 have "(\<forall>k\<in>K. nat \<bar>k\<bar> dvd n) \<longleftrightarrow> (\<exists>l. (\<forall>k\<in>K. k dvd l) \<and> n = nat \<bar>l\<bar>)" (is "?P \<longleftrightarrow> ?Q") |
|
2193 proof |
|
2194 assume ?P |
|
2195 then have "(\<forall>k\<in>K. k dvd int n) \<and> n = nat \<bar>int n\<bar>" |
|
2196 by (auto simp add: dvd_int_unfold_dvd_nat) |
|
2197 then show ?Q by blast |
|
2198 next |
|
2199 assume ?Q then show ?P |
|
2200 by (auto simp add: dvd_int_unfold_dvd_nat) |
|
2201 qed |
|
2202 then show "n \<in> {n. \<forall>k\<in>K. nat \<bar>k\<bar> dvd n} \<longleftrightarrow> n \<in> (\<lambda>k. nat \<bar>k\<bar>) ` {l. \<forall>k\<in>K. k dvd l}" |
|
2203 by auto |
|
2204 qed |
|
2205 then show "Lcm K = Gcd {l. \<forall>k\<in>K. k dvd l}" |
|
2206 by (simp add: Gcd_int_def Lcm_int_def Lcm_Gcd) |
|
2207 qed |
|
1686 |
2208 |
1687 lemma Lcm_empty_int [simp]: "Lcm {} = (1::int)" |
2209 lemma Lcm_empty_int [simp]: "Lcm {} = (1::int)" |
1688 by (simp add: Lcm_int_def) |
2210 by (simp add: Lcm_int_def) |
1689 |
2211 |
1690 lemma Lcm_insert_int [simp]: |
2212 lemma Lcm_insert_int [simp]: |
1691 shows "Lcm (insert (n::int) N) = lcm n (Lcm N)" |
2213 shows "Lcm (insert (n::int) N) = lcm n (Lcm N)" |
1692 by (simp add: Lcm_int_def lcm_int_def) |
2214 by (simp add: Lcm_int_def lcm_int_def) |
1693 |
2215 |
1694 lemma dvd_int_iff: "x dvd y \<longleftrightarrow> nat (abs x) dvd nat (abs y)" |
2216 lemma dvd_int_iff: "x dvd y \<longleftrightarrow> nat (abs x) dvd nat (abs y)" |
1695 by (simp add: zdvd_int) |
2217 by (fact dvd_int_unfold_dvd_nat) |
1696 |
2218 |
1697 lemma dvd_Lcm_int [simp]: |
2219 lemma dvd_Lcm_int [simp]: |
1698 fixes M :: "int set" assumes "m \<in> M" shows "m dvd Lcm M" |
2220 fixes M :: "int set" assumes "m \<in> M" shows "m dvd Lcm M" |
1699 using assms by (simp add: Lcm_int_def dvd_int_iff) |
2221 using assms by (simp add: Lcm_int_def dvd_int_iff) |
1700 |
2222 |
1701 lemma Lcm_dvd_int [simp]: |
2223 lemma Lcm_dvd_int [simp]: |
1702 fixes M :: "int set" |
2224 fixes M :: "int set" |
1703 assumes "\<forall>m\<in>M. m dvd n" shows "Lcm M dvd n" |
2225 assumes "\<forall>m\<in>M. m dvd n" shows "Lcm M dvd n" |
1704 using assms by (simp add: Lcm_int_def dvd_int_iff) |
2226 using assms by (simp add: Lcm_int_def dvd_int_iff) |
1705 |
2227 |
1706 instance int :: semiring_Gcd |
|
1707 by intro_classes (simp_all add: Gcd_int_def gcd_int_def dvd_int_iff Gcd_dvd dvd_Gcd) |
|
1708 |
|
1709 lemma Lcm_set_int [code, code_unfold]: |
2228 lemma Lcm_set_int [code, code_unfold]: |
1710 "Lcm (set xs) = fold lcm xs (1::int)" |
2229 "Lcm (set xs) = fold lcm xs (1::int)" |
1711 by (induct xs rule: rev_induct) (simp_all add: lcm_commute_int) |
2230 by (induct xs rule: rev_induct) (simp_all add: lcm_commute_int) |
1712 |
2231 |
1713 lemma Gcd_set_int [code]: |
2232 lemma Gcd_set_int [code]: |