src/Provers/Arith/fast_lin_arith.ML
changeset 51717 9e7d1c139569
parent 49387 167708456269
child 51930 52fd62618631
equal deleted inserted replaced
51709:19b47bfac6ef 51717:9e7d1c139569
    51 
    51 
    52   (*preprocessing, performed on a representation of subgoals as list of premises:*)
    52   (*preprocessing, performed on a representation of subgoals as list of premises:*)
    53   val pre_decomp: Proof.context -> typ list * term list -> (typ list * term list) list
    53   val pre_decomp: Proof.context -> typ list * term list -> (typ list * term list) list
    54 
    54 
    55   (*preprocessing, performed on the goal -- must do the same as 'pre_decomp':*)
    55   (*preprocessing, performed on the goal -- must do the same as 'pre_decomp':*)
    56   val pre_tac: simpset -> int -> tactic
    56   val pre_tac: Proof.context -> int -> tactic
    57 
    57 
    58   (*the limit on the number of ~= allowed; because each ~= is split
    58   (*the limit on the number of ~= allowed; because each ~= is split
    59     into two cases, this can lead to an explosion*)
    59     into two cases, this can lead to an explosion*)
    60   val neq_limit: int Config.T
    60   val neq_limit: int Config.T
    61 
    61 
    77 be modified by pre_decomp (pre_tac, resp.) in a corresponding way.  See
    77 be modified by pre_decomp (pre_tac, resp.) in a corresponding way.  See
    78 the comment for split_items below.  (This is even necessary for eta- and
    78 the comment for split_items below.  (This is even necessary for eta- and
    79 beta-equivalent modifications, as some of the lin. arith. code is not
    79 beta-equivalent modifications, as some of the lin. arith. code is not
    80 insensitive to them.)
    80 insensitive to them.)
    81 
    81 
    82 ss must reduce contradictory <= to False.
    82 Simpset must reduce contradictory <= to False.
    83    It should also cancel common summands to keep <= reduced;
    83    It should also cancel common summands to keep <= reduced;
    84    otherwise <= can grow to massive proportions.
    84    otherwise <= can grow to massive proportions.
    85 *)
    85 *)
    86 
    86 
    87 signature FAST_LIN_ARITH =
    87 signature FAST_LIN_ARITH =
    88 sig
    88 sig
    89   val prems_lin_arith_tac: simpset -> int -> tactic
    89   val prems_lin_arith_tac: Proof.context -> int -> tactic
    90   val lin_arith_tac: Proof.context -> bool -> int -> tactic
    90   val lin_arith_tac: Proof.context -> bool -> int -> tactic
    91   val lin_arith_simproc: simpset -> term -> thm option
    91   val lin_arith_simproc: Proof.context -> term -> thm option
    92   val map_data:
    92   val map_data:
    93     ({add_mono_thms: thm list, mult_mono_thms: thm list, inj_thms: thm list,
    93     ({add_mono_thms: thm list, mult_mono_thms: thm list, inj_thms: thm list,
    94       lessD: thm list, neqE: thm list, simpset: Simplifier.simpset,
    94       lessD: thm list, neqE: thm list, simpset: simpset,
    95       number_of: (theory -> typ -> int -> cterm) option} ->
    95       number_of: (theory -> typ -> int -> cterm) option} ->
    96      {add_mono_thms: thm list, mult_mono_thms: thm list, inj_thms: thm list,
    96      {add_mono_thms: thm list, mult_mono_thms: thm list, inj_thms: thm list,
    97       lessD: thm list, neqE: thm list, simpset: Simplifier.simpset,
    97       lessD: thm list, neqE: thm list, simpset: simpset,
    98       number_of: (theory -> typ -> int -> cterm) option}) ->
    98       number_of: (theory -> typ -> int -> cterm) option}) ->
    99       Context.generic -> Context.generic
    99       Context.generic -> Context.generic
   100   val add_inj_thms: thm list -> Context.generic -> Context.generic
   100   val add_inj_thms: thm list -> Context.generic -> Context.generic
   101   val add_lessD: thm -> Context.generic -> Context.generic
   101   val add_lessD: thm -> Context.generic -> Context.generic
   102   val add_simps: thm list -> Context.generic -> Context.generic
   102   val add_simps: thm list -> Context.generic -> Context.generic
   117    {add_mono_thms: thm list,
   117    {add_mono_thms: thm list,
   118     mult_mono_thms: thm list,
   118     mult_mono_thms: thm list,
   119     inj_thms: thm list,
   119     inj_thms: thm list,
   120     lessD: thm list,
   120     lessD: thm list,
   121     neqE: thm list,
   121     neqE: thm list,
   122     simpset: Simplifier.simpset,
   122     simpset: simpset,
   123     number_of: (theory -> typ -> int -> cterm) option};
   123     number_of: (theory -> typ -> int -> cterm) option};
   124 
   124 
   125   val empty : T =
   125   val empty : T =
   126    {add_mono_thms = [], mult_mono_thms = [], inj_thms = [],
   126    {add_mono_thms = [], mult_mono_thms = [], inj_thms = [],
   127     lessD = [], neqE = [], simpset = Simplifier.empty_ss,
   127     lessD = [], neqE = [], simpset = empty_ss,
   128     number_of = NONE};
   128     number_of = NONE};
   129   val extend = I;
   129   val extend = I;
   130   fun merge
   130   fun merge
   131     ({add_mono_thms = add_mono_thms1, mult_mono_thms = mult_mono_thms1, inj_thms = inj_thms1,
   131     ({add_mono_thms = add_mono_thms1, mult_mono_thms = mult_mono_thms1, inj_thms = inj_thms1,
   132       lessD = lessD1, neqE = neqE1, simpset = simpset1, number_of = number_of1},
   132       lessD = lessD1, neqE = neqE1, simpset = simpset1, number_of = number_of1},
   135     {add_mono_thms = Thm.merge_thms (add_mono_thms1, add_mono_thms2),
   135     {add_mono_thms = Thm.merge_thms (add_mono_thms1, add_mono_thms2),
   136      mult_mono_thms = Thm.merge_thms (mult_mono_thms1, mult_mono_thms2),
   136      mult_mono_thms = Thm.merge_thms (mult_mono_thms1, mult_mono_thms2),
   137      inj_thms = Thm.merge_thms (inj_thms1, inj_thms2),
   137      inj_thms = Thm.merge_thms (inj_thms1, inj_thms2),
   138      lessD = Thm.merge_thms (lessD1, lessD2),
   138      lessD = Thm.merge_thms (lessD1, lessD2),
   139      neqE = Thm.merge_thms (neqE1, neqE2),
   139      neqE = Thm.merge_thms (neqE1, neqE2),
   140      simpset = Simplifier.merge_ss (simpset1, simpset2),
   140      simpset = merge_ss (simpset1, simpset2),
   141      number_of = merge_options (number_of1, number_of2)};
   141      number_of = merge_options (number_of1, number_of2)};
   142 );
   142 );
   143 
   143 
   144 val map_data = Data.map;
   144 val map_data = Data.map;
   145 val get_data = Data.get o Context.Proof;
   145 val get_data = Data.get o Context.Proof;
   150 
   150 
   151 fun map_lessD f {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset, number_of} =
   151 fun map_lessD f {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset, number_of} =
   152   {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms, inj_thms = inj_thms,
   152   {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms, inj_thms = inj_thms,
   153     lessD = f lessD, neqE = neqE, simpset = simpset, number_of = number_of};
   153     lessD = f lessD, neqE = neqE, simpset = simpset, number_of = number_of};
   154 
   154 
   155 fun map_simpset f {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset, number_of} =
   155 fun map_simpset f context =
   156   {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms, inj_thms = inj_thms,
   156   map_data (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset, number_of} =>
   157     lessD = lessD, neqE = neqE, simpset = f simpset, number_of = number_of};
   157     {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms, inj_thms = inj_thms,
       
   158       lessD = lessD, neqE = neqE, simpset = simpset_map (Context.proof_of context) f simpset,
       
   159       number_of = number_of}) context;
   158 
   160 
   159 fun add_inj_thms thms = map_data (map_inj_thms (append thms));
   161 fun add_inj_thms thms = map_data (map_inj_thms (append thms));
   160 fun add_lessD thm = map_data (map_lessD (fn thms => thms @ [thm]));
   162 fun add_lessD thm = map_data (map_lessD (fn thms => thms @ [thm]));
   161 fun add_simps thms = map_data (map_simpset (fn simpset => simpset addsimps thms));
   163 fun add_simps thms = map_simpset (fn ctxt => ctxt addsimps thms);
   162 fun add_simprocs procs = map_data (map_simpset (fn simpset => simpset addsimprocs procs));
   164 fun add_simprocs procs = map_simpset (fn ctxt => ctxt addsimprocs procs);
   163 
   165 
   164 fun set_number_of f =
   166 fun set_number_of f =
   165   map_data (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset, ...} =>
   167   map_data (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset, ...} =>
   166    {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms, inj_thms = inj_thms,
   168    {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms, inj_thms = inj_thms,
   167     lessD = lessD, neqE = neqE, simpset = simpset, number_of = SOME f});
   169     lessD = lessD, neqE = neqE, simpset = simpset, number_of = SOME f});
   471 *)
   473 *)
   472 local
   474 local
   473   exception FalseE of thm
   475   exception FalseE of thm
   474 in
   476 in
   475 
   477 
   476 fun mkthm ss asms (just: injust) =
   478 fun mkthm ctxt asms (just: injust) =
   477   let
   479   let
   478     val ctxt = Simplifier.the_context ss;
       
   479     val thy = Proof_Context.theory_of ctxt;
   480     val thy = Proof_Context.theory_of ctxt;
   480     val {add_mono_thms, mult_mono_thms, inj_thms, lessD, simpset, ...} = get_data ctxt;
   481     val {add_mono_thms, mult_mono_thms, inj_thms, lessD, simpset, ...} = get_data ctxt;
   481     val number_of = number_of ctxt;
   482     val number_of = number_of ctxt;
   482     val simpset' = Simplifier.inherit_context ss simpset;
   483     val simpset_ctxt = put_simpset simpset ctxt;
   483     fun only_concl f thm =
   484     fun only_concl f thm =
   484       if Thm.no_prems thm then f (Thm.concl_of thm) else NONE;
   485       if Thm.no_prems thm then f (Thm.concl_of thm) else NONE;
   485     val atoms = atoms_of (map_filter (only_concl (LA_Data.decomp ctxt)) asms);
   486     val atoms = atoms_of (map_filter (only_concl (LA_Data.decomp ctxt)) asms);
   486 
   487 
   487     fun use_first rules thm =
   488     fun use_first rules thm =
   505 
   506 
   506     fun mult_by_add n thm =
   507     fun mult_by_add n thm =
   507       let fun mul i th = if i = 1 then th else mul (i - 1) (add_thms thm th)
   508       let fun mul i th = if i = 1 then th else mul (i - 1) (add_thms thm th)
   508       in mul n thm end;
   509       in mul n thm end;
   509 
   510 
   510     val rewr = Simplifier.rewrite simpset';
   511     val rewr = Simplifier.rewrite simpset_ctxt;
   511     val rewrite_concl = Conv.fconv_rule (Conv.concl_conv ~1 (Conv.arg_conv
   512     val rewrite_concl = Conv.fconv_rule (Conv.concl_conv ~1 (Conv.arg_conv
   512       (Conv.binop_conv rewr)));
   513       (Conv.binop_conv rewr)));
   513     fun discharge_prem thm = if Thm.nprems_of thm = 0 then thm else
   514     fun discharge_prem thm = if Thm.nprems_of thm = 0 then thm else
   514       let val cv = Conv.arg1_conv (Conv.arg_conv rewr)
   515       let val cv = Conv.arg1_conv (Conv.arg_conv rewr)
   515       in Thm.implies_elim (Conv.fconv_rule cv thm) LA_Logic.trueI end
   516       in Thm.implies_elim (Conv.fconv_rule cv thm) LA_Logic.trueI end
   535       if n = ~1 then thm RS LA_Logic.sym
   536       if n = ~1 then thm RS LA_Logic.sym
   536       else if n < 0 then mult (~n) thm RS LA_Logic.sym
   537       else if n < 0 then mult (~n) thm RS LA_Logic.sym
   537       else mult n thm;
   538       else mult n thm;
   538 
   539 
   539     fun simp thm =
   540     fun simp thm =
   540       let val thm' = trace_thm ctxt ["Simplified:"] (full_simplify simpset' thm)
   541       let val thm' = trace_thm ctxt ["Simplified:"] (full_simplify simpset_ctxt thm)
   541       in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end;
   542       in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end;
   542 
   543 
   543     fun mk (Asm i) = trace_thm ctxt ["Asm " ^ string_of_int i] (nth asms i)
   544     fun mk (Asm i) = trace_thm ctxt ["Asm " ^ string_of_int i] (nth asms i)
   544       | mk (Nat i) = trace_thm ctxt ["Nat " ^ string_of_int i] (LA_Logic.mk_nat_thm thy (nth atoms i))
   545       | mk (Nat i) = trace_thm ctxt ["Nat " ^ string_of_int i] (LA_Logic.mk_nat_thm thy (nth atoms i))
   545       | mk (LessD j) = trace_thm ctxt ["L"] (hd ([mk j] RL lessD))
   546       | mk (LessD j) = trace_thm ctxt ["L"] (hd ([mk j] RL lessD))
   552 
   553 
   553   in
   554   in
   554     let
   555     let
   555       val _ = trace_msg ctxt "mkthm";
   556       val _ = trace_msg ctxt "mkthm";
   556       val thm = trace_thm ctxt ["Final thm:"] (mk just);
   557       val thm = trace_thm ctxt ["Final thm:"] (mk just);
   557       val fls = simplify simpset' thm;
   558       val fls = simplify simpset_ctxt thm;
   558       val _ = trace_thm ctxt ["After simplification:"] fls;
   559       val _ = trace_thm ctxt ["After simplification:"] fls;
   559       val _ =
   560       val _ =
   560         if LA_Logic.is_False fls then ()
   561         if LA_Logic.is_False fls then ()
   561         else
   562         else
   562          (tracing (cat_lines
   563          (tracing (cat_lines
   797     (* dropping the conclusion doesn't work either, because even        *)
   798     (* dropping the conclusion doesn't work either, because even        *)
   798     (* 'False' does not imply arbitrary 'concl::prop')                  *)
   799     (* 'False' does not imply arbitrary 'concl::prop')                  *)
   799     (trace_msg ctxt "prove failed (cannot negate conclusion).";
   800     (trace_msg ctxt "prove failed (cannot negate conclusion).";
   800       (false, NONE));
   801       (false, NONE));
   801 
   802 
   802 fun refute_tac ss (i, split_neq, justs) =
   803 fun refute_tac ctxt (i, split_neq, justs) =
   803   fn state =>
   804   fn state =>
   804     let
   805     let
   805       val ctxt = Simplifier.the_context ss;
       
   806       val _ = trace_thm ctxt
   806       val _ = trace_thm ctxt
   807         ["refute_tac (on subgoal " ^ string_of_int i ^ ", with " ^
   807         ["refute_tac (on subgoal " ^ string_of_int i ^ ", with " ^
   808           string_of_int (length justs) ^ " justification(s)):"] state
   808           string_of_int (length justs) ^ " justification(s)):"] state
   809       val {neqE, ...} = get_data ctxt;
   809       val {neqE, ...} = get_data ctxt;
   810       fun just1 j =
   810       fun just1 j =
   813           REPEAT_DETERM (eresolve_tac neqE i)
   813           REPEAT_DETERM (eresolve_tac neqE i)
   814         else
   814         else
   815           all_tac) THEN
   815           all_tac) THEN
   816           PRIMITIVE (trace_thm ctxt ["State after neqE:"]) THEN
   816           PRIMITIVE (trace_thm ctxt ["State after neqE:"]) THEN
   817           (* use theorems generated from the actual justifications *)
   817           (* use theorems generated from the actual justifications *)
   818           Subgoal.FOCUS (fn {prems, ...} => rtac (mkthm ss prems j) 1) ctxt i
   818           Subgoal.FOCUS (fn {prems, ...} => rtac (mkthm ctxt prems j) 1) ctxt i
   819     in
   819     in
   820       (* rewrite "[| A1; ...; An |] ==> B" to "[| A1; ...; An; ~B |] ==> False" *)
   820       (* rewrite "[| A1; ...; An |] ==> B" to "[| A1; ...; An; ~B |] ==> False" *)
   821       DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i) THEN
   821       DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i) THEN
   822       (* user-defined preprocessing of the subgoal *)
   822       (* user-defined preprocessing of the subgoal *)
   823       DETERM (LA_Data.pre_tac ss i) THEN
   823       DETERM (LA_Data.pre_tac ctxt i) THEN
   824       PRIMITIVE (trace_thm ctxt ["State after pre_tac:"]) THEN
   824       PRIMITIVE (trace_thm ctxt ["State after pre_tac:"]) THEN
   825       (* prove every resulting subgoal, using its justification *)
   825       (* prove every resulting subgoal, using its justification *)
   826       EVERY (map just1 justs)
   826       EVERY (map just1 justs)
   827     end  state;
   827     end  state;
   828 
   828 
   829 (*
   829 (*
   830 Fast but very incomplete decider. Only premises and conclusions
   830 Fast but very incomplete decider. Only premises and conclusions
   831 that are already (negated) (in)equations are taken into account.
   831 that are already (negated) (in)equations are taken into account.
   832 *)
   832 *)
   833 fun simpset_lin_arith_tac ss show_ex = SUBGOAL (fn (A, i) =>
   833 fun simpset_lin_arith_tac ctxt show_ex = SUBGOAL (fn (A, i) =>
   834   let
   834   let
   835     val ctxt = Simplifier.the_context ss
       
   836     val params = rev (Logic.strip_params A)
   835     val params = rev (Logic.strip_params A)
   837     val Hs = Logic.strip_assums_hyp A
   836     val Hs = Logic.strip_assums_hyp A
   838     val concl = Logic.strip_assums_concl A
   837     val concl = Logic.strip_assums_concl A
   839     val _ = trace_term ctxt ["Trying to refute subgoal " ^ string_of_int i] A
   838     val _ = trace_term ctxt ["Trying to refute subgoal " ^ string_of_int i] A
   840   in
   839   in
   841     case prove ctxt params show_ex true Hs concl of
   840     case prove ctxt params show_ex true Hs concl of
   842       (_, NONE) => (trace_msg ctxt "Refutation failed."; no_tac)
   841       (_, NONE) => (trace_msg ctxt "Refutation failed."; no_tac)
   843     | (split_neq, SOME js) => (trace_msg ctxt "Refutation succeeded.";
   842     | (split_neq, SOME js) => (trace_msg ctxt "Refutation succeeded.";
   844                                refute_tac ss (i, split_neq, js))
   843                                refute_tac ctxt (i, split_neq, js))
   845   end);
   844   end);
   846 
   845 
   847 fun prems_lin_arith_tac ss =
   846 fun prems_lin_arith_tac ctxt =
   848   Method.insert_tac (Simplifier.prems_of ss) THEN'
   847   Method.insert_tac (Simplifier.prems_of ctxt) THEN'
   849   simpset_lin_arith_tac ss false;
   848   simpset_lin_arith_tac ctxt false;
   850 
   849 
   851 fun lin_arith_tac ctxt =
   850 fun lin_arith_tac ctxt =
   852   simpset_lin_arith_tac (Simplifier.context ctxt Simplifier.empty_ss);
   851   simpset_lin_arith_tac (empty_simpset ctxt);
   853 
   852 
   854 
   853 
   855 
   854 
   856 (** Forward proof from theorems **)
   855 (** Forward proof from theorems **)
   857 
   856 
   890             ct2, elim_neq neqs (asms', asms@[thm2]))
   889             ct2, elim_neq neqs (asms', asms@[thm2]))
   891           end
   890           end
   892       | NONE => elim_neq neqs (asm::asms', asms))
   891       | NONE => elim_neq neqs (asm::asms', asms))
   893 in elim_neq neqE ([], asms) end;
   892 in elim_neq neqE ([], asms) end;
   894 
   893 
   895 fun fwdproof ss (Tip asms : splittree) (j::js : injust list) = (mkthm ss asms j, js)
   894 fun fwdproof ctxt (Tip asms : splittree) (j::js : injust list) = (mkthm ctxt asms j, js)
   896   | fwdproof ss (Spl (thm, ct1, tree1, ct2, tree2)) js =
   895   | fwdproof ctxt (Spl (thm, ct1, tree1, ct2, tree2)) js =
   897       let
   896       let
   898         val (thm1, js1) = fwdproof ss tree1 js
   897         val (thm1, js1) = fwdproof ctxt tree1 js
   899         val (thm2, js2) = fwdproof ss tree2 js1
   898         val (thm2, js2) = fwdproof ctxt tree2 js1
   900         val thm1' = Thm.implies_intr ct1 thm1
   899         val thm1' = Thm.implies_intr ct1 thm1
   901         val thm2' = Thm.implies_intr ct2 thm2
   900         val thm2' = Thm.implies_intr ct2 thm2
   902       in (thm2' COMP (thm1' COMP thm), js2) end;
   901       in (thm2' COMP (thm1' COMP thm), js2) end;
   903       (* FIXME needs handle THM _ => NONE ? *)
   902       (* FIXME needs handle THM _ => NONE ? *)
   904 
   903 
   905 fun prover ss thms Tconcl (js : injust list) split_neq pos : thm option =
   904 fun prover ctxt thms Tconcl (js : injust list) split_neq pos : thm option =
   906   let
   905   let
   907     val ctxt = Simplifier.the_context ss
       
   908     val thy = Proof_Context.theory_of ctxt
   906     val thy = Proof_Context.theory_of ctxt
   909     val nTconcl = LA_Logic.neg_prop Tconcl
   907     val nTconcl = LA_Logic.neg_prop Tconcl
   910     val cnTconcl = cterm_of thy nTconcl
   908     val cnTconcl = cterm_of thy nTconcl
   911     val nTconclthm = Thm.assume cnTconcl
   909     val nTconclthm = Thm.assume cnTconcl
   912     val tree = (if split_neq then splitasms ctxt else Tip) (thms @ [nTconclthm])
   910     val tree = (if split_neq then splitasms ctxt else Tip) (thms @ [nTconclthm])
   913     val (Falsethm, _) = fwdproof ss tree js
   911     val (Falsethm, _) = fwdproof ctxt tree js
   914     val contr = if pos then LA_Logic.ccontr else LA_Logic.notI
   912     val contr = if pos then LA_Logic.ccontr else LA_Logic.notI
   915     val concl = Thm.implies_intr cnTconcl Falsethm COMP contr
   913     val concl = Thm.implies_intr cnTconcl Falsethm COMP contr
   916   in SOME (trace_thm ctxt ["Proved by lin. arith. prover:"] (LA_Logic.mk_Eq concl)) end
   914   in SOME (trace_thm ctxt ["Proved by lin. arith. prover:"] (LA_Logic.mk_Eq concl)) end
   917   (*in case concl contains ?-var, which makes assume fail:*)   (* FIXME Variable.import_terms *)
   915   (*in case concl contains ?-var, which makes assume fail:*)   (* FIXME Variable.import_terms *)
   918   handle THM _ => NONE;
   916   handle THM _ => NONE;
   921    This assumption is OK because
   919    This assumption is OK because
   922    1. lin_arith_simproc tries both to prove and disprove concl and
   920    1. lin_arith_simproc tries both to prove and disprove concl and
   923    2. lin_arith_simproc is applied by the Simplifier which
   921    2. lin_arith_simproc is applied by the Simplifier which
   924       dives into terms and will thus try the non-negated concl anyway.
   922       dives into terms and will thus try the non-negated concl anyway.
   925 *)
   923 *)
   926 fun lin_arith_simproc ss concl =
   924 fun lin_arith_simproc ctxt concl =
   927   let
   925   let
   928     val ctxt = Simplifier.the_context ss
   926     val thms = maps LA_Logic.atomize (Simplifier.prems_of ctxt)
   929     val thms = maps LA_Logic.atomize (Simplifier.prems_of ss)
       
   930     val Hs = map Thm.prop_of thms
   927     val Hs = map Thm.prop_of thms
   931     val Tconcl = LA_Logic.mk_Trueprop concl
   928     val Tconcl = LA_Logic.mk_Trueprop concl
   932   in
   929   in
   933     case prove ctxt [] false false Hs Tconcl of (* concl provable? *)
   930     case prove ctxt [] false false Hs Tconcl of (* concl provable? *)
   934       (split_neq, SOME js) => prover ss thms Tconcl js split_neq true
   931       (split_neq, SOME js) => prover ctxt thms Tconcl js split_neq true
   935     | (_, NONE) =>
   932     | (_, NONE) =>
   936         let val nTconcl = LA_Logic.neg_prop Tconcl in
   933         let val nTconcl = LA_Logic.neg_prop Tconcl in
   937           case prove ctxt [] false false Hs nTconcl of (* ~concl provable? *)
   934           case prove ctxt [] false false Hs nTconcl of (* ~concl provable? *)
   938             (split_neq, SOME js) => prover ss thms nTconcl js split_neq false
   935             (split_neq, SOME js) => prover ctxt thms nTconcl js split_neq false
   939           | (_, NONE) => NONE
   936           | (_, NONE) => NONE
   940         end
   937         end
   941   end;
   938   end;
   942 
   939 
   943 end;
   940 end;