src/HOL/TPTP/mash_export.ML
author blanchet
Wed, 18 Jul 2012 08:44:04 +0200
changeset 48324 3ee5b5589402
parent 48321 c552d7f1720b
child 48333 2250197977dc
permissions -rw-r--r--
speed up tautology/metaness check

(*  Title:      HOL/TPTP/mash_export.ML
    Author:     Jasmin Blanchette, TU Muenchen
    Copyright   2012

Export Isabelle theory information for MaSh (Machine-learning for Sledgehammer).
*)

signature MASH_EXPORT =
sig
  type params = Sledgehammer_Provers.params

  val generate_accessibility : theory -> bool -> string -> unit
  val generate_features :
    Proof.context -> string -> theory -> bool -> string -> unit
  val generate_isa_dependencies :
    theory -> bool -> string -> unit
  val generate_prover_dependencies :
    Proof.context -> params -> theory -> bool -> string -> unit
  val generate_commands : Proof.context -> string -> theory -> string -> unit
  val generate_iter_suggestions :
    Proof.context -> params -> theory -> int -> string -> unit
end;

structure MaSh_Export : MASH_EXPORT =
struct

open Sledgehammer_Fact
open Sledgehammer_Filter_Iter
open Sledgehammer_Filter_MaSh

fun thy_map_from_facts ths =
  ths |> sort (thm_ord o swap o pairself snd)
      |> map (snd #> `(theory_of_thm #> Context.theory_name))
      |> AList.coalesce (op =)
      |> map (apsnd (map Thm.get_name_hint))

fun has_thy thy th =
  Context.theory_name thy = Context.theory_name (theory_of_thm th)

fun parent_facts thy thy_map =
  let
    fun add_last thy =
      case AList.lookup (op =) thy_map (Context.theory_name thy) of
        SOME (last_fact :: _) => insert (op =) last_fact
      | _ => add_parent thy
    and add_parent thy = fold add_last (Theory.parents_of thy)
  in add_parent thy [] end

val thy_name_of_fact = hd o Long_Name.explode
fun thy_of_fact thy = Context.this_theory thy o thy_name_of_fact

val all_names =
  filter_out (is_likely_tautology_or_too_meta)
  #> map (rpair () o Thm.get_name_hint) #> Symtab.make

fun generate_accessibility thy include_thy file_name =
  let
    val path = file_name |> Path.explode
    val _ = File.write path ""
    fun do_fact fact prevs =
      let
        val s = escape_meta fact ^ ": " ^ escape_metas prevs ^ "\n"
        val _ = File.append path s
      in [fact] end
    val thy_map =
      all_facts_of thy Termtab.empty
      |> not include_thy ? filter_out (has_thy thy o snd)
      |> thy_map_from_facts
    fun do_thy facts =
      let
        val thy = thy_of_fact thy (hd facts)
        val parents = parent_facts thy thy_map
      in fold do_fact facts parents; () end
  in fold_rev (fn (_, facts) => K (do_thy facts)) thy_map () end

fun generate_features ctxt prover thy include_thy file_name =
  let
    val path = file_name |> Path.explode
    val _ = File.write path ""
    val css_table = clasimpset_rule_table_of ctxt
    val facts =
      all_facts_of thy css_table
      |> not include_thy ? filter_out (has_thy thy o snd)
    fun do_fact ((_, (_, status)), th) =
      let
        val name = Thm.get_name_hint th
        val feats =
          features_of ctxt prover (theory_of_thm th) status [prop_of th]
        val s = escape_meta name ^ ": " ^ escape_metas feats ^ "\n"
      in File.append path s end
  in List.app do_fact facts end

fun generate_isa_dependencies thy include_thy file_name =
  let
    val path = file_name |> Path.explode
    val _ = File.write path ""
    val ths =
      all_facts_of thy Termtab.empty
      |> not include_thy ? filter_out (has_thy thy o snd)
      |> map snd
    val all_names = all_names ths
    fun do_thm th =
      let
        val name = Thm.get_name_hint th
        val deps = isabelle_dependencies_of all_names th
        val s = escape_meta name ^ ": " ^ escape_metas deps ^ "\n"
      in File.append path s end
  in List.app do_thm ths end

fun generate_prover_dependencies ctxt (params as {provers, max_facts, ...}) thy
                                 include_thy file_name =
  let
    val path = file_name |> Path.explode
    val _ = File.write path ""
    val prover = hd provers
    val facts =
      all_facts_of thy Termtab.empty
      |> not include_thy ? filter_out (has_thy thy o snd)
    val ths = facts |> map snd
    val all_names = all_names ths
    fun is_dep dep (_, th) = Thm.get_name_hint th = dep
    fun add_isa_dep facts dep accum =
      if exists (is_dep dep) accum then
        accum
      else case find_first (is_dep dep) facts of
        SOME ((name, status), th) => accum @ [((name, status), th)]
      | NONE => accum (* shouldn't happen *)
    fun fix_name ((_, stature), th) =
      ((fn () => th |> Thm.get_name_hint, stature), th)
    fun do_thm th =
      let
        val name = Thm.get_name_hint th
        val goal = goal_of_thm thy th
        val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal ctxt goal 1
        val deps =
          case isabelle_dependencies_of all_names th of
            [] => []
          | isa_dep as [_] => isa_dep (* can hardly beat that *)
          | isa_deps =>
            let
              val facts =
                facts |> filter (fn (_, th') => thm_ord (th', th) = LESS)
              val facts =
                facts |> iterative_relevant_facts ctxt params prover
                             (the max_facts) NONE hyp_ts concl_t
                      |> fold (add_isa_dep facts) isa_deps
                      |> map fix_name
            in
              case run_prover_for_mash ctxt params prover facts goal of
                {outcome = NONE, used_facts, ...} =>
                used_facts |> map fst |> sort string_ord
              | _ => isa_deps
            end
        val s = escape_meta name ^ ": " ^ escape_metas deps ^ "\n"
      in File.append path s end
  in List.app do_thm ths end

fun generate_commands ctxt prover thy file_name =
  let
    val path = file_name |> Path.explode
    val _ = File.write path ""
    val css_table = Sledgehammer_Fact.clasimpset_rule_table_of ctxt
    val facts = all_facts_of thy css_table
    val (new_facts, old_facts) =
      facts |> List.partition (has_thy thy o snd)
            |>> sort (thm_ord o pairself snd)
    val ths = facts |> map snd
    val all_names = all_names ths
    fun do_fact ((_, (_, status)), th) prevs =
      let
        val name = Thm.get_name_hint th
        val feats = features_of ctxt prover thy status [prop_of th]
        val deps = isabelle_dependencies_of all_names th
        val kind = Thm.legacy_get_kind th
        val core = escape_metas prevs ^ "; " ^ escape_metas feats
        val query = if kind <> "" then "? " ^ core ^ "\n" else ""
        val update =
          "! " ^ escape_meta name ^ ": " ^ core ^ "; " ^
          escape_metas deps ^ "\n"
        val _ = File.append path (query ^ update)
      in [name] end
    val thy_map = old_facts |> thy_map_from_facts
    val parents = parent_facts thy thy_map
  in fold do_fact new_facts parents; () end

fun generate_iter_suggestions ctxt (params as {provers, ...}) thy max_relevant
                              file_name =
  let
    val path = file_name |> Path.explode
    val _ = File.write path ""
    val prover = hd provers
    val css_table = Sledgehammer_Fact.clasimpset_rule_table_of ctxt
    val facts = all_facts_of thy css_table
    val (new_facts, old_facts) =
      facts |> List.partition (has_thy thy o snd)
            |>> sort (thm_ord o pairself snd)
    fun do_fact (fact as (_, th)) old_facts =
      let
        val name = Thm.get_name_hint th
        val goal = goal_of_thm thy th
        val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal ctxt goal 1
        val kind = Thm.legacy_get_kind th
        val _ =
          if kind <> "" then
            let
              val suggs =
                old_facts
                |> Sledgehammer_Filter_Iter.iterative_relevant_facts ctxt params
                                prover max_relevant NONE hyp_ts concl_t
                |> map (fn ((name, _), _) => name ())
                |> sort string_ord
              val s = escape_meta name ^ ": " ^ escape_metas suggs ^ "\n"
            in File.append path s end
          else
            ()
      in fact :: old_facts end
  in fold do_fact new_facts old_facts; () end

end;