Version 1.0 of linear nat arithmetic.
authornipkow
Mon Jan 04 15:07:47 1999 +0100 (1999-01-04)
changeset 6055fdf4638bf726
parent 6054 4a4f6ad607a1
child 6056 b21813d1b701
Version 1.0 of linear nat arithmetic.
src/HOL/Arith.ML
src/HOL/Hoare/Hoare.thy
src/HOL/IsaMakefile
src/HOL/Lambda/Lambda.ML
src/HOL/Lambda/ListApplication.ML
src/HOL/List.ML
src/HOL/UNITY/Token.ML
src/HOL/arith_data.ML
     1.1 --- a/src/HOL/Arith.ML	Mon Dec 28 17:03:47 1998 +0100
     1.2 +++ b/src/HOL/Arith.ML	Mon Jan 04 15:07:47 1999 +0100
     1.3 @@ -626,6 +626,7 @@
     1.4  
     1.5  signature ARITH_DATA =
     1.6  sig
     1.7 +  val nat_cancel_sums_add: simproc list
     1.8    val nat_cancel_sums: simproc list
     1.9    val nat_cancel_factor: simproc list
    1.10    val nat_cancel: simproc list
    1.11 @@ -816,11 +817,13 @@
    1.12  val le_pats = prep_pats ["(l::nat) + m <= n", "(l::nat) <= m + n", "Suc m <= n", "m <= Suc n"];
    1.13  val diff_pats = prep_pats ["((l::nat) + m) - n", "(l::nat) - (m + n)", "Suc m - n", "m - Suc n"];
    1.14  
    1.15 -val nat_cancel_sums = map prep_simproc
    1.16 +val nat_cancel_sums_add = map prep_simproc
    1.17    [("nateq_cancel_sums", eq_pats, EqCancelSums.proc),
    1.18     ("natless_cancel_sums", less_pats, LessCancelSums.proc),
    1.19 -   ("natle_cancel_sums", le_pats, LeCancelSums.proc),
    1.20 -   ("natdiff_cancel_sums", diff_pats, DiffCancelSums.proc)];
    1.21 +   ("natle_cancel_sums", le_pats, LeCancelSums.proc)];
    1.22 +
    1.23 +val nat_cancel_sums = nat_cancel_sums_add @
    1.24 +  [prep_simproc("natdiff_cancel_sums", diff_pats, DiffCancelSums.proc)];
    1.25  
    1.26  val nat_cancel_factor = map prep_simproc
    1.27    [("nateq_cancel_factor", eq_pats, EqCancelFactor.proc),
    1.28 @@ -853,8 +856,9 @@
    1.29  val sym = sym;
    1.30  
    1.31  val nat = Type("nat",[]);
    1.32 +val boolT = Type("bool",[]);
    1.33  
    1.34 -fun nnb T = T = Type("fun",[nat,Type("fun",[nat,Type("bool",[])])])
    1.35 +fun nnb T = T = ([nat,nat] ---> boolT);
    1.36  
    1.37  (* Turn term into list of summand * multiplicity plus a constant *)
    1.38  fun poly(Const("Suc",_)$t, (p,i)) = poly(t, (p,i+1))
    1.39 @@ -882,13 +886,14 @@
    1.40    | decomp(_$(Const("Not",_)$(Const(rel,T)$lhs$rhs))) =
    1.41        negate(decomp2(rel,T,lhs,rhs))
    1.42    | decomp _ = None
    1.43 +
    1.44  (* reduce contradictory <= to False.
    1.45     Most of the work is done by the cancel tactics.
    1.46  *)
    1.47  val add_rules = [Zero_not_Suc,Suc_not_Zero,le_0_eq];
    1.48  
    1.49  val cancel_sums_ss = HOL_basic_ss addsimps add_rules
    1.50 -                                  addsimprocs nat_cancel_sums;
    1.51 +                                  addsimprocs nat_cancel_sums_add;
    1.52  
    1.53  val simp = simplify cancel_sums_ss;
    1.54  
    1.55 @@ -896,129 +901,120 @@
    1.56   (fn prems => [cut_facts_tac prems 1,
    1.57                 blast_tac (claset() addIs [add_le_mono]) 1]))
    1.58  ["(i <= j) & (k <= l) ==> i + k <= j + (l::nat)",
    1.59 - "(i = j) & (k <= l) ==> i + k <= j + (l::nat)",
    1.60 - "(i <= j) & (k = l) ==> i + k <= j + (l::nat)",
    1.61 - "(i = j) & (k = l) ==> i + k <= j + (l::nat)"
    1.62 + "(i  = j) & (k <= l) ==> i + k <= j + (l::nat)",
    1.63 + "(i <= j) & (k  = l) ==> i + k <= j + (l::nat)",
    1.64 + "(i  = j) & (k  = l) ==> i + k  = j + (l::nat)"
    1.65  ];
    1.66  
    1.67 +fun is_False thm =
    1.68 +  let val _ $ t = #prop(rep_thm thm)
    1.69 +  in t = Const("False",boolT) end;
    1.70 +
    1.71 +fun is_nat(t) = fastype_of1 t = nat;
    1.72 +
    1.73 +fun mk_nat_thm sg t =
    1.74 +  let val ct = cterm_of sg t  and cn = cterm_of sg (Var(("n",0),nat))
    1.75 +  in instantiate ([],[(cn,ct)]) le0 end;
    1.76 +
    1.77  end;
    1.78  
    1.79  structure Fast_Nat_Arith = Fast_Lin_Arith(Nat_LA_Data);
    1.80  
    1.81  simpset_ref () := (simpset() addSolver Fast_Nat_Arith.cut_lin_arith_tac);
    1.82  
    1.83 +val fast_nat_arith_tac = Fast_Nat_Arith.lin_arith_tac;
    1.84 +
    1.85 +(* Elimination of `-' on nat due to John Harrison *)
    1.86 +Goal "P(a - b::nat) = (!d. (b = a + d --> P 0) & (a = b + d --> P d))";
    1.87 +by(case_tac "a <= b" 1);
    1.88 +by(Auto_tac);
    1.89 +by(eres_inst_tac [("x","b-a")] allE 1);
    1.90 +by(Auto_tac);
    1.91 +qed "nat_diff_split";
    1.92 +
    1.93 +(* FIXME: K true should be replaced by a sensible test to speed things up
    1.94 +   in case there are lots of irrelevant terms involved
    1.95 +*)
    1.96 +val nat_arith_tac =
    1.97 +  refute_tac (K true) (REPEAT o split_tac[nat_diff_split])
    1.98 +             ((REPEAT o etac nat_neqE) THEN' fast_nat_arith_tac);
    1.99 +
   1.100  (*---------------------------------------------------------------------------*)
   1.101  (* End of proof procedures. Now go and USE them!                             *)
   1.102  (*---------------------------------------------------------------------------*)
   1.103  
   1.104 -
   1.105  (*** Subtraction laws -- mostly from Clemens Ballarin ***)
   1.106  
   1.107  Goal "[| a < (b::nat); c <= a |] ==> a-c < b-c";
   1.108 -by (subgoal_tac "c+(a-c) < c+(b-c)" 1);
   1.109 -by (Full_simp_tac 1);
   1.110 -by (subgoal_tac "c <= b" 1);
   1.111 -by (blast_tac (claset() addIs [less_imp_le, le_trans]) 2);
   1.112 -by (Asm_simp_tac 1);
   1.113 +by(nat_arith_tac 1);
   1.114  qed "diff_less_mono";
   1.115  
   1.116  Goal "a+b < (c::nat) ==> a < c-b";
   1.117 -by (dtac diff_less_mono 1);
   1.118 -by (rtac le_add2 1);
   1.119 -by (Asm_full_simp_tac 1);
   1.120 +by(nat_arith_tac 1);
   1.121  qed "add_less_imp_less_diff";
   1.122  
   1.123  Goal "(i < j-k) = (i+k < (j::nat))";
   1.124 -by (rtac iffI 1);
   1.125 - by (case_tac "k <= j" 1);
   1.126 -  by (dtac le_add_diff_inverse2 1);
   1.127 -  by (dres_inst_tac [("k","k")] add_less_mono1 1);
   1.128 -  by (Asm_full_simp_tac 1);
   1.129 - by (rotate_tac 1 1);
   1.130 - by (Asm_full_simp_tac 1);
   1.131 -by (etac add_less_imp_less_diff 1);
   1.132 +by(nat_arith_tac 1);
   1.133  qed "less_diff_conv";
   1.134  
   1.135  Goal "(j-k <= (i::nat)) = (j <= i+k)";
   1.136 -by (simp_tac (simpset() addsimps [less_diff_conv, le_def]) 1);
   1.137 +by(nat_arith_tac 1);
   1.138  qed "le_diff_conv";
   1.139  
   1.140  Goal "k <= j ==> (i <= j-k) = (i+k <= (j::nat))";
   1.141 -by (asm_full_simp_tac
   1.142 -    (simpset() delsimps [less_Suc_eq_le]
   1.143 -               addsimps [less_Suc_eq_le RS sym, less_diff_conv,
   1.144 -			 Suc_diff_le RS sym]) 1);
   1.145 +by(nat_arith_tac 1);
   1.146  qed "le_diff_conv2";
   1.147  
   1.148  Goal "Suc i <= n ==> Suc (n - Suc i) = n - i";
   1.149 -by (asm_full_simp_tac (simpset() addsimps [Suc_diff_le RS sym]) 1);
   1.150 +by(nat_arith_tac 1);
   1.151  qed "Suc_diff_Suc";
   1.152  
   1.153  Goal "i <= (n::nat) ==> n - (n - i) = i";
   1.154 -by (etac rev_mp 1);
   1.155 -by (res_inst_tac [("m","n"),("n","i")] diff_induct 1);
   1.156 -by (ALLGOALS (asm_simp_tac  (simpset() addsimps [Suc_diff_le])));
   1.157 +by(nat_arith_tac 1);
   1.158  qed "diff_diff_cancel";
   1.159  Addsimps [diff_diff_cancel];
   1.160  
   1.161  Goal "k <= (n::nat) ==> m <= n + m - k";
   1.162 -by (etac rev_mp 1);
   1.163 -by (res_inst_tac [("m", "k"), ("n", "n")] diff_induct 1);
   1.164 -by (Simp_tac 1);
   1.165 -by (simp_tac (simpset() addsimps [le_add2, less_imp_le]) 1);
   1.166 -by (Simp_tac 1);
   1.167 +by(nat_arith_tac 1);
   1.168  qed "le_add_diff";
   1.169  
   1.170 -Goal "0<k ==> j<i --> j+k-i < k";
   1.171 -by (res_inst_tac [("m","j"),("n","i")] diff_induct 1);
   1.172 -by (ALLGOALS Asm_simp_tac);
   1.173 -qed_spec_mp "add_diff_less";
   1.174 -
   1.175 +Goal "[| 0<k; j<i |] ==> j+k-i < k";
   1.176 +by(nat_arith_tac 1);
   1.177 +qed "add_diff_less";
   1.178  
   1.179  Goal "m-1 < n ==> m <= n";
   1.180 -by (exhaust_tac "m" 1);
   1.181 -by (auto_tac (claset(), simpset() addsimps [Suc_le_eq]));
   1.182 +by(nat_arith_tac 1);
   1.183  qed "pred_less_imp_le";
   1.184  
   1.185  Goal "j<=i ==> i - j < Suc i - j";
   1.186 -by (REPEAT (etac rev_mp 1));
   1.187 -by (res_inst_tac [("m","i"),("n","j")] diff_induct 1);
   1.188 -by Auto_tac;
   1.189 +by(nat_arith_tac 1);
   1.190  qed "diff_less_Suc_diff";
   1.191  
   1.192  Goal "i - j <= Suc i - j";
   1.193 -by (res_inst_tac [("m","i"),("n","j")] diff_induct 1);
   1.194 -by Auto_tac;
   1.195 +by(nat_arith_tac 1);
   1.196  qed "diff_le_Suc_diff";
   1.197  AddIffs [diff_le_Suc_diff];
   1.198  
   1.199  Goal "n - Suc i <= n - i";
   1.200 -by (case_tac "i<n" 1);
   1.201 -by (dtac diff_Suc_less_diff 1);
   1.202 -by (auto_tac (claset(), simpset() addsimps [less_imp_le, leI]));
   1.203 +by(nat_arith_tac 1);
   1.204  qed "diff_Suc_le_diff";
   1.205  AddIffs [diff_Suc_le_diff];
   1.206  
   1.207  Goal "0 < n ==> (m <= n-1) = (m<n)";
   1.208 -by (exhaust_tac "n" 1);
   1.209 -by (auto_tac (claset(), simpset() addsimps le_simps));
   1.210 +by(nat_arith_tac 1);
   1.211  qed "le_pred_eq";
   1.212  
   1.213  Goal "0 < n ==> (m-1 < n) = (m<=n)";
   1.214 -by (exhaust_tac "m" 1);
   1.215 -by (auto_tac (claset(), simpset() addsimps [Suc_le_eq]));
   1.216 +by(nat_arith_tac 1);
   1.217  qed "less_pred_eq";
   1.218  
   1.219  (*In ordinary notation: if 0<n and n<=m then m-n < m *)
   1.220  Goal "[| 0<n; ~ m<n |] ==> m - n < m";
   1.221 -by (subgoal_tac "0<n --> ~ m<n --> m - n < m" 1);
   1.222 -by (Blast_tac 1);
   1.223 -by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   1.224 -by (ALLGOALS(asm_simp_tac(simpset() addsimps [diff_less_Suc])));
   1.225 +by(nat_arith_tac 1);
   1.226  qed "diff_less";
   1.227  
   1.228  Goal "[| 0<n; n<=m |] ==> m - n < m";
   1.229 -by (asm_simp_tac (simpset() addsimps [diff_less, not_less_iff_le]) 1);
   1.230 +by(nat_arith_tac 1);
   1.231  qed "le_diff_less";
   1.232  
   1.233  
   1.234 @@ -1026,52 +1022,20 @@
   1.235  (** (Anti)Monotonicity of subtraction -- by Stefan Merz **)
   1.236  
   1.237  (* Monotonicity of subtraction in first argument *)
   1.238 -Goal "m <= (n::nat) --> (m-l) <= (n-l)";
   1.239 -by (induct_tac "n" 1);
   1.240 -by (Simp_tac 1);
   1.241 -by (simp_tac (simpset() addsimps [le_Suc_eq]) 1);
   1.242 -by (blast_tac (claset() addIs [diff_le_Suc_diff, le_trans]) 1);
   1.243 -qed_spec_mp "diff_le_mono";
   1.244 +Goal "m <= (n::nat) ==> (m-l) <= (n-l)";
   1.245 +by(nat_arith_tac 1);
   1.246 +qed "diff_le_mono";
   1.247  
   1.248  Goal "m <= (n::nat) ==> (l-n) <= (l-m)";
   1.249 -by (induct_tac "l" 1);
   1.250 -by (Simp_tac 1);
   1.251 -by (case_tac "n <= na" 1);
   1.252 -by (subgoal_tac "m <= na" 1);
   1.253 -by (asm_simp_tac (simpset() addsimps [Suc_diff_le]) 1);
   1.254 -by (fast_tac (claset() addEs [le_trans]) 1);
   1.255 -by (dtac not_leE 1);
   1.256 -by (asm_simp_tac (simpset() addsimps [if_Suc_diff_le]) 1);
   1.257 -qed_spec_mp "diff_le_mono2";
   1.258 +by(nat_arith_tac 1);
   1.259 +qed "diff_le_mono2";
   1.260  
   1.261  
   1.262  (*This proof requires natdiff_cancel_sums*)
   1.263 -Goal "m < (n::nat) --> m<l --> (l-n) < (l-m)";
   1.264 -by (induct_tac "l" 1);
   1.265 -by (Simp_tac 1);
   1.266 -by (Clarify_tac 1);
   1.267 -by (etac less_SucE 1);
   1.268 -by (Clarify_tac 2);
   1.269 -by (asm_simp_tac (simpset() addsimps [Suc_le_eq]) 2);
   1.270 -by (asm_simp_tac (simpset() addsimps [diff_Suc_le_Suc_diff RS le_less_trans,
   1.271 -				      Suc_diff_le, less_imp_le]) 1);
   1.272 -qed_spec_mp "diff_less_mono2";
   1.273 -
   1.274 -(** Elimination of `-' on nat due to John Harrison **)
   1.275 -(*This proof requires natle_cancel_sums*)
   1.276 +Goal "[| m < (n::nat); m<l |] ==> (l-n) < (l-m)";
   1.277 +by(nat_arith_tac 1);
   1.278 +qed "diff_less_mono2";
   1.279  
   1.280 -Goal "P(a - b::nat) = (!d. (b = a + d --> P 0) & (a = b + d --> P d))";
   1.281 -by(case_tac "a <= b" 1);
   1.282 -by(Auto_tac);
   1.283 -by(eres_inst_tac [("x","b-a")] allE 1);
   1.284 -by(Auto_tac);
   1.285 -qed "nat_diff_split";
   1.286 -
   1.287 -(*
   1.288 -This is an example of the power of nat_diff_split. Many of the `-' thms in
   1.289 -Arith.ML could take advantage of this, but would need to be moved.
   1.290 -*)
   1.291 -Goal "m-n = 0  -->  n-m = 0  -->  m=n";
   1.292 -by(simp_tac (simpset() addsplits [nat_diff_split]) 1);
   1.293 -qed_spec_mp "diffs0_imp_equal";
   1.294 -
   1.295 +Goal "[| m-n = 0; n-m = 0 |] ==>  m=n";
   1.296 +by(nat_arith_tac 1);
   1.297 +qed "diffs0_imp_equal";
     2.1 --- a/src/HOL/Hoare/Hoare.thy	Mon Dec 28 17:03:47 1998 +0100
     2.2 +++ b/src/HOL/Hoare/Hoare.thy	Mon Jan 04 15:07:47 1999 +0100
     2.3 @@ -18,12 +18,12 @@
     2.4  
     2.5  datatype
     2.6   'a com = Basic ('a fexp)         
     2.7 -   | Seq ('a com) ('a com)               ("(_;/_)"      [61,60] 60)
     2.8 +   | Seq ('a com) ('a com)               ("(_;/ _)"      [61,60] 60)
     2.9     | Cond ('a bexp) ('a com) ('a com)    ("(1IF _/ THEN _ / ELSE _/ FI)"  [0,0,0] 61)
    2.10     | While ('a bexp) ('a assn) ('a com)  ("(1WHILE _/ INV {_} //DO _ /OD)"  [0,0,0] 61)
    2.11    
    2.12  syntax
    2.13 -  "@assign"  :: id => 'b => 'a com        ("(2_ :=/ _ )" [70,65] 61)
    2.14 +  "@assign"  :: id => 'b => 'a com        ("(2_ :=/ _)" [70,65] 61)
    2.15    "@annskip" :: 'a com                    ("SKIP")
    2.16  
    2.17  translations
     3.1 --- a/src/HOL/IsaMakefile	Mon Dec 28 17:03:47 1998 +0100
     3.2 +++ b/src/HOL/IsaMakefile	Mon Jan 04 15:07:47 1999 +0100
     3.3 @@ -55,7 +55,7 @@
     3.4    Tools/inductive_package.ML Tools/primrec_package.ML \
     3.5    Tools/record_package.ML Tools/typedef_package.ML Trancl.ML \
     3.6    Trancl.thy Univ.ML Univ.thy Vimage.ML Vimage.thy WF.ML WF.thy \
     3.7 -  WF_Rel.ML WF_Rel.thy arith_data.ML cladata.ML equalities.ML \
     3.8 +  WF_Rel.ML WF_Rel.thy cladata.ML equalities.ML \
     3.9    equalities.thy hologic.ML mono.ML mono.thy simpdata.ML subset.ML \
    3.10    subset.thy thy_syntax.ML
    3.11  	@$(ISATOOL) usedir -b $(OUT)/Pure HOL
     4.1 --- a/src/HOL/Lambda/Lambda.ML	Mon Dec 28 17:03:47 1998 +0100
     4.2 +++ b/src/HOL/Lambda/Lambda.ML	Mon Jan 04 15:07:47 1999 +0100
     4.3 @@ -110,7 +110,6 @@
     4.4  Goal "!k. liftn (Suc n) t k = lift (liftn n t k) k";
     4.5  by (induct_tac "t" 1);
     4.6  by (ALLGOALS(asm_simp_tac(addsplit(simpset()))));
     4.7 -by (blast_tac (claset() addDs [add_lessD1]) 1);
     4.8  qed "liftn_lift";
     4.9  Addsimps [liftn_lift];
    4.10  
     5.1 --- a/src/HOL/Lambda/ListApplication.ML	Mon Dec 28 17:03:47 1998 +0100
     5.2 +++ b/src/HOL/Lambda/ListApplication.ML	Mon Jan 04 15:07:47 1999 +0100
     5.3 @@ -88,14 +88,7 @@
     5.4  Addsimps [size_apps];
     5.5  
     5.6  Goal "[| 0 < k; m <= n |] ==> m < n+k";
     5.7 -by (exhaust_tac "k" 1);
     5.8 - by (Asm_full_simp_tac 1);
     5.9 -by (Asm_full_simp_tac 1);
    5.10 -by (rtac le_imp_less_Suc 1);
    5.11 -by (exhaust_tac "n" 1);
    5.12 - by (Asm_full_simp_tac 1);
    5.13 -by (hyp_subst_tac 1);
    5.14 -by (etac trans_le_add1 1);
    5.15 +by(fast_nat_arith_tac 1);
    5.16  val lemma = result();
    5.17  
    5.18  (* a customized induction schema for $$ *)
     6.1 --- a/src/HOL/List.ML	Mon Dec 28 17:03:47 1998 +0100
     6.2 +++ b/src/HOL/List.ML	Mon Jan 04 15:07:47 1999 +0100
     6.3 @@ -858,7 +858,6 @@
     6.4  by (induct_tac "ns" 1);
     6.5   by (Simp_tac 1);
     6.6  by (Asm_full_simp_tac 1);
     6.7 -by (blast_tac (claset() addIs [trans_le_add1]) 1);
     6.8  qed_spec_mp "start_le_sum";
     6.9  
    6.10  Goal "n : set ns ==> n <= foldl op+ 0 ns";
     7.1 --- a/src/HOL/UNITY/Token.ML	Mon Dec 28 17:03:47 1998 +0100
     7.2 +++ b/src/HOL/UNITY/Token.ML	Mon Jan 04 15:07:47 1999 +0100
     7.3 @@ -61,8 +61,6 @@
     7.4                simpset() addsimps [diff_add_assoc2, linorder_neq_iff, 
     7.5                                    Suc_le_eq, Suc_diff_Suc, less_imp_diff_less, 
     7.6                                    add_diff_less, mod_less, mod_geq]));
     7.7 -by (etac subst 1);
     7.8 -by (asm_simp_tac (simpset() addsimps [add_diff_less]) 1);
     7.9  qed "nodeOrder_eq";
    7.10  
    7.11  
     8.1 --- a/src/HOL/arith_data.ML	Mon Dec 28 17:03:47 1998 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,257 +0,0 @@
     8.4 -(*  Title:      HOL/arith_data.ML
     8.5 -    ID:         $Id$
     8.6 -    Author:     Markus Wenzel and Stefan Berghofer, TU Muenchen
     8.7 -
     8.8 -Setup various arithmetic proof procedures.
     8.9 -*)
    8.10 -
    8.11 -signature ARITH_DATA =
    8.12 -sig
    8.13 -  val nat_cancel_sums: simproc list
    8.14 -  val nat_cancel_factor: simproc list
    8.15 -  val nat_cancel: simproc list
    8.16 -end;
    8.17 -
    8.18 -structure ArithData: ARITH_DATA =
    8.19 -struct
    8.20 -
    8.21 -
    8.22 -(** abstract syntax of structure nat: 0, Suc, + **)
    8.23 -
    8.24 -(* mk_sum, mk_norm_sum *)
    8.25 -
    8.26 -val one = HOLogic.mk_nat 1;
    8.27 -val mk_plus = HOLogic.mk_binop "op +";
    8.28 -
    8.29 -fun mk_sum [] = HOLogic.zero
    8.30 -  | mk_sum [t] = t
    8.31 -  | mk_sum (t :: ts) = mk_plus (t, mk_sum ts);
    8.32 -
    8.33 -(*normal form of sums: Suc (... (Suc (a + (b + ...))))*)
    8.34 -fun mk_norm_sum ts =
    8.35 -  let val (ones, sums) = partition (equal one) ts in
    8.36 -    funpow (length ones) HOLogic.mk_Suc (mk_sum sums)
    8.37 -  end;
    8.38 -
    8.39 -
    8.40 -(* dest_sum *)
    8.41 -
    8.42 -val dest_plus = HOLogic.dest_bin "op +" HOLogic.natT;
    8.43 -
    8.44 -fun dest_sum tm =
    8.45 -  if HOLogic.is_zero tm then []
    8.46 -  else
    8.47 -    (case try HOLogic.dest_Suc tm of
    8.48 -      Some t => one :: dest_sum t
    8.49 -    | None =>
    8.50 -        (case try dest_plus tm of
    8.51 -          Some (t, u) => dest_sum t @ dest_sum u
    8.52 -        | None => [tm]));
    8.53 -
    8.54 -
    8.55 -(** generic proof tools **)
    8.56 -
    8.57 -(* prove conversions *)
    8.58 -
    8.59 -val mk_eqv = HOLogic.mk_Trueprop o HOLogic.mk_eq;
    8.60 -
    8.61 -fun prove_conv expand_tac norm_tac sg (t, u) =
    8.62 -  mk_meta_eq (prove_goalw_cterm_nocheck [] (cterm_of sg (mk_eqv (t, u)))
    8.63 -    (K [expand_tac, norm_tac]))
    8.64 -  handle ERROR => error ("The error(s) above occurred while trying to prove " ^
    8.65 -    (string_of_cterm (cterm_of sg (mk_eqv (t, u)))));
    8.66 -
    8.67 -val subst_equals = prove_goal HOL.thy "[| t = s; u = t |] ==> u = s"
    8.68 -  (fn prems => [cut_facts_tac prems 1, SIMPSET' asm_simp_tac 1]);
    8.69 -
    8.70 -
    8.71 -(* rewriting *)
    8.72 -
    8.73 -fun simp_all rules = ALLGOALS (simp_tac (HOL_ss addsimps rules));
    8.74 -
    8.75 -val add_rules = [add_Suc, add_Suc_right, add_0, add_0_right];
    8.76 -val mult_rules = [mult_Suc, mult_Suc_right, mult_0, mult_0_right];
    8.77 -
    8.78 -
    8.79 -
    8.80 -(** cancel common summands **)
    8.81 -
    8.82 -structure Sum =
    8.83 -struct
    8.84 -  val mk_sum = mk_norm_sum;
    8.85 -  val dest_sum = dest_sum;
    8.86 -  val prove_conv = prove_conv;
    8.87 -  val norm_tac = simp_all add_rules THEN simp_all add_ac;
    8.88 -end;
    8.89 -
    8.90 -fun gen_uncancel_tac rule ct =
    8.91 -  rtac (instantiate' [] [None, Some ct] (rule RS subst_equals)) 1;
    8.92 -
    8.93 -
    8.94 -(* nat eq *)
    8.95 -
    8.96 -structure EqCancelSums = CancelSumsFun
    8.97 -(struct
    8.98 -  open Sum;
    8.99 -  val mk_bal = HOLogic.mk_eq;
   8.100 -  val dest_bal = HOLogic.dest_bin "op =" HOLogic.natT;
   8.101 -  val uncancel_tac = gen_uncancel_tac add_left_cancel;
   8.102 -end);
   8.103 -
   8.104 -
   8.105 -(* nat less *)
   8.106 -
   8.107 -structure LessCancelSums = CancelSumsFun
   8.108 -(struct
   8.109 -  open Sum;
   8.110 -  val mk_bal = HOLogic.mk_binrel "op <";
   8.111 -  val dest_bal = HOLogic.dest_bin "op <" HOLogic.natT;
   8.112 -  val uncancel_tac = gen_uncancel_tac add_left_cancel_less;
   8.113 -end);
   8.114 -
   8.115 -
   8.116 -(* nat le *)
   8.117 -
   8.118 -structure LeCancelSums = CancelSumsFun
   8.119 -(struct
   8.120 -  open Sum;
   8.121 -  val mk_bal = HOLogic.mk_binrel "op <=";
   8.122 -  val dest_bal = HOLogic.dest_bin "op <=" HOLogic.natT;
   8.123 -  val uncancel_tac = gen_uncancel_tac add_left_cancel_le;
   8.124 -end);
   8.125 -
   8.126 -
   8.127 -(* nat diff *)
   8.128 -
   8.129 -structure DiffCancelSums = CancelSumsFun
   8.130 -(struct
   8.131 -  open Sum;
   8.132 -  val mk_bal = HOLogic.mk_binop "op -";
   8.133 -  val dest_bal = HOLogic.dest_bin "op -" HOLogic.natT;
   8.134 -  val uncancel_tac = gen_uncancel_tac diff_cancel;
   8.135 -end);
   8.136 -
   8.137 -
   8.138 -
   8.139 -(** cancel common factor **)
   8.140 -
   8.141 -structure Factor =
   8.142 -struct
   8.143 -  val mk_sum = mk_norm_sum;
   8.144 -  val dest_sum = dest_sum;
   8.145 -  val prove_conv = prove_conv;
   8.146 -  val norm_tac = simp_all (add_rules @ mult_rules) THEN simp_all add_ac;
   8.147 -end;
   8.148 -
   8.149 -fun mk_cnat n = cterm_of (sign_of Nat.thy) (HOLogic.mk_nat n);
   8.150 -
   8.151 -fun gen_multiply_tac rule k =
   8.152 -  if k > 0 then
   8.153 -    rtac (instantiate' [] [None, Some (mk_cnat (k - 1))] (rule RS subst_equals)) 1
   8.154 -  else no_tac;
   8.155 -
   8.156 -
   8.157 -(* nat eq *)
   8.158 -
   8.159 -structure EqCancelFactor = CancelFactorFun
   8.160 -(struct
   8.161 -  open Factor;
   8.162 -  val mk_bal = HOLogic.mk_eq;
   8.163 -  val dest_bal = HOLogic.dest_bin "op =" HOLogic.natT;
   8.164 -  val multiply_tac = gen_multiply_tac Suc_mult_cancel1;
   8.165 -end);
   8.166 -
   8.167 -
   8.168 -(* nat less *)
   8.169 -
   8.170 -structure LessCancelFactor = CancelFactorFun
   8.171 -(struct
   8.172 -  open Factor;
   8.173 -  val mk_bal = HOLogic.mk_binrel "op <";
   8.174 -  val dest_bal = HOLogic.dest_bin "op <" HOLogic.natT;
   8.175 -  val multiply_tac = gen_multiply_tac Suc_mult_less_cancel1;
   8.176 -end);
   8.177 -
   8.178 -
   8.179 -(* nat le *)
   8.180 -
   8.181 -structure LeCancelFactor = CancelFactorFun
   8.182 -(struct
   8.183 -  open Factor;
   8.184 -  val mk_bal = HOLogic.mk_binrel "op <=";
   8.185 -  val dest_bal = HOLogic.dest_bin "op <=" HOLogic.natT;
   8.186 -  val multiply_tac = gen_multiply_tac Suc_mult_le_cancel1;
   8.187 -end);
   8.188 -
   8.189 -
   8.190 -
   8.191 -(** prepare nat_cancel simprocs **)
   8.192 -
   8.193 -fun prep_pat s = Thm.read_cterm (sign_of Arith.thy) (s, HOLogic.termTVar);
   8.194 -val prep_pats = map prep_pat;
   8.195 -
   8.196 -fun prep_simproc (name, pats, proc) = Simplifier.mk_simproc name pats proc;
   8.197 -
   8.198 -val eq_pats = prep_pats ["(l::nat) + m = n", "(l::nat) = m + n", "Suc m = n", "m = Suc n"];
   8.199 -val less_pats = prep_pats ["(l::nat) + m < n", "(l::nat) < m + n", "Suc m < n", "m < Suc n"];
   8.200 -val le_pats = prep_pats ["(l::nat) + m <= n", "(l::nat) <= m + n", "Suc m <= n", "m <= Suc n"];
   8.201 -val diff_pats = prep_pats ["((l::nat) + m) - n", "(l::nat) - (m + n)", "Suc m - n", "m - Suc n"];
   8.202 -
   8.203 -val nat_cancel_sums = map prep_simproc
   8.204 -  [("nateq_cancel_sums", eq_pats, EqCancelSums.proc),
   8.205 -   ("natless_cancel_sums", less_pats, LessCancelSums.proc),
   8.206 -   ("natle_cancel_sums", le_pats, LeCancelSums.proc),
   8.207 -   ("natdiff_cancel_sums", diff_pats, DiffCancelSums.proc)];
   8.208 -
   8.209 -val nat_cancel_factor = map prep_simproc
   8.210 -  [("nateq_cancel_factor", eq_pats, EqCancelFactor.proc),
   8.211 -   ("natless_cancel_factor", less_pats, LessCancelFactor.proc),
   8.212 -   ("natle_cancel_factor", le_pats, LeCancelFactor.proc)];
   8.213 -
   8.214 -val nat_cancel = nat_cancel_factor @ nat_cancel_sums;
   8.215 -
   8.216 -
   8.217 -end;
   8.218 -
   8.219 -
   8.220 -open ArithData;
   8.221 -
   8.222 -
   8.223 -context Arith.thy;
   8.224 -Addsimprocs nat_cancel;
   8.225 -
   8.226 -
   8.227 -(*This proof requires natdiff_cancel_sums*)
   8.228 -Goal "m < (n::nat) --> m<l --> (l-n) < (l-m)";
   8.229 -by (induct_tac "l" 1);
   8.230 -by (Simp_tac 1);
   8.231 -by (Clarify_tac 1);
   8.232 -by (etac less_SucE 1);
   8.233 -by (Clarify_tac 2);
   8.234 -by (asm_simp_tac (simpset() addsimps [Suc_le_eq]) 2);
   8.235 -by (asm_simp_tac (simpset() addsimps [diff_Suc_le_Suc_diff RS le_less_trans,
   8.236 -				      Suc_diff_le, less_imp_le]) 1);
   8.237 -qed_spec_mp "diff_less_mono2";
   8.238 -
   8.239 -(** Elimination of - on nat due to John Harrison **)
   8.240 -(*This proof requires natle_cancel_sums*)
   8.241 -
   8.242 -Goal "P(a - b::nat) = (!d. (b = a + d --> P 0) & (a = b + d --> P d))";
   8.243 -by(case_tac "a <= b" 1);
   8.244 -by(Auto_tac);
   8.245 -by(eres_inst_tac [("x","b-a")] allE 1);
   8.246 -by(Auto_tac);
   8.247 -qed "nat_diff_split";
   8.248 -
   8.249 -(*
   8.250 -This is an example of the power of nat_diff_split. Many of the `-' thms in
   8.251 -Arith.ML could take advantage of this, but would need to be moved.
   8.252 -*)
   8.253 -Goal "m-n = 0  -->  n-m = 0  -->  m=n";
   8.254 -by(simp_tac (simpset() addsplits [nat_diff_split]) 1);
   8.255 -qed_spec_mp "diffs0_imp_equal";
   8.256 -
   8.257 -use"fast_nat_decider";
   8.258 -
   8.259 -simpset_ref () := (simpset() addSolver
   8.260 -  (fn thms => cut_facts_tac thms THEN' Fast_Nat_Decider.nat_arith_tac));