src/Provers/clasimp.ML
author wenzelm
Sun, 06 Nov 2011 21:51:46 +0100
changeset 46246 7fe19930dfc9
parent 45761 22f665a2e91c
child 48982 c422128d3889
permissions -rw-r--r--
more explicit representation of rule_attribute vs. declaration_attribute vs. mixed_attribute;
misc tuning;
     1 (*  Title:      Provers/clasimp.ML
     2     Author:     David von Oheimb, TU Muenchen
     3 
     4 Combination of classical reasoner and simplifier (depends on
     5 splitter.ML, classical.ML, blast.ML).
     6 *)
     7 
     8 signature CLASIMP_DATA =
     9 sig
    10   structure Splitter: SPLITTER
    11   structure Classical: CLASSICAL
    12   structure Blast: BLAST
    13   val notE: thm
    14   val iffD1: thm
    15   val iffD2: thm
    16 end;
    17 
    18 signature CLASIMP =
    19 sig
    20   val addSss: Proof.context -> Proof.context
    21   val addss: Proof.context -> Proof.context
    22   val clarsimp_tac: Proof.context -> int -> tactic
    23   val mk_auto_tac: Proof.context -> int -> int -> tactic
    24   val auto_tac: Proof.context -> tactic
    25   val force_tac: Proof.context -> int -> tactic
    26   val fast_force_tac: Proof.context -> int -> tactic
    27   val slow_simp_tac: Proof.context -> int -> tactic
    28   val best_simp_tac: Proof.context -> int -> tactic
    29   val iff_add: attribute
    30   val iff_add': attribute
    31   val iff_del: attribute
    32   val iff_modifiers: Method.modifier parser list
    33   val clasimp_modifiers: Method.modifier parser list
    34   val clasimp_setup: theory -> theory
    35 end;
    36 
    37 functor Clasimp(Data: CLASIMP_DATA): CLASIMP =
    38 struct
    39 
    40 structure Splitter = Data.Splitter;
    41 structure Classical = Data.Classical;
    42 structure Blast = Data.Blast;
    43 
    44 
    45 (* simp as classical wrapper *)
    46 
    47 (*not totally safe: may instantiate unknowns that appear also in other subgoals*)
    48 val safe_asm_full_simp_tac = Simplifier.generic_simp_tac true (true, true, true);
    49 
    50 fun clasimp f name tac ctxt =
    51   Classical.map_claset (fn cs => f (cs, (name, CHANGED o tac (simpset_of ctxt)))) ctxt;
    52 
    53 (*Add a simpset to the claset!*)
    54 (*Caution: only one simpset added can be added by each of addSss and addss*)
    55 val addSss = clasimp Classical.addSafter "safe_asm_full_simp_tac" safe_asm_full_simp_tac;
    56 val addss = clasimp Classical.addbefore "asm_full_simp_tac" Simplifier.asm_full_simp_tac;
    57 
    58 
    59 (* iffs: addition of rules to simpsets and clasets simultaneously *)
    60 
    61 local
    62 
    63 (*Takes (possibly conditional) theorems of the form A<->B to
    64         the Safe Intr     rule B==>A and
    65         the Safe Destruct rule A==>B.
    66   Also ~A goes to the Safe Elim rule A ==> ?R
    67   Failing other cases, A is added as a Safe Intr rule*)
    68 
    69 fun add_iff safe unsafe =
    70   Thm.declaration_attribute (fn th =>
    71     let
    72       val n = nprems_of th;
    73       val (elim, intro) = if n = 0 then safe else unsafe;
    74       val zero_rotate = zero_var_indexes o rotate_prems n;
    75     in
    76       Thm.attribute_declaration intro (zero_rotate (th RS Data.iffD2)) #>
    77       Thm.attribute_declaration elim (Tactic.make_elim (zero_rotate (th RS Data.iffD1)))
    78       handle THM _ =>
    79         (Thm.attribute_declaration elim (zero_rotate (th RS Data.notE))
    80           handle THM _ => Thm.attribute_declaration intro th)
    81     end);
    82 
    83 fun del_iff del = Thm.declaration_attribute (fn th =>
    84   let val zero_rotate = zero_var_indexes o rotate_prems (nprems_of th) in
    85     Thm.attribute_declaration del (zero_rotate (th RS Data.iffD2)) #>
    86     Thm.attribute_declaration del (Tactic.make_elim (zero_rotate (th RS Data.iffD1)))
    87     handle THM _ =>
    88       (Thm.attribute_declaration del (zero_rotate (th RS Data.notE))
    89         handle THM _ => Thm.attribute_declaration del th)
    90   end);
    91 
    92 in
    93 
    94 val iff_add =
    95   Thm.declaration_attribute (fn th =>
    96     Thm.attribute_declaration (add_iff
    97       (Classical.safe_elim NONE, Classical.safe_intro NONE)
    98       (Classical.haz_elim NONE, Classical.haz_intro NONE)) th
    99     #> Thm.attribute_declaration Simplifier.simp_add th);
   100 
   101 val iff_add' =
   102   add_iff
   103     (Context_Rules.elim_query NONE, Context_Rules.intro_query NONE)
   104     (Context_Rules.elim_query NONE, Context_Rules.intro_query NONE);
   105 
   106 val iff_del =
   107   Thm.declaration_attribute (fn th =>
   108     Thm.attribute_declaration (del_iff Classical.rule_del) th #>
   109     Thm.attribute_declaration (del_iff Context_Rules.rule_del) th #>
   110     Thm.attribute_declaration Simplifier.simp_del th);
   111 
   112 end;
   113 
   114 
   115 (* tactics *)
   116 
   117 fun clarsimp_tac ctxt =
   118   safe_asm_full_simp_tac (simpset_of ctxt) THEN_ALL_NEW
   119   Classical.clarify_tac (addSss ctxt);
   120 
   121 
   122 (* auto_tac *)
   123 
   124 (* a variant of depth_tac that avoids interference of the simplifier
   125    with dup_step_tac when they are combined by auto_tac *)
   126 local
   127 
   128 fun slow_step_tac' ctxt =
   129   Classical.appWrappers ctxt
   130     (Classical.instp_step_tac ctxt APPEND' Classical.haz_step_tac ctxt);
   131 
   132 in
   133 
   134 fun nodup_depth_tac ctxt m i st =
   135   SELECT_GOAL
   136     (Classical.safe_steps_tac ctxt 1 THEN_ELSE
   137       (DEPTH_SOLVE (nodup_depth_tac ctxt m 1),
   138         Classical.inst0_step_tac ctxt 1 APPEND COND (K (m = 0)) no_tac
   139           (slow_step_tac' ctxt 1 THEN DEPTH_SOLVE (nodup_depth_tac ctxt (m - 1) 1)))) i st;
   140 
   141 end;
   142 
   143 (*Designed to be idempotent, except if Blast.depth_tac instantiates variables
   144   in some of the subgoals*)
   145 fun mk_auto_tac ctxt m n =
   146   let
   147     val main_tac =
   148       Blast.depth_tac ctxt m  (* fast but can't use wrappers *)
   149       ORELSE'
   150       (CHANGED o nodup_depth_tac (addss ctxt) n);  (* slower but more general *)
   151   in
   152     PARALLEL_GOALS (ALLGOALS (Simplifier.asm_full_simp_tac (simpset_of ctxt))) THEN
   153     TRY (Classical.safe_tac ctxt) THEN
   154     REPEAT_DETERM (FIRSTGOAL main_tac) THEN
   155     TRY (Classical.safe_tac (addSss ctxt)) THEN
   156     prune_params_tac
   157   end;
   158 
   159 fun auto_tac ctxt = mk_auto_tac ctxt 4 2;
   160 
   161 
   162 (* force_tac *)
   163 
   164 (* aimed to solve the given subgoal totally, using whatever tools possible *)
   165 fun force_tac ctxt =
   166   let val ctxt' = addss ctxt in
   167     SELECT_GOAL
   168      (Classical.clarify_tac ctxt' 1 THEN
   169       IF_UNSOLVED (Simplifier.asm_full_simp_tac (simpset_of ctxt) 1) THEN
   170       ALLGOALS (Classical.first_best_tac ctxt'))
   171   end;
   172 
   173 
   174 (* basic combinations *)
   175 
   176 fun fast_simp_tac ctxt i =
   177   let val _ = legacy_feature "Old name 'fastsimp' - use 'fastforce' instead"
   178   in Classical.fast_tac (addss ctxt) i end;
   179 
   180 val fast_force_tac = Classical.fast_tac o addss;
   181 val slow_simp_tac = Classical.slow_tac o addss;
   182 val best_simp_tac = Classical.best_tac o addss;
   183 
   184 (** concrete syntax **)
   185 
   186 (* attributes *)
   187 
   188 fun iff_att x = (Scan.lift
   189  (Args.del >> K iff_del ||
   190   Scan.option Args.add -- Args.query >> K iff_add' ||
   191   Scan.option Args.add >> K iff_add)) x;
   192 
   193 
   194 (* method modifiers *)
   195 
   196 val iffN = "iff";
   197 
   198 val iff_modifiers =
   199  [Args.$$$ iffN -- Scan.option Args.add -- Args.colon >> K ((I, iff_add): Method.modifier),
   200   Args.$$$ iffN -- Scan.option Args.add -- Args.query_colon >> K (I, iff_add'),
   201   Args.$$$ iffN -- Args.del -- Args.colon >> K (I, iff_del)];
   202 
   203 val clasimp_modifiers =
   204   Simplifier.simp_modifiers @ Splitter.split_modifiers @
   205   Classical.cla_modifiers @ iff_modifiers;
   206 
   207 
   208 (* methods *)
   209 
   210 fun clasimp_method' tac =
   211   Method.sections clasimp_modifiers >> K (SIMPLE_METHOD' o tac);
   212 
   213 val auto_method =
   214   Scan.lift (Scan.option (Parse.nat -- Parse.nat)) --|
   215     Method.sections clasimp_modifiers >>
   216   (fn NONE => SIMPLE_METHOD o CHANGED_PROP o auto_tac
   217     | SOME (m, n) => (fn ctxt => SIMPLE_METHOD (CHANGED_PROP (mk_auto_tac ctxt m n))));
   218 
   219 
   220 (* theory setup *)
   221 
   222 val clasimp_setup =
   223   Attrib.setup @{binding iff} iff_att "declaration of Simplifier / Classical rules" #>
   224   Method.setup @{binding fastsimp} (clasimp_method' fast_simp_tac) "combined fast and simp (legacy name)" #>
   225   Method.setup @{binding fastforce} (clasimp_method' fast_force_tac) "combined fast and simp" #>
   226   Method.setup @{binding slowsimp} (clasimp_method' slow_simp_tac) "combined slow and simp" #>
   227   Method.setup @{binding bestsimp} (clasimp_method' best_simp_tac) "combined best and simp" #>
   228   Method.setup @{binding force} (clasimp_method' force_tac) "force" #>
   229   Method.setup @{binding auto} auto_method "auto" #>
   230   Method.setup @{binding clarsimp} (clasimp_method' (CHANGED_PROP oo clarsimp_tac))
   231     "clarify simplified goal";
   232 
   233 end;