| author | wenzelm | 
| Thu, 19 Nov 2009 13:00:16 +0100 | |
| changeset 33763 | b1fbd5f3cfb4 | 
| parent 32960 | 69916a850301 | 
| child 37288 | 2b1c6dd48995 | 
| permissions | -rw-r--r-- | 
| 25422 | 1 | (* Title: HOL/Extraction/Euclid.thy | 
| 2 | Author: Markus Wenzel, TU Muenchen | |
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 3 | Author: Freek Wiedijk, Radboud University Nijmegen | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 4 | Author: Stefan Berghofer, TU Muenchen | 
| 25422 | 5 | *) | 
| 6 | ||
| 7 | header {* Euclid's theorem *}
 | |
| 8 | ||
| 9 | theory Euclid | |
| 32479 | 10 | imports "~~/src/HOL/Old_Number_Theory/Factorization" Util Efficient_Nat | 
| 25422 | 11 | begin | 
| 12 | ||
| 13 | text {*
 | |
| 14 | A constructive version of the proof of Euclid's theorem by | |
| 15 | Markus Wenzel and Freek Wiedijk \cite{Wenzel-Wiedijk-JAR2002}.
 | |
| 16 | *} | |
| 17 | ||
| 18 | lemma prime_eq: "prime p = (1 < p \<and> (\<forall>m. m dvd p \<longrightarrow> 1 < m \<longrightarrow> m = p))" | |
| 19 | apply (simp add: prime_def) | |
| 20 | apply (rule iffI) | |
| 21 | apply blast | |
| 22 | apply (erule conjE) | |
| 23 | apply (rule conjI) | |
| 24 | apply assumption | |
| 25 | apply (rule allI impI)+ | |
| 26 | apply (erule allE) | |
| 27 | apply (erule impE) | |
| 28 | apply assumption | |
| 29 | apply (case_tac "m=0") | |
| 30 | apply simp | |
| 31 | apply (case_tac "m=Suc 0") | |
| 32 | apply simp | |
| 33 | apply simp | |
| 34 | done | |
| 35 | ||
| 36 | lemma prime_eq': "prime p = (1 < p \<and> (\<forall>m k. p = m * k \<longrightarrow> 1 < m \<longrightarrow> m = p))" | |
| 37 | by (simp add: prime_eq dvd_def all_simps [symmetric] del: all_simps) | |
| 38 | ||
| 39 | lemma factor_greater_one1: "n = m * k \<Longrightarrow> m < n \<Longrightarrow> k < n \<Longrightarrow> Suc 0 < m" | |
| 40 | by (induct m) auto | |
| 41 | ||
| 42 | lemma factor_greater_one2: "n = m * k \<Longrightarrow> m < n \<Longrightarrow> k < n \<Longrightarrow> Suc 0 < k" | |
| 43 | by (induct k) auto | |
| 44 | ||
| 45 | lemma not_prime_ex_mk: | |
| 46 | assumes n: "Suc 0 < n" | |
| 47 | shows "(\<exists>m k. Suc 0 < m \<and> Suc 0 < k \<and> m < n \<and> k < n \<and> n = m * k) \<or> prime n" | |
| 48 | proof - | |
| 49 |   {
 | |
| 50 | fix k | |
| 51 | from nat_eq_dec | |
| 52 | have "(\<exists>m<n. n = m * k) \<or> \<not> (\<exists>m<n. n = m * k)" | |
| 53 | by (rule search) | |
| 54 | } | |
| 55 | hence "(\<exists>k<n. \<exists>m<n. n = m * k) \<or> \<not> (\<exists>k<n. \<exists>m<n. n = m * k)" | |
| 56 | by (rule search) | |
| 57 | thus ?thesis | |
| 58 | proof | |
| 59 | assume "\<exists>k<n. \<exists>m<n. n = m * k" | |
| 60 | then obtain k m where k: "k<n" and m: "m<n" and nmk: "n = m * k" | |
| 61 | by iprover | |
| 62 | from nmk m k have "Suc 0 < m" by (rule factor_greater_one1) | |
| 63 | moreover from nmk m k have "Suc 0 < k" by (rule factor_greater_one2) | |
| 64 | ultimately show ?thesis using k m nmk by iprover | |
| 65 | next | |
| 66 | assume "\<not> (\<exists>k<n. \<exists>m<n. n = m * k)" | |
| 67 | hence A: "\<forall>k<n. \<forall>m<n. n \<noteq> m * k" by iprover | |
| 68 | have "\<forall>m k. n = m * k \<longrightarrow> Suc 0 < m \<longrightarrow> m = n" | |
| 69 | proof (intro allI impI) | |
| 70 | fix m k | |
| 71 | assume nmk: "n = m * k" | |
| 72 | assume m: "Suc 0 < m" | |
| 73 | from n m nmk have k: "0 < k" | |
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 74 | by (cases k) auto | 
| 25422 | 75 | moreover from n have n: "0 < n" by simp | 
| 76 | moreover note m | |
| 77 | moreover from nmk have "m * k = n" by simp | |
| 78 | ultimately have kn: "k < n" by (rule prod_mn_less_k) | |
| 79 | show "m = n" | |
| 80 | proof (cases "k = Suc 0") | |
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 81 | case True | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 82 | with nmk show ?thesis by (simp only: mult_Suc_right) | 
| 25422 | 83 | next | 
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 84 | case False | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 85 | from m have "0 < m" by simp | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 86 | moreover note n | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 87 | moreover from False n nmk k have "Suc 0 < k" by auto | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 88 | moreover from nmk have "k * m = n" by (simp only: mult_ac) | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 89 | ultimately have mn: "m < n" by (rule prod_mn_less_k) | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32479diff
changeset | 90 | with kn A nmk show ?thesis by iprover | 
| 25422 | 91 | qed | 
| 92 | qed | |
| 93 | with n have "prime n" | |
| 94 | by (simp only: prime_eq' One_nat_def simp_thms) | |
| 95 | thus ?thesis .. | |
| 96 | qed | |
| 97 | qed | |
| 98 | ||
| 99 | lemma factor_exists: "Suc 0 < n \<Longrightarrow> (\<exists>l. primel l \<and> prod l = n)" | |
| 100 | proof (induct n rule: nat_wf_ind) | |
| 101 | case (1 n) | |
| 102 | from `Suc 0 < n` | |
| 103 | have "(\<exists>m k. Suc 0 < m \<and> Suc 0 < k \<and> m < n \<and> k < n \<and> n = m * k) \<or> prime n" | |
| 104 | by (rule not_prime_ex_mk) | |
| 105 | then show ?case | |
| 106 | proof | |
| 107 | assume "\<exists>m k. Suc 0 < m \<and> Suc 0 < k \<and> m < n \<and> k < n \<and> n = m * k" | |
| 108 | then obtain m k where m: "Suc 0 < m" and k: "Suc 0 < k" and mn: "m < n" | |
| 109 | and kn: "k < n" and nmk: "n = m * k" by iprover | |
| 110 | from mn and m have "\<exists>l. primel l \<and> prod l = m" by (rule 1) | |
| 111 | then obtain l1 where primel_l1: "primel l1" and prod_l1_m: "prod l1 = m" | |
| 112 | by iprover | |
| 113 | from kn and k have "\<exists>l. primel l \<and> prod l = k" by (rule 1) | |
| 114 | then obtain l2 where primel_l2: "primel l2" and prod_l2_k: "prod l2 = k" | |
| 115 | by iprover | |
| 116 | from primel_l1 primel_l2 | |
| 117 | have "\<exists>l. primel l \<and> prod l = prod l1 * prod l2" | |
| 25687 
f92c9dfa7681
split_primel: salvaged original proof after blow with sledghammer
 wenzelm parents: 
25422diff
changeset | 118 | by (rule split_primel) | 
| 25422 | 119 | with prod_l1_m prod_l2_k nmk show ?thesis by simp | 
| 120 | next | |
| 121 | assume "prime n" | |
| 122 | hence "primel [n] \<and> prod [n] = n" by (rule prime_primel) | |
| 123 | thus ?thesis .. | |
| 124 | qed | |
| 125 | qed | |
| 126 | ||
| 127 | lemma dvd_prod [iff]: "n dvd prod (n # ns)" | |
| 128 | by simp | |
| 129 | ||
| 25976 | 130 | primrec fact :: "nat \<Rightarrow> nat"    ("(_!)" [1000] 999)
 | 
| 131 | where | |
| 132 | "0! = 1" | |
| 133 | | "(Suc n)! = n! * Suc n" | |
| 25422 | 134 | |
| 135 | lemma fact_greater_0 [iff]: "0 < n!" | |
| 136 | by (induct n) simp_all | |
| 137 | ||
| 138 | lemma dvd_factorial: "0 < m \<Longrightarrow> m \<le> n \<Longrightarrow> m dvd n!" | |
| 139 | proof (induct n) | |
| 140 | case 0 | |
| 141 | then show ?case by simp | |
| 142 | next | |
| 143 | case (Suc n) | |
| 144 | from `m \<le> Suc n` show ?case | |
| 145 | proof (rule le_SucE) | |
| 146 | assume "m \<le> n" | |
| 147 | with `0 < m` have "m dvd n!" by (rule Suc) | |
| 148 | then have "m dvd (n! * Suc n)" by (rule dvd_mult2) | |
| 149 | then show ?thesis by simp | |
| 150 | next | |
| 151 | assume "m = Suc n" | |
| 152 | then have "m dvd (n! * Suc n)" | |
| 153 | by (auto intro: dvdI simp: mult_ac) | |
| 154 | then show ?thesis by simp | |
| 155 | qed | |
| 156 | qed | |
| 157 | ||
| 158 | lemma prime_factor_exists: | |
| 159 | assumes N: "(1::nat) < n" | |
| 160 | shows "\<exists>p. prime p \<and> p dvd n" | |
| 161 | proof - | |
| 162 | from N obtain l where primel_l: "primel l" | |
| 163 | and prod_l: "n = prod l" using factor_exists | |
| 164 | by simp iprover | |
| 165 | from prems have "l \<noteq> []" | |
| 166 | by (auto simp add: primel_nempty_g_one) | |
| 167 | then obtain x xs where l: "l = x # xs" | |
| 168 | by (cases l) simp | |
| 169 | from primel_l l have "prime x" by (simp add: primel_hd_tl) | |
| 170 | moreover from primel_l l prod_l | |
| 171 | have "x dvd n" by (simp only: dvd_prod) | |
| 172 | ultimately show ?thesis by iprover | |
| 173 | qed | |
| 174 | ||
| 175 | text {*
 | |
| 176 | Euclid's theorem: there are infinitely many primes. | |
| 177 | *} | |
| 178 | ||
| 179 | lemma Euclid: "\<exists>p. prime p \<and> n < p" | |
| 180 | proof - | |
| 181 | let ?k = "n! + 1" | |
| 182 | have "1 < n! + 1" by simp | |
| 183 | then obtain p where prime: "prime p" and dvd: "p dvd ?k" using prime_factor_exists by iprover | |
| 184 | have "n < p" | |
| 185 | proof - | |
| 186 | have "\<not> p \<le> n" | |
| 187 | proof | |
| 188 | assume pn: "p \<le> n" | |
| 189 | from `prime p` have "0 < p" by (rule prime_g_zero) | |
| 190 | then have "p dvd n!" using pn by (rule dvd_factorial) | |
| 31953 | 191 | with dvd have "p dvd ?k - n!" by (rule dvd_diff_nat) | 
| 25422 | 192 | then have "p dvd 1" by simp | 
| 193 | with prime show False using prime_nd_one by auto | |
| 194 | qed | |
| 195 | then show ?thesis by simp | |
| 196 | qed | |
| 197 | with prime show ?thesis by iprover | |
| 198 | qed | |
| 199 | ||
| 200 | extract Euclid | |
| 201 | ||
| 202 | text {*
 | |
| 203 | The program extracted from the proof of Euclid's theorem looks as follows. | |
| 204 | @{thm [display] Euclid_def}
 | |
| 205 | The program corresponding to the proof of the factorization theorem is | |
| 206 | @{thm [display] factor_exists_def}
 | |
| 207 | *} | |
| 208 | ||
| 27982 | 209 | instantiation nat :: default | 
| 210 | begin | |
| 211 | ||
| 212 | definition "default = (0::nat)" | |
| 213 | ||
| 214 | instance .. | |
| 215 | ||
| 216 | end | |
| 25422 | 217 | |
| 27982 | 218 | instantiation list :: (type) default | 
| 219 | begin | |
| 220 | ||
| 221 | definition "default = []" | |
| 222 | ||
| 223 | instance .. | |
| 224 | ||
| 225 | end | |
| 226 | ||
| 227 | consts_code | |
| 228 |   default ("(error \"default\")")
 | |
| 25422 | 229 | |
| 27982 | 230 | lemma "factor_exists 1007 = [53, 19]" by evaluation | 
| 231 | lemma "factor_exists 1007 = [53, 19]" by eval | |
| 232 | ||
| 233 | lemma "factor_exists 567 = [7, 3, 3, 3, 3]" by evaluation | |
| 234 | lemma "factor_exists 567 = [7, 3, 3, 3, 3]" by eval | |
| 235 | ||
| 236 | lemma "factor_exists 345 = [23, 5, 3]" by evaluation | |
| 237 | lemma "factor_exists 345 = [23, 5, 3]" by eval | |
| 238 | ||
| 239 | lemma "factor_exists 999 = [37, 3, 3, 3]" by evaluation | |
| 240 | lemma "factor_exists 999 = [37, 3, 3, 3]" by eval | |
| 25422 | 241 | |
| 27982 | 242 | lemma "factor_exists 876 = [73, 3, 2, 2]" by evaluation | 
| 243 | lemma "factor_exists 876 = [73, 3, 2, 2]" by eval | |
| 244 | ||
| 245 | primrec iterate :: "nat \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a list" where
 | |
| 246 | "iterate 0 f x = []" | |
| 247 | | "iterate (Suc n) f x = (let y = f x in y # iterate n f y)" | |
| 248 | ||
| 249 | lemma "iterate 4 Euclid 0 = [2, 3, 7, 71]" by evaluation | |
| 250 | lemma "iterate 4 Euclid 0 = [2, 3, 7, 71]" by eval | |
| 251 | ||
| 25422 | 252 | end |