src/HOL/Tools/Sledgehammer/sledgehammer_filter.ML
changeset 43245 cef69d31bfa4
parent 43085 0a2f5b86bdd7
child 43324 2b47822868e4
equal deleted inserted replaced
43244:db041e88a805 43245:cef69d31bfa4
    42   val fact_from_ref :
    42   val fact_from_ref :
    43     Proof.context -> unit Symtab.table -> thm list
    43     Proof.context -> unit Symtab.table -> thm list
    44     -> Facts.ref * Attrib.src list -> ((string * locality) * thm) list
    44     -> Facts.ref * Attrib.src list -> ((string * locality) * thm) list
    45   val all_facts :
    45   val all_facts :
    46     Proof.context -> 'a Symtab.table -> bool -> (term -> bool) -> thm list
    46     Proof.context -> 'a Symtab.table -> bool -> (term -> bool) -> thm list
    47     -> thm list -> (((unit -> string) * locality) * (bool * thm)) list
    47     -> thm list -> (((unit -> string) * locality) * thm) list
    48   val const_names_in_fact :
    48   val const_names_in_fact :
    49     theory -> (string * typ -> term list -> bool * term list) -> term
    49     theory -> (string * typ -> term list -> bool * term list) -> term
    50     -> string list
    50     -> string list
    51   val relevant_facts :
    51   val relevant_facts :
    52     Proof.context -> real * real -> int -> (term -> bool)
    52     Proof.context -> real * real -> int -> (term -> bool)
   182       SOME (p_name, ind_T)
   182       SOME (p_name, ind_T)
   183     else
   183     else
   184       NONE
   184       NONE
   185   | _ => NONE
   185   | _ => NONE
   186 
   186 
   187 fun instantiate_induct_rule ctxt concl_prop p_name ((name, loc), (multi, th))
   187 fun instantiate_induct_rule ctxt concl_prop p_name ((name, loc), th) ind_x =
   188                             ind_x =
       
   189   let
   188   let
   190     fun varify_noninducts (t as Free (s, T)) =
   189     fun varify_noninducts (t as Free (s, T)) =
   191         if (s, T) = ind_x orelse can dest_funT T then t else Var ((s, 0), T)
   190         if (s, T) = ind_x orelse can dest_funT T then t else Var ((s, 0), T)
   192       | varify_noninducts t = t
   191       | varify_noninducts t = t
   193     val p_inst =
   192     val p_inst =
   194       concl_prop |> map_aterms varify_noninducts |> close_form
   193       concl_prop |> map_aterms varify_noninducts |> close_form
   195                  |> lambda (Free ind_x)
   194                  |> lambda (Free ind_x)
   196                  |> string_for_term ctxt
   195                  |> string_for_term ctxt
   197   in
   196   in
   198     ((fn () => name () ^ "[where " ^ p_name ^ " = " ^ quote p_inst ^ "]", loc),
   197     ((fn () => name () ^ "[where " ^ p_name ^ " = " ^ quote p_inst ^ "]", loc),
   199      (multi, th |> read_instantiate ctxt [((p_name, 0), p_inst)]))
   198      th |> read_instantiate ctxt [((p_name, 0), p_inst)])
   200   end
   199   end
   201 
   200 
   202 fun type_match thy (T1, T2) =
   201 fun type_match thy (T1, T2) =
   203   (Sign.typ_match thy (T2, T1) Vartab.empty; true)
   202   (Sign.typ_match thy (T2, T1) Vartab.empty; true)
   204   handle Type.TYPE_MATCH => false
   203   handle Type.TYPE_MATCH => false
   205 
   204 
   206 fun instantiate_if_induct_rule ctxt stmt stmt_xs (ax as (_, (_, th))) =
   205 fun instantiate_if_induct_rule ctxt stmt stmt_xs (ax as (_, th)) =
   207   case struct_induct_rule_on th of
   206   case struct_induct_rule_on th of
   208     SOME (p_name, ind_T) =>
   207     SOME (p_name, ind_T) =>
   209     let val thy = Proof_Context.theory_of ctxt in
   208     let val thy = Proof_Context.theory_of ctxt in
   210       stmt_xs |> filter (fn (_, T) => type_match thy (T, ind_T))
   209       stmt_xs |> filter (fn (_, T) => type_match thy (T, ind_T))
   211               |> map_filter (try (instantiate_induct_rule ctxt stmt p_name ax))
   210               |> map_filter (try (instantiate_induct_rule ctxt stmt p_name ax))
   710   let val names = Long_Name.explode a in
   709   let val names = Long_Name.explode a in
   711     (length names > 2 andalso not (hd names = "local") andalso
   710     (length names > 2 andalso not (hd names = "local") andalso
   712      String.isSuffix "_def" a) orelse String.isSuffix "_defs" a
   711      String.isSuffix "_def" a) orelse String.isSuffix "_defs" a
   713   end
   712   end
   714 
   713 
   715 fun mk_fact_table g f xs =
   714 fun uniquify xs =
   716   fold (Termtab.update o `(g o prop_of o f)) xs Termtab.empty
   715   Termtab.fold (cons o snd)
   717 fun uniquify xs = Termtab.fold (cons o snd) (mk_fact_table I snd xs) []
   716                (fold (Termtab.update o `(prop_of o snd)) xs Termtab.empty) []
   718 
   717 
   719 (* FIXME: put other record thms here, or declare as "no_atp" *)
   718 (* FIXME: put other record thms here, or declare as "no_atp" *)
   720 fun multi_base_blacklist ctxt =
   719 fun multi_base_blacklist ctxt =
   721   ["defs", "select_defs", "update_defs", "split", "splits", "split_asm",
   720   ["defs", "select_defs", "update_defs", "split", "splits", "split_asm",
   722    "cases", "ext_cases", "eq.simps", "eq.refl", "nchotomy", "case_cong",
   721    "cases", "ext_cases", "eq.simps", "eq.refl", "nchotomy", "case_cong",
   795 val normalize_simp_prop =
   794 val normalize_simp_prop =
   796   meta_equify
   795   meta_equify
   797   #> map_aterms (fn Var ((s, _), T) => Var ((s, 0), T) | t => t)
   796   #> map_aterms (fn Var ((s, _), T) => Var ((s, 0), T) | t => t)
   798   #> map_types (map_type_tvar (fn ((s, _), S) => TVar ((s, 0), S)))
   797   #> map_types (map_type_tvar (fn ((s, _), S) => TVar ((s, 0), S)))
   799 
   798 
   800 fun clasimpset_rules_of ctxt =
   799 fun clasimpset_rule_table_of ctxt =
   801   let
   800   let
       
   801     fun add loc g f = fold (Termtab.update o rpair loc o g o prop_of o f)
   802     val {safeIs, safeEs, hazIs, hazEs, ...} = ctxt |> claset_of |> Classical.rep_cs
   802     val {safeIs, safeEs, hazIs, hazEs, ...} = ctxt |> claset_of |> Classical.rep_cs
   803     val intros = Item_Net.content safeIs @ Item_Net.content hazIs
   803     val intros = Item_Net.content safeIs @ Item_Net.content hazIs
   804     val elims = map Classical.classical_rule (Item_Net.content safeEs @ Item_Net.content hazEs)
   804     val elims = map Classical.classical_rule (Item_Net.content safeEs @ Item_Net.content hazEs)
   805     val simps = ctxt |> simpset_of |> dest_ss |> #simps
   805     val simps = ctxt |> simpset_of |> dest_ss |> #simps
   806   in
   806   in
   807     (mk_fact_table I I intros,
   807     Termtab.empty |> add Intro I I intros
   808      mk_fact_table I I elims,
   808                   |> add Elim I I elims
   809      mk_fact_table normalize_simp_prop snd simps)
   809                   |> add Simp I snd simps
       
   810                   |> add Simp normalize_simp_prop snd simps
   810   end
   811   end
   811 
   812 
   812 fun all_facts ctxt reserved really_all is_appropriate_prop add_ths chained_ths =
   813 fun all_facts ctxt reserved really_all is_appropriate_prop add_ths chained_ths =
   813   let
   814   let
   814     val thy = Proof_Context.theory_of ctxt
   815     val thy = Proof_Context.theory_of ctxt
   816     val local_facts = Proof_Context.facts_of ctxt
   817     val local_facts = Proof_Context.facts_of ctxt
   817     val named_locals = local_facts |> Facts.dest_static []
   818     val named_locals = local_facts |> Facts.dest_static []
   818     val assms = Assumption.all_assms_of ctxt
   819     val assms = Assumption.all_assms_of ctxt
   819     fun is_assum th = exists (fn ct => prop_of th aconv term_of ct) assms
   820     fun is_assum th = exists (fn ct => prop_of th aconv term_of ct) assms
   820     val is_chained = member Thm.eq_thm_prop chained_ths
   821     val is_chained = member Thm.eq_thm_prop chained_ths
   821     val (intros, elims, simps) = clasimpset_rules_of ctxt
   822     val clasimpset_table = clasimpset_rule_table_of ctxt
   822     fun locality_of_theorem global th =
   823     fun locality_of_theorem global th =
   823       if is_chained th then
   824       if is_chained th then
   824         Chained
   825         Chained
   825       else if global then
   826       else if global then
   826         let val t = prop_of th in
   827         Termtab.lookup clasimpset_table (prop_of th) |> the_default General
   827           if Termtab.defined intros t then Intro
       
   828           else if Termtab.defined elims t then Elim
       
   829           else if Termtab.defined simps (normalize_simp_prop t) then Simp
       
   830           else General
       
   831         end
       
   832       else
   828       else
   833         if is_assum th then Assum else Local
   829         if is_assum th then Assum else Local
   834     fun is_good_unnamed_local th =
   830     fun is_good_unnamed_local th =
   835       not (Thm.has_name_hint th) andalso
   831       not (Thm.has_name_hint th) andalso
   836       forall (fn (_, ths) => not (member Thm.eq_thm_prop ths th)) named_locals
   832       forall (fn (_, ths) => not (member Thm.eq_thm_prop ths th)) named_locals
   859               case try (Proof_Context.get_thms ctxt) a of
   855               case try (Proof_Context.get_thms ctxt) a of
   860                 NONE => false
   856                 NONE => false
   861               | SOME ths' => eq_list Thm.eq_thm_prop (ths, ths')
   857               | SOME ths' => eq_list Thm.eq_thm_prop (ths, ths')
   862           in
   858           in
   863             pair 1
   859             pair 1
   864             #> fold (fn th => fn (j, rest) =>
   860             #> fold (fn th => fn (j, (multis, unis)) =>
   865                         (j + 1,
   861                         (j + 1,
   866                          if not (member Thm.eq_thm_prop add_ths th) andalso
   862                          if not (member Thm.eq_thm_prop add_ths th) andalso
   867                             is_theorem_bad_for_atps is_appropriate_prop th then
   863                             is_theorem_bad_for_atps is_appropriate_prop th then
   868                            rest
   864                            (multis, unis)
   869                          else
   865                          else
   870                            (((fn () =>
   866                            let
       
   867                              val new =
       
   868                                (((fn () =>
   871                                  if name0 = "" then
   869                                  if name0 = "" then
   872                                    th |> backquote_thm
   870                                    th |> backquote_thm
   873                                  else
   871                                  else
   874                                    [Facts.extern ctxt facts name0,
   872                                    [Facts.extern ctxt facts name0,
   875                                     Name_Space.extern ctxt full_space name0,
   873                                     Name_Space.extern ctxt full_space name0,
   876                                     name0]
   874                                     name0]
   877                                    |> find_first check_thms
   875                                    |> find_first check_thms
   878                                    |> (fn SOME name =>
   876                                    |> (fn SOME name =>
   879                                           make_name reserved multi j name
   877                                           make_name reserved multi j name
   880                                         | NONE => "")),
   878                                         | NONE => "")),
   881                               locality_of_theorem global th),
   879                                 locality_of_theorem global th), th)
   882                               (multi, th)) :: rest)) ths
   880                            in
       
   881                              if multi then (new :: multis, unis)
       
   882                              else (multis, new :: unis)
       
   883                            end)) ths
   883             #> snd
   884             #> snd
   884           end)
   885           end)
   885   in
   886   in
   886     [] |> add_facts false fold local_facts (unnamed_locals @ named_locals)
   887     (* The single-name theorems go after the multiple-name ones, so that single
   887        |> add_facts true Facts.fold_static global_facts global_facts
   888        names are preferred when both are available. *)
       
   889     ([], []) |> add_facts false fold local_facts (unnamed_locals @ named_locals)
       
   890              |> add_facts true Facts.fold_static global_facts global_facts
       
   891              |> op @
   888   end
   892   end
   889 
       
   890 (* The single-name theorems go after the multiple-name ones, so that single
       
   891    names are preferred when both are available. *)
       
   892 fun rearrange_facts ctxt only =
       
   893   List.partition (fst o snd) #> op @ #> map (apsnd snd)
       
   894   #> (not (Config.get ctxt ignore_no_atp) andalso not only)
       
   895      ? filter_out (No_ATPs.member ctxt o snd)
       
   896 
   893 
   897 fun external_frees t =
   894 fun external_frees t =
   898   [] |> Term.add_frees t |> filter_out (can Name.dest_internal o fst)
   895   [] |> Term.add_frees t |> filter_out (can Name.dest_internal o fst)
   899 
   896 
   900 fun relevant_facts ctxt (threshold0, threshold1) max_relevant
   897 fun relevant_facts ctxt (threshold0, threshold1) max_relevant
   910       Logic.list_implies (hyp_ts |> filter_out (null o external_frees), concl_t)
   907       Logic.list_implies (hyp_ts |> filter_out (null o external_frees), concl_t)
   911       |> Object_Logic.atomize_term thy
   908       |> Object_Logic.atomize_term thy
   912     val ind_stmt_xs = external_frees ind_stmt
   909     val ind_stmt_xs = external_frees ind_stmt
   913     val facts =
   910     val facts =
   914       (if only then
   911       (if only then
   915          maps (map (fn ((name, loc), th) => ((K name, loc), (true, th)))
   912          maps (map (fn ((name, loc), th) => ((K name, loc), th))
   916                o fact_from_ref ctxt reserved chained_ths) add
   913                o fact_from_ref ctxt reserved chained_ths) add
   917        else
   914        else
   918          all_facts ctxt reserved false is_appropriate_prop add_ths chained_ths)
   915          all_facts ctxt reserved false is_appropriate_prop add_ths chained_ths)
   919       |> Config.get ctxt instantiate_inducts
   916       |> Config.get ctxt instantiate_inducts
   920          ? maps (instantiate_if_induct_rule ctxt ind_stmt ind_stmt_xs)
   917          ? maps (instantiate_if_induct_rule ctxt ind_stmt ind_stmt_xs)
   921       |> rearrange_facts ctxt only
   918       |> (not (Config.get ctxt ignore_no_atp) andalso not only)
       
   919          ? filter_out (No_ATPs.member ctxt o snd)
   922       |> uniquify
   920       |> uniquify
   923   in
   921   in
   924     trace_msg ctxt (fn () => "Considering " ^ string_of_int (length facts) ^
   922     trace_msg ctxt (fn () => "Considering " ^ string_of_int (length facts) ^
   925                              " facts");
   923                              " facts");
   926     (if only orelse threshold1 < 0.0 then
   924     (if only orelse threshold1 < 0.0 then