src/HOL/Number_Theory/Primes.thy
author eberlm <eberlm@in.tum.de>
Fri Jul 22 15:39:27 2016 +0200 (2016-07-22)
changeset 63535 6887fda4541a
parent 63534 523b488b15c9
child 63633 2accfb71e33b
permissions -rw-r--r--
Tuned primes
haftmann@32479
     1
(*  Authors:    Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb,
eberlm@63534
     2
                Thomas M. Rasmussen, Jeremy Avigad, Tobias Nipkow, 
eberlm@63534
     3
                Manuel Eberl
huffman@31706
     4
huffman@31706
     5
haftmann@32479
     6
This file deals with properties of primes. Definitions and lemmas are
haftmann@32479
     7
proved uniformly for the natural numbers and integers.
huffman@31706
     8
huffman@31706
     9
This file combines and revises a number of prior developments.
huffman@31706
    10
huffman@31706
    11
The original theories "GCD" and "Primes" were by Christophe Tabacznyj
wenzelm@58623
    12
and Lawrence C. Paulson, based on @{cite davenport92}. They introduced
huffman@31706
    13
gcd, lcm, and prime for the natural numbers.
huffman@31706
    14
huffman@31706
    15
The original theory "IntPrimes" was by Thomas M. Rasmussen, and
huffman@31706
    16
extended gcd, lcm, primes to the integers. Amine Chaieb provided
huffman@31706
    17
another extension of the notions to the integers, and added a number
huffman@31706
    18
of results to "Primes" and "GCD". IntPrimes also defined and developed
huffman@31706
    19
the congruence relations on the integers. The notion was extended to
webertj@33718
    20
the natural numbers by Chaieb.
huffman@31706
    21
avigad@32036
    22
Jeremy Avigad combined all of these, made everything uniform for the
avigad@32036
    23
natural numbers and the integers, and added a number of new theorems.
avigad@32036
    24
nipkow@31798
    25
Tobias Nipkow cleaned up a lot.
eberlm@63534
    26
eberlm@63534
    27
Florian Haftmann and Manuel Eberl put primality and prime factorisation
eberlm@63534
    28
onto an algebraic foundation and thus generalised these concepts to 
eberlm@63534
    29
other rings, such as polynomials. (see also the Factorial_Ring theory).
eberlm@63534
    30
eberlm@63534
    31
There were also previous formalisations of unique factorisation by 
eberlm@63534
    32
Thomas Marthedal Rasmussen, Jeremy Avigad, and David Gray.
wenzelm@21256
    33
*)
wenzelm@21256
    34
huffman@31706
    35
wenzelm@60526
    36
section \<open>Primes\<close>
wenzelm@21256
    37
haftmann@32479
    38
theory Primes
eberlm@63534
    39
imports "~~/src/HOL/Binomial" Euclidean_Algorithm
huffman@31706
    40
begin
huffman@31706
    41
eberlm@63534
    42
(* As a simp or intro rule,
eberlm@63534
    43
eberlm@63534
    44
     prime p \<Longrightarrow> p > 0
eberlm@63534
    45
eberlm@63534
    46
   wreaks havoc here. When the premise includes \<forall>x \<in># M. prime x, it
eberlm@63534
    47
   leads to the backchaining
eberlm@63534
    48
eberlm@63534
    49
     x > 0
eberlm@63534
    50
     prime x
eberlm@63534
    51
     x \<in># M   which is, unfortunately,
eberlm@63534
    52
     count M x > 0
eberlm@63534
    53
*)
eberlm@63534
    54
lp15@55242
    55
declare [[coercion int]]
lp15@55242
    56
declare [[coercion_enabled]]
huffman@31706
    57
eberlm@63534
    58
abbreviation (input) "prime \<equiv> is_prime"
eberlm@63534
    59
eberlm@63534
    60
lemma is_prime_elem_nat_iff:
eberlm@63534
    61
  "is_prime_elem (n :: nat) \<longleftrightarrow> (1 < n \<and> (\<forall>m. m dvd n \<longrightarrow> m = 1 \<or> m = n))"
eberlm@63534
    62
proof safe
eberlm@63534
    63
  assume *: "is_prime_elem n"
eberlm@63534
    64
  from * have "n \<noteq> 0" "n \<noteq> 1" by (intro notI, simp del: One_nat_def)+
eberlm@63534
    65
  thus "n > 1" by (cases n) simp_all
eberlm@63534
    66
  fix m assume m: "m dvd n" "m \<noteq> n"
eberlm@63534
    67
  from * \<open>m dvd n\<close> have "n dvd m \<or> is_unit m"
eberlm@63534
    68
    by (intro irreducibleD' prime_imp_irreducible)
eberlm@63534
    69
  with m show "m = 1" by (auto dest: dvd_antisym)
eberlm@63534
    70
next
eberlm@63534
    71
  assume "n > 1" "\<forall>m. m dvd n \<longrightarrow> m = 1 \<or> m = n"
eberlm@63534
    72
  thus "is_prime_elem n"
eberlm@63534
    73
    by (auto simp: prime_iff_irreducible irreducible_altdef)
eberlm@63534
    74
qed
eberlm@63534
    75
eberlm@63534
    76
lemma is_prime_nat_iff_is_prime_elem: "is_prime (n :: nat) \<longleftrightarrow> is_prime_elem n"
eberlm@63534
    77
  by (simp add: is_prime_def)
huffman@31706
    78
eberlm@63534
    79
lemma is_prime_nat_iff:
eberlm@63534
    80
  "is_prime (n :: nat) \<longleftrightarrow> (1 < n \<and> (\<forall>m. m dvd n \<longrightarrow> m = 1 \<or> m = n))"
eberlm@63534
    81
  by (simp add: is_prime_nat_iff_is_prime_elem is_prime_elem_nat_iff)
huffman@31706
    82
eberlm@63534
    83
lemma is_prime_elem_int_nat_transfer: "is_prime_elem (n::int) \<longleftrightarrow> is_prime_elem (nat (abs n))"
eberlm@63534
    84
proof
eberlm@63534
    85
  assume "is_prime_elem n"
eberlm@63534
    86
  thus "is_prime_elem (nat (abs n))" by (auto simp: is_prime_elem_def nat_dvd_iff)
eberlm@63534
    87
next
eberlm@63534
    88
  assume "is_prime_elem (nat (abs n))"
eberlm@63534
    89
  thus "is_prime_elem n"
eberlm@63534
    90
    by (auto simp: dvd_int_unfold_dvd_nat is_prime_elem_def abs_mult nat_mult_distrib)
eberlm@63534
    91
qed
eberlm@63534
    92
eberlm@63534
    93
lemma is_prime_elem_nat_int_transfer [simp]: "is_prime_elem (int n) \<longleftrightarrow> is_prime_elem n"
eberlm@63534
    94
  by (auto simp: is_prime_elem_int_nat_transfer)
eberlm@63534
    95
eberlm@63534
    96
lemma is_prime_nat_int_transfer [simp]: "is_prime (int n) \<longleftrightarrow> is_prime n"
eberlm@63534
    97
  by (auto simp: is_prime_elem_int_nat_transfer is_prime_def)
eberlm@63534
    98
eberlm@63534
    99
lemma is_prime_int_nat_transfer: "is_prime (n::int) \<longleftrightarrow> n \<ge> 0 \<and> is_prime (nat n)"
eberlm@63534
   100
  by (auto simp: is_prime_elem_int_nat_transfer is_prime_def)
huffman@31706
   101
eberlm@63534
   102
lemma is_prime_int_iff:
eberlm@63534
   103
  "is_prime (n::int) \<longleftrightarrow> (1 < n \<and> (\<forall>m. m \<ge> 0 \<and> m dvd n \<longrightarrow> m = 1 \<or> m = n))"
eberlm@63534
   104
proof (intro iffI conjI allI impI; (elim conjE)?)
eberlm@63534
   105
  assume *: "is_prime n"
eberlm@63534
   106
  hence irred: "irreducible n" by (simp add: prime_imp_irreducible)
eberlm@63534
   107
  from * have "n \<ge> 0" "n \<noteq> 0" "n \<noteq> 1" 
eberlm@63534
   108
    by (auto simp: is_prime_def zabs_def not_less split: if_splits)
eberlm@63534
   109
  thus "n > 1" by presburger
eberlm@63534
   110
  fix m assume "m dvd n" \<open>m \<ge> 0\<close>
eberlm@63534
   111
  with irred have "m dvd 1 \<or> n dvd m" by (auto simp: irreducible_altdef)
eberlm@63534
   112
  with \<open>m dvd n\<close> \<open>m \<ge> 0\<close> \<open>n > 1\<close> show "m = 1 \<or> m = n"
eberlm@63534
   113
    using associated_iff_dvd[of m n] by auto
eberlm@63534
   114
next
eberlm@63534
   115
  assume n: "1 < n" "\<forall>m. m \<ge> 0 \<and> m dvd n \<longrightarrow> m = 1 \<or> m = n"
eberlm@63534
   116
  hence "nat n > 1" by simp
eberlm@63534
   117
  moreover have "\<forall>m. m dvd nat n \<longrightarrow> m = 1 \<or> m = nat n"
eberlm@63534
   118
  proof (intro allI impI)
eberlm@63534
   119
    fix m assume "m dvd nat n"
eberlm@63534
   120
    with \<open>n > 1\<close> have "int m dvd n" by (auto simp: int_dvd_iff)
eberlm@63534
   121
    with n(2) have "int m = 1 \<or> int m = n" by auto
eberlm@63534
   122
    thus "m = 1 \<or> m = nat n" by auto
eberlm@63534
   123
  qed
eberlm@63534
   124
  ultimately show "is_prime n" 
eberlm@63534
   125
    unfolding is_prime_int_nat_transfer is_prime_nat_iff by auto
eberlm@63534
   126
qed
chaieb@22027
   127
eberlm@63534
   128
eberlm@63534
   129
lemma prime_nat_not_dvd:
eberlm@63534
   130
  assumes "prime p" "p > n" "n \<noteq> (1::nat)"
eberlm@63534
   131
  shows   "\<not>n dvd p"
eberlm@63534
   132
proof
eberlm@63534
   133
  assume "n dvd p"
eberlm@63534
   134
  from assms(1) have "irreducible p" by (simp add: prime_imp_irreducible)
eberlm@63534
   135
  from irreducibleD'[OF this \<open>n dvd p\<close>] \<open>n dvd p\<close> \<open>p > n\<close> assms show False
eberlm@63534
   136
    by (cases "n = 0") (auto dest!: dvd_imp_le)
eberlm@63534
   137
qed
chaieb@22027
   138
eberlm@63534
   139
lemma prime_int_not_dvd:
eberlm@63534
   140
  assumes "prime p" "p > n" "n > (1::int)"
eberlm@63534
   141
  shows   "\<not>n dvd p"
eberlm@63534
   142
proof
eberlm@63534
   143
  assume "n dvd p"
eberlm@63534
   144
  from assms(1) have "irreducible p" by (simp add: prime_imp_irreducible)
eberlm@63534
   145
  from irreducibleD'[OF this \<open>n dvd p\<close>] \<open>n dvd p\<close> \<open>p > n\<close> assms show False
eberlm@63534
   146
    by (auto dest!: zdvd_imp_le)
eberlm@63534
   147
qed
eberlm@63534
   148
eberlm@63534
   149
lemma prime_odd_nat: "prime p \<Longrightarrow> p > (2::nat) \<Longrightarrow> odd p"
eberlm@63534
   150
  by (intro prime_nat_not_dvd) auto
eberlm@63534
   151
eberlm@63534
   152
lemma prime_odd_int: "prime p \<Longrightarrow> p > (2::int) \<Longrightarrow> odd p"
eberlm@63534
   153
  by (intro prime_int_not_dvd) auto
wenzelm@22367
   154
eberlm@63534
   155
lemma prime_ge_0_int: "prime p \<Longrightarrow> p \<ge> (0::int)"
eberlm@63534
   156
  unfolding is_prime_int_iff by auto
eberlm@63534
   157
eberlm@63534
   158
lemma prime_gt_0_nat: "prime p \<Longrightarrow> p > (0::nat)"
eberlm@63534
   159
  unfolding is_prime_nat_iff by auto
eberlm@63534
   160
eberlm@63534
   161
lemma prime_gt_0_int: "prime p \<Longrightarrow> p > (0::int)"
eberlm@63534
   162
  unfolding is_prime_int_iff by auto
eberlm@63534
   163
eberlm@63534
   164
lemma prime_ge_1_nat: "prime p \<Longrightarrow> p \<ge> (1::nat)"
eberlm@63534
   165
  unfolding is_prime_nat_iff by auto
eberlm@63534
   166
eberlm@63534
   167
lemma prime_ge_Suc_0_nat: "prime p \<Longrightarrow> p \<ge> Suc 0"
eberlm@63534
   168
  unfolding is_prime_nat_iff by auto
eberlm@63534
   169
eberlm@63534
   170
lemma prime_ge_1_int: "prime p \<Longrightarrow> p \<ge> (1::int)"
eberlm@63534
   171
  unfolding is_prime_int_iff by auto
eberlm@63534
   172
eberlm@63534
   173
lemma prime_gt_1_nat: "prime p \<Longrightarrow> p > (1::nat)"
eberlm@63534
   174
  unfolding is_prime_nat_iff by auto
huffman@31706
   175
lp15@61762
   176
lemma prime_gt_Suc_0_nat: "prime p \<Longrightarrow> p > Suc 0"
eberlm@63534
   177
  unfolding is_prime_nat_iff by auto
huffman@31706
   178
eberlm@63534
   179
lemma prime_gt_1_int: "prime p \<Longrightarrow> p > (1::int)"
eberlm@63534
   180
  unfolding is_prime_int_iff by auto
huffman@31706
   181
eberlm@63534
   182
lemma prime_ge_2_nat: "prime p \<Longrightarrow> p \<ge> (2::nat)"
eberlm@63534
   183
  unfolding is_prime_nat_iff by auto
eberlm@63534
   184
eberlm@63534
   185
lemma prime_ge_2_int: "prime p \<Longrightarrow> p \<ge> (2::int)"
eberlm@63534
   186
  unfolding is_prime_int_iff by auto
huffman@31706
   187
lp15@59669
   188
lemma prime_int_altdef:
lp15@55242
   189
  "prime p = (1 < p \<and> (\<forall>m::int. m \<ge> 0 \<longrightarrow> m dvd p \<longrightarrow>
lp15@55242
   190
    m = 1 \<or> m = p))"
eberlm@63534
   191
  unfolding is_prime_int_iff by blast
chaieb@27568
   192
haftmann@62481
   193
lemma not_prime_eq_prod_nat:
eberlm@63534
   194
  assumes "m > 1" "\<not>prime (m::nat)"
eberlm@63534
   195
  shows   "\<exists>n k. n = m * k \<and> 1 < m \<and> m < n \<and> 1 < k \<and> k < n"
eberlm@63534
   196
  using assms irreducible_altdef[of m]
eberlm@63534
   197
  by (auto simp: prime_iff_irreducible is_prime_def irreducible_altdef)
huffman@53598
   198
huffman@53598
   199
wenzelm@60526
   200
subsubsection \<open>Make prime naively executable\<close>
nipkow@32007
   201
eberlm@63534
   202
lemma Suc_0_not_prime_nat [simp]: "~prime (Suc 0)"
eberlm@63534
   203
  unfolding One_nat_def [symmetric] by (rule not_is_prime_1)
nipkow@32007
   204
eberlm@63535
   205
lemma is_prime_nat_iff':
eberlm@63535
   206
  "prime (p :: nat) \<longleftrightarrow> p > 1 \<and> (\<forall>n \<in> {1<..<p}. ~ n dvd p)"
eberlm@63534
   207
proof safe
eberlm@63534
   208
  assume "p > 1" and *: "\<forall>n\<in>{1<..<p}. \<not>n dvd p"
eberlm@63534
   209
  show "is_prime p" unfolding is_prime_nat_iff
eberlm@63534
   210
  proof (intro conjI allI impI)
eberlm@63534
   211
    fix m assume "m dvd p"
eberlm@63534
   212
    with \<open>p > 1\<close> have "m \<noteq> 0" by (intro notI) auto
eberlm@63534
   213
    hence "m \<ge> 1" by simp
eberlm@63534
   214
    moreover from \<open>m dvd p\<close> and * have "m \<notin> {1<..<p}" by blast
eberlm@63534
   215
    with \<open>m dvd p\<close> and \<open>p > 1\<close> have "m \<le> 1 \<or> m = p" by (auto dest: dvd_imp_le)
eberlm@63534
   216
    ultimately show "m = 1 \<or> m = p" by simp
eberlm@63534
   217
  qed fact+
eberlm@63534
   218
qed (auto simp: is_prime_nat_iff)
nipkow@32007
   219
eberlm@63535
   220
lemma prime_nat_code [code_unfold]:
eberlm@63535
   221
  "(prime :: nat \<Rightarrow> bool) = (\<lambda>p. p > 1 \<and> (\<forall>n \<in> {1<..<p}. ~ n dvd p))"
eberlm@63535
   222
  by (rule ext, rule is_prime_nat_iff')
eberlm@63535
   223
eberlm@63535
   224
lemma is_prime_int_iff':
eberlm@63535
   225
  "prime (p :: int) \<longleftrightarrow> p > 1 \<and> (\<forall>n \<in> {1<..<p}. ~ n dvd p)" (is "?lhs = ?rhs")
eberlm@63534
   226
proof
eberlm@63534
   227
  assume "?lhs"
eberlm@63534
   228
  thus "?rhs" by (auto simp: is_prime_int_nat_transfer dvd_int_unfold_dvd_nat prime_nat_code)
eberlm@63534
   229
next
eberlm@63534
   230
  assume "?rhs"
eberlm@63534
   231
  thus "?lhs" by (auto simp: is_prime_int_nat_transfer zdvd_int prime_nat_code)
eberlm@63534
   232
qed
nipkow@32007
   233
eberlm@63535
   234
lemma prime_int_code [code_unfold]:
eberlm@63535
   235
  "(prime :: int \<Rightarrow> bool) = (\<lambda>p. p > 1 \<and> (\<forall>n \<in> {1<..<p}. ~ n dvd p))" 
eberlm@63535
   236
  by (rule ext, rule is_prime_int_iff')
eberlm@63535
   237
nipkow@32007
   238
lemma prime_nat_simp:
lp15@55242
   239
    "prime p \<longleftrightarrow> p > 1 \<and> (\<forall>n \<in> set [2..<p]. \<not> n dvd p)"
wenzelm@44872
   240
  by (auto simp add: prime_nat_code)
nipkow@32007
   241
eberlm@63534
   242
lemma prime_int_simp:
eberlm@63534
   243
    "prime (p::int) \<longleftrightarrow> p > 1 \<and> (\<forall>n \<in> {2..<p}. \<not> n dvd p)"
eberlm@63534
   244
  by (auto simp add: prime_int_code)
eberlm@63534
   245
huffman@47108
   246
lemmas prime_nat_simp_numeral [simp] = prime_nat_simp [of "numeral m"] for m
nipkow@32007
   247
nipkow@32007
   248
lemma two_is_prime_nat [simp]: "prime (2::nat)"
wenzelm@44872
   249
  by simp
nipkow@32007
   250
eberlm@63534
   251
declare is_prime_int_nat_transfer[of "numeral m" for m, simp]
eberlm@63534
   252
eberlm@63534
   253
wenzelm@60526
   254
text\<open>A bit of regression testing:\<close>
nipkow@32111
   255
haftmann@58954
   256
lemma "prime(97::nat)" by simp
wenzelm@44872
   257
lemma "prime(997::nat)" by eval
eberlm@63534
   258
lemma "prime(97::int)" by simp
eberlm@63534
   259
lemma "prime(997::int)" by eval
huffman@31706
   260
eberlm@63534
   261
lemma prime_factor_nat: 
eberlm@63534
   262
  "n \<noteq> (1::nat) \<Longrightarrow> \<exists>p. prime p \<and> p dvd n"
eberlm@63534
   263
  using prime_divisor_exists[of n]
eberlm@63534
   264
  by (cases "n = 0") (auto intro: exI[of _ "2::nat"])
nipkow@23983
   265
wenzelm@44872
   266
wenzelm@60526
   267
subsection \<open>Infinitely many primes\<close>
avigad@32036
   268
eberlm@63534
   269
lemma next_prime_bound: "\<exists>p::nat. prime p \<and> n < p \<and> p \<le> fact n + 1"
avigad@32036
   270
proof-
lp15@59730
   271
  have f1: "fact n + 1 \<noteq> (1::nat)" using fact_ge_1 [of n, where 'a=nat] by arith
avigad@32036
   272
  from prime_factor_nat [OF f1]
eberlm@63534
   273
  obtain p :: nat where "prime p" and "p dvd fact n + 1" by auto
wenzelm@44872
   274
  then have "p \<le> fact n + 1" apply (intro dvd_imp_le) apply auto done
wenzelm@44872
   275
  { assume "p \<le> n"
wenzelm@60526
   276
    from \<open>prime p\<close> have "p \<ge> 1"
avigad@32036
   277
      by (cases p, simp_all)
wenzelm@60526
   278
    with \<open>p <= n\<close> have "p dvd fact n"
lp15@59730
   279
      by (intro dvd_fact)
wenzelm@60526
   280
    with \<open>p dvd fact n + 1\<close> have "p dvd fact n + 1 - fact n"
avigad@32036
   281
      by (rule dvd_diff_nat)
wenzelm@44872
   282
    then have "p dvd 1" by simp
wenzelm@44872
   283
    then have "p <= 1" by auto
lp15@61762
   284
    moreover from \<open>prime p\<close> have "p > 1"
eberlm@63534
   285
      using is_prime_nat_iff by blast
avigad@32036
   286
    ultimately have False by auto}
wenzelm@44872
   287
  then have "n < p" by presburger
wenzelm@60526
   288
  with \<open>prime p\<close> and \<open>p <= fact n + 1\<close> show ?thesis by auto
avigad@32036
   289
qed
avigad@32036
   290
lp15@59669
   291
lemma bigger_prime: "\<exists>p. prime p \<and> p > (n::nat)"
wenzelm@44872
   292
  using next_prime_bound by auto
avigad@32036
   293
avigad@32036
   294
lemma primes_infinite: "\<not> (finite {(p::nat). prime p})"
avigad@32036
   295
proof
avigad@32036
   296
  assume "finite {(p::nat). prime p}"
avigad@32036
   297
  with Max_ge have "(EX b. (ALL x : {(p::nat). prime p}. x <= b))"
avigad@32036
   298
    by auto
avigad@32036
   299
  then obtain b where "ALL (x::nat). prime x \<longrightarrow> x <= b"
avigad@32036
   300
    by auto
wenzelm@44872
   301
  with bigger_prime [of b] show False
wenzelm@44872
   302
    by auto
avigad@32036
   303
qed
avigad@32036
   304
wenzelm@60526
   305
subsection\<open>Powers of Primes\<close>
lp15@55215
   306
wenzelm@60526
   307
text\<open>Versions for type nat only\<close>
lp15@55215
   308
lp15@59669
   309
lemma prime_product:
lp15@55215
   310
  fixes p::nat
lp15@55215
   311
  assumes "prime (p * q)"
lp15@55215
   312
  shows "p = 1 \<or> q = 1"
lp15@55215
   313
proof -
lp15@59669
   314
  from assms have
lp15@55215
   315
    "1 < p * q" and P: "\<And>m. m dvd p * q \<Longrightarrow> m = 1 \<or> m = p * q"
eberlm@63534
   316
    unfolding is_prime_nat_iff by auto
wenzelm@60526
   317
  from \<open>1 < p * q\<close> have "p \<noteq> 0" by (cases p) auto
lp15@55215
   318
  then have Q: "p = p * q \<longleftrightarrow> q = 1" by auto
lp15@55215
   319
  have "p dvd p * q" by simp
lp15@55215
   320
  then have "p = 1 \<or> p = p * q" by (rule P)
lp15@55215
   321
  then show ?thesis by (simp add: Q)
lp15@55215
   322
qed
lp15@55215
   323
eberlm@63534
   324
(* TODO: Generalise? *)
eberlm@63534
   325
lemma prime_power_mult_nat:
lp15@55215
   326
  fixes p::nat
lp15@55215
   327
  assumes p: "prime p" and xy: "x * y = p ^ k"
lp15@55215
   328
  shows "\<exists>i j. x = p ^i \<and> y = p^ j"
lp15@55215
   329
using xy
lp15@55215
   330
proof(induct k arbitrary: x y)
lp15@55215
   331
  case 0 thus ?case apply simp by (rule exI[where x="0"], simp)
lp15@55215
   332
next
lp15@55215
   333
  case (Suc k x y)
lp15@55215
   334
  from Suc.prems have pxy: "p dvd x*y" by auto
eberlm@63534
   335
  from is_prime_dvd_multD [OF p pxy] have pxyc: "p dvd x \<or> p dvd y" .
lp15@59669
   336
  from p have p0: "p \<noteq> 0" by - (rule ccontr, simp)
lp15@55215
   337
  {assume px: "p dvd x"
lp15@55215
   338
    then obtain d where d: "x = p*d" unfolding dvd_def by blast
lp15@55215
   339
    from Suc.prems d  have "p*d*y = p^Suc k" by simp
lp15@55215
   340
    hence th: "d*y = p^k" using p0 by simp
lp15@55215
   341
    from Suc.hyps[OF th] obtain i j where ij: "d = p^i" "y = p^j" by blast
lp15@59669
   342
    with d have "x = p^Suc i" by simp
lp15@55215
   343
    with ij(2) have ?case by blast}
lp15@59669
   344
  moreover
lp15@55215
   345
  {assume px: "p dvd y"
lp15@55215
   346
    then obtain d where d: "y = p*d" unfolding dvd_def by blast
haftmann@57512
   347
    from Suc.prems d  have "p*d*x = p^Suc k" by (simp add: mult.commute)
lp15@55215
   348
    hence th: "d*x = p^k" using p0 by simp
lp15@55215
   349
    from Suc.hyps[OF th] obtain i j where ij: "d = p^i" "x = p^j" by blast
lp15@59669
   350
    with d have "y = p^Suc i" by simp
lp15@55215
   351
    with ij(2) have ?case by blast}
lp15@55215
   352
  ultimately show ?case  using pxyc by blast
lp15@55215
   353
qed
lp15@55215
   354
eberlm@63534
   355
lemma prime_power_exp_nat:
lp15@55215
   356
  fixes p::nat
lp15@59669
   357
  assumes p: "prime p" and n: "n \<noteq> 0"
lp15@55215
   358
    and xn: "x^n = p^k" shows "\<exists>i. x = p^i"
lp15@55215
   359
  using n xn
lp15@55215
   360
proof(induct n arbitrary: k)
lp15@55215
   361
  case 0 thus ?case by simp
lp15@55215
   362
next
lp15@55215
   363
  case (Suc n k) hence th: "x*x^n = p^k" by simp
lp15@55215
   364
  {assume "n = 0" with Suc have ?case by simp (rule exI[where x="k"], simp)}
lp15@55215
   365
  moreover
lp15@55215
   366
  {assume n: "n \<noteq> 0"
eberlm@63534
   367
    from prime_power_mult_nat[OF p th]
lp15@55215
   368
    obtain i j where ij: "x = p^i" "x^n = p^j"by blast
lp15@55215
   369
    from Suc.hyps[OF n ij(2)] have ?case .}
lp15@55215
   370
  ultimately show ?case by blast
lp15@55215
   371
qed
lp15@55215
   372
eberlm@63534
   373
lemma divides_primepow_nat:
lp15@55215
   374
  fixes p::nat
lp15@59669
   375
  assumes p: "prime p"
lp15@55215
   376
  shows "d dvd p^k \<longleftrightarrow> (\<exists> i. i \<le> k \<and> d = p ^i)"
lp15@55215
   377
proof
lp15@59669
   378
  assume H: "d dvd p^k" then obtain e where e: "d*e = p^k"
haftmann@57512
   379
    unfolding dvd_def  apply (auto simp add: mult.commute) by blast
eberlm@63534
   380
  from prime_power_mult_nat[OF p e] obtain i j where ij: "d = p^i" "e=p^j" by blast
lp15@55215
   381
  from e ij have "p^(i + j) = p^k" by (simp add: power_add)
lp15@59669
   382
  hence "i + j = k" using p prime_gt_1_nat power_inject_exp[of p "i+j" k] by simp
lp15@55215
   383
  hence "i \<le> k" by arith
lp15@55215
   384
  with ij(1) show "\<exists>i\<le>k. d = p ^ i" by blast
lp15@55215
   385
next
lp15@55215
   386
  {fix i assume H: "i \<le> k" "d = p^i"
lp15@55215
   387
    then obtain j where j: "k = i + j"
lp15@55215
   388
      by (metis le_add_diff_inverse)
lp15@55215
   389
    hence "p^k = p^j*d" using H(2) by (simp add: power_add)
lp15@55215
   390
    hence "d dvd p^k" unfolding dvd_def by auto}
lp15@55215
   391
  thus "\<exists>i\<le>k. d = p ^ i \<Longrightarrow> d dvd p ^ k" by blast
lp15@55215
   392
qed
lp15@55215
   393
eberlm@63534
   394
wenzelm@60526
   395
subsection \<open>Chinese Remainder Theorem Variants\<close>
lp15@55238
   396
lp15@55238
   397
lemma bezout_gcd_nat:
lp15@55238
   398
  fixes a::nat shows "\<exists>x y. a * x - b * y = gcd a b \<or> b * x - a * y = gcd a b"
lp15@55238
   399
  using bezout_nat[of a b]
eberlm@62429
   400
by (metis bezout_nat diff_add_inverse gcd_add_mult gcd.commute
lp15@59669
   401
  gcd_nat.right_neutral mult_0)
lp15@55238
   402
lp15@55238
   403
lemma gcd_bezout_sum_nat:
lp15@59669
   404
  fixes a::nat
lp15@59669
   405
  assumes "a * x + b * y = d"
lp15@55238
   406
  shows "gcd a b dvd d"
lp15@55238
   407
proof-
lp15@55238
   408
  let ?g = "gcd a b"
lp15@59669
   409
    have dv: "?g dvd a*x" "?g dvd b * y"
lp15@55238
   410
      by simp_all
lp15@55238
   411
    from dvd_add[OF dv] assms
lp15@55238
   412
    show ?thesis by auto
lp15@55238
   413
qed
lp15@55238
   414
lp15@55238
   415
wenzelm@60526
   416
text \<open>A binary form of the Chinese Remainder Theorem.\<close>
lp15@55238
   417
eberlm@63534
   418
(* TODO: Generalise? *)
lp15@59669
   419
lemma chinese_remainder:
lp15@55238
   420
  fixes a::nat  assumes ab: "coprime a b" and a: "a \<noteq> 0" and b: "b \<noteq> 0"
lp15@55238
   421
  shows "\<exists>x q1 q2. x = u + q1 * a \<and> x = v + q2 * b"
lp15@55238
   422
proof-
lp15@55238
   423
  from bezout_add_strong_nat[OF a, of b] bezout_add_strong_nat[OF b, of a]
lp15@59669
   424
  obtain d1 x1 y1 d2 x2 y2 where dxy1: "d1 dvd a" "d1 dvd b" "a * x1 = b * y1 + d1"
lp15@55238
   425
    and dxy2: "d2 dvd b" "d2 dvd a" "b * x2 = a * y2 + d2" by blast
lp15@55238
   426
  then have d12: "d1 = 1" "d2 =1"
lp15@55238
   427
    by (metis ab coprime_nat)+
lp15@55238
   428
  let ?x = "v * a * x1 + u * b * x2"
lp15@55238
   429
  let ?q1 = "v * x1 + u * y2"
lp15@55238
   430
  let ?q2 = "v * y1 + u * x2"
lp15@59669
   431
  from dxy2(3)[simplified d12] dxy1(3)[simplified d12]
lp15@55238
   432
  have "?x = u + ?q1 * a" "?x = v + ?q2 * b"
lp15@55337
   433
    by algebra+
lp15@55238
   434
  thus ?thesis by blast
lp15@55238
   435
qed
lp15@55238
   436
wenzelm@60526
   437
text \<open>Primality\<close>
lp15@55238
   438
lp15@55238
   439
lemma coprime_bezout_strong:
lp15@55238
   440
  fixes a::nat assumes "coprime a b"  "b \<noteq> 1"
lp15@55238
   441
  shows "\<exists>x y. a * x = b * y + 1"
lp15@55238
   442
by (metis assms bezout_nat gcd_nat.left_neutral)
lp15@55238
   443
lp15@59669
   444
lemma bezout_prime:
lp15@55238
   445
  assumes p: "prime p" and pa: "\<not> p dvd a"
lp15@55238
   446
  shows "\<exists>x y. a*x = Suc (p*y)"
haftmann@62349
   447
proof -
lp15@55238
   448
  have ap: "coprime a p"
eberlm@63534
   449
    by (metis gcd.commute p pa is_prime_imp_coprime)
haftmann@62349
   450
  moreover from p have "p \<noteq> 1" by auto
haftmann@62349
   451
  ultimately have "\<exists>x y. a * x = p * y + 1"
haftmann@62349
   452
    by (rule coprime_bezout_strong)
haftmann@62349
   453
  then show ?thesis by simp    
lp15@55238
   454
qed
eberlm@63534
   455
(* END TODO *)
lp15@55238
   456
eberlm@63534
   457
eberlm@63534
   458
eberlm@63534
   459
subsection \<open>Multiplicity and primality for natural numbers and integers\<close>
eberlm@63534
   460
eberlm@63534
   461
lemma prime_factors_gt_0_nat:
eberlm@63534
   462
  "p \<in> prime_factors x \<Longrightarrow> p > (0::nat)"
eberlm@63534
   463
  by (simp add: prime_factors_prime prime_gt_0_nat)
eberlm@63534
   464
eberlm@63534
   465
lemma prime_factors_gt_0_int:
eberlm@63534
   466
  "p \<in> prime_factors x \<Longrightarrow> p > (0::int)"
eberlm@63534
   467
  by (simp add: prime_factors_prime prime_gt_0_int)
eberlm@63534
   468
eberlm@63534
   469
lemma prime_factors_ge_0_int [elim]:
eberlm@63534
   470
  fixes n :: int
eberlm@63534
   471
  shows "p \<in> prime_factors n \<Longrightarrow> p \<ge> 0"
eberlm@63534
   472
  unfolding prime_factors_def 
eberlm@63534
   473
  by (auto split: if_splits simp: is_prime_def dest!: in_prime_factorization_imp_prime)
eberlm@63534
   474
eberlm@63534
   475
lemma msetprod_prime_factorization_int:
eberlm@63534
   476
  fixes n :: int
eberlm@63534
   477
  assumes "n > 0"
eberlm@63534
   478
  shows   "msetprod (prime_factorization n) = n"
eberlm@63534
   479
  using assms by (simp add: msetprod_prime_factorization)
eberlm@63534
   480
eberlm@63534
   481
lemma prime_factorization_exists_nat:
eberlm@63534
   482
  "n > 0 \<Longrightarrow> (\<exists>M. (\<forall>p::nat \<in> set_mset M. prime p) \<and> n = (\<Prod>i \<in># M. i))"
eberlm@63534
   483
  using prime_factorization_exists[of n] by (auto simp: is_prime_def)
eberlm@63534
   484
eberlm@63534
   485
lemma msetprod_prime_factorization_nat [simp]: 
eberlm@63534
   486
  "(n::nat) > 0 \<Longrightarrow> msetprod (prime_factorization n) = n"
eberlm@63534
   487
  by (subst msetprod_prime_factorization) simp_all
eberlm@63534
   488
eberlm@63534
   489
lemma prime_factorization_nat:
eberlm@63534
   490
    "n > (0::nat) \<Longrightarrow> n = (\<Prod>p \<in> prime_factors n. p ^ multiplicity p n)"
eberlm@63534
   491
  by (simp add: setprod_prime_factors)
eberlm@63534
   492
eberlm@63534
   493
lemma prime_factorization_int:
eberlm@63534
   494
    "n > (0::int) \<Longrightarrow> n = (\<Prod>p \<in> prime_factors n. p ^ multiplicity p n)"
eberlm@63534
   495
  by (simp add: setprod_prime_factors)
eberlm@63534
   496
eberlm@63534
   497
lemma prime_factorization_unique_nat:
eberlm@63534
   498
  fixes f :: "nat \<Rightarrow> _"
eberlm@63534
   499
  assumes S_eq: "S = {p. 0 < f p}"
eberlm@63534
   500
    and "finite S"
eberlm@63534
   501
    and S: "\<forall>p\<in>S. prime p" "n = (\<Prod>p\<in>S. p ^ f p)"
eberlm@63534
   502
  shows "S = prime_factors n \<and> (\<forall>p. is_prime p \<longrightarrow> f p = multiplicity p n)"
eberlm@63534
   503
  using assms by (intro prime_factorization_unique'') auto
eberlm@63534
   504
eberlm@63534
   505
lemma prime_factorization_unique_int:
eberlm@63534
   506
  fixes f :: "int \<Rightarrow> _"
eberlm@63534
   507
  assumes S_eq: "S = {p. 0 < f p}"
eberlm@63534
   508
    and "finite S"
eberlm@63534
   509
    and S: "\<forall>p\<in>S. prime p" "abs n = (\<Prod>p\<in>S. p ^ f p)"
eberlm@63534
   510
  shows "S = prime_factors n \<and> (\<forall>p. is_prime p \<longrightarrow> f p = multiplicity p n)"
eberlm@63534
   511
  using assms by (intro prime_factorization_unique'') auto
eberlm@63534
   512
eberlm@63534
   513
lemma prime_factors_characterization_nat:
eberlm@63534
   514
  "S = {p. 0 < f (p::nat)} \<Longrightarrow>
eberlm@63534
   515
    finite S \<Longrightarrow> \<forall>p\<in>S. prime p \<Longrightarrow> n = (\<Prod>p\<in>S. p ^ f p) \<Longrightarrow> prime_factors n = S"
eberlm@63534
   516
  by (rule prime_factorization_unique_nat [THEN conjunct1, symmetric])
eberlm@63534
   517
eberlm@63534
   518
lemma prime_factors_characterization'_nat:
eberlm@63534
   519
  "finite {p. 0 < f (p::nat)} \<Longrightarrow>
eberlm@63534
   520
    (\<forall>p. 0 < f p \<longrightarrow> prime p) \<Longrightarrow>
eberlm@63534
   521
      prime_factors (\<Prod>p | 0 < f p. p ^ f p) = {p. 0 < f p}"
eberlm@63534
   522
  by (rule prime_factors_characterization_nat) auto
eberlm@63534
   523
eberlm@63534
   524
lemma prime_factors_characterization_int:
eberlm@63534
   525
  "S = {p. 0 < f (p::int)} \<Longrightarrow> finite S \<Longrightarrow>
eberlm@63534
   526
    \<forall>p\<in>S. prime p \<Longrightarrow> abs n = (\<Prod>p\<in>S. p ^ f p) \<Longrightarrow> prime_factors n = S"
eberlm@63534
   527
  by (rule prime_factorization_unique_int [THEN conjunct1, symmetric])
eberlm@63534
   528
eberlm@63534
   529
(* TODO Move *)
eberlm@63534
   530
lemma abs_setprod: "abs (setprod f A :: 'a :: linordered_idom) = setprod (\<lambda>x. abs (f x)) A"
eberlm@63534
   531
  by (cases "finite A", induction A rule: finite_induct) (simp_all add: abs_mult)
eberlm@63534
   532
eberlm@63534
   533
lemma primes_characterization'_int [rule_format]:
eberlm@63534
   534
  "finite {p. p \<ge> 0 \<and> 0 < f (p::int)} \<Longrightarrow> \<forall>p. 0 < f p \<longrightarrow> prime p \<Longrightarrow>
eberlm@63534
   535
      prime_factors (\<Prod>p | p \<ge> 0 \<and> 0 < f p. p ^ f p) = {p. p \<ge> 0 \<and> 0 < f p}"
eberlm@63534
   536
  by (rule prime_factors_characterization_int) (auto simp: abs_setprod prime_ge_0_int)
eberlm@63534
   537
eberlm@63534
   538
lemma multiplicity_characterization_nat:
eberlm@63534
   539
  "S = {p. 0 < f (p::nat)} \<Longrightarrow> finite S \<Longrightarrow> \<forall>p\<in>S. prime p \<Longrightarrow> is_prime p \<Longrightarrow>
eberlm@63534
   540
    n = (\<Prod>p\<in>S. p ^ f p) \<Longrightarrow> multiplicity p n = f p"
eberlm@63534
   541
  by (frule prime_factorization_unique_nat [of S f n, THEN conjunct2, rule_format, symmetric]) auto
eberlm@63534
   542
eberlm@63534
   543
lemma multiplicity_characterization'_nat: "finite {p. 0 < f (p::nat)} \<longrightarrow>
eberlm@63534
   544
    (\<forall>p. 0 < f p \<longrightarrow> prime p) \<longrightarrow> is_prime p \<longrightarrow>
eberlm@63534
   545
      multiplicity p (\<Prod>p | 0 < f p. p ^ f p) = f p"
eberlm@63534
   546
  by (intro impI, rule multiplicity_characterization_nat) auto
eberlm@63534
   547
eberlm@63534
   548
lemma multiplicity_characterization_int: "S = {p. 0 < f (p::int)} \<Longrightarrow>
eberlm@63534
   549
    finite S \<Longrightarrow> \<forall>p\<in>S. prime p \<Longrightarrow> is_prime p \<Longrightarrow> n = (\<Prod>p\<in>S. p ^ f p) \<Longrightarrow> multiplicity p n = f p"
eberlm@63534
   550
  by (frule prime_factorization_unique_int [of S f n, THEN conjunct2, rule_format, symmetric]) 
eberlm@63534
   551
     (auto simp: abs_setprod power_abs prime_ge_0_int intro!: setprod.cong)
eberlm@63534
   552
eberlm@63534
   553
lemma multiplicity_characterization'_int [rule_format]:
eberlm@63534
   554
  "finite {p. p \<ge> 0 \<and> 0 < f (p::int)} \<Longrightarrow>
eberlm@63534
   555
    (\<forall>p. 0 < f p \<longrightarrow> prime p) \<Longrightarrow> is_prime p \<Longrightarrow>
eberlm@63534
   556
      multiplicity p (\<Prod>p | p \<ge> 0 \<and> 0 < f p. p ^ f p) = f p"
eberlm@63534
   557
  by (rule multiplicity_characterization_int) (auto simp: prime_ge_0_int)
eberlm@63534
   558
eberlm@63534
   559
lemma multiplicity_one_nat [simp]: "multiplicity p (Suc 0) = 0"
eberlm@63534
   560
  unfolding One_nat_def [symmetric] by (rule multiplicity_one)
eberlm@63534
   561
eberlm@63534
   562
lemma multiplicity_eq_nat:
eberlm@63534
   563
  fixes x and y::nat
eberlm@63534
   564
  assumes "x > 0" "y > 0" "\<And>p. is_prime p \<Longrightarrow> multiplicity p x = multiplicity p y"
eberlm@63534
   565
  shows "x = y"
eberlm@63534
   566
  using multiplicity_eq_imp_eq[of x y] assms by simp
eberlm@63534
   567
eberlm@63534
   568
lemma multiplicity_eq_int:
eberlm@63534
   569
  fixes x y :: int
eberlm@63534
   570
  assumes "x > 0" "y > 0" "\<And>p. is_prime p \<Longrightarrow> multiplicity p x = multiplicity p y"
eberlm@63534
   571
  shows "x = y"
eberlm@63534
   572
  using multiplicity_eq_imp_eq[of x y] assms by simp
eberlm@63534
   573
eberlm@63534
   574
lemma multiplicity_prod_prime_powers:
eberlm@63534
   575
  assumes "finite S" "\<And>x. x \<in> S \<Longrightarrow> is_prime x" "is_prime p"
eberlm@63534
   576
  shows   "multiplicity p (\<Prod>p \<in> S. p ^ f p) = (if p \<in> S then f p else 0)"
eberlm@63534
   577
proof -
eberlm@63534
   578
  define g where "g = (\<lambda>x. if x \<in> S then f x else 0)"
eberlm@63534
   579
  define A where "A = Abs_multiset g"
eberlm@63534
   580
  have "{x. g x > 0} \<subseteq> S" by (auto simp: g_def)
eberlm@63534
   581
  from finite_subset[OF this assms(1)] have [simp]: "g :  multiset"
eberlm@63534
   582
    by (simp add: multiset_def)
eberlm@63534
   583
  from assms have count_A: "count A x = g x" for x unfolding A_def
eberlm@63534
   584
    by simp
eberlm@63534
   585
  have set_mset_A: "set_mset A = {x\<in>S. f x > 0}"
eberlm@63534
   586
    unfolding set_mset_def count_A by (auto simp: g_def)
eberlm@63534
   587
  with assms have prime: "prime x" if "x \<in># A" for x using that by auto
eberlm@63534
   588
  from set_mset_A assms have "(\<Prod>p \<in> S. p ^ f p) = (\<Prod>p \<in> S. p ^ g p) "
eberlm@63534
   589
    by (intro setprod.cong) (auto simp: g_def)
eberlm@63534
   590
  also from set_mset_A assms have "\<dots> = (\<Prod>p \<in> set_mset A. p ^ g p)"
eberlm@63534
   591
    by (intro setprod.mono_neutral_right) (auto simp: g_def set_mset_A)
eberlm@63534
   592
  also have "\<dots> = msetprod A"
eberlm@63534
   593
    by (auto simp: msetprod_multiplicity count_A set_mset_A intro!: setprod.cong)
eberlm@63534
   594
  also from assms have "multiplicity p \<dots> = msetsum (image_mset (multiplicity p) A)"
eberlm@63534
   595
    by (subst prime_multiplicity_msetprod_distrib) (auto dest: prime)
eberlm@63534
   596
  also from assms have "image_mset (multiplicity p) A = image_mset (\<lambda>x. if x = p then 1 else 0) A"
eberlm@63534
   597
    by (intro image_mset_cong) (auto simp: prime_multiplicity_other dest: prime)
eberlm@63534
   598
  also have "msetsum \<dots> = (if p \<in> S then f p else 0)" by (simp add: msetsum_delta count_A g_def)
eberlm@63534
   599
  finally show ?thesis .
eberlm@63534
   600
qed
eberlm@63534
   601
eberlm@63534
   602
(* TODO Legacy names *)
eberlm@63534
   603
lemmas prime_imp_coprime_nat = is_prime_imp_coprime[where ?'a = nat]
eberlm@63534
   604
lemmas prime_imp_coprime_int = is_prime_imp_coprime[where ?'a = int]
eberlm@63534
   605
lemmas prime_dvd_mult_nat = is_prime_dvd_mult_iff[where ?'a = nat]
eberlm@63534
   606
lemmas prime_dvd_mult_int = is_prime_dvd_mult_iff[where ?'a = int]
eberlm@63534
   607
lemmas prime_dvd_mult_eq_nat = is_prime_dvd_mult_iff[where ?'a = nat]
eberlm@63534
   608
lemmas prime_dvd_mult_eq_int = is_prime_dvd_mult_iff[where ?'a = int]
eberlm@63534
   609
lemmas prime_dvd_power_nat = is_prime_dvd_power[where ?'a = nat]
eberlm@63534
   610
lemmas prime_dvd_power_int = is_prime_dvd_power[where ?'a = int]
eberlm@63534
   611
lemmas prime_dvd_power_nat_iff = is_prime_dvd_power_iff[where ?'a = nat]
eberlm@63534
   612
lemmas prime_dvd_power_int_iff = is_prime_dvd_power_iff[where ?'a = int]
eberlm@63534
   613
lemmas prime_imp_power_coprime_nat = is_prime_imp_power_coprime[where ?'a = nat]
eberlm@63534
   614
lemmas prime_imp_power_coprime_int = is_prime_imp_power_coprime[where ?'a = int]
eberlm@63534
   615
lemmas primes_coprime_nat = primes_coprime[where ?'a = nat]
eberlm@63534
   616
lemmas primes_coprime_int = primes_coprime[where ?'a = nat]
eberlm@63534
   617
lemmas prime_divprod_pow_nat = prime_divprod_pow[where ?'a = nat]
eberlm@63534
   618
lemmas prime_exp = is_prime_elem_power_iff[where ?'a = nat]
eberlm@63534
   619
eberlm@63534
   620
end