src/HOL/ex/Factorization.ML
author nipkow
Tue, 28 Mar 2000 17:31:36 +0200
changeset 8600 a466c687c726
parent 8528 6c48043ccd0e
child 8935 548901d05a0e
permissions -rw-r--r--
mods because of weak_case_cong
paulson@8353
     1
(*  Title:      HOL/ex/Factorization.thy
paulson@8353
     2
    ID:         $Id$
paulson@8353
     3
    Author:     Thomas Marthedal Rasmussen
paulson@8353
     4
    Copyright   2000  University of Cambridge
paulson@8353
     5
paulson@8353
     6
Fundamental Theorem of Arithmetic (unique factorization into primes)
paulson@8353
     7
*)
paulson@8353
     8
paulson@8353
     9
paulson@8353
    10
(* --- Arithmetic --- *)
paulson@8353
    11
paulson@8353
    12
Goal "[| m ~= m*k; m ~= 1 |] ==> 1<m";
wenzelm@8442
    13
by (case_tac "m" 1);
paulson@8353
    14
by Auto_tac;
paulson@8353
    15
qed "one_less_m";
paulson@8353
    16
paulson@8353
    17
Goal "[| m ~= m*k; 1<m*k |] ==> 1<k";
wenzelm@8442
    18
by (case_tac "k" 1);
paulson@8353
    19
by Auto_tac;
paulson@8353
    20
qed "one_less_k";
paulson@8353
    21
paulson@8353
    22
Goal "[| 0<k; k*n=k*m |] ==> n=m";
paulson@8353
    23
by Auto_tac;
paulson@8353
    24
qed "mult_left_cancel";
paulson@8353
    25
paulson@8353
    26
Goal "[| 0<m; m*n = m |] ==> n=1";
wenzelm@8442
    27
by (case_tac "n" 1);
paulson@8353
    28
by Auto_tac;
paulson@8353
    29
qed "mn_eq_m_one";
paulson@8353
    30
paulson@8353
    31
Goal "[| 0<n; 0<k |] ==> 1<m --> m*n = k --> n<k";
paulson@8353
    32
by (induct_tac "m" 1);
paulson@8353
    33
by Auto_tac;
paulson@8353
    34
qed_spec_mp "prod_mn_less_k";
paulson@8353
    35
paulson@8353
    36
paulson@8353
    37
(* --- Prime List & Product --- *)
paulson@8353
    38
paulson@8353
    39
Goal "prod (xs @ ys) = prod xs * prod ys"; 
paulson@8353
    40
by (induct_tac "xs" 1);
paulson@8353
    41
by (ALLGOALS (asm_simp_tac (simpset() addsimps [mult_assoc])));
paulson@8353
    42
qed "prod_append";
paulson@8353
    43
paulson@8353
    44
Goal "prod (x#xs) = prod (y#ys) ==> x*prod xs = y*prod ys";
paulson@8353
    45
by Auto_tac;
paulson@8353
    46
qed "prod_xy_prod";
paulson@8353
    47
paulson@8353
    48
Goalw [primel_def] "primel (xs @ ys) = (primel xs & primel ys)";
paulson@8353
    49
by Auto_tac;
paulson@8353
    50
qed "primel_append";
paulson@8353
    51
paulson@8353
    52
Goalw [primel_def] "n:prime ==> primel [n] & prod [n] = n";
paulson@8353
    53
by Auto_tac;
paulson@8353
    54
qed "prime_primel";
paulson@8353
    55
paulson@8353
    56
Goalw [prime_def,dvd_def] "p:prime ==> ~(p dvd 1)";
paulson@8353
    57
by Auto_tac;
wenzelm@8442
    58
by (case_tac "k" 1);
paulson@8353
    59
by Auto_tac;
paulson@8353
    60
qed "prime_nd_one";
paulson@8353
    61
paulson@8353
    62
Goalw [dvd_def] "[| prod (x#xs) = prod ys |] ==> x dvd (prod ys)";
paulson@8353
    63
by (rtac exI 1);
paulson@8353
    64
by (rtac sym 1);
paulson@8353
    65
by (Asm_full_simp_tac 1);
paulson@8353
    66
qed "hd_dvd_prod";
paulson@8353
    67
paulson@8353
    68
Goalw [primel_def] "primel (x#xs) ==> primel xs";
paulson@8353
    69
by Auto_tac;
paulson@8353
    70
qed "primel_tl";
paulson@8353
    71
paulson@8353
    72
Goalw [primel_def] "(primel (x#xs)) = (x:prime & primel xs)"; 
paulson@8353
    73
by Auto_tac;
paulson@8353
    74
qed "primel_hd_tl";
paulson@8353
    75
paulson@8353
    76
Goalw [prime_def] "[| p:prime; q:prime; p dvd q |] ==> p=q";
paulson@8353
    77
by Auto_tac;
paulson@8353
    78
qed "primes_eq";
paulson@8353
    79
paulson@8353
    80
Goalw [primel_def,prime_def] "[| primel xs; prod xs = 1 |] ==> xs = []";
wenzelm@8442
    81
by (case_tac "xs" 1);
paulson@8353
    82
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
    83
qed "primel_one_empty";
paulson@8353
    84
paulson@8353
    85
Goalw [prime_def] "p:prime ==> 1<p";
paulson@8353
    86
by Auto_tac;
paulson@8353
    87
qed "prime_g_one";
paulson@8353
    88
paulson@8353
    89
Goalw [prime_def] "p:prime ==> 0<p";
paulson@8353
    90
by Auto_tac;
paulson@8353
    91
qed "prime_g_zero";
paulson@8353
    92
paulson@8353
    93
Goalw [primel_def,prime_def] "primel xs --> xs ~= [] --> 1 < prod xs";
paulson@8353
    94
by (induct_tac "xs" 1);
paulson@8353
    95
by (auto_tac (claset() addEs [one_less_mult], simpset()));
paulson@8353
    96
qed_spec_mp "primel_nempty_g_one";
paulson@8353
    97
paulson@8353
    98
Goalw [primel_def,prime_def] "primel xs --> 0 < prod xs"; 
paulson@8353
    99
by (induct_tac "xs" 1);
paulson@8353
   100
by Auto_tac;
paulson@8353
   101
qed_spec_mp "primel_prod_gz";
paulson@8353
   102
paulson@8353
   103
paulson@8353
   104
(* --- Sorting --- *)
paulson@8353
   105
paulson@8353
   106
Goal "nondec xs --> nondec (oinsert x xs)";
paulson@8353
   107
by (induct_tac "xs" 1);
wenzelm@8442
   108
by (case_tac "list" 2);
nipkow@8600
   109
by (ALLGOALS(asm_full_simp_tac (simpset()delcongs[thm"list.weak_case_cong"])));
paulson@8353
   110
qed_spec_mp "nondec_oinsert";
paulson@8353
   111
paulson@8353
   112
Goal "nondec (sort xs)";
paulson@8353
   113
by (induct_tac "xs" 1);
paulson@8353
   114
by (ALLGOALS (Asm_full_simp_tac));
paulson@8353
   115
by (etac nondec_oinsert 1);
paulson@8353
   116
qed "nondec_sort";
paulson@8353
   117
paulson@8353
   118
Goal "[| x<=y; l=y#ys |]  ==> x#l = oinsert x l";
paulson@8353
   119
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
   120
qed "x_less_y_oinsert";
paulson@8353
   121
paulson@8353
   122
Goal "nondec xs --> xs = sort xs";
paulson@8353
   123
by (induct_tac "xs" 1);
paulson@8353
   124
by Safe_tac;
paulson@8353
   125
by (ALLGOALS Asm_full_simp_tac);
wenzelm@8442
   126
by (case_tac "list" 1);
paulson@8353
   127
by (ALLGOALS Asm_full_simp_tac);
wenzelm@8442
   128
by (case_tac "list" 1);
paulson@8353
   129
by (Asm_full_simp_tac 1);
paulson@8353
   130
by (res_inst_tac [("y","aa"),("ys","lista")] x_less_y_oinsert 1); 
paulson@8353
   131
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
   132
qed_spec_mp "nondec_sort_eq";
paulson@8353
   133
paulson@8353
   134
Goal "oinsert x (oinsert y l) = oinsert y (oinsert x l)";
paulson@8353
   135
by (induct_tac "l" 1);
paulson@8528
   136
by Auto_tac;
paulson@8353
   137
qed "oinsert_x_y";
paulson@8353
   138
paulson@8353
   139
paulson@8353
   140
(* --- Permutation --- *)
paulson@8353
   141
paulson@8353
   142
Goalw [primel_def] "xs <~~> ys ==> primel xs --> primel ys";
paulson@8353
   143
by (etac perm.induct 1);
paulson@8353
   144
by (ALLGOALS Asm_simp_tac);
paulson@8353
   145
qed_spec_mp "perm_primel";
paulson@8353
   146
paulson@8353
   147
Goal "xs <~~> ys ==> prod xs = prod ys";
paulson@8353
   148
by (etac perm.induct 1);
paulson@8528
   149
by (ALLGOALS (asm_simp_tac (simpset() addsimps mult_ac)));
paulson@8353
   150
qed_spec_mp "perm_prod";
paulson@8353
   151
paulson@8353
   152
Goal "xs <~~> ys ==> oinsert a xs <~~> oinsert a ys"; 
paulson@8353
   153
by (etac perm.induct 1);
paulson@8528
   154
by Auto_tac;
paulson@8353
   155
qed "perm_subst_oinsert";
paulson@8353
   156
paulson@8353
   157
Goal "x#xs <~~> oinsert x xs";
paulson@8353
   158
by (induct_tac "xs" 1);
paulson@8528
   159
by Auto_tac;
paulson@8353
   160
qed "perm_oinsert";
paulson@8353
   161
paulson@8353
   162
Goal "xs <~~> sort xs";
paulson@8353
   163
by (induct_tac "xs" 1);
paulson@8528
   164
by (auto_tac (claset() addIs [perm_oinsert] 
paulson@8353
   165
	               addEs [perm_subst_oinsert],
paulson@8528
   166
              simpset()));
paulson@8353
   167
qed "perm_sort";
paulson@8353
   168
paulson@8353
   169
Goal "xs <~~> ys ==> sort xs = sort ys";
paulson@8353
   170
by (etac perm.induct 1);
paulson@8353
   171
by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [oinsert_x_y])));
paulson@8353
   172
qed "perm_sort_eq";
paulson@8353
   173
paulson@8353
   174
paulson@8353
   175
(* --- Existence --- *)
paulson@8353
   176
paulson@8353
   177
Goal "primel xs ==> EX ys. primel ys & nondec ys & prod ys = prod xs";
paulson@8353
   178
by (blast_tac (claset() addIs [nondec_sort, perm_prod,perm_primel,perm_sort,
paulson@8353
   179
			       perm_sym]) 1);
paulson@8353
   180
qed "ex_nondec_lemma";
paulson@8353
   181
paulson@8353
   182
Goalw [prime_def,dvd_def]
paulson@8353
   183
     "1<n & n~:prime --> (EX m k.1<m & 1<k & m<n & k<n & n=m*k)";
paulson@8353
   184
by (auto_tac (claset() addIs [n_less_m_mult_n, n_less_n_mult_m,
paulson@8353
   185
			      one_less_m, one_less_k], 
paulson@8353
   186
	      simpset()));
paulson@8353
   187
qed_spec_mp "not_prime_ex_mk";
paulson@8353
   188
paulson@8353
   189
Goal "[| primel xs; primel ys |] \
paulson@8353
   190
\     ==> EX l. primel l & prod l = prod xs * prod ys";
paulson@8353
   191
by (rtac exI 1);
paulson@8353
   192
by Safe_tac;
paulson@8353
   193
by (rtac prod_append 2);
paulson@8353
   194
by (asm_simp_tac (simpset() addsimps [primel_append]) 1);
paulson@8353
   195
qed "split_primel";
paulson@8353
   196
paulson@8353
   197
Goal "1<n --> (EX l. primel l & prod l = n)"; 
paulson@8353
   198
by (res_inst_tac [("n","n")] less_induct 1);
paulson@8353
   199
by (rtac impI 1);
paulson@8353
   200
by (case_tac "n:prime" 1);
paulson@8353
   201
by (rtac exI 1);
paulson@8353
   202
by (etac prime_primel 1);
paulson@8353
   203
by (cut_inst_tac [("n","n")] not_prime_ex_mk 1);
paulson@8353
   204
by (auto_tac (claset() addSIs [split_primel], simpset()));
paulson@8353
   205
qed_spec_mp "factor_exists";
paulson@8353
   206
paulson@8353
   207
Goal "1<n ==> (EX l. primel l & nondec l & prod l = n)"; 
paulson@8353
   208
by (etac (factor_exists RS exE) 1);
paulson@8353
   209
by (blast_tac (claset() addSIs [ex_nondec_lemma]) 1);
paulson@8353
   210
qed "nondec_factor_exists";
paulson@8353
   211
paulson@8353
   212
paulson@8353
   213
(* --- Uniqueness --- *)
paulson@8353
   214
paulson@8353
   215
Goal "p:prime ==> p dvd (prod xs) --> (EX m. m:set xs & p dvd m)";
paulson@8353
   216
by (induct_tac "xs" 1);
paulson@8353
   217
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
   218
by (etac prime_nd_one 1);
paulson@8353
   219
by (rtac impI 1);
paulson@8353
   220
by (dtac prime_dvd_mult 1);
paulson@8353
   221
by Auto_tac;
paulson@8353
   222
qed_spec_mp "prime_dvd_mult_list";
paulson@8353
   223
paulson@8353
   224
Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] \
paulson@8353
   225
\     ==> EX m. m :set ys & x dvd m";
paulson@8353
   226
by (rtac prime_dvd_mult_list 1);
paulson@8353
   227
by (etac hd_dvd_prod 2);
paulson@8353
   228
by (asm_full_simp_tac (simpset() addsimps [primel_hd_tl]) 1);
paulson@8353
   229
qed "hd_xs_dvd_prod";
paulson@8353
   230
paulson@8353
   231
Goal "[| primel (x#xs); primel ys; m:set ys; x dvd m |] ==> x=m";
paulson@8353
   232
by (rtac primes_eq 1);
paulson@8353
   233
by (auto_tac (claset(), simpset() addsimps [primel_def,primel_hd_tl]));
paulson@8353
   234
qed "prime_dvd_eq";
paulson@8353
   235
paulson@8353
   236
Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] ==> x:set ys";
paulson@8353
   237
by (ftac hd_xs_dvd_prod 1);
paulson@8353
   238
by Auto_tac;
paulson@8353
   239
by (dtac prime_dvd_eq 1);
paulson@8353
   240
by Auto_tac;
paulson@8353
   241
qed "hd_xs_eq_prod";
paulson@8353
   242
paulson@8353
   243
Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] \
paulson@8353
   244
\     ==> EX l. ys <~~> (x#l)";
paulson@8353
   245
by (rtac exI 1);
paulson@8353
   246
by (rtac perm_remove 1);
paulson@8353
   247
by (etac hd_xs_eq_prod 1);
paulson@8353
   248
by (ALLGOALS assume_tac);
paulson@8353
   249
qed "perm_primel_ex";
paulson@8353
   250
paulson@8353
   251
Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] \
paulson@8353
   252
\     ==> prod xs < prod ys";
paulson@8353
   253
by (auto_tac (claset() addIs [prod_mn_less_k,prime_g_one,primel_prod_gz],
paulson@8353
   254
              simpset() addsimps [primel_hd_tl]));
paulson@8353
   255
qed "primel_prod_less";
paulson@8353
   256
paulson@8353
   257
Goal "[| primel xs; p*prod xs = p; p:prime |] ==> xs=[]";
paulson@8353
   258
by (auto_tac (claset() addIs [primel_one_empty,mn_eq_m_one,prime_g_zero], 
paulson@8353
   259
	      simpset()));
paulson@8353
   260
qed "prod_one_empty";
paulson@8353
   261
paulson@8353
   262
Goal "[| ALL m. m < prod ys --> (ALL xs ys. primel xs & primel ys & \
paulson@8353
   263
\        prod xs = prod ys & prod xs = m --> xs <~~> ys); primel list; \
paulson@8353
   264
\        primel x; prod list = prod x; prod x < prod ys |] ==> x <~~> list";
paulson@8353
   265
by (Asm_full_simp_tac 1);
paulson@8353
   266
qed "uniq_ex_lemma";
paulson@8353
   267
paulson@8353
   268
Goal "ALL xs ys. (primel xs & primel ys & prod xs = prod ys & prod xs = n \
paulson@8353
   269
\     --> xs <~~> ys)";
paulson@8353
   270
by (res_inst_tac [("n","n")] less_induct 1);
paulson@8353
   271
by Safe_tac;
wenzelm@8442
   272
by (case_tac "xs" 1);
paulson@8353
   273
by (force_tac (claset() addIs [primel_one_empty], simpset()) 1);
paulson@8353
   274
by (rtac (perm_primel_ex RS exE) 1);
paulson@8353
   275
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
   276
by (rtac (perm.trans RS perm_sym) 1);
paulson@8353
   277
by (assume_tac 1);
paulson@8353
   278
by (rtac perm.Cons 1);
paulson@8353
   279
by (case_tac "x=[]" 1);
paulson@8353
   280
by (asm_full_simp_tac (simpset() addsimps [perm_sing_eq,primel_hd_tl]) 1);
paulson@8353
   281
by (res_inst_tac [("p","a")] prod_one_empty 1);
paulson@8353
   282
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
   283
by (etac uniq_ex_lemma 1);
paulson@8353
   284
by (auto_tac (claset() addIs [primel_tl,perm_primel],
paulson@8353
   285
	      simpset() addsimps [primel_hd_tl]));
paulson@8353
   286
by (res_inst_tac [("k","a"),("n","prod list"),("m","prod x")] mult_left_cancel 1);
paulson@8353
   287
by (res_inst_tac [("x","a")] primel_prod_less 3);
paulson@8353
   288
by (rtac prod_xy_prod 2);
paulson@8353
   289
by (res_inst_tac [("s","prod ys")] trans 2);
paulson@8353
   290
by (etac perm_prod 3);
paulson@8353
   291
by (etac (perm_prod RS sym) 5); 
paulson@8353
   292
by (auto_tac (claset() addIs [perm_primel,prime_g_zero], simpset()));
paulson@8353
   293
qed_spec_mp "factor_unique";
paulson@8353
   294
paulson@8353
   295
Goal "[| xs <~~> ys; nondec xs; nondec ys |] ==> xs = ys"; 
paulson@8353
   296
by (rtac trans 1);
paulson@8353
   297
by (rtac trans 1);
paulson@8353
   298
by (etac nondec_sort_eq 1);
paulson@8353
   299
by (etac perm_sort_eq 1);
paulson@8353
   300
by (etac (nondec_sort_eq RS sym) 1);
paulson@8353
   301
qed "perm_nondec_unique";
paulson@8353
   302
paulson@8353
   303
Goal "ALL n. 1<n --> (EX! l. primel l & nondec l & prod l = n)";
paulson@8353
   304
by Safe_tac;
paulson@8353
   305
by (etac nondec_factor_exists 1);
paulson@8353
   306
by (rtac perm_nondec_unique 1);
paulson@8353
   307
by (rtac factor_unique 1);
paulson@8353
   308
by (ALLGOALS Asm_full_simp_tac);
paulson@8353
   309
qed_spec_mp "unique_prime_factorization";