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 |