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