|
1 (* Title: HOL/Library/Cong.thy |
|
2 ID: |
|
3 Authors: Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb, |
|
4 Thomas M. Rasmussen, Jeremy Avigad |
|
5 |
|
6 |
|
7 Defines congruence (notation: [x = y] (mod z)) for natural numbers and |
|
8 integers. |
|
9 |
|
10 This file combines and revises a number of prior developments. |
|
11 |
|
12 The original theories "GCD" and "Primes" were by Christophe Tabacznyj |
|
13 and Lawrence C. Paulson, based on \cite{davenport92}. They introduced |
|
14 gcd, lcm, and prime for the natural numbers. |
|
15 |
|
16 The original theory "IntPrimes" was by Thomas M. Rasmussen, and |
|
17 extended gcd, lcm, primes to the integers. Amine Chaieb provided |
|
18 another extension of the notions to the integers, and added a number |
|
19 of results to "Primes" and "GCD". |
|
20 |
|
21 The original theory, "IntPrimes", by Thomas M. Rasmussen, defined and |
|
22 developed the congruence relations on the integers. The notion was |
|
23 extended to the natural numbers by Chiaeb. Jeremy Avigad combined |
|
24 these, revised and tidied them, made the development uniform for the |
|
25 natural numbers and the integers, and added a number of new theorems. |
|
26 |
|
27 *) |
|
28 |
|
29 |
|
30 header {* Congruence *} |
|
31 |
|
32 theory Cong |
|
33 imports GCD |
|
34 begin |
|
35 |
|
36 subsection {* Turn off One_nat_def *} |
|
37 |
|
38 lemma nat_induct' [case_names zero plus1, induct type: nat]: |
|
39 "\<lbrakk> P (0::nat); !!n. P n \<Longrightarrow> P (n + 1)\<rbrakk> \<Longrightarrow> P n" |
|
40 by (erule nat_induct) (simp add:One_nat_def) |
|
41 |
|
42 lemma nat_cases [case_names zero plus1, cases type: nat]: |
|
43 "P (0::nat) \<Longrightarrow> (!!n. P (n + 1)) \<Longrightarrow> P n" |
|
44 by(metis nat_induct') |
|
45 |
|
46 lemma power_plus_one [simp]: "(x::'a::power)^(n + 1) = x * x^n" |
|
47 by (simp add: One_nat_def) |
|
48 |
|
49 lemma nat_power_eq_one_eq [simp]: |
|
50 "((x::nat)^m = 1) = (m = 0 | x = 1)" |
|
51 by (induct m, auto) |
|
52 |
|
53 lemma card_insert_if' [simp]: "finite A \<Longrightarrow> |
|
54 card (insert x A) = (if x \<in> A then (card A) else (card A) + 1)" |
|
55 by (auto simp add: insert_absorb) |
|
56 |
|
57 (* why wasn't card_insert_if a simp rule? *) |
|
58 declare card_insert_disjoint [simp del] |
|
59 |
|
60 lemma nat_1' [simp]: "nat 1 = 1" |
|
61 by simp |
|
62 |
|
63 (* For those annoying moments where Suc reappears *) |
|
64 lemma Suc_remove: "Suc n = n + 1" |
|
65 by simp |
|
66 |
|
67 declare nat_1 [simp del] |
|
68 declare add_2_eq_Suc [simp del] |
|
69 declare add_2_eq_Suc' [simp del] |
|
70 |
|
71 |
|
72 declare mod_pos_pos_trivial [simp] |
|
73 |
|
74 |
|
75 subsection {* Main definitions *} |
|
76 |
|
77 class cong = |
|
78 |
|
79 fixes |
|
80 cong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ = _] '(mod _'))") |
|
81 |
|
82 begin |
|
83 |
|
84 abbreviation |
|
85 notcong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ \<noteq> _] '(mod _'))") |
|
86 where |
|
87 "notcong x y m == (~cong x y m)" |
|
88 |
|
89 end |
|
90 |
|
91 (* definitions for the natural numbers *) |
|
92 |
|
93 instantiation nat :: cong |
|
94 |
|
95 begin |
|
96 |
|
97 definition |
|
98 cong_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
|
99 where |
|
100 "cong_nat x y m = ((x mod m) = (y mod m))" |
|
101 |
|
102 instance proof qed |
|
103 |
|
104 end |
|
105 |
|
106 |
|
107 (* definitions for the integers *) |
|
108 |
|
109 instantiation int :: cong |
|
110 |
|
111 begin |
|
112 |
|
113 definition |
|
114 cong_int :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool" |
|
115 where |
|
116 "cong_int x y m = ((x mod m) = (y mod m))" |
|
117 |
|
118 instance proof qed |
|
119 |
|
120 end |
|
121 |
|
122 |
|
123 subsection {* Set up Transfer *} |
|
124 |
|
125 |
|
126 lemma transfer_nat_int_cong: |
|
127 "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> m >= 0 \<Longrightarrow> |
|
128 ([(nat x) = (nat y)] (mod (nat m))) = ([x = y] (mod m))" |
|
129 unfolding cong_int_def cong_nat_def |
|
130 apply (auto simp add: nat_mod_distrib [symmetric]) |
|
131 apply (subst (asm) eq_nat_nat_iff) |
|
132 apply (case_tac "m = 0", force, rule pos_mod_sign, force)+ |
|
133 apply assumption |
|
134 done |
|
135 |
|
136 declare TransferMorphism_nat_int[transfer add return: |
|
137 transfer_nat_int_cong] |
|
138 |
|
139 lemma transfer_int_nat_cong: |
|
140 "[(int x) = (int y)] (mod (int m)) = [x = y] (mod m)" |
|
141 apply (auto simp add: cong_int_def cong_nat_def) |
|
142 apply (auto simp add: zmod_int [symmetric]) |
|
143 done |
|
144 |
|
145 declare TransferMorphism_int_nat[transfer add return: |
|
146 transfer_int_nat_cong] |
|
147 |
|
148 |
|
149 subsection {* Congruence *} |
|
150 |
|
151 (* was zcong_0, etc. *) |
|
152 lemma nat_cong_0 [simp, presburger]: "([(a::nat) = b] (mod 0)) = (a = b)" |
|
153 by (unfold cong_nat_def, auto) |
|
154 |
|
155 lemma int_cong_0 [simp, presburger]: "([(a::int) = b] (mod 0)) = (a = b)" |
|
156 by (unfold cong_int_def, auto) |
|
157 |
|
158 lemma nat_cong_1 [simp, presburger]: "[(a::nat) = b] (mod 1)" |
|
159 by (unfold cong_nat_def, auto) |
|
160 |
|
161 lemma nat_cong_Suc_0 [simp, presburger]: "[(a::nat) = b] (mod Suc 0)" |
|
162 by (unfold cong_nat_def, auto simp add: One_nat_def) |
|
163 |
|
164 lemma int_cong_1 [simp, presburger]: "[(a::int) = b] (mod 1)" |
|
165 by (unfold cong_int_def, auto) |
|
166 |
|
167 lemma nat_cong_refl [simp]: "[(k::nat) = k] (mod m)" |
|
168 by (unfold cong_nat_def, auto) |
|
169 |
|
170 lemma int_cong_refl [simp]: "[(k::int) = k] (mod m)" |
|
171 by (unfold cong_int_def, auto) |
|
172 |
|
173 lemma nat_cong_sym: "[(a::nat) = b] (mod m) \<Longrightarrow> [b = a] (mod m)" |
|
174 by (unfold cong_nat_def, auto) |
|
175 |
|
176 lemma int_cong_sym: "[(a::int) = b] (mod m) \<Longrightarrow> [b = a] (mod m)" |
|
177 by (unfold cong_int_def, auto) |
|
178 |
|
179 lemma nat_cong_sym_eq: "[(a::nat) = b] (mod m) = [b = a] (mod m)" |
|
180 by (unfold cong_nat_def, auto) |
|
181 |
|
182 lemma int_cong_sym_eq: "[(a::int) = b] (mod m) = [b = a] (mod m)" |
|
183 by (unfold cong_int_def, auto) |
|
184 |
|
185 lemma nat_cong_trans [trans]: |
|
186 "[(a::nat) = b] (mod m) \<Longrightarrow> [b = c] (mod m) \<Longrightarrow> [a = c] (mod m)" |
|
187 by (unfold cong_nat_def, auto) |
|
188 |
|
189 lemma int_cong_trans [trans]: |
|
190 "[(a::int) = b] (mod m) \<Longrightarrow> [b = c] (mod m) \<Longrightarrow> [a = c] (mod m)" |
|
191 by (unfold cong_int_def, auto) |
|
192 |
|
193 lemma nat_cong_add: |
|
194 "[(a::nat) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a + c = b + d] (mod m)" |
|
195 apply (unfold cong_nat_def) |
|
196 apply (subst (1 2) mod_add_eq) |
|
197 apply simp |
|
198 done |
|
199 |
|
200 lemma int_cong_add: |
|
201 "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a + c = b + d] (mod m)" |
|
202 apply (unfold cong_int_def) |
|
203 apply (subst (1 2) mod_add_left_eq) |
|
204 apply (subst (1 2) mod_add_right_eq) |
|
205 apply simp |
|
206 done |
|
207 |
|
208 lemma int_cong_diff: |
|
209 "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a - c = b - d] (mod m)" |
|
210 apply (unfold cong_int_def) |
|
211 apply (subst (1 2) mod_diff_eq) |
|
212 apply simp |
|
213 done |
|
214 |
|
215 lemma int_cong_diff_aux: |
|
216 "(a::int) >= c \<Longrightarrow> b >= d \<Longrightarrow> [(a::int) = b] (mod m) \<Longrightarrow> |
|
217 [c = d] (mod m) \<Longrightarrow> [tsub a c = tsub b d] (mod m)" |
|
218 apply (subst (1 2) tsub_eq) |
|
219 apply (auto intro: int_cong_diff) |
|
220 done; |
|
221 |
|
222 lemma nat_cong_diff: |
|
223 assumes "(a::nat) >= c" and "b >= d" and "[a = b] (mod m)" and |
|
224 "[c = d] (mod m)" |
|
225 shows "[a - c = b - d] (mod m)" |
|
226 |
|
227 using prems by (rule int_cong_diff_aux [transferred]); |
|
228 |
|
229 lemma nat_cong_mult: |
|
230 "[(a::nat) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a * c = b * d] (mod m)" |
|
231 apply (unfold cong_nat_def) |
|
232 apply (subst (1 2) mod_mult_eq) |
|
233 apply simp |
|
234 done |
|
235 |
|
236 lemma int_cong_mult: |
|
237 "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a * c = b * d] (mod m)" |
|
238 apply (unfold cong_int_def) |
|
239 apply (subst (1 2) zmod_zmult1_eq) |
|
240 apply (subst (1 2) mult_commute) |
|
241 apply (subst (1 2) zmod_zmult1_eq) |
|
242 apply simp |
|
243 done |
|
244 |
|
245 lemma nat_cong_exp: "[(x::nat) = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)" |
|
246 apply (induct k) |
|
247 apply (auto simp add: nat_cong_refl nat_cong_mult) |
|
248 done |
|
249 |
|
250 lemma int_cong_exp: "[(x::int) = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)" |
|
251 apply (induct k) |
|
252 apply (auto simp add: int_cong_refl int_cong_mult) |
|
253 done |
|
254 |
|
255 lemma nat_cong_setsum [rule_format]: |
|
256 "(ALL x: A. [((f x)::nat) = g x] (mod m)) \<longrightarrow> |
|
257 [(SUM x:A. f x) = (SUM x:A. g x)] (mod m)" |
|
258 apply (case_tac "finite A") |
|
259 apply (induct set: finite) |
|
260 apply (auto intro: nat_cong_add) |
|
261 done |
|
262 |
|
263 lemma int_cong_setsum [rule_format]: |
|
264 "(ALL x: A. [((f x)::int) = g x] (mod m)) \<longrightarrow> |
|
265 [(SUM x:A. f x) = (SUM x:A. g x)] (mod m)" |
|
266 apply (case_tac "finite A") |
|
267 apply (induct set: finite) |
|
268 apply (auto intro: int_cong_add) |
|
269 done |
|
270 |
|
271 lemma nat_cong_setprod [rule_format]: |
|
272 "(ALL x: A. [((f x)::nat) = g x] (mod m)) \<longrightarrow> |
|
273 [(PROD x:A. f x) = (PROD x:A. g x)] (mod m)" |
|
274 apply (case_tac "finite A") |
|
275 apply (induct set: finite) |
|
276 apply (auto intro: nat_cong_mult) |
|
277 done |
|
278 |
|
279 lemma int_cong_setprod [rule_format]: |
|
280 "(ALL x: A. [((f x)::int) = g x] (mod m)) \<longrightarrow> |
|
281 [(PROD x:A. f x) = (PROD x:A. g x)] (mod m)" |
|
282 apply (case_tac "finite A") |
|
283 apply (induct set: finite) |
|
284 apply (auto intro: int_cong_mult) |
|
285 done |
|
286 |
|
287 lemma nat_cong_scalar: "[(a::nat)= b] (mod m) \<Longrightarrow> [a * k = b * k] (mod m)" |
|
288 by (rule nat_cong_mult, simp_all) |
|
289 |
|
290 lemma int_cong_scalar: "[(a::int)= b] (mod m) \<Longrightarrow> [a * k = b * k] (mod m)" |
|
291 by (rule int_cong_mult, simp_all) |
|
292 |
|
293 lemma nat_cong_scalar2: "[(a::nat)= b] (mod m) \<Longrightarrow> [k * a = k * b] (mod m)" |
|
294 by (rule nat_cong_mult, simp_all) |
|
295 |
|
296 lemma int_cong_scalar2: "[(a::int)= b] (mod m) \<Longrightarrow> [k * a = k * b] (mod m)" |
|
297 by (rule int_cong_mult, simp_all) |
|
298 |
|
299 lemma nat_cong_mult_self: "[(a::nat) * m = 0] (mod m)" |
|
300 by (unfold cong_nat_def, auto) |
|
301 |
|
302 lemma int_cong_mult_self: "[(a::int) * m = 0] (mod m)" |
|
303 by (unfold cong_int_def, auto) |
|
304 |
|
305 lemma int_cong_eq_diff_cong_0: "[(a::int) = b] (mod m) = [a - b = 0] (mod m)" |
|
306 apply (rule iffI) |
|
307 apply (erule int_cong_diff [of a b m b b, simplified]) |
|
308 apply (erule int_cong_add [of "a - b" 0 m b b, simplified]) |
|
309 done |
|
310 |
|
311 lemma int_cong_eq_diff_cong_0_aux: "a >= b \<Longrightarrow> |
|
312 [(a::int) = b] (mod m) = [tsub a b = 0] (mod m)" |
|
313 by (subst tsub_eq, assumption, rule int_cong_eq_diff_cong_0) |
|
314 |
|
315 lemma nat_cong_eq_diff_cong_0: |
|
316 assumes "(a::nat) >= b" |
|
317 shows "[a = b] (mod m) = [a - b = 0] (mod m)" |
|
318 |
|
319 using prems by (rule int_cong_eq_diff_cong_0_aux [transferred]) |
|
320 |
|
321 lemma nat_cong_diff_cong_0': |
|
322 "[(x::nat) = y] (mod n) \<longleftrightarrow> |
|
323 (if x <= y then [y - x = 0] (mod n) else [x - y = 0] (mod n))" |
|
324 apply (case_tac "y <= x") |
|
325 apply (frule nat_cong_eq_diff_cong_0 [where m = n]) |
|
326 apply auto [1] |
|
327 apply (subgoal_tac "x <= y") |
|
328 apply (frule nat_cong_eq_diff_cong_0 [where m = n]) |
|
329 apply (subst nat_cong_sym_eq) |
|
330 apply auto |
|
331 done |
|
332 |
|
333 lemma nat_cong_altdef: "(a::nat) >= b \<Longrightarrow> [a = b] (mod m) = (m dvd (a - b))" |
|
334 apply (subst nat_cong_eq_diff_cong_0, assumption) |
|
335 apply (unfold cong_nat_def) |
|
336 apply (simp add: dvd_eq_mod_eq_0 [symmetric]) |
|
337 done |
|
338 |
|
339 lemma int_cong_altdef: "[(a::int) = b] (mod m) = (m dvd (a - b))" |
|
340 apply (subst int_cong_eq_diff_cong_0) |
|
341 apply (unfold cong_int_def) |
|
342 apply (simp add: dvd_eq_mod_eq_0 [symmetric]) |
|
343 done |
|
344 |
|
345 lemma int_cong_abs: "[(x::int) = y] (mod abs m) = [x = y] (mod m)" |
|
346 by (simp add: int_cong_altdef) |
|
347 |
|
348 lemma int_cong_square: |
|
349 "\<lbrakk> prime (p::int); 0 < a; [a * a = 1] (mod p) \<rbrakk> |
|
350 \<Longrightarrow> [a = 1] (mod p) \<or> [a = - 1] (mod p)" |
|
351 apply (simp only: int_cong_altdef) |
|
352 apply (subst int_prime_dvd_mult_eq [symmetric], assumption) |
|
353 (* any way around this? *) |
|
354 apply (subgoal_tac "a * a - 1 = (a - 1) * (a - -1)") |
|
355 apply (auto simp add: ring_simps) |
|
356 done |
|
357 |
|
358 lemma int_cong_mult_rcancel: |
|
359 "coprime k (m::int) \<Longrightarrow> [a * k = b * k] (mod m) = [a = b] (mod m)" |
|
360 apply (subst (1 2) int_cong_altdef) |
|
361 apply (subst left_diff_distrib [symmetric]) |
|
362 apply (rule int_coprime_dvd_mult_iff) |
|
363 apply (subst int_gcd_commute, assumption) |
|
364 done |
|
365 |
|
366 lemma nat_cong_mult_rcancel: |
|
367 assumes "coprime k (m::nat)" |
|
368 shows "[a * k = b * k] (mod m) = [a = b] (mod m)" |
|
369 |
|
370 apply (rule int_cong_mult_rcancel [transferred]) |
|
371 using prems apply auto |
|
372 done |
|
373 |
|
374 lemma nat_cong_mult_lcancel: |
|
375 "coprime k (m::nat) \<Longrightarrow> [k * a = k * b ] (mod m) = [a = b] (mod m)" |
|
376 by (simp add: mult_commute nat_cong_mult_rcancel) |
|
377 |
|
378 lemma int_cong_mult_lcancel: |
|
379 "coprime k (m::int) \<Longrightarrow> [k * a = k * b] (mod m) = [a = b] (mod m)" |
|
380 by (simp add: mult_commute int_cong_mult_rcancel) |
|
381 |
|
382 (* was zcong_zgcd_zmult_zmod *) |
|
383 lemma int_coprime_cong_mult: |
|
384 "[(a::int) = b] (mod m) \<Longrightarrow> [a = b] (mod n) \<Longrightarrow> coprime m n |
|
385 \<Longrightarrow> [a = b] (mod m * n)" |
|
386 apply (simp only: int_cong_altdef) |
|
387 apply (erule (2) int_divides_mult) |
|
388 done |
|
389 |
|
390 lemma nat_coprime_cong_mult: |
|
391 assumes "[(a::nat) = b] (mod m)" and "[a = b] (mod n)" and "coprime m n" |
|
392 shows "[a = b] (mod m * n)" |
|
393 |
|
394 apply (rule int_coprime_cong_mult [transferred]) |
|
395 using prems apply auto |
|
396 done |
|
397 |
|
398 lemma nat_cong_less_imp_eq: "0 \<le> (a::nat) \<Longrightarrow> |
|
399 a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b" |
|
400 by (auto simp add: cong_nat_def mod_pos_pos_trivial) |
|
401 |
|
402 lemma int_cong_less_imp_eq: "0 \<le> (a::int) \<Longrightarrow> |
|
403 a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b" |
|
404 by (auto simp add: cong_int_def mod_pos_pos_trivial) |
|
405 |
|
406 lemma nat_cong_less_unique: |
|
407 "0 < (m::nat) \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))" |
|
408 apply auto |
|
409 apply (rule_tac x = "a mod m" in exI) |
|
410 apply (unfold cong_nat_def, auto) |
|
411 done |
|
412 |
|
413 lemma int_cong_less_unique: |
|
414 "0 < (m::int) \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))" |
|
415 apply auto |
|
416 apply (rule_tac x = "a mod m" in exI) |
|
417 apply (unfold cong_int_def, auto simp add: mod_pos_pos_trivial) |
|
418 done |
|
419 |
|
420 lemma int_cong_iff_lin: "([(a::int) = b] (mod m)) = (\<exists>k. b = a + m * k)" |
|
421 apply (auto simp add: int_cong_altdef dvd_def ring_simps) |
|
422 apply (rule_tac [!] x = "-k" in exI, auto) |
|
423 done |
|
424 |
|
425 lemma nat_cong_iff_lin: "([(a::nat) = b] (mod m)) = |
|
426 (\<exists>k1 k2. b + k1 * m = a + k2 * m)" |
|
427 apply (rule iffI) |
|
428 apply (case_tac "b <= a") |
|
429 apply (subst (asm) nat_cong_altdef, assumption) |
|
430 apply (unfold dvd_def, auto) |
|
431 apply (rule_tac x = k in exI) |
|
432 apply (rule_tac x = 0 in exI) |
|
433 apply (auto simp add: ring_simps) |
|
434 apply (subst (asm) nat_cong_sym_eq) |
|
435 apply (subst (asm) nat_cong_altdef) |
|
436 apply force |
|
437 apply (unfold dvd_def, auto) |
|
438 apply (rule_tac x = 0 in exI) |
|
439 apply (rule_tac x = k in exI) |
|
440 apply (auto simp add: ring_simps) |
|
441 apply (unfold cong_nat_def) |
|
442 apply (subgoal_tac "a mod m = (a + k2 * m) mod m") |
|
443 apply (erule ssubst)back |
|
444 apply (erule subst) |
|
445 apply auto |
|
446 done |
|
447 |
|
448 lemma int_cong_gcd_eq: "[(a::int) = b] (mod m) \<Longrightarrow> gcd a m = gcd b m" |
|
449 apply (subst (asm) int_cong_iff_lin, auto) |
|
450 apply (subst add_commute) |
|
451 apply (subst (2) int_gcd_commute) |
|
452 apply (subst mult_commute) |
|
453 apply (subst int_gcd_add_mult) |
|
454 apply (rule int_gcd_commute) |
|
455 done |
|
456 |
|
457 lemma nat_cong_gcd_eq: |
|
458 assumes "[(a::nat) = b] (mod m)" |
|
459 shows "gcd a m = gcd b m" |
|
460 |
|
461 apply (rule int_cong_gcd_eq [transferred]) |
|
462 using prems apply auto |
|
463 done |
|
464 |
|
465 lemma nat_cong_imp_coprime: "[(a::nat) = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> |
|
466 coprime b m" |
|
467 by (auto simp add: nat_cong_gcd_eq) |
|
468 |
|
469 lemma int_cong_imp_coprime: "[(a::int) = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> |
|
470 coprime b m" |
|
471 by (auto simp add: int_cong_gcd_eq) |
|
472 |
|
473 lemma nat_cong_cong_mod: "[(a::nat) = b] (mod m) = |
|
474 [a mod m = b mod m] (mod m)" |
|
475 by (auto simp add: cong_nat_def) |
|
476 |
|
477 lemma int_cong_cong_mod: "[(a::int) = b] (mod m) = |
|
478 [a mod m = b mod m] (mod m)" |
|
479 by (auto simp add: cong_int_def) |
|
480 |
|
481 lemma int_cong_minus [iff]: "[(a::int) = b] (mod -m) = [a = b] (mod m)" |
|
482 by (subst (1 2) int_cong_altdef, auto) |
|
483 |
|
484 lemma nat_cong_zero [iff]: "[(a::nat) = b] (mod 0) = (a = b)" |
|
485 by (auto simp add: cong_nat_def) |
|
486 |
|
487 lemma int_cong_zero [iff]: "[(a::int) = b] (mod 0) = (a = b)" |
|
488 by (auto simp add: cong_int_def) |
|
489 |
|
490 (* |
|
491 lemma int_mod_dvd_mod: |
|
492 "0 < (m::int) \<Longrightarrow> m dvd b \<Longrightarrow> (a mod b mod m) = (a mod m)" |
|
493 apply (unfold dvd_def, auto) |
|
494 apply (rule mod_mod_cancel) |
|
495 apply auto |
|
496 done |
|
497 |
|
498 lemma mod_dvd_mod: |
|
499 assumes "0 < (m::nat)" and "m dvd b" |
|
500 shows "(a mod b mod m) = (a mod m)" |
|
501 |
|
502 apply (rule int_mod_dvd_mod [transferred]) |
|
503 using prems apply auto |
|
504 done |
|
505 *) |
|
506 |
|
507 lemma nat_cong_add_lcancel: |
|
508 "[(a::nat) + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
|
509 by (simp add: nat_cong_iff_lin) |
|
510 |
|
511 lemma int_cong_add_lcancel: |
|
512 "[(a::int) + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
|
513 by (simp add: int_cong_iff_lin) |
|
514 |
|
515 lemma nat_cong_add_rcancel: "[(x::nat) + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
|
516 by (simp add: nat_cong_iff_lin) |
|
517 |
|
518 lemma int_cong_add_rcancel: "[(x::int) + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
|
519 by (simp add: int_cong_iff_lin) |
|
520 |
|
521 lemma nat_cong_add_lcancel_0: "[(a::nat) + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
|
522 by (simp add: nat_cong_iff_lin) |
|
523 |
|
524 lemma int_cong_add_lcancel_0: "[(a::int) + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
|
525 by (simp add: int_cong_iff_lin) |
|
526 |
|
527 lemma nat_cong_add_rcancel_0: "[x + (a::nat) = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
|
528 by (simp add: nat_cong_iff_lin) |
|
529 |
|
530 lemma int_cong_add_rcancel_0: "[x + (a::int) = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
|
531 by (simp add: int_cong_iff_lin) |
|
532 |
|
533 lemma nat_cong_dvd_modulus: "[(x::nat) = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> |
|
534 [x = y] (mod n)" |
|
535 apply (auto simp add: nat_cong_iff_lin dvd_def) |
|
536 apply (rule_tac x="k1 * k" in exI) |
|
537 apply (rule_tac x="k2 * k" in exI) |
|
538 apply (simp add: ring_simps) |
|
539 done |
|
540 |
|
541 lemma int_cong_dvd_modulus: "[(x::int) = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> |
|
542 [x = y] (mod n)" |
|
543 by (auto simp add: int_cong_altdef dvd_def) |
|
544 |
|
545 lemma nat_cong_dvd_eq: "[(x::nat) = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y" |
|
546 by (unfold cong_nat_def, auto simp add: dvd_eq_mod_eq_0) |
|
547 |
|
548 lemma int_cong_dvd_eq: "[(x::int) = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y" |
|
549 by (unfold cong_int_def, auto simp add: dvd_eq_mod_eq_0) |
|
550 |
|
551 lemma nat_cong_mod: "(n::nat) ~= 0 \<Longrightarrow> [a mod n = a] (mod n)" |
|
552 by (simp add: cong_nat_def) |
|
553 |
|
554 lemma int_cong_mod: "(n::int) ~= 0 \<Longrightarrow> [a mod n = a] (mod n)" |
|
555 by (simp add: cong_int_def) |
|
556 |
|
557 lemma nat_mod_mult_cong: "(a::nat) ~= 0 \<Longrightarrow> b ~= 0 |
|
558 \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)" |
|
559 by (simp add: cong_nat_def mod_mult2_eq mod_add_left_eq) |
|
560 |
|
561 lemma int_neg_cong: "([(a::int) = b] (mod m)) = ([-a = -b] (mod m))" |
|
562 apply (simp add: int_cong_altdef) |
|
563 apply (subst dvd_minus_iff [symmetric]) |
|
564 apply (simp add: ring_simps) |
|
565 done |
|
566 |
|
567 lemma int_cong_modulus_neg: "([(a::int) = b] (mod m)) = ([a = b] (mod -m))" |
|
568 by (auto simp add: int_cong_altdef) |
|
569 |
|
570 lemma int_mod_mult_cong: "(a::int) ~= 0 \<Longrightarrow> b ~= 0 |
|
571 \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)" |
|
572 apply (case_tac "b > 0") |
|
573 apply (simp add: cong_int_def mod_mod_cancel mod_add_left_eq) |
|
574 apply (subst (1 2) int_cong_modulus_neg) |
|
575 apply (unfold cong_int_def) |
|
576 apply (subgoal_tac "a * b = (-a * -b)") |
|
577 apply (erule ssubst) |
|
578 apply (subst zmod_zmult2_eq) |
|
579 apply (auto simp add: mod_add_left_eq) |
|
580 done |
|
581 |
|
582 lemma nat_cong_to_1: "([(a::nat) = 1] (mod n)) \<Longrightarrow> (n dvd (a - 1))" |
|
583 apply (case_tac "a = 0") |
|
584 apply force |
|
585 apply (subst (asm) nat_cong_altdef) |
|
586 apply auto |
|
587 done |
|
588 |
|
589 lemma nat_0_cong_1: "[(0::nat) = 1] (mod n) = (n = 1)" |
|
590 by (unfold cong_nat_def, auto) |
|
591 |
|
592 lemma int_0_cong_1: "[(0::int) = 1] (mod n) = ((n = 1) | (n = -1))" |
|
593 by (unfold cong_int_def, auto simp add: zmult_eq_1_iff) |
|
594 |
|
595 lemma nat_cong_to_1': "[(a::nat) = 1] (mod n) \<longleftrightarrow> |
|
596 a = 0 \<and> n = 1 \<or> (\<exists>m. a = 1 + m * n)" |
|
597 apply (case_tac "n = 1") |
|
598 apply auto [1] |
|
599 apply (drule_tac x = "a - 1" in spec) |
|
600 apply force |
|
601 apply (case_tac "a = 0") |
|
602 apply (auto simp add: nat_0_cong_1) [1] |
|
603 apply (rule iffI) |
|
604 apply (drule nat_cong_to_1) |
|
605 apply (unfold dvd_def) |
|
606 apply auto [1] |
|
607 apply (rule_tac x = k in exI) |
|
608 apply (auto simp add: ring_simps) [1] |
|
609 apply (subst nat_cong_altdef) |
|
610 apply (auto simp add: dvd_def) |
|
611 done |
|
612 |
|
613 lemma nat_cong_le: "(y::nat) <= x \<Longrightarrow> [x = y] (mod n) \<longleftrightarrow> (\<exists>q. x = q * n + y)" |
|
614 apply (subst nat_cong_altdef) |
|
615 apply assumption |
|
616 apply (unfold dvd_def, auto simp add: ring_simps) |
|
617 apply (rule_tac x = k in exI) |
|
618 apply auto |
|
619 done |
|
620 |
|
621 lemma nat_cong_solve: "(a::nat) \<noteq> 0 \<Longrightarrow> EX x. [a * x = gcd a n] (mod n)" |
|
622 apply (case_tac "n = 0") |
|
623 apply force |
|
624 apply (frule nat_bezout [of a n], auto) |
|
625 apply (rule exI, erule ssubst) |
|
626 apply (rule nat_cong_trans) |
|
627 apply (rule nat_cong_add) |
|
628 apply (subst mult_commute) |
|
629 apply (rule nat_cong_mult_self) |
|
630 prefer 2 |
|
631 apply simp |
|
632 apply (rule nat_cong_refl) |
|
633 apply (rule nat_cong_refl) |
|
634 done |
|
635 |
|
636 lemma int_cong_solve: "(a::int) \<noteq> 0 \<Longrightarrow> EX x. [a * x = gcd a n] (mod n)" |
|
637 apply (case_tac "n = 0") |
|
638 apply (case_tac "a \<ge> 0") |
|
639 apply auto |
|
640 apply (rule_tac x = "-1" in exI) |
|
641 apply auto |
|
642 apply (insert int_bezout [of a n], auto) |
|
643 apply (rule exI) |
|
644 apply (erule subst) |
|
645 apply (rule int_cong_trans) |
|
646 prefer 2 |
|
647 apply (rule int_cong_add) |
|
648 apply (rule int_cong_refl) |
|
649 apply (rule int_cong_sym) |
|
650 apply (rule int_cong_mult_self) |
|
651 apply simp |
|
652 apply (subst mult_commute) |
|
653 apply (rule int_cong_refl) |
|
654 done |
|
655 |
|
656 lemma nat_cong_solve_dvd: |
|
657 assumes a: "(a::nat) \<noteq> 0" and b: "gcd a n dvd d" |
|
658 shows "EX x. [a * x = d] (mod n)" |
|
659 proof - |
|
660 from nat_cong_solve [OF a] obtain x where |
|
661 "[a * x = gcd a n](mod n)" |
|
662 by auto |
|
663 hence "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" |
|
664 by (elim nat_cong_scalar2) |
|
665 also from b have "(d div gcd a n) * gcd a n = d" |
|
666 by (rule dvd_div_mult_self) |
|
667 also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)" |
|
668 by auto |
|
669 finally show ?thesis |
|
670 by auto |
|
671 qed |
|
672 |
|
673 lemma int_cong_solve_dvd: |
|
674 assumes a: "(a::int) \<noteq> 0" and b: "gcd a n dvd d" |
|
675 shows "EX x. [a * x = d] (mod n)" |
|
676 proof - |
|
677 from int_cong_solve [OF a] obtain x where |
|
678 "[a * x = gcd a n](mod n)" |
|
679 by auto |
|
680 hence "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" |
|
681 by (elim int_cong_scalar2) |
|
682 also from b have "(d div gcd a n) * gcd a n = d" |
|
683 by (rule dvd_div_mult_self) |
|
684 also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)" |
|
685 by auto |
|
686 finally show ?thesis |
|
687 by auto |
|
688 qed |
|
689 |
|
690 lemma nat_cong_solve_coprime: "coprime (a::nat) n \<Longrightarrow> |
|
691 EX x. [a * x = 1] (mod n)" |
|
692 apply (case_tac "a = 0") |
|
693 apply force |
|
694 apply (frule nat_cong_solve [of a n]) |
|
695 apply auto |
|
696 done |
|
697 |
|
698 lemma int_cong_solve_coprime: "coprime (a::int) n \<Longrightarrow> |
|
699 EX x. [a * x = 1] (mod n)" |
|
700 apply (case_tac "a = 0") |
|
701 apply auto |
|
702 apply (case_tac "n \<ge> 0") |
|
703 apply auto |
|
704 apply (subst cong_int_def, auto) |
|
705 apply (frule int_cong_solve [of a n]) |
|
706 apply auto |
|
707 done |
|
708 |
|
709 lemma nat_coprime_iff_invertible: "m > (1::nat) \<Longrightarrow> coprime a m = |
|
710 (EX x. [a * x = 1] (mod m))" |
|
711 apply (auto intro: nat_cong_solve_coprime) |
|
712 apply (unfold cong_nat_def, auto intro: nat_invertible_coprime) |
|
713 done |
|
714 |
|
715 lemma int_coprime_iff_invertible: "m > (1::int) \<Longrightarrow> coprime a m = |
|
716 (EX x. [a * x = 1] (mod m))" |
|
717 apply (auto intro: int_cong_solve_coprime) |
|
718 apply (unfold cong_int_def) |
|
719 apply (auto intro: int_invertible_coprime) |
|
720 done |
|
721 |
|
722 lemma int_coprime_iff_invertible': "m > (1::int) \<Longrightarrow> coprime a m = |
|
723 (EX x. 0 <= x & x < m & [a * x = 1] (mod m))" |
|
724 apply (subst int_coprime_iff_invertible) |
|
725 apply auto |
|
726 apply (auto simp add: cong_int_def) |
|
727 apply (rule_tac x = "x mod m" in exI) |
|
728 apply (auto simp add: mod_mult_right_eq [symmetric]) |
|
729 done |
|
730 |
|
731 |
|
732 lemma nat_cong_cong_lcm: "[(x::nat) = y] (mod a) \<Longrightarrow> |
|
733 [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)" |
|
734 apply (case_tac "y \<le> x") |
|
735 apply (auto simp add: nat_cong_altdef nat_lcm_least) [1] |
|
736 apply (rule nat_cong_sym) |
|
737 apply (subst (asm) (1 2) nat_cong_sym_eq) |
|
738 apply (auto simp add: nat_cong_altdef nat_lcm_least) |
|
739 done |
|
740 |
|
741 lemma int_cong_cong_lcm: "[(x::int) = y] (mod a) \<Longrightarrow> |
|
742 [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)" |
|
743 by (auto simp add: int_cong_altdef int_lcm_least) [1] |
|
744 |
|
745 lemma nat_cong_cong_coprime: "coprime a b \<Longrightarrow> [(x::nat) = y] (mod a) \<Longrightarrow> |
|
746 [x = y] (mod b) \<Longrightarrow> [x = y] (mod a * b)" |
|
747 apply (frule (1) nat_cong_cong_lcm)back |
|
748 apply (simp add: lcm_nat_def) |
|
749 done |
|
750 |
|
751 lemma int_cong_cong_coprime: "coprime a b \<Longrightarrow> [(x::int) = y] (mod a) \<Longrightarrow> |
|
752 [x = y] (mod b) \<Longrightarrow> [x = y] (mod a * b)" |
|
753 apply (frule (1) int_cong_cong_lcm)back |
|
754 apply (simp add: int_lcm_altdef int_cong_abs abs_mult [symmetric]) |
|
755 done |
|
756 |
|
757 lemma nat_cong_cong_setprod_coprime [rule_format]: "finite A \<Longrightarrow> |
|
758 (ALL i:A. (ALL j:A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow> |
|
759 (ALL i:A. [(x::nat) = y] (mod m i)) \<longrightarrow> |
|
760 [x = y] (mod (PROD i:A. m i))" |
|
761 apply (induct set: finite) |
|
762 apply auto |
|
763 apply (rule nat_cong_cong_coprime) |
|
764 apply (subst nat_gcd_commute) |
|
765 apply (rule nat_setprod_coprime) |
|
766 apply auto |
|
767 done |
|
768 |
|
769 lemma int_cong_cong_setprod_coprime [rule_format]: "finite A \<Longrightarrow> |
|
770 (ALL i:A. (ALL j:A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow> |
|
771 (ALL i:A. [(x::int) = y] (mod m i)) \<longrightarrow> |
|
772 [x = y] (mod (PROD i:A. m i))" |
|
773 apply (induct set: finite) |
|
774 apply auto |
|
775 apply (rule int_cong_cong_coprime) |
|
776 apply (subst int_gcd_commute) |
|
777 apply (rule int_setprod_coprime) |
|
778 apply auto |
|
779 done |
|
780 |
|
781 lemma nat_binary_chinese_remainder_aux: |
|
782 assumes a: "coprime (m1::nat) m2" |
|
783 shows "EX b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and> |
|
784 [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)" |
|
785 proof - |
|
786 from nat_cong_solve_coprime [OF a] |
|
787 obtain x1 where one: "[m1 * x1 = 1] (mod m2)" |
|
788 by auto |
|
789 from a have b: "coprime m2 m1" |
|
790 by (subst nat_gcd_commute) |
|
791 from nat_cong_solve_coprime [OF b] |
|
792 obtain x2 where two: "[m2 * x2 = 1] (mod m1)" |
|
793 by auto |
|
794 have "[m1 * x1 = 0] (mod m1)" |
|
795 by (subst mult_commute, rule nat_cong_mult_self) |
|
796 moreover have "[m2 * x2 = 0] (mod m2)" |
|
797 by (subst mult_commute, rule nat_cong_mult_self) |
|
798 moreover note one two |
|
799 ultimately show ?thesis by blast |
|
800 qed |
|
801 |
|
802 lemma int_binary_chinese_remainder_aux: |
|
803 assumes a: "coprime (m1::int) m2" |
|
804 shows "EX b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and> |
|
805 [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)" |
|
806 proof - |
|
807 from int_cong_solve_coprime [OF a] |
|
808 obtain x1 where one: "[m1 * x1 = 1] (mod m2)" |
|
809 by auto |
|
810 from a have b: "coprime m2 m1" |
|
811 by (subst int_gcd_commute) |
|
812 from int_cong_solve_coprime [OF b] |
|
813 obtain x2 where two: "[m2 * x2 = 1] (mod m1)" |
|
814 by auto |
|
815 have "[m1 * x1 = 0] (mod m1)" |
|
816 by (subst mult_commute, rule int_cong_mult_self) |
|
817 moreover have "[m2 * x2 = 0] (mod m2)" |
|
818 by (subst mult_commute, rule int_cong_mult_self) |
|
819 moreover note one two |
|
820 ultimately show ?thesis by blast |
|
821 qed |
|
822 |
|
823 lemma nat_binary_chinese_remainder: |
|
824 assumes a: "coprime (m1::nat) m2" |
|
825 shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)" |
|
826 proof - |
|
827 from nat_binary_chinese_remainder_aux [OF a] obtain b1 b2 |
|
828 where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" and |
|
829 "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)" |
|
830 by blast |
|
831 let ?x = "u1 * b1 + u2 * b2" |
|
832 have "[?x = u1 * 1 + u2 * 0] (mod m1)" |
|
833 apply (rule nat_cong_add) |
|
834 apply (rule nat_cong_scalar2) |
|
835 apply (rule `[b1 = 1] (mod m1)`) |
|
836 apply (rule nat_cong_scalar2) |
|
837 apply (rule `[b2 = 0] (mod m1)`) |
|
838 done |
|
839 hence "[?x = u1] (mod m1)" by simp |
|
840 have "[?x = u1 * 0 + u2 * 1] (mod m2)" |
|
841 apply (rule nat_cong_add) |
|
842 apply (rule nat_cong_scalar2) |
|
843 apply (rule `[b1 = 0] (mod m2)`) |
|
844 apply (rule nat_cong_scalar2) |
|
845 apply (rule `[b2 = 1] (mod m2)`) |
|
846 done |
|
847 hence "[?x = u2] (mod m2)" by simp |
|
848 with `[?x = u1] (mod m1)` show ?thesis by blast |
|
849 qed |
|
850 |
|
851 lemma int_binary_chinese_remainder: |
|
852 assumes a: "coprime (m1::int) m2" |
|
853 shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)" |
|
854 proof - |
|
855 from int_binary_chinese_remainder_aux [OF a] obtain b1 b2 |
|
856 where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" and |
|
857 "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)" |
|
858 by blast |
|
859 let ?x = "u1 * b1 + u2 * b2" |
|
860 have "[?x = u1 * 1 + u2 * 0] (mod m1)" |
|
861 apply (rule int_cong_add) |
|
862 apply (rule int_cong_scalar2) |
|
863 apply (rule `[b1 = 1] (mod m1)`) |
|
864 apply (rule int_cong_scalar2) |
|
865 apply (rule `[b2 = 0] (mod m1)`) |
|
866 done |
|
867 hence "[?x = u1] (mod m1)" by simp |
|
868 have "[?x = u1 * 0 + u2 * 1] (mod m2)" |
|
869 apply (rule int_cong_add) |
|
870 apply (rule int_cong_scalar2) |
|
871 apply (rule `[b1 = 0] (mod m2)`) |
|
872 apply (rule int_cong_scalar2) |
|
873 apply (rule `[b2 = 1] (mod m2)`) |
|
874 done |
|
875 hence "[?x = u2] (mod m2)" by simp |
|
876 with `[?x = u1] (mod m1)` show ?thesis by blast |
|
877 qed |
|
878 |
|
879 lemma nat_cong_modulus_mult: "[(x::nat) = y] (mod m * n) \<Longrightarrow> |
|
880 [x = y] (mod m)" |
|
881 apply (case_tac "y \<le> x") |
|
882 apply (simp add: nat_cong_altdef) |
|
883 apply (erule dvd_mult_left) |
|
884 apply (rule nat_cong_sym) |
|
885 apply (subst (asm) nat_cong_sym_eq) |
|
886 apply (simp add: nat_cong_altdef) |
|
887 apply (erule dvd_mult_left) |
|
888 done |
|
889 |
|
890 lemma int_cong_modulus_mult: "[(x::int) = y] (mod m * n) \<Longrightarrow> |
|
891 [x = y] (mod m)" |
|
892 apply (simp add: int_cong_altdef) |
|
893 apply (erule dvd_mult_left) |
|
894 done |
|
895 |
|
896 lemma nat_cong_less_modulus_unique: |
|
897 "[(x::nat) = y] (mod m) \<Longrightarrow> x < m \<Longrightarrow> y < m \<Longrightarrow> x = y" |
|
898 by (simp add: cong_nat_def) |
|
899 |
|
900 lemma nat_binary_chinese_remainder_unique: |
|
901 assumes a: "coprime (m1::nat) m2" and |
|
902 nz: "m1 \<noteq> 0" "m2 \<noteq> 0" |
|
903 shows "EX! x. x < m1 * m2 \<and> [x = u1] (mod m1) \<and> [x = u2] (mod m2)" |
|
904 proof - |
|
905 from nat_binary_chinese_remainder [OF a] obtain y where |
|
906 "[y = u1] (mod m1)" and "[y = u2] (mod m2)" |
|
907 by blast |
|
908 let ?x = "y mod (m1 * m2)" |
|
909 from nz have less: "?x < m1 * m2" |
|
910 by auto |
|
911 have one: "[?x = u1] (mod m1)" |
|
912 apply (rule nat_cong_trans) |
|
913 prefer 2 |
|
914 apply (rule `[y = u1] (mod m1)`) |
|
915 apply (rule nat_cong_modulus_mult) |
|
916 apply (rule nat_cong_mod) |
|
917 using nz apply auto |
|
918 done |
|
919 have two: "[?x = u2] (mod m2)" |
|
920 apply (rule nat_cong_trans) |
|
921 prefer 2 |
|
922 apply (rule `[y = u2] (mod m2)`) |
|
923 apply (subst mult_commute) |
|
924 apply (rule nat_cong_modulus_mult) |
|
925 apply (rule nat_cong_mod) |
|
926 using nz apply auto |
|
927 done |
|
928 have "ALL z. z < m1 * m2 \<and> [z = u1] (mod m1) \<and> [z = u2] (mod m2) \<longrightarrow> |
|
929 z = ?x" |
|
930 proof (clarify) |
|
931 fix z |
|
932 assume "z < m1 * m2" |
|
933 assume "[z = u1] (mod m1)" and "[z = u2] (mod m2)" |
|
934 have "[?x = z] (mod m1)" |
|
935 apply (rule nat_cong_trans) |
|
936 apply (rule `[?x = u1] (mod m1)`) |
|
937 apply (rule nat_cong_sym) |
|
938 apply (rule `[z = u1] (mod m1)`) |
|
939 done |
|
940 moreover have "[?x = z] (mod m2)" |
|
941 apply (rule nat_cong_trans) |
|
942 apply (rule `[?x = u2] (mod m2)`) |
|
943 apply (rule nat_cong_sym) |
|
944 apply (rule `[z = u2] (mod m2)`) |
|
945 done |
|
946 ultimately have "[?x = z] (mod m1 * m2)" |
|
947 by (auto intro: nat_coprime_cong_mult a) |
|
948 with `z < m1 * m2` `?x < m1 * m2` show "z = ?x" |
|
949 apply (intro nat_cong_less_modulus_unique) |
|
950 apply (auto, erule nat_cong_sym) |
|
951 done |
|
952 qed |
|
953 with less one two show ?thesis |
|
954 by auto |
|
955 qed |
|
956 |
|
957 lemma nat_chinese_remainder_aux: |
|
958 fixes A :: "'a set" and |
|
959 m :: "'a \<Rightarrow> nat" |
|
960 assumes fin: "finite A" and |
|
961 cop: "ALL i : A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))" |
|
962 shows "EX b. (ALL i : A. |
|
963 [b i = 1] (mod m i) \<and> [b i = 0] (mod (PROD j : A - {i}. m j)))" |
|
964 proof (rule finite_set_choice, rule fin, rule ballI) |
|
965 fix i |
|
966 assume "i : A" |
|
967 with cop have "coprime (PROD j : A - {i}. m j) (m i)" |
|
968 by (intro nat_setprod_coprime, auto) |
|
969 hence "EX x. [(PROD j : A - {i}. m j) * x = 1] (mod m i)" |
|
970 by (elim nat_cong_solve_coprime) |
|
971 then obtain x where "[(PROD j : A - {i}. m j) * x = 1] (mod m i)" |
|
972 by auto |
|
973 moreover have "[(PROD j : A - {i}. m j) * x = 0] |
|
974 (mod (PROD j : A - {i}. m j))" |
|
975 by (subst mult_commute, rule nat_cong_mult_self) |
|
976 ultimately show "\<exists>a. [a = 1] (mod m i) \<and> [a = 0] |
|
977 (mod setprod m (A - {i}))" |
|
978 by blast |
|
979 qed |
|
980 |
|
981 lemma nat_chinese_remainder: |
|
982 fixes A :: "'a set" and |
|
983 m :: "'a \<Rightarrow> nat" and |
|
984 u :: "'a \<Rightarrow> nat" |
|
985 assumes |
|
986 fin: "finite A" and |
|
987 cop: "ALL i:A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))" |
|
988 shows "EX x. (ALL i:A. [x = u i] (mod m i))" |
|
989 proof - |
|
990 from nat_chinese_remainder_aux [OF fin cop] obtain b where |
|
991 bprop: "ALL i:A. [b i = 1] (mod m i) \<and> |
|
992 [b i = 0] (mod (PROD j : A - {i}. m j))" |
|
993 by blast |
|
994 let ?x = "SUM i:A. (u i) * (b i)" |
|
995 show "?thesis" |
|
996 proof (rule exI, clarify) |
|
997 fix i |
|
998 assume a: "i : A" |
|
999 show "[?x = u i] (mod m i)" |
|
1000 proof - |
|
1001 from fin a have "?x = (SUM j:{i}. u j * b j) + |
|
1002 (SUM j:A-{i}. u j * b j)" |
|
1003 by (subst setsum_Un_disjoint [symmetric], auto intro: setsum_cong) |
|
1004 hence "[?x = u i * b i + (SUM j:A-{i}. u j * b j)] (mod m i)" |
|
1005 by auto |
|
1006 also have "[u i * b i + (SUM j:A-{i}. u j * b j) = |
|
1007 u i * 1 + (SUM j:A-{i}. u j * 0)] (mod m i)" |
|
1008 apply (rule nat_cong_add) |
|
1009 apply (rule nat_cong_scalar2) |
|
1010 using bprop a apply blast |
|
1011 apply (rule nat_cong_setsum) |
|
1012 apply (rule nat_cong_scalar2) |
|
1013 using bprop apply auto |
|
1014 apply (rule nat_cong_dvd_modulus) |
|
1015 apply (drule (1) bspec) |
|
1016 apply (erule conjE) |
|
1017 apply assumption |
|
1018 apply (rule dvd_setprod) |
|
1019 using fin a apply auto |
|
1020 done |
|
1021 finally show ?thesis |
|
1022 by simp |
|
1023 qed |
|
1024 qed |
|
1025 qed |
|
1026 |
|
1027 lemma nat_coprime_cong_prod [rule_format]: "finite A \<Longrightarrow> |
|
1028 (ALL i: A. (ALL j: A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow> |
|
1029 (ALL i: A. [(x::nat) = y] (mod m i)) \<longrightarrow> |
|
1030 [x = y] (mod (PROD i:A. m i))" |
|
1031 apply (induct set: finite) |
|
1032 apply auto |
|
1033 apply (erule (1) nat_coprime_cong_mult) |
|
1034 apply (subst nat_gcd_commute) |
|
1035 apply (rule nat_setprod_coprime) |
|
1036 apply auto |
|
1037 done |
|
1038 |
|
1039 lemma nat_chinese_remainder_unique: |
|
1040 fixes A :: "'a set" and |
|
1041 m :: "'a \<Rightarrow> nat" and |
|
1042 u :: "'a \<Rightarrow> nat" |
|
1043 assumes |
|
1044 fin: "finite A" and |
|
1045 nz: "ALL i:A. m i \<noteq> 0" and |
|
1046 cop: "ALL i:A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))" |
|
1047 shows "EX! x. x < (PROD i:A. m i) \<and> (ALL i:A. [x = u i] (mod m i))" |
|
1048 proof - |
|
1049 from nat_chinese_remainder [OF fin cop] obtain y where |
|
1050 one: "(ALL i:A. [y = u i] (mod m i))" |
|
1051 by blast |
|
1052 let ?x = "y mod (PROD i:A. m i)" |
|
1053 from fin nz have prodnz: "(PROD i:A. m i) \<noteq> 0" |
|
1054 by auto |
|
1055 hence less: "?x < (PROD i:A. m i)" |
|
1056 by auto |
|
1057 have cong: "ALL i:A. [?x = u i] (mod m i)" |
|
1058 apply auto |
|
1059 apply (rule nat_cong_trans) |
|
1060 prefer 2 |
|
1061 using one apply auto |
|
1062 apply (rule nat_cong_dvd_modulus) |
|
1063 apply (rule nat_cong_mod) |
|
1064 using prodnz apply auto |
|
1065 apply (rule dvd_setprod) |
|
1066 apply (rule fin) |
|
1067 apply assumption |
|
1068 done |
|
1069 have unique: "ALL z. z < (PROD i:A. m i) \<and> |
|
1070 (ALL i:A. [z = u i] (mod m i)) \<longrightarrow> z = ?x" |
|
1071 proof (clarify) |
|
1072 fix z |
|
1073 assume zless: "z < (PROD i:A. m i)" |
|
1074 assume zcong: "(ALL i:A. [z = u i] (mod m i))" |
|
1075 have "ALL i:A. [?x = z] (mod m i)" |
|
1076 apply clarify |
|
1077 apply (rule nat_cong_trans) |
|
1078 using cong apply (erule bspec) |
|
1079 apply (rule nat_cong_sym) |
|
1080 using zcong apply auto |
|
1081 done |
|
1082 with fin cop have "[?x = z] (mod (PROD i:A. m i))" |
|
1083 by (intro nat_coprime_cong_prod, auto) |
|
1084 with zless less show "z = ?x" |
|
1085 apply (intro nat_cong_less_modulus_unique) |
|
1086 apply (auto, erule nat_cong_sym) |
|
1087 done |
|
1088 qed |
|
1089 from less cong unique show ?thesis |
|
1090 by blast |
|
1091 qed |
|
1092 |
|
1093 end |