src/HOL/Tools/Sledgehammer/sledgehammer_filter_mash.ML
changeset 48303 f1d135d0ea69
parent 48302 6cf5e58f1185
child 48304 50e64af9c829
equal deleted inserted replaced
48302:6cf5e58f1185 48303:f1d135d0ea69
    12   type fact_override = Sledgehammer_Fact.fact_override
    12   type fact_override = Sledgehammer_Fact.fact_override
    13   type params = Sledgehammer_Provers.params
    13   type params = Sledgehammer_Provers.params
    14   type relevance_fudge = Sledgehammer_Provers.relevance_fudge
    14   type relevance_fudge = Sledgehammer_Provers.relevance_fudge
    15   type prover_result = Sledgehammer_Provers.prover_result
    15   type prover_result = Sledgehammer_Provers.prover_result
    16 
    16 
    17   val fact_name_of : string -> string
    17   val escape_meta : string -> string
       
    18   val escape_metas : string list -> string
    18   val all_non_tautological_facts_of :
    19   val all_non_tautological_facts_of :
    19     theory -> status Termtab.table -> fact list
    20     theory -> status Termtab.table -> fact list
    20   val theory_ord : theory * theory -> order
    21   val theory_ord : theory * theory -> order
    21   val thm_ord : thm * thm -> order
    22   val thm_ord : thm * thm -> order
    22   val thms_by_thy : ('a * thm) list -> (string * thm list) list
    23   val thy_facts_from_thms : ('a * thm) list -> string list Symtab.table
    23   val has_thy : theory -> thm -> bool
    24   val has_thy : theory -> thm -> bool
    24   val parent_facts : (string * thm list) list -> theory -> string list
    25   val parent_facts : theory -> string list Symtab.table -> string list
    25   val features_of : theory -> status -> term list -> string list
    26   val features_of : theory -> status -> term list -> string list
    26   val isabelle_dependencies_of : string list -> thm -> string list
    27   val isabelle_dependencies_of : string list -> thm -> string list
    27   val goal_of_thm : theory -> thm -> thm
    28   val goal_of_thm : theory -> thm -> thm
    28   val run_prover : Proof.context -> params -> fact list -> thm -> prover_result
    29   val run_prover : Proof.context -> params -> fact list -> thm -> prover_result
    29   val generate_accessibility : Proof.context -> theory -> bool -> string -> unit
    30   val generate_accessibility : Proof.context -> theory -> bool -> string -> unit
    78   else
    79   else
    79     (* fixed width, in case more digits follow *)
    80     (* fixed width, in case more digits follow *)
    80     "\\" ^ stringN_of_int 3 (Char.ord c)
    81     "\\" ^ stringN_of_int 3 (Char.ord c)
    81 
    82 
    82 val escape_meta = String.translate escape_meta_char
    83 val escape_meta = String.translate escape_meta_char
    83 
    84 val escape_metas = map escape_meta #> space_implode " "
    84 val thy_prefix = "y_"
    85 
    85 
    86 val thy_feature_prefix = "y_"
    86 val fact_name_of = escape_meta
    87 
    87 val thy_name_of = prefix thy_prefix o escape_meta
    88 val thy_feature_name_of = prefix thy_feature_prefix
    88 val const_name_of = prefix const_prefix o escape_meta
    89 val const_name_of = prefix const_prefix
    89 val type_name_of = prefix type_const_prefix o escape_meta
    90 val type_name_of = prefix type_const_prefix
    90 val class_name_of = prefix class_prefix o escape_meta
    91 val class_name_of = prefix class_prefix
    91 
       
    92 val thy_name_of_thm = theory_of_thm #> Context.theory_name
       
    93 
    92 
    94 local
    93 local
    95 
    94 
    96 fun has_bool @{typ bool} = true
    95 fun has_bool @{typ bool} = true
    97   | has_bool (Type (_, Ts)) = exists has_bool Ts
    96   | has_bool (Type (_, Ts)) = exists has_bool Ts
   189   else if Theory.subthy (swap p) then GREATER
   188   else if Theory.subthy (swap p) then GREATER
   190   else EQUAL
   189   else EQUAL
   191 
   190 
   192 val thm_ord = theory_ord o pairself theory_of_thm
   191 val thm_ord = theory_ord o pairself theory_of_thm
   193 
   192 
   194 fun thms_by_thy ths =
   193 (* ### FIXME: optimize *)
   195   ths |> map (snd #> `thy_name_of_thm)
   194 fun thy_facts_from_thms ths =
       
   195   ths |> map (snd #> `(theory_of_thm #> Context.theory_name))
   196       |> AList.group (op =)
   196       |> AList.group (op =)
   197       |> sort (int_ord o pairself (length o Theory.ancestors_of o theory_of_thm
   197       |> sort (int_ord o pairself (length o Theory.ancestors_of o theory_of_thm
   198                                    o hd o snd))
   198                                    o hd o snd))
   199       |> map (apsnd (sort thm_ord))
   199       |> map (apsnd (sort (rev_order o thm_ord) #> map Thm.get_name_hint))
   200 
   200       |> Symtab.make
   201 fun has_thy thy th = (Context.theory_name thy = thy_name_of_thm th)
   201 
   202 
   202 fun has_thy thy th =
   203 fun add_last_thms thy_ths thy =
   203   Context.theory_name thy = Context.theory_name (theory_of_thm th)
   204   case AList.lookup (op =) thy_ths (Context.theory_name thy) of
   204 
   205     SOME (ths as _ :: _) => insert Thm.eq_thm (List.last ths)
   205 fun parent_facts thy thy_facts =
   206   | _ => add_parent_thms thy_ths thy
   206   let
   207 and add_parent_thms thy_ths thy =
   207     fun add_last thy =
   208   fold (add_last_thms thy_ths) (Theory.parents_of thy)
   208       case Symtab.lookup thy_facts (Context.theory_name thy) of
   209 
   209         SOME (last_fact :: _) => insert (op =) last_fact
   210 fun parent_facts thy_ths thy =
   210       | _ => add_parent thy
   211   add_parent_thms thy_ths thy []
   211     and add_parent thy = fold add_last (Theory.parents_of thy)
   212   |> map (fact_name_of o Thm.get_name_hint)
   212   in add_parent thy [] end
   213 
   213 
   214 fun is_exists (s, _) = (s = @{const_name Ex} orelse s = @{const_name Ex1})
   214 fun is_exists (s, _) = (s = @{const_name Ex} orelse s = @{const_name Ex1})
   215 
   215 
   216 val term_max_depth = 1
   216 val term_max_depth = 1
   217 val type_max_depth = 1
   217 val type_max_depth = 1
   218 
   218 
   219 (* TODO: Generate type classes for types? *)
   219 (* TODO: Generate type classes for types? *)
   220 fun features_of thy status ts =
   220 fun features_of thy status ts =
   221   thy_name_of (Context.theory_name thy) ::
   221   thy_feature_name_of (Context.theory_name thy) ::
   222   interesting_terms_types_and_classes term_max_depth type_max_depth ts
   222   interesting_terms_types_and_classes term_max_depth type_max_depth ts
   223   |> exists (not o is_lambda_free) ts ? cons "lambdas"
   223   |> exists (not o is_lambda_free) ts ? cons "lambdas"
   224   |> exists (exists_Const is_exists) ts ? cons "skolems"
   224   |> exists (exists_Const is_exists) ts ? cons "skolems"
   225   |> exists (not o is_fo_term thy) ts ? cons "ho"
   225   |> exists (not o is_fo_term thy) ts ? cons "ho"
   226   |> (case status of
   226   |> (case status of
   231       | Elim => cons "elim"
   231       | Elim => cons "elim"
   232       | Simp => cons "simp"
   232       | Simp => cons "simp"
   233       | Def => cons "def")
   233       | Def => cons "def")
   234 
   234 
   235 fun isabelle_dependencies_of all_facts =
   235 fun isabelle_dependencies_of all_facts =
   236   thms_in_proof (SOME all_facts)
   236   thms_in_proof (SOME all_facts) #> sort string_ord
   237   #> map fact_name_of #> sort string_ord
       
   238 
   237 
   239 val freezeT = Type.legacy_freeze_type
   238 val freezeT = Type.legacy_freeze_type
   240 
   239 
   241 fun freeze (t $ u) = freeze t $ freeze u
   240 fun freeze (t $ u) = freeze t $ freeze u
   242   | freeze (Abs (s, T, t)) = Abs (s, freezeT T, freeze t)
   241   | freeze (Abs (s, T, t)) = Abs (s, freezeT T, freeze t)
   256     val prover =
   255     val prover =
   257       Sledgehammer_Minimize.get_minimizing_prover ctxt
   256       Sledgehammer_Minimize.get_minimizing_prover ctxt
   258           Sledgehammer_Provers.Normal (hd provers)
   257           Sledgehammer_Provers.Normal (hd provers)
   259   in prover params (K (K (K ""))) problem end
   258   in prover params (K (K (K ""))) problem end
   260 
   259 
       
   260 (* ###
       
   261 fun compute_accessibility thy thy_facts =
       
   262   let
       
   263     fun add_facts (f :: fs) prevs = (f, prevs) :: add_facts fs [th]
       
   264     fun add_thy facts =
       
   265       let
       
   266         val thy = theory_of_thm (hd facts)
       
   267         val parents = parent_facts thy_facts thy
       
   268       in add_thms facts parents end
       
   269   in fold (add_thy o snd) thy_facts end
       
   270 *)
       
   271 
       
   272 fun accessibility_of thy thy_facts =
       
   273   case Symtab.lookup thy_facts (Context.theory_name thy) of
       
   274     SOME (fact :: _) => [fact]
       
   275   | _ => parent_facts thy thy_facts
       
   276 
       
   277 fun theory_of_fact thy fact =
       
   278   Context.this_theory thy (hd (Long_Name.explode fact))
       
   279 
   261 fun generate_accessibility ctxt thy include_thy file_name =
   280 fun generate_accessibility ctxt thy include_thy file_name =
   262   let
   281   let
   263     val path = file_name |> Path.explode
   282     val path = file_name |> Path.explode
   264     val _ = File.write path ""
   283     val _ = File.write path ""
   265     val css_table = clasimpset_rule_table_of ctxt
   284     fun do_fact fact prevs =
   266     fun do_thm th prevs =
       
   267       let
   285       let
   268         val s = th ^ ": " ^ space_implode " " prevs ^ "\n"
   286         val s = escape_meta fact ^ ": " ^ escape_metas prevs ^ "\n"
   269         val _ = File.append path s
   287         val _ = File.append path s
   270       in [th] end
   288       in [fact] end
   271     val thy_ths =
   289     val thy_facts =
   272       all_non_tautological_facts_of thy css_table
   290       all_non_tautological_facts_of thy Termtab.empty
   273       |> not include_thy ? filter_out (has_thy thy o snd)
   291       |> not include_thy ? filter_out (has_thy thy o snd)
   274       |> thms_by_thy
   292       |> thy_facts_from_thms
   275     fun do_thy ths =
   293     fun do_thy facts =
   276       let
   294       let
   277         val thy = theory_of_thm (hd ths)
   295         val thy = theory_of_fact thy (hd facts)
   278         val parents = parent_facts thy_ths thy
   296         val parents = parent_facts thy thy_facts
   279         val ths = ths |> map (fact_name_of o Thm.get_name_hint)
   297       in fold do_fact facts parents; () end
   280       in fold do_thm ths parents; () end
   298   in Symtab.fold (fn (_, facts) => K (do_thy facts)) thy_facts () end
   281   in List.app (do_thy o snd) thy_ths end
       
   282 
   299 
   283 fun generate_features ctxt thy include_thy file_name =
   300 fun generate_features ctxt thy include_thy file_name =
   284   let
   301   let
   285     val path = file_name |> Path.explode
   302     val path = file_name |> Path.explode
   286     val _ = File.write path ""
   303     val _ = File.write path ""
   290       |> not include_thy ? filter_out (has_thy thy o snd)
   307       |> not include_thy ? filter_out (has_thy thy o snd)
   291     fun do_fact ((_, (_, status)), th) =
   308     fun do_fact ((_, (_, status)), th) =
   292       let
   309       let
   293         val name = Thm.get_name_hint th
   310         val name = Thm.get_name_hint th
   294         val feats = features_of (theory_of_thm th) status [prop_of th]
   311         val feats = features_of (theory_of_thm th) status [prop_of th]
   295         val s = fact_name_of name ^ ": " ^ space_implode " " feats ^ "\n"
   312         val s = escape_meta name ^ ": " ^ escape_metas feats ^ "\n"
   296       in File.append path s end
   313       in File.append path s end
   297   in List.app do_fact facts end
   314   in List.app do_fact facts end
   298 
   315 
   299 fun generate_isa_dependencies ctxt thy include_thy file_name =
   316 fun generate_isa_dependencies ctxt thy include_thy file_name =
   300   let
   317   let
   301     val path = file_name |> Path.explode
   318     val path = file_name |> Path.explode
   302     val _ = File.write path ""
   319     val _ = File.write path ""
   303     val css_table = clasimpset_rule_table_of ctxt
       
   304     val ths =
   320     val ths =
   305       all_non_tautological_facts_of thy css_table
   321       all_non_tautological_facts_of thy Termtab.empty
   306       |> not include_thy ? filter_out (has_thy thy o snd)
   322       |> not include_thy ? filter_out (has_thy thy o snd)
   307       |> map snd
   323       |> map snd
   308     val all_names = ths |> map Thm.get_name_hint
   324     val all_names = ths |> map Thm.get_name_hint
   309     fun do_thm th =
   325     fun do_thm th =
   310       let
   326       let
   311         val name = Thm.get_name_hint th
   327         val name = Thm.get_name_hint th
   312         val deps = isabelle_dependencies_of all_names th
   328         val deps = isabelle_dependencies_of all_names th
   313         val s = fact_name_of name ^ ": " ^ space_implode " " deps ^ "\n"
   329         val s = escape_meta name ^ ": " ^ escape_metas deps ^ "\n"
   314       in File.append path s end
   330       in File.append path s end
   315   in List.app do_thm ths end
   331   in List.app do_thm ths end
   316 
   332 
   317 fun generate_atp_dependencies ctxt (params as {provers, max_facts, ...}) thy
   333 fun generate_atp_dependencies ctxt (params as {provers, max_facts, ...}) thy
   318                               include_thy file_name =
   334                               include_thy file_name =
   319   let
   335   let
   320     val path = file_name |> Path.explode
   336     val path = file_name |> Path.explode
   321     val _ = File.write path ""
   337     val _ = File.write path ""
   322     val css_table = clasimpset_rule_table_of ctxt
       
   323     val facts =
   338     val facts =
   324       all_non_tautological_facts_of thy css_table
   339       all_non_tautological_facts_of thy Termtab.empty
   325       |> not include_thy ? filter_out (has_thy thy o snd)
   340       |> not include_thy ? filter_out (has_thy thy o snd)
   326     val ths = facts |> map snd
   341     val ths = facts |> map snd
   327     val all_names = ths |> map Thm.get_name_hint
   342     val all_names = ths |> map Thm.get_name_hint
   328     fun is_dep dep (_, th) = fact_name_of (Thm.get_name_hint th) = dep
   343     fun is_dep dep (_, th) = Thm.get_name_hint th = dep
   329     fun add_isa_dep facts dep accum =
   344     fun add_isa_dep facts dep accum =
   330       if exists (is_dep dep) accum then
   345       if exists (is_dep dep) accum then
   331         accum
   346         accum
   332       else case find_first (is_dep dep) facts of
   347       else case find_first (is_dep dep) facts of
   333         SOME ((name, status), th) => accum @ [((name, status), th)]
   348         SOME ((name, status), th) => accum @ [((name, status), th)]
   334       | NONE => accum (* shouldn't happen *)
   349       | NONE => accum (* shouldn't happen *)
   335     fun fix_name ((_, stature), th) =
   350     fun fix_name ((_, stature), th) =
   336       ((fn () => th |> Thm.get_name_hint |> fact_name_of, stature), th)
   351       ((fn () => th |> Thm.get_name_hint, stature), th)
   337     fun do_thm th =
   352     fun do_thm th =
   338       let
   353       let
   339         val name = Thm.get_name_hint th
   354         val name = Thm.get_name_hint th
   340         val goal = goal_of_thm thy th
   355         val goal = goal_of_thm thy th
   341         val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal ctxt goal 1
   356         val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal ctxt goal 1
   356               case run_prover ctxt params facts goal of
   371               case run_prover ctxt params facts goal of
   357                 {outcome = NONE, used_facts, ...} =>
   372                 {outcome = NONE, used_facts, ...} =>
   358                 used_facts |> map fst |> sort string_ord
   373                 used_facts |> map fst |> sort string_ord
   359               | _ => isa_deps
   374               | _ => isa_deps
   360             end
   375             end
   361         val s = fact_name_of name ^ ": " ^ space_implode " " deps ^ "\n"
   376         val s = escape_meta name ^ ": " ^ escape_metas deps ^ "\n"
   362       in File.append path s end
   377       in File.append path s end
   363   in List.app do_thm ths end
   378   in List.app do_thm ths end
   364 
   379 
   365 
   380 
   366 (*** Low-level communication with MaSh ***)
   381 (*** Low-level communication with MaSh ***)
   367 
   382 
   368 fun mash_RESET () = (warning "MaSh RESET"; File.rm (mk_path model_file))
   383 fun mash_RESET () = (warning "MaSh RESET"; File.rm (mk_path model_file))
   369 
   384 
   370 fun mash_ADD fact access feats deps =
   385 fun mash_ADD fact access feats deps =
   371   warning ("MaSh ADD " ^ fact ^ ": " ^ space_implode " " access ^ "; " ^
   386   warning ("MaSh ADD " ^ fact ^ ": " ^ escape_metas access ^ "; " ^
   372            space_implode " " feats ^ "; " ^ space_implode " " deps)
   387            escape_metas feats ^ "; " ^ escape_metas deps)
   373 
   388 
   374 fun mash_DEL facts feats =
   389 fun mash_DEL facts feats =
   375   warning ("MaSh DEL " ^ space_implode " " facts ^ "; " ^
   390   warning ("MaSh DEL " ^ escape_metas facts ^ "; " ^ escape_metas feats)
   376            space_implode " " feats)
       
   377 
   391 
   378 fun mash_SUGGEST access feats =
   392 fun mash_SUGGEST access feats =
   379   (warning ("MaSh SUGGEST " ^ space_implode " " access ^ "; " ^
   393   (warning ("MaSh SUGGEST " ^ escape_metas access ^ "; " ^ escape_metas feats);
   380             space_implode " " feats);
       
   381    [])
   394    [])
   382 
   395 
   383 
   396 
   384 (*** High-level communication with MaSh ***)
   397 (*** High-level communication with MaSh ***)
   385 
   398 
   420     end
   433     end
   421 
   434 
   422 fun mash_save ({fresh, completed_thys, thy_facts} : mash_state) =
   435 fun mash_save ({fresh, completed_thys, thy_facts} : mash_state) =
   423   let
   436   let
   424     val path = mk_path state_file
   437     val path = mk_path state_file
   425     val comp_line = (completed_thys |> Symtab.keys |> space_implode " ") ^ "\n"
   438     val comp_line = (completed_thys |> Symtab.keys |> escape_metas) ^ "\n"
   426     fun fact_line_for (thy, facts) = space_implode " " (thy :: facts) ^ "\n"
   439     fun fact_line_for (thy, facts) = escape_metas (thy :: facts) ^ "\n"
   427   in
   440   in
   428     File.write path (string_of_int fresh ^ "\n" ^ comp_line);
   441     File.write path (string_of_int fresh ^ "\n" ^ comp_line);
   429     Symtab.fold (fn thy_fact => fn () =>
   442     Symtab.fold (fn thy_fact => fn () =>
   430                     File.append path (fact_line_for thy_fact)) thy_facts
   443                     File.append path (fact_line_for thy_fact)) thy_facts
   431   end
   444   end
   448 
   461 
   449 end
   462 end
   450 
   463 
   451 fun mash_can_suggest_facts () =
   464 fun mash_can_suggest_facts () =
   452   not (Symtab.is_empty (#thy_facts (mash_value ())))
   465   not (Symtab.is_empty (#thy_facts (mash_value ())))
   453 
       
   454 fun accessibility_of thy thy_facts =
       
   455   let
       
   456     val _ = 0
       
   457   in
       
   458     [] (*###*)
       
   459   end
       
   460 
   466 
   461 fun mash_suggest_facts ctxt params prover max_facts hyp_ts concl_t facts =
   467 fun mash_suggest_facts ctxt params prover max_facts hyp_ts concl_t facts =
   462   let
   468   let
   463     val thy = Proof_Context.theory_of ctxt
   469     val thy = Proof_Context.theory_of ctxt
   464     val access = accessibility_of thy (#thy_facts (mash_value ()))
   470     val access = accessibility_of thy (#thy_facts (mash_value ()))
   477   mash_change (fn {fresh, completed_thys, thy_facts} =>
   483   mash_change (fn {fresh, completed_thys, thy_facts} =>
   478     let
   484     let
   479       val fact = fresh_fact_prefix ^ string_of_int fresh
   485       val fact = fresh_fact_prefix ^ string_of_int fresh
   480       val access = accessibility_of thy thy_facts
   486       val access = accessibility_of thy thy_facts
   481       val feats = features_of thy General [t]
   487       val feats = features_of thy General [t]
   482       val deps = ths |> map (fact_name_of o Thm.get_name_hint)
   488       val deps = ths |> map Thm.get_name_hint
   483     in
   489     in
   484       mash_ADD fact access feats deps;
   490       mash_ADD fact access feats deps;
   485       {fresh = fresh + 1, completed_thys = completed_thys,
   491       {fresh = fresh + 1, completed_thys = completed_thys,
   486        thy_facts = thy_facts}
   492        thy_facts = thy_facts}
   487     end)
   493     end)