src/HOL/Tools/Sledgehammer/sledgehammer_fact_preprocessor.ML
changeset 37348 3ad1bfd2de46
parent 37347 635425a442e8
child 37349 3d7058e24b7a
equal deleted inserted replaced
37347:635425a442e8 37348:3ad1bfd2de46
    12   val trace_msg: (unit -> string) -> unit
    12   val trace_msg: (unit -> string) -> unit
    13   val skolem_prefix: string
    13   val skolem_prefix: string
    14   val skolem_infix: string
    14   val skolem_infix: string
    15   val cnf_axiom: theory -> thm -> thm list
    15   val cnf_axiom: theory -> thm -> thm list
    16   val multi_base_blacklist: string list
    16   val multi_base_blacklist: string list
    17   val is_bad_for_atp: thm -> bool
    17   val is_theorem_bad_for_atps: thm -> bool
    18   val type_has_topsort: typ -> bool
    18   val type_has_topsort: typ -> bool
    19   val cnf_rules_pairs: theory -> (string * thm) list -> (thm * (string * int)) list
    19   val cnf_rules_pairs:
    20   val suppress_endtheory: bool Unsynchronized.ref
    20     theory -> (string * thm) list -> (thm * (string * int)) list
    21     (*for emergency use where endtheory causes problems*)
    21   val use_skolem_cache: bool Unsynchronized.ref
       
    22     (* for emergency use where the Skolem cache causes problems *)
    22   val strip_subgoal : thm -> int -> (string * typ) list * term list * term
    23   val strip_subgoal : thm -> int -> (string * typ) list * term list * term
    23   val neg_clausify: thm -> thm list
    24   val neg_clausify: thm -> thm list
    24   val neg_conjecture_clauses:
    25   val neg_conjecture_clauses:
    25     Proof.context -> thm -> int -> thm list list * (string * typ) list
    26     Proof.context -> thm -> int -> thm list list * (string * typ) list
    26   val neg_clausify_tac: Proof.context -> int -> tactic
    27   val neg_clausify_tac: Proof.context -> int -> tactic
    84             if member (op =) lhs_vars v then I else insert (op =) (TFree v)
    85             if member (op =) lhs_vars v then I else insert (op =) (TFree v)
    85         | add_new_TFrees _ = I
    86         | add_new_TFrees _ = I
    86       val rhs_consts = fold_aterms (fn Const c => insert (op =) c | _ => I) rhs []
    87       val rhs_consts = fold_aterms (fn Const c => insert (op =) c | _ => I) rhs []
    87   in fold (#2 #> Term.fold_atyps add_new_TFrees) rhs_consts [] end;
    88   in fold (#2 #> Term.fold_atyps add_new_TFrees) rhs_consts [] end;
    88 
    89 
    89 (*Traverse a theorem, declaring Skolem function definitions. String s is the suggested
    90 (* Traverse a theorem, declaring Skolem function definitions. String "s" is the
    90   prefix for the Skolem constant.*)
    91    suggested prefix for the Skolem constants. *)
    91 fun declare_skofuns s th =
    92 fun declare_skolem_funs s th =
    92   let
    93   let
    93     val nref = Unsynchronized.ref 0    (* FIXME ??? *)
    94     val nref = Unsynchronized.ref 0    (* FIXME ??? *)
    94     fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) (axs, thy) =
    95     fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) (axs, thy) =
    95           (*Existential: declare a Skolem function, then insert into body and continue*)
    96           (*Existential: declare a Skolem function, then insert into body and continue*)
    96           let
    97           let
   119       | dec_sko (@{const Trueprop} $ p) thx = dec_sko p thx
   120       | dec_sko (@{const Trueprop} $ p) thx = dec_sko p thx
   120       | dec_sko t thx = thx (*Do nothing otherwise*)
   121       | dec_sko t thx = thx (*Do nothing otherwise*)
   121   in fn thy => dec_sko (Thm.prop_of th) ([], thy) end;
   122   in fn thy => dec_sko (Thm.prop_of th) ([], thy) end;
   122 
   123 
   123 (*Traverse a theorem, accumulating Skolem function definitions.*)
   124 (*Traverse a theorem, accumulating Skolem function definitions.*)
   124 fun assume_skofuns s th =
   125 fun assume_skolem_funs s th =
   125   let val sko_count = Unsynchronized.ref 0   (* FIXME ??? *)
   126   let val sko_count = Unsynchronized.ref 0   (* FIXME ??? *)
   126       fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) defs =
   127       fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) defs =
   127             (*Existential: declare a Skolem function, then insert into body and continue*)
   128             (*Existential: declare a Skolem function, then insert into body and continue*)
   128             let val skos = map (#1 o Logic.dest_equals) defs  (*existing sko fns*)
   129             let val skos = map (#1 o Logic.dest_equals) defs  (*existing sko fns*)
   129                 val args = subtract (op =) skos (OldTerm.term_frees xtp) (*the formal parameters*)
   130                 val args = subtract (op =) skos (OldTerm.term_frees xtp) (*the formal parameters*)
   300         |> Meson.make_nnf ctxt |> strip_lambdas ~1
   301         |> Meson.make_nnf ctxt |> strip_lambdas ~1
   301   in  (th3, ctxt)  end;
   302   in  (th3, ctxt)  end;
   302 
   303 
   303 (*Generate Skolem functions for a theorem supplied in nnf*)
   304 (*Generate Skolem functions for a theorem supplied in nnf*)
   304 fun assume_skolem_of_def s th =
   305 fun assume_skolem_of_def s th =
   305   map (skolem_of_def o Thm.assume o (cterm_of (theory_of_thm th))) (assume_skofuns s th);
   306   map (skolem_of_def o Thm.assume o (cterm_of (theory_of_thm th)))
       
   307       (assume_skolem_funs s th)
   306 
   308 
   307 
   309 
   308 (*** Blacklisting (FIXME: duplicated in "Sledgehammer_Fact_Filter"?) ***)
   310 (*** Blacklisting (FIXME: duplicated in "Sledgehammer_Fact_Filter"?) ***)
   309 
   311 
   310 val max_lambda_nesting = 3;
   312 val max_lambda_nesting = 3
   311 
   313 
   312 fun excessive_lambdas (f$t, k) = excessive_lambdas (f,k) orelse excessive_lambdas (t,k)
   314 fun term_has_too_many_lambdas max (t1 $ t2) =
   313   | excessive_lambdas (Abs(_,_,t), k) = k=0 orelse excessive_lambdas (t,k-1)
   315     exists (term_has_too_many_lambdas max) [t1, t2]
   314   | excessive_lambdas _ = false;
   316   | term_has_too_many_lambdas max (Abs (_, _, t)) =
   315 
   317     max = 0 orelse term_has_too_many_lambdas (max - 1) t
   316 fun is_formula_type T = (T = HOLogic.boolT orelse T = propT);
   318   | term_has_too_many_lambdas _ _ = false
   317 
   319 
   318 (*Don't count nested lambdas at the level of formulas, as they are quantifiers*)
   320 fun is_formula_type T = (T = HOLogic.boolT orelse T = propT)
   319 fun excessive_lambdas_fm Ts (Abs(_,T,t)) = excessive_lambdas_fm (T::Ts) t
   321 
   320   | excessive_lambdas_fm Ts t =
   322 (* Don't count nested lambdas at the level of formulas, since they are
   321       if is_formula_type (fastype_of1 (Ts, t))
   323    quantifiers. *)
   322       then exists (excessive_lambdas_fm Ts) (#2 (strip_comb t))
   324 fun formula_has_too_many_lambdas Ts (Abs (_, T, t)) =
   323       else excessive_lambdas (t, max_lambda_nesting);
   325     formula_has_too_many_lambdas (T :: Ts) t
   324 
   326   | formula_has_too_many_lambdas Ts t =
   325 (*The max apply_depth of any metis call in Metis_Examples (on 31-10-2007) was 11.*)
   327     if is_formula_type (fastype_of1 (Ts, t)) then
   326 val max_apply_depth = 15;
   328       exists (formula_has_too_many_lambdas Ts) (#2 (strip_comb t))
   327 
   329     else
   328 fun apply_depth (f$t) = Int.max (apply_depth f, apply_depth t + 1)
   330       term_has_too_many_lambdas max_lambda_nesting t
   329   | apply_depth (Abs(_,_,t)) = apply_depth t
   331 
   330   | apply_depth _ = 0;
   332 (* The max apply depth of any "metis" call in "Metis_Examples" (on 31-10-2007)
   331 
   333    was 11. *)
   332 fun too_complex t =
   334 val max_apply_depth = 15
   333   apply_depth t > max_apply_depth orelse
   335 
   334   Meson.too_many_clauses NONE t orelse
   336 fun apply_depth (f $ t) = Int.max (apply_depth f, apply_depth t + 1)
   335   excessive_lambdas_fm [] t;
   337   | apply_depth (Abs (_, _, t)) = apply_depth t
       
   338   | apply_depth _ = 0
       
   339 
       
   340 fun is_formula_too_complex t =
       
   341   apply_depth t > max_apply_depth orelse Meson.too_many_clauses NONE t orelse
       
   342   formula_has_too_many_lambdas [] t
   336 
   343 
   337 fun is_strange_thm th =
   344 fun is_strange_thm th =
   338   case head_of (concl_of th) of
   345   case head_of (concl_of th) of
   339       Const (a, _) => (a <> @{const_name Trueprop} andalso
   346       Const (a, _) => (a <> @{const_name Trueprop} andalso
   340                        a <> @{const_name "=="})
   347                        a <> @{const_name "=="})
   341     | _ => false;
   348     | _ => false;
   342 
   349 
   343 fun is_bad_for_atp th =
   350 fun is_theorem_bad_for_atps thm =
   344   too_complex (prop_of th) orelse
   351   let val t = prop_of thm in
   345   exists_type type_has_topsort (prop_of th) orelse is_strange_thm th
   352     is_formula_too_complex t orelse exists_type type_has_topsort t orelse
       
   353     is_strange_thm thm
       
   354   end
   346 
   355 
   347 (* FIXME: put other record thms here, or declare as "no_atp" *)
   356 (* FIXME: put other record thms here, or declare as "no_atp" *)
   348 val multi_base_blacklist =
   357 val multi_base_blacklist =
   349   ["defs", "select_defs", "update_defs", "induct", "inducts", "split", "splits",
   358   ["defs", "select_defs", "update_defs", "induct", "inducts", "split", "splits",
   350    "split_asm", "cases", "ext_cases"];
   359    "split_asm", "cases", "ext_cases"];
   354   else gensym "unknown_thm_";
   363   else gensym "unknown_thm_";
   355 
   364 
   356 (*Skolemize a named theorem, with Skolem functions as additional premises.*)
   365 (*Skolemize a named theorem, with Skolem functions as additional premises.*)
   357 fun skolem_thm (s, th) =
   366 fun skolem_thm (s, th) =
   358   if member (op =) multi_base_blacklist (Long_Name.base_name s) orelse
   367   if member (op =) multi_base_blacklist (Long_Name.base_name s) orelse
   359      is_bad_for_atp th then
   368      is_theorem_bad_for_atps th then
   360     []
   369     []
   361   else
   370   else
   362     let
   371     let
   363       val ctxt0 = Variable.global_thm_context th
   372       val ctxt0 = Variable.global_thm_context th
   364       val (nnfth, ctxt1) = to_nnf th ctxt0
   373       val (nnfth, ctxt1) = to_nnf th ctxt0
   412 
   421 
   413 local
   422 local
   414 
   423 
   415 fun skolem_def (name, th) thy =
   424 fun skolem_def (name, th) thy =
   416   let val ctxt0 = Variable.global_thm_context th in
   425   let val ctxt0 = Variable.global_thm_context th in
   417     (case try (to_nnf th) ctxt0 of
   426     case try (to_nnf th) ctxt0 of
   418       NONE => (NONE, thy)
   427       NONE => (NONE, thy)
   419     | SOME (nnfth, ctxt1) =>
   428     | SOME (nnfth, ctxt1) =>
   420         let val (defs, thy') = declare_skofuns (flatten_name name) nnfth thy
   429       let val (defs, thy') = declare_skolem_funs (flatten_name name) nnfth thy
   421         in (SOME (th, ctxt0, ctxt1, nnfth, defs), thy') end)
   430       in (SOME (th, ctxt0, ctxt1, nnfth, defs), thy') end
   422   end;
   431   end;
   423 
   432 
   424 fun skolem_cnfs (th, ctxt0, ctxt1, nnfth, defs) =
   433 fun skolem_cnfs (th, ctxt0, ctxt1, nnfth, defs) =
   425   let
   434   let
   426     val (cnfs, ctxt2) = Meson.make_cnf (map skolem_of_def defs) nnfth ctxt1;
   435     val (cnfs, ctxt2) = Meson.make_cnf (map skolem_of_def defs) nnfth ctxt1;
   440       if Facts.is_concealed facts name orelse already_seen thy name then I
   449       if Facts.is_concealed facts name orelse already_seen thy name then I
   441       else cons (name, ths));
   450       else cons (name, ths));
   442     val new_thms = (new_facts, []) |-> fold (fn (name, ths) =>
   451     val new_thms = (new_facts, []) |-> fold (fn (name, ths) =>
   443       if member (op =) multi_base_blacklist (Long_Name.base_name name) then I
   452       if member (op =) multi_base_blacklist (Long_Name.base_name name) then I
   444       else fold_index (fn (i, th) =>
   453       else fold_index (fn (i, th) =>
   445         if is_bad_for_atp th orelse is_some (lookup_cache thy th) then I
   454         if is_theorem_bad_for_atps th orelse is_some (lookup_cache thy th) then
   446         else cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths);
   455           I
       
   456         else
       
   457           cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths)
   447   in
   458   in
   448     if null new_facts then NONE
   459     if null new_facts then NONE
   449     else
   460     else
   450       let
   461       let
   451         val (defs, thy') = thy
   462         val (defs, thy') = thy
   456       in SOME (fold update_cache cache_entries thy') end
   467       in SOME (fold update_cache cache_entries thy') end
   457   end;
   468   end;
   458 
   469 
   459 end;
   470 end;
   460 
   471 
   461 val suppress_endtheory = Unsynchronized.ref false
   472 val use_skolem_cache = Unsynchronized.ref true
   462 
   473 
   463 fun clause_cache_endtheory thy =
   474 fun clause_cache_endtheory thy =
   464   if ! suppress_endtheory then NONE
   475   if !use_skolem_cache then saturate_skolem_cache thy else NONE
   465   else saturate_skolem_cache thy;
       
   466 
   476 
   467 
   477 
   468 (*The cache can be kept smaller by inspecting the prop of each thm. Can ignore all that are
   478 (*The cache can be kept smaller by inspecting the prop of each thm. Can ignore all that are
   469   lambda_free, but then the individual theory caches become much bigger.*)
   479   lambda_free, but then the individual theory caches become much bigger.*)
   470 
   480 
   508 
   518 
   509 
   519 
   510 (** setup **)
   520 (** setup **)
   511 
   521 
   512 val setup =
   522 val setup =
   513   perhaps saturate_skolem_cache #>
   523   perhaps saturate_skolem_cache
   514   Theory.at_end clause_cache_endtheory;
   524   #> Theory.at_end clause_cache_endtheory
   515 
   525 
   516 end;
   526 end;