src/HOL/Arith.ML
changeset 8859 b1ea21d70c85
parent 8833 d6122f13b8a6
child 8935 548901d05a0e
equal deleted inserted replaced
8858:b739f0ecc1fa 8859:b1ea21d70c85
   407 (*This and the next few suggested by Florian Kammueller*)
   407 (*This and the next few suggested by Florian Kammueller*)
   408 Goal "!!i::nat. i-j-k = i-k-j";
   408 Goal "!!i::nat. i-j-k = i-k-j";
   409 by (simp_tac (simpset() addsimps [diff_diff_left, add_commute]) 1);
   409 by (simp_tac (simpset() addsimps [diff_diff_left, add_commute]) 1);
   410 qed "diff_commute";
   410 qed "diff_commute";
   411 
   411 
   412 Goal "k<=j --> j<=i --> i - (j - k) = i - j + (k::nat)";
       
   413 by (res_inst_tac [("m","i"),("n","j")] diff_induct 1);
       
   414 by (ALLGOALS Asm_simp_tac);
       
   415 by (asm_simp_tac (simpset() addsimps [Suc_diff_le, le_Suc_eq]) 1);
       
   416 qed_spec_mp "diff_diff_right";
       
   417 
       
   418 Goal "k <= (j::nat) --> (i + j) - k = i + (j - k)";
   412 Goal "k <= (j::nat) --> (i + j) - k = i + (j - k)";
   419 by (res_inst_tac [("m","j"),("n","k")] diff_induct 1);
   413 by (res_inst_tac [("m","j"),("n","k")] diff_induct 1);
   420 by (ALLGOALS Asm_simp_tac);
   414 by (ALLGOALS Asm_simp_tac);
   421 qed_spec_mp "diff_add_assoc";
   415 qed_spec_mp "diff_add_assoc";
   422 
   416 
   426 
   420 
   427 Goal "(n+m) - n = (m::nat)";
   421 Goal "(n+m) - n = (m::nat)";
   428 by (induct_tac "n" 1);
   422 by (induct_tac "n" 1);
   429 by (ALLGOALS Asm_simp_tac);
   423 by (ALLGOALS Asm_simp_tac);
   430 qed "diff_add_inverse";
   424 qed "diff_add_inverse";
   431 Addsimps [diff_add_inverse];
       
   432 
   425 
   433 Goal "(m+n) - n = (m::nat)";
   426 Goal "(m+n) - n = (m::nat)";
   434 by (simp_tac (simpset() addsimps [diff_add_assoc]) 1);
   427 by (simp_tac (simpset() addsimps [diff_add_assoc]) 1);
   435 qed "diff_add_inverse2";
   428 qed "diff_add_inverse2";
   436 Addsimps [diff_add_inverse2];
       
   437 
   429 
   438 Goal "i <= (j::nat) ==> (j-i=k) = (j=k+i)";
   430 Goal "i <= (j::nat) ==> (j-i=k) = (j=k+i)";
   439 by Safe_tac;
   431 by Safe_tac;
   440 by (ALLGOALS Asm_simp_tac);
   432 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_add_inverse2])));
   441 qed "le_imp_diff_is_add";
   433 qed "le_imp_diff_is_add";
   442 
   434 
   443 Goal "(m-n = 0) = (m <= n)";
   435 Goal "(m-n = 0) = (m <= n)";
   444 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   436 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   445 by (ALLGOALS Asm_simp_tac);
   437 by (ALLGOALS Asm_simp_tac);
   475 
   467 
   476 Goal "(k+m) - (k+n) = m - (n::nat)";
   468 Goal "(k+m) - (k+n) = m - (n::nat)";
   477 by (induct_tac "k" 1);
   469 by (induct_tac "k" 1);
   478 by (ALLGOALS Asm_simp_tac);
   470 by (ALLGOALS Asm_simp_tac);
   479 qed "diff_cancel";
   471 qed "diff_cancel";
   480 Addsimps [diff_cancel];
       
   481 
   472 
   482 Goal "(m+k) - (n+k) = m - (n::nat)";
   473 Goal "(m+k) - (n+k) = m - (n::nat)";
   483 val add_commute_k = read_instantiate [("n","k")] add_commute;
   474 by (asm_simp_tac
   484 by (asm_simp_tac (simpset() addsimps [add_commute_k]) 1);
   475     (simpset() addsimps [diff_cancel, inst "n" "k" add_commute]) 1);
   485 qed "diff_cancel2";
   476 qed "diff_cancel2";
   486 Addsimps [diff_cancel2];
       
   487 
   477 
   488 Goal "n - (n+m) = 0";
   478 Goal "n - (n+m) = 0";
   489 by (induct_tac "n" 1);
   479 by (induct_tac "n" 1);
   490 by (ALLGOALS Asm_simp_tac);
   480 by (ALLGOALS Asm_simp_tac);
   491 qed "diff_add_0";
   481 qed "diff_add_0";
   492 Addsimps [diff_add_0];
       
   493 
   482 
   494 
   483 
   495 (** Difference distributes over multiplication **)
   484 (** Difference distributes over multiplication **)
   496 
   485 
   497 Goal "!!m::nat. (m - n) * k = (m * k) - (n * k)";
   486 Goal "!!m::nat. (m - n) * k = (m * k) - (n * k)";
   498 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   487 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
   499 by (ALLGOALS Asm_simp_tac);
   488 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_cancel])));
   500 qed "diff_mult_distrib" ;
   489 qed "diff_mult_distrib" ;
   501 
   490 
   502 Goal "!!m::nat. k * (m - n) = (k * m) - (k * n)";
   491 Goal "!!m::nat. k * (m - n) = (k * m) - (k * n)";
   503 val mult_commute_k = read_instantiate [("m","k")] mult_commute;
   492 val mult_commute_k = read_instantiate [("m","k")] mult_commute;
   504 by (simp_tac (simpset() addsimps [diff_mult_distrib, mult_commute_k]) 1);
   493 by (simp_tac (simpset() addsimps [diff_mult_distrib, mult_commute_k]) 1);
   537 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [mult_commute])));
   526 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [mult_commute])));
   538 qed "mult_less_mono1";
   527 qed "mult_less_mono1";
   539 
   528 
   540 Goal "(0 < m*n) = (0<m & 0<n)";
   529 Goal "(0 < m*n) = (0<m & 0<n)";
   541 by (induct_tac "m" 1);
   530 by (induct_tac "m" 1);
   542 by (induct_tac "n" 2);
   531 by (case_tac "n" 2);
   543 by (ALLGOALS Asm_simp_tac);
   532 by (ALLGOALS Asm_simp_tac);
   544 qed "zero_less_mult_iff";
   533 qed "zero_less_mult_iff";
   545 Addsimps [zero_less_mult_iff];
   534 Addsimps [zero_less_mult_iff];
       
   535 
       
   536 Goal "(1 <= m*n) = (1<=m & 1<=n)";
       
   537 by (induct_tac "m" 1);
       
   538 by (case_tac "n" 2);
       
   539 by (ALLGOALS Asm_simp_tac);
       
   540 qed "one_le_mult_iff";
       
   541 Addsimps [one_le_mult_iff];
   546 
   542 
   547 Goal "(m*n = 1) = (m=1 & n=1)";
   543 Goal "(m*n = 1) = (m=1 & n=1)";
   548 by (induct_tac "m" 1);
   544 by (induct_tac "m" 1);
   549 by (Simp_tac 1);
   545 by (Simp_tac 1);
   550 by (induct_tac "n" 1);
   546 by (induct_tac "n" 1);
   997 solver all the time rather than add the additional check. *)
   993 solver all the time rather than add the additional check. *)
   998 
   994 
   999 simpset_ref () := (simpset() addSolver
   995 simpset_ref () := (simpset() addSolver
  1000    (mk_solver "lin. arith." Fast_Arith.cut_lin_arith_tac));
   996    (mk_solver "lin. arith." Fast_Arith.cut_lin_arith_tac));
  1001 
   997 
  1002 (*Elimination of `-' on nat due to John Harrison. *)
   998 (*Elimination of `-' on nat*)
  1003 Goal "P(a - b::nat) = (ALL d. (b = a + d --> P 0) & (a = b + d --> P d))";
   999 Goal "P(a - b::nat) = (ALL d. (a<b --> P 0) & (a = b + d --> P d))";
  1004 by (case_tac "a <= b" 1);
  1000 by (case_tac "a < b" 1);
  1005 by Auto_tac;
  1001 by (auto_tac (claset(), simpset() addsimps [diff_is_0_eq RS iffD2]));
  1006 by (eres_inst_tac [("x","b-a")] allE 1);
       
  1007 by (asm_simp_tac (simpset() addsimps [diff_is_0_eq RS iffD2]) 1);
       
  1008 qed "nat_diff_split";
  1002 qed "nat_diff_split";
  1009 
  1003 
  1010 (*LCP's version, replacing b=a+d by a<b, which sometimes works better*)
  1004 val nat_diff_split = nat_diff_split;
  1011 Goal "P(a - b::nat) = (ALL d. (a<b --> P 0) & (a = b + d --> P d))";
       
  1012 by (auto_tac (claset(), simpset() addsplits [nat_diff_split]));
       
  1013 qed "nat_diff_split'";
       
  1014 
       
  1015 
  1005 
  1016 (* FIXME: K true should be replaced by a sensible test to speed things up
  1006 (* FIXME: K true should be replaced by a sensible test to speed things up
  1017    in case there are lots of irrelevant terms involved;
  1007    in case there are lots of irrelevant terms involved;
  1018    elimination of min/max can be optimized:
  1008    elimination of min/max can be optimized:
  1019    (max m n + k <= r) = (m+k <= r & n+k <= r)
  1009    (max m n + k <= r) = (m+k <= r & n+k <= r)
  1111 Goal "[| 0<n; 0<m |] ==> m - n < m";
  1101 Goal "[| 0<n; 0<m |] ==> m - n < m";
  1112 by (arith_tac 1);
  1102 by (arith_tac 1);
  1113 qed "diff_less";
  1103 qed "diff_less";
  1114 
  1104 
  1115 Goal "j <= (k::nat) ==> (j+i)-k = i-(k-j)";
  1105 Goal "j <= (k::nat) ==> (j+i)-k = i-(k-j)";
  1116 by (asm_simp_tac (simpset() addsplits [nat_diff_split']) 1);
  1106 by (asm_simp_tac (simpset() addsplits [nat_diff_split]) 1);
  1117 qed "diff_add_assoc_diff";
  1107 qed "diff_add_assoc_diff";
  1118 
  1108 
  1119 
  1109 
  1120 (*** Reducing subtraction to addition ***)
  1110 (*** Reducing subtraction to addition ***)
  1121 
  1111 
  1136 qed "diff_Suc_le_Suc_diff";
  1126 qed "diff_Suc_le_Suc_diff";
  1137 
  1127 
  1138 (** Simplification of relational expressions involving subtraction **)
  1128 (** Simplification of relational expressions involving subtraction **)
  1139 
  1129 
  1140 Goal "[| k <= m;  k <= (n::nat) |] ==> ((m-k) - (n-k)) = (m-n)";
  1130 Goal "[| k <= m;  k <= (n::nat) |] ==> ((m-k) - (n-k)) = (m-n)";
  1141 by (asm_simp_tac (simpset() addsplits [nat_diff_split']) 1);
  1131 by (asm_simp_tac (simpset() addsplits [nat_diff_split]) 1);
  1142 qed "diff_diff_eq";
  1132 qed "diff_diff_eq";
  1143 
  1133 
  1144 Goal "[| k <= m;  k <= (n::nat) |] ==> (m-k = n-k) = (m=n)";
  1134 Goal "[| k <= m;  k <= (n::nat) |] ==> (m-k = n-k) = (m=n)";
  1145 by (auto_tac (claset(), simpset() addsplits [nat_diff_split']));
  1135 by (auto_tac (claset(), simpset() addsplits [nat_diff_split]));
  1146 qed "eq_diff_iff";
  1136 qed "eq_diff_iff";
  1147 
  1137 
  1148 Goal "[| k <= m;  k <= (n::nat) |] ==> (m-k < n-k) = (m<n)";
  1138 Goal "[| k <= m;  k <= (n::nat) |] ==> (m-k < n-k) = (m<n)";
  1149 by (auto_tac (claset(), simpset() addsplits [nat_diff_split']));
  1139 by (auto_tac (claset(), simpset() addsplits [nat_diff_split]));
  1150 qed "less_diff_iff";
  1140 qed "less_diff_iff";
  1151 
  1141 
  1152 Goal "[| k <= m;  k <= (n::nat) |] ==> (m-k <= n-k) = (m<=n)";
  1142 Goal "[| k <= m;  k <= (n::nat) |] ==> (m-k <= n-k) = (m<=n)";
  1153 by (auto_tac (claset(), simpset() addsplits [nat_diff_split']));
  1143 by (auto_tac (claset(), simpset() addsplits [nat_diff_split]));
  1154 qed "le_diff_iff";
  1144 qed "le_diff_iff";
  1155 
  1145 
  1156 
  1146 
  1157 (** (Anti)Monotonicity of subtraction -- by Stephan Merz **)
  1147 (** (Anti)Monotonicity of subtraction -- by Stephan Merz **)
  1158 
  1148 
  1187 
  1177 
  1188 Goal "[| 1<n; 1<m |] ==> n<n*m";
  1178 Goal "[| 1<n; 1<m |] ==> n<n*m";
  1189 by (case_tac "m" 1);
  1179 by (case_tac "m" 1);
  1190 by Auto_tac;
  1180 by Auto_tac;
  1191 qed "n_less_n_mult_m"; 
  1181 qed "n_less_n_mult_m"; 
       
  1182 
       
  1183 
       
  1184 (** Rewriting to pull differences out **)
       
  1185 
       
  1186 Goal "k<=j --> i - (j - k) = i + (k::nat) - j";
       
  1187 by (arith_tac 1);
       
  1188 qed "diff_diff_right";
       
  1189 
       
  1190 Goal "k <= j ==> m - Suc (j - k) = m + k - Suc j";
       
  1191 by (arith_tac 1);
       
  1192 qed "diff_Suc_diff_eq1"; 
       
  1193 
       
  1194 Goal "k <= j ==> Suc (j - k) - m = Suc j - (k + m)";
       
  1195 by (arith_tac 1);
       
  1196 qed "diff_Suc_diff_eq2"; 
       
  1197 
       
  1198 (*The others are
       
  1199       i - j - k = i - (j + k),
       
  1200       k <= j ==> j - k + i = j + i - k,
       
  1201       k <= j ==> i + (j - k) = i + j - k *)
       
  1202 Addsimps [diff_diff_left, diff_diff_right, diff_add_assoc2 RS sym, 
       
  1203 	  diff_add_assoc RS sym, diff_Suc_diff_eq1, diff_Suc_diff_eq2];
       
  1204