src/ZF/Arith.ML
changeset 6070 032babd0120b
parent 6068 2d8f3e1f1151
child 6153 bff90585cce5
equal deleted inserted replaced
6069:a99879bd9f13 6070:032babd0120b
     4     Copyright   1992  University of Cambridge
     4     Copyright   1992  University of Cambridge
     5 
     5 
     6 Arithmetic operators and their definitions
     6 Arithmetic operators and their definitions
     7 
     7 
     8 Proofs about elementary arithmetic: addition, multiplication, etc.
     8 Proofs about elementary arithmetic: addition, multiplication, etc.
     9 
       
    10 Could prove def_rec_0, def_rec_succ...
       
    11 *)
     9 *)
    12 
       
    13 open Arith;
       
    14 
    10 
    15 (*"Difference" is subtraction of natural numbers.
    11 (*"Difference" is subtraction of natural numbers.
    16   There are no negative numbers; we have
    12   There are no negative numbers; we have
    17      m #- n = 0  iff  m<=n   and     m #- n = succ(k) iff m>n.
    13      m #- n = 0  iff  m<=n   and     m #- n = succ(k) iff m>n.
    18   Also, rec(m, 0, %z w.z) is pred(m).   
    14   Also, rec(m, 0, %z w.z) is pred(m).   
    19 *)
    15 *)
    20 
    16 
    21 (** rec -- better than nat_rec; the succ case has no type requirement! **)
       
    22 
       
    23 val rec_trans = rec_def RS def_transrec RS trans;
       
    24 
       
    25 Goal "rec(0,a,b) = a";
       
    26 by (rtac rec_trans 1);
       
    27 by (rtac nat_case_0 1);
       
    28 qed "rec_0";
       
    29 
       
    30 Goal "rec(succ(m),a,b) = b(m, rec(m,a,b))";
       
    31 by (rtac rec_trans 1);
       
    32 by (Simp_tac 1);
       
    33 qed "rec_succ";
       
    34 
       
    35 Addsimps [rec_0, rec_succ];
       
    36 
       
    37 val major::prems = Goal
       
    38     "[| n: nat;  \
       
    39 \       a: C(0);  \
       
    40 \       !!m z. [| m: nat;  z: C(m) |] ==> b(m,z): C(succ(m))  \
       
    41 \    |] ==> rec(n,a,b) : C(n)";
       
    42 by (rtac (major RS nat_induct) 1);
       
    43 by (ALLGOALS
       
    44     (asm_simp_tac (simpset() addsimps prems)));
       
    45 qed "rec_type";
       
    46 
       
    47 Addsimps [rec_type, nat_0_le, nat_le_refl];
    17 Addsimps [rec_type, nat_0_le, nat_le_refl];
    48 val nat_typechecks = [rec_type, nat_0I, nat_1I, nat_succI, Ord_nat];
    18 val nat_typechecks = [rec_type, nat_0I, nat_1I, nat_succI, Ord_nat];
    49 
    19 
    50 Goal "[| 0<k; k: nat |] ==> EX j: nat. k = succ(j)";
    20 Goal "[| 0<k; k: nat |] ==> EX j: nat. k = succ(j)";
    51 by (etac rev_mp 1);
    21 by (etac rev_mp 1);
    52 by (etac nat_induct 1);
    22 by (induct_tac "k" 1);
    53 by (Simp_tac 1);
    23 by (Simp_tac 1);
    54 by (Blast_tac 1);
    24 by (Blast_tac 1);
    55 val lemma = result();
    25 val lemma = result();
    56 
    26 
    57 (* [| 0 < k; k: nat; !!j. [| j: nat; k = succ(j) |] ==> Q |] ==> Q *)
    27 (* [| 0 < k; k: nat; !!j. [| j: nat; k = succ(j) |] ==> Q |] ==> Q *)
    58 bind_thm ("zero_lt_natE", lemma RS bexE);
    28 bind_thm ("zero_lt_natE", lemma RS bexE);
    59 
    29 
    60 
    30 
    61 (** Addition **)
    31 (** Addition **)
    62 
    32 
    63 qed_goalw "add_type" Arith.thy [add_def]
    33 Goal "[| m:nat;  n:nat |] ==> m #+ n : nat";
    64     "[| m:nat;  n:nat |] ==> m #+ n : nat"
    34 by (induct_tac "m" 1);
    65  (fn prems=> [ (typechk_tac (prems@nat_typechecks@ZF_typechecks)) ]);
    35 by Auto_tac;
    66 
    36 qed "add_type";
    67 qed_goalw "add_0" Arith.thy [add_def]
    37 Addsimps [add_type];
    68     "0 #+ n = n"
       
    69  (fn _ => [ (rtac rec_0 1) ]);
       
    70 
       
    71 qed_goalw "add_succ" Arith.thy [add_def]
       
    72     "succ(m) #+ n = succ(m #+ n)"
       
    73  (fn _=> [ (rtac rec_succ 1) ]); 
       
    74 
       
    75 Addsimps [add_0, add_succ];
       
    76 
    38 
    77 (** Multiplication **)
    39 (** Multiplication **)
    78 
    40 
    79 qed_goalw "mult_type" Arith.thy [mult_def]
    41 Goal "[| m:nat;  n:nat |] ==> m #* n : nat";
    80     "[| m:nat;  n:nat |] ==> m #* n : nat"
    42 by (induct_tac "m" 1);
    81  (fn prems=>
    43 by Auto_tac;
    82   [ (typechk_tac (prems@[add_type]@nat_typechecks@ZF_typechecks)) ]);
    44 qed "mult_type";
    83 
    45 Addsimps [mult_type];
    84 qed_goalw "mult_0" Arith.thy [mult_def]
    46 
    85     "0 #* n = 0"
       
    86  (fn _ => [ (rtac rec_0 1) ]);
       
    87 
       
    88 qed_goalw "mult_succ" Arith.thy [mult_def]
       
    89     "succ(m) #* n = n #+ (m #* n)"
       
    90  (fn _ => [ (rtac rec_succ 1) ]); 
       
    91 
       
    92 Addsimps [mult_0, mult_succ];
       
    93 
    47 
    94 (** Difference **)
    48 (** Difference **)
    95 
    49 
    96 qed_goalw "diff_type" Arith.thy [diff_def]
    50 Goal "[| m:nat;  n:nat |] ==> m #- n : nat";
    97     "[| m:nat;  n:nat |] ==> m #- n : nat"
    51 by (induct_tac "n" 1);
    98  (fn prems=> [ (typechk_tac (prems@nat_typechecks@ZF_typechecks)) ]);
    52 by Auto_tac;
    99 
    53 by (fast_tac (claset() addIs [nat_case_type]) 1);
   100 qed_goalw "diff_0" Arith.thy [diff_def]
    54 qed "diff_type";
   101     "m #- 0 = m"
    55 Addsimps [diff_type];
   102  (fn _ => [ (rtac rec_0 1) ]);
    56 
   103 
    57 Goal "n:nat ==> 0 #- n = 0";
   104 qed_goalw "diff_0_eq_0" Arith.thy [diff_def]
    58 by (induct_tac "n" 1);
   105     "n:nat ==> 0 #- n = 0"
    59 by Auto_tac;
   106  (fn [prem]=>
    60 qed "diff_0_eq_0";
   107   [ (rtac (prem RS nat_induct) 1),
    61 
   108     (ALLGOALS (Asm_simp_tac)) ]);
    62 (*Must simplify BEFORE the induction: else we get a critical pair*)
   109 
    63 Goal "[| m:nat;  n:nat |] ==> succ(m) #- succ(n) = m #- n";
   110 (*Must simplify BEFORE the induction!!  (Else we get a critical pair)
    64 by (Asm_simp_tac 1);
   111   succ(m) #- succ(n)   rewrites to   pred(succ(m) #- n)  *)
    65 by (induct_tac "n" 1);
   112 qed_goalw "diff_succ_succ" Arith.thy [diff_def]
    66 by Auto_tac;
   113     "[| m:nat;  n:nat |] ==> succ(m) #- succ(n) = m #- n"
    67 qed "diff_succ_succ";
   114  (fn prems=>
    68 
   115   [ (asm_simp_tac (simpset() addsimps prems) 1),
    69 Addsimps [diff_0_eq_0, diff_succ_succ];
   116     (nat_ind_tac "n" prems 1),
    70 
   117     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]);
    71 (*This defining property is no longer wanted*)
   118 
    72 Delsimps [diff_SUCC];  
   119 Addsimps [diff_0, diff_0_eq_0, diff_succ_succ];
       
   120 
    73 
   121 val prems = goal Arith.thy 
    74 val prems = goal Arith.thy 
   122     "[| m:nat;  n:nat |] ==> m #- n le m";
    75     "[| m:nat;  n:nat |] ==> m #- n le m";
   123 by (rtac (prems MRS diff_induct) 1);
    76 by (rtac (prems MRS diff_induct) 1);
   124 by (etac leE 3);
    77 by (etac leE 3);
   127 qed "diff_le_self";
    80 qed "diff_le_self";
   128 
    81 
   129 (*** Simplification over add, mult, diff ***)
    82 (*** Simplification over add, mult, diff ***)
   130 
    83 
   131 val arith_typechecks = [add_type, mult_type, diff_type];
    84 val arith_typechecks = [add_type, mult_type, diff_type];
   132 Addsimps arith_typechecks;
       
   133 
    85 
   134 
    86 
   135 (*** Addition ***)
    87 (*** Addition ***)
   136 
    88 
   137 (*Associative law for addition*)
    89 (*Associative law for addition*)
   138 qed_goal "add_assoc" Arith.thy 
    90 Goal "m:nat ==> (m #+ n) #+ k = m #+ (n #+ k)";
   139     "m:nat ==> (m #+ n) #+ k = m #+ (n #+ k)"
    91 by (induct_tac "m" 1);
   140  (fn prems=>
    92 by Auto_tac;
   141   [ (nat_ind_tac "m" prems 1),
    93 qed "add_assoc";
   142     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]);
       
   143 
    94 
   144 (*The following two lemmas are used for add_commute and sometimes
    95 (*The following two lemmas are used for add_commute and sometimes
   145   elsewhere, since they are safe for rewriting.*)
    96   elsewhere, since they are safe for rewriting.*)
   146 qed_goal "add_0_right" Arith.thy
    97 Goal "m:nat ==> m #+ 0 = m";
   147     "m:nat ==> m #+ 0 = m"
    98 by (induct_tac "m" 1);
   148  (fn prems=>
    99 by Auto_tac;
   149   [ (nat_ind_tac "m" prems 1),
   100 qed "add_0_right";
   150     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); 
   101 
   151 
   102 Goal "m:nat ==> m #+ succ(n) = succ(m #+ n)";
   152 qed_goal "add_succ_right" Arith.thy
   103 by (induct_tac "m" 1);
   153     "m:nat ==> m #+ succ(n) = succ(m #+ n)"
   104 by Auto_tac;
   154  (fn prems=>
   105 qed "add_succ_right";
   155   [ (nat_ind_tac "m" prems 1),
       
   156     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); 
       
   157 
   106 
   158 Addsimps [add_0_right, add_succ_right];
   107 Addsimps [add_0_right, add_succ_right];
   159 
   108 
   160 (*Commutative law for addition*)  
   109 (*Commutative law for addition*)  
   161 qed_goal "add_commute" Arith.thy 
   110 Goal "[| m:nat;  n:nat |] ==> m #+ n = n #+ m";
   162     "!!m n. [| m:nat;  n:nat |] ==> m #+ n = n #+ m"
   111 by (induct_tac "n" 1);
   163  (fn _ =>
   112 by Auto_tac;
   164   [ (nat_ind_tac "n" [] 1),
   113 qed "add_commute";
   165     (ALLGOALS Asm_simp_tac) ]);
       
   166 
   114 
   167 (*for a/c rewriting*)
   115 (*for a/c rewriting*)
   168 qed_goal "add_left_commute" Arith.thy
   116 Goal "[| m:nat;  n:nat |] ==> m#+(n#+k)=n#+(m#+k)";
   169     "!!m n k. [| m:nat;  n:nat |] ==> m#+(n#+k)=n#+(m#+k)"
   117 by (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]);
   118 qed "add_left_commute";
   171 
   119 
   172 (*Addition is an AC-operator*)
   120 (*Addition is an AC-operator*)
   173 val add_ac = [add_assoc, add_commute, add_left_commute];
   121 val add_ac = [add_assoc, add_commute, add_left_commute];
   174 
   122 
   175 (*Cancellation law on the left*)
   123 (*Cancellation law on the left*)
   176 val [eqn,knat] = goal Arith.thy 
   124 Goal "[| k #+ m = k #+ n;  k:nat |] ==> m=n";
   177     "[| k #+ m = k #+ n;  k:nat |] ==> m=n";
   125 by (etac rev_mp 1);
   178 by (rtac (eqn RS rev_mp) 1);
   126 by (induct_tac "k" 1);
   179 by (nat_ind_tac "k" [knat] 1);
   127 by Auto_tac;
   180 by (ALLGOALS (Simp_tac));
       
   181 qed "add_left_cancel";
   128 qed "add_left_cancel";
   182 
   129 
   183 (*** Multiplication ***)
   130 (*** Multiplication ***)
   184 
   131 
   185 (*right annihilation in product*)
   132 (*right annihilation in product*)
   186 qed_goal "mult_0_right" Arith.thy 
   133 Goal "m:nat ==> m #* 0 = 0";
   187     "!!m. m:nat ==> m #* 0 = 0"
   134 by (induct_tac "m" 1);
   188  (fn _=>
   135 by Auto_tac;
   189   [ (nat_ind_tac "m" [] 1),
   136 qed "mult_0_right";
   190     (ALLGOALS (Asm_simp_tac))  ]);
       
   191 
   137 
   192 (*right successor law for multiplication*)
   138 (*right successor law for multiplication*)
   193 qed_goal "mult_succ_right" Arith.thy 
   139 Goal "[| m:nat;  n:nat |] ==> m #* succ(n) = m #+ (m #* n)";
   194     "!!m n. [| m:nat;  n:nat |] ==> m #* succ(n) = m #+ (m #* n)"
   140 by (induct_tac "m" 1);
   195  (fn _ =>
   141 by (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac)));
   196   [ (nat_ind_tac "m" [] 1),
   142 qed "mult_succ_right";
   197     (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac))) ]);
       
   198 
   143 
   199 Addsimps [mult_0_right, mult_succ_right];
   144 Addsimps [mult_0_right, mult_succ_right];
   200 
   145 
   201 Goal "n:nat ==> 1 #* n = n";
   146 Goal "n:nat ==> 1 #* n = n";
   202 by (Asm_simp_tac 1);
   147 by (Asm_simp_tac 1);
   204 
   149 
   205 Goal "n:nat ==> n #* 1 = n";
   150 Goal "n:nat ==> n #* 1 = n";
   206 by (Asm_simp_tac 1);
   151 by (Asm_simp_tac 1);
   207 qed "mult_1_right";
   152 qed "mult_1_right";
   208 
   153 
       
   154 Addsimps [mult_1, mult_1_right];
       
   155 
   209 (*Commutative law for multiplication*)
   156 (*Commutative law for multiplication*)
   210 qed_goal "mult_commute" Arith.thy 
   157 Goal "[| m:nat;  n:nat |] ==> m #* n = n #* m";
   211     "!!m n. [| m:nat;  n:nat |] ==> m #* n = n #* m"
   158 by (induct_tac "m" 1);
   212  (fn _=>
   159 by Auto_tac;
   213   [ (nat_ind_tac "m" [] 1),
   160 qed "mult_commute";
   214     (ALLGOALS Asm_simp_tac) ]);
       
   215 
   161 
   216 (*addition distributes over multiplication*)
   162 (*addition distributes over multiplication*)
   217 qed_goal "add_mult_distrib" Arith.thy 
   163 Goal "[| 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)"
   164 by (induct_tac "m" 1);
   219  (fn _=>
   165 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_assoc RS sym])));
   220   [ (etac nat_induct 1),
   166 qed "add_mult_distrib";
   221     (ALLGOALS (asm_simp_tac (simpset() addsimps [add_assoc RS sym]))) ]);
       
   222 
   167 
   223 (*Distributive law on the left; requires an extra typing premise*)
   168 (*Distributive law on the left; requires an extra typing premise*)
   224 qed_goal "add_mult_distrib_left" Arith.thy 
   169 Goal "[| 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)"
   170 by (induct_tac "m" 1);
   226  (fn prems=>
   171 by (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac)));
   227   [ (nat_ind_tac "m" [] 1),
   172 qed "add_mult_distrib_left";
   228     (Asm_simp_tac 1),
       
   229     (asm_simp_tac (simpset() addsimps add_ac) 1) ]);
       
   230 
   173 
   231 (*Associative law for multiplication*)
   174 (*Associative law for multiplication*)
   232 qed_goal "mult_assoc" Arith.thy 
   175 Goal "[| 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)"
   176 by (induct_tac "m" 1);
   234  (fn _=>
   177 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_mult_distrib])));
   235   [ (etac nat_induct 1),
   178 qed "mult_assoc";
   236     (ALLGOALS (asm_simp_tac (simpset() addsimps [add_mult_distrib]))) ]);
       
   237 
   179 
   238 (*for a/c rewriting*)
   180 (*for a/c rewriting*)
   239 qed_goal "mult_left_commute" Arith.thy 
   181 Goal "[| 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)"
   182 by (rtac (mult_commute RS trans) 1);
   241  (fn _ => [rtac (mult_commute RS trans) 1, 
   183 by (rtac (mult_assoc RS trans) 3);
   242            rtac (mult_assoc RS trans) 3, 
   184 by (rtac (mult_commute RS subst_context) 6);
   243            rtac (mult_commute RS subst_context) 6,
   185 by (REPEAT (ares_tac [mult_type] 1));
   244            REPEAT (ares_tac [mult_type] 1)]);
   186 qed "mult_left_commute";
   245 
   187 
   246 val mult_ac = [mult_assoc,mult_commute,mult_left_commute];
   188 val mult_ac = [mult_assoc,mult_commute,mult_left_commute];
   247 
   189 
   248 
   190 
   249 (*** Difference ***)
   191 (*** Difference ***)
   250 
   192 
   251 qed_goal "diff_self_eq_0" Arith.thy 
   193 Goal "m:nat ==> m #- m = 0";
   252     "m:nat ==> m #- m = 0"
   194 by (induct_tac "m" 1);
   253  (fn prems=>
   195 by Auto_tac;
   254   [ (nat_ind_tac "m" prems 1),
   196 qed "diff_self_eq_0";
   255     (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]);
       
   256 
   197 
   257 (*Addition is the inverse of subtraction*)
   198 (*Addition is the inverse of subtraction*)
   258 Goal "[| n le m;  m:nat |] ==> n #+ (m#-n) = m";
   199 Goal "[| n le m;  m:nat |] ==> n #+ (m#-n) = m";
   259 by (forward_tac [lt_nat_in_nat] 1);
   200 by (forward_tac [lt_nat_in_nat] 1);
   260 by (etac nat_succI 1);
   201 by (etac nat_succI 1);
   285 Addsimps [zero_less_diff];
   226 Addsimps [zero_less_diff];
   286 
   227 
   287 
   228 
   288 (** Subtraction is the inverse of addition. **)
   229 (** Subtraction is the inverse of addition. **)
   289 
   230 
   290 val [mnat,nnat] = goal Arith.thy
   231 Goal "[| m:nat;  n:nat |] ==> (n#+m) #- n = m";
   291     "[| m:nat;  n:nat |] ==> (n#+m) #- n = m";
   232 by (induct_tac "n" 1);
   292 by (rtac (nnat RS nat_induct) 1);
   233 by Auto_tac;
   293 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mnat])));
       
   294 qed "diff_add_inverse";
   234 qed "diff_add_inverse";
   295 
   235 
   296 Goal "[| m:nat;  n:nat |] ==> (m#+n) #- n = m";
   236 Goal "[| m:nat;  n:nat |] ==> (m#+n) #- n = m";
   297 by (res_inst_tac [("m1","m")] (add_commute RS ssubst) 1);
   237 by (res_inst_tac [("m1","m")] (add_commute RS ssubst) 1);
   298 by (REPEAT (ares_tac [diff_add_inverse] 1));
   238 by (REPEAT (ares_tac [diff_add_inverse] 1));
   299 qed "diff_add_inverse2";
   239 qed "diff_add_inverse2";
   300 
   240 
   301 Goal "[| k:nat; m: nat; n: nat |] ==> (k#+m) #- (k#+n) = m #- n";
   241 Goal "[| k:nat; m: nat; n: nat |] ==> (k#+m) #- (k#+n) = m #- n";
   302 by (nat_ind_tac "k" [] 1);
   242 by (induct_tac "k" 1);
   303 by (ALLGOALS Asm_simp_tac);
   243 by (ALLGOALS Asm_simp_tac);
   304 qed "diff_cancel";
   244 qed "diff_cancel";
   305 
   245 
   306 Goal "[| k:nat; m: nat; n: nat |] ==> (m#+k) #- (n#+k) = m #- n";
   246 Goal "[| k:nat; m: nat; n: nat |] ==> (m#+k) #- (n#+k) = m #- n";
   307 val add_commute_k = read_instantiate [("n","k")] add_commute;
   247 val add_commute_k = read_instantiate [("n","k")] add_commute;
   308 by (asm_simp_tac (simpset() addsimps [add_commute_k, diff_cancel]) 1);
   248 by (asm_simp_tac (simpset() addsimps [add_commute_k, diff_cancel]) 1);
   309 qed "diff_cancel2";
   249 qed "diff_cancel2";
   310 
   250 
   311 val [mnat,nnat] = goal Arith.thy
   251 Goal "[| m:nat;  n:nat |] ==> n #- (n#+m) = 0";
   312     "[| m:nat;  n:nat |] ==> n #- (n#+m) = 0";
   252 by (induct_tac "n" 1);
   313 by (rtac (nnat RS nat_induct) 1);
   253 by Auto_tac;
   314 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mnat])));
       
   315 qed "diff_add_0";
   254 qed "diff_add_0";
   316 
   255 
   317 (** Difference distributes over multiplication **)
   256 (** Difference distributes over multiplication **)
   318 
   257 
   319 Goal "[| m:nat; n: nat; k:nat |] ==> (m #- n) #* k = (m #* k) #- (n #* k)";
   258 Goal "[| m:nat; n: nat; k:nat |] ==> (m #- n) #* k = (m #* k) #- (n #* k)";
   332 Goal "[| 0<n;  n le m;  m:nat |] ==> m #- n < m";
   271 Goal "[| 0<n;  n le m;  m:nat |] ==> m #- n < m";
   333 by (forward_tac [lt_nat_in_nat] 1 THEN etac nat_succI 1);
   272 by (forward_tac [lt_nat_in_nat] 1 THEN etac nat_succI 1);
   334 by (etac rev_mp 1);
   273 by (etac rev_mp 1);
   335 by (etac rev_mp 1);
   274 by (etac rev_mp 1);
   336 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   275 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   337 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_le_self,diff_succ_succ])));
   276 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_le_self])));
   338 qed "div_termination";
   277 qed "div_termination";
   339 
   278 
   340 val div_rls =   (*for mod and div*)
   279 val div_rls =   (*for mod and div*)
   341     nat_typechecks @
   280     nat_typechecks @
   342     [Ord_transrec_type, apply_type, div_termination RS ltD, if_type,
   281     [Ord_transrec_type, apply_type, div_termination RS ltD, if_type,
   343      nat_into_Ord, not_lt_iff_le RS iffD1];
   282      nat_into_Ord, not_lt_iff_le RS iffD1];
   344 
   283 
   345 val div_ss = (simpset()) addsimps [nat_into_Ord, div_termination RS ltD,
   284 val div_ss = simpset() addsimps [nat_into_Ord, div_termination RS ltD,
   346                                   not_lt_iff_le RS iffD2];
   285 				 not_lt_iff_le RS iffD2];
   347 
   286 
   348 (*Type checking depends upon termination!*)
   287 (*Type checking depends upon termination!*)
   349 Goalw [mod_def] "[| 0<n;  m:nat;  n:nat |] ==> m mod n : nat";
   288 Goalw [mod_def] "[| 0<n;  m:nat;  n:nat |] ==> m mod n : nat";
   350 by (REPEAT (ares_tac div_rls 1 ORELSE etac lt_trans 1));
   289 by (REPEAT (ares_tac div_rls 1 ORELSE etac lt_trans 1));
   351 qed "mod_type";
   290 qed "mod_type";
   440 by (asm_simp_tac (simpset() addsimps [mod_less_divisor RS ltD]) 2);
   379 by (asm_simp_tac (simpset() addsimps [mod_less_divisor RS ltD]) 2);
   441 by (asm_simp_tac (simpset() addsimps [mod_succ] setloop Step_tac) 1);
   380 by (asm_simp_tac (simpset() addsimps [mod_succ] setloop Step_tac) 1);
   442 qed "mod2_succ_succ";
   381 qed "mod2_succ_succ";
   443 
   382 
   444 Goal "m:nat ==> (m#+m) mod 2 = 0";
   383 Goal "m:nat ==> (m#+m) mod 2 = 0";
   445 by (etac nat_induct 1);
   384 by (induct_tac "m" 1);
   446 by (simp_tac (simpset() addsimps [mod_less]) 1);
   385 by (simp_tac (simpset() addsimps [mod_less]) 1);
   447 by (asm_simp_tac (simpset() addsimps [mod2_succ_succ, add_succ_right]) 1);
   386 by (asm_simp_tac (simpset() addsimps [mod2_succ_succ, add_succ_right]) 1);
   448 qed "mod2_add_self";
   387 qed "mod2_add_self";
   449 
   388 
   450 
   389 
   451 (**** Additional theorems about "le" ****)
   390 (**** Additional theorems about "le" ****)
   452 
   391 
   453 Goal "[| m:nat;  n:nat |] ==> m le m #+ n";
   392 Goal "[| m:nat;  n:nat |] ==> m le m #+ n";
   454 by (etac nat_induct 1);
   393 by (induct_tac "m" 1);
   455 by (ALLGOALS Asm_simp_tac);
   394 by (ALLGOALS Asm_simp_tac);
   456 qed "add_le_self";
   395 qed "add_le_self";
   457 
   396 
   458 Goal "[| m:nat;  n:nat |] ==> m le n #+ m";
   397 Goal "[| m:nat;  n:nat |] ==> m le n #+ m";
   459 by (stac add_commute 1);
   398 by (stac add_commute 1);
   508 
   447 
   509 (*** Monotonicity of Multiplication ***)
   448 (*** Monotonicity of Multiplication ***)
   510 
   449 
   511 Goal "[| i le j; j:nat; k:nat |] ==> i#*k le j#*k";
   450 Goal "[| i le j; j:nat; k:nat |] ==> i#*k le j#*k";
   512 by (forward_tac [lt_nat_in_nat] 1);
   451 by (forward_tac [lt_nat_in_nat] 1);
   513 by (nat_ind_tac "k" [] 2);
   452 by (induct_tac "k" 2);
   514 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_le_mono])));
   453 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_le_mono])));
   515 qed "mult_le_mono1";
   454 qed "mult_le_mono1";
   516 
   455 
   517 (* le monotonicity, BOTH arguments*)
   456 (* le monotonicity, BOTH arguments*)
   518 Goal "[| i le j; k le l; j:nat; l:nat |] ==> i#*k le j#*l";
   457 Goal "[| i le j; k le l; j:nat; l:nat |] ==> i#*k le j#*l";
   527 (*strict, in 1st argument; proof is by induction on k>0*)
   466 (*strict, in 1st argument; proof is by induction on k>0*)
   528 Goal "[| i<j; 0<k; j:nat; k:nat |] ==> k#*i < k#*j";
   467 Goal "[| i<j; 0<k; j:nat; k:nat |] ==> k#*i < k#*j";
   529 by (etac zero_lt_natE 1);
   468 by (etac zero_lt_natE 1);
   530 by (forward_tac [lt_nat_in_nat] 2);
   469 by (forward_tac [lt_nat_in_nat] 2);
   531 by (ALLGOALS Asm_simp_tac);
   470 by (ALLGOALS Asm_simp_tac);
   532 by (nat_ind_tac "x" [] 1);
   471 by (induct_tac "x" 1);
   533 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_lt_mono])));
   472 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_lt_mono])));
   534 qed "mult_lt_mono2";
   473 qed "mult_lt_mono2";
   535 
   474 
   536 Goal "[| i<j; 0<c; i:nat; j:nat; c:nat |] ==> i#*c < j#*c";
   475 Goal "[| i<j; 0<c; i:nat; j:nat; c:nat |] ==> i#*c < j#*c";
   537 by (asm_simp_tac (simpset() addsimps [mult_lt_mono2, mult_commute]) 1);
   476 by (asm_simp_tac (simpset() addsimps [mult_lt_mono2, mult_commute]) 1);
   569                          zero_lt_mult_iff, le_refl RS mult_le_mono, mod_geq,
   508                          zero_lt_mult_iff, le_refl RS mult_le_mono, mod_geq,
   570                          diff_mult_distrib2 RS sym,
   509                          diff_mult_distrib2 RS sym,
   571                          div_termination RS ltD]) 1);
   510                          div_termination RS ltD]) 1);
   572 qed "mult_mod_distrib";
   511 qed "mult_mod_distrib";
   573 
   512 
   574 (** Lemma for gcd **)
   513 (*Lemma for gcd*)
   575 
       
   576 val mono_lemma = (nat_into_Ord RS Ord_0_lt) RSN (2,mult_lt_mono2);
       
   577 
       
   578 Goal "[| m = m#*n; m: nat; n: nat |] ==> n=1 | m=0";
   514 Goal "[| m = m#*n; m: nat; n: nat |] ==> n=1 | m=0";
   579 by (rtac disjCI 1);
   515 by (rtac disjCI 1);
   580 by (dtac sym 1);
   516 by (dtac sym 1);
   581 by (rtac Ord_linear_lt 1 THEN REPEAT_SOME (ares_tac [nat_into_Ord,nat_1I]));
   517 by (rtac Ord_linear_lt 1 THEN REPEAT_SOME (ares_tac [nat_into_Ord,nat_1I]));
   582 by (fast_tac (claset() addss (simpset())) 1);
   518 by (dtac (nat_into_Ord RS Ord_0_lt RSN (2,mult_lt_mono2)) 2);
   583 by (fast_tac (le_cs addDs [mono_lemma] 
   519 by Auto_tac;
   584                     addss (simpset() addsimps [mult_1_right])) 1);
       
   585 qed "mult_eq_self_implies_10";
   520 qed "mult_eq_self_implies_10";
   586 
       
   587 
   521 
   588 (*Thanks to Sten Agerholm*)
   522 (*Thanks to Sten Agerholm*)
   589 Goal "[|m#+n le m#+k; m:nat; n:nat; k:nat|] ==> n le k";
   523 Goal "[|m#+n le m#+k; m:nat; n:nat; k:nat|] ==> n le k";
   590 by (etac rev_mp 1);
   524 by (etac rev_mp 1);
   591 by (eres_inst_tac [("n","n")] nat_induct 1);
   525 by (induct_tac "m" 1);
   592 by (Asm_simp_tac 1);
   526 by (Asm_simp_tac 1);
   593 by Safe_tac;
   527 by Safe_tac;
   594 by (asm_full_simp_tac (simpset() addsimps [not_le_iff_lt,nat_into_Ord]) 1);
   528 by (asm_full_simp_tac (simpset() addsimps [not_le_iff_lt,nat_into_Ord]) 1);
   595 by (etac lt_asym 1);
       
   596 by (assume_tac 1);
       
   597 by (Asm_full_simp_tac 1);
       
   598 by (asm_full_simp_tac (simpset() addsimps [le_iff, nat_into_Ord]) 1);
       
   599 by (Blast_tac 1);
       
   600 qed "add_le_elim1";
   529 qed "add_le_elim1";
   601 
   530 
   602 Goal "[| m<n; n: nat |] ==> EX k: nat. n = succ(m#+k)";
   531 Goal "[| m<n; n: nat |] ==> EX k: nat. n = succ(m#+k)";
   603 by (forward_tac [lt_nat_in_nat] 1 THEN assume_tac 1);
   532 by (forward_tac [lt_nat_in_nat] 1 THEN assume_tac 1);
   604 be rev_mp 1;
   533 be rev_mp 1;
   605 by (etac nat_induct 1);
   534 by (induct_tac "n" 1);
   606 by (ALLGOALS (simp_tac (simpset() addsimps [le_iff])));
   535 by (ALLGOALS (simp_tac (simpset() addsimps [le_iff])));
   607 by (blast_tac (claset() addSEs [leE] 
   536 by (blast_tac (claset() addSEs [leE] 
   608                         addSIs [add_0_right RS sym, add_succ_right RS sym]) 1);
   537                         addSIs [add_0_right RS sym, add_succ_right RS sym]) 1);
   609 qed_spec_mp "less_imp_Suc_add";
   538 qed_spec_mp "less_imp_Suc_add";