src/HOL/Tools/SMT/smt_solver.ML
changeset 41239 d6e804ff29c3
parent 41131 fc9d503c3d67
child 41241 7d07736aaaf6
equal deleted inserted replaced
41238:78e4508d2e54 41239:d6e804ff29c3
    31   val is_locally_installed: Proof.context -> string -> bool
    31   val is_locally_installed: Proof.context -> string -> bool
    32   val is_remotely_available: Proof.context -> string -> bool
    32   val is_remotely_available: Proof.context -> string -> bool
    33   val default_max_relevant: Proof.context -> string -> int
    33   val default_max_relevant: Proof.context -> string -> int
    34 
    34 
    35   (*filter*)
    35   (*filter*)
    36   val smt_filter: bool -> Time.time -> Proof.state ->
    36   type 'a smt_filter_head_result = 'a list * (int option * thm) list *
    37     ('a * (int option * thm)) list -> int ->
    37     (((int * thm) list * Proof.context) * (int * (int option * thm)) list)
    38     {outcome: SMT_Failure.failure option, used_facts: ('a * thm) list,
    38   val smt_filter_head: Time.time -> Proof.state ->
    39     run_time_in_msecs: int option}
    39     ('a * (int option * thm)) list -> int -> 'a smt_filter_head_result
       
    40   val smt_filter_tail: bool -> 'a smt_filter_head_result ->
       
    41     {outcome: SMT_Failure.failure option, used_facts: ('a * thm) list}
    40 
    42 
    41   (*tactic*)
    43   (*tactic*)
    42   val smt_tac': bool -> Proof.context -> thm list -> int -> Tactical.tactic
    44   val smt_tac': bool -> Proof.context -> thm list -> int -> Tactical.tactic
    43   val smt_tac: Proof.context -> thm list -> int -> Tactical.tactic
    45   val smt_tac: Proof.context -> thm list -> int -> Tactical.tactic
    44 
    46 
   210   options: Proof.context -> string list,
   212   options: Proof.context -> string list,
   211   reconstruct: Proof.context -> string list * SMT_Translate.recon ->
   213   reconstruct: Proof.context -> string list * SMT_Translate.recon ->
   212     int list * thm,
   214     int list * thm,
   213   default_max_relevant: int }
   215   default_max_relevant: int }
   214 
   216 
   215 fun gen_solver name (info : solver_info) rm ctxt iwthms =
   217 fun gen_solver_head ctxt iwthms =
       
   218   SMT_Normalize.normalize ctxt iwthms
       
   219   |> rpair ctxt
       
   220   |-> SMT_Monomorph.monomorph
       
   221 
       
   222 fun gen_solver_tail (name, info : solver_info) rm (iwthms', ctxt) iwthms =
   216   let
   223   let
   217     val {env_var, is_remote, options, reconstruct, ...} = info
   224     val {env_var, is_remote, options, reconstruct, ...} = info
   218     val cmd = (rm, env_var, is_remote, name)
   225     val cmd = (rm, env_var, is_remote, name)
   219   in
   226   in
   220     SMT_Normalize.normalize ctxt iwthms
   227     (iwthms', ctxt)
   221     |> rpair ctxt
   228     |-> invoke name cmd options
   222     |-> SMT_Monomorph.monomorph
   229     |> reconstruct ctxt
   223     |> (fn (iwthms', ctxt') => invoke name cmd options iwthms' ctxt'
       
   224     |> reconstruct ctxt')
       
   225     |> (fn (idxs, thm) => thm
   230     |> (fn (idxs, thm) => thm
   226     |> tap (fn _ => trace_assumptions ctxt iwthms idxs)
   231     |> tap (fn _ => trace_assumptions ctxt iwthms idxs)
   227     |> pair idxs)
   232     |> pair idxs)
   228   end
   233   end
   229 
   234 
   282 fun name_and_solver_of ctxt =
   287 fun name_and_solver_of ctxt =
   283   let val name = C.solver_of ctxt
   288   let val name = C.solver_of ctxt
   284   in (name, get_info ctxt name) end
   289   in (name, get_info ctxt name) end
   285 
   290 
   286 val solver_name_of = fst o name_and_solver_of
   291 val solver_name_of = fst o name_and_solver_of
   287 fun solver_of ctxt =
   292 fun solver_of ctxt rm ctxt' =
   288   let val (name, raw_solver) = name_and_solver_of ctxt
   293   `(gen_solver_head ctxt') #-> gen_solver_tail (name_and_solver_of ctxt) rm
   289   in gen_solver name raw_solver end
       
   290 
   294 
   291 val available_solvers_of = Symtab.keys o Solvers.get o Context.Proof
   295 val available_solvers_of = Symtab.keys o Solvers.get o Context.Proof
   292 
   296 
   293 fun is_locally_installed ctxt name =
   297 fun is_locally_installed ctxt name =
   294   let val {env_var, ...} = get_info ctxt name
   298   let val {env_var, ...} = get_info ctxt name
   304 val has_topsort = Term.exists_type (Term.exists_subtype (fn
   308 val has_topsort = Term.exists_type (Term.exists_subtype (fn
   305     TFree (_, []) => true
   309     TFree (_, []) => true
   306   | TVar (_, []) => true
   310   | TVar (_, []) => true
   307   | _ => false))
   311   | _ => false))
   308 
   312 
   309 fun smt_solver rm ctxt iwthms =
   313 (* without this test, we would run into problems when atomizing the rules: *)
   310   (* without this test, we would run into problems when atomizing the rules: *)
   314 fun check_topsort iwthms =
   311   if exists (has_topsort o Thm.prop_of o snd o snd) iwthms then
   315   if exists (has_topsort o Thm.prop_of o snd o snd) iwthms then
   312     raise SMT_Failure.SMT (SMT_Failure.Other_Failure ("proof state " ^
   316     raise SMT_Failure.SMT (SMT_Failure.Other_Failure ("proof state " ^
   313       "contains the universal sort {}"))
   317       "contains the universal sort {}"))
   314   else solver_of ctxt rm ctxt iwthms
   318   else
       
   319     ()
   315 
   320 
   316 val cnot = Thm.cterm_of @{theory} @{const Not}
   321 val cnot = Thm.cterm_of @{theory} @{const Not}
   317 
   322 
   318 fun mk_result outcome xrules =
   323 fun mk_result outcome xrules = { outcome = outcome, used_facts = xrules }
   319   { outcome = outcome, used_facts = xrules, run_time_in_msecs = NONE }
   324 
   320 
   325 type 'a smt_filter_head_result = 'a list * (int option * thm) list *
   321 fun smt_filter run_remote time_limit st xwrules i =
   326   (((int * thm) list * Proof.context) * (int * (int option * thm)) list)
       
   327 
       
   328 fun smt_filter_head time_limit st xwrules i =
   322   let
   329   let
   323     val ctxt =
   330     val ctxt =
   324       Proof.context_of st
   331       Proof.context_of st
   325       |> Config.put C.oracle false
   332       |> Config.put C.oracle false
   326       |> Config.put C.timeout (Time.toReal time_limit)
   333       |> Config.put C.timeout (Time.toReal time_limit)
   331     val ({context=ctxt', prems, concl, ...}, _) = Subgoal.focus ctxt i goal
   338     val ({context=ctxt', prems, concl, ...}, _) = Subgoal.focus ctxt i goal
   332     fun negate ct = Thm.dest_comb ct ||> Thm.capply cnot |-> Thm.capply
   339     fun negate ct = Thm.dest_comb ct ||> Thm.capply cnot |-> Thm.capply
   333     val cprop = negate (Thm.rhs_of (SMT_Normalize.atomize_conv ctxt' concl))
   340     val cprop = negate (Thm.rhs_of (SMT_Normalize.atomize_conv ctxt' concl))
   334 
   341 
   335     val (xs, wthms) = split_list xwrules
   342     val (xs, wthms) = split_list xwrules
   336     val xrules = xs ~~ map snd wthms
   343   in
   337   in
   344     (xs, wthms,
   338     wthms
   345      wthms
   339     |> map_index I
   346      |> map_index I
   340     |> append (map (pair ~1 o pair NONE) (Thm.assume cprop :: prems @ facts))
   347      |> append (map (pair ~1 o pair NONE) (Thm.assume cprop :: prems @ facts))
   341     |> smt_solver (SOME run_remote) ctxt'
   348      |> tap check_topsort
       
   349      |> `(gen_solver_head ctxt'))
       
   350   end
       
   351 
       
   352 fun smt_filter_tail run_remote (xs, wthms, head as ((_, ctxt), _)) =
       
   353   let val xrules = xs ~~ map snd wthms in
       
   354     head
       
   355     |-> gen_solver_tail (name_and_solver_of ctxt) (SOME run_remote)
   342     |> distinct (op =) o fst
   356     |> distinct (op =) o fst
   343     |> map_filter (try (nth xrules))
   357     |> map_filter (try (nth xrules))
   344     |> (if solver_name_of ctxt = "z3" (* FIXME *) then I else K xrules)
   358     |> (if solver_name_of ctxt = "z3" (* FIXME *) then I else K xrules)
   345     |> mk_result NONE
   359     |> mk_result NONE
   346   end
   360   end
   347   handle SMT_Failure.SMT fail => mk_result (SOME fail) []
   361   handle SMT_Failure.SMT fail => mk_result (SOME fail) []
   348   (* FIXME: measure runtime *)
       
   349 
       
   350 
   362 
   351 
   363 
   352 (* SMT tactic *)
   364 (* SMT tactic *)
   353 
   365 
   354 fun smt_tac' pass_exns ctxt rules =
   366 fun smt_tac' pass_exns ctxt rules =
   355   CONVERSION (SMT_Normalize.atomize_conv ctxt)
   367   CONVERSION (SMT_Normalize.atomize_conv ctxt)
   356   THEN' Tactic.rtac @{thm ccontr}
   368   THEN' Tactic.rtac @{thm ccontr}
   357   THEN' SUBPROOF (fn {context=ctxt', prems, ...} =>
   369   THEN' SUBPROOF (fn {context=ctxt', prems, ...} =>
   358     let
   370     let
   359       fun solve iwthms = snd (smt_solver NONE ctxt' iwthms)
   371       val solve = snd o solver_of ctxt' NONE ctxt' o tap check_topsort
   360       val tag = "Solver " ^ C.solver_of ctxt' ^ ": "
   372       val tag = "Solver " ^ C.solver_of ctxt' ^ ": "
   361       val str_of = prefix tag o SMT_Failure.string_of_failure ctxt'
   373       val str_of = prefix tag o SMT_Failure.string_of_failure ctxt'
   362       fun safe_solve iwthms =
   374       fun safe_solve iwthms =
   363         if pass_exns then SOME (solve iwthms)
   375         if pass_exns then SOME (solve iwthms)
   364         else (SOME (solve iwthms)
   376         else (SOME (solve iwthms)