| author | haftmann | 
| Tue, 20 Mar 2007 15:52:43 +0100 | |
| changeset 22486 | d3b6cb2306b6 | 
| parent 21962 | 279b129498b6 | 
| child 22997 | d4f3b015b50b | 
| permissions | -rw-r--r-- | 
| 12869 | 1 | (* Title: HOL/Tools/svc_funcs.ML | 
| 2 | ID: $Id$ | |
| 3 | Author: Lawrence C Paulson | |
| 4 | Copyright 1999 University of Cambridge | |
| 5 | ||
| 6 | Translation functions for the interface to SVC | |
| 7 | ||
| 19336 
fb5e19d26d5e
removed some illegal characters: they were crashing SML/NJ
 paulson parents: 
19277diff
changeset | 8 | Based upon the work of Soren T. Heilmann | 
| 12869 | 9 | |
| 10 | Integers and naturals are translated as follows: | |
| 11 | In a positive context, replace x<y by x+1<=y | |
| 12 | In a negative context, replace x<=y by x<y+1 | |
| 13 | In a negative context, replace x=y by x<y+1 & y<x+1 | |
| 14 | Biconditionals (if-and-only-iff) are expanded if they require such translations | |
| 15 | in either operand. | |
| 16 | ||
| 17 | For each variable of type nat, an assumption is added that it is non-negative. | |
| 18 | *) | |
| 19 | ||
| 20 | structure Svc = | |
| 21 | struct | |
| 22 | val trace = ref false; | |
| 23 | ||
| 24 | datatype expr = | |
| 25 | Buildin of string * expr list | |
| 26 | | Interp of string * expr list | |
| 27 | | UnInterp of string * expr list | |
| 16836 | 28 | | FalseExpr | 
| 12869 | 29 | | TrueExpr | 
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15574diff
changeset | 30 | | Int of IntInf.int | 
| 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15574diff
changeset | 31 | | Rat of IntInf.int * IntInf.int; | 
| 12869 | 32 | |
| 16836 | 33 | fun signedInt i = | 
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15574diff
changeset | 34 | if i < 0 then "-" ^ IntInf.toString (~i) | 
| 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15574diff
changeset | 35 | else IntInf.toString i; | 
| 16836 | 36 | |
| 12869 | 37 | fun is_intnat T = T = HOLogic.intT orelse T = HOLogic.natT; | 
| 16836 | 38 | |
| 12869 | 39 | fun is_numeric T = is_intnat T orelse T = HOLogic.realT; | 
| 16836 | 40 | |
| 12869 | 41 | fun is_numeric_op T = is_numeric (domain_type T); | 
| 42 | ||
| 43 | fun toString t = | |
| 16836 | 44 | let fun ue (Buildin(s, l)) = | 
| 45 |              "(" ^ s ^ (Library.foldl (fn (a, b) => a ^ " " ^ (ue b)) ("", l)) ^ ") "
 | |
| 46 | | ue (Interp(s, l)) = | |
| 47 |              "{" ^ s ^ (Library.foldl (fn (a, b) => a ^ " " ^ (ue b)) ("", l)) ^ "} "
 | |
| 48 | | ue (UnInterp(s, l)) = | |
| 49 |              "(" ^ s ^ (Library.foldl (fn (a, b) => a ^ " " ^ (ue b)) ("", l)) ^ ") "
 | |
| 50 | | ue (FalseExpr) = "FALSE " | |
| 51 | | ue (TrueExpr) = "TRUE " | |
| 52 | | ue (Int i) = (signedInt i) ^ " " | |
| 53 | | ue (Rat(i, j)) = (signedInt i) ^ "|" ^ (signedInt j) ^ " " | |
| 12869 | 54 | in | 
| 16836 | 55 | ue t | 
| 12869 | 56 | end; | 
| 57 | ||
| 16836 | 58 | fun valid e = | 
| 59 | let val svc_home = getenv "SVC_HOME" | |
| 12869 | 60 | val svc_machine = getenv "SVC_MACHINE" | 
| 61 | val check_valid = if svc_home = "" | |
| 16836 | 62 | then error "Environment variable SVC_HOME not set" | 
| 63 | else if svc_machine = "" | |
| 64 | then error "Environment variable SVC_MACHINE not set" | |
| 65 | else svc_home ^ "/" ^ svc_machine ^ "/bin/check_valid" | |
| 12869 | 66 | val svc_input = toString e | 
| 67 |       val _ = if !trace then tracing ("Calling SVC:\n" ^ svc_input) else ()
 | |
| 68 | val svc_input_file = File.tmp_path (Path.basic "SVM_in"); | |
| 69 | val svc_output_file = File.tmp_path (Path.basic "SVM_out"); | |
| 70 | val _ = (File.write svc_input_file svc_input; | |
| 16836 | 71 | execute (check_valid ^ " -dump-result " ^ | 
| 72 | File.shell_path svc_output_file ^ | |
| 73 | " " ^ File.shell_path svc_input_file ^ | |
| 74 | ">/dev/null 2>&1")) | |
| 12869 | 75 | val svc_output = | 
| 21395 
f34ac19659ae
moved some fundamental concepts to General/basics.ML;
 wenzelm parents: 
21078diff
changeset | 76 | (case try File.read svc_output_file of | 
| 15531 | 77 | SOME out => out | 
| 78 | | NONE => error "SVC returned no output"); | |
| 12869 | 79 | in | 
| 80 |       if ! trace then tracing ("SVC Returns:\n" ^ svc_output)
 | |
| 81 | else (File.rm svc_input_file; File.rm svc_output_file); | |
| 82 | String.isPrefix "VALID" svc_output | |
| 83 | end | |
| 84 | ||
| 16836 | 85 |  fun fail t = raise TERM ("SVC oracle", [t]);
 | 
| 12869 | 86 | |
| 87 | fun apply c args = | |
| 88 | let val (ts, bs) = ListPair.unzip args | |
| 89 | in (list_comb(c,ts), exists I bs) end; | |
| 90 | ||
| 91 | (*Determining whether the biconditionals must be unfolded: if there are | |
| 92 | int or nat comparisons below*) | |
| 93 | val iff_tag = | |
| 94 | let fun tag t = | |
| 16836 | 95 | let val (c,ts) = strip_comb t | 
| 96 | in case c of | |
| 97 |              Const("op &", _)   => apply c (map tag ts)
 | |
| 98 |            | Const("op |", _)   => apply c (map tag ts)
 | |
| 99 |            | Const("op -->", _) => apply c (map tag ts)
 | |
| 100 |            | Const("Not", _)    => apply c (map tag ts)
 | |
| 101 |            | Const("True", _)   => (c, false)
 | |
| 102 |            | Const("False", _)  => (c, false)
 | |
| 103 |            | Const("op =", Type ("fun", [T,_])) =>
 | |
| 104 | if T = HOLogic.boolT then | |
| 105 | (*biconditional: with int/nat comparisons below?*) | |
| 106 | let val [t1,t2] = ts | |
| 107 | val (u1,b1) = tag t1 | |
| 108 | and (u2,b2) = tag t2 | |
| 109 | val cname = if b1 orelse b2 then "unfold" else "keep" | |
| 110 | in | |
| 111 |                         (Const ("SVC_Oracle.iff_" ^ cname, dummyT) $ u1 $ u2,
 | |
| 112 | b1 orelse b2) | |
| 113 | end | |
| 114 | else (*might be numeric equality*) (t, is_intnat T) | |
| 19277 | 115 |            | Const("Orderings.less", Type ("fun", [T,_]))  => (t, is_intnat T)
 | 
| 116 |            | Const("Orderings.less_eq", Type ("fun", [T,_])) => (t, is_intnat T)
 | |
| 16836 | 117 | | _ => (t, false) | 
| 118 | end | |
| 12869 | 119 | in #1 o tag end; | 
| 120 | ||
| 121 | (*Map expression e to 0<=a --> e, where "a" is the name of a nat variable*) | |
| 21078 | 122 | fun add_nat_var a e = | 
| 12869 | 123 |      Buildin("=>", [Buildin("<=", [Int 0, UnInterp (a, [])]),
 | 
| 16836 | 124 | e]); | 
| 12869 | 125 | |
| 126 | fun param_string [] = "" | |
| 127 | | param_string is = "_" ^ space_implode "_" (map string_of_int is) | |
| 128 | ||
| 129 | (*Translate an Isabelle formula into an SVC expression | |
| 130 | pos ["positive"]: true if an assumption, false if a goal*) | |
| 131 | fun expr_of pos t = | |
| 132 | let | |
| 133 | val params = rev (rename_wrt_term t (Term.strip_all_vars t)) | |
| 134 | and body = Term.strip_all_body t | |
| 135 | val nat_vars = ref ([] : string list) | |
| 136 | (*translation of a variable: record all natural numbers*) | |
| 137 | fun trans_var (a,T,is) = | |
| 20853 | 138 | (if T = HOLogic.natT then nat_vars := (insert (op =) a (!nat_vars)) | 
| 16836 | 139 | else (); | 
| 12869 | 140 | UnInterp (a ^ param_string is, [])) | 
| 141 | (*A variable, perhaps applied to a series of parameters*) | |
| 142 |     fun var (Free(a,T), is)      = trans_var ("F_" ^ a, T, is)
 | |
| 143 | | var (Var((a, 0), T), is) = trans_var (a, T, is) | |
| 16836 | 144 | | var (Bound i, is) = | 
| 12869 | 145 | let val (a,T) = List.nth (params, i) | 
| 16836 | 146 |           in  trans_var ("B_" ^ a, T, is)  end
 | 
| 12869 | 147 | | var (t $ Bound i, is) = var(t,i::is) | 
| 148 | (*removing a parameter from a Var: the bound var index will | |
| 149 | become part of the Var's name*) | |
| 16836 | 150 | | var (t,_) = fail t; | 
| 12869 | 151 | (*translation of a literal*) | 
| 21820 
2f2b6a965ccc
introduced mk/dest_numeral/number for mk/dest_binum etc.
 haftmann parents: 
21395diff
changeset | 152 | val lit = snd o HOLogic.dest_number; | 
| 12869 | 153 | (*translation of a literal expression [no variables]*) | 
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 154 |     fun litExp (Const("HOL.plus", T) $ x $ y) =
 | 
| 16836 | 155 | if is_numeric_op T then (litExp x) + (litExp y) | 
| 156 | else fail t | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 157 |       | litExp (Const("HOL.minus", T) $ x $ y) =
 | 
| 16836 | 158 | if is_numeric_op T then (litExp x) - (litExp y) | 
| 159 | else fail t | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 160 |       | litExp (Const("HOL.times", T) $ x $ y) =
 | 
| 16836 | 161 | if is_numeric_op T then (litExp x) * (litExp y) | 
| 162 | else fail t | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 163 |       | litExp (Const("HOL.uminus", T) $ x)   =
 | 
| 16836 | 164 | if is_numeric_op T then ~(litExp x) | 
| 165 | else fail t | |
| 166 | | litExp t = lit t | |
| 167 | handle Match => fail t | |
| 12869 | 168 | (*translation of a real/rational expression*) | 
| 169 |     fun suc t = Interp("+", [Int 1, t])
 | |
| 170 |     fun tm (Const("Suc", T) $ x) = suc (tm x)
 | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 171 |       | tm (Const("HOL.plus", T) $ x $ y) =
 | 
| 16836 | 172 |           if is_numeric_op T then Interp("+", [tm x, tm y])
 | 
| 173 | else fail t | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 174 |       | tm (Const("HOL.minus", T) $ x $ y) =
 | 
| 16836 | 175 | if is_numeric_op T then | 
| 176 |               Interp("+", [tm x, Interp("*", [Int ~1, tm y])])
 | |
| 177 | else fail t | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 178 |       | tm (Const("HOL.times", T) $ x $ y) =
 | 
| 16836 | 179 |           if is_numeric_op T then Interp("*", [tm x, tm y])
 | 
| 180 | else fail t | |
| 181 |       | tm (Const("RealDef.rinv", T) $ x) =
 | |
| 182 | if domain_type T = HOLogic.realT then | |
| 183 | Rat(1, litExp x) | |
| 184 | else fail t | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17465diff
changeset | 185 |       | tm (Const("HOL.uminus", T) $ x) =
 | 
| 16836 | 186 |           if is_numeric_op T then Interp("*", [Int ~1, tm x])
 | 
| 187 | else fail t | |
| 188 | | tm t = Int (lit t) | |
| 189 | handle Match => var (t,[]) | |
| 12869 | 190 | (*translation of a formula*) | 
| 16836 | 191 |     and fm pos (Const("op &", _) $ p $ q) =
 | 
| 192 |             Buildin("AND", [fm pos p, fm pos q])
 | |
| 193 |       | fm pos (Const("op |", _) $ p $ q) =
 | |
| 194 |             Buildin("OR", [fm pos p, fm pos q])
 | |
| 195 |       | fm pos (Const("op -->", _) $ p $ q) =
 | |
| 196 |             Buildin("=>", [fm (not pos) p, fm pos q])
 | |
| 197 |       | fm pos (Const("Not", _) $ p) =
 | |
| 198 |             Buildin("NOT", [fm (not pos) p])
 | |
| 12869 | 199 |       | fm pos (Const("True", _)) = TrueExpr
 | 
| 200 |       | fm pos (Const("False", _)) = FalseExpr
 | |
| 16836 | 201 |       | fm pos (Const("SVC_Oracle.iff_keep", _) $ p $ q) =
 | 
| 202 | (*polarity doesn't matter*) | |
| 203 |             Buildin("=", [fm pos p, fm pos q])
 | |
| 204 |       | fm pos (Const("SVC_Oracle.iff_unfold", _) $ p $ q) =
 | |
| 205 |             Buildin("AND",   (*unfolding uses both polarities*)
 | |
| 206 |                          [Buildin("=>", [fm (not pos) p, fm pos q]),
 | |
| 207 |                           Buildin("=>", [fm (not pos) q, fm pos p])])
 | |
| 208 |       | fm pos (t as Const("op =", Type ("fun", [T,_])) $ x $ y) =
 | |
| 209 | let val tx = tm x and ty = tm y | |
| 210 | in if pos orelse T = HOLogic.realT then | |
| 211 |                        Buildin("=", [tx, ty])
 | |
| 212 | else if is_intnat T then | |
| 213 |                        Buildin("AND",
 | |
| 214 |                                     [Buildin("<", [tx, suc ty]),
 | |
| 215 |                                      Buildin("<", [ty, suc tx])])
 | |
| 216 | else fail t | |
| 217 | end | |
| 218 | (*inequalities: possible types are nat, int, real*) | |
| 19277 | 219 |       | fm pos (t as Const("Orderings.less",  Type ("fun", [T,_])) $ x $ y) =
 | 
| 16836 | 220 | if not pos orelse T = HOLogic.realT then | 
| 221 |                 Buildin("<", [tm x, tm y])
 | |
| 222 | else if is_intnat T then | |
| 223 |                 Buildin("<=", [suc (tm x), tm y])
 | |
| 224 | else fail t | |
| 19277 | 225 |       | fm pos (t as Const("Orderings.less_eq",  Type ("fun", [T,_])) $ x $ y) =
 | 
| 16836 | 226 | if pos orelse T = HOLogic.realT then | 
| 227 |                 Buildin("<=", [tm x, tm y])
 | |
| 228 | else if is_intnat T then | |
| 229 |                 Buildin("<", [tm x, suc (tm y)])
 | |
| 230 | else fail t | |
| 12869 | 231 | | fm pos t = var(t,[]); | 
| 232 | (*entry point, and translation of a meta-formula*) | |
| 233 |       fun mt pos ((c as Const("Trueprop", _)) $ p) = fm pos (iff_tag p)
 | |
| 16836 | 234 |         | mt pos ((c as Const("==>", _)) $ p $ q) =
 | 
| 235 |             Buildin("=>", [mt (not pos) p, mt pos q])
 | |
| 236 | | mt pos t = fm pos (iff_tag t) (*it might be a formula*) | |
| 12869 | 237 | |
| 238 | val body_e = mt pos body (*evaluate now to assign into !nat_vars*) | |
| 16836 | 239 | in | 
| 21078 | 240 | fold_rev add_nat_var (!nat_vars) body_e | 
| 12869 | 241 | end; | 
| 242 | ||
| 243 | ||
| 244 | (*The oracle proves the given formula t, if possible*) | |
| 16836 | 245 | fun oracle thy t = | 
| 21962 | 246 |   (if ! trace then tracing ("SVC oracle: problem is\n" ^ Sign.string_of_term thy t) else ();
 | 
| 247 | if valid (expr_of false t) then t else fail t); | |
| 12869 | 248 | |
| 249 | end; |