src/Tools/solve_direct.ML
author blanchet
Fri, 27 May 2011 10:30:08 +0200
changeset 43865 58150aa44941
parent 43861 abb5d1f907e4
child 43866 5a0dec7bc099
permissions -rw-r--r--
prioritize try and auto try's tools, with fast ones first, with a slight preference for provers vs. counterexample generators
     1 (*  Title:      Tools/solve_direct.ML
     2     Author:     Timothy Bourke and Gerwin Klein, NICTA
     3 
     4 Check whether a newly stated theorem can be solved directly by an
     5 existing theorem.  Duplicate lemmas can be detected in this way.
     6 
     7 The implementation relies critically on the Find_Theorems solves
     8 feature.
     9 *)
    10 
    11 signature SOLVE_DIRECT =
    12 sig
    13   val solve_directN: string
    14   val someN: string
    15   val noneN: string
    16   val unknownN: string
    17   val auto: bool Unsynchronized.ref
    18   val max_solutions: int Unsynchronized.ref
    19   val solve_direct: bool -> Proof.state -> bool * (string * Proof.state)
    20   val setup: theory -> theory
    21 end;
    22 
    23 structure Solve_Direct: SOLVE_DIRECT =
    24 struct
    25 
    26 val solve_directN = "solve_direct";
    27 
    28 val someN = "some";
    29 val noneN = "none";
    30 val unknownN = "none";
    31 
    32 (* preferences *)
    33 
    34 val auto = Unsynchronized.ref false;
    35 val max_solutions = Unsynchronized.ref 5;
    36 
    37 val _ =
    38   ProofGeneralPgip.add_preference Preferences.category_tracing
    39   (Unsynchronized.setmp auto true (fn () =>
    40     Preferences.bool_pref auto
    41       "auto-solve-direct"
    42       ("Run " ^ quote solve_directN ^ " automatically.")) ());
    43 
    44 
    45 (* solve_direct command *)
    46 
    47 fun solve_direct auto state =
    48   let
    49     val ctxt = Proof.context_of state;
    50 
    51     val crits = [(true, Find_Theorems.Solves)];
    52     fun find g =
    53       snd (Find_Theorems.find_theorems ctxt (SOME g) (SOME (! max_solutions)) false crits);
    54 
    55     fun prt_result (goal, results) =
    56       let
    57         val msg =
    58           (if auto then "Auto " else "") ^ solve_directN ^ ": " ^
    59           (case goal of
    60             NONE => "The current goal"
    61           | SOME sg => Syntax.string_of_term ctxt (Thm.term_of sg));
    62       in
    63         Pretty.big_list
    64           (msg ^ " can be solved directly with")
    65           (map (Find_Theorems.pretty_thm ctxt) results)
    66       end;
    67 
    68     fun seek_against_goal () =
    69       (case try Proof.simple_goal state of
    70         NONE => NONE
    71       | SOME {goal = st, ...} =>
    72           let
    73             val subgoals = Drule.strip_imp_prems (Thm.cprop_of st);
    74             val rs =
    75               if length subgoals = 1
    76               then [(NONE, find st)]
    77               else map (fn sg => (SOME sg, find (Goal.init sg))) subgoals;
    78             val results = filter_out (null o snd) rs;
    79           in if null results then NONE else SOME results end);
    80     fun message results = separate (Pretty.brk 0) (map prt_result results);
    81   in
    82     (case try seek_against_goal () of
    83       SOME (SOME results) =>
    84         (someN,
    85           state |>
    86            (if auto then
    87              Proof.goal_message
    88                (fn () =>
    89                  Pretty.chunks
    90                   [Pretty.str "",
    91                    Pretty.markup Markup.hilite (message results)])
    92             else
    93               tap (fn _ =>
    94                 Output.urgent_message (Pretty.string_of (Pretty.chunks (message results))))))
    95     | SOME NONE => (noneN, state)
    96     | NONE => (unknownN, state))
    97   end
    98   |> `(fn (outcome_code, _) => outcome_code = someN);
    99 
   100 val _ =
   101   Outer_Syntax.improper_command solve_directN
   102     "try to solve conjectures directly with existing theorems" Keyword.diag
   103     (Scan.succeed
   104       (Toplevel.keep (fn state => ignore (solve_direct false (Toplevel.proof_of state)))));
   105 
   106 
   107 (* hook *)
   108 
   109 val setup = Try.register_tool (solve_directN, (10, auto, solve_direct));
   110 
   111 end;