src/HOL/Library/Sum_Of_Squares/sos_wrapper.ML
author wenzelm
Thu, 06 Aug 2009 19:51:59 +0200
changeset 32332 bc5cec7b2be6
parent 32265 src/HOL/Library/sos_wrapper.ML@d50f0cb67578
child 32362 c0c640d86b4e
permissions -rw-r--r--
misc changes to SOS by Philipp Meyer:
CSDP_EXE as central setting;
separate component src/HOL/Library/Sum_Of_Squares;
misc tuning and rearrangement of neos_csdp_client;
more robust treatment of shell paths;
debugging depends on local flag;
removed unused parts;
     1 (* Title:      sos_wrapper.ML
     2    Author:     Philipp Meyer, TU Muenchen
     3 
     4 Added functionality for sums of squares, e.g. calling a remote prover
     5 *)
     6 
     7 signature SOS_WRAPPER =
     8 sig
     9 
    10   datatype prover_result = Success | Failure | Error
    11 
    12   val setup: theory -> theory
    13   val destdir: string ref
    14 end
    15 
    16 structure SosWrapper : SOS_WRAPPER=
    17 struct
    18 
    19 datatype prover_result = Success | Failure | Error
    20 fun str_of_result Success = "Success"
    21   | str_of_result Failure = "Failure"
    22   | str_of_result Error = "Error"
    23 
    24 (*** output control ***)
    25 
    26 fun debug s = if ! Sos.debugging then Output.writeln s else ()
    27 val write = Output.priority
    28 
    29 (*** calling provers ***)
    30 
    31 val destdir = ref ""
    32 
    33 fun filename dir name =
    34   let
    35     val probfile = Path.basic (name ^ serial_string ())
    36     val dir_path = Path.explode dir
    37   in
    38     if dir = "" then
    39       File.tmp_path probfile
    40     else
    41       if File.exists dir_path then
    42         Path.append dir_path probfile
    43       else
    44         error ("No such directory: " ^ dir)
    45   end
    46 
    47 fun run_solver name cmd find_failure input =
    48   let
    49     val _ = write ("Calling solver: " ^ name)
    50 
    51     (* create input file *)
    52     val dir = ! destdir
    53     val input_file = filename dir "sos_in" 
    54     val _ = File.write input_file input
    55 
    56     (* call solver *)
    57     val output_file = filename dir "sos_out"
    58     val (output, rv) = system_out (
    59       if File.exists cmd then space_implode " "
    60         [File.shell_path cmd, File.platform_path input_file, File.platform_path output_file]
    61       else error ("Bad executable: " ^ File.shell_path cmd))
    62  
    63     (* read and analysize output *)
    64     val (res, res_msg) = find_failure rv
    65     val result = if File.exists output_file then File.read output_file else ""
    66 
    67     (* remove temporary files *)
    68     val _ = if dir = "" then
    69         (File.rm input_file ; if File.exists output_file then File.rm output_file else ())
    70         else ()
    71 
    72     val _ = debug ("Solver output:\n" ^ output)
    73 
    74     val _ = write (str_of_result res ^ ": " ^ res_msg)
    75   in
    76     case res of
    77       Success => result
    78     | Failure => raise Sos.Failure res_msg
    79     | Error => error ("Prover failed: " ^ res_msg)
    80   end
    81 
    82 (*** various provers ***)
    83 
    84 (* local csdp client *)
    85 
    86 fun find_csdp_failure rv =
    87   case rv of
    88     0 => (Success, "SDP solved")
    89   | 1 => (Failure, "SDP is primal infeasible")
    90   | 2 => (Failure, "SDP is dual infeasible")
    91   | 3 => (Success, "SDP solved with reduced accuracy")
    92   | 4 => (Failure, "Maximum iterations reached")
    93   | 5 => (Failure, "Stuck at edge of primal feasibility")
    94   | 6 => (Failure, "Stuck at edge of dual infeasibility")
    95   | 7 => (Failure, "Lack of progress")
    96   | 8 => (Failure, "X, Z, or O was singular")
    97   | 9 => (Failure, "Detected NaN or Inf values")
    98   | _ => (Error, "return code is " ^ string_of_int rv)
    99 
   100 val csdp = ("$CSDP_EXE", find_csdp_failure)
   101 
   102 (* remote neos server *)
   103 
   104 fun find_neos_failure rv =
   105   case rv of
   106     20 => (Error, "error submitting job")
   107   | 21 => (Error, "no solution")
   108   |  _ => find_csdp_failure rv
   109 
   110 val neos_csdp = ("$ISABELLE_SUM_OF_SQUARES/neos_csdp_client", find_neos_failure)
   111 
   112 (* save provers in table *)
   113 
   114 val provers =
   115      Symtab.make [("remote_csdp", neos_csdp),("csdp", csdp)]
   116 
   117 fun get_prover name =
   118   case Symtab.lookup provers name of
   119     SOME prover => prover
   120   | NONE => error ("unknown prover: " ^ name)
   121 
   122 fun call_solver name =
   123   let
   124     val (cmd, find_failure) = get_prover name
   125   in
   126     run_solver name (Path.explode cmd) find_failure
   127   end
   128 
   129 (* setup tactic *)
   130 
   131 val def_solver = "remote_csdp"
   132 
   133 fun sos_solver name = (SIMPLE_METHOD' o (Sos.sos_tac (call_solver name))) 
   134 
   135 val sos_method = Scan.optional (Scan.lift OuterParse.xname) def_solver >> sos_solver
   136 
   137 val setup = Method.setup @{binding sos} sos_method
   138   "Prove universal problems over the reals using sums of squares"
   139 
   140 end