src/HOL/arith_data.ML
changeset 24076 ae946f751c44
parent 23881 851c74f1bb69
child 24095 785c3cd7fcb5
equal deleted inserted replaced
24075:366d4d234814 24076:ae946f751c44
   174 
   174 
   175 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);
   176 
   176 
   177 val mk_Trueprop = HOLogic.mk_Trueprop;
   177 val mk_Trueprop = HOLogic.mk_Trueprop;
   178 
   178 
   179 fun atomize thm = case #prop(rep_thm thm) of
   179 fun atomize thm = case Thm.prop_of thm of
   180     Const("Trueprop",_) $ (Const("op &",_) $ _ $ _) =>
   180     Const("Trueprop",_) $ (Const("op &",_) $ _ $ _) =>
   181     atomize(thm RS conjunct1) @ atomize(thm RS conjunct2)
   181     atomize(thm RS conjunct1) @ atomize(thm RS conjunct2)
   182   | _ => [thm];
   182   | _ => [thm];
   183 
   183 
   184 fun neg_prop ((TP as Const("Trueprop",_)) $ (Const("Not",_) $ t)) = TP $ t
   184 fun neg_prop ((TP as Const("Trueprop",_)) $ (Const("Not",_) $ t)) = TP $ t
   185   | neg_prop ((TP as Const("Trueprop",_)) $ t) = TP $ (HOLogic.Not $t)
   185   | neg_prop ((TP as Const("Trueprop",_)) $ t) = TP $ (HOLogic.Not $t)
   186   | neg_prop t = raise TERM ("neg_prop", [t]);
   186   | neg_prop t = raise TERM ("neg_prop", [t]);
   187 
   187 
   188 fun is_False thm =
   188 fun is_False thm =
   189   let val _ $ t = #prop(rep_thm thm)
   189   let val _ $ t = Thm.prop_of thm
   190   in t = Const("False",HOLogic.boolT) end;
   190   in t = Const("False",HOLogic.boolT) end;
   191 
   191 
   192 fun is_nat(t) = fastype_of1 t = HOLogic.natT;
   192 fun is_nat(t) = fastype_of1 t = HOLogic.natT;
   193 
   193 
   194 fun mk_nat_thm sg t =
   194 fun mk_nat_thm sg t =
   204 
   204 
   205 fun mk_arith_tactic name tactic = ArithTactic {name = name, tactic = tactic, id = stamp ()};
   205 fun mk_arith_tactic name tactic = ArithTactic {name = name, tactic = tactic, id = stamp ()};
   206 
   206 
   207 fun eq_arith_tactic (ArithTactic {id = id1, ...}, ArithTactic {id = id2, ...}) = (id1 = id2);
   207 fun eq_arith_tactic (ArithTactic {id = id1, ...}, ArithTactic {id = id2, ...}) = (id1 = id2);
   208 
   208 
   209 structure ArithTheoryData = TheoryDataFun
   209 structure ArithContextData = GenericDataFun
   210 (
   210 (
   211   type T = {splits: thm list,
   211   type T = {splits: thm list,
   212             inj_consts: (string * typ) list,
   212             inj_consts: (string * typ) list,
   213             discrete: string list,
   213             discrete: string list,
   214             tactics: arithtactic list};
   214             tactics: arithtactic list};
   215   val empty = {splits = [], inj_consts = [], discrete = [], tactics = []};
   215   val empty = {splits = [], inj_consts = [], discrete = [], tactics = []};
   216   val copy = I;
       
   217   val extend = I;
   216   val extend = I;
   218   fun merge _ ({splits= splits1, inj_consts= inj_consts1, discrete= discrete1, tactics= tactics1},
   217   fun merge _ ({splits= splits1, inj_consts= inj_consts1, discrete= discrete1, tactics= tactics1},
   219              {splits= splits2, inj_consts= inj_consts2, discrete= discrete2, tactics= tactics2}) =
   218              {splits= splits2, inj_consts= inj_consts2, discrete= discrete2, tactics= tactics2}) =
   220    {splits = Library.merge Thm.eq_thm_prop (splits1, splits2),
   219    {splits = Library.merge Thm.eq_thm_prop (splits1, splits2),
   221     inj_consts = Library.merge (op =) (inj_consts1, inj_consts2),
   220     inj_consts = Library.merge (op =) (inj_consts1, inj_consts2),
   222     discrete = Library.merge (op =) (discrete1, discrete2),
   221     discrete = Library.merge (op =) (discrete1, discrete2),
   223     tactics = Library.merge eq_arith_tactic (tactics1, tactics2)};
   222     tactics = Library.merge eq_arith_tactic (tactics1, tactics2)};
   224 );
   223 );
   225 
   224 
       
   225 val get_arith_data = ArithContextData.get o Context.Proof;
       
   226 
   226 val arith_split_add = Thm.declaration_attribute (fn thm =>
   227 val arith_split_add = Thm.declaration_attribute (fn thm =>
   227   Context.mapping (ArithTheoryData.map (fn {splits,inj_consts,discrete,tactics} =>
   228   ArithContextData.map (fn {splits, inj_consts, discrete, tactics} =>
   228     {splits= insert Thm.eq_thm_prop thm splits, inj_consts= inj_consts, discrete= discrete, tactics= tactics})) I);
   229     {splits = insert Thm.eq_thm_prop thm splits,
   229 
   230      inj_consts = inj_consts, discrete = discrete, tactics = tactics}));
   230 fun arith_discrete d = ArithTheoryData.map (fn {splits,inj_consts,discrete,tactics} =>
   231 
   231   {splits = splits, inj_consts = inj_consts, discrete = insert (op =) d discrete, tactics= tactics});
   232 fun arith_discrete d = ArithContextData.map (fn {splits, inj_consts, discrete, tactics} =>
   232 
   233   {splits = splits, inj_consts = inj_consts,
   233 fun arith_inj_const c = ArithTheoryData.map (fn {splits,inj_consts,discrete,tactics} =>
   234    discrete = insert (op =) d discrete, tactics = tactics});
   234   {splits = splits, inj_consts = insert (op =) c inj_consts, discrete = discrete, tactics= tactics});
   235 
   235 
   236 fun arith_inj_const c = ArithContextData.map (fn {splits, inj_consts, discrete, tactics} =>
   236 fun arith_tactic_add tac = ArithTheoryData.map (fn {splits,inj_consts,discrete,tactics} =>
   237   {splits = splits, inj_consts = insert (op =) c inj_consts,
   237   {splits= splits, inj_consts= inj_consts, discrete= discrete, tactics= insert eq_arith_tactic tac tactics});
   238    discrete = discrete, tactics= tactics});
       
   239 
       
   240 fun arith_tactic_add tac = ArithContextData.map (fn {splits, inj_consts, discrete, tactics} =>
       
   241   {splits = splits, inj_consts = inj_consts, discrete = discrete,
       
   242    tactics = insert eq_arith_tactic tac tactics});
   238 
   243 
   239 
   244 
   240 signature HOL_LIN_ARITH_DATA =
   245 signature HOL_LIN_ARITH_DATA =
   241 sig
   246 sig
   242   include LIN_ARITH_DATA
   247   include LIN_ARITH_DATA
   243   val fast_arith_split_limit : int ref
   248   val fast_arith_split_limit: int ConfigOption.T
       
   249   val setup_options: theory -> theory
   244 end;
   250 end;
   245 
   251 
   246 structure LA_Data_Ref: HOL_LIN_ARITH_DATA =
   252 structure LA_Data_Ref: HOL_LIN_ARITH_DATA =
   247 struct
   253 struct
       
   254 
       
   255 val (fast_arith_split_limit, setup1) = ConfigOption.int "fast_arith_split_limit" 9;
       
   256 val (fast_arith_neq_limit, setup2) = ConfigOption.int "fast_arith_neq_limit" 9;
       
   257 val setup_options = setup1 #> setup2;
       
   258 
   248 
   259 
   249 (* internal representation of linear (in-)equations *)
   260 (* internal representation of linear (in-)equations *)
   250 type decompT = ((term * Rat.rat) list * Rat.rat * string * (term * Rat.rat) list * Rat.rat * bool);
   261 type decompT = ((term * Rat.rat) list * Rat.rat * string * (term * Rat.rat) list * Rat.rat * bool);
   251 
   262 
   252 (* Decomposition of terms *)
   263 (* Decomposition of terms *)
   385   else (* special cases *)
   396   else (* special cases *)
   386     if D mem discrete then  (true, true)  else  (false, false)
   397     if D mem discrete then  (true, true)  else  (false, false)
   387   | allows_lin_arith sg discrete U =
   398   | allows_lin_arith sg discrete U =
   388   (of_lin_arith_sort sg U, false);
   399   (of_lin_arith_sort sg U, false);
   389 
   400 
   390 fun decomp_typecheck (sg, discrete, inj_consts) (T : typ, xxx) : decompT option =
   401 fun decomp_typecheck (thy, discrete, inj_consts) (T : typ, xxx) : decompT option =
   391   case T of
   402   case T of
   392     Type ("fun", [U, _]) =>
   403     Type ("fun", [U, _]) =>
   393       (case allows_lin_arith sg discrete U of
   404       (case allows_lin_arith thy discrete U of
   394         (true, d) =>
   405         (true, d) =>
   395           (case decomp0 inj_consts xxx of
   406           (case decomp0 inj_consts xxx of
   396             NONE                   => NONE
   407             NONE                   => NONE
   397           | SOME (p, i, rel, q, j) => SOME (p, i, rel, q, j, d))
   408           | SOME (p, i, rel, q, j) => SOME (p, i, rel, q, j, d))
   398       | (false, _) =>
   409       | (false, _) =>
   409   (Const ("Not", _) $ (Const (rel, T) $ lhs $ rhs))) =
   420   (Const ("Not", _) $ (Const (rel, T) $ lhs $ rhs))) =
   410       negate (decomp_typecheck data (T, (rel, lhs, rhs)))
   421       negate (decomp_typecheck data (T, (rel, lhs, rhs)))
   411   | decomp_negation data _ =
   422   | decomp_negation data _ =
   412       NONE;
   423       NONE;
   413 
   424 
   414 fun decomp sg : term -> decompT option =
   425 fun decomp ctxt : term -> decompT option =
   415 let
   426   let
   416   val {discrete, inj_consts, ...} = ArithTheoryData.get sg
   427     val thy = ProofContext.theory_of ctxt
   417 in
   428     val {discrete, inj_consts, ...} = get_arith_data ctxt
   418   decomp_negation (sg, discrete, inj_consts)
   429   in decomp_negation (thy, discrete, inj_consts) end;
   419 end;
       
   420 
   430 
   421 fun domain_is_nat (_ $ (Const (_, T) $ _ $ _))                      = nT T
   431 fun domain_is_nat (_ $ (Const (_, T) $ _ $ _))                      = nT T
   422   | domain_is_nat (_ $ (Const ("Not", _) $ (Const (_, T) $ _ $ _))) = nT T
   432   | domain_is_nat (_ $ (Const ("Not", _) $ (Const (_, T) $ _ $ _))) = nT T
   423   | domain_is_nat _                                                 = false;
   433   | domain_is_nat _                                                 = false;
   424 
   434 
   425 fun number_of (n, T) = HOLogic.mk_number T n;
   435 fun number_of (n, T) = HOLogic.mk_number T n;
   426 
       
   427 (*---------------------------------------------------------------------------*)
       
   428 (* code that performs certain goal transformations for linear arithmetic     *)
       
   429 (*---------------------------------------------------------------------------*)
       
   430 
       
   431 (* A "do nothing" variant of pre_decomp and pre_tac:
       
   432 
       
   433 fun pre_decomp sg Ts termitems = [termitems];
       
   434 fun pre_tac i = all_tac;
       
   435 *)
       
   436 
   436 
   437 (*---------------------------------------------------------------------------*)
   437 (*---------------------------------------------------------------------------*)
   438 (* the following code performs splitting of certain constants (e.g. min,     *)
   438 (* the following code performs splitting of certain constants (e.g. min,     *)
   439 (* max) in a linear arithmetic problem; similar to what split_tac later does *)
   439 (* max) in a linear arithmetic problem; similar to what split_tac later does *)
   440 (* to the proof state                                                        *)
   440 (* to the proof state                                                        *)
   441 (*---------------------------------------------------------------------------*)
   441 (*---------------------------------------------------------------------------*)
   442 
       
   443 val fast_arith_split_limit = ref 9;
       
   444 
   442 
   445 (* checks if splitting with 'thm' is implemented                             *)
   443 (* checks if splitting with 'thm' is implemented                             *)
   446 
   444 
   447 fun is_split_thm (thm : thm) : bool =
   445 fun is_split_thm (thm : thm) : bool =
   448   case concl_of thm of _ $ (_ $ (_ $ lhs) $ _) => (
   446   case concl_of thm of _ $ (_ $ (_ $ lhs) $ _) => (
   491 (*        Or even better, the splitter should be extended to provide         *)
   489 (*        Or even better, the splitter should be extended to provide         *)
   492 (*        splitting on terms as well as splitting on theorems (where the     *)
   490 (*        splitting on terms as well as splitting on theorems (where the     *)
   493 (*        former can have a faster implementation as it does not need to be  *)
   491 (*        former can have a faster implementation as it does not need to be  *)
   494 (*        proof-producing).                                                  *)
   492 (*        proof-producing).                                                  *)
   495 
   493 
   496 fun split_once_items (sg : theory) (Ts : typ list, terms : term list) :
   494 fun split_once_items ctxt (Ts : typ list, terms : term list) :
   497                      (typ list * term list) list option =
   495                      (typ list * term list) list option =
   498 let
   496 let
       
   497   val thy = ProofContext.theory_of ctxt
   499   (* takes a list  [t1, ..., tn]  to the term                                *)
   498   (* takes a list  [t1, ..., tn]  to the term                                *)
   500   (*   tn' --> ... --> t1' --> False  ,                                      *)
   499   (*   tn' --> ... --> t1' --> False  ,                                      *)
   501   (* where ti' = HOLogic.dest_Trueprop ti                                    *)
   500   (* where ti' = HOLogic.dest_Trueprop ti                                    *)
   502   (* term list -> term *)
       
   503   fun REPEAT_DETERM_etac_rev_mp terms' =
   501   fun REPEAT_DETERM_etac_rev_mp terms' =
   504     fold (curry HOLogic.mk_imp) (map HOLogic.dest_Trueprop terms') HOLogic.false_const
   502     fold (curry HOLogic.mk_imp) (map HOLogic.dest_Trueprop terms') HOLogic.false_const
   505   val split_thms = filter is_split_thm (#splits (ArithTheoryData.get sg))
   503   val split_thms = filter is_split_thm (#splits (get_arith_data ctxt))
   506   val cmap       = Splitter.cmap_of_split_thms split_thms
   504   val cmap       = Splitter.cmap_of_split_thms split_thms
   507   val splits     = Splitter.split_posns cmap sg Ts (REPEAT_DETERM_etac_rev_mp terms)
   505   val splits     = Splitter.split_posns cmap thy Ts (REPEAT_DETERM_etac_rev_mp terms)
       
   506   val split_limit = ConfigOption.get ctxt fast_arith_split_limit
   508 in
   507 in
   509   if length splits > !fast_arith_split_limit then (
   508   if length splits > split_limit then
   510     tracing ("fast_arith_split_limit exceeded (current value is " ^
   509    (tracing ("fast_arith_split_limit exceeded (current value is " ^
   511               string_of_int (!fast_arith_split_limit) ^ ")");
   510       string_of_int split_limit ^ ")"); NONE)
   512     NONE
   511   else (
   513   ) else (
       
   514   case splits of [] =>
   512   case splits of [] =>
   515     (* split_tac would fail: no possible split *)
   513     (* split_tac would fail: no possible split *)
   516     NONE
   514     NONE
   517   | ((_, _, _, split_type, split_term) :: _) => (
   515   | ((_, _, _, split_type, split_term) :: _) => (
   518     (* ignore all but the first possible split *)
   516     (* ignore all but the first possible split *)
   782     (* this will only happen if a split theorem can be applied for which no  *)
   780     (* this will only happen if a split theorem can be applied for which no  *)
   783     (* code exists above -- in which case either the split theorem should be *)
   781     (* code exists above -- in which case either the split theorem should be *)
   784     (* implemented above, or 'is_split_thm' should be modified to filter it  *)
   782     (* implemented above, or 'is_split_thm' should be modified to filter it  *)
   785     (* out                                                                   *)
   783     (* out                                                                   *)
   786     | (t, ts) => (
   784     | (t, ts) => (
   787       warning ("Lin. Arith.: split rule for " ^ Sign.string_of_term sg t ^
   785       warning ("Lin. Arith.: split rule for " ^ ProofContext.string_of_term ctxt t ^
   788                " (with " ^ Int.toString (length ts) ^
   786                " (with " ^ string_of_int (length ts) ^
   789                " argument(s)) not implemented; proof reconstruction is likely to fail");
   787                " argument(s)) not implemented; proof reconstruction is likely to fail");
   790       NONE
   788       NONE
   791     ))
   789     ))
   792   )
   790   )
   793 end;
   791 end;
   811   List.exists
   809   List.exists
   812     (fn (Trueprop $ (Const ("Not", _) $ t)) => member (op aconv) terms (Trueprop $ t)
   810     (fn (Trueprop $ (Const ("Not", _) $ t)) => member (op aconv) terms (Trueprop $ t)
   813       | _                                   => false)
   811       | _                                   => false)
   814     terms;
   812     terms;
   815 
   813 
   816 fun pre_decomp sg (Ts : typ list, terms : term list) : (typ list * term list) list =
   814 fun pre_decomp ctxt (Ts : typ list, terms : term list) : (typ list * term list) list =
   817 let
   815 let
   818   (* repeatedly split (including newly emerging subgoals) until no further   *)
   816   (* repeatedly split (including newly emerging subgoals) until no further   *)
   819   (* splitting is possible                                                   *)
   817   (* splitting is possible                                                   *)
   820   fun split_loop ([] : (typ list * term list) list) = ([] : (typ list * term list) list)
   818   fun split_loop ([] : (typ list * term list) list) = ([] : (typ list * term list) list)
   821     | split_loop (subgoal::subgoals)                = (
   819     | split_loop (subgoal::subgoals)                = (
   822         case split_once_items sg subgoal of
   820         case split_once_items ctxt subgoal of
   823           SOME new_subgoals => split_loop (new_subgoals @ subgoals)
   821           SOME new_subgoals => split_loop (new_subgoals @ subgoals)
   824         | NONE              => subgoal :: split_loop subgoals
   822         | NONE              => subgoal :: split_loop subgoals
   825       )
   823       )
   826   fun is_relevant t  = isSome (decomp sg t)
   824   fun is_relevant t  = isSome (decomp ctxt t)
   827   (* filter_prems_tac is_relevant: *)
   825   (* filter_prems_tac is_relevant: *)
   828   val relevant_terms = filter_prems_tac_items is_relevant terms
   826   val relevant_terms = filter_prems_tac_items is_relevant terms
   829   (* split_tac, NNF normalization: *)
   827   (* split_tac, NNF normalization: *)
   830   val split_goals    = split_loop [(Ts, relevant_terms)]
   828   val split_goals    = split_loop [(Ts, relevant_terms)]
   831   (* necessary because split_once_tac may normalize terms: *)
   829   (* necessary because split_once_tac may normalize terms: *)
   853       not_all, not_ex, not_not]
   851       not_all, not_ex, not_not]
   854   fun prem_nnf_tac i st =
   852   fun prem_nnf_tac i st =
   855     full_simp_tac (Simplifier.theory_context (Thm.theory_of_thm st) nnf_simpset) i st
   853     full_simp_tac (Simplifier.theory_context (Thm.theory_of_thm st) nnf_simpset) i st
   856 in
   854 in
   857 
   855 
   858 fun split_once_tac (split_thms : thm list) (i : int) : tactic =
   856 fun split_once_tac ctxt split_thms =
   859 let
   857   let
   860   fun cond_split_tac i st =
   858     val thy = ProofContext.theory_of ctxt
   861     let
   859     val cond_split_tac = SUBGOAL (fn (subgoal, i) =>
   862       val subgoal = Logic.nth_prem (i, Thm.prop_of st)
   860       let
   863       val Ts      = rev (map snd (Logic.strip_params subgoal))
   861         val Ts = rev (map snd (Logic.strip_params subgoal))
   864       val concl   = HOLogic.dest_Trueprop (Logic.strip_assums_concl subgoal)
   862         val concl = HOLogic.dest_Trueprop (Logic.strip_assums_concl subgoal)
   865       val cmap    = Splitter.cmap_of_split_thms split_thms
   863         val cmap = Splitter.cmap_of_split_thms split_thms
   866       val splits  = Splitter.split_posns cmap (theory_of_thm st) Ts concl
   864         val splits = Splitter.split_posns cmap thy Ts concl
   867     in
   865         val split_limit = ConfigOption.get ctxt fast_arith_split_limit
   868       if length splits > !fast_arith_split_limit then
   866       in
   869         no_tac st
   867         if length splits > split_limit then no_tac
   870       else
   868         else split_tac split_thms i
   871         split_tac split_thms i st
   869       end)
   872     end
   870   in
   873 in
   871     EVERY' [
   874   EVERY' [
   872       REPEAT_DETERM o etac rev_mp,
   875     REPEAT_DETERM o etac rev_mp,
   873       cond_split_tac,
   876     cond_split_tac,
   874       rtac ccontr,
   877     rtac ccontr,
   875       prem_nnf_tac,
   878     prem_nnf_tac,
   876       TRY o REPEAT_ALL_NEW (DETERM o (eresolve_tac [conjE, exE] ORELSE' etac disjE))
   879     TRY o REPEAT_ALL_NEW (DETERM o (eresolve_tac [conjE, exE] ORELSE' etac disjE))
   877     ]
   880   ] i
   878   end;
   881 end
       
   882 
   879 
   883 end;  (* local *)
   880 end;  (* local *)
   884 
   881 
   885 (* remove irrelevant premises, then split the i-th subgoal (and all new      *)
   882 (* remove irrelevant premises, then split the i-th subgoal (and all new      *)
   886 (* subgoals) by using 'split_once_tac' repeatedly.  Beta-eta-normalize new   *)
   883 (* subgoals) by using 'split_once_tac' repeatedly.  Beta-eta-normalize new   *)
   887 (* subgoals and finally attempt to solve them by finding an immediate        *)
   884 (* subgoals and finally attempt to solve them by finding an immediate        *)
   888 (* contradiction (i.e. a term and its negation) in their premises.           *)
   885 (* contradiction (i.e. a term and its negation) in their premises.           *)
   889 
   886 
   890 fun pre_tac i st =
   887 fun pre_tac ctxt i =
   891 let
   888 let
   892   val sg            = theory_of_thm st
   889   val split_thms = filter is_split_thm (#splits (get_arith_data ctxt))
   893   val split_thms    = filter is_split_thm (#splits (ArithTheoryData.get sg))
   890   fun is_relevant t = isSome (decomp ctxt t)
   894   fun is_relevant t = isSome (decomp sg t)
       
   895 in
   891 in
   896   DETERM (
   892   DETERM (
   897     TRY (filter_prems_tac is_relevant i)
   893     TRY (filter_prems_tac is_relevant i)
   898       THEN (
   894       THEN (
   899         (TRY o REPEAT_ALL_NEW (split_once_tac split_thms))
   895         (TRY o REPEAT_ALL_NEW (split_once_tac ctxt split_thms))
   900           THEN_ALL_NEW
   896           THEN_ALL_NEW
   901             (CONVERSION Drule.beta_eta_conversion
   897             (CONVERSION Drule.beta_eta_conversion
   902               THEN'
   898               THEN'
   903             (TRY o (etac notE THEN' eq_assume_tac)))
   899             (TRY o (etac notE THEN' eq_assume_tac)))
   904       ) i
   900       ) i
   905   ) st
   901   )
   906 end;
   902 end;
   907 
   903 
   908 end;  (* LA_Data_Ref *)
   904 end;  (* LA_Data_Ref *)
   909 
   905 
   910 
   906 
   911 structure Fast_Arith =
   907 structure Fast_Arith =
   912   Fast_Lin_Arith(structure LA_Logic=LA_Logic and LA_Data=LA_Data_Ref);
   908   Fast_Lin_Arith(structure LA_Logic=LA_Logic and LA_Data=LA_Data_Ref);
   913 
   909 
   914 val fast_arith_tac         = Fast_Arith.lin_arith_tac false;
   910 fun fast_arith_tac ctxt    = Fast_Arith.lin_arith_tac ctxt false;
   915 val fast_ex_arith_tac      = Fast_Arith.lin_arith_tac;
   911 val fast_ex_arith_tac      = Fast_Arith.lin_arith_tac;
   916 val trace_arith            = Fast_Arith.trace;
   912 val trace_arith            = Fast_Arith.trace;
   917 val fast_arith_neq_limit   = Fast_Arith.fast_arith_neq_limit;
       
   918 val fast_arith_split_limit = LA_Data_Ref.fast_arith_split_limit;
       
   919 
   913 
   920 (* reduce contradictory <= to False.
   914 (* reduce contradictory <= to False.
   921    Most of the work is done by the cancel tactics. *)
   915    Most of the work is done by the cancel tactics. *)
   922 
   916 
   923 val init_lin_arith_data =
   917 val init_arith_data =
   924  Fast_Arith.map_data (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, ...} =>
   918  Fast_Arith.map_data (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, ...} =>
   925    {add_mono_thms = add_mono_thms @
   919    {add_mono_thms = add_mono_thms @
   926     @{thms add_mono_thms_ordered_semiring} @ @{thms add_mono_thms_ordered_field},
   920     @{thms add_mono_thms_ordered_semiring} @ @{thms add_mono_thms_ordered_field},
   927     mult_mono_thms = mult_mono_thms,
   921     mult_mono_thms = mult_mono_thms,
   928     inj_thms = inj_thms,
   922     inj_thms = inj_thms,
   929     lessD = lessD @ [thm "Suc_leI"],
   923     lessD = lessD @ [thm "Suc_leI"],
   930     neqE = [@{thm linorder_neqE_nat}, @{thm linorder_neqE_ordered_idom}],
   924     neqE = [@{thm linorder_neqE_nat}, @{thm linorder_neqE_ordered_idom}],
   931     simpset = HOL_basic_ss
   925     simpset = HOL_basic_ss
   932       addsimps [@{thm "monoid_add_class.zero_plus.add_0_left"}, @{thm "monoid_add_class.zero_plus.add_0_right"},
   926       addsimps
       
   927        [@{thm "monoid_add_class.zero_plus.add_0_left"},
       
   928         @{thm "monoid_add_class.zero_plus.add_0_right"},
   933         @{thm "Zero_not_Suc"}, @{thm "Suc_not_Zero"}, @{thm "le_0_eq"}, @{thm "One_nat_def"},
   929         @{thm "Zero_not_Suc"}, @{thm "Suc_not_Zero"}, @{thm "le_0_eq"}, @{thm "One_nat_def"},
   934         @{thm "order_less_irrefl"}, @{thm "zero_neq_one"}, @{thm "zero_less_one"},
   930         @{thm "order_less_irrefl"}, @{thm "zero_neq_one"}, @{thm "zero_less_one"},
   935         @{thm "zero_le_one"}, @{thm "zero_neq_one"} RS not_sym, @{thm "not_one_le_zero"},
   931         @{thm "zero_le_one"}, @{thm "zero_neq_one"} RS not_sym, @{thm "not_one_le_zero"},
   936         @{thm "not_one_less_zero"}]
   932         @{thm "not_one_less_zero"}]
   937       addsimprocs [ab_group_add_cancel.sum_conv, ab_group_add_cancel.rel_conv]
   933       addsimprocs [ab_group_add_cancel.sum_conv, ab_group_add_cancel.rel_conv]
   939       addsimprocs nat_cancel_sums_add}) #>
   935       addsimprocs nat_cancel_sums_add}) #>
   940   arith_discrete "nat";
   936   arith_discrete "nat";
   941 
   937 
   942 val fast_nat_arith_simproc =
   938 val fast_nat_arith_simproc =
   943   Simplifier.simproc (the_context ()) "fast_nat_arith"
   939   Simplifier.simproc (the_context ()) "fast_nat_arith"
   944     ["(m::nat) < n","(m::nat) <= n", "(m::nat) = n"] Fast_Arith.lin_arith_prover;
   940     ["(m::nat) < n","(m::nat) <= n", "(m::nat) = n"] (K Fast_Arith.lin_arith_simproc);
   945 
   941 
   946 (* Because of fast_nat_arith_simproc, the arithmetic solver is really only
   942 (* Because of fast_nat_arith_simproc, the arithmetic solver is really only
   947 useful to detect inconsistencies among the premises for subgoals which are
   943 useful to detect inconsistencies among the premises for subgoals which are
   948 *not* themselves (in)equalities, because the latter activate
   944 *not* themselves (in)equalities, because the latter activate
   949 fast_nat_arith_simproc anyway. However, it seems cheaper to activate the
   945 fast_nat_arith_simproc anyway. However, it seems cheaper to activate the
   952 
   948 
   953 (* arith proof method *)
   949 (* arith proof method *)
   954 
   950 
   955 local
   951 local
   956 
   952 
   957 fun raw_arith_tac ex i st =
   953 fun raw_arith_tac ctxt ex =
   958   (* FIXME: K true should be replaced by a sensible test (perhaps "isSome o
   954   (* FIXME: K true should be replaced by a sensible test (perhaps "isSome o
   959      decomp sg"? -- but note that the test is applied to terms already before
   955      decomp sg"? -- but note that the test is applied to terms already before
   960      they are split/normalized) to speed things up in case there are lots of
   956      they are split/normalized) to speed things up in case there are lots of
   961      irrelevant terms involved; elimination of min/max can be optimized:
   957      irrelevant terms involved; elimination of min/max can be optimized:
   962      (max m n + k <= r) = (m+k <= r & n+k <= r)
   958      (max m n + k <= r) = (m+k <= r & n+k <= r)
   967     (* split_tac may use split theorems that have not been implemented in    *)
   963     (* split_tac may use split theorems that have not been implemented in    *)
   968     (* fast_arith_tac (cf. pre_decomp and split_once_items above), and       *)
   964     (* fast_arith_tac (cf. pre_decomp and split_once_items above), and       *)
   969     (* fast_arith_split_limit may trigger.                                   *)
   965     (* fast_arith_split_limit may trigger.                                   *)
   970     (* Therefore splitting outside of fast_arith_tac may allow us to prove   *)
   966     (* Therefore splitting outside of fast_arith_tac may allow us to prove   *)
   971     (* some goals that fast_arith_tac alone would fail on.                   *)
   967     (* some goals that fast_arith_tac alone would fail on.                   *)
   972     (REPEAT_DETERM o split_tac (#splits (ArithTheoryData.get (Thm.theory_of_thm st))))
   968     (REPEAT_DETERM o split_tac (#splits (get_arith_data ctxt)))
   973     (fast_ex_arith_tac ex)
   969     (fast_ex_arith_tac ctxt ex);
   974     i st;
   970 
   975 
   971 fun more_arith_tacs ctxt =
   976 fun arith_theory_tac i st =
   972   let val tactics = #tactics (get_arith_data ctxt)
   977 let
   973   in FIRST' (map (fn ArithTactic {tactic, ...} => tactic) tactics) end;
   978   val tactics = #tactics (ArithTheoryData.get (Thm.theory_of_thm st))
   974 
   979 in
   975 in
   980   FIRST' (map (fn ArithTactic {tactic, ...} => tactic) tactics) i st
   976 
   981 end;
   977 fun simple_arith_tac ctxt = FIRST' [fast_arith_tac ctxt,
   982 
   978   ObjectLogic.full_atomize_tac THEN' (REPEAT_DETERM o rtac impI) THEN' raw_arith_tac ctxt true];
   983 in
   979 
   984 
   980 fun arith_tac ctxt = FIRST' [fast_arith_tac ctxt,
   985   val simple_arith_tac = FIRST' [fast_arith_tac,
   981   ObjectLogic.full_atomize_tac THEN' (REPEAT_DETERM o rtac impI) THEN' raw_arith_tac ctxt true,
   986     ObjectLogic.full_atomize_tac THEN' (REPEAT_DETERM o rtac impI) THEN' raw_arith_tac true];
   982   more_arith_tacs ctxt];
   987 
   983 
   988   val arith_tac = FIRST' [fast_arith_tac,
   984 fun silent_arith_tac ctxt = FIRST' [fast_arith_tac ctxt,
   989     ObjectLogic.full_atomize_tac THEN' (REPEAT_DETERM o rtac impI) THEN' raw_arith_tac true,
   985   ObjectLogic.full_atomize_tac THEN' (REPEAT_DETERM o rtac impI) THEN' raw_arith_tac ctxt false,
   990     arith_theory_tac];
   986   more_arith_tacs ctxt];
   991 
   987 
   992   val silent_arith_tac = FIRST' [fast_arith_tac,
   988 fun arith_method src =
   993     ObjectLogic.full_atomize_tac THEN' (REPEAT_DETERM o rtac impI) THEN' raw_arith_tac false,
   989   Method.syntax Args.bang_facts src
   994     arith_theory_tac];
   990   #> (fn (prems, ctxt) => Method.METHOD (fn facts =>
   995 
   991       HEADGOAL (Method.insert_tac (prems @ facts) THEN' arith_tac ctxt)));
   996   fun arith_method prems =
       
   997     Method.METHOD (fn facts => HEADGOAL (Method.insert_tac (prems @ facts) THEN' arith_tac));
       
   998 
   992 
   999 end;
   993 end;
  1000 
   994 
  1001 (* antisymmetry:
   995 (* antisymmetry:
  1002    combines x <= y (or ~(y < x)) and y <= x (or ~(x < y)) into x = y
   996    combines x <= y (or ~(y < x)) and y <= x (or ~(x < y)) into x = y
  1043 *)
  1037 *)
  1044 
  1038 
  1045 (* theory setup *)
  1039 (* theory setup *)
  1046 
  1040 
  1047 val arith_setup =
  1041 val arith_setup =
  1048   init_lin_arith_data #>
  1042   init_arith_data #>
  1049   (fn thy => (Simplifier.change_simpset_of thy (fn ss => ss
  1043   Simplifier.map_ss (fn ss => ss
  1050     addsimprocs (nat_cancel_sums @ [fast_nat_arith_simproc])
  1044     addsimprocs (nat_cancel_sums @ [fast_nat_arith_simproc])
  1051     addSolver (mk_solver' "lin. arith." Fast_Arith.cut_lin_arith_tac)); thy)) #>
  1045     addSolver (mk_solver' "lin. arith." Fast_Arith.cut_lin_arith_tac)) #>
  1052   Method.add_methods
  1046   Context.mapping
  1053     [("arith", (arith_method o fst) oo Method.syntax Args.bang_facts,
  1047    (LA_Data_Ref.setup_options #>
  1054       "decide linear arithmethic")] #>
  1048     Method.add_methods
  1055   Attrib.add_attributes [("arith_split", Attrib.no_args arith_split_add,
  1049       [("arith", arith_method,
  1056     "declaration of split rules for arithmetic procedure")];
  1050         "decide linear arithmethic")] #>
       
  1051     Attrib.add_attributes [("arith_split", Attrib.no_args arith_split_add,
       
  1052       "declaration of split rules for arithmetic procedure")]) I;