src/Tools/solve_direct.ML
author wenzelm
Mon, 25 Oct 2010 16:41:23 +0200
changeset 40375 0843888de43e
parent 40360 9ed3711366c8
child 40376 db6e84082695
permissions -rw-r--r--
observe Isabelle/ML coding standards;
     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 auto : bool Unsynchronized.ref
    14   val max_solutions : int Unsynchronized.ref
    15   val setup : theory -> theory
    16 end;
    17 
    18 structure Solve_Direct : SOLVE_DIRECT =
    19 struct
    20 
    21 val solve_directN = "solve_direct";
    22 
    23 
    24 (* preferences *)
    25 
    26 val auto = Unsynchronized.ref false;
    27 val max_solutions = Unsynchronized.ref 5;
    28 
    29 val _ =
    30   ProofGeneralPgip.add_preference Preferences.category_tracing
    31   (Unsynchronized.setmp auto true (fn () =>
    32     Preferences.bool_pref auto
    33       ("Auto " ^ solve_directN)
    34       ("Run " ^ quote solve_directN ^ " automatically.")) ());
    35 
    36 
    37 (* solve_direct command *)
    38 
    39 fun solve_direct auto state =
    40   let
    41     val ctxt = Proof.context_of state;
    42 
    43     val crits = [(true, Find_Theorems.Solves)];
    44     fun find g =
    45       snd (Find_Theorems.find_theorems ctxt (SOME g) (SOME (! max_solutions)) false crits);
    46 
    47     fun prt_result (goal, results) =
    48       let
    49         val msg =
    50           (if auto then "Auto " else "") ^ solve_directN ^ ": " ^
    51           (case goal of
    52             NONE => "The current goal"
    53           | SOME sg => Syntax.string_of_term ctxt (Thm.term_of sg));
    54       in
    55         Pretty.big_list
    56           (msg ^ " can be solved directly with")
    57           (map (Find_Theorems.pretty_thm ctxt) results)
    58       end;
    59 
    60     fun seek_against_goal () =
    61       (case try Proof.simple_goal state of
    62         NONE => NONE
    63       | SOME {goal = st, ...} =>
    64           let
    65             val subgoals = Drule.strip_imp_prems (Thm.cprop_of st);
    66             val rs =
    67               if length subgoals = 1
    68               then [(NONE, find st)]
    69               else map (fn sg => (SOME sg, find (Goal.init sg))) subgoals;
    70             val results = filter_out (null o snd) rs;
    71           in if null results then NONE else SOME results end);
    72     fun message results = separate (Pretty.brk 0) (map prt_result results);
    73   in
    74     (case try seek_against_goal () of
    75       SOME (SOME results) =>
    76         (true,
    77           state |>
    78            (if auto then
    79              Proof.goal_message
    80                (fn () =>
    81                  Pretty.chunks
    82                   [Pretty.str "",
    83                    Pretty.markup Markup.hilite (message results)])
    84             else
    85               tap (fn _ =>
    86                 priority (Pretty.string_of (Pretty.chunks (message results))))))
    87     | _ => (false, state))
    88   end;
    89 
    90 val invoke_solve_direct = fst o solve_direct false;
    91 
    92 val _ =
    93   Outer_Syntax.improper_command solve_directN
    94     "try to solve conjectures directly with existing theorems" Keyword.diag
    95     (Scan.succeed (Toplevel.keep (K () o invoke_solve_direct o Toplevel.proof_of)));
    96 
    97 
    98 (* hook *)
    99 
   100 fun auto_solve_direct state =
   101   if not (! auto) then (false, state) else solve_direct true state;
   102 
   103 val setup = Auto_Tools.register_tool (solve_directN, auto_solve_direct);
   104 
   105 end;