src/HOL/simpdata.ML
author haftmann
Mon Nov 27 13:42:47 2006 +0100 (2006-11-27)
changeset 21551 d276e7d25017
parent 21313 26fc3a45547c
child 21674 8a6bf9d7c751
permissions -rw-r--r--
introduced Simpdata structure
     1 (*  Title:      HOL/simpdata.ML
     2     ID:         $Id$
     3     Author:     Tobias Nipkow
     4     Copyright   1991  University of Cambridge
     5 
     6 Instantiation of the generic simplifier for HOL.
     7 *)
     8 
     9 (** tools setup **)
    10 
    11 structure Quantifier1 = Quantifier1Fun
    12 (struct
    13   (*abstract syntax*)
    14   fun dest_eq ((c as Const("op =",_)) $ s $ t) = SOME (c, s, t)
    15     | dest_eq _ = NONE;
    16   fun dest_conj ((c as Const("op &",_)) $ s $ t) = SOME (c, s, t)
    17     | dest_conj _ = NONE;
    18   fun dest_imp ((c as Const("op -->",_)) $ s $ t) = SOME (c, s, t)
    19     | dest_imp _ = NONE;
    20   val conj = HOLogic.conj
    21   val imp  = HOLogic.imp
    22   (*rules*)
    23   val iff_reflection = thm "eq_reflection"
    24   val iffI = thm "iffI"
    25   val iff_trans = thm "trans"
    26   val conjI= thm "conjI"
    27   val conjE= thm "conjE"
    28   val impI = thm "impI"
    29   val mp   = thm "mp"
    30   val uncurry = thm "uncurry"
    31   val exI  = thm "exI"
    32   val exE  = thm "exE"
    33   val iff_allI = thm "iff_allI"
    34   val iff_exI = thm "iff_exI"
    35   val all_comm = thm "all_comm"
    36   val ex_comm = thm "ex_comm"
    37 end);
    38 
    39 structure Simpdata =
    40 struct
    41 
    42 local
    43   val eq_reflection = thm "eq_reflection"
    44 in fun mk_meta_eq r = r RS eq_reflection end;
    45 fun safe_mk_meta_eq r = mk_meta_eq r handle Thm.THM _ => r;
    46 
    47 local
    48   val Eq_FalseI = thm "Eq_FalseI"
    49   val Eq_TrueI = thm "Eq_TrueI"
    50 in fun mk_eq th = case concl_of th
    51   (*expects Trueprop if not == *)
    52   of Const ("==",_) $ _ $ _ => th
    53    | _ $ (Const ("op =", _) $ _ $ _) => mk_meta_eq th
    54    | _ $ (Const ("Not", _) $ _) => th RS Eq_FalseI
    55    | _ => th RS Eq_TrueI
    56 end;
    57 
    58 local
    59   val meta_eq_to_obj_eq = thm "meta_eq_to_obj_eq"
    60   val Eq_TrueI = thm "Eq_TrueI"
    61 in fun mk_eq_True r =
    62   SOME (r RS meta_eq_to_obj_eq RS Eq_TrueI) handle Thm.THM _ => NONE;
    63 end;
    64 
    65 (* Produce theorems of the form
    66   (P1 =simp=> ... =simp=> Pn => x == y) ==> (P1 =simp=> ... =simp=> Pn => x = y)
    67 *)
    68 local
    69   val meta_eq_to_obj_eq = thm "meta_eq_to_obj_eq"
    70   val simp_implies_def = thm "simp_implies_def"
    71 in fun lift_meta_eq_to_obj_eq i st =
    72   let
    73     fun count_imp (Const ("HOL.simp_implies", _) $ P $ Q) = 1 + count_imp Q
    74       | count_imp _ = 0;
    75     val j = count_imp (Logic.strip_assums_concl (List.nth (prems_of st, i - 1)))
    76   in if j = 0 then meta_eq_to_obj_eq
    77     else
    78       let
    79         val Ps = map (fn k => Free ("P" ^ string_of_int k, propT)) (1 upto j);
    80         fun mk_simp_implies Q = foldr (fn (R, S) =>
    81           Const ("HOL.simp_implies", propT --> propT --> propT) $ R $ S) Q Ps
    82         val aT = TFree ("'a", HOLogic.typeS);
    83         val x = Free ("x", aT);
    84         val y = Free ("y", aT)
    85       in Goal.prove_global (Thm.theory_of_thm st) []
    86         [mk_simp_implies (Logic.mk_equals (x, y))]
    87         (mk_simp_implies (HOLogic.mk_Trueprop (HOLogic.mk_eq (x, y))))
    88         (fn prems => EVERY
    89          [rewrite_goals_tac [simp_implies_def],
    90           REPEAT (ares_tac (meta_eq_to_obj_eq :: map (rewrite_rule [simp_implies_def]) prems) 1)])
    91       end
    92   end;
    93 end;
    94 
    95 (*Congruence rules for = (instead of ==)*)
    96 fun mk_meta_cong rl = zero_var_indexes
    97   (let val rl' = Seq.hd (TRYALL (fn i => fn st =>
    98      rtac (lift_meta_eq_to_obj_eq i st) i st) rl)
    99    in mk_meta_eq rl' handle THM _ =>
   100      if can Logic.dest_equals (concl_of rl') then rl'
   101      else error "Conclusion of congruence rules must be =-equality"
   102    end);
   103 
   104 fun mk_atomize pairs =
   105   let
   106     fun atoms thm =
   107       let
   108         fun res th = map (fn rl => th RS rl);   (*exception THM*)
   109         fun res_fixed rls =
   110           if Thm.maxidx_of (Thm.adjust_maxidx_thm ~1 thm) = ~1 then res thm rls
   111           else Variable.trade (K (fn [thm'] => res thm' rls)) (Variable.thm_context thm) [thm];
   112       in
   113         case concl_of thm
   114           of Const ("Trueprop", _) $ p => (case head_of p
   115             of Const (a, _) => (case AList.lookup (op =) pairs a
   116               of SOME rls => (maps atoms (res_fixed rls) handle THM _ => [thm])
   117               | NONE => [thm])
   118             | _ => [thm])
   119           | _ => [thm]
   120       end;
   121   in atoms end;
   122 
   123 fun mksimps pairs =
   124   map_filter (try mk_eq) o mk_atomize pairs o gen_all;
   125 
   126 local
   127   val simp_impliesI = thm "simp_impliesI"
   128   val TrueI = thm "TrueI"
   129   val FalseE = thm "FalseE"
   130   val refl = thm "refl"
   131 in fun unsafe_solver_tac prems =
   132   (fn i => REPEAT_DETERM (match_tac [simp_impliesI] i)) THEN'
   133   FIRST'[resolve_tac(reflexive_thm :: TrueI :: refl :: prems), atac, etac FalseE];
   134 end;
   135 val unsafe_solver = mk_solver "HOL unsafe" unsafe_solver_tac;
   136 
   137 (*No premature instantiation of variables during simplification*)
   138 local
   139   val simp_impliesI = thm "simp_impliesI"
   140   val TrueI = thm "TrueI"
   141   val FalseE = thm "FalseE"
   142   val refl = thm "refl"
   143 in fun safe_solver_tac prems =
   144   (fn i => REPEAT_DETERM (match_tac [simp_impliesI] i)) THEN'
   145   FIRST'[match_tac(reflexive_thm :: TrueI :: refl :: prems),
   146          eq_assume_tac, ematch_tac [FalseE]];
   147 end;
   148 val safe_solver = mk_solver "HOL safe" safe_solver_tac;
   149 
   150 structure SplitterData =
   151 struct
   152   structure Simplifier = Simplifier
   153   val mk_eq           = mk_eq
   154   val meta_eq_to_iff  = thm "meta_eq_to_obj_eq"
   155   val iffD            = thm "iffD2"
   156   val disjE           = thm "disjE"
   157   val conjE           = thm "conjE"
   158   val exE             = thm "exE"
   159   val contrapos       = thm "contrapos_nn"
   160   val contrapos2      = thm "contrapos_pp"
   161   val notnotD         = thm "notnotD"
   162 end;
   163 
   164 structure Splitter = SplitterFun(SplitterData);
   165 
   166 (* integration of simplifier with classical reasoner *)
   167 
   168 structure Clasimp = ClasimpFun
   169  (structure Simplifier = Simplifier and Splitter = Splitter
   170   and Classical  = Classical and Blast = Blast
   171   val iffD1 = thm "iffD1" val iffD2 = thm "iffD2" val notE = thm "notE");
   172 
   173 val mksimps_pairs =
   174   [("op -->", [thm "mp"]), ("op &", [thm "conjunct1", thm "conjunct2"]),
   175    ("All", [thm "spec"]), ("True", []), ("False", []),
   176    ("HOL.If", [thm "if_bool_eq_conj" RS thm "iffD1"])];
   177 
   178 val simpset_basic =
   179   Simplifier.theory_context (the_context ()) empty_ss
   180     setsubgoaler asm_simp_tac
   181     setSSolver safe_solver
   182     setSolver unsafe_solver
   183     setmksimps (mksimps mksimps_pairs)
   184     setmkeqTrue mk_eq_True
   185     setmkcong mk_meta_cong;
   186 
   187 fun simplify rews = Simplifier.full_simplify (simpset_basic addsimps rews);
   188 
   189 fun unfold_tac ths =
   190   let val ss0 = Simplifier.clear_ss simpset_basic addsimps ths
   191   in fn ss => ALLGOALS (full_simp_tac (Simplifier.inherit_context ss ss0)) end;
   192 
   193 
   194 
   195 (** simprocs **)
   196 
   197 (* simproc for proving "(y = x) == False" from premise "~(x = y)" *)
   198 
   199 val use_neq_simproc = ref true;
   200 
   201 local
   202   val thy = the_context ();
   203   val neq_to_EQ_False = thm "not_sym" RS thm "Eq_FalseI";
   204   fun neq_prover sg ss (eq $ lhs $ rhs) =
   205     let
   206       fun test thm = (case #prop (rep_thm thm) of
   207                     _ $ (Not $ (eq' $ l' $ r')) =>
   208                       Not = HOLogic.Not andalso eq' = eq andalso
   209                       r' aconv lhs andalso l' aconv rhs
   210                   | _ => false)
   211     in if !use_neq_simproc then case find_first test (prems_of_ss ss)
   212      of NONE => NONE
   213       | SOME thm => SOME (thm RS neq_to_EQ_False)
   214      else NONE
   215     end
   216 in
   217 
   218 val neq_simproc = Simplifier.simproc thy "neq_simproc" ["x = y"] neq_prover;
   219 
   220 end;
   221 
   222 
   223 (* simproc for Let *)
   224 
   225 val use_let_simproc = ref true;
   226 
   227 local
   228   val thy = the_context ();
   229   val Let_folded = thm "Let_folded";
   230   val Let_unfold = thm "Let_unfold";
   231   val Let_def = thm "Let_def";
   232   val (f_Let_unfold, x_Let_unfold) =
   233       let val [(_$(f$x)$_)] = prems_of Let_unfold
   234       in (cterm_of thy f, cterm_of thy x) end
   235   val (f_Let_folded, x_Let_folded) =
   236       let val [(_$(f$x)$_)] = prems_of Let_folded
   237       in (cterm_of thy f, cterm_of thy x) end;
   238   val g_Let_folded =
   239       let val [(_$_$(g$_))] = prems_of Let_folded in cterm_of thy g end;
   240 in
   241 
   242 val let_simproc =
   243   Simplifier.simproc thy "let_simp" ["Let x f"]
   244    (fn sg => fn ss => fn t =>
   245      let val ctxt = Simplifier.the_context ss;
   246          val ([t'], ctxt') = Variable.import_terms false [t] ctxt;
   247      in Option.map (hd o Variable.export ctxt' ctxt o single)
   248       (case t' of (Const ("Let",_)$x$f) => (* x and f are already in normal form *)
   249          if not (!use_let_simproc) then NONE
   250          else if is_Free x orelse is_Bound x orelse is_Const x
   251          then SOME Let_def
   252          else
   253           let
   254              val n = case f of (Abs (x,_,_)) => x | _ => "x";
   255              val cx = cterm_of sg x;
   256              val {T=xT,...} = rep_cterm cx;
   257              val cf = cterm_of sg f;
   258              val fx_g = Simplifier.rewrite ss (Thm.capply cf cx);
   259              val (_$_$g) = prop_of fx_g;
   260              val g' = abstract_over (x,g);
   261            in (if (g aconv g')
   262                then
   263                   let
   264                     val rl = cterm_instantiate [(f_Let_unfold,cf),(x_Let_unfold,cx)] Let_unfold;
   265                   in SOME (rl OF [fx_g]) end
   266                else if Term.betapply (f,x) aconv g then NONE (*avoid identity conversion*)
   267                else let
   268                      val abs_g'= Abs (n,xT,g');
   269                      val g'x = abs_g'$x;
   270                      val g_g'x = symmetric (beta_conversion false (cterm_of sg g'x));
   271                      val rl = cterm_instantiate
   272                                [(f_Let_folded,cterm_of sg f),(x_Let_folded,cx),
   273                                 (g_Let_folded,cterm_of sg abs_g')]
   274                                Let_folded;
   275                    in SOME (rl OF [transitive fx_g g_g'x])
   276                    end)
   277            end
   278         | _ => NONE)
   279      end)
   280 
   281 end;
   282 
   283 
   284 (* generic refutation procedure *)
   285 
   286 (* parameters:
   287 
   288    test: term -> bool
   289    tests if a term is at all relevant to the refutation proof;
   290    if not, then it can be discarded. Can improve performance,
   291    esp. if disjunctions can be discarded (no case distinction needed!).
   292 
   293    prep_tac: int -> tactic
   294    A preparation tactic to be applied to the goal once all relevant premises
   295    have been moved to the conclusion.
   296 
   297    ref_tac: int -> tactic
   298    the actual refutation tactic. Should be able to deal with goals
   299    [| A1; ...; An |] ==> False
   300    where the Ai are atomic, i.e. no top-level &, | or EX
   301 *)
   302 
   303 local
   304   val conjE = thm "conjE"
   305   val exE = thm "exE"
   306   val disjE = thm "disjE"
   307   val notE = thm "notE"
   308   val rev_mp = thm "rev_mp"
   309   val ccontr = thm "ccontr"
   310   val nnf_simpset =
   311     empty_ss setmkeqTrue mk_eq_True
   312     setmksimps (mksimps mksimps_pairs)
   313     addsimps [thm "imp_conv_disj", thm "iff_conv_conj_imp", thm "de_Morgan_disj", thm "de_Morgan_conj",
   314       thm "not_all", thm "not_ex", thm "not_not"];
   315   fun prem_nnf_tac i st =
   316     full_simp_tac (Simplifier.theory_context (Thm.theory_of_thm st) nnf_simpset) i st;
   317 in
   318 fun refute_tac test prep_tac ref_tac =
   319   let val refute_prems_tac =
   320         REPEAT_DETERM
   321               (eresolve_tac [conjE, exE] 1 ORELSE
   322                filter_prems_tac test 1 ORELSE
   323                etac disjE 1) THEN
   324         ((etac notE 1 THEN eq_assume_tac 1) ORELSE
   325          ref_tac 1);
   326   in EVERY'[TRY o filter_prems_tac test,
   327             REPEAT_DETERM o etac rev_mp, prep_tac, rtac ccontr, prem_nnf_tac,
   328             SELECT_GOAL (DEPTH_SOLVE refute_prems_tac)]
   329   end;
   330 end;
   331 
   332 val defALL_regroup =
   333   Simplifier.simproc (the_context ())
   334     "defined ALL" ["ALL x. P x"] Quantifier1.rearrange_all;
   335 
   336 val defEX_regroup =
   337   Simplifier.simproc (the_context ())
   338     "defined EX" ["EX x. P x"] Quantifier1.rearrange_ex;
   339 
   340 
   341 val simpset_simprocs = simpset_basic
   342   addsimprocs [defALL_regroup, defEX_regroup, neq_simproc, let_simproc]
   343 
   344 end;
   345 
   346 structure Splitter = Simpdata.Splitter;
   347 structure Clasimp = Simpdata.Clasimp;