src/HOL/Tools/try0.ML
author desharna
Thu, 27 Mar 2025 13:30:16 +0100
changeset 82360 6a09257afd06
parent 82359 d2960b321468
child 82362 396676efbd6d
permissions -rw-r--r--
moved try0's HOL-specific stuff into own theory
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46641
8801a24f9e9a renamed 'try_methods' to 'try0'
blanchet
parents: 45666
diff changeset
     1
(*  Title:      HOL/Tools/try0.ML
38942
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
     2
    Author:     Jasmin Blanchette, TU Muenchen
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
     3
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
     4
Try a combination of proof methods.
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
     5
*)
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
     6
46641
8801a24f9e9a renamed 'try_methods' to 'try0'
blanchet
parents: 45666
diff changeset
     7
signature TRY0 =
38942
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
     8
sig
82360
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
     9
  val serial_commas : string -> string list -> string list
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    10
81369
0677712016b5 try0: add 'use' modifier for thms to insert;
Fabian Huch <huch@in.tum.de>
parents: 81368
diff changeset
    11
  datatype modifier = Use | Simp | Intro | Elim | Dest
82355
4ace4f6f7101 tuned naming
desharna
parents: 82217
diff changeset
    12
  type xref = Facts.ref * Token.src list
4ace4f6f7101 tuned naming
desharna
parents: 82217
diff changeset
    13
  type tagged_xref = xref * modifier list
82213
559399b4de9f tuned to use stronger type Time.time
desharna
parents: 81470
diff changeset
    14
  type result = {name: string, command: string, time: Time.time, state: Proof.state}
82358
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    15
  type proof_method = Time.time option -> tagged_xref list -> Proof.state -> result option
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    16
  type proof_method_options = {run_if_auto_try: bool}
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    17
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    18
  val register_proof_method : string -> proof_method_options -> proof_method -> unit
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    19
  val get_proof_method : string -> proof_method option
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    20
82360
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    21
  datatype mode = Auto_Try | Try | Normal
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    22
  val generic_try0 : mode -> Time.time option -> tagged_xref list -> Proof.state ->
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    23
    (bool * (string * string list)) * result list
82355
4ace4f6f7101 tuned naming
desharna
parents: 82217
diff changeset
    24
  val try0 : Time.time option -> tagged_xref list -> Proof.state -> result list
81365
Fabian Huch <huch@in.tum.de>
parents: 81364
diff changeset
    25
end
38942
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
    26
46641
8801a24f9e9a renamed 'try_methods' to 'try0'
blanchet
parents: 45666
diff changeset
    27
structure Try0 : TRY0 =
38942
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
    28
struct
e10c11971fa7 "try" -- a new diagnosis tool that tries to apply several methods in parallel
blanchet
parents:
diff changeset
    29
82360
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    30
fun serial_commas _ [] = ["??"]
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    31
  | serial_commas _ [s] = [s]
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    32
  | serial_commas conj [s1, s2] = [s1, conj, s2]
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    33
  | serial_commas conj [s1, s2, s3] = [s1 ^ ",", s2 ^ ",", conj, s3]
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    34
  | serial_commas conj (s :: ss) = s ^ "," :: serial_commas conj ss;
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
    35
81365
Fabian Huch <huch@in.tum.de>
parents: 81364
diff changeset
    36
val noneN = "none"
43026
0f15575a6465 handle non-auto try cases gracefully in Try Methods
blanchet
parents: 43024
diff changeset
    37
81365
Fabian Huch <huch@in.tum.de>
parents: 81364
diff changeset
    38
datatype mode = Auto_Try | Try | Normal
43020
abb5d1f907e4 added "try" command, to launch Solve Direct, Quickcheck, Nitpick, Sledgehammer, and Try Methods
blanchet
parents: 43018
diff changeset
    39
81365
Fabian Huch <huch@in.tum.de>
parents: 81364
diff changeset
    40
val default_timeout = seconds 5.0
38944
827c98e8ba8b fiddling with "try"
blanchet
parents: 38942
diff changeset
    41
81369
0677712016b5 try0: add 'use' modifier for thms to insert;
Fabian Huch <huch@in.tum.de>
parents: 81368
diff changeset
    42
datatype modifier = Use | Simp | Intro | Elim | Dest
82355
4ace4f6f7101 tuned naming
desharna
parents: 82217
diff changeset
    43
type xref = Facts.ref * Token.src list
4ace4f6f7101 tuned naming
desharna
parents: 82217
diff changeset
    44
type tagged_xref = xref * modifier list
81366
e020e7bfbbfa clarified: proper type;
Fabian Huch <huch@in.tum.de>
parents: 81365
diff changeset
    45
82213
559399b4de9f tuned to use stronger type Time.time
desharna
parents: 81470
diff changeset
    46
type result = {name: string, command: string, time: Time.time, state: Proof.state}
82356
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    47
type proof_method = Time.time option -> tagged_xref list -> Proof.state -> result option
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    48
type proof_method_options = {run_if_auto_try: bool}
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    49
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    50
val noop_proof_method : proof_method = fn _ => fn _ => fn _ => NONE
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    51
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    52
local
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    53
  val proof_methods =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    54
    Synchronized.var "Try0.proof_methods" (Symtab.empty : proof_method Symtab.table);
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    55
  val auto_try_proof_methods_names =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    56
    Synchronized.var "Try0.auto_try_proof_methods" (Symset.empty : Symset.T);
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    57
in
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    58
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    59
fun register_proof_method name ({run_if_auto_try} : proof_method_options) proof_method =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    60
  let
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    61
    val () = if name = "" then error "Registering unnamed proof method" else ()
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    62
    val () = Synchronized.change proof_methods (Symtab.update_new (name, proof_method))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    63
    val () =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    64
      if run_if_auto_try then
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    65
        Synchronized.change auto_try_proof_methods_names (Symset.insert name)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    66
      else
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    67
        ()
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    68
  in () end
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    69
82358
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    70
fun get_proof_method (name : string) : proof_method option =
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    71
  Symtab.lookup (Synchronized.value proof_methods) name;
82356
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    72
82358
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    73
fun get_all_proof_methods () : (string * proof_method) list =
82356
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    74
  Symtab.fold (fn x => fn xs => x :: xs) (Synchronized.value proof_methods) []
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    75
82358
cc85ccb1a6b2 tuned signature
desharna
parents: 82357
diff changeset
    76
fun get_all_proof_method_names () : string list =
82356
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    77
  Symtab.fold (fn (name, _) => fn names => name :: names) (Synchronized.value proof_methods) []
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    78
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    79
fun get_all_auto_try_proof_method_names () : string list =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    80
  Symset.dest (Synchronized.value auto_try_proof_methods_names)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    81
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    82
fun should_auto_try_proof_method (name : string) : bool =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    83
  Symset.member (Synchronized.value auto_try_proof_methods_names) name
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    84
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    85
end
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    86
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    87
fun get_proof_method_or_noop name =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    88
  (case get_proof_method name of
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    89
    NONE => noop_proof_method
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    90
  | SOME proof_method => proof_method)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    91
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    92
val apply_proof_method = get_proof_method_or_noop
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    93
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    94
fun maybe_apply_proof_method name mode : proof_method =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    95
  if mode <> Auto_Try orelse should_auto_try_proof_method name then
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    96
    get_proof_method_or_noop name
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    97
  else
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    98
    noop_proof_method
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
    99
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   100
fun time_string time = string_of_int (Time.toMilliseconds time) ^ " ms"
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   101
fun tool_time_string (s, time) = s ^ ": " ^ time_string time
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   102
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   103
fun generic_try0 mode timeout_opt (tagged : tagged_xref list) st =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   104
  let
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   105
    fun try_method method = method mode timeout_opt tagged st
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   106
    fun get_message {command, time, ...} = "Found proof: " ^ Active.sendback_markup_command
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   107
      command ^ " (" ^ time_string time ^ ")"
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   108
    val print_step = Option.map (tap (writeln o get_message))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   109
    fun get_results methods : result list =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   110
      if mode = Normal then
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   111
        methods
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   112
        |> Par_List.map (try_method #> print_step)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   113
        |> map_filter I
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   114
        |> sort (Time.compare o apply2 #time)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   115
      else
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   116
        methods
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   117
        |> Par_List.get_some try_method
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   118
        |> the_list
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   119
    val proof_method_names = get_all_proof_method_names ()
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   120
    val maybe_apply_methods = map maybe_apply_proof_method proof_method_names
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   121
  in
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   122
    if mode = Normal then
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   123
      let val names = map quote proof_method_names in
82360
6a09257afd06 moved try0's HOL-specific stuff into own theory
desharna
parents: 82359
diff changeset
   124
        writeln ("Trying " ^ implode_space (serial_commas "and" names) ^ "...")
82356
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   125
      end
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   126
    else
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   127
      ();
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   128
    (case get_results maybe_apply_methods of
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   129
      [] => (if mode = Normal then writeln "No proof found" else (); ((false, (noneN, [])), []))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   130
    | results as {name, command, ...} :: _ =>
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   131
      let
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   132
        val method_times =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   133
          results
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   134
          |> map (fn {name, time, ...} => (time, name))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   135
          |> AList.coalesce (op =)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   136
          |> map (swap o apsnd commas)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   137
        val message =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   138
          (case mode of
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   139
             Auto_Try => "Auto Try0 found a proof"
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   140
           | Try => "Try0 found a proof"
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   141
           | Normal => "Try this") ^ ": " ^
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   142
          Active.sendback_markup_command command ^
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   143
          (case method_times of
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   144
            [(_, ms)] => " (" ^ time_string ms ^ ")"
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   145
          | method_times => "\n(" ^ space_implode "; " (map tool_time_string method_times) ^ ")")
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   146
      in
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   147
        ((true, (name, if mode = Auto_Try then [message] else (writeln message; []))), results)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   148
      end)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   149
  end
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   150
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   151
fun try0 timeout_opt = snd oo generic_try0 Normal timeout_opt
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   152
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   153
fun try0_trans tagged =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   154
  Toplevel.keep_proof
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   155
    (ignore o generic_try0 Normal (SOME default_timeout) tagged o Toplevel.proof_of)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   156
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   157
val parse_fact_refs = Scan.repeat1 (Scan.unless (Parse.name -- Args.colon) Parse.thm)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   158
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   159
val parse_attr =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   160
  Args.$$$ "simp" |-- Args.colon |-- parse_fact_refs >> (map (rpair [Simp]))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   161
  || Args.$$$ "intro" |-- Args.colon |-- parse_fact_refs >> (map (rpair [Intro]))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   162
  || Args.$$$ "elim" |-- Args.colon |-- parse_fact_refs >> (map (rpair [Elim]))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   163
  || Args.$$$ "dest" |-- Args.colon |-- parse_fact_refs >> (map (rpair [Dest]))
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   164
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   165
fun parse_attrs x =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   166
  (Args.parens parse_attrs
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   167
   || Scan.repeat parse_attr >> (fn tagged => fold (curry (op @)) tagged [])) x
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   168
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   169
val _ =
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   170
  Outer_Syntax.command \<^command_keyword>\<open>try0\<close> "try a combination of proof methods"
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   171
    (Scan.optional parse_attrs [] #>> try0_trans)
79a86a1ecb3d refactored try0's internals
desharna
parents: 82355
diff changeset
   172
82216
9807c44f5d57 tuned: restricted visibility of definitions
desharna
parents: 82215
diff changeset
   173
end