src/HOL/Tools/arith_data.ML
author wenzelm
Fri, 28 Oct 2011 23:41:16 +0200
changeset 46165 3c5d3d286055
parent 45816 2625de88c994
child 46491 f2a587696afb
permissions -rw-r--r--
tuned Named_Thms: proper binding;
     1 (*  Title:      HOL/Tools/arith_data.ML
     2     Author:     Markus Wenzel, Stefan Berghofer, and Tobias Nipkow
     3 
     4 Common arithmetic proof auxiliary and legacy.
     5 *)
     6 
     7 signature ARITH_DATA =
     8 sig
     9   val arith_tac: Proof.context -> int -> tactic
    10   val verbose_arith_tac: Proof.context -> int -> tactic
    11   val add_tactic: string -> (bool -> Proof.context -> int -> tactic) -> theory -> theory
    12   val get_arith_facts: Proof.context -> thm list
    13 
    14   val mk_number: typ -> int -> term
    15   val mk_sum: typ -> term list -> term
    16   val long_mk_sum: typ -> term list -> term
    17   val dest_sum: term -> term list
    18 
    19   val prove_conv_nohyps: tactic list -> Proof.context -> term * term -> thm option
    20   val prove_conv: tactic list -> Proof.context -> thm list -> term * term -> thm option
    21   val prove_conv2: tactic -> (simpset -> tactic) -> simpset -> term * term -> thm
    22   val simp_all_tac: thm list -> simpset -> tactic
    23   val simplify_meta_eq: thm list -> simpset -> thm -> thm
    24 
    25   val setup: theory -> theory
    26 end;
    27 
    28 structure Arith_Data: ARITH_DATA =
    29 struct
    30 
    31 (* slots for plugging in arithmetic facts and tactics *)
    32 
    33 structure Arith_Facts = Named_Thms
    34 (
    35   val name = @{binding arith}
    36   val description = "arith facts -- only ground formulas"
    37 );
    38 
    39 val get_arith_facts = Arith_Facts.get;
    40 
    41 structure Arith_Tactics = Theory_Data
    42 (
    43   type T = (serial * (string * (bool -> Proof.context -> int -> tactic))) list;
    44   val empty = [];
    45   val extend = I;
    46   fun merge data : T = AList.merge (op =) (K true) data;
    47 );
    48 
    49 fun add_tactic name tac = Arith_Tactics.map (cons (serial (), (name, tac)));
    50 
    51 fun gen_arith_tac verbose ctxt =
    52   let
    53     val tactics = Arith_Tactics.get (Proof_Context.theory_of ctxt);
    54     fun invoke (_, (name, tac)) k st = tac verbose ctxt k st;
    55   in FIRST' (map invoke (rev tactics)) end;
    56 
    57 val arith_tac = gen_arith_tac false;
    58 val verbose_arith_tac = gen_arith_tac true;
    59 
    60 val setup =
    61   Arith_Facts.setup #>
    62   Method.setup @{binding arith}
    63     (Scan.succeed (fn ctxt =>
    64       METHOD (fn facts => HEADGOAL (Method.insert_tac (get_arith_facts ctxt @ facts)
    65         THEN' verbose_arith_tac ctxt))))
    66     "various arithmetic decision procedures";
    67 
    68 
    69 (* some specialized syntactic operations *)
    70 
    71 fun mk_number T n = HOLogic.number_of_const T $ HOLogic.mk_numeral n;
    72 
    73 val mk_plus = HOLogic.mk_binop @{const_name Groups.plus};
    74 
    75 fun mk_minus t = 
    76   let val T = Term.fastype_of t
    77   in Const (@{const_name Groups.uminus}, T --> T) $ t end;
    78 
    79 (*Thus mk_sum[t] yields t+0; longer sums don't have a trailing zero*)
    80 fun mk_sum T [] = mk_number T 0
    81   | mk_sum T [t, u] = mk_plus (t, u)
    82   | mk_sum T (t :: ts) = mk_plus (t, mk_sum T ts);
    83 
    84 (*this version ALWAYS includes a trailing zero*)
    85 fun long_mk_sum T [] = mk_number T 0
    86   | long_mk_sum T (t :: ts) = mk_plus (t, mk_sum T ts);
    87 
    88 (*decompose additions AND subtractions as a sum*)
    89 fun dest_summing (pos, Const (@{const_name Groups.plus}, _) $ t $ u, ts) =
    90       dest_summing (pos, t, dest_summing (pos, u, ts))
    91   | dest_summing (pos, Const (@{const_name Groups.minus}, _) $ t $ u, ts) =
    92       dest_summing (pos, t, dest_summing (not pos, u, ts))
    93   | dest_summing (pos, t, ts) = (if pos then t else mk_minus t) :: ts;
    94 
    95 fun dest_sum t = dest_summing (true, t, []);
    96 
    97 
    98 (* various auxiliary and legacy *)
    99 
   100 fun prove_conv_nohyps tacs ctxt (t, u) =
   101   if t aconv u then NONE
   102   else let val eq = HOLogic.mk_Trueprop (HOLogic.mk_eq (t, u))
   103   in SOME (Goal.prove ctxt [] [] eq (K (EVERY tacs))) end;
   104 
   105 fun prove_conv tacs ctxt (_: thm list) = prove_conv_nohyps tacs ctxt;
   106 
   107 fun prove_conv2 expand_tac norm_tac ss tu = (* FIXME avoid Drule.export_without_context *)
   108   mk_meta_eq (Drule.export_without_context (Goal.prove (Simplifier.the_context ss) [] []
   109       (HOLogic.mk_Trueprop (HOLogic.mk_eq tu))
   110     (K (EVERY [expand_tac, norm_tac ss]))));
   111 
   112 fun simp_all_tac rules =
   113   let val ss0 = HOL_ss addsimps rules
   114   in fn ss => ALLGOALS (simp_tac (Simplifier.inherit_context ss ss0)) end;
   115 
   116 fun simplify_meta_eq rules =
   117   let val ss0 = HOL_basic_ss addeqcongs [@{thm eq_cong2}] addsimps rules
   118   in fn ss => simplify (Simplifier.inherit_context ss ss0) o mk_meta_eq end
   119 
   120 end;