src/ZF/Arith.ML
changeset 4091 771b1f6422a8
parent 3840 e0baea4d485a
child 4839 a7322db15065
equal deleted inserted replaced
4090:9f1eaab75e8c 4091:771b1f6422a8
    39 \       a: C(0);  \
    39 \       a: C(0);  \
    40 \       !!m z. [| m: nat;  z: C(m) |] ==> b(m,z): C(succ(m))  \
    40 \       !!m z. [| m: nat;  z: C(m) |] ==> b(m,z): C(succ(m))  \
    41 \    |] ==> rec(n,a,b) : C(n)";
    41 \    |] ==> rec(n,a,b) : C(n)";
    42 by (rtac (major RS nat_induct) 1);
    42 by (rtac (major RS nat_induct) 1);
    43 by (ALLGOALS
    43 by (ALLGOALS
    44     (asm_simp_tac (!simpset addsimps prems)));
    44     (asm_simp_tac (simpset() addsimps prems)));
    45 qed "rec_type";
    45 qed "rec_type";
    46 
    46 
    47 Addsimps [rec_type, nat_0_le, nat_le_refl];
    47 Addsimps [rec_type, nat_0_le, nat_le_refl];
    48 val nat_typechecks = [rec_type, nat_0I, nat_1I, nat_succI, Ord_nat];
    48 val nat_typechecks = [rec_type, nat_0I, nat_1I, nat_succI, Ord_nat];
    49 
    49 
   110 (*Must simplify BEFORE the induction!!  (Else we get a critical pair)
   110 (*Must simplify BEFORE the induction!!  (Else we get a critical pair)
   111   succ(m) #- succ(n)   rewrites to   pred(succ(m) #- n)  *)
   111   succ(m) #- succ(n)   rewrites to   pred(succ(m) #- n)  *)
   112 qed_goalw "diff_succ_succ" Arith.thy [diff_def]
   112 qed_goalw "diff_succ_succ" Arith.thy [diff_def]
   113     "[| m:nat;  n:nat |] ==> succ(m) #- succ(n) = m #- n"
   113     "[| m:nat;  n:nat |] ==> succ(m) #- succ(n) = m #- n"
   114  (fn prems=>
   114  (fn prems=>
   115   [ (asm_simp_tac (!simpset addsimps prems) 1),
   115   [ (asm_simp_tac (simpset() addsimps prems) 1),
   116     (nat_ind_tac "n" prems 1),
   116     (nat_ind_tac "n" prems 1),
   117     (ALLGOALS (asm_simp_tac (!simpset addsimps prems))) ]);
   117     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]);
   118 
   118 
   119 Addsimps [diff_0, diff_0_eq_0, diff_succ_succ];
   119 Addsimps [diff_0, diff_0_eq_0, diff_succ_succ];
   120 
   120 
   121 val prems = goal Arith.thy 
   121 val prems = goal Arith.thy 
   122     "[| m:nat;  n:nat |] ==> m #- n le m";
   122     "[| m:nat;  n:nat |] ==> m #- n le m";
   123 by (rtac (prems MRS diff_induct) 1);
   123 by (rtac (prems MRS diff_induct) 1);
   124 by (etac leE 3);
   124 by (etac leE 3);
   125 by (ALLGOALS
   125 by (ALLGOALS
   126     (asm_simp_tac (!simpset addsimps (prems @ [le_iff, nat_into_Ord]))));
   126     (asm_simp_tac (simpset() addsimps (prems @ [le_iff, nat_into_Ord]))));
   127 qed "diff_le_self";
   127 qed "diff_le_self";
   128 
   128 
   129 (*** Simplification over add, mult, diff ***)
   129 (*** Simplification over add, mult, diff ***)
   130 
   130 
   131 val arith_typechecks = [add_type, mult_type, diff_type];
   131 val arith_typechecks = [add_type, mult_type, diff_type];
   137 (*Associative law for addition*)
   137 (*Associative law for addition*)
   138 qed_goal "add_assoc" Arith.thy 
   138 qed_goal "add_assoc" Arith.thy 
   139     "m:nat ==> (m #+ n) #+ k = m #+ (n #+ k)"
   139     "m:nat ==> (m #+ n) #+ k = m #+ (n #+ k)"
   140  (fn prems=>
   140  (fn prems=>
   141   [ (nat_ind_tac "m" prems 1),
   141   [ (nat_ind_tac "m" prems 1),
   142     (ALLGOALS (asm_simp_tac (!simpset addsimps prems))) ]);
   142     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]);
   143 
   143 
   144 (*The following two lemmas are used for add_commute and sometimes
   144 (*The following two lemmas are used for add_commute and sometimes
   145   elsewhere, since they are safe for rewriting.*)
   145   elsewhere, since they are safe for rewriting.*)
   146 qed_goal "add_0_right" Arith.thy
   146 qed_goal "add_0_right" Arith.thy
   147     "m:nat ==> m #+ 0 = m"
   147     "m:nat ==> m #+ 0 = m"
   148  (fn prems=>
   148  (fn prems=>
   149   [ (nat_ind_tac "m" prems 1),
   149   [ (nat_ind_tac "m" prems 1),
   150     (ALLGOALS (asm_simp_tac (!simpset addsimps prems))) ]); 
   150     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); 
   151 
   151 
   152 qed_goal "add_succ_right" Arith.thy
   152 qed_goal "add_succ_right" Arith.thy
   153     "m:nat ==> m #+ succ(n) = succ(m #+ n)"
   153     "m:nat ==> m #+ succ(n) = succ(m #+ n)"
   154  (fn prems=>
   154  (fn prems=>
   155   [ (nat_ind_tac "m" prems 1),
   155   [ (nat_ind_tac "m" prems 1),
   156     (ALLGOALS (asm_simp_tac (!simpset addsimps prems))) ]); 
   156     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); 
   157 
   157 
   158 Addsimps [add_0_right, add_succ_right];
   158 Addsimps [add_0_right, add_succ_right];
   159 
   159 
   160 (*Commutative law for addition*)  
   160 (*Commutative law for addition*)  
   161 qed_goal "add_commute" Arith.thy 
   161 qed_goal "add_commute" Arith.thy 
   165     (ALLGOALS Asm_simp_tac) ]);
   165     (ALLGOALS Asm_simp_tac) ]);
   166 
   166 
   167 (*for a/c rewriting*)
   167 (*for a/c rewriting*)
   168 qed_goal "add_left_commute" Arith.thy
   168 qed_goal "add_left_commute" Arith.thy
   169     "!!m n k. [| m:nat;  n:nat |] ==> m#+(n#+k)=n#+(m#+k)"
   169     "!!m n k. [| m:nat;  n:nat |] ==> m#+(n#+k)=n#+(m#+k)"
   170  (fn _ => [asm_simp_tac(!simpset addsimps [add_assoc RS sym, add_commute]) 1]);
   170  (fn _ => [asm_simp_tac(simpset() addsimps [add_assoc RS sym, add_commute]) 1]);
   171 
   171 
   172 (*Addition is an AC-operator*)
   172 (*Addition is an AC-operator*)
   173 val add_ac = [add_assoc, add_commute, add_left_commute];
   173 val add_ac = [add_assoc, add_commute, add_left_commute];
   174 
   174 
   175 (*Cancellation law on the left*)
   175 (*Cancellation law on the left*)
   192 (*right successor law for multiplication*)
   192 (*right successor law for multiplication*)
   193 qed_goal "mult_succ_right" Arith.thy 
   193 qed_goal "mult_succ_right" Arith.thy 
   194     "!!m n. [| m:nat;  n:nat |] ==> m #* succ(n) = m #+ (m #* n)"
   194     "!!m n. [| m:nat;  n:nat |] ==> m #* succ(n) = m #+ (m #* n)"
   195  (fn _ =>
   195  (fn _ =>
   196   [ (nat_ind_tac "m" [] 1),
   196   [ (nat_ind_tac "m" [] 1),
   197     (ALLGOALS (asm_simp_tac (!simpset addsimps add_ac))) ]);
   197     (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac))) ]);
   198 
   198 
   199 Addsimps [mult_0_right, mult_succ_right];
   199 Addsimps [mult_0_right, mult_succ_right];
   200 
   200 
   201 goal Arith.thy "!!n. n:nat ==> 1 #* n = n";
   201 goal Arith.thy "!!n. n:nat ==> 1 #* n = n";
   202 by (Asm_simp_tac 1);
   202 by (Asm_simp_tac 1);
   216 (*addition distributes over multiplication*)
   216 (*addition distributes over multiplication*)
   217 qed_goal "add_mult_distrib" Arith.thy 
   217 qed_goal "add_mult_distrib" Arith.thy 
   218     "!!m n. [| m:nat;  k:nat |] ==> (m #+ n) #* k = (m #* k) #+ (n #* k)"
   218     "!!m n. [| m:nat;  k:nat |] ==> (m #+ n) #* k = (m #* k) #+ (n #* k)"
   219  (fn _=>
   219  (fn _=>
   220   [ (etac nat_induct 1),
   220   [ (etac nat_induct 1),
   221     (ALLGOALS (asm_simp_tac (!simpset addsimps [add_assoc RS sym]))) ]);
   221     (ALLGOALS (asm_simp_tac (simpset() addsimps [add_assoc RS sym]))) ]);
   222 
   222 
   223 (*Distributive law on the left; requires an extra typing premise*)
   223 (*Distributive law on the left; requires an extra typing premise*)
   224 qed_goal "add_mult_distrib_left" Arith.thy 
   224 qed_goal "add_mult_distrib_left" Arith.thy 
   225     "!!m. [| m:nat;  n:nat;  k:nat |] ==> k #* (m #+ n) = (k #* m) #+ (k #* n)"
   225     "!!m. [| m:nat;  n:nat;  k:nat |] ==> k #* (m #+ n) = (k #* m) #+ (k #* n)"
   226  (fn prems=>
   226  (fn prems=>
   227   [ (nat_ind_tac "m" [] 1),
   227   [ (nat_ind_tac "m" [] 1),
   228     (Asm_simp_tac 1),
   228     (Asm_simp_tac 1),
   229     (asm_simp_tac (!simpset addsimps add_ac) 1) ]);
   229     (asm_simp_tac (simpset() addsimps add_ac) 1) ]);
   230 
   230 
   231 (*Associative law for multiplication*)
   231 (*Associative law for multiplication*)
   232 qed_goal "mult_assoc" Arith.thy 
   232 qed_goal "mult_assoc" Arith.thy 
   233     "!!m n k. [| m:nat;  n:nat;  k:nat |] ==> (m #* n) #* k = m #* (n #* k)"
   233     "!!m n k. [| m:nat;  n:nat;  k:nat |] ==> (m #* n) #* k = m #* (n #* k)"
   234  (fn _=>
   234  (fn _=>
   235   [ (etac nat_induct 1),
   235   [ (etac nat_induct 1),
   236     (ALLGOALS (asm_simp_tac (!simpset addsimps [add_mult_distrib]))) ]);
   236     (ALLGOALS (asm_simp_tac (simpset() addsimps [add_mult_distrib]))) ]);
   237 
   237 
   238 (*for a/c rewriting*)
   238 (*for a/c rewriting*)
   239 qed_goal "mult_left_commute" Arith.thy 
   239 qed_goal "mult_left_commute" Arith.thy 
   240     "!!m n k. [| m:nat;  n:nat;  k:nat |] ==> m #* (n #* k) = n #* (m #* k)"
   240     "!!m n k. [| m:nat;  n:nat;  k:nat |] ==> m #* (n #* k) = n #* (m #* k)"
   241  (fn _ => [rtac (mult_commute RS trans) 1, 
   241  (fn _ => [rtac (mult_commute RS trans) 1, 
   250 
   250 
   251 qed_goal "diff_self_eq_0" Arith.thy 
   251 qed_goal "diff_self_eq_0" Arith.thy 
   252     "m:nat ==> m #- m = 0"
   252     "m:nat ==> m #- m = 0"
   253  (fn prems=>
   253  (fn prems=>
   254   [ (nat_ind_tac "m" prems 1),
   254   [ (nat_ind_tac "m" prems 1),
   255     (ALLGOALS (asm_simp_tac (!simpset addsimps prems))) ]);
   255     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]);
   256 
   256 
   257 (*Addition is the inverse of subtraction*)
   257 (*Addition is the inverse of subtraction*)
   258 goal Arith.thy "!!m n. [| n le m;  m:nat |] ==> n #+ (m#-n) = m";
   258 goal Arith.thy "!!m n. [| n le m;  m:nat |] ==> n #+ (m#-n) = m";
   259 by (forward_tac [lt_nat_in_nat] 1);
   259 by (forward_tac [lt_nat_in_nat] 1);
   260 by (etac nat_succI 1);
   260 by (etac nat_succI 1);
   275 (** Subtraction is the inverse of addition. **)
   275 (** Subtraction is the inverse of addition. **)
   276 
   276 
   277 val [mnat,nnat] = goal Arith.thy
   277 val [mnat,nnat] = goal Arith.thy
   278     "[| m:nat;  n:nat |] ==> (n#+m) #- n = m";
   278     "[| m:nat;  n:nat |] ==> (n#+m) #- n = m";
   279 by (rtac (nnat RS nat_induct) 1);
   279 by (rtac (nnat RS nat_induct) 1);
   280 by (ALLGOALS (asm_simp_tac (!simpset addsimps [mnat])));
   280 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mnat])));
   281 qed "diff_add_inverse";
   281 qed "diff_add_inverse";
   282 
   282 
   283 goal Arith.thy
   283 goal Arith.thy
   284     "!!m n. [| m:nat;  n:nat |] ==> (m#+n) #- n = m";
   284     "!!m n. [| m:nat;  n:nat |] ==> (m#+n) #- n = m";
   285 by (res_inst_tac [("m1","m")] (add_commute RS ssubst) 1);
   285 by (res_inst_tac [("m1","m")] (add_commute RS ssubst) 1);
   293 qed "diff_cancel";
   293 qed "diff_cancel";
   294 
   294 
   295 goal Arith.thy
   295 goal Arith.thy
   296     "!!n. [| k:nat; m: nat; n: nat |] ==> (m#+k) #- (n#+k) = m #- n";
   296     "!!n. [| k:nat; m: nat; n: nat |] ==> (m#+k) #- (n#+k) = m #- n";
   297 val add_commute_k = read_instantiate [("n","k")] add_commute;
   297 val add_commute_k = read_instantiate [("n","k")] add_commute;
   298 by (asm_simp_tac (!simpset addsimps [add_commute_k, diff_cancel]) 1);
   298 by (asm_simp_tac (simpset() addsimps [add_commute_k, diff_cancel]) 1);
   299 qed "diff_cancel2";
   299 qed "diff_cancel2";
   300 
   300 
   301 val [mnat,nnat] = goal Arith.thy
   301 val [mnat,nnat] = goal Arith.thy
   302     "[| m:nat;  n:nat |] ==> n #- (n#+m) = 0";
   302     "[| m:nat;  n:nat |] ==> n #- (n#+m) = 0";
   303 by (rtac (nnat RS nat_induct) 1);
   303 by (rtac (nnat RS nat_induct) 1);
   304 by (ALLGOALS (asm_simp_tac (!simpset addsimps [mnat])));
   304 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mnat])));
   305 qed "diff_add_0";
   305 qed "diff_add_0";
   306 
   306 
   307 (** Difference distributes over multiplication **)
   307 (** Difference distributes over multiplication **)
   308 
   308 
   309 goal Arith.thy 
   309 goal Arith.thy 
   310   "!!m n. [| m:nat; n: nat; k:nat |] ==> (m #- n) #* k = (m #* k) #- (n #* k)";
   310   "!!m n. [| m:nat; n: nat; k:nat |] ==> (m #- n) #* k = (m #* k) #- (n #* k)";
   311 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   311 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   312 by (ALLGOALS (asm_simp_tac (!simpset addsimps [diff_cancel])));
   312 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_cancel])));
   313 qed "diff_mult_distrib" ;
   313 qed "diff_mult_distrib" ;
   314 
   314 
   315 goal Arith.thy 
   315 goal Arith.thy 
   316   "!!m. [| m:nat; n: nat; k:nat |] ==> k #* (m #- n) = (k #* m) #- (k #* n)";
   316   "!!m. [| m:nat; n: nat; k:nat |] ==> k #* (m #- n) = (k #* m) #- (k #* n)";
   317 val mult_commute_k = read_instantiate [("m","k")] mult_commute;
   317 val mult_commute_k = read_instantiate [("m","k")] mult_commute;
   318 by (asm_simp_tac (!simpset addsimps 
   318 by (asm_simp_tac (simpset() addsimps 
   319                   [mult_commute_k, diff_mult_distrib]) 1);
   319                   [mult_commute_k, diff_mult_distrib]) 1);
   320 qed "diff_mult_distrib2" ;
   320 qed "diff_mult_distrib2" ;
   321 
   321 
   322 (*** Remainder ***)
   322 (*** Remainder ***)
   323 
   323 
   324 goal Arith.thy "!!m n. [| 0<n;  n le m;  m:nat |] ==> m #- n < m";
   324 goal Arith.thy "!!m n. [| 0<n;  n le m;  m:nat |] ==> m #- n < m";
   325 by (forward_tac [lt_nat_in_nat] 1 THEN etac nat_succI 1);
   325 by (forward_tac [lt_nat_in_nat] 1 THEN etac nat_succI 1);
   326 by (etac rev_mp 1);
   326 by (etac rev_mp 1);
   327 by (etac rev_mp 1);
   327 by (etac rev_mp 1);
   328 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   328 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   329 by (ALLGOALS (asm_simp_tac (!simpset addsimps [diff_le_self,diff_succ_succ])));
   329 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_le_self,diff_succ_succ])));
   330 qed "div_termination";
   330 qed "div_termination";
   331 
   331 
   332 val div_rls =   (*for mod and div*)
   332 val div_rls =   (*for mod and div*)
   333     nat_typechecks @
   333     nat_typechecks @
   334     [Ord_transrec_type, apply_type, div_termination RS ltD, if_type,
   334     [Ord_transrec_type, apply_type, div_termination RS ltD, if_type,
   335      nat_into_Ord, not_lt_iff_le RS iffD1];
   335      nat_into_Ord, not_lt_iff_le RS iffD1];
   336 
   336 
   337 val div_ss = (!simpset) addsimps [nat_into_Ord, div_termination RS ltD,
   337 val div_ss = (simpset()) addsimps [nat_into_Ord, div_termination RS ltD,
   338                                   not_lt_iff_le RS iffD2];
   338                                   not_lt_iff_le RS iffD2];
   339 
   339 
   340 (*Type checking depends upon termination!*)
   340 (*Type checking depends upon termination!*)
   341 goalw Arith.thy [mod_def] "!!m n. [| 0<n;  m:nat;  n:nat |] ==> m mod n : nat";
   341 goalw Arith.thy [mod_def] "!!m n. [| 0<n;  m:nat;  n:nat |] ==> m mod n : nat";
   342 by (REPEAT (ares_tac div_rls 1 ORELSE etac lt_trans 1));
   342 by (REPEAT (ares_tac div_rls 1 ORELSE etac lt_trans 1));
   384 by (excluded_middle_tac "x<n" 1);
   384 by (excluded_middle_tac "x<n" 1);
   385 (*case x<n*)
   385 (*case x<n*)
   386 by (Asm_simp_tac 2);
   386 by (Asm_simp_tac 2);
   387 (*case n le x*)
   387 (*case n le x*)
   388 by (asm_full_simp_tac
   388 by (asm_full_simp_tac
   389      (!simpset addsimps [not_lt_iff_le, nat_into_Ord, add_assoc,
   389      (simpset() addsimps [not_lt_iff_le, nat_into_Ord, add_assoc,
   390                          div_termination RS ltD, add_diff_inverse]) 1);
   390                          div_termination RS ltD, add_diff_inverse]) 1);
   391 qed "mod_div_equality";
   391 qed "mod_div_equality";
   392 
   392 
   393 (*** Further facts about mod (mainly for mutilated checkerboard ***)
   393 (*** Further facts about mod (mainly for mutilated checkerboard ***)
   394 
   394 
   396     "!!m n. [| 0<n;  m:nat;  n:nat |] ==> \
   396     "!!m n. [| 0<n;  m:nat;  n:nat |] ==> \
   397 \           succ(m) mod n = if(succ(m mod n) = n, 0, succ(m mod n))";
   397 \           succ(m) mod n = if(succ(m mod n) = n, 0, succ(m mod n))";
   398 by (etac complete_induct 1);
   398 by (etac complete_induct 1);
   399 by (excluded_middle_tac "succ(x)<n" 1);
   399 by (excluded_middle_tac "succ(x)<n" 1);
   400 (* case succ(x) < n *)
   400 (* case succ(x) < n *)
   401 by (asm_simp_tac (!simpset addsimps [mod_less, nat_le_refl RS lt_trans,
   401 by (asm_simp_tac (simpset() addsimps [mod_less, nat_le_refl RS lt_trans,
   402                                      succ_neq_self]) 2);
   402                                      succ_neq_self]) 2);
   403 by (asm_simp_tac (!simpset addsimps [ltD RS mem_imp_not_eq]) 2);
   403 by (asm_simp_tac (simpset() addsimps [ltD RS mem_imp_not_eq]) 2);
   404 (* case n le succ(x) *)
   404 (* case n le succ(x) *)
   405 by (asm_full_simp_tac
   405 by (asm_full_simp_tac
   406      (!simpset addsimps [not_lt_iff_le, nat_into_Ord, mod_geq]) 1);
   406      (simpset() addsimps [not_lt_iff_le, nat_into_Ord, mod_geq]) 1);
   407 by (etac leE 1);
   407 by (etac leE 1);
   408 by (asm_simp_tac (!simpset addsimps [div_termination RS ltD, diff_succ, 
   408 by (asm_simp_tac (simpset() addsimps [div_termination RS ltD, diff_succ, 
   409                                      mod_geq]) 1);
   409                                      mod_geq]) 1);
   410 by (asm_simp_tac (!simpset addsimps [mod_less, diff_self_eq_0]) 1);
   410 by (asm_simp_tac (simpset() addsimps [mod_less, diff_self_eq_0]) 1);
   411 qed "mod_succ";
   411 qed "mod_succ";
   412 
   412 
   413 goal Arith.thy "!!m n. [| 0<n;  m:nat;  n:nat |] ==> m mod n < n";
   413 goal Arith.thy "!!m n. [| 0<n;  m:nat;  n:nat |] ==> m mod n < n";
   414 by (etac complete_induct 1);
   414 by (etac complete_induct 1);
   415 by (excluded_middle_tac "x<n" 1);
   415 by (excluded_middle_tac "x<n" 1);
   416 (*case x<n*)
   416 (*case x<n*)
   417 by (asm_simp_tac (!simpset addsimps [mod_less]) 2);
   417 by (asm_simp_tac (simpset() addsimps [mod_less]) 2);
   418 (*case n le x*)
   418 (*case n le x*)
   419 by (asm_full_simp_tac
   419 by (asm_full_simp_tac
   420      (!simpset addsimps [not_lt_iff_le, nat_into_Ord,
   420      (simpset() addsimps [not_lt_iff_le, nat_into_Ord,
   421                          mod_geq, div_termination RS ltD]) 1);
   421                          mod_geq, div_termination RS ltD]) 1);
   422 qed "mod_less_divisor";
   422 qed "mod_less_divisor";
   423 
   423 
   424 
   424 
   425 goal Arith.thy
   425 goal Arith.thy
   426     "!!k b. [| k: nat; b<2 |] ==> k mod 2 = b | k mod 2 = if(b=1,0,1)";
   426     "!!k b. [| k: nat; b<2 |] ==> k mod 2 = b | k mod 2 = if(b=1,0,1)";
   427 by (subgoal_tac "k mod 2: 2" 1);
   427 by (subgoal_tac "k mod 2: 2" 1);
   428 by (asm_simp_tac (!simpset addsimps [mod_less_divisor RS ltD]) 2);
   428 by (asm_simp_tac (simpset() addsimps [mod_less_divisor RS ltD]) 2);
   429 by (dtac ltD 1);
   429 by (dtac ltD 1);
   430 by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 1);
   430 by (asm_simp_tac (simpset() setloop split_tac [expand_if]) 1);
   431 by (Blast_tac 1);
   431 by (Blast_tac 1);
   432 qed "mod2_cases";
   432 qed "mod2_cases";
   433 
   433 
   434 goal Arith.thy "!!m. m:nat ==> succ(succ(m)) mod 2 = m mod 2";
   434 goal Arith.thy "!!m. m:nat ==> succ(succ(m)) mod 2 = m mod 2";
   435 by (subgoal_tac "m mod 2: 2" 1);
   435 by (subgoal_tac "m mod 2: 2" 1);
   436 by (asm_simp_tac (!simpset addsimps [mod_less_divisor RS ltD]) 2);
   436 by (asm_simp_tac (simpset() addsimps [mod_less_divisor RS ltD]) 2);
   437 by (asm_simp_tac (!simpset addsimps [mod_succ] setloop Step_tac) 1);
   437 by (asm_simp_tac (simpset() addsimps [mod_succ] setloop Step_tac) 1);
   438 qed "mod2_succ_succ";
   438 qed "mod2_succ_succ";
   439 
   439 
   440 goal Arith.thy "!!m. m:nat ==> (m#+m) mod 2 = 0";
   440 goal Arith.thy "!!m. m:nat ==> (m#+m) mod 2 = 0";
   441 by (etac nat_induct 1);
   441 by (etac nat_induct 1);
   442 by (simp_tac (!simpset addsimps [mod_less]) 1);
   442 by (simp_tac (simpset() addsimps [mod_less]) 1);
   443 by (asm_simp_tac (!simpset addsimps [mod2_succ_succ, add_succ_right]) 1);
   443 by (asm_simp_tac (simpset() addsimps [mod2_succ_succ, add_succ_right]) 1);
   444 qed "mod2_add_self";
   444 qed "mod2_add_self";
   445 
   445 
   446 
   446 
   447 (**** Additional theorems about "le" ****)
   447 (**** Additional theorems about "le" ****)
   448 
   448 
   461 (*strict, in 1st argument; proof is by rule induction on 'less than'*)
   461 (*strict, in 1st argument; proof is by rule induction on 'less than'*)
   462 goal Arith.thy "!!i j k. [| i<j; j:nat; k:nat |] ==> i#+k < j#+k";
   462 goal Arith.thy "!!i j k. [| i<j; j:nat; k:nat |] ==> i#+k < j#+k";
   463 by (forward_tac [lt_nat_in_nat] 1);
   463 by (forward_tac [lt_nat_in_nat] 1);
   464 by (assume_tac 1);
   464 by (assume_tac 1);
   465 by (etac succ_lt_induct 1);
   465 by (etac succ_lt_induct 1);
   466 by (ALLGOALS (asm_simp_tac (!simpset addsimps [leI])));
   466 by (ALLGOALS (asm_simp_tac (simpset() addsimps [leI])));
   467 qed "add_lt_mono1";
   467 qed "add_lt_mono1";
   468 
   468 
   469 (*strict, in both arguments*)
   469 (*strict, in both arguments*)
   470 goal Arith.thy "!!i j k l. [| i<j; k<l; j:nat; l:nat |] ==> i#+k < j#+l";
   470 goal Arith.thy "!!i j k l. [| i<j; k<l; j:nat; l:nat |] ==> i#+k < j#+l";
   471 by (rtac (add_lt_mono1 RS lt_trans) 1);
   471 by (rtac (add_lt_mono1 RS lt_trans) 1);
   507 (*** Monotonicity of Multiplication ***)
   507 (*** Monotonicity of Multiplication ***)
   508 
   508 
   509 goal Arith.thy "!!i j k. [| i le j; j:nat; k:nat |] ==> i#*k le j#*k";
   509 goal Arith.thy "!!i j k. [| i le j; j:nat; k:nat |] ==> i#*k le j#*k";
   510 by (forward_tac [lt_nat_in_nat] 1);
   510 by (forward_tac [lt_nat_in_nat] 1);
   511 by (nat_ind_tac "k" [] 2);
   511 by (nat_ind_tac "k" [] 2);
   512 by (ALLGOALS (asm_simp_tac (!simpset addsimps [add_le_mono])));
   512 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_le_mono])));
   513 qed "mult_le_mono1";
   513 qed "mult_le_mono1";
   514 
   514 
   515 (* le monotonicity, BOTH arguments*)
   515 (* le monotonicity, BOTH arguments*)
   516 goal Arith.thy
   516 goal Arith.thy
   517     "!!i j k. [| i le j; k le l; j:nat; l:nat |] ==> i#*k le j#*l";
   517     "!!i j k. [| i le j; k le l; j:nat; l:nat |] ==> i#*k le j#*l";
   527 goal Arith.thy "!!i j k. [| i<j; 0<k; j:nat; k:nat |] ==> k#*i < k#*j";
   527 goal Arith.thy "!!i j k. [| i<j; 0<k; j:nat; k:nat |] ==> k#*i < k#*j";
   528 by (etac zero_lt_natE 1);
   528 by (etac zero_lt_natE 1);
   529 by (forward_tac [lt_nat_in_nat] 2);
   529 by (forward_tac [lt_nat_in_nat] 2);
   530 by (ALLGOALS Asm_simp_tac);
   530 by (ALLGOALS Asm_simp_tac);
   531 by (nat_ind_tac "x" [] 1);
   531 by (nat_ind_tac "x" [] 1);
   532 by (ALLGOALS (asm_simp_tac (!simpset addsimps [add_lt_mono])));
   532 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_lt_mono])));
   533 qed "mult_lt_mono2";
   533 qed "mult_lt_mono2";
   534 
   534 
   535 goal Arith.thy "!!k. [| m: nat; n: nat |] ==> 0 < m#*n <-> 0<m & 0<n";
   535 goal Arith.thy "!!k. [| m: nat; n: nat |] ==> 0 < m#*n <-> 0<m & 0<n";
   536 by (best_tac (!claset addEs [natE] addss (!simpset)) 1);
   536 by (best_tac (claset() addEs [natE] addss (simpset())) 1);
   537 qed "zero_lt_mult_iff";
   537 qed "zero_lt_mult_iff";
   538 
   538 
   539 goal Arith.thy "!!k. [| m: nat; n: nat |] ==> m#*n = 1 <-> m=1 & n=1";
   539 goal Arith.thy "!!k. [| m: nat; n: nat |] ==> m#*n = 1 <-> m=1 & n=1";
   540 by (best_tac (!claset addEs [natE] addss (!simpset)) 1);
   540 by (best_tac (claset() addEs [natE] addss (simpset())) 1);
   541 qed "mult_eq_1_iff";
   541 qed "mult_eq_1_iff";
   542 
   542 
   543 (*Cancellation law for division*)
   543 (*Cancellation law for division*)
   544 goal Arith.thy
   544 goal Arith.thy
   545    "!!k. [| 0<n; 0<k; k:nat; m:nat; n:nat |] ==> (k#*m) div (k#*n) = m div n";
   545    "!!k. [| 0<n; 0<k; k:nat; m:nat; n:nat |] ==> (k#*m) div (k#*n) = m div n";
   546 by (eres_inst_tac [("i","m")] complete_induct 1);
   546 by (eres_inst_tac [("i","m")] complete_induct 1);
   547 by (excluded_middle_tac "x<n" 1);
   547 by (excluded_middle_tac "x<n" 1);
   548 by (asm_simp_tac (!simpset addsimps [div_less, zero_lt_mult_iff, 
   548 by (asm_simp_tac (simpset() addsimps [div_less, zero_lt_mult_iff, 
   549                                      mult_lt_mono2]) 2);
   549                                      mult_lt_mono2]) 2);
   550 by (asm_full_simp_tac
   550 by (asm_full_simp_tac
   551      (!simpset addsimps [not_lt_iff_le, nat_into_Ord,
   551      (simpset() addsimps [not_lt_iff_le, nat_into_Ord,
   552                          zero_lt_mult_iff, le_refl RS mult_le_mono, div_geq,
   552                          zero_lt_mult_iff, le_refl RS mult_le_mono, div_geq,
   553                          diff_mult_distrib2 RS sym,
   553                          diff_mult_distrib2 RS sym,
   554                          div_termination RS ltD]) 1);
   554                          div_termination RS ltD]) 1);
   555 qed "div_cancel";
   555 qed "div_cancel";
   556 
   556 
   557 goal Arith.thy
   557 goal Arith.thy
   558    "!!k. [| 0<n; 0<k; k:nat; m:nat; n:nat |] ==> \
   558    "!!k. [| 0<n; 0<k; k:nat; m:nat; n:nat |] ==> \
   559 \        (k#*m) mod (k#*n) = k #* (m mod n)";
   559 \        (k#*m) mod (k#*n) = k #* (m mod n)";
   560 by (eres_inst_tac [("i","m")] complete_induct 1);
   560 by (eres_inst_tac [("i","m")] complete_induct 1);
   561 by (excluded_middle_tac "x<n" 1);
   561 by (excluded_middle_tac "x<n" 1);
   562 by (asm_simp_tac (!simpset addsimps [mod_less, zero_lt_mult_iff, 
   562 by (asm_simp_tac (simpset() addsimps [mod_less, zero_lt_mult_iff, 
   563                                      mult_lt_mono2]) 2);
   563                                      mult_lt_mono2]) 2);
   564 by (asm_full_simp_tac
   564 by (asm_full_simp_tac
   565      (!simpset addsimps [not_lt_iff_le, nat_into_Ord,
   565      (simpset() addsimps [not_lt_iff_le, nat_into_Ord,
   566                          zero_lt_mult_iff, le_refl RS mult_le_mono, mod_geq,
   566                          zero_lt_mult_iff, le_refl RS mult_le_mono, mod_geq,
   567                          diff_mult_distrib2 RS sym,
   567                          diff_mult_distrib2 RS sym,
   568                          div_termination RS ltD]) 1);
   568                          div_termination RS ltD]) 1);
   569 qed "mult_mod_distrib";
   569 qed "mult_mod_distrib";
   570 
   570 
   574 
   574 
   575 goal Arith.thy "!!m n. [| m = m#*n; m: nat; n: nat |] ==> n=1 | m=0";
   575 goal Arith.thy "!!m n. [| m = m#*n; m: nat; n: nat |] ==> n=1 | m=0";
   576 by (rtac disjCI 1);
   576 by (rtac disjCI 1);
   577 by (dtac sym 1);
   577 by (dtac sym 1);
   578 by (rtac Ord_linear_lt 1 THEN REPEAT_SOME (ares_tac [nat_into_Ord,nat_1I]));
   578 by (rtac Ord_linear_lt 1 THEN REPEAT_SOME (ares_tac [nat_into_Ord,nat_1I]));
   579 by (fast_tac (!claset addss (!simpset)) 1);
   579 by (fast_tac (claset() addss (simpset())) 1);
   580 by (fast_tac (le_cs addDs [mono_lemma] 
   580 by (fast_tac (le_cs addDs [mono_lemma] 
   581                     addss (!simpset addsimps [mult_1_right])) 1);
   581                     addss (simpset() addsimps [mult_1_right])) 1);
   582 qed "mult_eq_self_implies_10";
   582 qed "mult_eq_self_implies_10";
   583 
   583 
   584 
   584 
   585 (*Thanks to Sten Agerholm*)
   585 (*Thanks to Sten Agerholm*)
   586 goal Arith.thy  (* add_le_elim1 *)
   586 goal Arith.thy  (* add_le_elim1 *)
   587     "!!m n k. [|m#+n le m#+k; m:nat; n:nat; k:nat|] ==> n le k";
   587     "!!m n k. [|m#+n le m#+k; m:nat; n:nat; k:nat|] ==> n le k";
   588 by (etac rev_mp 1);
   588 by (etac rev_mp 1);
   589 by (eres_inst_tac [("n","n")] nat_induct 1);
   589 by (eres_inst_tac [("n","n")] nat_induct 1);
   590 by (Asm_simp_tac 1);
   590 by (Asm_simp_tac 1);
   591 by Safe_tac;
   591 by Safe_tac;
   592 by (asm_full_simp_tac (!simpset addsimps [not_le_iff_lt,nat_into_Ord]) 1);
   592 by (asm_full_simp_tac (simpset() addsimps [not_le_iff_lt,nat_into_Ord]) 1);
   593 by (etac lt_asym 1);
   593 by (etac lt_asym 1);
   594 by (assume_tac 1);
   594 by (assume_tac 1);
   595 by (Asm_full_simp_tac 1);
   595 by (Asm_full_simp_tac 1);
   596 by (asm_full_simp_tac (!simpset addsimps [le_iff, nat_into_Ord]) 1);
   596 by (asm_full_simp_tac (simpset() addsimps [le_iff, nat_into_Ord]) 1);
   597 by (Blast_tac 1);
   597 by (Blast_tac 1);
   598 qed "add_le_elim1";
   598 qed "add_le_elim1";
   599 
   599