added signature ATP_MINIMAL,
authorboehmes
Sat, 05 Sep 2009 22:01:31 +0200
changeset 32525 ea322e847633
parent 32524 9f2784eae302
child 32526 e6996fb0a774
added signature ATP_MINIMAL, fixed AtpMinimal.minimalize for the trivial case, Mirabelle: added an option to minimize a theorem set found by sledgehammer, use timeout of sledgehammer instead of additional timeLimit
src/HOL/Mirabelle/Tools/mirabelle_sledgehammer.ML
src/HOL/Mirabelle/doc/options.txt
src/HOL/Tools/ATP_Manager/atp_minimal.ML
--- a/src/HOL/Mirabelle/Tools/mirabelle_sledgehammer.ML	Sat Sep 05 17:35:05 2009 +0200
+++ b/src/HOL/Mirabelle/Tools/mirabelle_sledgehammer.ML	Sat Sep 05 22:01:31 2009 +0200
@@ -9,10 +9,15 @@
 val keepK = "keep"
 val metisK = "metis"
 val full_typesK = "full_types"
+val minimizeK = "minimize"
+val minimize_timeoutK = "minimize_timeout"
 
 fun sh_tag id = "#" ^ string_of_int id ^ " sledgehammer: "
+fun minimize_tag id = "#" ^ string_of_int id ^ " minimize (sledgehammer): "
 fun metis_tag id = "#" ^ string_of_int id ^ " metis (sledgehammer): "
 
+val separator = "-----"
+
 
 datatype data = Data of {
   sh_calls: int,
@@ -125,6 +130,11 @@
 fun change_data id f = (change data (AList.map_entry (op =) id f); ())
 
 
+fun get_atp thy args =
+  AList.lookup (op =) args proverK
+  |> the_default (hd (space_explode " " (AtpManager.get_atps ())))
+  |> (fn name => (name, the (AtpManager.get_prover name thy)))
+
 local
 
 fun safe init done f x =
@@ -144,51 +154,18 @@
 
 fun done_sh path = AtpWrapper.destdir := path
 
-fun run_sh prover_name timeout st _ =
+fun run_sh (prover_name, prover) timeout st _ =
   let
-    val prover = the (AtpManager.get_prover prover_name (Proof.theory_of st))
-    val atp_timeout = AtpManager.get_timeout () 
-    val atp = prover atp_timeout NONE NONE prover_name 1
+    val atp = prover (Time.toSeconds timeout) NONE NONE prover_name 1
     val ((success, (message, thm_names), atp_time, _, _, _), sh_time) =
-      TimeLimit.timeLimit timeout (Mirabelle.cpu_time atp) (Proof.get_goal st)
+      Mirabelle.cpu_time atp (Proof.get_goal st)
   in
     if success then (message, SOME (atp_time, sh_time, thm_names))
     else (message, NONE)
   end
   handle ResHolClause.TOO_TRIVIAL => ("trivial", SOME (0, 0, []))
-       | TimeLimit.TimeOut => ("timeout", NONE)
        | ERROR msg => ("error: " ^ msg, NONE)
 
-in
-
-fun run_sledgehammer args thm_names id {pre=st, timeout, log, ...} =
-  let
-    val _ = change_data id inc_sh_calls 
-    val prover_name =
-      AList.lookup (op =) args proverK
-      |> the_default (hd (space_explode " " (AtpManager.get_atps ())))
-    val dir = AList.lookup (op =) args keepK
-    val (msg, result) =
-      safe init_sh done_sh (run_sh prover_name timeout st) dir
-  in
-    (case result of
-      SOME (atp_time, sh_time, names) =>
-        let
-          val _ = change_data id inc_sh_success
-          val _ = change_data id (inc_sh_time (atp_time + sh_time))
-          val _ = change thm_names (K (SOME names))
-        in
-          log (sh_tag id ^ "succeeded (" ^ string_of_int atp_time ^ "+" ^
-            string_of_int sh_time ^ ") [" ^ prover_name ^ "]:\n" ^ msg)
-        end
-    | NONE => log (sh_tag id ^ "failed: " ^ msg))
-  end
-
-end
-
-
-local
-
 fun thms_of_name ctxt name =
   let
     val lex = OuterKeyword.get_lexicons
@@ -204,10 +181,54 @@
 
 in
 
-fun run_metis args thm_names id {pre=st, timeout, log, ...} =
+fun run_sledgehammer args named_thms id {pre=st, timeout, log, ...} =
   let
-    fun get_thms ctxt = maps (thms_of_name ctxt)
+    val _ = change_data id inc_sh_calls 
+    val atp as (prover_name, _) = get_atp (Proof.theory_of st) args
+    val dir = AList.lookup (op =) args keepK
+    val (msg, result) = safe init_sh done_sh (run_sh atp timeout st) dir
+  in
+    (case result of
+      SOME (atp_time, sh_time, names) =>
+        let
+          val _ = change_data id inc_sh_success
+          val _ = change_data id (inc_sh_time (atp_time + sh_time))
+
+          fun get_thms name = (name, thms_of_name (Proof.context_of st) name)
+          val _ = named_thms := SOME (map get_thms names)
+        in
+          log (sh_tag id ^ "succeeded (" ^ string_of_int atp_time ^ "+" ^
+            string_of_int sh_time ^ ") [" ^ prover_name ^ "]:\n" ^ msg)
+        end
+    | NONE => log (sh_tag id ^ "failed: " ^ msg))
+  end
+
+end
+
 
+fun run_minimize args named_thms id {pre=st, log, ...} =
+  let
+    val (prover_name, prover) = get_atp (Proof.theory_of st) args
+    val minimize = AtpMinimal.minimalize prover prover_name
+    val timeout =
+      AList.lookup (op =) args minimize_timeoutK
+      |> Option.map (fst o read_int o explode)
+      |> the_default 5
+    val _ = log separator
+  in
+    (case minimize timeout st (these (!named_thms)) of
+      (SOME named_thms', msg) =>
+        if length named_thms' = length (these (!named_thms))
+        then log (minimize_tag id ^ "already minimal")
+        else
+         (named_thms := SOME named_thms';
+          log (minimize_tag id ^ "succeeded:\n" ^ msg))
+    | (NONE, msg) => log (minimize_tag id ^ "failed: " ^ msg))
+  end
+
+
+fun run_metis args named_thms id {pre=st, timeout, log, ...} =
+  let
     fun metis thms ctxt = MetisTools.metis_tac ctxt thms
     fun apply_metis thms = Mirabelle.can_apply timeout (metis thms) st
 
@@ -219,27 +240,29 @@
       handle TimeLimit.TimeOut => (change_data id inc_metis_timeout; "timeout")
            | ERROR msg => "error: " ^ msg
 
-    val _ = log "-----"
+    val _ = log separator
     val _ = change_data id inc_metis_calls
   in
-    thm_names
-    |> get_thms (Proof.context_of st)
+    maps snd named_thms
     |> timed_metis
     |> log o prefix (metis_tag id) 
   end
 
-end
-
 
 fun sledgehammer_action args id (st as {log, ...}) =
   let
-    val thm_names = ref (NONE : string list option)
-    val _ = Mirabelle.catch sh_tag (run_sledgehammer args thm_names) id st
-  in
-    if AList.defined (op =) args metisK andalso is_some (!thm_names)
-    then Mirabelle.catch metis_tag (run_metis args (these (!thm_names))) id st
-    else ()
-  end
+    val named_thms = ref (NONE : (string * thm list) list option)
+
+    fun if_enabled k f =
+      if AList.defined (op =) args k andalso is_some (!named_thms)
+      then f id st else ()
+
+    val _ = Mirabelle.catch sh_tag (run_sledgehammer args named_thms) id st
+    val _ = if_enabled minimizeK
+      (Mirabelle.catch minimize_tag (run_minimize args named_thms))
+    val _ = if_enabled metisK
+      (Mirabelle.catch metis_tag (run_metis args (these (!named_thms))))
+  in () end
 
 fun invoke args =
   let
--- a/src/HOL/Mirabelle/doc/options.txt	Sat Sep 05 17:35:05 2009 +0200
+++ b/src/HOL/Mirabelle/doc/options.txt	Sat Sep 05 22:01:31 2009 +0200
@@ -2,5 +2,7 @@
 
   * prover=NAME: name of the external prover to call
   * keep=PATH: path where to keep temporary files created by sledgehammer 
+  * full_types: enable full-typed encoding
+  * minimize: enable minimization of theorem set found by sledgehammer
+  * minimize_timeout: timeout for each minimization step
   * metis: apply metis with the theorems found by sledgehammer
-  * full_types: turn on full-typed encoding
--- a/src/HOL/Tools/ATP_Manager/atp_minimal.ML	Sat Sep 05 17:35:05 2009 +0200
+++ b/src/HOL/Tools/ATP_Manager/atp_minimal.ML	Sat Sep 05 22:01:31 2009 +0200
@@ -4,7 +4,13 @@
 Minimalization of theorem list for metis by using an external automated theorem prover
 *)
 
-structure AtpMinimal: sig end =
+signature ATP_MINIMAL =
+sig
+  val minimalize: AtpManager.prover -> string -> int -> Proof.state ->
+    (string * thm list) list -> (string * thm list) list option * string
+end
+
+structure AtpMinimal: ATP_MINIMAL =
 struct
 
 (* output control *)
@@ -103,8 +109,7 @@
 fun sh_test_thms prover prover_name time_limit subgoalno state filtered name_thms_pairs =
   let
     val _ = println ("Testing " ^ (length_string name_thms_pairs) ^ " theorems... ")
-    val name_thm_pairs =
-      flat (map (fn (n, ths) => map_index (fn (i, th) => (n, th)) ths) name_thms_pairs)
+    val name_thm_pairs = maps (fn (n, ths) => map (pair n) ths) name_thms_pairs
     val _ = debug_fn (fn () => print_names name_thm_pairs)
     val axclauses = ResAxioms.cnf_rules_pairs (Proof.theory_of state) name_thm_pairs
     val (result, proof) =
@@ -130,6 +135,7 @@
     val test_thms_fun = sh_test_thms prover prover_name time_limit 1 state
     fun test_thms filtered thms =
       case test_thms_fun filtered thms of (Success _, _) => true | _ => false
+    val answer' = pair and answer'' = pair NONE
   in
     (* try prove first to check result and get used theorems *)
     (case test_thms_fun NONE name_thms_pairs of
@@ -141,25 +147,26 @@
               filter (fn (name1, _) => List.exists (equal name1) ordered_used) name_thms_pairs
             else
               name_thms_pairs
-          val min_thms = (minimal (test_thms (SOME filtered)) to_use)
+          val min_thms = if null to_use then []
+            else minimal (test_thms (SOME filtered)) to_use
           val min_names = order_unique (map fst min_thms)
           val _ = println ("Minimal " ^ (length_string min_thms) ^ " theorems")
           val _ = debug_fn (fn () => print_names min_thms)
         in
-          answer ("Try this command: " ^
+          answer' (SOME min_thms) ("Try this command: " ^
             Markup.markup Markup.sendback ("apply (metis " ^ space_implode " " min_names ^ ")"))
         end
     | (Timeout, _) =>
-        answer ("Timeout: You may need to increase the time limit of " ^
+        answer'' ("Timeout: You may need to increase the time limit of " ^
           Int.toString time_limit ^ " seconds. Call atp_minimize [time=...] ")
     | (Error, msg) =>
-        answer ("Error in prover: " ^ msg)
+        answer'' ("Error in prover: " ^ msg)
     | (Failure, _) =>
-        answer "Failure: No proof with the theorems supplied")
+        answer'' "Failure: No proof with the theorems supplied")
     handle ResHolClause.TOO_TRIVIAL =>
-        answer ("Trivial: Try this command: " ^ Markup.markup Markup.sendback "apply metis")
+        answer' (SOME []) ("Trivial: Try this command: " ^ Markup.markup Markup.sendback "apply metis")
     | ERROR msg =>
-        answer ("Error: " ^ msg)
+        answer'' ("Error: " ^ msg)
   end
 
 
@@ -204,8 +211,9 @@
         SOME prover => prover
       | NONE => error ("Unknown prover: " ^ quote prover_name)
     val name_thms_pairs = get_thms (Proof.context_of state) thm_names
+    fun print_answer (_, msg) = answer msg
   in
-    minimalize prover prover_name time_limit state name_thms_pairs
+    print_answer (minimalize prover prover_name time_limit state name_thms_pairs)
   end
 
 val parse_args = Scan.optional (Args.bracks (P.list (P.xname --| P.$$$ "=" -- P.xname))) []