| author | wenzelm | 
| Wed, 04 Jul 2007 16:49:34 +0200 | |
| changeset 23566 | b65692d4adcd | 
| parent 23400 | a64b39e5809b | 
| child 23881 | 851c74f1bb69 | 
| permissions | -rw-r--r-- | 
| 23164 | 1 | (* Title: HOL/int_arith1.ML | 
| 2 | ID: $Id$ | |
| 3 | Authors: Larry Paulson and Tobias Nipkow | |
| 4 | ||
| 5 | Simprocs and decision procedure for linear arithmetic. | |
| 6 | *) | |
| 7 | ||
| 8 | (** Misc ML bindings **) | |
| 9 | ||
| 10 | val succ_Pls = thm "succ_Pls"; | |
| 11 | val succ_Min = thm "succ_Min"; | |
| 12 | val succ_1 = thm "succ_1"; | |
| 13 | val succ_0 = thm "succ_0"; | |
| 14 | ||
| 15 | val pred_Pls = thm "pred_Pls"; | |
| 16 | val pred_Min = thm "pred_Min"; | |
| 17 | val pred_1 = thm "pred_1"; | |
| 18 | val pred_0 = thm "pred_0"; | |
| 19 | ||
| 20 | val minus_Pls = thm "minus_Pls"; | |
| 21 | val minus_Min = thm "minus_Min"; | |
| 22 | val minus_1 = thm "minus_1"; | |
| 23 | val minus_0 = thm "minus_0"; | |
| 24 | ||
| 25 | val add_Pls = thm "add_Pls"; | |
| 26 | val add_Min = thm "add_Min"; | |
| 27 | val add_BIT_11 = thm "add_BIT_11"; | |
| 28 | val add_BIT_10 = thm "add_BIT_10"; | |
| 29 | val add_BIT_0 = thm "add_BIT_0"; | |
| 30 | val add_Pls_right = thm "add_Pls_right"; | |
| 31 | val add_Min_right = thm "add_Min_right"; | |
| 32 | ||
| 33 | val mult_Pls = thm "mult_Pls"; | |
| 34 | val mult_Min = thm "mult_Min"; | |
| 35 | val mult_num1 = thm "mult_num1"; | |
| 36 | val mult_num0 = thm "mult_num0"; | |
| 37 | ||
| 38 | val neg_def = thm "neg_def"; | |
| 39 | val iszero_def = thm "iszero_def"; | |
| 40 | ||
| 41 | val number_of_succ = thm "number_of_succ"; | |
| 42 | val number_of_pred = thm "number_of_pred"; | |
| 43 | val number_of_minus = thm "number_of_minus"; | |
| 44 | val number_of_add = thm "number_of_add"; | |
| 45 | val diff_number_of_eq = thm "diff_number_of_eq"; | |
| 46 | val number_of_mult = thm "number_of_mult"; | |
| 47 | val double_number_of_BIT = thm "double_number_of_BIT"; | |
| 48 | val numeral_0_eq_0 = thm "numeral_0_eq_0"; | |
| 49 | val numeral_1_eq_1 = thm "numeral_1_eq_1"; | |
| 50 | val numeral_m1_eq_minus_1 = thm "numeral_m1_eq_minus_1"; | |
| 51 | val mult_minus1 = thm "mult_minus1"; | |
| 52 | val mult_minus1_right = thm "mult_minus1_right"; | |
| 53 | val minus_number_of_mult = thm "minus_number_of_mult"; | |
| 54 | val zero_less_nat_eq = thm "zero_less_nat_eq"; | |
| 55 | val eq_number_of_eq = thm "eq_number_of_eq"; | |
| 56 | val iszero_number_of_Pls = thm "iszero_number_of_Pls"; | |
| 57 | val nonzero_number_of_Min = thm "nonzero_number_of_Min"; | |
| 58 | val iszero_number_of_BIT = thm "iszero_number_of_BIT"; | |
| 59 | val iszero_number_of_0 = thm "iszero_number_of_0"; | |
| 60 | val iszero_number_of_1 = thm "iszero_number_of_1"; | |
| 61 | val less_number_of_eq_neg = thm "less_number_of_eq_neg"; | |
| 62 | val le_number_of_eq = thm "le_number_of_eq"; | |
| 63 | val not_neg_number_of_Pls = thm "not_neg_number_of_Pls"; | |
| 64 | val neg_number_of_Min = thm "neg_number_of_Min"; | |
| 65 | val neg_number_of_BIT = thm "neg_number_of_BIT"; | |
| 66 | val le_number_of_eq_not_less = thm "le_number_of_eq_not_less"; | |
| 67 | val abs_number_of = thm "abs_number_of"; | |
| 68 | val number_of_reorient = thm "number_of_reorient"; | |
| 69 | val add_number_of_left = thm "add_number_of_left"; | |
| 70 | val mult_number_of_left = thm "mult_number_of_left"; | |
| 71 | val add_number_of_diff1 = thm "add_number_of_diff1"; | |
| 72 | val add_number_of_diff2 = thm "add_number_of_diff2"; | |
| 73 | val less_iff_diff_less_0 = thm "less_iff_diff_less_0"; | |
| 74 | val eq_iff_diff_eq_0 = thm "eq_iff_diff_eq_0"; | |
| 75 | val le_iff_diff_le_0 = thm "le_iff_diff_le_0"; | |
| 76 | ||
| 77 | val arith_extra_simps = thms "arith_extra_simps"; | |
| 78 | val arith_simps = thms "arith_simps"; | |
| 79 | val rel_simps = thms "rel_simps"; | |
| 80 | ||
| 81 | val zless_imp_add1_zle = thm "zless_imp_add1_zle"; | |
| 82 | ||
| 83 | val combine_common_factor = thm "combine_common_factor"; | |
| 84 | val eq_add_iff1 = thm "eq_add_iff1"; | |
| 85 | val eq_add_iff2 = thm "eq_add_iff2"; | |
| 86 | val less_add_iff1 = thm "less_add_iff1"; | |
| 87 | val less_add_iff2 = thm "less_add_iff2"; | |
| 88 | val le_add_iff1 = thm "le_add_iff1"; | |
| 89 | val le_add_iff2 = thm "le_add_iff2"; | |
| 90 | ||
| 91 | val arith_special = thms "arith_special"; | |
| 92 | ||
| 93 | structure Int_Numeral_Base_Simprocs = | |
| 94 | struct | |
| 95 | fun prove_conv tacs ctxt (_: thm list) (t, u) = | |
| 96 | if t aconv u then NONE | |
| 97 | else | |
| 98 | let val eq = HOLogic.mk_Trueprop (HOLogic.mk_eq (t, u)) | |
| 99 | in SOME (Goal.prove ctxt [] [] eq (K (EVERY tacs))) end | |
| 100 | ||
| 101 | fun prove_conv_nohyps tacs sg = prove_conv tacs sg []; | |
| 102 | ||
| 103 | fun prep_simproc (name, pats, proc) = | |
| 104 | Simplifier.simproc (the_context()) name pats proc; | |
| 105 | ||
| 106 |   fun is_numeral (Const(@{const_name Numeral.number_of}, _) $ w) = true
 | |
| 107 | | is_numeral _ = false | |
| 108 | ||
| 109 | fun simplify_meta_eq f_number_of_eq f_eq = | |
| 110 | mk_meta_eq ([f_eq, f_number_of_eq] MRS trans) | |
| 111 | ||
| 112 | (*reorientation simprules using ==, for the following simproc*) | |
| 113 | val meta_zero_reorient = zero_reorient RS eq_reflection | |
| 114 | val meta_one_reorient = one_reorient RS eq_reflection | |
| 115 | val meta_number_of_reorient = number_of_reorient RS eq_reflection | |
| 116 | ||
| 117 | (*reorientation simplification procedure: reorients (polymorphic) | |
| 118 | 0 = x, 1 = x, nnn = x provided x isn't 0, 1 or a numeral.*) | |
| 119 | fun reorient_proc sg _ (_ $ t $ u) = | |
| 120 | case u of | |
| 121 | 	Const(@{const_name HOL.zero}, _) => NONE
 | |
| 122 |       | Const(@{const_name HOL.one}, _) => NONE
 | |
| 123 |       | Const(@{const_name Numeral.number_of}, _) $ _ => NONE
 | |
| 124 | | _ => SOME (case t of | |
| 125 | 		  Const(@{const_name HOL.zero}, _) => meta_zero_reorient
 | |
| 126 | 		| Const(@{const_name HOL.one}, _) => meta_one_reorient
 | |
| 127 | 		| Const(@{const_name Numeral.number_of}, _) $ _ => meta_number_of_reorient)
 | |
| 128 | ||
| 129 | val reorient_simproc = | |
| 130 |       prep_simproc ("reorient_simproc", ["0=x", "1=x", "number_of w = x"], reorient_proc)
 | |
| 131 | ||
| 132 | end; | |
| 133 | ||
| 134 | ||
| 135 | Addsimprocs [Int_Numeral_Base_Simprocs.reorient_simproc]; | |
| 136 | ||
| 137 | ||
| 138 | structure Int_Numeral_Simprocs = | |
| 139 | struct | |
| 140 | ||
| 141 | (*Maps 0 to Numeral0 and 1 to Numeral1 so that arithmetic in Int_Numeral_Base_Simprocs | |
| 142 | isn't complicated by the abstract 0 and 1.*) | |
| 143 | val numeral_syms = [numeral_0_eq_0 RS sym, numeral_1_eq_1 RS sym]; | |
| 144 | ||
| 145 | (** New term ordering so that AC-rewriting brings numerals to the front **) | |
| 146 | ||
| 147 | (*Order integers by absolute value and then by sign. The standard integer | |
| 148 | ordering is not well-founded.*) | |
| 149 | fun num_ord (i,j) = | |
| 150 | (case IntInf.compare (IntInf.abs i, IntInf.abs j) of | |
| 151 | EQUAL => int_ord (IntInf.sign i, IntInf.sign j) | |
| 152 | | ord => ord); | |
| 153 | ||
| 154 | (*This resembles Term.term_ord, but it puts binary numerals before other | |
| 155 | non-atomic terms.*) | |
| 156 | local open Term | |
| 157 | in | |
| 158 | fun numterm_ord (Abs (_, T, t), Abs(_, U, u)) = | |
| 159 | (case numterm_ord (t, u) of EQUAL => typ_ord (T, U) | ord => ord) | |
| 160 | | numterm_ord | |
| 161 |      (Const(@{const_name Numeral.number_of}, _) $ v, Const(@{const_name Numeral.number_of}, _) $ w) =
 | |
| 162 | num_ord (HOLogic.dest_numeral v, HOLogic.dest_numeral w) | |
| 163 |   | numterm_ord (Const(@{const_name Numeral.number_of}, _) $ _, _) = LESS
 | |
| 164 |   | numterm_ord (_, Const(@{const_name Numeral.number_of}, _) $ _) = GREATER
 | |
| 165 | | numterm_ord (t, u) = | |
| 166 | (case int_ord (size_of_term t, size_of_term u) of | |
| 167 | EQUAL => | |
| 168 | let val (f, ts) = strip_comb t and (g, us) = strip_comb u in | |
| 169 | (case hd_ord (f, g) of EQUAL => numterms_ord (ts, us) | ord => ord) | |
| 170 | end | |
| 171 | | ord => ord) | |
| 172 | and numterms_ord (ts, us) = list_ord numterm_ord (ts, us) | |
| 173 | end; | |
| 174 | ||
| 175 | fun numtermless tu = (numterm_ord tu = LESS); | |
| 176 | ||
| 177 | (*Defined in this file, but perhaps needed only for Int_Numeral_Base_Simprocs of type nat.*) | |
| 178 | val num_ss = HOL_ss settermless numtermless; | |
| 179 | ||
| 180 | ||
| 181 | (** Utilities **) | |
| 182 | ||
| 183 | fun mk_number T n = HOLogic.number_of_const T $ HOLogic.mk_numeral n; | |
| 184 | ||
| 185 | fun find_first_numeral past (t::terms) = | |
| 186 | ((snd (HOLogic.dest_number t), rev past @ terms) | |
| 187 | handle TERM _ => find_first_numeral (t::past) terms) | |
| 188 |   | find_first_numeral past [] = raise TERM("find_first_numeral", []);
 | |
| 189 | ||
| 190 | val mk_plus = HOLogic.mk_binop @{const_name HOL.plus};
 | |
| 191 | ||
| 192 | fun mk_minus t = | |
| 193 | let val T = Term.fastype_of t | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 194 |   in Const (@{const_name HOL.uminus}, T --> T) $ t end;
 | 
| 23164 | 195 | |
| 196 | (*Thus mk_sum[t] yields t+0; longer sums don't have a trailing zero*) | |
| 197 | fun mk_sum T [] = mk_number T 0 | |
| 198 | | mk_sum T [t,u] = mk_plus (t, u) | |
| 199 | | mk_sum T (t :: ts) = mk_plus (t, mk_sum T ts); | |
| 200 | ||
| 201 | (*this version ALWAYS includes a trailing zero*) | |
| 202 | fun long_mk_sum T [] = mk_number T 0 | |
| 203 | | long_mk_sum T (t :: ts) = mk_plus (t, mk_sum T ts); | |
| 204 | ||
| 205 | val dest_plus = HOLogic.dest_bin @{const_name HOL.plus} Term.dummyT;
 | |
| 206 | ||
| 207 | (*decompose additions AND subtractions as a sum*) | |
| 208 | fun dest_summing (pos, Const (@{const_name HOL.plus}, _) $ t $ u, ts) =
 | |
| 209 | dest_summing (pos, t, dest_summing (pos, u, ts)) | |
| 210 |   | dest_summing (pos, Const (@{const_name HOL.minus}, _) $ t $ u, ts) =
 | |
| 211 | dest_summing (pos, t, dest_summing (not pos, u, ts)) | |
| 212 | | dest_summing (pos, t, ts) = | |
| 213 | if pos then t::ts else mk_minus t :: ts; | |
| 214 | ||
| 215 | fun dest_sum t = dest_summing (true, t, []); | |
| 216 | ||
| 217 | val mk_diff = HOLogic.mk_binop @{const_name HOL.minus};
 | |
| 218 | val dest_diff = HOLogic.dest_bin @{const_name HOL.minus} Term.dummyT;
 | |
| 219 | ||
| 220 | val mk_times = HOLogic.mk_binop @{const_name HOL.times};
 | |
| 221 | ||
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 222 | fun one_of T = Const(@{const_name HOL.one},T);
 | 
| 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 223 | |
| 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 224 | (* build product with trailing 1 rather than Numeral 1 in order to avoid the | 
| 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 225 | unnecessary restriction to type class number_ring | 
| 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 226 | which is not required for cancellation of common factors in divisions. | 
| 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 227 | *) | 
| 23164 | 228 | fun mk_prod T = | 
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 229 | let val one = one_of T | 
| 23164 | 230 | fun mk [] = one | 
| 231 | | mk [t] = t | |
| 232 | | mk (t :: ts) = if t = one then mk ts else mk_times (t, mk ts) | |
| 233 | in mk end; | |
| 234 | ||
| 235 | (*This version ALWAYS includes a trailing one*) | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 236 | fun long_mk_prod T [] = one_of T | 
| 23164 | 237 | | long_mk_prod T (t :: ts) = mk_times (t, mk_prod T ts); | 
| 238 | ||
| 239 | val dest_times = HOLogic.dest_bin @{const_name HOL.times} Term.dummyT;
 | |
| 240 | ||
| 241 | fun dest_prod t = | |
| 242 | let val (t,u) = dest_times t | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 243 | in dest_prod t @ dest_prod u end | 
| 23164 | 244 | handle TERM _ => [t]; | 
| 245 | ||
| 246 | (*DON'T do the obvious simplifications; that would create special cases*) | |
| 247 | fun mk_coeff (k, t) = mk_times (mk_number (Term.fastype_of t) k, t); | |
| 248 | ||
| 249 | (*Express t as a product of (possibly) a numeral with other sorted terms*) | |
| 250 | fun dest_coeff sign (Const (@{const_name HOL.uminus}, _) $ t) = dest_coeff (~sign) t
 | |
| 251 | | dest_coeff sign t = | |
| 252 | let val ts = sort Term.term_ord (dest_prod t) | |
| 253 | val (n, ts') = find_first_numeral [] ts | |
| 254 | handle TERM _ => (1, ts) | |
| 255 | in (sign*n, mk_prod (Term.fastype_of t) ts') end; | |
| 256 | ||
| 257 | (*Find first coefficient-term THAT MATCHES u*) | |
| 258 | fun find_first_coeff past u [] = raise TERM("find_first_coeff", [])
 | |
| 259 | | find_first_coeff past u (t::terms) = | |
| 260 | let val (n,u') = dest_coeff 1 t | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 261 | in if u aconv u' then (n, rev past @ terms) | 
| 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 262 | else find_first_coeff (t::past) u terms | 
| 23164 | 263 | end | 
| 264 | handle TERM _ => find_first_coeff (t::past) u terms; | |
| 265 | ||
| 266 | (*Fractions as pairs of ints. Can't use Rat.rat because the representation | |
| 267 | needs to preserve negative values in the denominator.*) | |
| 268 | fun mk_frac (p, q : IntInf.int) = if q = 0 then raise Div else (p, q); | |
| 269 | ||
| 270 | (*Don't reduce fractions; sums must be proved by rule add_frac_eq. | |
| 271 | Fractions are reduced later by the cancel_numeral_factor simproc.*) | |
| 272 | fun add_frac ((p1 : IntInf.int, q1 : IntInf.int), (p2, q2)) = (p1 * q2 + p2 * q1, q1 * q2); | |
| 273 | ||
| 274 | val mk_divide = HOLogic.mk_binop @{const_name HOL.divide};
 | |
| 275 | ||
| 276 | (*Build term (p / q) * t*) | |
| 277 | fun mk_fcoeff ((p, q), t) = | |
| 278 | let val T = Term.fastype_of t | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 279 | in mk_times (mk_divide (mk_number T p, mk_number T q), t) end; | 
| 23164 | 280 | |
| 281 | (*Express t as a product of a fraction with other sorted terms*) | |
| 282 | fun dest_fcoeff sign (Const (@{const_name HOL.uminus}, _) $ t) = dest_fcoeff (~sign) t
 | |
| 283 |   | dest_fcoeff sign (Const (@{const_name HOL.divide}, _) $ t $ u) =
 | |
| 284 | let val (p, t') = dest_coeff sign t | |
| 285 | val (q, u') = dest_coeff 1 u | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 286 | in (mk_frac (p, q), mk_divide (t', u')) end | 
| 23164 | 287 | | dest_fcoeff sign t = | 
| 288 | let val (p, t') = dest_coeff sign t | |
| 289 | val T = Term.fastype_of t | |
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 290 | in (mk_frac (p, 1), mk_divide (t', one_of T)) end; | 
| 23164 | 291 | |
| 292 | ||
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 293 | (*Simplify Numeral0+n, n+Numeral0, Numeral1*n, n*Numeral1, 1*x, x*1, x/1 *) | 
| 23164 | 294 | val add_0s = thms "add_0s"; | 
| 23400 
a64b39e5809b
The simprocs "divide_cancel_factor" and "ring_eq_cancel_factor" no
 nipkow parents: 
23365diff
changeset | 295 | val mult_1s = thms "mult_1s" @ [thm"mult_1_left", thm"mult_1_right", thm"divide_1"]; | 
| 23164 | 296 | |
| 297 | (*Simplify inverse Numeral1, a/Numeral1*) | |
| 298 | val inverse_1s = [@{thm inverse_numeral_1}];
 | |
| 299 | val divide_1s = [@{thm divide_numeral_1}];
 | |
| 300 | ||
| 301 | (*To perform binary arithmetic. The "left" rewriting handles patterns | |
| 302 | created by the Int_Numeral_Base_Simprocs, such as 3 * (5 * x). *) | |
| 303 | val simps = [numeral_0_eq_0 RS sym, numeral_1_eq_1 RS sym, | |
| 304 | add_number_of_left, mult_number_of_left] @ | |
| 305 | arith_simps @ rel_simps; | |
| 306 | ||
| 307 | (*Binary arithmetic BUT NOT ADDITION since it may collapse adjacent terms | |
| 308 | during re-arrangement*) | |
| 309 | val non_add_simps = | |
| 310 | subtract Thm.eq_thm [add_number_of_left, number_of_add RS sym] simps; | |
| 311 | ||
| 312 | (*To evaluate binary negations of coefficients*) | |
| 313 | val minus_simps = [numeral_m1_eq_minus_1 RS sym, number_of_minus RS sym, | |
| 314 | minus_1, minus_0, minus_Pls, minus_Min, | |
| 315 | pred_1, pred_0, pred_Pls, pred_Min]; | |
| 316 | ||
| 317 | (*To let us treat subtraction as addition*) | |
| 318 | val diff_simps = [@{thm diff_minus}, @{thm minus_add_distrib}, @{thm minus_minus}];
 | |
| 319 | ||
| 320 | (*To let us treat division as multiplication*) | |
| 321 | val divide_simps = [@{thm divide_inverse}, @{thm inverse_mult_distrib}, @{thm inverse_inverse_eq}];
 | |
| 322 | ||
| 323 | (*push the unary minus down: - x * y = x * - y *) | |
| 324 | val minus_mult_eq_1_to_2 = | |
| 325 |     [@{thm minus_mult_left} RS sym, @{thm minus_mult_right}] MRS trans |> standard;
 | |
| 326 | ||
| 327 | (*to extract again any uncancelled minuses*) | |
| 328 | val minus_from_mult_simps = | |
| 329 |     [@{thm minus_minus}, @{thm minus_mult_left} RS sym, @{thm minus_mult_right} RS sym];
 | |
| 330 | ||
| 331 | (*combine unary minus with numeric literals, however nested within a product*) | |
| 332 | val mult_minus_simps = | |
| 333 |     [@{thm mult_assoc}, @{thm minus_mult_left}, minus_mult_eq_1_to_2];
 | |
| 334 | ||
| 335 | (*Apply the given rewrite (if present) just once*) | |
| 336 | fun trans_tac NONE = all_tac | |
| 337 | | trans_tac (SOME th) = ALLGOALS (rtac (th RS trans)); | |
| 338 | ||
| 339 | fun simplify_meta_eq rules = | |
| 340 | let val ss0 = HOL_basic_ss addeqcongs [eq_cong2] addsimps rules | |
| 341 | in fn ss => simplify (Simplifier.inherit_context ss ss0) o mk_meta_eq end | |
| 342 | ||
| 343 | structure CancelNumeralsCommon = | |
| 344 | struct | |
| 345 | val mk_sum = mk_sum | |
| 346 | val dest_sum = dest_sum | |
| 347 | val mk_coeff = mk_coeff | |
| 348 | val dest_coeff = dest_coeff 1 | |
| 349 | val find_first_coeff = find_first_coeff [] | |
| 350 | val trans_tac = fn _ => trans_tac | |
| 351 | ||
| 352 | val norm_ss1 = num_ss addsimps numeral_syms @ add_0s @ mult_1s @ | |
| 353 | diff_simps @ minus_simps @ add_ac | |
| 354 | val norm_ss2 = num_ss addsimps non_add_simps @ mult_minus_simps | |
| 355 | val norm_ss3 = num_ss addsimps minus_from_mult_simps @ add_ac @ mult_ac | |
| 356 | fun norm_tac ss = | |
| 357 | ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss1)) | |
| 358 | THEN ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss2)) | |
| 359 | THEN ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss3)) | |
| 360 | ||
| 361 | val numeral_simp_ss = HOL_ss addsimps add_0s @ simps | |
| 362 | fun numeral_simp_tac ss = ALLGOALS (simp_tac (Simplifier.inherit_context ss numeral_simp_ss)) | |
| 363 | val simplify_meta_eq = simplify_meta_eq (add_0s @ mult_1s) | |
| 364 | end; | |
| 365 | ||
| 366 | ||
| 367 | structure EqCancelNumerals = CancelNumeralsFun | |
| 368 | (open CancelNumeralsCommon | |
| 369 | val prove_conv = Int_Numeral_Base_Simprocs.prove_conv | |
| 370 | val mk_bal = HOLogic.mk_eq | |
| 371 | val dest_bal = HOLogic.dest_bin "op =" Term.dummyT | |
| 372 | val bal_add1 = eq_add_iff1 RS trans | |
| 373 | val bal_add2 = eq_add_iff2 RS trans | |
| 374 | ); | |
| 375 | ||
| 376 | structure LessCancelNumerals = CancelNumeralsFun | |
| 377 | (open CancelNumeralsCommon | |
| 378 | val prove_conv = Int_Numeral_Base_Simprocs.prove_conv | |
| 379 |   val mk_bal   = HOLogic.mk_binrel @{const_name Orderings.less}
 | |
| 380 |   val dest_bal = HOLogic.dest_bin @{const_name Orderings.less} Term.dummyT
 | |
| 381 | val bal_add1 = less_add_iff1 RS trans | |
| 382 | val bal_add2 = less_add_iff2 RS trans | |
| 383 | ); | |
| 384 | ||
| 385 | structure LeCancelNumerals = CancelNumeralsFun | |
| 386 | (open CancelNumeralsCommon | |
| 387 | val prove_conv = Int_Numeral_Base_Simprocs.prove_conv | |
| 388 |   val mk_bal   = HOLogic.mk_binrel @{const_name Orderings.less_eq}
 | |
| 389 |   val dest_bal = HOLogic.dest_bin @{const_name Orderings.less_eq} Term.dummyT
 | |
| 390 | val bal_add1 = le_add_iff1 RS trans | |
| 391 | val bal_add2 = le_add_iff2 RS trans | |
| 392 | ); | |
| 393 | ||
| 394 | val cancel_numerals = | |
| 395 | map Int_Numeral_Base_Simprocs.prep_simproc | |
| 396 |    [("inteq_cancel_numerals",
 | |
| 397 | ["(l::'a::number_ring) + m = n", | |
| 398 | "(l::'a::number_ring) = m + n", | |
| 399 | "(l::'a::number_ring) - m = n", | |
| 400 | "(l::'a::number_ring) = m - n", | |
| 401 | "(l::'a::number_ring) * m = n", | |
| 402 | "(l::'a::number_ring) = m * n"], | |
| 403 | K EqCancelNumerals.proc), | |
| 404 |     ("intless_cancel_numerals",
 | |
| 405 |      ["(l::'a::{ordered_idom,number_ring}) + m < n",
 | |
| 406 |       "(l::'a::{ordered_idom,number_ring}) < m + n",
 | |
| 407 |       "(l::'a::{ordered_idom,number_ring}) - m < n",
 | |
| 408 |       "(l::'a::{ordered_idom,number_ring}) < m - n",
 | |
| 409 |       "(l::'a::{ordered_idom,number_ring}) * m < n",
 | |
| 410 |       "(l::'a::{ordered_idom,number_ring}) < m * n"],
 | |
| 411 | K LessCancelNumerals.proc), | |
| 412 |     ("intle_cancel_numerals",
 | |
| 413 |      ["(l::'a::{ordered_idom,number_ring}) + m <= n",
 | |
| 414 |       "(l::'a::{ordered_idom,number_ring}) <= m + n",
 | |
| 415 |       "(l::'a::{ordered_idom,number_ring}) - m <= n",
 | |
| 416 |       "(l::'a::{ordered_idom,number_ring}) <= m - n",
 | |
| 417 |       "(l::'a::{ordered_idom,number_ring}) * m <= n",
 | |
| 418 |       "(l::'a::{ordered_idom,number_ring}) <= m * n"],
 | |
| 419 | K LeCancelNumerals.proc)]; | |
| 420 | ||
| 421 | ||
| 422 | structure CombineNumeralsData = | |
| 423 | struct | |
| 424 | type coeff = IntInf.int | |
| 425 | val iszero = (fn x : IntInf.int => x = 0) | |
| 426 | val add = IntInf.+ | |
| 427 | val mk_sum = long_mk_sum (*to work for e.g. 2*x + 3*x *) | |
| 428 | val dest_sum = dest_sum | |
| 429 | val mk_coeff = mk_coeff | |
| 430 | val dest_coeff = dest_coeff 1 | |
| 431 | val left_distrib = combine_common_factor RS trans | |
| 432 | val prove_conv = Int_Numeral_Base_Simprocs.prove_conv_nohyps | |
| 433 | val trans_tac = fn _ => trans_tac | |
| 434 | ||
| 435 | val norm_ss1 = num_ss addsimps numeral_syms @ add_0s @ mult_1s @ | |
| 436 | diff_simps @ minus_simps @ add_ac | |
| 437 | val norm_ss2 = num_ss addsimps non_add_simps @ mult_minus_simps | |
| 438 | val norm_ss3 = num_ss addsimps minus_from_mult_simps @ add_ac @ mult_ac | |
| 439 | fun norm_tac ss = | |
| 440 | ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss1)) | |
| 441 | THEN ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss2)) | |
| 442 | THEN ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss3)) | |
| 443 | ||
| 444 | val numeral_simp_ss = HOL_ss addsimps add_0s @ simps | |
| 445 | fun numeral_simp_tac ss = ALLGOALS (simp_tac (Simplifier.inherit_context ss numeral_simp_ss)) | |
| 446 | val simplify_meta_eq = simplify_meta_eq (add_0s @ mult_1s) | |
| 447 | end; | |
| 448 | ||
| 449 | structure CombineNumerals = CombineNumeralsFun(CombineNumeralsData); | |
| 450 | ||
| 451 | (*Version for fields, where coefficients can be fractions*) | |
| 452 | structure FieldCombineNumeralsData = | |
| 453 | struct | |
| 454 | type coeff = IntInf.int * IntInf.int | |
| 455 | val iszero = (fn (p : IntInf.int, q) => p = 0) | |
| 456 | val add = add_frac | |
| 457 | val mk_sum = long_mk_sum | |
| 458 | val dest_sum = dest_sum | |
| 459 | val mk_coeff = mk_fcoeff | |
| 460 | val dest_coeff = dest_fcoeff 1 | |
| 461 | val left_distrib = combine_common_factor RS trans | |
| 462 | val prove_conv = Int_Numeral_Base_Simprocs.prove_conv_nohyps | |
| 463 | val trans_tac = fn _ => trans_tac | |
| 464 | ||
| 465 | val norm_ss1 = num_ss addsimps numeral_syms @ add_0s @ mult_1s @ | |
| 466 | inverse_1s @ divide_simps @ diff_simps @ minus_simps @ add_ac | |
| 467 | val norm_ss2 = num_ss addsimps non_add_simps @ mult_minus_simps | |
| 468 | val norm_ss3 = num_ss addsimps minus_from_mult_simps @ add_ac @ mult_ac | |
| 469 | fun norm_tac ss = | |
| 470 | ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss1)) | |
| 471 | THEN ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss2)) | |
| 472 | THEN ALLGOALS (simp_tac (Simplifier.inherit_context ss norm_ss3)) | |
| 473 | ||
| 474 |   val numeral_simp_ss = HOL_ss addsimps add_0s @ simps @ [@{thm add_frac_eq}]
 | |
| 475 | fun numeral_simp_tac ss = ALLGOALS (simp_tac (Simplifier.inherit_context ss numeral_simp_ss)) | |
| 476 | val simplify_meta_eq = simplify_meta_eq (add_0s @ mult_1s @ divide_1s) | |
| 477 | end; | |
| 478 | ||
| 479 | structure FieldCombineNumerals = CombineNumeralsFun(FieldCombineNumeralsData); | |
| 480 | ||
| 481 | val combine_numerals = | |
| 482 | Int_Numeral_Base_Simprocs.prep_simproc | |
| 483 |     ("int_combine_numerals", 
 | |
| 484 | ["(i::'a::number_ring) + j", "(i::'a::number_ring) - j"], | |
| 485 | K CombineNumerals.proc); | |
| 486 | ||
| 487 | val field_combine_numerals = | |
| 488 | Int_Numeral_Base_Simprocs.prep_simproc | |
| 489 |     ("field_combine_numerals", 
 | |
| 490 |      ["(i::'a::{number_ring,field,division_by_zero}) + j",
 | |
| 491 |       "(i::'a::{number_ring,field,division_by_zero}) - j"], 
 | |
| 492 | K FieldCombineNumerals.proc); | |
| 493 | ||
| 494 | end; | |
| 495 | ||
| 496 | Addsimprocs Int_Numeral_Simprocs.cancel_numerals; | |
| 497 | Addsimprocs [Int_Numeral_Simprocs.combine_numerals]; | |
| 498 | Addsimprocs [Int_Numeral_Simprocs.field_combine_numerals]; | |
| 499 | ||
| 500 | (*examples: | |
| 501 | print_depth 22; | |
| 502 | set timing; | |
| 503 | set trace_simp; | |
| 504 | fun test s = (Goal s, by (Simp_tac 1)); | |
| 505 | ||
| 506 | test "l + 2 + 2 + 2 + (l + 2) + (oo + 2) = (uu::int)"; | |
| 507 | ||
| 508 | test "2*u = (u::int)"; | |
| 509 | test "(i + j + 12 + (k::int)) - 15 = y"; | |
| 510 | test "(i + j + 12 + (k::int)) - 5 = y"; | |
| 511 | ||
| 512 | test "y - b < (b::int)"; | |
| 513 | test "y - (3*b + c) < (b::int) - 2*c"; | |
| 514 | ||
| 515 | test "(2*x - (u*v) + y) - v*3*u = (w::int)"; | |
| 516 | test "(2*x*u*v + (u*v)*4 + y) - v*u*4 = (w::int)"; | |
| 517 | test "(2*x*u*v + (u*v)*4 + y) - v*u = (w::int)"; | |
| 518 | test "u*v - (x*u*v + (u*v)*4 + y) = (w::int)"; | |
| 519 | ||
| 520 | test "(i + j + 12 + (k::int)) = u + 15 + y"; | |
| 521 | test "(i + j*2 + 12 + (k::int)) = j + 5 + y"; | |
| 522 | ||
| 523 | test "2*y + 3*z + 6*w + 2*y + 3*z + 2*u = 2*y' + 3*z' + 6*w' + 2*y' + 3*z' + u + (vv::int)"; | |
| 524 | ||
| 525 | test "a + -(b+c) + b = (d::int)"; | |
| 526 | test "a + -(b+c) - b = (d::int)"; | |
| 527 | ||
| 528 | (*negative numerals*) | |
| 529 | test "(i + j + -2 + (k::int)) - (u + 5 + y) = zz"; | |
| 530 | test "(i + j + -3 + (k::int)) < u + 5 + y"; | |
| 531 | test "(i + j + 3 + (k::int)) < u + -6 + y"; | |
| 532 | test "(i + j + -12 + (k::int)) - 15 = y"; | |
| 533 | test "(i + j + 12 + (k::int)) - -15 = y"; | |
| 534 | test "(i + j + -12 + (k::int)) - -15 = y"; | |
| 535 | *) | |
| 536 | ||
| 537 | ||
| 538 | (** Constant folding for multiplication in semirings **) | |
| 539 | ||
| 540 | (*We do not need folding for addition: combine_numerals does the same thing*) | |
| 541 | ||
| 542 | structure Semiring_Times_Assoc_Data : ASSOC_FOLD_DATA = | |
| 543 | struct | |
| 544 | val assoc_ss = HOL_ss addsimps mult_ac | |
| 545 | val eq_reflection = eq_reflection | |
| 546 | end; | |
| 547 | ||
| 548 | structure Semiring_Times_Assoc = Assoc_Fold (Semiring_Times_Assoc_Data); | |
| 549 | ||
| 550 | val assoc_fold_simproc = | |
| 551 | Int_Numeral_Base_Simprocs.prep_simproc | |
| 552 |    ("semiring_assoc_fold", ["(a::'a::comm_semiring_1_cancel) * b"],
 | |
| 553 | K Semiring_Times_Assoc.proc); | |
| 554 | ||
| 555 | Addsimprocs [assoc_fold_simproc]; | |
| 556 | ||
| 557 | ||
| 558 | ||
| 559 | ||
| 560 | (*** decision procedure for linear arithmetic ***) | |
| 561 | ||
| 562 | (*---------------------------------------------------------------------------*) | |
| 563 | (* Linear arithmetic *) | |
| 564 | (*---------------------------------------------------------------------------*) | |
| 565 | ||
| 566 | (* | |
| 567 | Instantiation of the generic linear arithmetic package for int. | |
| 568 | *) | |
| 569 | ||
| 570 | (* Update parameters of arithmetic prover *) | |
| 571 | local | |
| 572 | ||
| 573 | (* reduce contradictory <= to False *) | |
| 574 | val add_rules = | |
| 575 | simp_thms @ arith_simps @ rel_simps @ arith_special @ | |
| 576 |     [@{thm neg_le_iff_le}, @{thm numeral_0_eq_0}, @{thm numeral_1_eq_1},
 | |
| 577 |      @{thm minus_zero}, @{thm diff_minus}, @{thm left_minus}, @{thm right_minus},
 | |
| 578 |      @{thm mult_zero_left}, @{thm mult_zero_right}, @{thm mult_num1}, @{thm mult_1_right},
 | |
| 579 |      @{thm minus_mult_left} RS sym, @{thm minus_mult_right} RS sym,
 | |
| 580 |      @{thm minus_add_distrib}, @{thm minus_minus}, @{thm mult_assoc},
 | |
| 23365 | 581 |      @{thm of_nat_0}, @{thm of_nat_1}, @{thm of_nat_Suc}, @{thm of_nat_add},
 | 
| 582 |      @{thm of_nat_mult}, @{thm of_int_0}, @{thm of_int_1}, @{thm of_int_add},
 | |
| 583 |      @{thm of_int_mult}]
 | |
| 23164 | 584 | |
| 23365 | 585 | val nat_inj_thms = [@{thm zle_int} RS iffD2, @{thm int_int_eq} RS iffD2]
 | 
| 23164 | 586 | |
| 587 | val Int_Numeral_Base_Simprocs = assoc_fold_simproc | |
| 588 | :: Int_Numeral_Simprocs.combine_numerals | |
| 589 | :: Int_Numeral_Simprocs.cancel_numerals; | |
| 590 | ||
| 591 | in | |
| 592 | ||
| 593 | val int_arith_setup = | |
| 594 |   Fast_Arith.map_data (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset} =>
 | |
| 595 |    {add_mono_thms = add_mono_thms,
 | |
| 596 |     mult_mono_thms = @{thm mult_strict_left_mono} :: @{thm mult_left_mono} :: mult_mono_thms,
 | |
| 597 | inj_thms = nat_inj_thms @ inj_thms, | |
| 598 | lessD = lessD @ [zless_imp_add1_zle], | |
| 599 | neqE = neqE, | |
| 600 | simpset = simpset addsimps add_rules | |
| 601 | addsimprocs Int_Numeral_Base_Simprocs | |
| 602 | addcongs [if_weak_cong]}) #> | |
| 603 |   arith_inj_const ("Nat.of_nat", HOLogic.natT --> HOLogic.intT) #>
 | |
| 604 | arith_discrete "IntDef.int" | |
| 605 | ||
| 606 | end; | |
| 607 | ||
| 608 | val fast_int_arith_simproc = | |
| 609 |   Simplifier.simproc @{theory}
 | |
| 610 | "fast_int_arith" | |
| 611 |      ["(m::'a::{ordered_idom,number_ring}) < n",
 | |
| 612 |       "(m::'a::{ordered_idom,number_ring}) <= n",
 | |
| 613 |       "(m::'a::{ordered_idom,number_ring}) = n"] Fast_Arith.lin_arith_prover;
 | |
| 614 | ||
| 615 | Addsimprocs [fast_int_arith_simproc]; |