src/HOL/Library/Sum_Of_Squares/sos_wrapper.ML
changeset 32949 aa6c470a962a
parent 32944 ecc0705174c2
child 35010 d6e492cea6e4
equal deleted inserted replaced
32948:e95a4be101a8 32949:aa6c470a962a
     1 (* Title:      sos_wrapper.ML
     1 (*  Title:      HOL/Library/Sum_Of_Squares/sos_wrapper.ML
     2    Author:     Philipp Meyer, TU Muenchen
     2     Author:     Philipp Meyer, TU Muenchen
     3 
     3 
     4 Added functionality for sums of squares, e.g. calling a remote prover
     4 Added functionality for sums of squares, e.g. calling a remote prover.
     5 *)
     5 *)
     6 
     6 
     7 signature SOS_WRAPPER =
     7 signature SOS_WRAPPER =
     8 sig
     8 sig
     9 
       
    10   datatype prover_result = Success | Failure | Error
     9   datatype prover_result = Success | Failure | Error
    11 
       
    12   val setup: theory -> theory
    10   val setup: theory -> theory
    13   val destdir: string Unsynchronized.ref
    11   val destdir: string Unsynchronized.ref
    14   val get_prover_name: unit -> string
    12   val prover_name: string Unsynchronized.ref
    15   val set_prover_name: string -> unit
       
    16 end
    13 end
    17 
    14 
    18 structure SosWrapper : SOS_WRAPPER=
    15 structure SOS_Wrapper: SOS_WRAPPER =
    19 struct
    16 struct
    20 
    17 
    21 datatype prover_result = Success | Failure | Error
    18 datatype prover_result = Success | Failure | Error
       
    19 
    22 fun str_of_result Success = "Success"
    20 fun str_of_result Success = "Success"
    23   | str_of_result Failure = "Failure"
    21   | str_of_result Failure = "Failure"
    24   | str_of_result Error = "Error"
    22   | str_of_result Error = "Error"
    25 
    23 
       
    24 
    26 (*** output control ***)
    25 (*** output control ***)
    27 
    26 
    28 fun debug s = if ! Sos.debugging then Output.writeln s else ()
    27 fun debug s = if ! Sum_Of_Squares.debugging then writeln s else ()
    29 val write = Output.warning
    28 
    30 
    29 
    31 (*** calling provers ***)
    30 (*** calling provers ***)
    32 
    31 
    33 val destdir = Unsynchronized.ref ""
    32 val destdir = Unsynchronized.ref ""
    34 
    33 
    37     val probfile = Path.basic (name ^ serial_string ())
    36     val probfile = Path.basic (name ^ serial_string ())
    38     val dir_path = Path.explode dir
    37     val dir_path = Path.explode dir
    39   in
    38   in
    40     if dir = "" then
    39     if dir = "" then
    41       File.tmp_path probfile
    40       File.tmp_path probfile
    42     else
    41     else if File.exists dir_path then
    43       if File.exists dir_path then
    42       Path.append dir_path probfile
    44         Path.append dir_path probfile
    43     else error ("No such directory: " ^ dir)
    45       else
       
    46         error ("No such directory: " ^ dir)
       
    47   end
    44   end
    48 
    45 
    49 fun run_solver name cmd find_failure input =
    46 fun run_solver name cmd find_failure input =
    50   let
    47   let
    51     val _ = write ("Calling solver: " ^ name)
    48     val _ = warning ("Calling solver: " ^ name)
    52 
    49 
    53     (* create input file *)
    50     (* create input file *)
    54     val dir = ! destdir
    51     val dir = ! destdir
    55     val input_file = filename dir "sos_in" 
    52     val input_file = filename dir "sos_in"
    56     val _ = File.write input_file input
    53     val _ = File.write input_file input
    57 
    54 
    58     (* call solver *)
    55     (* call solver *)
    59     val output_file = filename dir "sos_out"
    56     val output_file = filename dir "sos_out"
    60     val (output, rv) = system_out (
    57     val (output, rv) = system_out (
    61       if File.exists cmd then space_implode " "
    58       if File.exists cmd then space_implode " "
    62         [File.shell_path cmd, File.shell_path input_file, File.shell_path output_file]
    59         [File.shell_path cmd, File.shell_path input_file, File.shell_path output_file]
    63       else error ("Bad executable: " ^ File.platform_path cmd))
    60       else error ("Bad executable: " ^ File.platform_path cmd))
    64  
    61 
    65     (* read and analysize output *)
    62     (* read and analyze output *)
    66     val (res, res_msg) = find_failure rv
    63     val (res, res_msg) = find_failure rv
    67     val result = if File.exists output_file then File.read output_file else ""
    64     val result = if File.exists output_file then File.read output_file else ""
    68 
    65 
    69     (* remove temporary files *)
    66     (* remove temporary files *)
    70     val _ = if dir = "" then
    67     val _ =
    71         (File.rm input_file ; if File.exists output_file then File.rm output_file else ())
    68       if dir = "" then
    72         else ()
    69         (File.rm input_file; if File.exists output_file then File.rm output_file else ())
       
    70       else ()
    73 
    71 
    74     val _ = debug ("Solver output:\n" ^ output)
    72     val _ = debug ("Solver output:\n" ^ output)
    75 
    73 
    76     val _ = write (str_of_result res ^ ": " ^ res_msg)
    74     val _ = warning (str_of_result res ^ ": " ^ res_msg)
    77   in
    75   in
    78     case res of
    76     (case res of
    79       Success => result
    77       Success => result
    80     | Failure => raise Sos.Failure res_msg
    78     | Failure => raise Sum_Of_Squares.Failure res_msg
    81     | Error => error ("Prover failed: " ^ res_msg)
    79     | Error => error ("Prover failed: " ^ res_msg))
    82   end
    80   end
       
    81 
    83 
    82 
    84 (*** various provers ***)
    83 (*** various provers ***)
    85 
    84 
    86 (* local csdp client *)
    85 (* local csdp client *)
    87 
    86 
    99   | 9 => (Failure, "Detected NaN or Inf values")
    98   | 9 => (Failure, "Detected NaN or Inf values")
   100   | _ => (Error, "return code is " ^ string_of_int rv)
    99   | _ => (Error, "return code is " ^ string_of_int rv)
   101 
   100 
   102 val csdp = ("$CSDP_EXE", find_csdp_failure)
   101 val csdp = ("$CSDP_EXE", find_csdp_failure)
   103 
   102 
       
   103 
   104 (* remote neos server *)
   104 (* remote neos server *)
   105 
   105 
   106 fun find_neos_failure rv =
   106 fun find_neos_failure rv =
   107   case rv of
   107   case rv of
   108     20 => (Error, "error submitting job")
   108     20 => (Error, "error submitting job")
   109   | 21 => (Error, "interrupt")
   109   | 21 => (Error, "interrupt")
   110   |  _ => find_csdp_failure rv
   110   |  _ => find_csdp_failure rv
   111 
   111 
   112 val neos_csdp = ("$ISABELLE_SUM_OF_SQUARES/neos_csdp_client", find_neos_failure)
   112 val neos_csdp = ("$ISABELLE_SUM_OF_SQUARES/neos_csdp_client", find_neos_failure)
   113 
   113 
   114 (* default prover *)
   114 
       
   115 (* named provers *)
       
   116 
       
   117 fun prover "remote_csdp" = neos_csdp
       
   118   | prover "csdp" = csdp
       
   119   | prover name = error ("Unknown prover: " ^ name)
   115 
   120 
   116 val prover_name = Unsynchronized.ref "remote_csdp"
   121 val prover_name = Unsynchronized.ref "remote_csdp"
   117 
   122 
   118 fun get_prover_name () = CRITICAL (fn () => ! prover_name);
   123 fun call_solver opt_name =
   119 fun set_prover_name str = CRITICAL (fn () => prover_name := str);
   124   let
       
   125     val name = the_default (! prover_name) opt_name
       
   126     val (cmd, find_failure) = prover name
       
   127   in run_solver name (Path.explode cmd) find_failure end
   120 
   128 
   121 (* save provers in table *)
       
   122 
       
   123 val provers =
       
   124      Symtab.make [("remote_csdp", neos_csdp),("csdp", csdp)]
       
   125 
       
   126 fun get_prover name =
       
   127   case Symtab.lookup provers name of
       
   128     SOME prover => prover
       
   129   | NONE => error ("unknown prover: " ^ name)
       
   130 
       
   131 fun call_solver name_option =
       
   132   let
       
   133     val name = the_default (get_prover_name()) name_option
       
   134     val (cmd, find_failure) = get_prover name
       
   135   in
       
   136     run_solver name (Path.explode cmd) find_failure
       
   137   end
       
   138 
   129 
   139 (* certificate output *)
   130 (* certificate output *)
   140 
   131 
   141 fun output_line cert = "To repeat this proof with a certifiate use this command:\n" ^
   132 fun output_line cert =
   142         (Markup.markup Markup.sendback) ("by (sos_cert \"" ^ cert ^ "\")")
   133   "To repeat this proof with a certifiate use this command:\n" ^
       
   134     Markup.markup Markup.sendback ("by (sos_cert \"" ^ cert ^ "\")")
   143 
   135 
   144 val print_cert = Output.writeln o output_line o PositivstellensatzTools.pss_tree_to_cert
   136 val print_cert = warning o output_line o PositivstellensatzTools.pss_tree_to_cert
   145 
   137 
   146 (* setup tactic *)
       
   147 
   138 
   148 fun parse_cert (input as (ctxt, _)) = 
   139 (* method setup *)
   149   (Scan.lift OuterParse.string >>
       
   150     PositivstellensatzTools.cert_to_pss_tree (Context.proof_of ctxt)) input
       
   151 
   140 
   152 fun sos_solver print method = (SIMPLE_METHOD' o (Sos.sos_tac print method)) 
   141 fun sos_solver print method = SIMPLE_METHOD' o Sum_Of_Squares.sos_tac print method
   153 
       
   154 val sos_method =
       
   155    Scan.lift (Scan.option OuterParse.xname) >> (fn n => Sos.Prover (call_solver n)) >>
       
   156    sos_solver print_cert
       
   157 
       
   158 val sos_cert_method =
       
   159   parse_cert >> Sos.Certificate >> sos_solver ignore
       
   160 
   142 
   161 val setup =
   143 val setup =
   162      Method.setup @{binding sos} sos_method
   144   Method.setup @{binding sos}
   163      "Prove universal problems over the reals using sums of squares"
   145     (Scan.lift (Scan.option OuterParse.xname)
   164   #> Method.setup @{binding sos_cert} sos_cert_method
   146       >> (sos_solver print_cert o Sum_Of_Squares.Prover o call_solver))
   165      "Prove universal problems over the reals using sums of squares with certificates"
   147     "prove universal problems over the reals using sums of squares" #>
       
   148   Method.setup @{binding sos_cert}
       
   149     (Scan.lift OuterParse.string
       
   150       >> (fn cert => fn ctxt =>
       
   151         sos_solver ignore
       
   152           (Sum_Of_Squares.Certificate (PositivstellensatzTools.cert_to_pss_tree ctxt cert)) ctxt))
       
   153     "prove universal problems over the reals using sums of squares with certificates"
   166 
   154 
   167 end
   155 end