src/HOL/Tools/SMT/smt_solver.ML
changeset 40161 539d07b00e5f
parent 39811 0659e84bdc5f
child 40162 7f58a9a843c2
equal deleted inserted replaced
40160:539351451286 40161:539d07b00e5f
    15   type solver_config = {
    15   type solver_config = {
    16     command: {env_var: string, remote_name: string option},
    16     command: {env_var: string, remote_name: string option},
    17     arguments: string list,
    17     arguments: string list,
    18     interface: interface,
    18     interface: interface,
    19     reconstruct: (string list * SMT_Translate.recon) -> Proof.context ->
    19     reconstruct: (string list * SMT_Translate.recon) -> Proof.context ->
    20       thm * Proof.context }
    20       (int list * thm) * Proof.context }
    21 
    21 
    22   (*options*)
    22   (*options*)
    23   val timeout: int Config.T
    23   val timeout: int Config.T
    24   val with_timeout: Proof.context -> ('a -> 'b) -> 'a -> 'b
    24   val with_timeout: Proof.context -> ('a -> 'b) -> 'a -> 'b
    25   val trace: bool Config.T
    25   val trace: bool Config.T
    28   (*certificates*)
    28   (*certificates*)
    29   val fixed_certificates: bool Config.T
    29   val fixed_certificates: bool Config.T
    30   val select_certificates: string -> Context.generic -> Context.generic
    30   val select_certificates: string -> Context.generic -> Context.generic
    31 
    31 
    32   (*solvers*)
    32   (*solvers*)
    33   type solver = Proof.context -> thm list -> thm
    33   type solver = Proof.context -> (int * thm) list -> int list * thm
    34   type solver_info = Context.generic -> Pretty.T list
    34   type solver_info = Context.generic -> Pretty.T list
    35   val add_solver: string * (Proof.context -> solver_config) ->
    35   val add_solver: string * (Proof.context -> solver_config) ->
    36     Context.generic -> Context.generic
    36     Context.generic -> Context.generic
    37   val all_solver_names_of: Context.generic -> string list
    37   val all_solver_names_of: Context.generic -> string list
    38   val add_solver_info: string * solver_info -> Context.generic ->
    38   val add_solver_info: string * solver_info -> Context.generic ->
    39     Context.generic
    39     Context.generic
    40   val solver_name_of: Context.generic -> string
    40   val solver_name_of: Context.generic -> string
    41   val select_solver: string -> Context.generic -> Context.generic
    41   val select_solver: string -> Context.generic -> Context.generic
    42   val solver_of: Context.generic -> solver
    42   val solver_of: Context.generic -> solver
    43 
    43 
       
    44   (*solver*)
       
    45   val smt_solver: Proof.context -> ('a * thm) list -> 'a list * thm
       
    46   val smt_filter: Proof.context -> ('a * thm) list -> 'a list * string
       
    47 
    44   (*tactic*)
    48   (*tactic*)
    45   val smt_tac': bool -> Proof.context -> thm list -> int -> Tactical.tactic
    49   val smt_tac': bool -> Proof.context -> thm list -> int -> Tactical.tactic
    46   val smt_tac: Proof.context -> thm list -> int -> Tactical.tactic
    50   val smt_tac: Proof.context -> thm list -> int -> Tactical.tactic
    47 
    51 
    48   (*setup*)
    52   (*setup*)
    64 type solver_config = {
    68 type solver_config = {
    65   command: {env_var: string, remote_name: string option},
    69   command: {env_var: string, remote_name: string option},
    66   arguments: string list,
    70   arguments: string list,
    67   interface: interface,
    71   interface: interface,
    68   reconstruct: (string list * SMT_Translate.recon) -> Proof.context ->
    72   reconstruct: (string list * SMT_Translate.recon) -> Proof.context ->
    69     thm * Proof.context }
    73     (int list * thm) * Proof.context }
    70 
    74 
    71 
    75 
    72 
    76 
    73 (* SMT options *)
    77 (* SMT options *)
    74 
    78 
   175     trace_msg ctxt (fn () => Pretty.string_of (Pretty.big_list "SMT names:" [
   179     trace_msg ctxt (fn () => Pretty.string_of (Pretty.big_list "SMT names:" [
   176       Pretty.big_list "sorts:" (map pretty_typ (Symtab.dest typs)),
   180       Pretty.big_list "sorts:" (map pretty_typ (Symtab.dest typs)),
   177       Pretty.big_list "functions:" (map pretty_term (Symtab.dest terms))])) ()
   181       Pretty.big_list "functions:" (map pretty_term (Symtab.dest terms))])) ()
   178   end
   182   end
   179 
   183 
   180 fun invoke translate_config comments command arguments thms ctxt =
   184 fun invoke translate_config comments command arguments irules ctxt =
   181   thms
   185   irules
   182   |> SMT_Translate.translate translate_config ctxt comments
   186   |> SMT_Translate.translate translate_config ctxt comments
   183   ||> tap (trace_recon_data ctxt)
   187   ||> tap (trace_recon_data ctxt)
   184   |>> run_solver ctxt command arguments
   188   |>> run_solver ctxt command arguments
   185   |> rpair ctxt
   189   |> rpair ctxt
   186 
   190 
   200   in
   204   in
   201     (prems, ctxt)
   205     (prems, ctxt)
   202     |-> SMT_Normalize.normalize extra_norm has_datatypes
   206     |-> SMT_Normalize.normalize extra_norm has_datatypes
   203     |-> invoke translate comments command arguments
   207     |-> invoke translate comments command arguments
   204     |-> reconstruct
   208     |-> reconstruct
   205     |-> (fn thm => fn ctxt' => thm
   209     |-> (fn (idxs, thm) => fn ctxt' => thm
   206     |> singleton (ProofContext.export ctxt' ctxt)
   210     |> singleton (ProofContext.export ctxt' ctxt)
   207     |> discharge_definitions)
   211     |> discharge_definitions
       
   212     |> pair idxs)
   208   end
   213   end
   209 
   214 
   210 
   215 
   211 
   216 
   212 (* solver store *)
   217 (* solver store *)
   213 
   218 
   214 type solver = Proof.context -> thm list -> thm
   219 type solver = Proof.context -> (int * thm) list -> int list * thm
   215 type solver_info = Context.generic -> Pretty.T list
   220 type solver_info = Context.generic -> Pretty.T list
   216 
   221 
   217 structure Solvers = Generic_Data
   222 structure Solvers = Generic_Data
   218 (
   223 (
   219   type T = ((Proof.context -> solver_config) * solver_info) Symtab.table
   224   type T = ((Proof.context -> solver_config) * solver_info) Symtab.table
   254   | SOME (s, _) => s)
   259   | SOME (s, _) => s)
   255 
   260 
   256 fun solver_of context =
   261 fun solver_of context =
   257   let val name = solver_name_of context
   262   let val name = solver_name_of context
   258   in gen_solver name (raw_solver_of context name) end
   263   in gen_solver name (raw_solver_of context name) end
       
   264 
       
   265 
       
   266 
       
   267 (* SMT solver *)
       
   268 
       
   269 val has_topsort = Term.exists_type (Term.exists_subtype (fn
       
   270     TFree (_, []) => true
       
   271   | TVar (_, []) => true
       
   272   | _ => false))
       
   273 
       
   274 fun smt_solver ctxt xrules =
       
   275   (* without this test, we would run into problems when atomizing the rules: *)
       
   276   if exists (has_topsort o Thm.prop_of o snd) xrules
       
   277   then raise SMT "proof state contains the universal sort {}"
       
   278   else
       
   279     split_list xrules
       
   280     ||>> solver_of (Context.Proof ctxt) ctxt o map_index I
       
   281     |>> uncurry (map_filter o try o nth) o apsnd (distinct (op =))
       
   282 
       
   283 fun smt_filter ctxt xrules =
       
   284   (fst (smt_solver ctxt xrules), "")
       
   285   handle SMT msg => ([], "SMT: " ^ msg)
       
   286        | SMT_COUNTEREXAMPLE _ => ([], "SMT: potential counterexample")
   259 
   287 
   260 
   288 
   261 
   289 
   262 (* SMT tactic *)
   290 (* SMT tactic *)
   263 
   291 
   277   fun SAFE pass_exns tac ctxt i st =
   305   fun SAFE pass_exns tac ctxt i st =
   278     if pass_exns then tac ctxt i st
   306     if pass_exns then tac ctxt i st
   279     else (tac ctxt i st
   307     else (tac ctxt i st
   280       handle SMT msg => fail_tac (trace_msg ctxt (prefix "SMT: ")) msg st
   308       handle SMT msg => fail_tac (trace_msg ctxt (prefix "SMT: ")) msg st
   281            | SMT_COUNTEREXAMPLE ce => fail_tac tracing (pretty_cex ctxt ce) st)
   309            | SMT_COUNTEREXAMPLE ce => fail_tac tracing (pretty_cex ctxt ce) st)
   282 
       
   283   fun smt_solver rules ctxt = solver_of (Context.Proof ctxt) ctxt rules
       
   284 
       
   285   val has_topsort = Term.exists_type (Term.exists_subtype (fn
       
   286       TFree (_, []) => true
       
   287     | TVar (_, []) => true
       
   288     | _ => false))
       
   289 in
   310 in
   290 fun smt_tac' pass_exns ctxt rules =
   311 fun smt_tac' pass_exns ctxt rules =
   291   CONVERSION (SMT_Normalize.atomize_conv ctxt)
   312   CONVERSION (SMT_Normalize.atomize_conv ctxt)
   292   THEN' Tactic.rtac @{thm ccontr}
   313   THEN' Tactic.rtac @{thm ccontr}
   293   THEN' SUBPROOF (fn {context, prems, ...} =>
   314   THEN' SUBPROOF (fn {context, prems, ...} =>
   294     let val thms = rules @ prems
   315     let fun solve cx = snd (smt_solver cx (map (pair ()) (rules @ prems)))
   295     in
   316     in SAFE pass_exns (Tactic.rtac o solve) context 1 end) ctxt
   296       if exists (has_topsort o Thm.prop_of) thms
       
   297       then fail_tac (trace_msg context I)
       
   298         "SMT: proof state contains the universal sort {}"
       
   299       else SAFE pass_exns (Tactic.rtac o smt_solver thms) context 1
       
   300     end) ctxt
       
   301 
   317 
   302 val smt_tac = smt_tac' false
   318 val smt_tac = smt_tac' false
   303 end
   319 end
   304 
   320 
   305 val smt_method =
   321 val smt_method =
   355       Pretty.big_list "Solver-specific settings:" infos])
   371       Pretty.big_list "Solver-specific settings:" infos])
   356   end
   372   end
   357 
   373 
   358 val _ =
   374 val _ =
   359   Outer_Syntax.improper_command "smt_status"
   375   Outer_Syntax.improper_command "smt_status"
   360     "show the available SMT solvers and the currently selected solver" Keyword.diag
   376     "show the available SMT solvers and the currently selected solver"
       
   377     Keyword.diag
   361     (Scan.succeed (Toplevel.no_timing o Toplevel.keep (fn state =>
   378     (Scan.succeed (Toplevel.no_timing o Toplevel.keep (fn state =>
   362       print_setup (Context.Proof (Toplevel.context_of state)))))
   379       print_setup (Context.Proof (Toplevel.context_of state)))))
   363 
   380 
   364 end
   381 end