src/Tools/solve_direct.ML
author wenzelm
Mon, 25 Oct 2010 16:52:20 +0200
changeset 40376 db6e84082695
parent 40375 0843888de43e
child 40392 7ee65dbffa31
permissions -rw-r--r--
export main ML entry by default;
observe elisp format for preferences;
clarified command setup;
blanchet@40360
     1
(*  Title:      Tools/solve_direct.ML
wenzelm@30981
     2
    Author:     Timothy Bourke and Gerwin Klein, NICTA
wenzelm@30981
     3
wenzelm@30981
     4
Check whether a newly stated theorem can be solved directly by an
wenzelm@30981
     5
existing theorem.  Duplicate lemmas can be detected in this way.
wenzelm@30981
     6
blanchet@39575
     7
The implementation relies critically on the Find_Theorems solves
wenzelm@30981
     8
feature.
wenzelm@30981
     9
*)
wenzelm@30981
    10
blanchet@40360
    11
signature SOLVE_DIRECT =
wenzelm@30981
    12
sig
wenzelm@40376
    13
  val auto: bool Unsynchronized.ref
wenzelm@40376
    14
  val max_solutions: int Unsynchronized.ref
wenzelm@40376
    15
  val solve_direct: bool -> Proof.state -> bool * Proof.state
wenzelm@40376
    16
  val setup: theory -> theory
wenzelm@30981
    17
end;
wenzelm@30981
    18
wenzelm@40376
    19
structure Solve_Direct: SOLVE_DIRECT =
wenzelm@30981
    20
struct
wenzelm@30981
    21
wenzelm@40375
    22
val solve_directN = "solve_direct";
wenzelm@40375
    23
blanchet@40360
    24
wenzelm@30981
    25
(* preferences *)
wenzelm@30981
    26
wenzelm@32740
    27
val auto = Unsynchronized.ref false;
blanchet@39575
    28
val max_solutions = Unsynchronized.ref 5;
wenzelm@33889
    29
wenzelm@33889
    30
val _ =
wenzelm@33889
    31
  ProofGeneralPgip.add_preference Preferences.category_tracing
wenzelm@39862
    32
  (Unsynchronized.setmp auto true (fn () =>
wenzelm@30981
    33
    Preferences.bool_pref auto
wenzelm@40376
    34
      "auto-solve-direct"
blanchet@40360
    35
      ("Run " ^ quote solve_directN ^ " automatically.")) ());
wenzelm@30981
    36
wenzelm@40375
    37
wenzelm@40375
    38
(* solve_direct command *)
wenzelm@40375
    39
blanchet@40360
    40
fun solve_direct auto state =
wenzelm@30981
    41
  let
wenzelm@30981
    42
    val ctxt = Proof.context_of state;
wenzelm@30981
    43
wenzelm@33309
    44
    val crits = [(true, Find_Theorems.Solves)];
wenzelm@40375
    45
    fun find g =
wenzelm@40375
    46
      snd (Find_Theorems.find_theorems ctxt (SOME g) (SOME (! max_solutions)) false crits);
wenzelm@30981
    47
wenzelm@30981
    48
    fun prt_result (goal, results) =
wenzelm@30981
    49
      let
wenzelm@30981
    50
        val msg =
blanchet@40360
    51
          (if auto then "Auto " else "") ^ solve_directN ^ ": " ^
wenzelm@30981
    52
          (case goal of
wenzelm@30981
    53
            NONE => "The current goal"
wenzelm@30981
    54
          | SOME sg => Syntax.string_of_term ctxt (Thm.term_of sg));
wenzelm@30981
    55
      in
wenzelm@30981
    56
        Pretty.big_list
blanchet@40360
    57
          (msg ^ " can be solved directly with")
wenzelm@33309
    58
          (map (Find_Theorems.pretty_thm ctxt) results)
wenzelm@30981
    59
      end;
wenzelm@30981
    60
wenzelm@30981
    61
    fun seek_against_goal () =
wenzelm@33290
    62
      (case try Proof.simple_goal state of
wenzelm@30981
    63
        NONE => NONE
wenzelm@33290
    64
      | SOME {goal = st, ...} =>
wenzelm@30981
    65
          let
wenzelm@32860
    66
            val subgoals = Drule.strip_imp_prems (Thm.cprop_of st);
wenzelm@30981
    67
            val rs =
wenzelm@30981
    68
              if length subgoals = 1
wenzelm@32860
    69
              then [(NONE, find st)]
wenzelm@30981
    70
              else map (fn sg => (SOME sg, find (Goal.init sg))) subgoals;
wenzelm@30981
    71
            val results = filter_out (null o snd) rs;
wenzelm@30981
    72
          in if null results then NONE else SOME results end);
wenzelm@40375
    73
    fun message results = separate (Pretty.brk 0) (map prt_result results);
blanchet@40360
    74
  in
blanchet@40360
    75
    (case try seek_against_goal () of
blanchet@40360
    76
      SOME (SOME results) =>
wenzelm@40375
    77
        (true,
wenzelm@40375
    78
          state |>
wenzelm@40375
    79
           (if auto then
wenzelm@40375
    80
             Proof.goal_message
wenzelm@40375
    81
               (fn () =>
wenzelm@40375
    82
                 Pretty.chunks
wenzelm@40375
    83
                  [Pretty.str "",
wenzelm@40375
    84
                   Pretty.markup Markup.hilite (message results)])
wenzelm@40375
    85
            else
wenzelm@40375
    86
              tap (fn _ =>
wenzelm@40375
    87
                priority (Pretty.string_of (Pretty.chunks (message results))))))
blanchet@40360
    88
    | _ => (false, state))
blanchet@40360
    89
  end;
wenzelm@30981
    90
blanchet@40360
    91
val _ =
blanchet@40360
    92
  Outer_Syntax.improper_command solve_directN
wenzelm@40375
    93
    "try to solve conjectures directly with existing theorems" Keyword.diag
wenzelm@40376
    94
    (Scan.succeed
wenzelm@40376
    95
      (Toplevel.keep (fn state => ignore (solve_direct false (Toplevel.proof_of state)))));
wenzelm@40375
    96
blanchet@40360
    97
blanchet@40360
    98
(* hook *)
blanchet@40360
    99
blanchet@40360
   100
fun auto_solve_direct state =
wenzelm@40375
   101
  if not (! auto) then (false, state) else solve_direct true state;
blanchet@40360
   102
wenzelm@40375
   103
val setup = Auto_Tools.register_tool (solve_directN, auto_solve_direct);
wenzelm@30981
   104
wenzelm@30981
   105
end;