src/HOL/arith_data.ML
changeset 20217 25b068a99d2b
parent 20044 92cc2f4c7335
child 20254 58b71535ed00
equal deleted inserted replaced
20216:f30b73385060 20217:25b068a99d2b
    26 (*normal form of sums: Suc (... (Suc (a + (b + ...))))*)
    26 (*normal form of sums: Suc (... (Suc (a + (b + ...))))*)
    27 fun mk_norm_sum ts =
    27 fun mk_norm_sum ts =
    28   let val (ones, sums) = List.partition (equal one) ts in
    28   let val (ones, sums) = List.partition (equal one) ts in
    29     funpow (length ones) HOLogic.mk_Suc (mk_sum sums)
    29     funpow (length ones) HOLogic.mk_Suc (mk_sum sums)
    30   end;
    30   end;
    31 
       
    32 
    31 
    33 (* dest_sum *)
    32 (* dest_sum *)
    34 
    33 
    35 val dest_plus = HOLogic.dest_bin "HOL.plus" HOLogic.natT;
    34 val dest_plus = HOLogic.dest_bin "HOL.plus" HOLogic.natT;
    36 
    35 
    42     | NONE =>
    41     | NONE =>
    43         (case try dest_plus tm of
    42         (case try dest_plus tm of
    44           SOME (t, u) => dest_sum t @ dest_sum u
    43           SOME (t, u) => dest_sum t @ dest_sum u
    45         | NONE => [tm]));
    44         | NONE => [tm]));
    46 
    45 
    47 
       
    48 (** generic proof tools **)
    46 (** generic proof tools **)
    49 
    47 
    50 (* prove conversions *)
    48 (* prove conversions *)
    51 
    49 
    52 fun prove_conv expand_tac norm_tac ss tu =  (* FIXME avoid standard *)
    50 fun prove_conv expand_tac norm_tac ss tu =  (* FIXME avoid standard *)
    55     (K (EVERY [expand_tac, norm_tac ss]))));
    53     (K (EVERY [expand_tac, norm_tac ss]))));
    56 
    54 
    57 val subst_equals = prove_goal HOL.thy "[| t = s; u = t |] ==> u = s"
    55 val subst_equals = prove_goal HOL.thy "[| t = s; u = t |] ==> u = s"
    58   (fn prems => [cut_facts_tac prems 1, SIMPSET' asm_simp_tac 1]);
    56   (fn prems => [cut_facts_tac prems 1, SIMPSET' asm_simp_tac 1]);
    59 
    57 
    60 
       
    61 (* rewriting *)
    58 (* rewriting *)
    62 
    59 
    63 fun simp_all_tac rules =
    60 fun simp_all_tac rules =
    64   let val ss0 = HOL_ss addsimps rules
    61   let val ss0 = HOL_ss addsimps rules
    65   in fn ss => ALLGOALS (simp_tac (Simplifier.inherit_context ss ss0)) end;
    62   in fn ss => ALLGOALS (simp_tac (Simplifier.inherit_context ss ss0)) end;
    68 val mult_rules = [mult_Suc, mult_Suc_right, mult_0, mult_0_right];
    65 val mult_rules = [mult_Suc, mult_Suc_right, mult_0, mult_0_right];
    69 
    66 
    70 fun prep_simproc (name, pats, proc) =
    67 fun prep_simproc (name, pats, proc) =
    71   Simplifier.simproc (the_context ()) name pats proc;
    68   Simplifier.simproc (the_context ()) name pats proc;
    72 
    69 
    73 end;
    70 end;  (* NatArithUtils *)
       
    71 
    74 
    72 
    75 signature ARITH_DATA =
    73 signature ARITH_DATA =
    76 sig
    74 sig
    77   val nat_cancel_sums_add: simproc list
    75   val nat_cancel_sums_add: simproc list
    78   val nat_cancel_sums: simproc list
    76   val nat_cancel_sums: simproc list
    79 end;
    77 end;
    80 
    78 
       
    79 
    81 structure ArithData: ARITH_DATA =
    80 structure ArithData: ARITH_DATA =
    82 struct
    81 struct
    83 
    82 
    84 open NatArithUtils;
    83 open NatArithUtils;
    85 
       
    86 
    84 
    87 (** cancel common summands **)
    85 (** cancel common summands **)
    88 
    86 
    89 structure Sum =
    87 structure Sum =
    90 struct
    88 struct
    97 end;
    95 end;
    98 
    96 
    99 fun gen_uncancel_tac rule ct =
    97 fun gen_uncancel_tac rule ct =
   100   rtac (instantiate' [] [NONE, SOME ct] (rule RS subst_equals)) 1;
    98   rtac (instantiate' [] [NONE, SOME ct] (rule RS subst_equals)) 1;
   101 
    99 
   102 
       
   103 (* nat eq *)
   100 (* nat eq *)
   104 
   101 
   105 structure EqCancelSums = CancelSumsFun
   102 structure EqCancelSums = CancelSumsFun
   106 (struct
   103 (struct
   107   open Sum;
   104   open Sum;
   108   val mk_bal = HOLogic.mk_eq;
   105   val mk_bal = HOLogic.mk_eq;
   109   val dest_bal = HOLogic.dest_bin "op =" HOLogic.natT;
   106   val dest_bal = HOLogic.dest_bin "op =" HOLogic.natT;
   110   val uncancel_tac = gen_uncancel_tac nat_add_left_cancel;
   107   val uncancel_tac = gen_uncancel_tac nat_add_left_cancel;
   111 end);
   108 end);
   112 
   109 
   113 
       
   114 (* nat less *)
   110 (* nat less *)
   115 
   111 
   116 structure LessCancelSums = CancelSumsFun
   112 structure LessCancelSums = CancelSumsFun
   117 (struct
   113 (struct
   118   open Sum;
   114   open Sum;
   119   val mk_bal = HOLogic.mk_binrel "Orderings.less";
   115   val mk_bal = HOLogic.mk_binrel "Orderings.less";
   120   val dest_bal = HOLogic.dest_bin "Orderings.less" HOLogic.natT;
   116   val dest_bal = HOLogic.dest_bin "Orderings.less" HOLogic.natT;
   121   val uncancel_tac = gen_uncancel_tac nat_add_left_cancel_less;
   117   val uncancel_tac = gen_uncancel_tac nat_add_left_cancel_less;
   122 end);
   118 end);
   123 
   119 
   124 
       
   125 (* nat le *)
   120 (* nat le *)
   126 
   121 
   127 structure LeCancelSums = CancelSumsFun
   122 structure LeCancelSums = CancelSumsFun
   128 (struct
   123 (struct
   129   open Sum;
   124   open Sum;
   130   val mk_bal = HOLogic.mk_binrel "Orderings.less_eq";
   125   val mk_bal = HOLogic.mk_binrel "Orderings.less_eq";
   131   val dest_bal = HOLogic.dest_bin "Orderings.less_eq" HOLogic.natT;
   126   val dest_bal = HOLogic.dest_bin "Orderings.less_eq" HOLogic.natT;
   132   val uncancel_tac = gen_uncancel_tac nat_add_left_cancel_le;
   127   val uncancel_tac = gen_uncancel_tac nat_add_left_cancel_le;
   133 end);
   128 end);
   134 
   129 
   135 
       
   136 (* nat diff *)
   130 (* nat diff *)
   137 
   131 
   138 structure DiffCancelSums = CancelSumsFun
   132 structure DiffCancelSums = CancelSumsFun
   139 (struct
   133 (struct
   140   open Sum;
   134   open Sum;
   141   val mk_bal = HOLogic.mk_binop "HOL.minus";
   135   val mk_bal = HOLogic.mk_binop "HOL.minus";
   142   val dest_bal = HOLogic.dest_bin "HOL.minus" HOLogic.natT;
   136   val dest_bal = HOLogic.dest_bin "HOL.minus" HOLogic.natT;
   143   val uncancel_tac = gen_uncancel_tac diff_cancel;
   137   val uncancel_tac = gen_uncancel_tac diff_cancel;
   144 end);
   138 end);
   145 
   139 
   146 
       
   147 
       
   148 (** prepare nat_cancel simprocs **)
   140 (** prepare nat_cancel simprocs **)
   149 
   141 
   150 val nat_cancel_sums_add = map prep_simproc
   142 val nat_cancel_sums_add = map prep_simproc
   151   [("nateq_cancel_sums",
   143   [("nateq_cancel_sums",
   152      ["(l::nat) + m = n", "(l::nat) = m + n", "Suc m = n", "m = Suc n"], K EqCancelSums.proc),
   144      ["(l::nat) + m = n", "(l::nat) = m + n", "Suc m = n", "m = Suc n"], K EqCancelSums.proc),
   157 
   149 
   158 val nat_cancel_sums = nat_cancel_sums_add @
   150 val nat_cancel_sums = nat_cancel_sums_add @
   159   [prep_simproc ("natdiff_cancel_sums",
   151   [prep_simproc ("natdiff_cancel_sums",
   160     ["((l::nat) + m) - n", "(l::nat) - (m + n)", "Suc m - n", "m - Suc n"], K DiffCancelSums.proc)];
   152     ["((l::nat) + m) - n", "(l::nat) - (m + n)", "Suc m - n", "m - Suc n"], K DiffCancelSums.proc)];
   161 
   153 
   162 end;
   154 end;  (* ArithData *)
   163 
   155 
   164 open ArithData;
   156 open ArithData;
   165 
   157 
   166 
   158 
   167 (*---------------------------------------------------------------------------*)
   159 (*---------------------------------------------------------------------------*)
   170 
   162 
   171 (* Parameters data for general linear arithmetic functor *)
   163 (* Parameters data for general linear arithmetic functor *)
   172 
   164 
   173 structure LA_Logic: LIN_ARITH_LOGIC =
   165 structure LA_Logic: LIN_ARITH_LOGIC =
   174 struct
   166 struct
       
   167 
   175 val ccontr = ccontr;
   168 val ccontr = ccontr;
   176 val conjI = conjI;
   169 val conjI = conjI;
   177 val notI = notI;
   170 val notI = notI;
   178 val sym = sym;
   171 val sym = sym;
   179 val not_lessD = linorder_not_less RS iffD1;
   172 val not_lessD = linorder_not_less RS iffD1;
   180 val not_leD = linorder_not_le RS iffD1;
   173 val not_leD = linorder_not_le RS iffD1;
   181 
   174 
   182 
       
   183 fun mk_Eq thm = (thm RS Eq_FalseI) handle THM _ => (thm RS Eq_TrueI);
   175 fun mk_Eq thm = (thm RS Eq_FalseI) handle THM _ => (thm RS Eq_TrueI);
   184 
   176 
   185 val mk_Trueprop = HOLogic.mk_Trueprop;
   177 val mk_Trueprop = HOLogic.mk_Trueprop;
   186 
   178 
   187 fun atomize thm = case #prop(rep_thm thm) of
   179 fun atomize thm = case #prop(rep_thm thm) of
   200 
   192 
   201 fun mk_nat_thm sg t =
   193 fun mk_nat_thm sg t =
   202   let val ct = cterm_of sg t  and cn = cterm_of sg (Var(("n",0),HOLogic.natT))
   194   let val ct = cterm_of sg t  and cn = cterm_of sg (Var(("n",0),HOLogic.natT))
   203   in instantiate ([],[(cn,ct)]) le0 end;
   195   in instantiate ([],[(cn,ct)]) le0 end;
   204 
   196 
   205 end;
   197 end;  (* LA_Logic *)
   206 
   198 
   207 
   199 
   208 (* arith theory data *)
   200 (* arith theory data *)
   209 
   201 
   210 structure ArithTheoryData = TheoryDataFun
   202 structure ArithTheoryData = TheoryDataFun
   233 
   225 
   234 fun arith_inj_const c = ArithTheoryData.map (fn {splits,inj_consts,discrete,presburger} =>
   226 fun arith_inj_const c = ArithTheoryData.map (fn {splits,inj_consts,discrete,presburger} =>
   235   {splits = splits, inj_consts = c :: inj_consts, discrete = discrete, presburger = presburger});
   227   {splits = splits, inj_consts = c :: inj_consts, discrete = discrete, presburger = presburger});
   236 
   228 
   237 
   229 
   238 structure LA_Data_Ref: LIN_ARITH_DATA =
   230 signature HOL_LIN_ARITH_DATA =
       
   231 sig
       
   232   include LIN_ARITH_DATA
       
   233   val fast_arith_split_limit : int ref
       
   234 end;
       
   235 
       
   236 structure LA_Data_Ref: HOL_LIN_ARITH_DATA =
   239 struct
   237 struct
       
   238 
       
   239 (* internal representation of linear (in-)equations *)
       
   240 type decompT = ((term * Rat.rat) list * Rat.rat * string * (term * Rat.rat) list * Rat.rat * bool);
   240 
   241 
   241 (* Decomposition of terms *)
   242 (* Decomposition of terms *)
   242 
   243 
   243 fun nT (Type("fun",[N,_])) = N = HOLogic.natT
   244 fun nT (Type("fun",[N,_])) = N = HOLogic.natT
   244   | nT _ = false;
   245   | nT _ = false;
   368   let val {discrete, inj_consts, ...} = ArithTheoryData.get sg
   369   let val {discrete, inj_consts, ...} = ArithTheoryData.get sg
   369   in decomp2 (sg,discrete,inj_consts) end
   370   in decomp2 (sg,discrete,inj_consts) end
   370 
   371 
   371 fun number_of(n,T) = HOLogic.number_of_const T $ (HOLogic.mk_binum n)
   372 fun number_of(n,T) = HOLogic.number_of_const T $ (HOLogic.mk_binum n)
   372 
   373 
   373 end;
   374 (*---------------------------------------------------------------------------*)
       
   375 (* code that performs certain goal transformations for linear arithmetic     *)
       
   376 (*---------------------------------------------------------------------------*)
       
   377 
       
   378 (* A "do nothing" variant of pre_decomp and pre_tac:
       
   379 
       
   380 fun pre_decomp sg Ts termitems = [termitems];
       
   381 fun pre_tac i = all_tac;
       
   382 *)
       
   383 
       
   384 (*---------------------------------------------------------------------------*)
       
   385 (* the following code performs splitting of certain constants (e.g. min,     *)
       
   386 (* max) in a linear arithmetic problem; similar to what split_tac later does *)
       
   387 (* to the proof state                                                        *)
       
   388 (*---------------------------------------------------------------------------*)
       
   389 
       
   390 val fast_arith_split_limit = ref 9;
       
   391 
       
   392 (* checks whether splitting with 'thm' is implemented                        *)
       
   393 
       
   394 (* Thm.thm -> bool *)
       
   395 
       
   396 fun is_split_thm thm =
       
   397   case concl_of thm of _ $ (_ $ (_ $ lhs) $ _) =>  (* Trueprop $ ((op =) $ (?P $ lhs) $ rhs) *)
       
   398     (case head_of lhs of
       
   399       Const (a, _) => a mem_string ["Orderings.max", "Orderings.min", "HOL.abs", "HOL.minus", "IntDef.nat", "Divides.op mod", "Divides.op div"]
       
   400     | _            => (warning ("Lin. Arith.: wrong format for split rule " ^ Display.string_of_thm thm); false))
       
   401   | _ => (warning ("Lin. Arith.: wrong format for split rule " ^ Display.string_of_thm thm); false);
       
   402 
       
   403 (* substitute new for occurrences of old in a term, incrementing bound       *)
       
   404 (* variables as needed when substituting inside an abstraction               *)
       
   405 
       
   406 (* (term * term) list -> term -> term *)
       
   407 
       
   408 fun subst_term []    t = t
       
   409   | subst_term pairs t =
       
   410       (case AList.lookup (op aconv) pairs t of
       
   411         SOME new =>
       
   412           new
       
   413       | NONE     =>
       
   414           (case t of Abs (a, T, body) =>
       
   415             let val pairs' = map (pairself (incr_boundvars 1)) pairs
       
   416             in  Abs (a, T, subst_term pairs' body)  end
       
   417           | t1 $ t2                   =>
       
   418             subst_term pairs t1 $ subst_term pairs t2
       
   419           | _ => t));
       
   420 
       
   421 (* approximates the effect of one application of split_tac (followed by NNF  *)
       
   422 (* normalization) on the subgoal represented by '(Ts, terms)'; returns a     *)
       
   423 (* list of new subgoals (each again represented by a typ list for bound      *)
       
   424 (* variables and a term list for premises), or NONE if split_tac would fail  *)
       
   425 (* on the subgoal                                                            *)
       
   426 
       
   427 (* theory -> typ list * term list -> (typ list * term list) list option *)
       
   428 
       
   429 (* FIXME: currently only the effect of certain split theorems is reproduced  *)
       
   430 (*        (which is why we need 'is_split_thm').  A more canonical           *)
       
   431 (*        implementation should analyze the right-hand side of the split     *)
       
   432 (*        theorem that can be applied, and modify the subgoal accordingly.   *)
       
   433 
       
   434 fun split_once_items sg (Ts, terms) =
       
   435 let
       
   436   (* takes a list  [t1, ..., tn]  to the term                                *)
       
   437   (*   tn' --> ... --> t1' --> False  ,                                      *)
       
   438   (* where ti' = HOLogic.dest_Trueprop ti                                    *)
       
   439   (* term list -> term *)
       
   440   fun REPEAT_DETERM_etac_rev_mp terms' =
       
   441     fold (curry HOLogic.mk_imp) (map HOLogic.dest_Trueprop terms') HOLogic.false_const
       
   442   val split_thms = filter is_split_thm (#splits (ArithTheoryData.get sg))
       
   443   val cmap       = Splitter.cmap_of_split_thms split_thms
       
   444   val splits     = Splitter.split_posns cmap sg Ts (REPEAT_DETERM_etac_rev_mp terms)
       
   445 in
       
   446   if length splits > !fast_arith_split_limit then (
       
   447     tracing ("fast_arith_split_limit exceeded (current value is " ^ string_of_int (!fast_arith_split_limit) ^ ")");
       
   448     NONE
       
   449   ) else (
       
   450   case splits of [] =>
       
   451     NONE  (* split_tac would fail: no possible split *)
       
   452   | ((_, _, _, split_type, split_term) :: _) => (  (* ignore all but the first possible split *)
       
   453     case strip_comb split_term of
       
   454     (* ?P (max ?i ?j) = ((?i <= ?j --> ?P ?j) & (~ ?i <= ?j --> ?P ?i)) *)
       
   455       (Const ("Orderings.max", _), [t1, t2]) =>
       
   456       let
       
   457         val rev_terms     = rev terms
       
   458         val terms1        = map (subst_term [(split_term, t1)]) rev_terms
       
   459         val terms2        = map (subst_term [(split_term, t2)]) rev_terms
       
   460         val t1_leq_t2     = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ t1 $ t2
       
   461         val not_t1_leq_t2 = HOLogic.Not $ t1_leq_t2
       
   462         val not_false     = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   463         val subgoal1      = (HOLogic.mk_Trueprop t1_leq_t2) :: terms2 @ [not_false]
       
   464         val subgoal2      = (HOLogic.mk_Trueprop not_t1_leq_t2) :: terms1 @ [not_false]
       
   465       in
       
   466         SOME [(Ts, subgoal1), (Ts, subgoal2)]
       
   467       end
       
   468     (* ?P (min ?i ?j) = ((?i <= ?j --> ?P ?i) & (~ ?i <= ?j --> ?P ?j)) *)
       
   469     | (Const ("Orderings.min", _), [t1, t2]) =>
       
   470       let
       
   471         val rev_terms     = rev terms
       
   472         val terms1        = map (subst_term [(split_term, t1)]) rev_terms
       
   473         val terms2        = map (subst_term [(split_term, t2)]) rev_terms
       
   474         val t1_leq_t2     = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ t1 $ t2
       
   475         val not_t1_leq_t2 = HOLogic.Not $ t1_leq_t2
       
   476         val not_false     = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   477         val subgoal1      = (HOLogic.mk_Trueprop t1_leq_t2) :: terms1 @ [not_false]
       
   478         val subgoal2      = (HOLogic.mk_Trueprop not_t1_leq_t2) :: terms2 @ [not_false]
       
   479       in
       
   480         SOME [(Ts, subgoal1), (Ts, subgoal2)]
       
   481       end
       
   482     (* ?P (abs ?a) = ((0 <= ?a --> ?P ?a) & (?a < 0 --> ?P (- ?a))) *)
       
   483     | (Const ("HOL.abs", _), [t1]) =>
       
   484       let
       
   485         val rev_terms     = rev terms
       
   486         val terms1        = map (subst_term [(split_term, t1)]) rev_terms
       
   487         val terms2        = map (subst_term [(split_term, Const ("HOL.uminus", split_type --> split_type) $ t1)]) rev_terms
       
   488         val zero          = Const ("0", split_type)
       
   489         val zero_leq_t1   = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ zero $ t1
       
   490         val t1_lt_zero    = Const ("Orderings.less", split_type --> split_type --> HOLogic.boolT) $ t1 $ zero
       
   491         val not_false     = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   492         val subgoal1      = (HOLogic.mk_Trueprop zero_leq_t1) :: terms1 @ [not_false]
       
   493         val subgoal2      = (HOLogic.mk_Trueprop t1_lt_zero) :: terms2 @ [not_false]
       
   494       in
       
   495         SOME [(Ts, subgoal1), (Ts, subgoal2)]
       
   496       end
       
   497     (* ?P (?a - ?b) = ((?a < ?b --> ?P 0) & (ALL d. ?a = ?b + d --> ?P d)) *)
       
   498     | (Const ("HOL.minus", _), [t1, t2]) =>
       
   499       let
       
   500         (* "d" in the above theorem becomes a new bound variable after NNF   *)
       
   501         (* transformation, therefore some adjustment of indices is necessary *)
       
   502         val rev_terms       = rev terms
       
   503         val zero            = Const ("0", split_type)
       
   504         val d               = Bound 0
       
   505         val terms1          = map (subst_term [(split_term, zero)]) rev_terms
       
   506         val terms2          = map (subst_term [(incr_boundvars 1 split_term, d)]) (map (incr_boundvars 1) rev_terms)
       
   507         val t1'             = incr_boundvars 1 t1
       
   508         val t2'             = incr_boundvars 1 t2
       
   509         val t1_lt_t2        = Const ("Orderings.less", split_type --> split_type --> HOLogic.boolT) $ t1 $ t2
       
   510         val t1_eq_t2_plus_d = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t1' $ (Const ("HOL.plus", split_type --> split_type --> split_type) $ t2' $ d)
       
   511         val not_false       = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   512         val subgoal1        = (HOLogic.mk_Trueprop t1_lt_t2) :: terms1 @ [not_false]
       
   513         val subgoal2        = (HOLogic.mk_Trueprop t1_eq_t2_plus_d) :: terms2 @ [not_false]
       
   514       in
       
   515         SOME [(Ts, subgoal1), (split_type :: Ts, subgoal2)]
       
   516       end
       
   517     (* ?P (nat ?i) = ((ALL n. ?i = int n --> ?P n) & (?i < 0 --> ?P 0)) *)
       
   518     | (Const ("IntDef.nat", _), [t1]) =>
       
   519       let
       
   520         val rev_terms   = rev terms
       
   521         val zero_int    = Const ("0", HOLogic.intT)
       
   522         val zero_nat    = Const ("0", HOLogic.natT)
       
   523         val n           = Bound 0
       
   524         val terms1      = map (subst_term [(incr_boundvars 1 split_term, n)]) (map (incr_boundvars 1) rev_terms)
       
   525         val terms2      = map (subst_term [(split_term, zero_nat)]) rev_terms
       
   526         val t1'         = incr_boundvars 1 t1
       
   527         val t1_eq_int_n = Const ("op =", HOLogic.intT --> HOLogic.intT --> HOLogic.boolT) $ t1' $ (Const ("IntDef.int", HOLogic.natT --> HOLogic.intT) $ n)
       
   528         val t1_lt_zero  = Const ("Orderings.less", HOLogic.intT --> HOLogic.intT --> HOLogic.boolT) $ t1 $ zero_int
       
   529         val not_false   = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   530         val subgoal1    = (HOLogic.mk_Trueprop t1_eq_int_n) :: terms1 @ [not_false]
       
   531         val subgoal2    = (HOLogic.mk_Trueprop t1_lt_zero) :: terms2 @ [not_false]
       
   532       in
       
   533         SOME [(HOLogic.natT :: Ts, subgoal1), (Ts, subgoal2)]
       
   534       end
       
   535     (* "?P ((?n::nat) mod (number_of ?k)) = ((number_of ?k = 0 --> ?P ?n) & (~ (number_of ?k = 0) --> (ALL i j. j < number_of ?k --> ?n = number_of ?k * i + j --> ?P j))) *)
       
   536     | (Const ("Divides.op mod", Type ("fun", [Type ("nat", []), _])), [t1, t2]) =>
       
   537       let
       
   538         val rev_terms               = rev terms
       
   539         val zero                    = Const ("0", split_type)
       
   540         val i                       = Bound 1
       
   541         val j                       = Bound 0
       
   542         val terms1                  = map (subst_term [(split_term, t1)]) rev_terms
       
   543         val terms2                  = map (subst_term [(incr_boundvars 2 split_term, j)]) (map (incr_boundvars 2) rev_terms)
       
   544         val t1'                     = incr_boundvars 2 t1
       
   545         val t2'                     = incr_boundvars 2 t2
       
   546         val t2_eq_zero              = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t2 $ zero
       
   547         val t2_neq_zero             = HOLogic.mk_not (Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t2' $ zero)
       
   548         val j_lt_t2                 = Const ("Orderings.less", split_type --> split_type--> HOLogic.boolT) $ j $ t2'
       
   549         val t1_eq_t2_times_i_plus_j = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t1' $
       
   550                                        (Const ("HOL.plus", split_type --> split_type --> split_type) $
       
   551                                          (Const ("HOL.times", split_type --> split_type --> split_type) $ t2' $ i) $ j)
       
   552         val not_false               = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   553         val subgoal1                = (HOLogic.mk_Trueprop t2_eq_zero) :: terms1 @ [not_false]
       
   554         val subgoal2                = (map HOLogic.mk_Trueprop [t2_neq_zero, j_lt_t2, t1_eq_t2_times_i_plus_j]) @ terms2 @ [not_false]
       
   555       in
       
   556         SOME [(Ts, subgoal1), (split_type :: split_type :: Ts, subgoal2)]
       
   557       end
       
   558     (* "?P ((?n::nat) div (number_of ?k)) = ((number_of ?k = 0 --> ?P 0) & (~ (number_of ?k = 0) --> (ALL i j. j < number_of ?k --> ?n = number_of ?k * i + j --> ?P i))) *)
       
   559     | (Const ("Divides.op div", Type ("fun", [Type ("nat", []), _])), [t1, t2]) =>
       
   560       let
       
   561         val rev_terms               = rev terms
       
   562         val zero                    = Const ("0", split_type)
       
   563         val i                       = Bound 1
       
   564         val j                       = Bound 0
       
   565         val terms1                  = map (subst_term [(split_term, zero)]) rev_terms
       
   566         val terms2                  = map (subst_term [(incr_boundvars 2 split_term, i)]) (map (incr_boundvars 2) rev_terms)
       
   567         val t1'                     = incr_boundvars 2 t1
       
   568         val t2'                     = incr_boundvars 2 t2
       
   569         val t2_eq_zero              = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t2 $ zero
       
   570         val t2_neq_zero             = HOLogic.mk_not (Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t2' $ zero)
       
   571         val j_lt_t2                 = Const ("Orderings.less", split_type --> split_type--> HOLogic.boolT) $ j $ t2'
       
   572         val t1_eq_t2_times_i_plus_j = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t1' $
       
   573                                        (Const ("HOL.plus", split_type --> split_type --> split_type) $
       
   574                                          (Const ("HOL.times", split_type --> split_type --> split_type) $ t2' $ i) $ j)
       
   575         val not_false               = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   576         val subgoal1                = (HOLogic.mk_Trueprop t2_eq_zero) :: terms1 @ [not_false]
       
   577         val subgoal2                = (map HOLogic.mk_Trueprop [t2_neq_zero, j_lt_t2, t1_eq_t2_times_i_plus_j]) @ terms2 @ [not_false]
       
   578       in
       
   579         SOME [(Ts, subgoal1), (split_type :: split_type :: Ts, subgoal2)]
       
   580       end
       
   581     (* "?P ((?n::int) mod (number_of ?k)) = ((iszero (number_of ?k) --> ?P ?n) &
       
   582                                               (neg (number_of (bin_minus ?k)) --> (ALL i j. 0 <= j & j < number_of ?k & ?n = number_of ?k * i + j --> ?P j)) &
       
   583                                               (neg (number_of ?k) --> (ALL i j. number_of ?k < j & j <= 0 & ?n = number_of ?k * i + j --> ?P j))) *)
       
   584     | (Const ("Divides.op mod", Type ("fun", [Type ("IntDef.int", []), _])), [t1, t2 as (number_of $ k)]) =>
       
   585       let
       
   586         val rev_terms               = rev terms
       
   587         val zero                    = Const ("0", split_type)
       
   588         val i                       = Bound 1
       
   589         val j                       = Bound 0
       
   590         val terms1                  = map (subst_term [(split_term, t1)]) rev_terms
       
   591         val terms2_3                = map (subst_term [(incr_boundvars 2 split_term, j)]) (map (incr_boundvars 2) rev_terms)
       
   592         val t1'                     = incr_boundvars 2 t1
       
   593         val (t2' as (_ $ k'))       = incr_boundvars 2 t2
       
   594         val iszero_t2               = Const ("IntDef.iszero", split_type --> HOLogic.boolT) $ t2
       
   595         val neg_minus_k             = Const ("IntDef.neg", split_type --> HOLogic.boolT) $
       
   596                                         (number_of $ (Const ("Numeral.bin_minus", HOLogic.binT --> HOLogic.binT) $ k'))
       
   597         val zero_leq_j              = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ zero $ j
       
   598         val j_lt_t2                 = Const ("Orderings.less", split_type --> split_type--> HOLogic.boolT) $ j $ t2'
       
   599         val t1_eq_t2_times_i_plus_j = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t1' $
       
   600                                        (Const ("HOL.plus", split_type --> split_type --> split_type) $
       
   601                                          (Const ("HOL.times", split_type --> split_type --> split_type) $ t2' $ i) $ j)
       
   602         val neg_t2                  = Const ("IntDef.neg", split_type --> HOLogic.boolT) $ t2'
       
   603         val t2_lt_j                 = Const ("Orderings.less", split_type --> split_type--> HOLogic.boolT) $ t2' $ j
       
   604         val j_leq_zero              = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ j $ zero
       
   605         val not_false               = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   606         val subgoal1                = (HOLogic.mk_Trueprop iszero_t2) :: terms1 @ [not_false]
       
   607         val subgoal2                = (map HOLogic.mk_Trueprop [neg_minus_k, zero_leq_j])
       
   608                                         @ hd terms2_3
       
   609                                         :: (if tl terms2_3 = [] then [not_false] else [])
       
   610                                         @ (map HOLogic.mk_Trueprop [j_lt_t2, t1_eq_t2_times_i_plus_j])
       
   611                                         @ (if tl terms2_3 = [] then [] else tl terms2_3 @ [not_false])
       
   612         val subgoal3                = (map HOLogic.mk_Trueprop [neg_t2, t2_lt_j])
       
   613                                         @ hd terms2_3
       
   614                                         :: (if tl terms2_3 = [] then [not_false] else [])
       
   615                                         @ (map HOLogic.mk_Trueprop [j_leq_zero, t1_eq_t2_times_i_plus_j])
       
   616                                         @ (if tl terms2_3 = [] then [] else tl terms2_3 @ [not_false])
       
   617         val Ts'                     = split_type :: split_type :: Ts
       
   618       in
       
   619         SOME [(Ts, subgoal1), (Ts', subgoal2), (Ts', subgoal3)]
       
   620       end
       
   621     (* "?P ((?n::int) div (number_of ?k)) = ((iszero (number_of ?k) --> ?P 0) &
       
   622                                               (neg (number_of (bin_minus ?k)) --> (ALL i. (EX j. 0 <= j & j < number_of ?k & ?n = number_of ?k * i + j) --> ?P i)) &
       
   623                                               (neg (number_of ?k) --> (ALL i. (EX j. number_of ?k < j & j <= 0 & ?n = number_of ?k * i + j) --> ?P i))) *)
       
   624     | (Const ("Divides.op div", Type ("fun", [Type ("IntDef.int", []), _])), [t1, t2 as (number_of $ k)]) =>
       
   625       let
       
   626         val rev_terms               = rev terms
       
   627         val zero                    = Const ("0", split_type)
       
   628         val i                       = Bound 1
       
   629         val j                       = Bound 0
       
   630         val terms1                  = map (subst_term [(split_term, zero)]) rev_terms
       
   631         val terms2_3                = map (subst_term [(incr_boundvars 2 split_term, i)]) (map (incr_boundvars 2) rev_terms)
       
   632         val t1'                     = incr_boundvars 2 t1
       
   633         val (t2' as (_ $ k'))       = incr_boundvars 2 t2
       
   634         val iszero_t2               = Const ("IntDef.iszero", split_type --> HOLogic.boolT) $ t2
       
   635         val neg_minus_k             = Const ("IntDef.neg", split_type --> HOLogic.boolT) $
       
   636                                         (number_of $ (Const ("Numeral.bin_minus", HOLogic.binT --> HOLogic.binT) $ k'))
       
   637         val zero_leq_j              = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ zero $ j
       
   638         val j_lt_t2                 = Const ("Orderings.less", split_type --> split_type--> HOLogic.boolT) $ j $ t2'
       
   639         val t1_eq_t2_times_i_plus_j = Const ("op =", split_type --> split_type --> HOLogic.boolT) $ t1' $
       
   640                                        (Const ("HOL.plus", split_type --> split_type --> split_type) $
       
   641                                          (Const ("HOL.times", split_type --> split_type --> split_type) $ t2' $ i) $ j)
       
   642         val neg_t2                  = Const ("IntDef.neg", split_type --> HOLogic.boolT) $ t2'
       
   643         val t2_lt_j                 = Const ("Orderings.less", split_type --> split_type--> HOLogic.boolT) $ t2' $ j
       
   644         val j_leq_zero              = Const ("Orderings.less_eq", split_type --> split_type --> HOLogic.boolT) $ j $ zero
       
   645         val not_false               = HOLogic.mk_Trueprop (HOLogic.Not $ HOLogic.false_const)
       
   646         val subgoal1                = (HOLogic.mk_Trueprop iszero_t2) :: terms1 @ [not_false]
       
   647         val subgoal2                = (HOLogic.mk_Trueprop neg_minus_k)
       
   648                                         :: terms2_3
       
   649                                         @ not_false
       
   650                                         :: (map HOLogic.mk_Trueprop [zero_leq_j, j_lt_t2, t1_eq_t2_times_i_plus_j])
       
   651         val subgoal3                = (HOLogic.mk_Trueprop neg_t2)
       
   652                                         :: terms2_3
       
   653                                         @ not_false
       
   654                                         :: (map HOLogic.mk_Trueprop [t2_lt_j, j_leq_zero, t1_eq_t2_times_i_plus_j])
       
   655         val Ts'                     = split_type :: split_type :: Ts
       
   656       in
       
   657         SOME [(Ts, subgoal1), (Ts', subgoal2), (Ts', subgoal3)]
       
   658       end
       
   659     (* this will only happen if a split theorem can be applied for which no code exists above -- *)
       
   660     (* in which case either the split theorem should be implemented above, or 'is_split_thm'     *)
       
   661     (* should be modified to filter it out                                                       *)
       
   662     | (t, ts) => (
       
   663       warning ("Lin. Arith.: split rule for " ^ Sign.string_of_term sg t ^ " (with " ^ Int.toString (length ts) ^
       
   664                " argument(s)) not implemented; proof reconstruction is likely to fail");
       
   665       NONE
       
   666     ))
       
   667   )
       
   668 end;
       
   669 
       
   670 (* remove terms that do not satisfy p; change the order of the remaining     *)
       
   671 (* terms in the same way as filter_prems_tac does                            *)
       
   672 
       
   673 (* (term -> bool) -> term list -> term list *)
       
   674 
       
   675 fun filter_prems_tac_items p terms =
       
   676 let
       
   677   fun filter_prems (t, (left, right)) =
       
   678     if  p t  then  (left, right @ [t])  else  (left @ right, [])
       
   679   val (left, right) = foldl filter_prems ([], []) terms
       
   680 in
       
   681   right @ left
       
   682 end;
       
   683 
       
   684 (* return true iff TRY (etac notE) THEN eq_assume_tac would succeed on a     *)
       
   685 (* subgoal that has 'terms' as premises                                      *)
       
   686 
       
   687 (* term list -> bool *)
       
   688 
       
   689 fun negated_term_occurs_positively terms =
       
   690   List.exists (fn (TP $ (Const ("Not", _) $ t)) => member (op aconv) terms (TP $ t) | _ => false) terms;
       
   691 
       
   692 (* theory -> typ list * term list -> (typ list * term list) list *)
       
   693 
       
   694 fun pre_decomp sg (Ts, terms) =
       
   695 let
       
   696   (* repeatedly split (including newly emerging subgoals) until no further   *)
       
   697   (* splitting is possible                                                   *)
       
   698   (* (typ list * term list) list -> (typ list * term list) list *)
       
   699   fun split_loop [] = []
       
   700     | split_loop (subgoal::subgoals) = (
       
   701         case split_once_items sg subgoal of
       
   702           SOME new_subgoals => split_loop (new_subgoals @ subgoals)
       
   703         | NONE              => subgoal :: split_loop subgoals
       
   704       )
       
   705   fun is_relevant t  = isSome (decomp sg t)
       
   706   val relevant_terms = filter_prems_tac_items is_relevant terms                                (* filter_prems_tac is_relevant *)
       
   707   val split_goals    = split_loop [(Ts, relevant_terms)]                                       (* split_tac, NNF normalization *)
       
   708   val beta_eta_norm  = map (apsnd (map (Envir.eta_contract o Envir.beta_norm))) split_goals    (* necessary because split_once_tac may normalize terms *)
       
   709   val result         = List.filter (not o negated_term_occurs_positively o snd) beta_eta_norm  (* TRY (etac notE) THEN eq_assume_tac *)
       
   710 in
       
   711   result
       
   712 end;
       
   713 
       
   714 (* takes the i-th subgoal  [| A1; ...; An |] ==> B  to                       *)
       
   715 (* An --> ... --> A1 --> B,  performs splitting with the given 'split_thms'  *)
       
   716 (* (resulting in a different subgoal P), takes  P  to  ~P ==> False,         *)
       
   717 (* performs NNF-normalization of ~P, and eliminates conjunctions,            *)
       
   718 (* disjunctions and existential quantifiers from the premises, possibly (in  *)
       
   719 (* the case of disjunctions) resulting in several new subgoals, each of the  *)
       
   720 (* general form  [| Q1; ...; Qm |] ==> False.  Fails if more than            *)
       
   721 (* !fast_arith_split_limit splits are possible.                              *)
       
   722 
       
   723 (* Thm.thm list -> int -> Tactical.tactic *)
       
   724 
       
   725 fun split_once_tac split_thms i =
       
   726 let
       
   727   val nnf_simpset =
       
   728     empty_ss setmkeqTrue mk_eq_True
       
   729     setmksimps (mksimps mksimps_pairs)
       
   730     addsimps [imp_conv_disj, iff_conv_conj_imp, de_Morgan_disj, de_Morgan_conj, 
       
   731       not_all, not_ex, not_not]
       
   732   fun prem_nnf_tac i st =
       
   733     full_simp_tac (Simplifier.theory_context (Thm.theory_of_thm st) nnf_simpset) i st
       
   734   fun cond_split_tac i st =
       
   735     let
       
   736       val subgoal = Logic.nth_prem (i, Thm.prop_of st)
       
   737       val Ts      = rev (map snd (Logic.strip_params subgoal))
       
   738       val concl   = HOLogic.dest_Trueprop (Logic.strip_assums_concl subgoal)
       
   739       val cmap    = Splitter.cmap_of_split_thms split_thms
       
   740       val splits  = Splitter.split_posns cmap (theory_of_thm st) Ts concl
       
   741     in
       
   742       if length splits > !fast_arith_split_limit then
       
   743         no_tac st
       
   744       else
       
   745         split_tac split_thms i st
       
   746     end
       
   747 in
       
   748   EVERY' [
       
   749     REPEAT_DETERM o etac rev_mp,
       
   750     cond_split_tac,
       
   751     rtac ccontr,
       
   752     prem_nnf_tac,
       
   753     TRY o REPEAT_ALL_NEW (DETERM o (eresolve_tac [conjE, exE] ORELSE' etac disjE))
       
   754   ] i
       
   755 end;
       
   756 
       
   757 (* remove irrelevant premises, then split the i-th subgoal (and all new      *)
       
   758 (* subgoals) by using 'split_once_tac' repeatedly.  Beta-eta-normalize new   *)
       
   759 (* subgoals and finally attempt to solve them by finding an immediate        *)
       
   760 (* contradiction (i.e. a term and its negation) in their premises.           *)
       
   761 
       
   762 (* int -> Tactical.tactic *)
       
   763 
       
   764 fun pre_tac i st =
       
   765 let
       
   766   val sg            = theory_of_thm st
       
   767   val split_thms    = filter is_split_thm (#splits (ArithTheoryData.get sg))
       
   768   fun is_relevant t = isSome (decomp sg t)
       
   769 in
       
   770   DETERM (
       
   771     TRY (filter_prems_tac is_relevant i)
       
   772       THEN (
       
   773         (TRY o REPEAT_ALL_NEW (split_once_tac split_thms))
       
   774           THEN_ALL_NEW
       
   775             ((fn j => PRIMITIVE (Drule.fconv_rule (Drule.goals_conv (equal j) (Drule.beta_eta_conversion))))
       
   776               THEN'
       
   777             (TRY o (etac notE THEN' eq_assume_tac)))
       
   778       ) i
       
   779   ) st
       
   780 end;
       
   781 
       
   782 end;  (* LA_Data_Ref *)
   374 
   783 
   375 
   784 
   376 structure Fast_Arith =
   785 structure Fast_Arith =
   377   Fast_Lin_Arith(structure LA_Logic=LA_Logic and LA_Data=LA_Data_Ref);
   786   Fast_Lin_Arith(structure LA_Logic=LA_Logic and LA_Data=LA_Data_Ref);
   378 
   787 
   379 val fast_arith_tac    = Fast_Arith.lin_arith_tac false
   788 val fast_arith_tac         = Fast_Arith.lin_arith_tac false;
   380 and fast_ex_arith_tac = Fast_Arith.lin_arith_tac
   789 val fast_ex_arith_tac      = Fast_Arith.lin_arith_tac;
   381 and trace_arith    = Fast_Arith.trace
   790 val trace_arith            = Fast_Arith.trace;
   382 and fast_arith_neq_limit = Fast_Arith.fast_arith_neq_limit;
   791 val fast_arith_neq_limit   = Fast_Arith.fast_arith_neq_limit;
       
   792 val fast_arith_split_limit = LA_Data_Ref.fast_arith_split_limit;
   383 
   793 
   384 local
   794 local
   385 
   795 
   386 (* reduce contradictory <= to False.
   796 (* reduce contradictory <= to False.
   387    Most of the work is done by the cancel tactics.
   797    Most of the work is done by the cancel tactics.
   437 
   847 
   438 val fast_nat_arith_simproc =
   848 val fast_nat_arith_simproc =
   439   Simplifier.simproc (the_context ()) "fast_nat_arith"
   849   Simplifier.simproc (the_context ()) "fast_nat_arith"
   440     ["(m::nat) < n","(m::nat) <= n", "(m::nat) = n"] Fast_Arith.lin_arith_prover;
   850     ["(m::nat) < n","(m::nat) <= n", "(m::nat) = n"] Fast_Arith.lin_arith_prover;
   441 
   851 
   442 
       
   443 (* Because of fast_nat_arith_simproc, the arithmetic solver is really only
   852 (* Because of fast_nat_arith_simproc, the arithmetic solver is really only
   444 useful to detect inconsistencies among the premises for subgoals which are
   853 useful to detect inconsistencies among the premises for subgoals which are
   445 *not* themselves (in)equalities, because the latter activate
   854 *not* themselves (in)equalities, because the latter activate
   446 fast_nat_arith_simproc anyway. However, it seems cheaper to activate the
   855 fast_nat_arith_simproc anyway. However, it seems cheaper to activate the
   447 solver all the time rather than add the additional check. *)
   856 solver all the time rather than add the additional check. *)
   448 
   857 
   449 
   858 
   450 (* arith proof method *)
   859 (* arith proof method *)
   451 
   860 
   452 (* FIXME: K true should be replaced by a sensible test to speed things up
       
   453    in case there are lots of irrelevant terms involved;
       
   454    elimination of min/max can be optimized:
       
   455    (max m n + k <= r) = (m+k <= r & n+k <= r)
       
   456    (l <= min m n + k) = (l <= m+k & l <= n+k)
       
   457 *)
       
   458 local
   861 local
   459 (* a simpset for computations subject to optimization !!! *)
   862 
   460 (*
       
   461 val binarith = map thm
       
   462   ["Pls_0_eq", "Min_1_eq",
       
   463  "bin_pred_Pls","bin_pred_Min","bin_pred_1","bin_pred_0",
       
   464   "bin_succ_Pls", "bin_succ_Min", "bin_succ_1", "bin_succ_0",
       
   465   "bin_add_Pls", "bin_add_Min", "bin_add_BIT_0", "bin_add_BIT_10",
       
   466   "bin_add_BIT_11", "bin_minus_Pls", "bin_minus_Min", "bin_minus_1", 
       
   467   "bin_minus_0", "bin_mult_Pls", "bin_mult_Min", "bin_mult_1", "bin_mult_0", 
       
   468   "bin_add_Pls_right", "bin_add_Min_right"];
       
   469  val intarithrel = 
       
   470      (map thm ["int_eq_number_of_eq","int_neg_number_of_BIT", 
       
   471 		"int_le_number_of_eq","int_iszero_number_of_0",
       
   472 		"int_less_number_of_eq_neg"]) @
       
   473      (map (fn s => thm s RS thm "lift_bool") 
       
   474 	  ["int_iszero_number_of_Pls","int_iszero_number_of_1",
       
   475 	   "int_neg_number_of_Min"])@
       
   476      (map (fn s => thm s RS thm "nlift_bool") 
       
   477 	  ["int_nonzero_number_of_Min","int_not_neg_number_of_Pls"]);
       
   478      
       
   479 val intarith = map thm ["int_number_of_add_sym", "int_number_of_minus_sym",
       
   480 			"int_number_of_diff_sym", "int_number_of_mult_sym"];
       
   481 val natarith = map thm ["add_nat_number_of", "diff_nat_number_of",
       
   482 			"mult_nat_number_of", "eq_nat_number_of",
       
   483 			"less_nat_number_of"]
       
   484 val powerarith = 
       
   485     (map thm ["nat_number_of", "zpower_number_of_even", 
       
   486 	      "zpower_Pls", "zpower_Min"]) @ 
       
   487     [(Tactic.simplify true [thm "zero_eq_Numeral0_nring", 
       
   488 			   thm "one_eq_Numeral1_nring"] 
       
   489   (thm "zpower_number_of_odd"))]
       
   490 
       
   491 val comp_arith = binarith @ intarith @ intarithrel @ natarith 
       
   492 	    @ powerarith @[thm"not_false_eq_true", thm "not_true_eq_false"];
       
   493 
       
   494 val comp_ss = HOL_basic_ss addsimps comp_arith addsimps simp_thms;
       
   495 *)
       
   496 fun raw_arith_tac ex i st =
   863 fun raw_arith_tac ex i st =
       
   864   (* FIXME: K true should be replaced by a sensible test (perhaps "isSome o
       
   865      decomp sg"?) to speed things up in case there are lots of irrelevant
       
   866      terms involved; elimination of min/max can be optimized:
       
   867      (max m n + k <= r) = (m+k <= r & n+k <= r)
       
   868      (l <= min m n + k) = (l <= m+k & l <= n+k)
       
   869   *)
   497   refute_tac (K true)
   870   refute_tac (K true)
   498    (REPEAT_DETERM o split_tac (#splits (ArithTheoryData.get (Thm.theory_of_thm st))))
   871     (* Splitting is also done inside fast_arith_tac, but not completely --   *)
   499 (*   (REPEAT o 
   872     (* split_tac may use split theorems that have not been implemented in    *)
   500     (fn i =>(split_tac (#splits (ArithTheoryData.get(Thm.theory_of_thm st))) i)
   873     (* fast_arith_tac (cf. pre_decomp and split_once_items above).           *)
   501 		THEN (simp_tac comp_ss i))) *)
   874     (* Therefore splitting outside of fast_arith_tac may allow us to prove   *)
   502    ((REPEAT_DETERM o etac linorder_neqE) THEN' fast_ex_arith_tac ex)
   875     (* some goals that fast_arith_tac alone would fail on.                   *)
   503    i st;
   876     (REPEAT_DETERM o split_tac (#splits (ArithTheoryData.get (Thm.theory_of_thm st))))
       
   877     (fast_ex_arith_tac ex)
       
   878     i st;
   504 
   879 
   505 fun presburger_tac i st =
   880 fun presburger_tac i st =
   506   (case ArithTheoryData.get (Thm.theory_of_thm st) of
   881   (case ArithTheoryData.get (Thm.theory_of_thm st) of
   507      {presburger = SOME tac, ...} =>
   882      {presburger = SOME tac, ...} =>
   508        (warning "Trying full Presburger arithmetic ..."; tac i st)
   883        (warning "Trying full Presburger arithmetic ..."; tac i st)
   509    | _ => no_tac st);
   884    | _ => no_tac st);
   510 
   885 
   511 in
   886 in
   512 
   887 
   513 val simple_arith_tac = FIRST' [fast_arith_tac,
   888   val simple_arith_tac = FIRST' [fast_arith_tac,
   514   ObjectLogic.atomize_tac THEN' raw_arith_tac true];
   889     ObjectLogic.atomize_tac THEN' raw_arith_tac true];
   515 
   890 
   516 val arith_tac = FIRST' [fast_arith_tac,
   891   val arith_tac = FIRST' [fast_arith_tac,
   517   ObjectLogic.atomize_tac THEN' raw_arith_tac true,
   892     ObjectLogic.atomize_tac THEN' raw_arith_tac true,
   518   presburger_tac];
   893     presburger_tac];
   519 
   894 
   520 val silent_arith_tac = FIRST' [fast_arith_tac,
   895   val silent_arith_tac = FIRST' [fast_arith_tac,
   521   ObjectLogic.atomize_tac THEN' raw_arith_tac false,
   896     ObjectLogic.atomize_tac THEN' raw_arith_tac false,
   522   presburger_tac];
   897     presburger_tac];
   523 
   898 
   524 fun arith_method prems =
   899   fun arith_method prems =
   525   Method.METHOD (fn facts => HEADGOAL (Method.insert_tac (prems @ facts) THEN' arith_tac));
   900     Method.METHOD (fn facts => HEADGOAL (Method.insert_tac (prems @ facts) THEN' arith_tac));
   526 
   901 
   527 end;
   902 end;
   528 
   903 
   529 (* antisymmetry:
   904 (* antisymmetry:
   530    combines x <= y (or ~(y < x)) and y <= x (or ~(x < y)) into x = y
   905    combines x <= y (or ~(y < x)) and y <= x (or ~(x < y)) into x = y