src/HOL/Number_Theory/Prime_Powers.thy
changeset 66276 acc3b7dd0b21
child 66453 cc19f7ca2ed6
equal deleted inserted replaced
66275:2c1d223c5417 66276:acc3b7dd0b21
       
     1 (*
       
     2   File:      HOL/Number_Theory/Prime_Powers.thy
       
     3   Author:    Manuel Eberl <eberlm@in.tum.de>
       
     4 
       
     5   Prime powers and the Mangoldt function
       
     6 *)
       
     7 section \<open>Prime powers\<close>
       
     8 theory Prime_Powers
       
     9   imports Complex_Main "~~/src/HOL/Computational_Algebra/Primes"
       
    10 begin
       
    11 
       
    12 definition aprimedivisor :: "'a :: normalization_semidom \<Rightarrow> 'a" where
       
    13   "aprimedivisor q = (SOME p. prime p \<and> p dvd q)"
       
    14 
       
    15 definition primepow :: "'a :: normalization_semidom \<Rightarrow> bool" where
       
    16   "primepow n \<longleftrightarrow> (\<exists>p k. prime p \<and> k > 0 \<and> n = p ^ k)"
       
    17 
       
    18 definition primepow_factors :: "'a :: normalization_semidom \<Rightarrow> 'a set" where
       
    19   "primepow_factors n = {x. primepow x \<and> x dvd n}"
       
    20   
       
    21 lemma primepow_gt_Suc_0: "primepow n \<Longrightarrow> n > Suc 0"
       
    22   using one_less_power[of "p::nat" for p] by (auto simp: primepow_def prime_nat_iff)
       
    23 
       
    24 lemma
       
    25   assumes "prime p" "p dvd n"
       
    26   shows prime_aprimedivisor: "prime (aprimedivisor n)" 
       
    27     and aprimedivisor_dvd:   "aprimedivisor n dvd n"
       
    28 proof -
       
    29   from assms have "\<exists>p. prime p \<and> p dvd n" by auto
       
    30   from someI_ex[OF this] show "prime (aprimedivisor n)" "aprimedivisor n dvd n"
       
    31       unfolding aprimedivisor_def by (simp_all add: conj_commute)
       
    32 qed    
       
    33 
       
    34 lemma
       
    35   assumes "n \<noteq> 0" "\<not>is_unit (n :: 'a :: factorial_semiring)"
       
    36   shows prime_aprimedivisor': "prime (aprimedivisor n)" 
       
    37     and aprimedivisor_dvd':   "aprimedivisor n dvd n"
       
    38 proof -
       
    39   from someI_ex[OF prime_divisor_exists[OF assms]] 
       
    40     show "prime (aprimedivisor n)" "aprimedivisor n dvd n"
       
    41       unfolding aprimedivisor_def by (simp_all add: conj_commute)
       
    42 qed
       
    43 
       
    44 lemma aprimedivisor_of_prime [simp]: 
       
    45   assumes "prime p"
       
    46   shows   "aprimedivisor p = p"
       
    47 proof -
       
    48   from assms have "\<exists>q. prime q \<and> q dvd p" by auto
       
    49   from someI_ex[OF this, folded aprimedivisor_def] assms show ?thesis
       
    50     by (auto intro: primes_dvd_imp_eq)
       
    51 qed
       
    52 
       
    53 lemma aprimedivisor_pos_nat: "(n::nat) > 1 \<Longrightarrow> aprimedivisor n > 0"
       
    54   using aprimedivisor_dvd'[of n] by (auto elim: dvdE intro!: Nat.gr0I)
       
    55 
       
    56 lemma aprimedivisor_primepow_power:
       
    57   assumes "primepow n" "k > 0"
       
    58   shows   "aprimedivisor (n ^ k) = aprimedivisor n"
       
    59 proof -
       
    60   from assms obtain p l where l: "prime p" "l > 0" "n = p ^ l"
       
    61     by (auto simp: primepow_def)
       
    62   from l assms have *: "prime (aprimedivisor (n ^ k))" "aprimedivisor (n ^ k) dvd n ^ k"
       
    63     by (intro prime_aprimedivisor[of p] aprimedivisor_dvd[of p] dvd_power; 
       
    64         simp add: power_mult [symmetric])+
       
    65   from * l have "aprimedivisor (n ^ k) dvd p ^ (l * k)" by (simp add: power_mult)
       
    66   with assms * l have "aprimedivisor (n ^ k) dvd p" 
       
    67     by (subst (asm) prime_dvd_power_iff) simp_all
       
    68   with l assms have "aprimedivisor (n ^ k) = p"
       
    69     by (intro primes_dvd_imp_eq prime_aprimedivisor l) (auto simp: power_mult [symmetric])
       
    70   moreover from l have "aprimedivisor n dvd p ^ l" 
       
    71     by (auto intro: aprimedivisor_dvd simp: prime_gt_0_nat)
       
    72   with assms l have "aprimedivisor n dvd p"
       
    73     by (subst (asm) prime_dvd_power_iff) (auto intro!: prime_aprimedivisor simp: prime_gt_0_nat)
       
    74   with l assms have "aprimedivisor n = p"
       
    75     by (intro primes_dvd_imp_eq prime_aprimedivisor l) auto
       
    76   ultimately show ?thesis by simp
       
    77 qed
       
    78 
       
    79 lemma aprimedivisor_prime_power:
       
    80   assumes "prime p" "k > 0"
       
    81   shows   "aprimedivisor (p ^ k) = p"
       
    82 proof -
       
    83   from assms have *: "prime (aprimedivisor (p ^ k))" "aprimedivisor (p ^ k) dvd p ^ k"
       
    84     by (intro prime_aprimedivisor[of p] aprimedivisor_dvd[of p]; simp add: prime_nat_iff)+
       
    85   from assms * have "aprimedivisor (p ^ k) dvd p" 
       
    86     by (subst (asm) prime_dvd_power_iff) simp_all
       
    87   with assms * show "aprimedivisor (p ^ k) = p" by (intro primes_dvd_imp_eq)
       
    88 qed
       
    89 
       
    90 lemma prime_factorization_primepow:
       
    91   assumes "primepow n"
       
    92   shows   "prime_factorization n = 
       
    93              replicate_mset (multiplicity (aprimedivisor n) n) (aprimedivisor n)"
       
    94   using assms
       
    95   by (auto simp: primepow_def aprimedivisor_prime_power prime_factorization_prime_power)
       
    96 
       
    97 lemma primepow_decompose:
       
    98   assumes "primepow n"
       
    99   shows   "aprimedivisor n ^ multiplicity (aprimedivisor n) n = n"
       
   100 proof -
       
   101   from assms have "n \<noteq> 0" by (intro notI) (auto simp: primepow_def)
       
   102   hence "n = unit_factor n * prod_mset (prime_factorization n)"
       
   103     by (subst prod_mset_prime_factorization) simp_all
       
   104   also from assms have "unit_factor n = 1" by (auto simp: primepow_def unit_factor_power)
       
   105   also have "prime_factorization n = 
       
   106                replicate_mset (multiplicity (aprimedivisor n) n) (aprimedivisor n)"
       
   107     by (intro prime_factorization_primepow assms)
       
   108   also have "prod_mset \<dots> = aprimedivisor n ^ multiplicity (aprimedivisor n) n" by simp
       
   109   finally show ?thesis by simp
       
   110 qed
       
   111 
       
   112 lemma prime_power_not_one:
       
   113   assumes "prime p" "k > 0"
       
   114   shows   "p ^ k \<noteq> 1"
       
   115 proof
       
   116   assume "p ^ k = 1"
       
   117   hence "is_unit (p ^ k)" by simp
       
   118   thus False using assms by (simp add: is_unit_power_iff)
       
   119 qed
       
   120 
       
   121 lemma zero_not_primepow [simp]: "\<not>primepow 0"
       
   122   by (auto simp: primepow_def)
       
   123 
       
   124 lemma one_not_primepow [simp]: "\<not>primepow 1"
       
   125   by (auto simp: primepow_def prime_power_not_one)
       
   126 
       
   127 lemma primepow_not_unit [simp]: "primepow p \<Longrightarrow> \<not>is_unit p"
       
   128   by (auto simp: primepow_def is_unit_power_iff)
       
   129 
       
   130 lemma unit_factor_primepow: "primepow p \<Longrightarrow> unit_factor p = 1"
       
   131   by (auto simp: primepow_def unit_factor_power)
       
   132 
       
   133 lemma aprimedivisor_primepow:
       
   134   assumes "prime p" "p dvd n" "primepow (n :: 'a :: factorial_semiring)"
       
   135   shows   "aprimedivisor (p * n) = p" "aprimedivisor n = p"
       
   136 proof -
       
   137   from assms have [simp]: "n \<noteq> 0" by auto
       
   138   define q where "q = aprimedivisor n"
       
   139   with assms have q: "prime q" by (auto simp: q_def intro!: prime_aprimedivisor)
       
   140   from \<open>primepow n\<close> have n: "n = q ^ multiplicity q n" 
       
   141     by (simp add: primepow_decompose q_def)
       
   142   have nz: "multiplicity q n \<noteq> 0"
       
   143   proof
       
   144     assume "multiplicity q n = 0"
       
   145     with n have n': "n = unit_factor n" by simp
       
   146     have "is_unit n" by (subst n', rule unit_factor_is_unit) (insert assms, auto)
       
   147     with assms show False by auto
       
   148   qed
       
   149   with \<open>prime p\<close> \<open>p dvd n\<close> q have "p dvd q" 
       
   150     by (subst (asm) n) (auto intro: prime_dvd_power)
       
   151   with \<open>prime p\<close> q have "p = q" by (intro primes_dvd_imp_eq)
       
   152   thus "aprimedivisor n = p" by (simp add: q_def)
       
   153 
       
   154   define r where "r = aprimedivisor (p * n)"
       
   155   with assms have r: "r dvd (p * n)" "prime r" unfolding r_def
       
   156     by (intro aprimedivisor_dvd[of p] prime_aprimedivisor[of p]; simp)+
       
   157   hence "r dvd q ^ Suc (multiplicity q n)"
       
   158     by (subst (asm) n) (auto simp: \<open>p = q\<close> dest: dvd_unit_imp_unit)
       
   159   with r have "r dvd q" 
       
   160     by (auto intro: prime_dvd_power_nat simp: prime_dvd_mult_iff dest: prime_dvd_power)
       
   161   with r q have "r = q" by (intro primes_dvd_imp_eq)
       
   162   thus "aprimedivisor (p * n) = p" by (simp add: r_def \<open>p = q\<close>)
       
   163 qed
       
   164 
       
   165 lemma power_eq_prime_powerD:
       
   166   fixes p :: "'a :: factorial_semiring"
       
   167   assumes "prime p" "n > 0" "x ^ n = p ^ k"
       
   168   shows   "\<exists>i. normalize x = normalize (p ^ i)"
       
   169 proof -
       
   170   have "normalize x = normalize (p ^ multiplicity p x)"
       
   171   proof (rule multiplicity_eq_imp_eq)
       
   172     fix q :: 'a assume "prime q"
       
   173     from assms have "multiplicity q (x ^ n) = multiplicity q (p ^ k)" by simp
       
   174     with \<open>prime q\<close> and assms have "n * multiplicity q x = k * multiplicity q p"
       
   175       by (subst (asm) (1 2) prime_elem_multiplicity_power_distrib) (auto simp: power_0_left)
       
   176     with assms and \<open>prime q\<close> show "multiplicity q x = multiplicity q (p ^ multiplicity p x)"
       
   177       by (cases "p = q") (auto simp: multiplicity_distinct_prime_power prime_multiplicity_other)
       
   178   qed (insert assms, auto simp: power_0_left)
       
   179   thus ?thesis by auto
       
   180 qed
       
   181   
       
   182 
       
   183 lemma primepow_power_iff:
       
   184   assumes "unit_factor p = 1"
       
   185   shows   "primepow (p ^ n) \<longleftrightarrow> primepow (p :: 'a :: factorial_semiring) \<and> n > 0"
       
   186 proof safe
       
   187   assume "primepow (p ^ n)"
       
   188   hence n: "n \<noteq> 0" by (auto intro!: Nat.gr0I)
       
   189   thus "n > 0" by simp
       
   190   from assms have [simp]: "normalize p = p"
       
   191     using normalize_mult_unit_factor[of p] by (simp only: mult.right_neutral)
       
   192   from \<open>primepow (p ^ n)\<close> obtain q k where *: "k > 0" "prime q" "p ^ n = q ^ k"
       
   193     by (auto simp: primepow_def)
       
   194   with power_eq_prime_powerD[of q n p k] n 
       
   195     obtain i where eq: "normalize p = normalize (q ^ i)" by auto
       
   196   with primepow_not_unit[OF \<open>primepow (p ^ n)\<close>] have "i \<noteq> 0" 
       
   197     by (intro notI) (simp add: normalize_1_iff is_unit_power_iff del: primepow_not_unit)
       
   198   with \<open>normalize p = normalize (q ^ i)\<close> \<open>prime q\<close> show "primepow p"
       
   199     by (auto simp: normalize_power primepow_def intro!: exI[of _ q] exI[of _ i])
       
   200 next
       
   201   assume "primepow p" "n > 0"
       
   202   then obtain q k where *: "k > 0" "prime q" "p = q ^ k" by (auto simp: primepow_def)
       
   203   with \<open>n > 0\<close> show "primepow (p ^ n)"
       
   204     by (auto simp: primepow_def power_mult intro!: exI[of _ q] exI[of _ "k * n"])
       
   205 qed
       
   206 
       
   207 lemma primepow_prime [simp]: "prime n \<Longrightarrow> primepow n"
       
   208   by (auto simp: primepow_def intro!: exI[of _ n] exI[of _ "1::nat"])
       
   209 
       
   210 lemma primepow_prime_power [simp]: 
       
   211     "prime (p :: 'a :: factorial_semiring) \<Longrightarrow> primepow (p ^ n) \<longleftrightarrow> n > 0"
       
   212   by (subst primepow_power_iff) auto
       
   213 
       
   214 (* TODO Generalise *)
       
   215 lemma primepow_multD:
       
   216   assumes "primepow (a * b :: nat)"
       
   217   shows   "a = 1 \<or> primepow a" "b = 1 \<or> primepow b"
       
   218 proof -
       
   219   from assms obtain p k where k: "k > 0" "a * b = p ^ k" "prime p"
       
   220     unfolding primepow_def by auto
       
   221   then obtain i j where "a = p ^ i" "b = p ^ j"
       
   222     using prime_power_mult_nat[of p a b] by blast
       
   223   with \<open>prime p\<close> show "a = 1 \<or> primepow a" "b = 1 \<or> primepow b" by auto
       
   224 qed
       
   225 
       
   226 lemma primepow_mult_aprimedivisorI:
       
   227   assumes "primepow (n :: 'a :: factorial_semiring)"
       
   228   shows   "primepow (aprimedivisor n * n)"
       
   229   by (subst (2) primepow_decompose[OF assms, symmetric], subst power_Suc [symmetric],
       
   230       subst primepow_prime_power) 
       
   231      (insert assms, auto intro!: prime_aprimedivisor' dest: primepow_gt_Suc_0)
       
   232 
       
   233 lemma aprimedivisor_vimage:
       
   234   assumes "prime (p :: 'a :: factorial_semiring)"
       
   235   shows   "aprimedivisor -` {p} \<inter> primepow_factors n = {p ^ k |k. k > 0 \<and> p ^ k dvd n}"
       
   236 proof safe
       
   237   fix q assume q: "q \<in> primepow_factors n"
       
   238   hence q': "q \<noteq> 0" "q \<noteq> 1" by (auto simp: primepow_def primepow_factors_def prime_power_not_one)
       
   239   let ?n = "multiplicity (aprimedivisor q) q"
       
   240   from q q' have "q = aprimedivisor q ^ ?n \<and> ?n > 0 \<and> aprimedivisor q ^ ?n dvd n"
       
   241     using prime_aprimedivisor'[of q] aprimedivisor_dvd'[of q]
       
   242     by (subst primepow_decompose [symmetric])
       
   243        (auto simp: primepow_factors_def multiplicity_gt_zero_iff unit_factor_primepow
       
   244              intro: dvd_trans[OF multiplicity_dvd])
       
   245   thus "\<exists>k. q = aprimedivisor q ^ k \<and> k > 0 \<and> aprimedivisor q ^ k dvd n" ..
       
   246 next
       
   247   fix k :: nat assume k: "p ^ k dvd n" "k > 0"
       
   248   with assms show "p ^ k \<in> aprimedivisor -` {p}"
       
   249     by (auto simp: aprimedivisor_prime_power)
       
   250   with assms k show "p ^ k \<in> primepow_factors n"
       
   251     by (auto simp: primepow_factors_def primepow_def aprimedivisor_prime_power intro: Suc_leI)
       
   252 qed
       
   253   
       
   254 lemma primepow_factors_altdef:
       
   255   fixes x :: "'a :: factorial_semiring"
       
   256   assumes "x \<noteq> 0"
       
   257   shows "primepow_factors x = {p ^ k |p k. p \<in> prime_factors x \<and> k \<in> {0<.. multiplicity p x}}"
       
   258 proof (intro equalityI subsetI)
       
   259   fix q assume "q \<in> primepow_factors x"
       
   260   then obtain p k where pk: "prime p" "k > 0" "q = p ^ k" "q dvd x" 
       
   261     unfolding primepow_factors_def primepow_def by blast
       
   262   moreover have "k \<le> multiplicity p x" using pk assms by (intro multiplicity_geI) auto
       
   263   ultimately show "q \<in> {p ^ k |p k. p \<in> prime_factors x \<and> k \<in> {0<.. multiplicity p x}}"
       
   264     by (auto simp: prime_factors_multiplicity intro!: exI[of _ p] exI[of _ k])
       
   265 qed (auto simp: primepow_factors_def prime_factors_multiplicity multiplicity_dvd')
       
   266 
       
   267 lemma finite_primepow_factors:
       
   268   assumes "x \<noteq> (0 :: 'a :: factorial_semiring)"
       
   269   shows   "finite (primepow_factors x)"
       
   270 proof -
       
   271   have "finite (SIGMA p:prime_factors x. {0<..multiplicity p x})"
       
   272     by (intro finite_SigmaI) simp_all
       
   273   hence "finite ((\<lambda>(p,k). p ^ k) ` \<dots>)" (is "finite ?A") by (rule finite_imageI)
       
   274   also have "?A = primepow_factors x"
       
   275     using assms by (subst primepow_factors_altdef) fast+
       
   276   finally show ?thesis .
       
   277 qed
       
   278 
       
   279 
       
   280 definition mangoldt :: "nat \<Rightarrow> 'a :: real_algebra_1" where
       
   281   "mangoldt n = (if primepow n then of_real (ln (real (aprimedivisor n))) else 0)"
       
   282   
       
   283 lemma of_real_mangoldt [simp]: "of_real (mangoldt n) = mangoldt n"
       
   284   by (simp add: mangoldt_def)
       
   285 
       
   286 lemma mangoldt_sum:
       
   287   assumes "n \<noteq> 0"
       
   288   shows   "(\<Sum>d | d dvd n. mangoldt d :: 'a :: real_algebra_1) = of_real (ln (real n))"
       
   289 proof -
       
   290   have "(\<Sum>d | d dvd n. mangoldt d :: 'a) = of_real (\<Sum>d | d dvd n. mangoldt d)" by simp
       
   291   also have "(\<Sum>d | d dvd n. mangoldt d) = (\<Sum>d \<in> primepow_factors n. ln (real (aprimedivisor d)))"
       
   292     using assms by (intro sum.mono_neutral_cong_right) (auto simp: primepow_factors_def mangoldt_def)
       
   293   also have "\<dots> = ln (real (\<Prod>d \<in> primepow_factors n. aprimedivisor d))"
       
   294     using assms finite_primepow_factors[of n]
       
   295     by (subst ln_prod [symmetric])
       
   296        (auto simp: primepow_factors_def intro!: aprimedivisor_pos_nat 
       
   297              intro: Nat.gr0I primepow_gt_Suc_0)
       
   298   also have "primepow_factors n = 
       
   299                (\<lambda>(p,k). p ^ k) ` (SIGMA p:prime_factors n. {0<..multiplicity p n})" 
       
   300     (is "_ = _ ` ?A") by (subst primepow_factors_altdef[OF assms]) fast+
       
   301   also have "prod aprimedivisor \<dots> = (\<Prod>(p,k)\<in>?A. aprimedivisor (p ^ k))"
       
   302     by (subst prod.reindex)
       
   303        (auto simp: inj_on_def prime_power_inj'' prime_factors_multiplicity 
       
   304                    prod.Sigma [symmetric] case_prod_unfold)
       
   305   also have "\<dots> = (\<Prod>(p,k)\<in>?A. p)" 
       
   306     by (intro prod.cong refl) (auto simp: aprimedivisor_prime_power prime_factors_multiplicity)
       
   307   also have "\<dots> = (\<Prod>x\<in>prime_factors n. \<Prod>k\<in>{0<..multiplicity x n}. x)"
       
   308     by (rule prod.Sigma [symmetric]) auto
       
   309   also have "\<dots> = (\<Prod>x\<in>prime_factors n. x ^ multiplicity x n)" 
       
   310     by (intro prod.cong refl) (simp add: prod_constant)
       
   311   also have "\<dots> = n" using assms by (intro prime_factorization_nat [symmetric]) simp
       
   312   finally show ?thesis .
       
   313 qed
       
   314   
       
   315 end