author | haftmann |
Fri, 20 Oct 2017 20:57:55 +0200 | |
changeset 66888 | 930abfdf8727 |
parent 66837 | 6ba663ff2b1c |
child 66954 | 0230af0f3c59 |
permissions | -rw-r--r-- |
41959 | 1 |
(* Title: HOL/Number_Theory/Cong.thy |
66380 | 2 |
Author: Christophe Tabacznyj |
3 |
Author: Lawrence C. Paulson |
|
4 |
Author: Amine Chaieb |
|
5 |
Author: Thomas M. Rasmussen |
|
6 |
Author: Jeremy Avigad |
|
31719 | 7 |
|
8 |
Defines congruence (notation: [x = y] (mod z)) for natural numbers and |
|
9 |
integers. |
|
10 |
||
11 |
This file combines and revises a number of prior developments. |
|
12 |
||
13 |
The original theories "GCD" and "Primes" were by Christophe Tabacznyj |
|
58623 | 14 |
and Lawrence C. Paulson, based on @{cite davenport92}. They introduced |
31719 | 15 |
gcd, lcm, and prime for the natural numbers. |
16 |
||
17 |
The original theory "IntPrimes" was by Thomas M. Rasmussen, and |
|
18 |
extended gcd, lcm, primes to the integers. Amine Chaieb provided |
|
19 |
another extension of the notions to the integers, and added a number |
|
44872 | 20 |
of results to "Primes" and "GCD". |
31719 | 21 |
|
22 |
The original theory, "IntPrimes", by Thomas M. Rasmussen, defined and |
|
23 |
developed the congruence relations on the integers. The notion was |
|
33718 | 24 |
extended to the natural numbers by Chaieb. Jeremy Avigad combined |
31719 | 25 |
these, revised and tidied them, made the development uniform for the |
26 |
natural numbers and the integers, and added a number of new theorems. |
|
27 |
*) |
|
28 |
||
60526 | 29 |
section \<open>Congruence\<close> |
31719 | 30 |
|
31 |
theory Cong |
|
66453
cc19f7ca2ed6
session-qualified theory imports: isabelle imports -U -i -d '~~/src/Benchmarks' -a;
wenzelm
parents:
66380
diff
changeset
|
32 |
imports "HOL-Computational_Algebra.Primes" |
31719 | 33 |
begin |
34 |
||
66888 | 35 |
subsection \<open>Generic congruences\<close> |
36 |
||
37 |
context unique_euclidean_semiring |
|
31719 | 38 |
begin |
39 |
||
66888 | 40 |
definition cong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ = _] '(()mod _'))") |
41 |
where "cong b c a \<longleftrightarrow> b mod a = c mod a" |
|
42 |
||
58937 | 43 |
abbreviation notcong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ \<noteq> _] '(()mod _'))") |
66888 | 44 |
where "notcong b c a \<equiv> \<not> cong b c a" |
45 |
||
46 |
lemma cong_mod_left [simp]: |
|
47 |
"[b mod a = c] (mod a) \<longleftrightarrow> [b = c] (mod a)" |
|
48 |
by (simp add: cong_def) |
|
49 |
||
50 |
lemma cong_mod_right [simp]: |
|
51 |
"[b = c mod a] (mod a) \<longleftrightarrow> [b = c] (mod a)" |
|
52 |
by (simp add: cong_def) |
|
53 |
||
54 |
lemma cong_dvd_iff: |
|
55 |
"a dvd b \<longleftrightarrow> a dvd c" if "[b = c] (mod a)" |
|
56 |
using that by (auto simp: cong_def dvd_eq_mod_eq_0) |
|
57 |
||
58 |
lemma cong_0 [simp, presburger]: |
|
59 |
"[b = c] (mod 0) \<longleftrightarrow> b = c" |
|
60 |
by (simp add: cong_def) |
|
61 |
||
62 |
lemma cong_1 [simp, presburger]: |
|
63 |
"[b = c] (mod 1)" |
|
64 |
by (simp add: cong_def) |
|
65 |
||
66 |
lemma cong_refl [simp]: |
|
67 |
"[b = b] (mod a)" |
|
68 |
by (simp add: cong_def) |
|
69 |
||
70 |
lemma cong_sym: |
|
71 |
"[b = c] (mod a) \<Longrightarrow> [c = b] (mod a)" |
|
72 |
by (simp add: cong_def) |
|
73 |
||
74 |
lemma cong_sym_eq: |
|
75 |
"[b = c] (mod a) \<longleftrightarrow> [c = b] (mod a)" |
|
76 |
by (auto simp add: cong_def) |
|
77 |
||
78 |
lemma cong_trans [trans]: |
|
79 |
"[b = c] (mod a) \<Longrightarrow> [c = d] (mod a) \<Longrightarrow> [b = d] (mod a)" |
|
80 |
by (simp add: cong_def) |
|
81 |
||
82 |
lemma cong_add: |
|
83 |
"[b = c] (mod a) \<Longrightarrow> [d = e] (mod a) \<Longrightarrow> [b + d = c + e] (mod a)" |
|
84 |
by (auto simp add: cong_def intro: mod_add_cong) |
|
85 |
||
86 |
lemma cong_mult: |
|
87 |
"[b = c] (mod a) \<Longrightarrow> [d = e] (mod a) \<Longrightarrow> [b * d = c * e] (mod a)" |
|
88 |
by (auto simp add: cong_def intro: mod_mult_cong) |
|
89 |
||
90 |
lemma cong_pow: |
|
91 |
"[b = c] (mod a) \<Longrightarrow> [b ^ n = c ^ n] (mod a)" |
|
92 |
by (simp add: cong_def power_mod [symmetric, of b n a] power_mod [symmetric, of c n a]) |
|
93 |
||
94 |
lemma cong_sum: |
|
95 |
"[sum f A = sum g A] (mod a)" if "\<And>x. x \<in> A \<Longrightarrow> [f x = g x] (mod a)" |
|
96 |
using that by (induct A rule: infinite_finite_induct) (auto intro: cong_add) |
|
97 |
||
98 |
lemma cong_prod: |
|
99 |
"[prod f A = prod g A] (mod a)" if "(\<And>x. x \<in> A \<Longrightarrow> [f x = g x] (mod a))" |
|
100 |
using that by (induct A rule: infinite_finite_induct) (auto intro: cong_mult) |
|
101 |
||
102 |
lemma cong_scalar_right: |
|
103 |
"[b = c] (mod a) \<Longrightarrow> [b * d = c * d] (mod a)" |
|
104 |
by (simp add: cong_mult) |
|
105 |
||
106 |
lemma cong_scalar_left: |
|
107 |
"[b = c] (mod a) \<Longrightarrow> [d * b = d * c] (mod a)" |
|
108 |
by (simp add: cong_mult) |
|
109 |
||
110 |
lemma cong_mult_self_right: "[b * a = 0] (mod a)" |
|
111 |
by (simp add: cong_def) |
|
112 |
||
113 |
lemma cong_mult_self_left: "[a * b = 0] (mod a)" |
|
114 |
by (simp add: cong_def) |
|
115 |
||
116 |
lemma cong_0_iff: "[b = 0] (mod a) \<longleftrightarrow> a dvd b" |
|
117 |
by (simp add: cong_def dvd_eq_mod_eq_0) |
|
118 |
||
119 |
lemma mod_mult_cong_right: |
|
120 |
"[c mod (a * b) = d] (mod a) \<longleftrightarrow> [c = d] (mod a)" |
|
121 |
by (simp add: cong_def mod_mod_cancel mod_add_left_eq) |
|
122 |
||
123 |
lemma mod_mult_cong_left: |
|
124 |
"[c mod (b * a) = d] (mod a) \<longleftrightarrow> [c = d] (mod a)" |
|
125 |
using mod_mult_cong_right [of c a b d] by (simp add: ac_simps) |
|
126 |
||
127 |
end |
|
128 |
||
129 |
context unique_euclidean_ring |
|
130 |
begin |
|
131 |
||
132 |
lemma cong_diff: |
|
133 |
"[b = c] (mod a) \<Longrightarrow> [d = e] (mod a) \<Longrightarrow> [b - d = c - e] (mod a)" |
|
134 |
by (auto simp add: cong_def intro: mod_diff_cong) |
|
135 |
||
136 |
lemma cong_diff_iff_cong_0: |
|
137 |
"[b - c = 0] (mod a) \<longleftrightarrow> [b = c] (mod a)" (is "?P \<longleftrightarrow> ?Q") |
|
138 |
proof |
|
139 |
assume ?P |
|
140 |
then have "[b - c + c = 0 + c] (mod a)" |
|
141 |
by (rule cong_add) simp |
|
142 |
then show ?Q |
|
143 |
by simp |
|
144 |
next |
|
145 |
assume ?Q |
|
146 |
with cong_diff [of b c a c c] show ?P |
|
147 |
by simp |
|
148 |
qed |
|
149 |
||
150 |
lemma cong_minus_minus_iff: |
|
151 |
"[- b = - c] (mod a) \<longleftrightarrow> [b = c] (mod a)" |
|
152 |
using cong_diff_iff_cong_0 [of b c a] cong_diff_iff_cong_0 [of "- b" "- c" a] |
|
153 |
by (simp add: cong_0_iff dvd_diff_commute) |
|
154 |
||
155 |
lemma cong_modulus_minus_iff: "[b = c] (mod - a) \<longleftrightarrow> [b = c] (mod a)" |
|
156 |
using cong_diff_iff_cong_0 [of b c a] cong_diff_iff_cong_0 [of b c " -a"] |
|
157 |
by (simp add: cong_0_iff) |
|
31719 | 158 |
|
159 |
end |
|
160 |
||
66380 | 161 |
|
66888 | 162 |
subsection \<open>Congruences on @{typ nat} and @{typ int}\<close> |
31719 | 163 |
|
164 |
lemma transfer_nat_int_cong: |
|
66380 | 165 |
"x \<ge> 0 \<Longrightarrow> y \<ge> 0 \<Longrightarrow> m \<ge> 0 \<Longrightarrow> [nat x = nat y] (mod (nat m)) \<longleftrightarrow> [x = y] (mod m)" |
166 |
for x y m :: int |
|
66888 | 167 |
by (auto simp add: cong_def nat_mod_distrib [symmetric]) |
168 |
(metis eq_nat_nat_iff le_less mod_by_0 pos_mod_conj) |
|
31719 | 169 |
|
66380 | 170 |
declare transfer_morphism_nat_int [transfer add return: transfer_nat_int_cong] |
31719 | 171 |
|
66888 | 172 |
lemma cong_int_iff: |
173 |
"[int m = int q] (mod int n) \<longleftrightarrow> [m = q] (mod n)" |
|
174 |
by (simp add: cong_def of_nat_mod [symmetric]) |
|
175 |
||
176 |
lemma transfer_int_nat_cong: |
|
177 |
"[int x = int y] (mod (int m)) = [x = y] (mod m)" |
|
178 |
by (fact cong_int_iff) |
|
31719 | 179 |
|
66380 | 180 |
declare transfer_morphism_int_nat [transfer add return: transfer_int_nat_cong] |
31719 | 181 |
|
66888 | 182 |
lemma cong_Suc_0 [simp, presburger]: |
183 |
"[m = n] (mod Suc 0)" |
|
184 |
using cong_1 [of m n] by simp |
|
31719 | 185 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
186 |
lemma cong_diff_aux_int: |
66380 | 187 |
"[a = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> |
188 |
a \<ge> c \<Longrightarrow> b \<ge> d \<Longrightarrow> [tsub a c = tsub b d] (mod m)" |
|
189 |
for a b c d :: int |
|
66888 | 190 |
by (metis cong_diff tsub_eq) |
31719 | 191 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
192 |
lemma cong_diff_nat: |
66888 | 193 |
"[a - c = b - d] (mod m)" if "[a = b] (mod m)" "[c = d] (mod m)" |
194 |
and "a \<ge> c" "b \<ge> d" for a b c d m :: nat |
|
195 |
using that by (rule cong_diff_aux_int [transferred]) |
|
31719 | 196 |
|
66888 | 197 |
lemma cong_diff_iff_cong_0_aux_int: "a \<ge> b \<Longrightarrow> [tsub a b = 0] (mod m) = [a = b] (mod m)" |
198 |
for a b :: int |
|
199 |
by (subst tsub_eq, assumption, rule cong_diff_iff_cong_0) |
|
31719 | 200 |
|
66888 | 201 |
lemma cong_diff_iff_cong_0_nat: |
66380 | 202 |
fixes a b :: nat |
203 |
assumes "a \<ge> b" |
|
66888 | 204 |
shows "[a - b = 0] (mod m) = [a = b] (mod m)" |
205 |
using assms by (rule cong_diff_iff_cong_0_aux_int [transferred]) |
|
31719 | 206 |
|
66380 | 207 |
lemma cong_altdef_nat: "a \<ge> b \<Longrightarrow> [a = b] (mod m) \<longleftrightarrow> m dvd (a - b)" |
208 |
for a b :: nat |
|
66888 | 209 |
by (simp add: cong_0_iff [symmetric] cong_diff_iff_cong_0_nat) |
31719 | 210 |
|
66380 | 211 |
lemma cong_altdef_int: "[a = b] (mod m) \<longleftrightarrow> m dvd (a - b)" |
212 |
for a b :: int |
|
66888 | 213 |
by (simp add: cong_0_iff [symmetric] cong_diff_iff_cong_0) |
31719 | 214 |
|
66888 | 215 |
lemma cong_abs_int [simp]: "[x = y] (mod abs m) \<longleftrightarrow> [x = y] (mod m)" |
66380 | 216 |
for x y :: int |
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
217 |
by (simp add: cong_altdef_int) |
31719 | 218 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
219 |
lemma cong_square_int: |
66380 | 220 |
"prime p \<Longrightarrow> 0 < a \<Longrightarrow> [a * a = 1] (mod p) \<Longrightarrow> [a = 1] (mod p) \<or> [a = - 1] (mod p)" |
221 |
for a :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
222 |
apply (simp only: cong_altdef_int) |
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
223 |
apply (subst prime_dvd_mult_eq_int [symmetric], assumption) |
36350 | 224 |
apply (auto simp add: field_simps) |
44872 | 225 |
done |
31719 | 226 |
|
66380 | 227 |
lemma cong_mult_rcancel_int: "coprime k m \<Longrightarrow> [a * k = b * k] (mod m) = [a = b] (mod m)" |
228 |
for a k m :: int |
|
62353
7f927120b5a2
dropped various legacy fact bindings and tuned proofs
haftmann
parents:
62349
diff
changeset
|
229 |
by (metis cong_altdef_int left_diff_distrib coprime_dvd_mult_iff gcd.commute) |
31719 | 230 |
|
66380 | 231 |
lemma cong_mult_rcancel_nat: "coprime k m \<Longrightarrow> [a * k = b * k] (mod m) = [a = b] (mod m)" |
232 |
for a k m :: nat |
|
55371 | 233 |
by (metis cong_mult_rcancel_int [transferred]) |
31719 | 234 |
|
66380 | 235 |
lemma cong_mult_lcancel_nat: "coprime k m \<Longrightarrow> [k * a = k * b ] (mod m) = [a = b] (mod m)" |
236 |
for a k m :: nat |
|
57512
cc97b347b301
reduced name variants for assoc and commute on plus and mult
haftmann
parents:
57418
diff
changeset
|
237 |
by (simp add: mult.commute cong_mult_rcancel_nat) |
31719 | 238 |
|
66380 | 239 |
lemma cong_mult_lcancel_int: "coprime k m \<Longrightarrow> [k * a = k * b] (mod m) = [a = b] (mod m)" |
240 |
for a k m :: int |
|
57512
cc97b347b301
reduced name variants for assoc and commute on plus and mult
haftmann
parents:
57418
diff
changeset
|
241 |
by (simp add: mult.commute cong_mult_rcancel_int) |
31719 | 242 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
243 |
lemma coprime_cong_mult_int: |
66380 | 244 |
"[a = b] (mod m) \<Longrightarrow> [a = b] (mod n) \<Longrightarrow> coprime m n \<Longrightarrow> [a = b] (mod m * n)" |
245 |
for a b :: int |
|
246 |
by (metis divides_mult cong_altdef_int) |
|
31719 | 247 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
248 |
lemma coprime_cong_mult_nat: |
66380 | 249 |
"[a = b] (mod m) \<Longrightarrow> [a = b] (mod n) \<Longrightarrow> coprime m n \<Longrightarrow> [a = b] (mod m * n)" |
250 |
for a b :: nat |
|
251 |
by (metis coprime_cong_mult_int [transferred]) |
|
31719 | 252 |
|
66380 | 253 |
lemma cong_less_imp_eq_nat: "0 \<le> a \<Longrightarrow> a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b" |
254 |
for a b :: nat |
|
66888 | 255 |
by (auto simp add: cong_def) |
31719 | 256 |
|
66380 | 257 |
lemma cong_less_imp_eq_int: "0 \<le> a \<Longrightarrow> a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b" |
258 |
for a b :: int |
|
66888 | 259 |
by (auto simp add: cong_def) |
31719 | 260 |
|
66380 | 261 |
lemma cong_less_unique_nat: "0 < m \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))" |
262 |
for a m :: nat |
|
66888 | 263 |
by (auto simp: cong_def) (metis mod_less_divisor mod_mod_trivial) |
31719 | 264 |
|
66380 | 265 |
lemma cong_less_unique_int: "0 < m \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))" |
266 |
for a m :: int |
|
66888 | 267 |
by (auto simp: cong_def) (metis mod_mod_trivial pos_mod_conj) |
31719 | 268 |
|
66380 | 269 |
lemma cong_iff_lin_int: "[a = b] (mod m) \<longleftrightarrow> (\<exists>k. b = a + m * k)" |
270 |
for a b :: int |
|
66837 | 271 |
by (auto simp add: cong_altdef_int algebra_simps elim!: dvdE) |
272 |
(simp add: distrib_right [symmetric] add_eq_0_iff) |
|
31719 | 273 |
|
66380 | 274 |
lemma cong_iff_lin_nat: "([a = b] (mod m)) \<longleftrightarrow> (\<exists>k1 k2. b + k1 * m = a + k2 * m)" |
275 |
(is "?lhs = ?rhs") |
|
276 |
for a b :: nat |
|
277 |
proof |
|
278 |
assume ?lhs |
|
55371 | 279 |
show ?rhs |
280 |
proof (cases "b \<le> a") |
|
281 |
case True |
|
66380 | 282 |
with \<open>?lhs\<close> show ?rhs |
57512
cc97b347b301
reduced name variants for assoc and commute on plus and mult
haftmann
parents:
57418
diff
changeset
|
283 |
by (metis cong_altdef_nat dvd_def le_add_diff_inverse add_0_right mult_0 mult.commute) |
55371 | 284 |
next |
285 |
case False |
|
66380 | 286 |
with \<open>?lhs\<close> show ?rhs |
66888 | 287 |
by (metis cong_def mult.commute nat_le_linear nat_mod_eq_lemma) |
55371 | 288 |
qed |
289 |
next |
|
290 |
assume ?rhs |
|
291 |
then show ?lhs |
|
66888 | 292 |
by (metis cong_def mult.commute nat_mod_eq_iff) |
55371 | 293 |
qed |
31719 | 294 |
|
66380 | 295 |
lemma cong_gcd_eq_int: "[a = b] (mod m) \<Longrightarrow> gcd a m = gcd b m" |
296 |
for a b :: int |
|
66888 | 297 |
by (auto simp add: cong_def) (metis gcd_red_int) |
31719 | 298 |
|
66380 | 299 |
lemma cong_gcd_eq_nat: "[a = b] (mod m) \<Longrightarrow> gcd a m = gcd b m" |
300 |
for a b :: nat |
|
63092 | 301 |
by (metis cong_gcd_eq_int [transferred]) |
31719 | 302 |
|
66380 | 303 |
lemma cong_imp_coprime_nat: "[a = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> coprime b m" |
304 |
for a b :: nat |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
305 |
by (auto simp add: cong_gcd_eq_nat) |
31719 | 306 |
|
66380 | 307 |
lemma cong_imp_coprime_int: "[a = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> coprime b m" |
308 |
for a b :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
309 |
by (auto simp add: cong_gcd_eq_int) |
31719 | 310 |
|
66380 | 311 |
lemma cong_cong_mod_nat: "[a = b] (mod m) \<longleftrightarrow> [a mod m = b mod m] (mod m)" |
312 |
for a b :: nat |
|
66888 | 313 |
by simp |
31719 | 314 |
|
66380 | 315 |
lemma cong_cong_mod_int: "[a = b] (mod m) \<longleftrightarrow> [a mod m = b mod m] (mod m)" |
316 |
for a b :: int |
|
66888 | 317 |
by simp |
31719 | 318 |
|
66380 | 319 |
lemma cong_minus_int [iff]: "[a = b] (mod - m) \<longleftrightarrow> [a = b] (mod m)" |
320 |
for a b :: int |
|
55371 | 321 |
by (metis cong_iff_lin_int minus_equation_iff mult_minus_left mult_minus_right) |
31719 | 322 |
|
323 |
(* |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
324 |
lemma mod_dvd_mod_int: |
31719 | 325 |
"0 < (m::int) \<Longrightarrow> m dvd b \<Longrightarrow> (a mod b mod m) = (a mod m)" |
326 |
apply (unfold dvd_def, auto) |
|
327 |
apply (rule mod_mod_cancel) |
|
328 |
apply auto |
|
44872 | 329 |
done |
31719 | 330 |
|
331 |
lemma mod_dvd_mod: |
|
332 |
assumes "0 < (m::nat)" and "m dvd b" |
|
333 |
shows "(a mod b mod m) = (a mod m)" |
|
334 |
||
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
335 |
apply (rule mod_dvd_mod_int [transferred]) |
41541 | 336 |
using assms apply auto |
337 |
done |
|
31719 | 338 |
*) |
339 |
||
66380 | 340 |
lemma cong_add_lcancel_nat: "[a + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
341 |
for a x y :: nat |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
342 |
by (simp add: cong_iff_lin_nat) |
31719 | 343 |
|
66380 | 344 |
lemma cong_add_lcancel_int: "[a + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
345 |
for a x y :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
346 |
by (simp add: cong_iff_lin_int) |
31719 | 347 |
|
66380 | 348 |
lemma cong_add_rcancel_nat: "[x + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
349 |
for a x y :: nat |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
350 |
by (simp add: cong_iff_lin_nat) |
31719 | 351 |
|
66380 | 352 |
lemma cong_add_rcancel_int: "[x + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)" |
353 |
for a x y :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
354 |
by (simp add: cong_iff_lin_int) |
31719 | 355 |
|
66380 | 356 |
lemma cong_add_lcancel_0_nat: "[a + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
357 |
for a x :: nat |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
358 |
by (simp add: cong_iff_lin_nat) |
31719 | 359 |
|
66380 | 360 |
lemma cong_add_lcancel_0_int: "[a + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
361 |
for a x :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
362 |
by (simp add: cong_iff_lin_int) |
31719 | 363 |
|
66380 | 364 |
lemma cong_add_rcancel_0_nat: "[x + a = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
365 |
for a x :: nat |
|
366 |
by (simp add: cong_iff_lin_nat) |
|
367 |
||
368 |
lemma cong_add_rcancel_0_int: "[x + a = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" |
|
369 |
for a x :: int |
|
370 |
by (simp add: cong_iff_lin_int) |
|
371 |
||
372 |
lemma cong_dvd_modulus_nat: "[x = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> [x = y] (mod n)" |
|
373 |
for x y :: nat |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
374 |
apply (auto simp add: cong_iff_lin_nat dvd_def) |
66380 | 375 |
apply (rule_tac x= "k1 * k" in exI) |
376 |
apply (rule_tac x= "k2 * k" in exI) |
|
36350 | 377 |
apply (simp add: field_simps) |
44872 | 378 |
done |
31719 | 379 |
|
66380 | 380 |
lemma cong_dvd_modulus_int: "[x = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> [x = y] (mod n)" |
381 |
for x y :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
382 |
by (auto simp add: cong_altdef_int dvd_def) |
31719 | 383 |
|
66380 | 384 |
lemma cong_to_1_nat: |
385 |
fixes a :: nat |
|
386 |
assumes "[a = 1] (mod n)" |
|
387 |
shows "n dvd (a - 1)" |
|
388 |
proof (cases "a = 0") |
|
389 |
case True |
|
390 |
then show ?thesis by force |
|
391 |
next |
|
392 |
case False |
|
393 |
with assms show ?thesis by (metis cong_altdef_nat leI less_one) |
|
394 |
qed |
|
395 |
||
396 |
lemma cong_0_1_nat': "[0 = Suc 0] (mod n) \<longleftrightarrow> n = Suc 0" |
|
66888 | 397 |
by (auto simp: cong_def) |
66380 | 398 |
|
399 |
lemma cong_0_1_nat: "[0 = 1] (mod n) \<longleftrightarrow> n = 1" |
|
400 |
for n :: nat |
|
66888 | 401 |
by (auto simp: cong_def) |
66380 | 402 |
|
403 |
lemma cong_0_1_int: "[0 = 1] (mod n) \<longleftrightarrow> n = 1 \<or> n = - 1" |
|
404 |
for n :: int |
|
66888 | 405 |
by (auto simp: cong_def zmult_eq_1_iff) |
66380 | 406 |
|
407 |
lemma cong_to_1'_nat: "[a = 1] (mod n) \<longleftrightarrow> a = 0 \<and> n = 1 \<or> (\<exists>m. a = 1 + m * n)" |
|
408 |
for a :: nat |
|
409 |
by (metis add.right_neutral cong_0_1_nat cong_iff_lin_nat cong_to_1_nat |
|
410 |
dvd_div_mult_self leI le_add_diff_inverse less_one mult_eq_if) |
|
411 |
||
412 |
lemma cong_le_nat: "y \<le> x \<Longrightarrow> [x = y] (mod n) \<longleftrightarrow> (\<exists>q. x = q * n + y)" |
|
413 |
for x y :: nat |
|
66837 | 414 |
by (auto simp add: cong_altdef_nat le_imp_diff_is_add elim!: dvdE) |
66380 | 415 |
|
416 |
lemma cong_solve_nat: |
|
417 |
fixes a :: nat |
|
418 |
assumes "a \<noteq> 0" |
|
419 |
shows "\<exists>x. [a * x = gcd a n] (mod n)" |
|
420 |
proof (cases "n = 0") |
|
421 |
case True |
|
422 |
then show ?thesis by force |
|
423 |
next |
|
424 |
case False |
|
425 |
then show ?thesis |
|
426 |
using bezout_nat [of a n, OF \<open>a \<noteq> 0\<close>] |
|
66888 | 427 |
by auto (metis cong_add_rcancel_0_nat cong_mult_self_left) |
66380 | 428 |
qed |
429 |
||
430 |
lemma cong_solve_int: "a \<noteq> 0 \<Longrightarrow> \<exists>x. [a * x = gcd a n] (mod n)" |
|
431 |
for a :: int |
|
432 |
apply (cases "n = 0") |
|
433 |
apply (cases "a \<ge> 0") |
|
434 |
apply auto |
|
435 |
apply (rule_tac x = "-1" in exI) |
|
436 |
apply auto |
|
437 |
apply (insert bezout_int [of a n], auto) |
|
438 |
apply (metis cong_iff_lin_int mult.commute) |
|
44872 | 439 |
done |
31719 | 440 |
|
44872 | 441 |
lemma cong_solve_dvd_nat: |
66380 | 442 |
fixes a :: nat |
443 |
assumes a: "a \<noteq> 0" and b: "gcd a n dvd d" |
|
444 |
shows "\<exists>x. [a * x = d] (mod n)" |
|
31719 | 445 |
proof - |
44872 | 446 |
from cong_solve_nat [OF a] obtain x where "[a * x = gcd a n](mod n)" |
31719 | 447 |
by auto |
44872 | 448 |
then have "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" |
66888 | 449 |
using cong_scalar_left by blast |
31719 | 450 |
also from b have "(d div gcd a n) * gcd a n = d" |
451 |
by (rule dvd_div_mult_self) |
|
452 |
also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)" |
|
453 |
by auto |
|
454 |
finally show ?thesis |
|
455 |
by auto |
|
456 |
qed |
|
457 |
||
44872 | 458 |
lemma cong_solve_dvd_int: |
31719 | 459 |
assumes a: "(a::int) \<noteq> 0" and b: "gcd a n dvd d" |
66380 | 460 |
shows "\<exists>x. [a * x = d] (mod n)" |
31719 | 461 |
proof - |
44872 | 462 |
from cong_solve_int [OF a] obtain x where "[a * x = gcd a n](mod n)" |
31719 | 463 |
by auto |
44872 | 464 |
then have "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" |
66888 | 465 |
using cong_scalar_left by blast |
31719 | 466 |
also from b have "(d div gcd a n) * gcd a n = d" |
467 |
by (rule dvd_div_mult_self) |
|
468 |
also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)" |
|
469 |
by auto |
|
470 |
finally show ?thesis |
|
471 |
by auto |
|
472 |
qed |
|
473 |
||
66380 | 474 |
lemma cong_solve_coprime_nat: |
475 |
fixes a :: nat |
|
476 |
assumes "coprime a n" |
|
477 |
shows "\<exists>x. [a * x = 1] (mod n)" |
|
478 |
proof (cases "a = 0") |
|
479 |
case True |
|
66888 | 480 |
with assms show ?thesis |
481 |
by (simp add: cong_0_1_nat') |
|
66380 | 482 |
next |
483 |
case False |
|
66888 | 484 |
with assms show ?thesis |
485 |
by (metis cong_solve_nat) |
|
66380 | 486 |
qed |
31719 | 487 |
|
66380 | 488 |
lemma cong_solve_coprime_int: "coprime (a::int) n \<Longrightarrow> \<exists>x. [a * x = 1] (mod n)" |
44872 | 489 |
apply (cases "a = 0") |
66380 | 490 |
apply auto |
491 |
apply (cases "n \<ge> 0") |
|
492 |
apply auto |
|
55161 | 493 |
apply (metis cong_solve_int) |
494 |
done |
|
495 |
||
62349
7c23469b5118
cleansed junk-producing interpretations for gcd/lcm on nat altogether
haftmann
parents:
62348
diff
changeset
|
496 |
lemma coprime_iff_invertible_nat: |
66380 | 497 |
"m > 0 \<Longrightarrow> coprime a m = (\<exists>x. [a * x = Suc 0] (mod m))" |
62429
25271ff79171
Tuned Euclidean Rings/GCD rings
Manuel Eberl <eberlm@in.tum.de>
parents:
62353
diff
changeset
|
498 |
by (metis One_nat_def cong_gcd_eq_nat cong_solve_coprime_nat coprime_lmult gcd.commute gcd_Suc_0) |
66380 | 499 |
|
500 |
lemma coprime_iff_invertible_int: "m > 0 \<Longrightarrow> coprime a m \<longleftrightarrow> (\<exists>x. [a * x = 1] (mod m))" |
|
501 |
for m :: int |
|
55161 | 502 |
apply (auto intro: cong_solve_coprime_int) |
66888 | 503 |
using cong_gcd_eq_int coprime_mul_eq' apply fastforce |
44872 | 504 |
done |
31719 | 505 |
|
66380 | 506 |
lemma coprime_iff_invertible'_nat: |
507 |
"m > 0 \<Longrightarrow> coprime a m \<longleftrightarrow> (\<exists>x. 0 \<le> x \<and> x < m \<and> [a * x = Suc 0] (mod m))" |
|
55161 | 508 |
apply (subst coprime_iff_invertible_nat) |
66380 | 509 |
apply auto |
66888 | 510 |
apply (auto simp add: cong_def) |
55161 | 511 |
apply (metis mod_less_divisor mod_mult_right_eq) |
44872 | 512 |
done |
31719 | 513 |
|
66380 | 514 |
lemma coprime_iff_invertible'_int: |
515 |
"m > 0 \<Longrightarrow> coprime a m \<longleftrightarrow> (\<exists>x. 0 \<le> x \<and> x < m \<and> [a * x = 1] (mod m))" |
|
516 |
for m :: int |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
517 |
apply (subst coprime_iff_invertible_int) |
66888 | 518 |
apply (auto simp add: cong_def) |
55371 | 519 |
apply (metis mod_mult_right_eq pos_mod_conj) |
44872 | 520 |
done |
31719 | 521 |
|
66380 | 522 |
lemma cong_cong_lcm_nat: "[x = y] (mod a) \<Longrightarrow> [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)" |
523 |
for x y :: nat |
|
44872 | 524 |
apply (cases "y \<le> x") |
66888 | 525 |
apply (simp add: cong_altdef_nat) |
526 |
apply (meson cong_altdef_nat cong_sym lcm_least_iff nat_le_linear) |
|
44872 | 527 |
done |
31719 | 528 |
|
66380 | 529 |
lemma cong_cong_lcm_int: "[x = y] (mod a) \<Longrightarrow> [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)" |
530 |
for x y :: int |
|
531 |
by (auto simp add: cong_altdef_int lcm_least) |
|
31719 | 532 |
|
66888 | 533 |
lemma cong_cong_prod_coprime_nat: |
534 |
"[x = y] (mod (\<Prod>i\<in>A. m i))" if |
|
535 |
"(\<forall>i\<in>A. [(x::nat) = y] (mod m i))" |
|
536 |
and "(\<forall>i\<in>A. (\<forall>j\<in>A. i \<noteq> j \<longrightarrow> coprime (m i) (m j)))" |
|
537 |
using that apply (induct A rule: infinite_finite_induct) |
|
538 |
apply auto |
|
64272 | 539 |
apply (metis One_nat_def coprime_cong_mult_nat gcd.commute prod_coprime) |
44872 | 540 |
done |
31719 | 541 |
|
66888 | 542 |
lemma cong_cong_prod_coprime_int [rule_format]: |
543 |
"[x = y] (mod (\<Prod>i\<in>A. m i))" if |
|
544 |
"(\<forall>i\<in>A. [(x::int) = y] (mod m i))" |
|
545 |
"(\<forall>i\<in>A. (\<forall>j\<in>A. i \<noteq> j \<longrightarrow> coprime (m i) (m j)))" |
|
546 |
using that apply (induct A rule: infinite_finite_induct) |
|
31719 | 547 |
apply auto |
64272 | 548 |
apply (metis coprime_cong_mult_int gcd.commute prod_coprime) |
44872 | 549 |
done |
31719 | 550 |
|
44872 | 551 |
lemma binary_chinese_remainder_aux_nat: |
66380 | 552 |
fixes m1 m2 :: nat |
553 |
assumes a: "coprime m1 m2" |
|
554 |
shows "\<exists>b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and> [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)" |
|
31719 | 555 |
proof - |
66380 | 556 |
from cong_solve_coprime_nat [OF a] obtain x1 where 1: "[m1 * x1 = 1] (mod m2)" |
31719 | 557 |
by auto |
44872 | 558 |
from a have b: "coprime m2 m1" |
62348 | 559 |
by (subst gcd.commute) |
66380 | 560 |
from cong_solve_coprime_nat [OF b] obtain x2 where 2: "[m2 * x2 = 1] (mod m1)" |
31719 | 561 |
by auto |
562 |
have "[m1 * x1 = 0] (mod m1)" |
|
66888 | 563 |
by (simp add: cong_mult_self_left) |
31719 | 564 |
moreover have "[m2 * x2 = 0] (mod m2)" |
66888 | 565 |
by (simp add: cong_mult_self_left) |
66380 | 566 |
ultimately show ?thesis |
567 |
using 1 2 by blast |
|
31719 | 568 |
qed |
569 |
||
44872 | 570 |
lemma binary_chinese_remainder_aux_int: |
66380 | 571 |
fixes m1 m2 :: int |
572 |
assumes a: "coprime m1 m2" |
|
573 |
shows "\<exists>b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and> [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)" |
|
31719 | 574 |
proof - |
66380 | 575 |
from cong_solve_coprime_int [OF a] obtain x1 where 1: "[m1 * x1 = 1] (mod m2)" |
31719 | 576 |
by auto |
44872 | 577 |
from a have b: "coprime m2 m1" |
62348 | 578 |
by (subst gcd.commute) |
66380 | 579 |
from cong_solve_coprime_int [OF b] obtain x2 where 2: "[m2 * x2 = 1] (mod m1)" |
31719 | 580 |
by auto |
581 |
have "[m1 * x1 = 0] (mod m1)" |
|
66888 | 582 |
by (simp add: cong_mult_self_left) |
31719 | 583 |
moreover have "[m2 * x2 = 0] (mod m2)" |
66888 | 584 |
by (simp add: cong_mult_self_left) |
66380 | 585 |
ultimately show ?thesis |
586 |
using 1 2 by blast |
|
31719 | 587 |
qed |
588 |
||
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
589 |
lemma binary_chinese_remainder_nat: |
66380 | 590 |
fixes m1 m2 :: nat |
591 |
assumes a: "coprime m1 m2" |
|
592 |
shows "\<exists>x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)" |
|
31719 | 593 |
proof - |
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
594 |
from binary_chinese_remainder_aux_nat [OF a] obtain b1 b2 |
66380 | 595 |
where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" |
596 |
and "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)" |
|
31719 | 597 |
by blast |
598 |
let ?x = "u1 * b1 + u2 * b2" |
|
599 |
have "[?x = u1 * 1 + u2 * 0] (mod m1)" |
|
66888 | 600 |
using \<open>[b1 = 1] (mod m1)\<close> \<open>[b2 = 0] (mod m1)\<close> cong_add cong_scalar_left by blast |
44872 | 601 |
then have "[?x = u1] (mod m1)" by simp |
31719 | 602 |
have "[?x = u1 * 0 + u2 * 1] (mod m2)" |
66888 | 603 |
using \<open>[b1 = 0] (mod m2)\<close> \<open>[b2 = 1] (mod m2)\<close> cong_add cong_scalar_left by blast |
66380 | 604 |
then have "[?x = u2] (mod m2)" |
605 |
by simp |
|
606 |
with \<open>[?x = u1] (mod m1)\<close> show ?thesis |
|
607 |
by blast |
|
31719 | 608 |
qed |
609 |
||
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
610 |
lemma binary_chinese_remainder_int: |
66380 | 611 |
fixes m1 m2 :: int |
612 |
assumes a: "coprime m1 m2" |
|
613 |
shows "\<exists>x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)" |
|
31719 | 614 |
proof - |
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
615 |
from binary_chinese_remainder_aux_int [OF a] obtain b1 b2 |
66380 | 616 |
where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" |
617 |
and "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)" |
|
31719 | 618 |
by blast |
619 |
let ?x = "u1 * b1 + u2 * b2" |
|
620 |
have "[?x = u1 * 1 + u2 * 0] (mod m1)" |
|
66888 | 621 |
using \<open>[b1 = 1] (mod m1)\<close> \<open>[b2 = 0] (mod m1)\<close> cong_add cong_scalar_left by blast |
44872 | 622 |
then have "[?x = u1] (mod m1)" by simp |
31719 | 623 |
have "[?x = u1 * 0 + u2 * 1] (mod m2)" |
66888 | 624 |
using \<open>[b1 = 0] (mod m2)\<close> \<open>[b2 = 1] (mod m2)\<close> cong_add cong_scalar_left by blast |
44872 | 625 |
then have "[?x = u2] (mod m2)" by simp |
66380 | 626 |
with \<open>[?x = u1] (mod m1)\<close> show ?thesis |
627 |
by blast |
|
31719 | 628 |
qed |
629 |
||
66380 | 630 |
lemma cong_modulus_mult_nat: "[x = y] (mod m * n) \<Longrightarrow> [x = y] (mod m)" |
631 |
for x y :: nat |
|
44872 | 632 |
apply (cases "y \<le> x") |
66380 | 633 |
apply (simp add: cong_altdef_nat) |
634 |
apply (erule dvd_mult_left) |
|
66888 | 635 |
apply (rule cong_sym) |
636 |
apply (subst (asm) cong_sym_eq) |
|
44872 | 637 |
apply (simp add: cong_altdef_nat) |
31719 | 638 |
apply (erule dvd_mult_left) |
44872 | 639 |
done |
31719 | 640 |
|
66380 | 641 |
lemma cong_modulus_mult_int: "[x = y] (mod m * n) \<Longrightarrow> [x = y] (mod m)" |
642 |
for x y :: int |
|
44872 | 643 |
apply (simp add: cong_altdef_int) |
31719 | 644 |
apply (erule dvd_mult_left) |
44872 | 645 |
done |
31719 | 646 |
|
66380 | 647 |
lemma cong_less_modulus_unique_nat: "[x = y] (mod m) \<Longrightarrow> x < m \<Longrightarrow> y < m \<Longrightarrow> x = y" |
648 |
for x y :: nat |
|
66888 | 649 |
by (simp add: cong_def) |
31719 | 650 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
651 |
lemma binary_chinese_remainder_unique_nat: |
66380 | 652 |
fixes m1 m2 :: nat |
653 |
assumes a: "coprime m1 m2" |
|
44872 | 654 |
and nz: "m1 \<noteq> 0" "m2 \<noteq> 0" |
63901 | 655 |
shows "\<exists>!x. x < m1 * m2 \<and> [x = u1] (mod m1) \<and> [x = u2] (mod m2)" |
31719 | 656 |
proof - |
66380 | 657 |
from binary_chinese_remainder_nat [OF a] obtain y |
658 |
where "[y = u1] (mod m1)" and "[y = u2] (mod m2)" |
|
31719 | 659 |
by blast |
660 |
let ?x = "y mod (m1 * m2)" |
|
661 |
from nz have less: "?x < m1 * m2" |
|
44872 | 662 |
by auto |
66380 | 663 |
have 1: "[?x = u1] (mod m1)" |
66888 | 664 |
apply (rule cong_trans) |
66380 | 665 |
prefer 2 |
666 |
apply (rule \<open>[y = u1] (mod m1)\<close>) |
|
66888 | 667 |
apply (rule cong_modulus_mult_nat [of _ _ _ m2]) |
668 |
apply simp |
|
31719 | 669 |
done |
66380 | 670 |
have 2: "[?x = u2] (mod m2)" |
66888 | 671 |
apply (rule cong_trans) |
66380 | 672 |
prefer 2 |
673 |
apply (rule \<open>[y = u2] (mod m2)\<close>) |
|
57512
cc97b347b301
reduced name variants for assoc and commute on plus and mult
haftmann
parents:
57418
diff
changeset
|
674 |
apply (subst mult.commute) |
66888 | 675 |
apply (rule cong_modulus_mult_nat [of _ _ _ m1]) |
676 |
apply simp |
|
31719 | 677 |
done |
66380 | 678 |
have "\<forall>z. z < m1 * m2 \<and> [z = u1] (mod m1) \<and> [z = u2] (mod m2) \<longrightarrow> z = ?x" |
44872 | 679 |
proof clarify |
31719 | 680 |
fix z |
681 |
assume "z < m1 * m2" |
|
682 |
assume "[z = u1] (mod m1)" and "[z = u2] (mod m2)" |
|
683 |
have "[?x = z] (mod m1)" |
|
66888 | 684 |
apply (rule cong_trans) |
66380 | 685 |
apply (rule \<open>[?x = u1] (mod m1)\<close>) |
66888 | 686 |
apply (rule cong_sym) |
60526 | 687 |
apply (rule \<open>[z = u1] (mod m1)\<close>) |
31719 | 688 |
done |
689 |
moreover have "[?x = z] (mod m2)" |
|
66888 | 690 |
apply (rule cong_trans) |
66380 | 691 |
apply (rule \<open>[?x = u2] (mod m2)\<close>) |
66888 | 692 |
apply (rule cong_sym) |
60526 | 693 |
apply (rule \<open>[z = u2] (mod m2)\<close>) |
31719 | 694 |
done |
695 |
ultimately have "[?x = z] (mod m1 * m2)" |
|
66888 | 696 |
using a by (auto intro: coprime_cong_mult_nat simp add: mod_mult_cong_left mod_mult_cong_right) |
60526 | 697 |
with \<open>z < m1 * m2\<close> \<open>?x < m1 * m2\<close> show "z = ?x" |
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
698 |
apply (intro cong_less_modulus_unique_nat) |
66888 | 699 |
apply (auto, erule cong_sym) |
31719 | 700 |
done |
44872 | 701 |
qed |
66380 | 702 |
with less 1 2 show ?thesis by auto |
31719 | 703 |
qed |
704 |
||
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
705 |
lemma chinese_remainder_aux_nat: |
44872 | 706 |
fixes A :: "'a set" |
707 |
and m :: "'a \<Rightarrow> nat" |
|
708 |
assumes fin: "finite A" |
|
66380 | 709 |
and cop: "\<forall>i \<in> A. (\<forall>j \<in> A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))" |
710 |
shows "\<exists>b. (\<forall>i \<in> A. [b i = 1] (mod m i) \<and> [b i = 0] (mod (\<Prod>j \<in> A - {i}. m j)))" |
|
31719 | 711 |
proof (rule finite_set_choice, rule fin, rule ballI) |
712 |
fix i |
|
66380 | 713 |
assume "i \<in> A" |
61954 | 714 |
with cop have "coprime (\<Prod>j \<in> A - {i}. m j) (m i)" |
66380 | 715 |
by (intro prod_coprime) auto |
716 |
then have "\<exists>x. [(\<Prod>j \<in> A - {i}. m j) * x = 1] (mod m i)" |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
717 |
by (elim cong_solve_coprime_nat) |
61954 | 718 |
then obtain x where "[(\<Prod>j \<in> A - {i}. m j) * x = 1] (mod m i)" |
31719 | 719 |
by auto |
66380 | 720 |
moreover have "[(\<Prod>j \<in> A - {i}. m j) * x = 0] (mod (\<Prod>j \<in> A - {i}. m j))" |
66888 | 721 |
by (simp add: cong_0_iff) |
66380 | 722 |
ultimately show "\<exists>a. [a = 1] (mod m i) \<and> [a = 0] (mod prod m (A - {i}))" |
31719 | 723 |
by blast |
724 |
qed |
|
725 |
||
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
726 |
lemma chinese_remainder_nat: |
44872 | 727 |
fixes A :: "'a set" |
728 |
and m :: "'a \<Rightarrow> nat" |
|
729 |
and u :: "'a \<Rightarrow> nat" |
|
730 |
assumes fin: "finite A" |
|
66380 | 731 |
and cop: "\<forall>i \<in> A. \<forall>j \<in> A. i \<noteq> j \<longrightarrow> coprime (m i) (m j)" |
732 |
shows "\<exists>x. \<forall>i \<in> A. [x = u i] (mod m i)" |
|
31719 | 733 |
proof - |
66380 | 734 |
from chinese_remainder_aux_nat [OF fin cop] |
735 |
obtain b where b: "\<forall>i \<in> A. [b i = 1] (mod m i) \<and> [b i = 0] (mod (\<Prod>j \<in> A - {i}. m j))" |
|
31719 | 736 |
by blast |
61954 | 737 |
let ?x = "\<Sum>i\<in>A. (u i) * (b i)" |
66380 | 738 |
show ?thesis |
31719 | 739 |
proof (rule exI, clarify) |
740 |
fix i |
|
66380 | 741 |
assume a: "i \<in> A" |
44872 | 742 |
show "[?x = u i] (mod m i)" |
31719 | 743 |
proof - |
66380 | 744 |
from fin a have "?x = (\<Sum>j \<in> {i}. u j * b j) + (\<Sum>j \<in> A - {i}. u j * b j)" |
745 |
by (subst sum.union_disjoint [symmetric]) (auto intro: sum.cong) |
|
61954 | 746 |
then have "[?x = u i * b i + (\<Sum>j \<in> A - {i}. u j * b j)] (mod m i)" |
31719 | 747 |
by auto |
61954 | 748 |
also have "[u i * b i + (\<Sum>j \<in> A - {i}. u j * b j) = |
749 |
u i * 1 + (\<Sum>j \<in> A - {i}. u j * 0)] (mod m i)" |
|
66888 | 750 |
apply (rule cong_add) |
751 |
apply (rule cong_scalar_left) |
|
66380 | 752 |
using b a apply blast |
66888 | 753 |
apply (rule cong_sum) |
754 |
apply (rule cong_scalar_left) |
|
66380 | 755 |
using b apply auto |
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
756 |
apply (rule cong_dvd_modulus_nat) |
66380 | 757 |
apply (drule (1) bspec) |
758 |
apply (erule conjE) |
|
759 |
apply assumption |
|
59010 | 760 |
apply rule |
31719 | 761 |
using fin a apply auto |
762 |
done |
|
763 |
finally show ?thesis |
|
764 |
by simp |
|
765 |
qed |
|
766 |
qed |
|
767 |
qed |
|
768 |
||
66888 | 769 |
lemma coprime_cong_prod_nat: |
770 |
"[x = y] (mod (\<Prod>i\<in>A. m i))" |
|
771 |
if "\<forall>i\<in>A. (\<forall>j\<in>A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))" |
|
772 |
and "\<forall>i\<in>A. [x = y] (mod m i)" for x y :: nat |
|
773 |
using that apply (induct A rule: infinite_finite_induct) |
|
31719 | 774 |
apply auto |
64272 | 775 |
apply (metis One_nat_def coprime_cong_mult_nat gcd.commute prod_coprime) |
44872 | 776 |
done |
31719 | 777 |
|
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
778 |
lemma chinese_remainder_unique_nat: |
44872 | 779 |
fixes A :: "'a set" |
780 |
and m :: "'a \<Rightarrow> nat" |
|
781 |
and u :: "'a \<Rightarrow> nat" |
|
782 |
assumes fin: "finite A" |
|
61954 | 783 |
and nz: "\<forall>i\<in>A. m i \<noteq> 0" |
66380 | 784 |
and cop: "\<forall>i\<in>A. \<forall>j\<in>A. i \<noteq> j \<longrightarrow> coprime (m i) (m j)" |
63901 | 785 |
shows "\<exists>!x. x < (\<Prod>i\<in>A. m i) \<and> (\<forall>i\<in>A. [x = u i] (mod m i))" |
31719 | 786 |
proof - |
44872 | 787 |
from chinese_remainder_nat [OF fin cop] |
66380 | 788 |
obtain y where one: "(\<forall>i\<in>A. [y = u i] (mod m i))" |
31719 | 789 |
by blast |
61954 | 790 |
let ?x = "y mod (\<Prod>i\<in>A. m i)" |
791 |
from fin nz have prodnz: "(\<Prod>i\<in>A. m i) \<noteq> 0" |
|
31719 | 792 |
by auto |
61954 | 793 |
then have less: "?x < (\<Prod>i\<in>A. m i)" |
31719 | 794 |
by auto |
66380 | 795 |
have cong: "\<forall>i\<in>A. [?x = u i] (mod m i)" |
31719 | 796 |
apply auto |
66888 | 797 |
apply (rule cong_trans) |
66380 | 798 |
prefer 2 |
31719 | 799 |
using one apply auto |
66888 | 800 |
apply (rule cong_dvd_modulus_nat [of _ _ "prod m A"]) |
801 |
apply simp |
|
802 |
using fin apply auto |
|
31719 | 803 |
done |
66380 | 804 |
have unique: "\<forall>z. z < (\<Prod>i\<in>A. m i) \<and> (\<forall>i\<in>A. [z = u i] (mod m i)) \<longrightarrow> z = ?x" |
805 |
proof clarify |
|
31719 | 806 |
fix z |
61954 | 807 |
assume zless: "z < (\<Prod>i\<in>A. m i)" |
66380 | 808 |
assume zcong: "(\<forall>i\<in>A. [z = u i] (mod m i))" |
809 |
have "\<forall>i\<in>A. [?x = z] (mod m i)" |
|
44872 | 810 |
apply clarify |
66888 | 811 |
apply (rule cong_trans) |
31719 | 812 |
using cong apply (erule bspec) |
66888 | 813 |
apply (rule cong_sym) |
31719 | 814 |
using zcong apply auto |
815 |
done |
|
61954 | 816 |
with fin cop have "[?x = z] (mod (\<Prod>i\<in>A. m i))" |
44872 | 817 |
apply (intro coprime_cong_prod_nat) |
66380 | 818 |
apply auto |
44872 | 819 |
done |
31719 | 820 |
with zless less show "z = ?x" |
31952
40501bb2d57c
renamed lemmas: nat_xyz/int_xyz -> xyz_nat/xyz_int
nipkow
parents:
31792
diff
changeset
|
821 |
apply (intro cong_less_modulus_unique_nat) |
66380 | 822 |
apply auto |
66888 | 823 |
apply (erule cong_sym) |
31719 | 824 |
done |
44872 | 825 |
qed |
66380 | 826 |
from less cong unique show ?thesis |
827 |
by blast |
|
31719 | 828 |
qed |
829 |
||
830 |
end |