added monomorphization option to Sledgehammer ATPs -- this looks promising but is still off by default
authorblanchet
Thu, 31 Mar 2011 11:16:52 +0200
changeset 42180 a6c141925a8a
parent 42179 24662b614fd4
child 42181 8f25605e646c
added monomorphization option to Sledgehammer ATPs -- this looks promising but is still off by default
NEWS
doc-src/Sledgehammer/sledgehammer.tex
src/HOL/Tools/SMT/smt_monomorph.ML
src/HOL/Tools/Sledgehammer/sledgehammer_atp_reconstruct.ML
src/HOL/Tools/Sledgehammer/sledgehammer_atp_translate.ML
src/HOL/Tools/Sledgehammer/sledgehammer_isar.ML
src/HOL/Tools/Sledgehammer/sledgehammer_minimize.ML
src/HOL/Tools/Sledgehammer/sledgehammer_provers.ML
src/HOL/Tools/Sledgehammer/sledgehammer_run.ML
--- a/NEWS	Thu Mar 31 11:16:51 2011 +0200
+++ b/NEWS	Thu Mar 31 11:16:52 2011 +0200
@@ -49,6 +49,7 @@
 * Sledgehammer:
   - sledgehammer available_provers ~> sledgehammer supported_provers
     INCOMPATIBILITY.
+  - Added "monomorphize" and "monomorphize_limit" options.
 
 * "try":
   - Added "simp:", "intro:", and "elim:" options.
--- a/doc-src/Sledgehammer/sledgehammer.tex	Thu Mar 31 11:16:51 2011 +0200
+++ b/doc-src/Sledgehammer/sledgehammer.tex	Thu Mar 31 11:16:52 2011 +0200
@@ -555,6 +555,19 @@
 filter. If the option is set to \textit{smart}, it is set to a value that was
 empirically found to be appropriate for the prover. A typical value would be
 300.
+
+\opfalse{monomorphize}{dont\_monomorphize}
+Specifies whether the relevant facts should be monomorphized---i.e., whether
+their type variables should be instantiated with relevant ground types.
+Monomorphization is always performed for SMT solvers, irrespective of this
+option. Monomorphization can simplify reasoning but also leads to larger fact
+bases, which can slow down the ATPs.
+
+\opdefault{monomorphize\_limit}{int}{\upshape 4}
+Specifies the maximum number of iterations for the monomorphization fixpoint
+construction. The higher this limit is, the more monomorphic instances are
+potentially generated.
+
 \end{enum}
 
 \subsection{Output Format}
--- a/src/HOL/Tools/SMT/smt_monomorph.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/SMT/smt_monomorph.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -28,8 +28,8 @@
 
 signature SMT_MONOMORPH =
 sig
-  val monomorph: (int * thm) list -> Proof.context ->
-    (int * thm) list * Proof.context
+  val monomorph: ('a * thm) list -> Proof.context ->
+    ('a * thm) list * Proof.context
 end
 
 structure SMT_Monomorph: SMT_MONOMORPH =
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_atp_reconstruct.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_atp_reconstruct.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -88,6 +88,8 @@
   #> raw_explode #> filter_out Symbol.is_blank #> parse_clause_formula_relation
   #> fst
 
+val unprefix_fact_number = space_implode "_" o tl o space_explode "_"
+
 fun repair_conjecture_shape_and_fact_names output conjecture_shape fact_names =
   if String.isSubstring set_ClauseFormulaRelationN output then
     let
@@ -100,7 +102,8 @@
         |> map (fn s => find_index (curry (op =) s) seq + 1)
       fun names_for_number j =
         j |> AList.lookup (op =) name_map |> these
-          |> map_filter (try (unprefix fact_prefix)) |> map unascii_of
+          |> map_filter (try (unascii_of o unprefix_fact_number
+                              o unprefix fact_prefix))
           |> map (fn name =>
                      (name, name |> find_first_in_list_vector fact_names |> the)
                      handle Option.Option =>
@@ -145,16 +148,19 @@
       "\nTo minimize the number of lemmas, try this: " ^
       Markup.markup Markup.sendback command ^ "."
 
-val vampire_fact_prefix = "f" (* grrr... *)
+val vampire_step_prefix = "f" (* grrr... *)
 
 fun resolve_fact fact_names ((_, SOME s)) =
-    (case strip_prefix_and_unascii fact_prefix s of
-       SOME s' => (case find_first_in_list_vector fact_names s' of
-                     SOME x => [(s', x)]
-                   | NONE => [])
+    (case try (unprefix fact_prefix) s of
+       SOME s' =>
+       let val s' = s' |> unprefix_fact_number |> unascii_of in
+         case find_first_in_list_vector fact_names s' of
+           SOME x => [(s', x)]
+         | NONE => []
+       end
      | NONE => [])
   | resolve_fact fact_names (num, NONE) =
-    case Int.fromString (perhaps (try (unprefix vampire_fact_prefix)) num) of
+    case Int.fromString (perhaps (try (unprefix vampire_step_prefix)) num) of
       SOME j =>
       if j > 0 andalso j <= Vector.length fact_names then
         Vector.sub (fact_names, j - 1)
@@ -233,7 +239,7 @@
 
 val raw_prefix = "X"
 val assum_prefix = "A"
-val fact_prefix = "F"
+val have_prefix = "F"
 
 fun resolve_conjecture conjecture_shape (num, s_opt) =
   let
@@ -847,7 +853,7 @@
               (l, subst, next_fact)
             else
               let
-                val l' = (prefix_for_depth depth fact_prefix, next_fact)
+                val l' = (prefix_for_depth depth have_prefix, next_fact)
               in (l', (l, l') :: subst, next_fact + 1) end
           val relabel_facts =
             apfst (maps (the_list o AList.lookup (op =) subst))
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_atp_translate.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_atp_translate.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -442,9 +442,13 @@
                 (atp_type_literals_for_types type_sys ctypes_sorts))
            (formula_for_combformula ctxt type_sys combformula)
 
-fun problem_line_for_fact ctxt prefix type_sys (formula as {name, kind, ...}) =
-  Fof (prefix ^ ascii_of name, kind, formula_for_fact ctxt type_sys formula,
-       NONE)
+(* Each fact is given a unique fact number to avoid name clashes (e.g., because
+   of monomorphization). The TPTP explicitly forbids name clashes, and some of
+   the remote provers might care. *)
+fun problem_line_for_fact ctxt prefix type_sys
+                          (j, formula as {name, kind, ...}) =
+  Fof (prefix ^ string_of_int j ^ "_" ^ ascii_of name, kind,
+       formula_for_fact ctxt type_sys formula, NONE)
 
 fun problem_line_for_class_rel_clause (ClassRelClause {name, subclass,
                                                        superclass, ...}) =
@@ -626,7 +630,8 @@
     (* Reordering these might or might not confuse the proof reconstruction
        code or the SPASS Flotter hack. *)
     val problem =
-      [(factsN, map (problem_line_for_fact ctxt fact_prefix type_sys) facts),
+      [(factsN, map (problem_line_for_fact ctxt fact_prefix type_sys)
+                    (0 upto length facts - 1 ~~ facts)),
        (class_relsN, map problem_line_for_class_rel_clause class_rel_clauses),
        (aritiesN, map problem_line_for_arity_clause arity_clauses),
        (helpersN, []),
@@ -638,7 +643,8 @@
     val helper_lines =
       get_helper_facts ctxt explicit_forall type_sys
                        (maps (map (#3 o dest_Fof) o snd) problem)
-      |>> map (problem_line_for_fact ctxt helper_prefix type_sys
+      |>> map (pair 0
+               #> problem_line_for_fact ctxt helper_prefix type_sys
                #> repair_problem_line thy explicit_forall type_sys const_tab)
       |> op @
     val (problem, pool) =
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_isar.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_isar.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -79,10 +79,12 @@
    ("verbose", "false"),
    ("overlord", "false"),
    ("blocking", "false"),
+   ("relevance_thresholds", "0.45 0.85"),
+   ("max_relevant", "smart"),
+   ("monomorphize", "false"),
+   ("monomorphize_limit", "4"),
    ("type_sys", "smart"),
    ("explicit_apply", "false"),
-   ("relevance_thresholds", "0.45 0.85"),
-   ("max_relevant", "smart"),
    ("isar_proof", "false"),
    ("isar_shrink_factor", "1")]
 
@@ -95,6 +97,7 @@
    ("quiet", "verbose"),
    ("no_overlord", "overlord"),
    ("non_blocking", "blocking"),
+   ("dont_monomorphize", "monomorphize"),
    ("partial_types", "full_types"),
    ("implicit_apply", "explicit_apply"),
    ("no_isar_proof", "isar_proof")]
@@ -233,6 +236,10 @@
     val blocking = auto orelse debug orelse lookup_bool "blocking"
     val provers = lookup_string "provers" |> space_explode " "
                   |> auto ? single o hd
+    val relevance_thresholds = lookup_real_pair "relevance_thresholds"
+    val max_relevant = lookup_int_option "max_relevant"
+    val monomorphize = lookup_bool "monomorphize"
+    val monomorphize_limit = lookup_int "monomorphize_limit"
     val type_sys =
       case (lookup_string "type_sys", lookup_bool "full_types") of
         ("tags", full_types) => Tags full_types
@@ -245,18 +252,18 @@
         else
           error ("Unknown type system: " ^ quote type_sys ^ ".")
     val explicit_apply = lookup_bool "explicit_apply"
-    val relevance_thresholds = lookup_real_pair "relevance_thresholds"
-    val max_relevant = lookup_int_option "max_relevant"
     val isar_proof = lookup_bool "isar_proof"
     val isar_shrink_factor = Int.max (1, lookup_int "isar_shrink_factor")
     val timeout = (if auto then NONE else lookup_time "timeout") |> the_timeout
     val expect = lookup_string "expect"
   in
     {debug = debug, verbose = verbose, overlord = overlord, blocking = blocking,
-     provers = provers, type_sys = type_sys, explicit_apply = explicit_apply,
-     relevance_thresholds = relevance_thresholds, max_relevant = max_relevant,
-     isar_proof = isar_proof, isar_shrink_factor = isar_shrink_factor,
-     timeout = timeout, expect = expect}
+     provers = provers, relevance_thresholds = relevance_thresholds,
+     max_relevant = max_relevant, monomorphize = monomorphize,
+     monomorphize_limit = monomorphize_limit, type_sys = type_sys,
+     explicit_apply = explicit_apply, isar_proof = isar_proof,
+     isar_shrink_factor = isar_shrink_factor, timeout = timeout,
+     expect = expect}
   end
 
 fun get_params auto ctxt = extract_params auto (default_raw_params ctxt)
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_minimize.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_minimize.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -42,8 +42,8 @@
 
 fun print silent f = if silent then () else Output.urgent_message (f ())
 
-fun test_facts ({debug, verbose, overlord, provers, type_sys, isar_proof,
-                 isar_shrink_factor, ...} : params)
+fun test_facts ({debug, verbose, overlord, provers, monomorphize_limit,
+                 type_sys, isar_proof, isar_shrink_factor, ...} : params)
         explicit_apply_opt silent (prover : prover) timeout i n state facts =
   let
     val thy = Proof.theory_of state
@@ -65,6 +65,7 @@
       {debug = debug, verbose = verbose, overlord = overlord, blocking = true,
        provers = provers, type_sys = type_sys, explicit_apply = explicit_apply,
        relevance_thresholds = (1.01, 1.01), max_relevant = NONE,
+       monomorphize = false, monomorphize_limit = monomorphize_limit,
        isar_proof = isar_proof, isar_shrink_factor = isar_shrink_factor,
        timeout = timeout, expect = ""}
     val facts =
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_provers.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_provers.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -21,10 +21,12 @@
      overlord: bool,
      blocking: bool,
      provers: string list,
+     relevance_thresholds: real * real,
+     max_relevant: int option,
+     monomorphize: bool,
+     monomorphize_limit: int,
      type_sys: type_system,
      explicit_apply: bool,
-     relevance_thresholds: real * real,
-     max_relevant: int option,
      isar_proof: bool,
      isar_shrink_factor: int,
      timeout: Time.time,
@@ -66,7 +68,6 @@
   val smt_iter_fact_frac : real Unsynchronized.ref
   val smt_iter_time_frac : real Unsynchronized.ref
   val smt_iter_min_msecs : int Unsynchronized.ref
-  val smt_monomorphize_limit : int Unsynchronized.ref
 
   val das_Tool : string
   val select_smt_solver : string -> Proof.context -> Proof.context
@@ -229,10 +230,12 @@
    overlord: bool,
    blocking: bool,
    provers: string list,
+   relevance_thresholds: real * real,
+   max_relevant: int option,
+   monomorphize: bool,
+   monomorphize_limit: int,
    type_sys: type_system,
    explicit_apply: bool,
-   relevance_thresholds: real * real,
-   max_relevant: int option,
    isar_proof: bool,
    isar_shrink_factor: int,
    timeout: Time.time,
@@ -333,13 +336,27 @@
         ({exec, required_execs, arguments, has_incomplete_mode, proof_delims,
           known_failures, explicit_forall, use_conjecture_for_hypotheses, ...}
           : atp_config)
-        ({debug, verbose, overlord, type_sys, explicit_apply, isar_proof,
-          isar_shrink_factor, timeout, ...} : params)
+        ({debug, verbose, overlord, monomorphize, monomorphize_limit, type_sys,
+          explicit_apply, isar_proof, isar_shrink_factor, timeout, ...}
+         : params)
         minimize_command ({state, goal, subgoal, facts, ...} : prover_problem) =
   let
     val ctxt = Proof.context_of state
     val (_, hyp_ts, concl_t) = strip_subgoal goal subgoal
-    val facts = facts |> map (atp_translated_fact ctxt)
+    fun monomorphize_facts facts =
+      let
+        val facts = facts |> map untranslated_fact
+        val indexed_facts =
+          (~1, goal) :: (0 upto length facts - 1 ~~ map snd facts)
+      in
+        ctxt |> Config.put SMT_Config.monomorph_limit monomorphize_limit
+             |> SMT_Monomorph.monomorph indexed_facts |> fst
+             |> sort (int_ord o pairself fst)
+             |> filter_out (curry (op =) ~1 o fst)
+             |> map (Untranslated_Fact o apfst (fst o nth facts))
+      end
+    val facts = facts |> monomorphize ? monomorphize_facts
+                      |> map (atp_translated_fact ctxt)
     val (dest_dir, problem_prefix) =
       if overlord then overlord_file_location_for_prover name
       else (Config.get ctxt dest_dir, Config.get ctxt problem_prefix)
@@ -513,9 +530,9 @@
 val smt_iter_fact_frac = Unsynchronized.ref 0.5
 val smt_iter_time_frac = Unsynchronized.ref 0.5
 val smt_iter_min_msecs = Unsynchronized.ref 5000
-val smt_monomorphize_limit = Unsynchronized.ref 4
 
-fun smt_filter_loop name ({debug, verbose, overlord, timeout, ...} : params)
+fun smt_filter_loop name ({debug, verbose, overlord, monomorphize_limit,
+                           timeout, ...} : params)
                     state i smt_filter =
   let
     val ctxt = Proof.context_of state
@@ -529,7 +546,7 @@
           else
             I)
       #> Config.put SMT_Config.infer_triggers (!smt_triggers)
-      #> Config.put SMT_Config.monomorph_limit (!smt_monomorphize_limit)
+      #> Config.put SMT_Config.monomorph_limit monomorphize_limit
     val state = state |> Proof.map_context repair_context
 
     fun iter timeout iter_num outcome0 time_so_far facts =
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_run.ML	Thu Mar 31 11:16:51 2011 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_run.ML	Thu Mar 31 11:16:52 2011 +0200
@@ -164,9 +164,9 @@
 (* FUDGE *)
 val auto_max_relevant_divisor = 2
 
-fun run_sledgehammer (params as {debug, blocking, provers, type_sys,
-                                 relevance_thresholds, max_relevant, timeout,
-                                 ...})
+fun run_sledgehammer (params as {debug, blocking, provers, monomorphize,
+                                 type_sys, relevance_thresholds, max_relevant,
+                                 timeout, ...})
                      auto i (relevance_override as {only, ...}) minimize_command
                      state =
   if null provers then
@@ -246,7 +246,10 @@
         else
           launch_provers state
               (get_facts "ATP" no_dangerous_types atp_relevance_fudge o K atps)
-              (ATP_Translated_Fact oo K (translate_atp_fact ctxt false o fst))
+              (if monomorphize then
+                 K (Untranslated_Fact o fst)
+               else
+                 ATP_Translated_Fact oo K (translate_atp_fact ctxt false o fst))
               (K (K NONE)) atps
       fun launch_smts accum =
         if null smts then