src/Pure/Isar/find_theorems.ML
changeset 16964 6a25e42eaff5
parent 16895 df67fc190e06
child 17106 2bd6c20cdda1
equal deleted inserted replaced
16963:32626fb8ae49 16964:6a25e42eaff5
    76   otherwise the default ordering ("by package") is used.
    76   otherwise the default ordering ("by package") is used.
    77 *)
    77 *)
    78 
    78 
    79 
    79 
    80 (* matching theorems *)
    80 (* matching theorems *)
    81 
    81     
    82 fun is_matching_thm (extract_thms, extract_term) ctxt po obj thm =
    82 fun is_nontrivial sg = is_Const o head_of o ObjectLogic.drop_judgment sg;
       
    83 
       
    84 (*extract terms from term_src, refine them to the parts that concern us,
       
    85   if po try match them against obj else vice versa.
       
    86   trivial matches are ignored.
       
    87   returns: smallest substitution size*)
       
    88 fun is_matching_thm (extract_terms, refine_term) ctxt po obj term_src =
    83   let
    89   let
    84     val sg = ProofContext.sign_of ctxt;
    90     val sg = ProofContext.sign_of ctxt;
    85     val tsig = Sign.tsig_of sg;
    91     val tsig = Sign.tsig_of sg;
    86 
    92 
    87     val is_nontrivial = is_Const o head_of o ObjectLogic.drop_judgment sg;
       
    88 
       
    89     fun matches pat =
    93     fun matches pat =
    90       is_nontrivial pat andalso
    94       is_nontrivial sg pat andalso
    91       Pattern.matches tsig (if po then (pat,obj) else (obj,pat));
    95       Pattern.matches tsig (if po then (pat,obj) else (obj,pat));
    92 
    96 
    93     fun substsize pat =
    97     fun substsize pat =
    94       let 
    98       let 
    95         val (_,subst) = Pattern.match tsig (if po then (pat,obj) else (obj,pat))
    99         val (_,subst) = Pattern.match tsig (if po then (pat,obj) else (obj,pat))
    96       in Vartab.foldl (op + o apsnd (size_of_term o snd o snd)) (0, subst)
   100       in Vartab.foldl (op + o apsnd (size_of_term o snd o snd)) (0, subst)
    97       end;
   101       end;
    98 
   102 
    99     fun bestmatch [] = NONE
   103     fun bestmatch [] = NONE
   100      |  bestmatch (x :: xs) = SOME (nprems_of thm, foldl Int.min x xs);
   104      |  bestmatch (x :: xs) = SOME (foldl Int.min x xs);
   101 
   105 
   102     val match_thm = matches o extract_term o Thm.prop_of;
   106     val match_thm = matches o refine_term;
   103   in
   107   in
   104     map (substsize o extract_term o Thm.prop_of) 
   108     map (substsize o refine_term) 
   105         (List.filter match_thm (extract_thms thm)) |> bestmatch
   109         (List.filter match_thm (extract_terms term_src)) |> bestmatch
   106   end;
   110   end;
   107 
   111 
   108 
   112 
   109 (* filter_name *)
   113 (* filter_name *)
   110 
   114 
   121   then SOME (0,0) else NONE;
   125   then SOME (0,0) else NONE;
   122 
   126 
   123 
   127 
   124 (* filter intro/elim/dest rules *)
   128 (* filter intro/elim/dest rules *)
   125 
   129 
   126 local
   130 fun filter_dest ctxt goal (_,thm) =
   127 
   131   let
   128 (*elimination rule: conclusion is a Var which does not appear in the major premise*)
   132     val extract_dest =
   129 fun is_elim ctxt thm =
   133      (fn thm => if Thm.no_prems thm then [] else [prop_of thm],
   130   let
       
   131     val sg = ProofContext.sign_of ctxt;
       
   132     val prop = Thm.prop_of thm;
       
   133     val concl = ObjectLogic.drop_judgment sg (Logic.strip_imp_concl prop);
       
   134     val major_prem = Library.take (1, Logic.strip_imp_prems prop);
       
   135     val prem_vars = Drule.vars_of_terms major_prem;
       
   136   in
       
   137     not (null major_prem) andalso
       
   138     Term.is_Var concl andalso
       
   139     not (Term.dest_Var concl mem prem_vars)
       
   140   end;
       
   141 
       
   142 fun filter_elim_dest check_thm ctxt goal (_,thm) =
       
   143   let
       
   144     val extract_elim =
       
   145      (fn thm => if Thm.no_prems thm then [] else [thm],
       
   146       hd o Logic.strip_imp_prems);
   134       hd o Logic.strip_imp_prems);
   147     val prems = Logic.prems_of_goal goal 1;
   135     val prems = Logic.prems_of_goal goal 1;
   148 
   136 
   149     fun try_subst prem = is_matching_thm extract_elim ctxt true prem thm;
   137     fun try_subst prem = is_matching_thm extract_dest ctxt true prem thm;
   150     
   138     
   151     (*keep successful substitutions*)
   139     (*keep successful substitutions*)
   152     val ss = prems |> List.map try_subst 
   140     val ss = prems |> List.map try_subst 
   153              |> List.filter isSome 
   141              |> List.filter isSome 
   154              |> List.map (#2 o valOf);
   142              |> List.map valOf;
   155   in
   143   in
   156     (*if possible, keep best substitution (one with smallest size)*)
   144     (*if possible, keep best substitution (one with smallest size)*)
   157     (*elim and dest rules always have assumptions, so an elim with one 
   145     (*dest rules always have assumptions, so a dest with one 
   158       assumption is as good as an intro rule with none*)
   146       assumption is as good as an intro rule with none*)
   159     if check_thm ctxt thm andalso not (null ss) 
   147     if not (null ss) 
   160     then SOME (nprems_of thm - 1, foldl Int.min (hd ss) (tl ss)) else NONE
   148     then SOME (nprems_of thm - 1, foldl Int.min (hd ss) (tl ss)) else NONE
   161   end;
   149   end;
   162 
   150 
   163 in
       
   164 
       
   165 fun filter_intro ctxt goal (_,thm) =
   151 fun filter_intro ctxt goal (_,thm) =
   166   let
   152   let
   167     val extract_intro = (single, Logic.strip_imp_concl);
   153     val extract_intro = (single o prop_of, Logic.strip_imp_concl);
   168     val concl = Logic.concl_of_goal goal 1;
   154     val concl = Logic.concl_of_goal goal 1;
   169   in
   155     val ss = is_matching_thm extract_intro ctxt true concl thm;
   170     is_matching_thm extract_intro ctxt true concl thm
   156   in
   171   end;
   157     if is_some ss then SOME (nprems_of thm, valOf ss) else NONE
   172 
   158   end;
   173 fun filter_elim ctxt = filter_elim_dest is_elim ctxt;
   159 
   174 fun filter_dest ctxt = filter_elim_dest (not oo is_elim) ctxt;
   160 fun filter_elim ctxt goal (_,thm) =
   175 
   161   if not (Thm.no_prems thm) then
   176 end;
   162     let
       
   163       val rule = prop_of thm;
       
   164       val prems = Logic.prems_of_goal goal 1;
       
   165       val goal_concl = Logic.concl_of_goal goal 1;
       
   166       val rule_mp = (hd o Logic.strip_imp_prems) rule;
       
   167       val rule_concl = Logic.strip_imp_concl rule;
       
   168       fun combine t1 t2 = Const ("combine", dummyT --> dummyT) $ (t1 $ t2);
       
   169       val rule_tree = combine rule_mp rule_concl;
       
   170       fun goal_tree prem = (combine prem goal_concl);
       
   171       fun try_subst prem = 
       
   172         is_matching_thm (single, I) ctxt true (goal_tree prem) rule_tree;
       
   173       (*keep successful substitutions*)
       
   174       val ss = prems |> List.map try_subst 
       
   175                |> List.filter isSome 
       
   176                |> List.map valOf; 
       
   177     in
       
   178     (*elim rules always have assumptions, so an elim with one 
       
   179       assumption is as good as an intro rule with none*)
       
   180       if is_nontrivial (ProofContext.sign_of ctxt) (Thm.major_prem_of thm) 
       
   181         andalso not (null ss)
       
   182       then SOME (nprems_of thm - 1, foldl Int.min (hd ss) (tl ss)) else NONE
       
   183     end
       
   184   else NONE
   177 
   185 
   178 
   186 
   179 (* filter_simp *)
   187 (* filter_simp *)
   180 
   188 
   181 fun filter_simp ctxt t (_,thm) =
   189 fun filter_simp ctxt t (_,thm) =
   182   let
   190   let
   183     val (_, {mk_rews = {mk, ...}, ...}) =
   191     val (_, {mk_rews = {mk, ...}, ...}) =
   184       MetaSimplifier.rep_ss (Simplifier.local_simpset_of ctxt);
   192       MetaSimplifier.rep_ss (Simplifier.local_simpset_of ctxt);
   185     val extract_simp = (mk, #1 o Logic.dest_equals o Logic.strip_imp_concl);
   193     val extract_simp = 
   186   in is_matching_thm extract_simp ctxt false t thm end;
   194       ((List.map prop_of) o mk, #1 o Logic.dest_equals o Logic.strip_imp_concl);
       
   195     val ss = is_matching_thm extract_simp ctxt false t thm
       
   196   in 
       
   197     if is_some ss then SOME (nprems_of thm, valOf ss) else NONE 
       
   198   end;
   187 
   199 
   188 
   200 
   189 (* filter_pattern *)
   201 (* filter_pattern *)
   190 
   202 
   191 fun filter_pattern ctxt pat (_, thm) =
   203 fun filter_pattern ctxt pat (_, thm) =
   224   let
   236   let
   225     fun eval_filters filters thm =
   237     fun eval_filters filters thm =
   226       map (fn f => f thm) filters |> List.foldl opt_add (SOME (0,0));
   238       map (fn f => f thm) filters |> List.foldl opt_add (SOME (0,0));
   227 
   239 
   228     (*filters return: (number of assumptions, substitution size) option, so
   240     (*filters return: (number of assumptions, substitution size) option, so
   229       sort (desc. in both cases) according to whether a theorem has assumptions,
   241       sort (desc. in both cases) according to number of assumptions first,
   230       then by the substitution size*)
   242       then by the substitution size*)
   231     fun thm_ord (((p0,s0),_),((p1,s1),_)) =
   243     fun thm_ord (((p0,s0),_),((p1,s1),_)) =
   232       prod_ord (int_ord o pairself (fn 0 => 0 | x => 1)) 
   244       prod_ord int_ord int_ord ((p1,s1),(p0,s0));
   233                int_ord ((p1,s1),(p0,s0));
       
   234 
   245 
   235     val processed = List.map (fn t => (eval_filters filters t, t)) thms;
   246     val processed = List.map (fn t => (eval_filters filters t, t)) thms;
   236     val filtered = List.filter (isSome o #1) processed;
   247     val filtered = List.filter (isSome o #1) processed;
   237   in
   248   in
   238     filtered |> List.map (apfst valOf) |> sort thm_ord |> map #2
   249     filtered |> List.map (apfst valOf) |> sort thm_ord |> map #2