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 *) |
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] |
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 |