src/Tools/auto_solve.ML
author wenzelm
Wed, 22 Sep 2010 18:21:48 +0200
changeset 39862 8052101883c3
parent 39575 0a85f960ac50
permissions -rw-r--r--
renamed setmp_noncritical to Unsynchronized.setmp to emphasize its meaning;
     1 (*  Title:      Tools/auto_solve.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 AUTO_SOLVE =
    12 sig
    13   val auto : bool Unsynchronized.ref
    14   val max_solutions : int Unsynchronized.ref
    15   val setup : theory -> theory
    16 end;
    17 
    18 structure Auto_Solve : AUTO_SOLVE =
    19 struct
    20 
    21 (* preferences *)
    22 
    23 val auto = Unsynchronized.ref false;
    24 val max_solutions = Unsynchronized.ref 5;
    25 
    26 val _ =
    27   ProofGeneralPgip.add_preference Preferences.category_tracing
    28   (Unsynchronized.setmp auto true (fn () =>
    29     Preferences.bool_pref auto
    30       "auto-solve" "Try to solve conjectures with existing theorems.") ());
    31 
    32 
    33 (* hook *)
    34 
    35 fun auto_solve state =
    36   let
    37     val ctxt = Proof.context_of state;
    38 
    39     val crits = [(true, Find_Theorems.Solves)];
    40     fun find g = snd (Find_Theorems.find_theorems ctxt (SOME g) (SOME (! max_solutions)) false crits);
    41 
    42     fun prt_result (goal, results) =
    43       let
    44         val msg =
    45           (case goal of
    46             NONE => "The current goal"
    47           | SOME sg => Syntax.string_of_term ctxt (Thm.term_of sg));
    48       in
    49         Pretty.big_list
    50           (msg ^ " could be solved directly with:")
    51           (map (Find_Theorems.pretty_thm ctxt) results)
    52       end;
    53 
    54     fun seek_against_goal () =
    55       (case try Proof.simple_goal state of
    56         NONE => NONE
    57       | SOME {goal = st, ...} =>
    58           let
    59             val subgoals = Drule.strip_imp_prems (Thm.cprop_of st);
    60             val rs =
    61               if length subgoals = 1
    62               then [(NONE, find st)]
    63               else map (fn sg => (SOME sg, find (Goal.init sg))) subgoals;
    64             val results = filter_out (null o snd) rs;
    65           in if null results then NONE else SOME results end);
    66 
    67     fun go () =
    68       (case try seek_against_goal () of
    69         SOME (SOME results) =>
    70           (true, state |> Proof.goal_message
    71                   (fn () => Pretty.chunks
    72                     [Pretty.str "",
    73                       Pretty.markup Markup.hilite
    74                         (separate (Pretty.brk 0) (map prt_result results))]))
    75       | _ => (false, state));
    76   in if not (!auto) then (false, state) else go () end;
    77 
    78 val setup = Auto_Tools.register_tool ("solve", auto_solve)
    79 
    80 end;