| author | wenzelm | 
| Sat, 13 Mar 2021 12:45:31 +0100 | |
| changeset 73420 | 2c5d58e58fd2 | 
| parent 73419 | 22f3f2117ed7 | 
| child 74640 | 85d8d9eeb4e1 | 
| permissions | -rw-r--r-- | 
| 33982 | 1 | (* Title: HOL/Tools/Nitpick/kodkod.ML | 
| 33192 | 2 | Author: Jasmin Blanchette, TU Muenchen | 
| 55888 | 3 | Copyright 2008-2014 | 
| 33192 | 4 | |
| 39456 | 5 | ML interface for Kodkod. | 
| 33192 | 6 | *) | 
| 7 | ||
| 8 | signature KODKOD = | |
| 9 | sig | |
| 10 | type n_ary_index = int * int | |
| 11 | type setting = string * string | |
| 12 | ||
| 13 | datatype tuple = | |
| 14 | Tuple of int list | | |
| 15 | TupleIndex of n_ary_index | | |
| 16 | TupleReg of n_ary_index | |
| 17 | ||
| 18 | datatype tuple_set = | |
| 19 | TupleUnion of tuple_set * tuple_set | | |
| 20 | TupleDifference of tuple_set * tuple_set | | |
| 21 | TupleIntersect of tuple_set * tuple_set | | |
| 22 | TupleProduct of tuple_set * tuple_set | | |
| 23 | TupleProject of tuple_set * int | | |
| 24 | TupleSet of tuple list | | |
| 25 | TupleRange of tuple * tuple | | |
| 26 | TupleArea of tuple * tuple | | |
| 27 | TupleAtomSeq of int * int | | |
| 28 | TupleSetReg of n_ary_index | |
| 29 | ||
| 30 | datatype tuple_assign = | |
| 31 | AssignTuple of n_ary_index * tuple | | |
| 32 | AssignTupleSet of n_ary_index * tuple_set | |
| 33 | ||
| 34 | type bound = (n_ary_index * string) list * tuple_set list | |
| 35 | type int_bound = int option * tuple_set list | |
| 36 | ||
| 37 | datatype formula = | |
| 38 | All of decl list * formula | | |
| 39 | Exist of decl list * formula | | |
| 40 | FormulaLet of expr_assign list * formula | | |
| 41 | FormulaIf of formula * formula * formula | | |
| 42 | Or of formula * formula | | |
| 43 | Iff of formula * formula | | |
| 44 | Implies of formula * formula | | |
| 45 | And of formula * formula | | |
| 46 | Not of formula | | |
| 47 | Acyclic of n_ary_index | | |
| 48 | Function of n_ary_index * rel_expr * rel_expr | | |
| 49 | Functional of n_ary_index * rel_expr * rel_expr | | |
| 38126 | 50 | TotalOrdering of n_ary_index * rel_expr * rel_expr * rel_expr | | 
| 33192 | 51 | Subset of rel_expr * rel_expr | | 
| 52 | RelEq of rel_expr * rel_expr | | |
| 53 | IntEq of int_expr * int_expr | | |
| 54 | LT of int_expr * int_expr | | |
| 55 | LE of int_expr * int_expr | | |
| 56 | No of rel_expr | | |
| 57 | Lone of rel_expr | | |
| 58 | One of rel_expr | | |
| 59 | Some of rel_expr | | |
| 60 | False | | |
| 61 | True | | |
| 62 | FormulaReg of int | |
| 63 | and rel_expr = | |
| 64 | RelLet of expr_assign list * rel_expr | | |
| 65 | RelIf of formula * rel_expr * rel_expr | | |
| 66 | Union of rel_expr * rel_expr | | |
| 67 | Difference of rel_expr * rel_expr | | |
| 68 | Override of rel_expr * rel_expr | | |
| 69 | Intersect of rel_expr * rel_expr | | |
| 70 | Product of rel_expr * rel_expr | | |
| 71 | IfNo of rel_expr * rel_expr | | |
| 72 | Project of rel_expr * int_expr list | | |
| 73 | Join of rel_expr * rel_expr | | |
| 74 | Closure of rel_expr | | |
| 75 | ReflexiveClosure of rel_expr | | |
| 76 | Transpose of rel_expr | | |
| 77 | Comprehension of decl list * formula | | |
| 78 | Bits of int_expr | | |
| 79 | Int of int_expr | | |
| 80 | Iden | | |
| 81 | Ints | | |
| 82 | None | | |
| 83 | Univ | | |
| 84 | Atom of int | | |
| 85 | AtomSeq of int * int | | |
| 86 | Rel of n_ary_index | | |
| 87 | Var of n_ary_index | | |
| 88 | RelReg of n_ary_index | |
| 89 | and int_expr = | |
| 90 | Sum of decl list * int_expr | | |
| 91 | IntLet of expr_assign list * int_expr | | |
| 92 | IntIf of formula * int_expr * int_expr | | |
| 93 | SHL of int_expr * int_expr | | |
| 94 | SHA of int_expr * int_expr | | |
| 95 | SHR of int_expr * int_expr | | |
| 96 | Add of int_expr * int_expr | | |
| 97 | Sub of int_expr * int_expr | | |
| 98 | Mult of int_expr * int_expr | | |
| 99 | Div of int_expr * int_expr | | |
| 100 | Mod of int_expr * int_expr | | |
| 101 | Cardinality of rel_expr | | |
| 102 | SetSum of rel_expr | | |
| 103 | BitOr of int_expr * int_expr | | |
| 104 | BitXor of int_expr * int_expr | | |
| 105 | BitAnd of int_expr * int_expr | | |
| 106 | BitNot of int_expr | | |
| 107 | Neg of int_expr | | |
| 108 | Absolute of int_expr | | |
| 109 | Signum of int_expr | | |
| 110 | Num of int | | |
| 111 | IntReg of int | |
| 112 | and decl = | |
| 113 | DeclNo of n_ary_index * rel_expr | | |
| 114 | DeclLone of n_ary_index * rel_expr | | |
| 115 | DeclOne of n_ary_index * rel_expr | | |
| 116 | DeclSome of n_ary_index * rel_expr | | |
| 117 | DeclSet of n_ary_index * rel_expr | |
| 118 | and expr_assign = | |
| 119 | AssignFormulaReg of int * formula | | |
| 120 | AssignRelReg of n_ary_index * rel_expr | | |
| 121 | AssignIntReg of int * int_expr | |
| 122 | ||
| 36390 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 123 | type 'a fold_expr_funcs = | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 124 |     {formula_func: formula -> 'a -> 'a,
 | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 125 | rel_expr_func: rel_expr -> 'a -> 'a, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 126 | int_expr_func: int_expr -> 'a -> 'a} | 
| 33192 | 127 | |
| 50488 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 128 | val kodkodi_version : unit -> int list | 
| 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 129 | |
| 33192 | 130 | val fold_formula : 'a fold_expr_funcs -> formula -> 'a -> 'a | 
| 131 | val fold_rel_expr : 'a fold_expr_funcs -> rel_expr -> 'a -> 'a | |
| 132 | val fold_int_expr : 'a fold_expr_funcs -> int_expr -> 'a -> 'a | |
| 133 | val fold_decl : 'a fold_expr_funcs -> decl -> 'a -> 'a | |
| 134 | val fold_expr_assign : 'a fold_expr_funcs -> expr_assign -> 'a -> 'a | |
| 135 | ||
| 36390 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 136 | type 'a fold_tuple_funcs = | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 137 |     {tuple_func: tuple -> 'a -> 'a,
 | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 138 | tuple_set_func: tuple_set -> 'a -> 'a} | 
| 33192 | 139 | |
| 140 | val fold_tuple : 'a fold_tuple_funcs -> tuple -> 'a -> 'a | |
| 141 | val fold_tuple_set : 'a fold_tuple_funcs -> tuple_set -> 'a -> 'a | |
| 142 | val fold_tuple_assign : 'a fold_tuple_funcs -> tuple_assign -> 'a -> 'a | |
| 143 | val fold_bound : | |
| 144 | 'a fold_expr_funcs -> 'a fold_tuple_funcs -> bound -> 'a -> 'a | |
| 145 | val fold_int_bound : 'a fold_tuple_funcs -> int_bound -> 'a -> 'a | |
| 146 | ||
| 36390 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 147 | type problem = | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 148 |     {comment: string,
 | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 149 | settings: setting list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 150 | univ_card: int, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 151 | tuple_assigns: tuple_assign list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 152 | bounds: bound list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 153 | int_bounds: int_bound list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 154 | expr_assigns: expr_assign list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 155 | formula: formula} | 
| 33192 | 156 | |
| 157 | type raw_bound = n_ary_index * int list list | |
| 158 | ||
| 159 | datatype outcome = | |
| 35333 
f61de25f71f9
distinguish between Kodkodi warnings and errors in Nitpick;
 blanchet parents: 
35309diff
changeset | 160 | Normal of (int * raw_bound list) list * int list * string | | 
| 33192 | 161 | TimedOut of int list | | 
| 162 | Error of string * int list | |
| 163 | ||
| 164 | exception SYNTAX of string * string | |
| 165 | ||
| 166 | val max_arity : int -> int | |
| 167 | val arity_of_rel_expr : rel_expr -> int | |
| 35185 
9b8f351cced6
added yet another hint to Nitpick's output, this time warning about problems for which nothing was effectively tested
 blanchet parents: 
35079diff
changeset | 168 | val is_problem_trivially_false : problem -> bool | 
| 35814 | 169 | val problems_equivalent : problem * problem -> bool | 
| 33192 | 170 | val solve_any_problem : | 
| 54816 
10d48c2a3e32
made timeouts in Sledgehammer not be 'option's -- simplified lots of code
 blanchet parents: 
53093diff
changeset | 171 | bool -> bool -> Time.time -> int -> int -> problem list -> outcome | 
| 33192 | 172 | end; | 
| 173 | ||
| 174 | structure Kodkod : KODKOD = | |
| 175 | struct | |
| 176 | ||
| 177 | type n_ary_index = int * int | |
| 178 | ||
| 179 | type setting = string * string | |
| 180 | ||
| 181 | datatype tuple = | |
| 182 | Tuple of int list | | |
| 183 | TupleIndex of n_ary_index | | |
| 184 | TupleReg of n_ary_index | |
| 185 | ||
| 186 | datatype tuple_set = | |
| 187 | TupleUnion of tuple_set * tuple_set | | |
| 188 | TupleDifference of tuple_set * tuple_set | | |
| 189 | TupleIntersect of tuple_set * tuple_set | | |
| 190 | TupleProduct of tuple_set * tuple_set | | |
| 191 | TupleProject of tuple_set * int | | |
| 192 | TupleSet of tuple list | | |
| 193 | TupleRange of tuple * tuple | | |
| 194 | TupleArea of tuple * tuple | | |
| 195 | TupleAtomSeq of int * int | | |
| 196 | TupleSetReg of n_ary_index | |
| 197 | ||
| 198 | datatype tuple_assign = | |
| 199 | AssignTuple of n_ary_index * tuple | | |
| 200 | AssignTupleSet of n_ary_index * tuple_set | |
| 201 | ||
| 202 | type bound = (n_ary_index * string) list * tuple_set list | |
| 203 | type int_bound = int option * tuple_set list | |
| 204 | ||
| 205 | datatype formula = | |
| 206 | All of decl list * formula | | |
| 207 | Exist of decl list * formula | | |
| 208 | FormulaLet of expr_assign list * formula | | |
| 209 | FormulaIf of formula * formula * formula | | |
| 210 | Or of formula * formula | | |
| 211 | Iff of formula * formula | | |
| 212 | Implies of formula * formula | | |
| 213 | And of formula * formula | | |
| 214 | Not of formula | | |
| 215 | Acyclic of n_ary_index | | |
| 216 | Function of n_ary_index * rel_expr * rel_expr | | |
| 217 | Functional of n_ary_index * rel_expr * rel_expr | | |
| 38126 | 218 | TotalOrdering of n_ary_index * rel_expr * rel_expr * rel_expr | | 
| 33192 | 219 | Subset of rel_expr * rel_expr | | 
| 220 | RelEq of rel_expr * rel_expr | | |
| 221 | IntEq of int_expr * int_expr | | |
| 222 | LT of int_expr * int_expr | | |
| 223 | LE of int_expr * int_expr | | |
| 224 | No of rel_expr | | |
| 225 | Lone of rel_expr | | |
| 226 | One of rel_expr | | |
| 227 | Some of rel_expr | | |
| 228 | False | | |
| 229 | True | | |
| 230 | FormulaReg of int | |
| 231 | and rel_expr = | |
| 232 | RelLet of expr_assign list * rel_expr | | |
| 233 | RelIf of formula * rel_expr * rel_expr | | |
| 234 | Union of rel_expr * rel_expr | | |
| 235 | Difference of rel_expr * rel_expr | | |
| 236 | Override of rel_expr * rel_expr | | |
| 237 | Intersect of rel_expr * rel_expr | | |
| 238 | Product of rel_expr * rel_expr | | |
| 239 | IfNo of rel_expr * rel_expr | | |
| 240 | Project of rel_expr * int_expr list | | |
| 241 | Join of rel_expr * rel_expr | | |
| 242 | Closure of rel_expr | | |
| 243 | ReflexiveClosure of rel_expr | | |
| 244 | Transpose of rel_expr | | |
| 245 | Comprehension of decl list * formula | | |
| 246 | Bits of int_expr | | |
| 247 | Int of int_expr | | |
| 248 | Iden | | |
| 249 | Ints | | |
| 250 | None | | |
| 251 | Univ | | |
| 252 | Atom of int | | |
| 253 | AtomSeq of int * int | | |
| 254 | Rel of n_ary_index | | |
| 255 | Var of n_ary_index | | |
| 256 | RelReg of n_ary_index | |
| 257 | and int_expr = | |
| 258 | Sum of decl list * int_expr | | |
| 259 | IntLet of expr_assign list * int_expr | | |
| 260 | IntIf of formula * int_expr * int_expr | | |
| 261 | SHL of int_expr * int_expr | | |
| 262 | SHA of int_expr * int_expr | | |
| 263 | SHR of int_expr * int_expr | | |
| 264 | Add of int_expr * int_expr | | |
| 265 | Sub of int_expr * int_expr | | |
| 266 | Mult of int_expr * int_expr | | |
| 267 | Div of int_expr * int_expr | | |
| 268 | Mod of int_expr * int_expr | | |
| 269 | Cardinality of rel_expr | | |
| 270 | SetSum of rel_expr | | |
| 271 | BitOr of int_expr * int_expr | | |
| 272 | BitXor of int_expr * int_expr | | |
| 273 | BitAnd of int_expr * int_expr | | |
| 274 | BitNot of int_expr | | |
| 275 | Neg of int_expr | | |
| 276 | Absolute of int_expr | | |
| 277 | Signum of int_expr | | |
| 278 | Num of int | | |
| 279 | IntReg of int | |
| 280 | and decl = | |
| 281 | DeclNo of n_ary_index * rel_expr | | |
| 282 | DeclLone of n_ary_index * rel_expr | | |
| 283 | DeclOne of n_ary_index * rel_expr | | |
| 284 | DeclSome of n_ary_index * rel_expr | | |
| 285 | DeclSet of n_ary_index * rel_expr | |
| 286 | and expr_assign = | |
| 287 | AssignFormulaReg of int * formula | | |
| 288 | AssignRelReg of n_ary_index * rel_expr | | |
| 289 | AssignIntReg of int * int_expr | |
| 290 | ||
| 36390 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 291 | type problem = | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 292 |   {comment: string,
 | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 293 | settings: setting list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 294 | univ_card: int, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 295 | tuple_assigns: tuple_assign list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 296 | bounds: bound list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 297 | int_bounds: int_bound list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 298 | expr_assigns: expr_assign list, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 299 | formula: formula} | 
| 33192 | 300 | |
| 301 | type raw_bound = n_ary_index * int list list | |
| 302 | ||
| 303 | datatype outcome = | |
| 35333 
f61de25f71f9
distinguish between Kodkodi warnings and errors in Nitpick;
 blanchet parents: 
35309diff
changeset | 304 | Normal of (int * raw_bound list) list * int list * string | | 
| 33192 | 305 | TimedOut of int list | | 
| 306 | Error of string * int list | |
| 307 | ||
| 308 | exception SYNTAX of string * string | |
| 309 | ||
| 36390 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 310 | type 'a fold_expr_funcs = | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 311 |   {formula_func: formula -> 'a -> 'a,
 | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 312 | rel_expr_func: rel_expr -> 'a -> 'a, | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 313 | int_expr_func: int_expr -> 'a -> 'a} | 
| 33192 | 314 | |
| 50488 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 315 | fun kodkodi_version () = | 
| 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 316 | getenv "KODKODI_VERSION" | 
| 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 317 | |> space_explode "." | 
| 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 318 | |> map (the_default 0 o Int.fromString) | 
| 
1b3eb579e08b
use modern SAT solvers with modern Kodkod versions
 blanchet parents: 
50487diff
changeset | 319 | |
| 38126 | 320 | |
| 321 | (** Auxiliary functions on Kodkod problems **) | |
| 35718 | 322 | |
| 33192 | 323 | fun fold_formula (F : 'a fold_expr_funcs) formula = | 
| 324 | case formula of | |
| 325 | All (ds, f) => fold (fold_decl F) ds #> fold_formula F f | |
| 326 | | Exist (ds, f) => fold (fold_decl F) ds #> fold_formula F f | |
| 327 | | FormulaLet (bs, f) => fold (fold_expr_assign F) bs #> fold_formula F f | |
| 328 | | FormulaIf (f, f1, f2) => | |
| 329 | fold_formula F f #> fold_formula F f1 #> fold_formula F f2 | |
| 330 | | Or (f1, f2) => fold_formula F f1 #> fold_formula F f2 | |
| 331 | | Iff (f1, f2) => fold_formula F f1 #> fold_formula F f2 | |
| 332 | | Implies (f1, f2) => fold_formula F f1 #> fold_formula F f2 | |
| 333 | | And (f1, f2) => fold_formula F f1 #> fold_formula F f2 | |
| 334 | | Not f => fold_formula F f | |
| 335 | | Acyclic x => fold_rel_expr F (Rel x) | |
| 336 | | Function (x, r1, r2) => | |
| 337 | fold_rel_expr F (Rel x) #> fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 338 | | Functional (x, r1, r2) => | |
| 339 | fold_rel_expr F (Rel x) #> fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 38126 | 340 | | TotalOrdering (x, r1, r2, r3) => | 
| 341 | fold_rel_expr F (Rel x) #> fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 342 | #> fold_rel_expr F r3 | |
| 33192 | 343 | | Subset (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | 
| 344 | | RelEq (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 345 | | IntEq (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 346 | | LT (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 347 | | LE (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 348 | | No r => fold_rel_expr F r | |
| 349 | | Lone r => fold_rel_expr F r | |
| 350 | | One r => fold_rel_expr F r | |
| 351 | | Some r => fold_rel_expr F r | |
| 352 | | False => #formula_func F formula | |
| 353 | | True => #formula_func F formula | |
| 354 | | FormulaReg _ => #formula_func F formula | |
| 355 | and fold_rel_expr F rel_expr = | |
| 356 | case rel_expr of | |
| 357 | RelLet (bs, r) => fold (fold_expr_assign F) bs #> fold_rel_expr F r | |
| 358 | | RelIf (f, r1, r2) => | |
| 359 | fold_formula F f #> fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 360 | | Union (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 361 | | Difference (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 362 | | Override (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 363 | | Intersect (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 364 | | Product (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 365 | | IfNo (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 366 | | Project (r1, is) => fold_rel_expr F r1 #> fold (fold_int_expr F) is | |
| 367 | | Join (r1, r2) => fold_rel_expr F r1 #> fold_rel_expr F r2 | |
| 368 | | Closure r => fold_rel_expr F r | |
| 369 | | ReflexiveClosure r => fold_rel_expr F r | |
| 370 | | Transpose r => fold_rel_expr F r | |
| 371 | | Comprehension (ds, f) => fold (fold_decl F) ds #> fold_formula F f | |
| 372 | | Bits i => fold_int_expr F i | |
| 373 | | Int i => fold_int_expr F i | |
| 374 | | Iden => #rel_expr_func F rel_expr | |
| 375 | | Ints => #rel_expr_func F rel_expr | |
| 376 | | None => #rel_expr_func F rel_expr | |
| 377 | | Univ => #rel_expr_func F rel_expr | |
| 378 | | Atom _ => #rel_expr_func F rel_expr | |
| 379 | | AtomSeq _ => #rel_expr_func F rel_expr | |
| 380 | | Rel _ => #rel_expr_func F rel_expr | |
| 381 | | Var _ => #rel_expr_func F rel_expr | |
| 382 | | RelReg _ => #rel_expr_func F rel_expr | |
| 383 | and fold_int_expr F int_expr = | |
| 384 | case int_expr of | |
| 385 | Sum (ds, i) => fold (fold_decl F) ds #> fold_int_expr F i | |
| 386 | | IntLet (bs, i) => fold (fold_expr_assign F) bs #> fold_int_expr F i | |
| 387 | | IntIf (f, i1, i2) => | |
| 388 | fold_formula F f #> fold_int_expr F i1 #> fold_int_expr F i2 | |
| 389 | | SHL (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 390 | | SHA (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 391 | | SHR (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 392 | | Add (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 393 | | Sub (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 394 | | Mult (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 395 | | Div (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 396 | | Mod (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 397 | | Cardinality r => fold_rel_expr F r | |
| 398 | | SetSum r => fold_rel_expr F r | |
| 399 | | BitOr (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 400 | | BitXor (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 401 | | BitAnd (i1, i2) => fold_int_expr F i1 #> fold_int_expr F i2 | |
| 402 | | BitNot i => fold_int_expr F i | |
| 403 | | Neg i => fold_int_expr F i | |
| 404 | | Absolute i => fold_int_expr F i | |
| 405 | | Signum i => fold_int_expr F i | |
| 406 | | Num _ => #int_expr_func F int_expr | |
| 407 | | IntReg _ => #int_expr_func F int_expr | |
| 408 | and fold_decl F decl = | |
| 409 | case decl of | |
| 410 | DeclNo (x, r) => fold_rel_expr F (Var x) #> fold_rel_expr F r | |
| 411 | | DeclLone (x, r) => fold_rel_expr F (Var x) #> fold_rel_expr F r | |
| 412 | | DeclOne (x, r) => fold_rel_expr F (Var x) #> fold_rel_expr F r | |
| 413 | | DeclSome (x, r) => fold_rel_expr F (Var x) #> fold_rel_expr F r | |
| 414 | | DeclSet (x, r) => fold_rel_expr F (Var x) #> fold_rel_expr F r | |
| 415 | and fold_expr_assign F assign = | |
| 416 | case assign of | |
| 417 | AssignFormulaReg (x, f) => fold_formula F (FormulaReg x) #> fold_formula F f | |
| 418 | | AssignRelReg (x, r) => fold_rel_expr F (RelReg x) #> fold_rel_expr F r | |
| 419 | | AssignIntReg (x, i) => fold_int_expr F (IntReg x) #> fold_int_expr F i | |
| 420 | ||
| 36390 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 421 | type 'a fold_tuple_funcs = | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 422 |   {tuple_func: tuple -> 'a -> 'a,
 | 
| 
eee4ee6a5cbe
remove "show_skolems" option and change style of record declarations
 blanchet parents: 
36385diff
changeset | 423 | tuple_set_func: tuple_set -> 'a -> 'a} | 
| 33192 | 424 | |
| 425 | fun fold_tuple (F : 'a fold_tuple_funcs) = #tuple_func F | |
| 55889 | 426 | |
| 33192 | 427 | fun fold_tuple_set F tuple_set = | 
| 428 | case tuple_set of | |
| 429 | TupleUnion (ts1, ts2) => fold_tuple_set F ts1 #> fold_tuple_set F ts2 | |
| 430 | | TupleDifference (ts1, ts2) => fold_tuple_set F ts1 #> fold_tuple_set F ts2 | |
| 431 | | TupleIntersect (ts1, ts2) => fold_tuple_set F ts1 #> fold_tuple_set F ts2 | |
| 432 | | TupleProduct (ts1, ts2) => fold_tuple_set F ts1 #> fold_tuple_set F ts2 | |
| 433 | | TupleProject (ts, _) => fold_tuple_set F ts | |
| 434 | | TupleSet ts => fold (fold_tuple F) ts | |
| 435 | | TupleRange (t1, t2) => fold_tuple F t1 #> fold_tuple F t2 | |
| 436 | | TupleArea (t1, t2) => fold_tuple F t1 #> fold_tuple F t2 | |
| 437 | | TupleAtomSeq _ => #tuple_set_func F tuple_set | |
| 438 | | TupleSetReg _ => #tuple_set_func F tuple_set | |
| 55889 | 439 | |
| 33192 | 440 | fun fold_tuple_assign F assign = | 
| 441 | case assign of | |
| 442 | AssignTuple (x, t) => fold_tuple F (TupleReg x) #> fold_tuple F t | |
| 443 | | AssignTupleSet (x, ts) => | |
| 444 | fold_tuple_set F (TupleSetReg x) #> fold_tuple_set F ts | |
| 55889 | 445 | |
| 33192 | 446 | fun fold_bound expr_F tuple_F (zs, tss) = | 
| 447 | fold (fold_rel_expr expr_F) (map (Rel o fst) zs) | |
| 448 | #> fold (fold_tuple_set tuple_F) tss | |
| 55889 | 449 | |
| 33192 | 450 | fun fold_int_bound F (_, tss) = fold (fold_tuple_set F) tss | 
| 451 | ||
| 452 | fun max_arity univ_card = floor (Math.ln 2147483647.0 | |
| 453 | / Math.ln (Real.fromInt univ_card)) | |
| 55889 | 454 | |
| 33192 | 455 | fun arity_of_rel_expr (RelLet (_, r)) = arity_of_rel_expr r | 
| 456 | | arity_of_rel_expr (RelIf (_, r1, _)) = arity_of_rel_expr r1 | |
| 457 | | arity_of_rel_expr (Union (r1, _)) = arity_of_rel_expr r1 | |
| 458 | | arity_of_rel_expr (Difference (r1, _)) = arity_of_rel_expr r1 | |
| 459 | | arity_of_rel_expr (Override (r1, _)) = arity_of_rel_expr r1 | |
| 460 | | arity_of_rel_expr (Intersect (r1, _)) = arity_of_rel_expr r1 | |
| 461 | | arity_of_rel_expr (Product (r1, r2)) = sum_arities_of_rel_exprs r1 r2 | |
| 462 | | arity_of_rel_expr (IfNo (r1, _)) = arity_of_rel_expr r1 | |
| 35280 
54ab4921f826
fixed a few bugs in Nitpick and removed unreferenced variables
 blanchet parents: 
35187diff
changeset | 463 | | arity_of_rel_expr (Project (_, is)) = length is | 
| 33192 | 464 | | arity_of_rel_expr (Join (r1, r2)) = sum_arities_of_rel_exprs r1 r2 - 2 | 
| 465 | | arity_of_rel_expr (Closure _) = 2 | |
| 466 | | arity_of_rel_expr (ReflexiveClosure _) = 2 | |
| 467 | | arity_of_rel_expr (Transpose _) = 2 | |
| 468 | | arity_of_rel_expr (Comprehension (ds, _)) = | |
| 469 | fold (curry op + o arity_of_decl) ds 0 | |
| 470 | | arity_of_rel_expr (Bits _) = 1 | |
| 471 | | arity_of_rel_expr (Int _) = 1 | |
| 472 | | arity_of_rel_expr Iden = 2 | |
| 473 | | arity_of_rel_expr Ints = 1 | |
| 474 | | arity_of_rel_expr None = 1 | |
| 475 | | arity_of_rel_expr Univ = 1 | |
| 476 | | arity_of_rel_expr (Atom _) = 1 | |
| 477 | | arity_of_rel_expr (AtomSeq _) = 1 | |
| 478 | | arity_of_rel_expr (Rel (n, _)) = n | |
| 479 | | arity_of_rel_expr (Var (n, _)) = n | |
| 480 | | arity_of_rel_expr (RelReg (n, _)) = n | |
| 481 | and sum_arities_of_rel_exprs r1 r2 = arity_of_rel_expr r1 + arity_of_rel_expr r2 | |
| 482 | and arity_of_decl (DeclNo ((n, _), _)) = n | |
| 483 | | arity_of_decl (DeclLone ((n, _), _)) = n | |
| 484 | | arity_of_decl (DeclOne ((n, _), _)) = n | |
| 485 | | arity_of_decl (DeclSome ((n, _), _)) = n | |
| 486 | | arity_of_decl (DeclSet ((n, _), _)) = n | |
| 487 | ||
| 35185 
9b8f351cced6
added yet another hint to Nitpick's output, this time warning about problems for which nothing was effectively tested
 blanchet parents: 
35079diff
changeset | 488 | fun is_problem_trivially_false ({formula = False, ...} : problem) = true
 | 
| 
9b8f351cced6
added yet another hint to Nitpick's output, this time warning about problems for which nothing was effectively tested
 blanchet parents: 
35079diff
changeset | 489 | | is_problem_trivially_false _ = false | 
| 
9b8f351cced6
added yet another hint to Nitpick's output, this time warning about problems for which nothing was effectively tested
 blanchet parents: 
35079diff
changeset | 490 | |
| 35814 | 491 | val chop_solver = take 2 o space_explode "," | 
| 33192 | 492 | |
| 35814 | 493 | fun settings_equivalent ([], []) = true | 
| 494 | | settings_equivalent ((key1, value1) :: settings1, | |
| 495 | (key2, value2) :: settings2) = | |
| 496 | key1 = key2 andalso | |
| 497 | (value1 = value2 orelse key1 = "delay" orelse | |
| 498 | (key1 = "solver" andalso chop_solver value1 = chop_solver value2)) andalso | |
| 499 | settings_equivalent (settings1, settings2) | |
| 500 | | settings_equivalent _ = false | |
| 501 | ||
| 502 | fun problems_equivalent (p1 : problem, p2 : problem) = | |
| 34936 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 503 | #univ_card p1 = #univ_card p2 andalso | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 504 | #formula p1 = #formula p2 andalso | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 505 | #bounds p1 = #bounds p2 andalso | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 506 | #expr_assigns p1 = #expr_assigns p2 andalso | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 507 | #tuple_assigns p1 = #tuple_assigns p2 andalso | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 508 | #int_bounds p1 = #int_bounds p2 andalso | 
| 35814 | 509 | settings_equivalent (#settings p1, #settings p2) | 
| 33192 | 510 | |
| 35718 | 511 | (** Serialization of problem **) | 
| 34998 | 512 | |
| 34124 
c4628a1dcf75
added support for binary nat/int representation to Nitpick
 blanchet parents: 
34121diff
changeset | 513 | fun base_name j = | 
| 
c4628a1dcf75
added support for binary nat/int representation to Nitpick
 blanchet parents: 
34121diff
changeset | 514 | if j < 0 then string_of_int (~j - 1) ^ "'" else string_of_int j | 
| 33192 | 515 | |
| 516 | fun n_ary_name (1, j) prefix _ _ = prefix ^ base_name j | |
| 517 | | n_ary_name (2, j) _ prefix _ = prefix ^ base_name j | |
| 34124 
c4628a1dcf75
added support for binary nat/int representation to Nitpick
 blanchet parents: 
34121diff
changeset | 518 | | n_ary_name (n, j) _ _ prefix = prefix ^ string_of_int n ^ "_" ^ base_name j | 
| 33192 | 519 | |
| 520 | fun atom_name j = "A" ^ base_name j | |
| 521 | fun atom_seq_name (k, 0) = "u" ^ base_name k | |
| 522 | | atom_seq_name (k, j0) = "u" ^ base_name k ^ "@" ^ base_name j0 | |
| 523 | fun formula_reg_name j = "$f" ^ base_name j | |
| 524 | fun rel_reg_name j = "$e" ^ base_name j | |
| 525 | fun int_reg_name j = "$i" ^ base_name j | |
| 526 | ||
| 527 | fun tuple_name x = n_ary_name x "A" "P" "T" | |
| 50487 | 528 | fun rel_name x = n_ary_name x "s" "r" "m" | 
| 33192 | 529 | fun var_name x = n_ary_name x "S" "R" "M" | 
| 530 | fun tuple_reg_name x = n_ary_name x "$A" "$P" "$T" | |
| 531 | fun tuple_set_reg_name x = n_ary_name x "$a" "$p" "$t" | |
| 532 | ||
| 533 | fun inline_comment "" = "" | |
| 534 | | inline_comment comment = | |
| 535 | " /* " ^ translate_string (fn "\n" => " " | "*" => "* " | s => s) comment ^ | |
| 536 | " */" | |
| 55889 | 537 | |
| 33192 | 538 | fun block_comment "" = "" | 
| 539 | | block_comment comment = prefix_lines "// " comment ^ "\n" | |
| 540 | ||
| 50487 | 541 | fun commented_rel_name (x, s) = rel_name x ^ inline_comment s | 
| 33192 | 542 | |
| 543 | fun string_for_tuple (Tuple js) = "[" ^ commas (map atom_name js) ^ "]" | |
| 544 | | string_for_tuple (TupleIndex x) = tuple_name x | |
| 545 | | string_for_tuple (TupleReg x) = tuple_reg_name x | |
| 546 | ||
| 547 | val no_prec = 100 | |
| 548 | val prec_TupleUnion = 1 | |
| 549 | val prec_TupleIntersect = 2 | |
| 550 | val prec_TupleProduct = 3 | |
| 551 | val prec_TupleProject = 4 | |
| 552 | ||
| 553 | fun precedence_ts (TupleUnion _) = prec_TupleUnion | |
| 554 | | precedence_ts (TupleDifference _) = prec_TupleUnion | |
| 555 | | precedence_ts (TupleIntersect _) = prec_TupleIntersect | |
| 556 | | precedence_ts (TupleProduct _) = prec_TupleProduct | |
| 557 | | precedence_ts (TupleProject _) = prec_TupleProject | |
| 558 | | precedence_ts _ = no_prec | |
| 559 | ||
| 560 | fun string_for_tuple_set tuple_set = | |
| 561 | let | |
| 562 | fun sub tuple_set outer_prec = | |
| 563 | let | |
| 564 | val prec = precedence_ts tuple_set | |
| 565 | val need_parens = (prec < outer_prec) | |
| 566 | in | |
| 567 |         (if need_parens then "(" else "") ^
 | |
| 568 | (case tuple_set of | |
| 569 | TupleUnion (ts1, ts2) => sub ts1 prec ^ " + " ^ sub ts2 (prec + 1) | |
| 570 | | TupleDifference (ts1, ts2) => | |
| 35280 
54ab4921f826
fixed a few bugs in Nitpick and removed unreferenced variables
 blanchet parents: 
35187diff
changeset | 571 | sub ts1 prec ^ " - " ^ sub ts2 (prec + 1) | 
| 
54ab4921f826
fixed a few bugs in Nitpick and removed unreferenced variables
 blanchet parents: 
35187diff
changeset | 572 | | TupleIntersect (ts1, ts2) => sub ts1 prec ^ " & " ^ sub ts2 prec | 
| 33192 | 573 | | TupleProduct (ts1, ts2) => sub ts1 prec ^ "->" ^ sub ts2 prec | 
| 34124 
c4628a1dcf75
added support for binary nat/int representation to Nitpick
 blanchet parents: 
34121diff
changeset | 574 | | TupleProject (ts, c) => sub ts prec ^ "[" ^ string_of_int c ^ "]" | 
| 33192 | 575 |          | TupleSet ts => "{" ^ commas (map string_for_tuple ts) ^ "}"
 | 
| 576 | | TupleRange (t1, t2) => | |
| 577 |            "{" ^ string_for_tuple t1 ^
 | |
| 578 | (if t1 = t2 then "" else " .. " ^ string_for_tuple t2) ^ "}" | |
| 579 | | TupleArea (t1, t2) => | |
| 580 |            "{" ^ string_for_tuple t1 ^ " # " ^ string_for_tuple t2 ^ "}"
 | |
| 581 | | TupleAtomSeq x => atom_seq_name x | |
| 582 | | TupleSetReg x => tuple_set_reg_name x) ^ | |
| 583 | (if need_parens then ")" else "") | |
| 584 | end | |
| 585 | in sub tuple_set 0 end | |
| 586 | ||
| 587 | fun string_for_tuple_assign (AssignTuple (x, t)) = | |
| 588 | tuple_reg_name x ^ " := " ^ string_for_tuple t ^ "\n" | |
| 589 | | string_for_tuple_assign (AssignTupleSet (x, ts)) = | |
| 590 | tuple_set_reg_name x ^ " := " ^ string_for_tuple_set ts ^ "\n" | |
| 591 | ||
| 50487 | 592 | fun string_for_bound (zs, tss) = | 
| 593 | "bounds " ^ commas (map commented_rel_name zs) ^ ": " ^ | |
| 33192 | 594 | (if length tss = 1 then "" else "[") ^ commas (map string_for_tuple_set tss) ^ | 
| 595 | (if length tss = 1 then "" else "]") ^ "\n" | |
| 596 | ||
| 597 | fun int_string_for_bound (opt_n, tss) = | |
| 598 | (case opt_n of | |
| 34124 
c4628a1dcf75
added support for binary nat/int representation to Nitpick
 blanchet parents: 
34121diff
changeset | 599 | SOME n => signed_string_of_int n ^ ": " | 
| 33192 | 600 | | NONE => "") ^ "[" ^ commas (map string_for_tuple_set tss) ^ "]" | 
| 601 | ||
| 602 | val prec_All = 1 | |
| 603 | val prec_Or = 2 | |
| 604 | val prec_Iff = 3 | |
| 605 | val prec_Implies = 4 | |
| 606 | val prec_And = 5 | |
| 607 | val prec_Not = 6 | |
| 608 | val prec_Eq = 7 | |
| 609 | val prec_Some = 8 | |
| 610 | val prec_SHL = 9 | |
| 611 | val prec_Add = 10 | |
| 612 | val prec_Mult = 11 | |
| 613 | val prec_Override = 12 | |
| 614 | val prec_Intersect = 13 | |
| 615 | val prec_Product = 14 | |
| 616 | val prec_IfNo = 15 | |
| 617 | val prec_Project = 17 | |
| 618 | val prec_Join = 18 | |
| 619 | val prec_BitNot = 19 | |
| 620 | ||
| 621 | fun precedence_f (All _) = prec_All | |
| 622 | | precedence_f (Exist _) = prec_All | |
| 623 | | precedence_f (FormulaLet _) = prec_All | |
| 624 | | precedence_f (FormulaIf _) = prec_All | |
| 625 | | precedence_f (Or _) = prec_Or | |
| 626 | | precedence_f (Iff _) = prec_Iff | |
| 627 | | precedence_f (Implies _) = prec_Implies | |
| 628 | | precedence_f (And _) = prec_And | |
| 629 | | precedence_f (Not _) = prec_Not | |
| 630 | | precedence_f (Acyclic _) = no_prec | |
| 631 | | precedence_f (Function _) = no_prec | |
| 632 | | precedence_f (Functional _) = no_prec | |
| 633 | | precedence_f (TotalOrdering _) = no_prec | |
| 634 | | precedence_f (Subset _) = prec_Eq | |
| 635 | | precedence_f (RelEq _) = prec_Eq | |
| 636 | | precedence_f (IntEq _) = prec_Eq | |
| 637 | | precedence_f (LT _) = prec_Eq | |
| 638 | | precedence_f (LE _) = prec_Eq | |
| 639 | | precedence_f (No _) = prec_Some | |
| 640 | | precedence_f (Lone _) = prec_Some | |
| 641 | | precedence_f (One _) = prec_Some | |
| 642 | | precedence_f (Some _) = prec_Some | |
| 643 | | precedence_f False = no_prec | |
| 644 | | precedence_f True = no_prec | |
| 645 | | precedence_f (FormulaReg _) = no_prec | |
| 646 | and precedence_r (RelLet _) = prec_All | |
| 647 | | precedence_r (RelIf _) = prec_All | |
| 648 | | precedence_r (Union _) = prec_Add | |
| 649 | | precedence_r (Difference _) = prec_Add | |
| 650 | | precedence_r (Override _) = prec_Override | |
| 651 | | precedence_r (Intersect _) = prec_Intersect | |
| 652 | | precedence_r (Product _) = prec_Product | |
| 653 | | precedence_r (IfNo _) = prec_IfNo | |
| 654 | | precedence_r (Project _) = prec_Project | |
| 655 | | precedence_r (Join _) = prec_Join | |
| 656 | | precedence_r (Closure _) = prec_BitNot | |
| 657 | | precedence_r (ReflexiveClosure _) = prec_BitNot | |
| 658 | | precedence_r (Transpose _) = prec_BitNot | |
| 659 | | precedence_r (Comprehension _) = no_prec | |
| 660 | | precedence_r (Bits _) = no_prec | |
| 661 | | precedence_r (Int _) = no_prec | |
| 662 | | precedence_r Iden = no_prec | |
| 663 | | precedence_r Ints = no_prec | |
| 664 | | precedence_r None = no_prec | |
| 665 | | precedence_r Univ = no_prec | |
| 666 | | precedence_r (Atom _) = no_prec | |
| 667 | | precedence_r (AtomSeq _) = no_prec | |
| 668 | | precedence_r (Rel _) = no_prec | |
| 669 | | precedence_r (Var _) = no_prec | |
| 670 | | precedence_r (RelReg _) = no_prec | |
| 671 | and precedence_i (Sum _) = prec_All | |
| 672 | | precedence_i (IntLet _) = prec_All | |
| 673 | | precedence_i (IntIf _) = prec_All | |
| 674 | | precedence_i (SHL _) = prec_SHL | |
| 675 | | precedence_i (SHA _) = prec_SHL | |
| 676 | | precedence_i (SHR _) = prec_SHL | |
| 677 | | precedence_i (Add _) = prec_Add | |
| 678 | | precedence_i (Sub _) = prec_Add | |
| 679 | | precedence_i (Mult _) = prec_Mult | |
| 680 | | precedence_i (Div _) = prec_Mult | |
| 681 | | precedence_i (Mod _) = prec_Mult | |
| 682 | | precedence_i (Cardinality _) = no_prec | |
| 683 | | precedence_i (SetSum _) = no_prec | |
| 684 | | precedence_i (BitOr _) = prec_Intersect | |
| 685 | | precedence_i (BitXor _) = prec_Intersect | |
| 686 | | precedence_i (BitAnd _) = prec_Intersect | |
| 687 | | precedence_i (BitNot _) = prec_BitNot | |
| 688 | | precedence_i (Neg _) = prec_BitNot | |
| 689 | | precedence_i (Absolute _) = prec_BitNot | |
| 690 | | precedence_i (Signum _) = prec_BitNot | |
| 691 | | precedence_i (Num _) = no_prec | |
| 692 | | precedence_i (IntReg _) = no_prec | |
| 693 | ||
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 694 | fun write_problem out problems = | 
| 33192 | 695 | let | 
| 696 | fun out_outmost_f (And (f1, f2)) = | |
| 697 | (out_outmost_f f1; out "\n && "; out_outmost_f f2) | |
| 698 | | out_outmost_f f = out_f f prec_And | |
| 699 | and out_f formula outer_prec = | |
| 700 | let | |
| 701 | val prec = precedence_f formula | |
| 702 | val need_parens = (prec < outer_prec) | |
| 703 | in | |
| 704 |         (if need_parens then out "(" else ());
 | |
| 705 | (case formula of | |
| 706 | All (ds, f) => (out "all ["; out_decls ds; out "] | "; out_f f prec) | |
| 707 | | Exist (ds, f) => | |
| 708 | (out "some ["; out_decls ds; out "] | "; out_f f prec) | |
| 709 | | FormulaLet (bs, f) => | |
| 710 | (out "let ["; out_assigns bs; out "] | "; out_f f prec) | |
| 711 | | FormulaIf (f, f1, f2) => | |
| 712 | (out "if "; out_f f prec; out " then "; out_f f1 prec; out " else "; | |
| 713 | out_f f2 prec) | |
| 714 | | Or (f1, f2) => (out_f f1 prec; out " || "; out_f f2 prec) | |
| 715 | | Iff (f1, f2) => (out_f f1 prec; out " <=> "; out_f f2 prec) | |
| 716 | | Implies (f1, f2) => (out_f f1 (prec + 1); out " => "; out_f f2 prec) | |
| 717 | | And (f1, f2) => (out_f f1 prec; out " && "; out_f f2 prec) | |
| 718 | | Not f => (out "! "; out_f f prec) | |
| 719 |          | Acyclic x => out ("ACYCLIC(" ^ rel_name x ^ ")")
 | |
| 720 | | Function (x, r1, r2) => | |
| 721 |            (out ("FUNCTION(" ^ rel_name x ^ ", "); out_r r1 0; out " -> one ";
 | |
| 722 | out_r r2 0; out ")") | |
| 723 | | Functional (x, r1, r2) => | |
| 724 |            (out ("FUNCTION(" ^ rel_name x ^ ", "); out_r r1 0; out " -> lone ";
 | |
| 725 | out_r r2 0; out ")") | |
| 38126 | 726 | | TotalOrdering (x, r1, r2, r3) => | 
| 727 |            (out ("TOTAL_ORDERING(" ^ rel_name x ^ ", "); out_r r1 0; out ", ";
 | |
| 728 | out_r r2 0; out ", "; out_r r3 0; out ")") | |
| 33192 | 729 | | Subset (r1, r2) => (out_r r1 prec; out " in "; out_r r2 prec) | 
| 730 | | RelEq (r1, r2) => (out_r r1 prec; out " = "; out_r r2 prec) | |
| 731 | | IntEq (i1, i2) => (out_i i1 prec; out " = "; out_i i2 prec) | |
| 732 | | LT (i1, i2) => (out_i i1 prec; out " < "; out_i i2 prec) | |
| 733 | | LE (i1, i2) => (out_i i1 prec; out " <= "; out_i i2 prec) | |
| 734 | | No r => (out "no "; out_r r prec) | |
| 735 | | Lone r => (out "lone "; out_r r prec) | |
| 736 | | One r => (out "one "; out_r r prec) | |
| 737 | | Some r => (out "some "; out_r r prec) | |
| 738 | | False => out "false" | |
| 739 | | True => out "true" | |
| 740 | | FormulaReg j => out (formula_reg_name j)); | |
| 741 | (if need_parens then out ")" else ()) | |
| 742 | end | |
| 743 | and out_r rel_expr outer_prec = | |
| 744 | let | |
| 745 | val prec = precedence_r rel_expr | |
| 746 | val need_parens = (prec < outer_prec) | |
| 747 | in | |
| 748 |         (if need_parens then out "(" else ());
 | |
| 749 | (case rel_expr of | |
| 750 | RelLet (bs, r) => | |
| 751 | (out "let ["; out_assigns bs; out "] | "; out_r r prec) | |
| 752 | | RelIf (f, r1, r2) => | |
| 753 | (out "if "; out_f f prec; out " then "; out_r r1 prec; | |
| 754 | out " else "; out_r r2 prec) | |
| 755 | | Union (r1, r2) => (out_r r1 prec; out " + "; out_r r2 (prec + 1)) | |
| 756 | | Difference (r1, r2) => | |
| 757 | (out_r r1 prec; out " - "; out_r r2 (prec + 1)) | |
| 758 | | Override (r1, r2) => (out_r r1 prec; out " ++ "; out_r r2 prec) | |
| 759 | | Intersect (r1, r2) => (out_r r1 prec; out " & "; out_r r2 prec) | |
| 760 | | Product (r1, r2) => (out_r r1 prec; out "->"; out_r r2 prec) | |
| 761 | | IfNo (r1, r2) => (out_r r1 prec; out "\\"; out_r r2 prec) | |
| 762 | | Project (r1, is) => (out_r r1 prec; out "["; out_columns is; out "]") | |
| 763 | | Join (r1, r2) => (out_r r1 prec; out "."; out_r r2 (prec + 1)) | |
| 764 | | Closure r => (out "^"; out_r r prec) | |
| 765 | | ReflexiveClosure r => (out "*"; out_r r prec) | |
| 766 | | Transpose r => (out "~"; out_r r prec) | |
| 767 | | Comprehension (ds, f) => | |
| 768 |            (out "{["; out_decls ds; out "] | "; out_f f 0; out "}")
 | |
| 769 | | Bits i => (out "Bits["; out_i i 0; out "]") | |
| 770 | | Int i => (out "Int["; out_i i 0; out "]") | |
| 771 | | Iden => out "iden" | |
| 772 | | Ints => out "ints" | |
| 773 | | None => out "none" | |
| 774 | | Univ => out "univ" | |
| 775 | | Atom j => out (atom_name j) | |
| 776 | | AtomSeq x => out (atom_seq_name x) | |
| 777 | | Rel x => out (rel_name x) | |
| 778 | | Var x => out (var_name x) | |
| 779 | | RelReg (_, j) => out (rel_reg_name j)); | |
| 780 | (if need_parens then out ")" else ()) | |
| 781 | end | |
| 782 | and out_i int_expr outer_prec = | |
| 783 | let | |
| 784 | val prec = precedence_i int_expr | |
| 785 | val need_parens = (prec < outer_prec) | |
| 786 | in | |
| 787 |         (if need_parens then out "(" else ());
 | |
| 788 | (case int_expr of | |
| 789 | Sum (ds, i) => (out "sum ["; out_decls ds; out "] | "; out_i i prec) | |
| 790 | | IntLet (bs, i) => | |
| 791 | (out "let ["; out_assigns bs; out "] | "; out_i i prec) | |
| 792 | | IntIf (f, i1, i2) => | |
| 793 | (out "if "; out_f f prec; out " then "; out_i i1 prec; | |
| 794 | out " else "; out_i i2 prec) | |
| 795 | | SHL (i1, i2) => (out_i i1 prec; out " << "; out_i i2 (prec + 1)) | |
| 796 | | SHA (i1, i2) => (out_i i1 prec; out " >> "; out_i i2 (prec + 1)) | |
| 797 | | SHR (i1, i2) => (out_i i1 prec; out " >>> "; out_i i2 (prec + 1)) | |
| 798 | | Add (i1, i2) => (out_i i1 prec; out " + "; out_i i2 (prec + 1)) | |
| 799 | | Sub (i1, i2) => (out_i i1 prec; out " - "; out_i i2 (prec + 1)) | |
| 800 | | Mult (i1, i2) => (out_i i1 prec; out " * "; out_i i2 (prec + 1)) | |
| 801 | | Div (i1, i2) => (out_i i1 prec; out " / "; out_i i2 (prec + 1)) | |
| 802 | | Mod (i1, i2) => (out_i i1 prec; out " % "; out_i i2 (prec + 1)) | |
| 803 |          | Cardinality r => (out "#("; out_r r 0; out ")")
 | |
| 804 |          | SetSum r => (out "sum("; out_r r 0; out ")")
 | |
| 805 | | BitOr (i1, i2) => (out_i i1 prec; out " | "; out_i i2 prec) | |
| 806 | | BitXor (i1, i2) => (out_i i1 prec; out " ^ "; out_i i2 prec) | |
| 807 | | BitAnd (i1, i2) => (out_i i1 prec; out " & "; out_i i2 prec) | |
| 808 | | BitNot i => (out "~"; out_i i prec) | |
| 809 | | Neg i => (out "-"; out_i i prec) | |
| 810 | | Absolute i => (out "abs "; out_i i prec) | |
| 811 | | Signum i => (out "sgn "; out_i i prec) | |
| 34124 
c4628a1dcf75
added support for binary nat/int representation to Nitpick
 blanchet parents: 
34121diff
changeset | 812 | | Num k => out (signed_string_of_int k) | 
| 33192 | 813 | | IntReg j => out (int_reg_name j)); | 
| 814 | (if need_parens then out ")" else ()) | |
| 815 | end | |
| 816 | and out_decls [] = () | |
| 817 | | out_decls [d] = out_decl d | |
| 818 | | out_decls (d :: ds) = (out_decl d; out ", "; out_decls ds) | |
| 819 | and out_decl (DeclNo (x, r)) = | |
| 820 | (out (var_name x); out " : no "; out_r r 0) | |
| 821 | | out_decl (DeclLone (x, r)) = | |
| 822 | (out (var_name x); out " : lone "; out_r r 0) | |
| 823 | | out_decl (DeclOne (x, r)) = | |
| 824 | (out (var_name x); out " : one "; out_r r 0) | |
| 825 | | out_decl (DeclSome (x, r)) = | |
| 826 | (out (var_name x); out " : some "; out_r r 0) | |
| 827 | | out_decl (DeclSet (x, r)) = | |
| 828 | (out (var_name x); out " : set "; out_r r 0) | |
| 829 | and out_assigns [] = () | |
| 830 | | out_assigns [b] = out_assign b | |
| 831 | | out_assigns (b :: bs) = (out_assign b; out ", "; out_assigns bs) | |
| 832 | and out_assign (AssignFormulaReg (j, f)) = | |
| 833 | (out (formula_reg_name j); out " := "; out_f f 0) | |
| 834 | | out_assign (AssignRelReg ((_, j), r)) = | |
| 835 | (out (rel_reg_name j); out " := "; out_r r 0) | |
| 836 | | out_assign (AssignIntReg (j, i)) = | |
| 837 | (out (int_reg_name j); out " := "; out_i i 0) | |
| 838 | and out_columns [] = () | |
| 839 | | out_columns [i] = out_i i 0 | |
| 840 | | out_columns (i :: is) = (out_i i 0; out ", "; out_columns is) | |
| 841 |     and out_problem {comment, settings, univ_card, tuple_assigns, bounds,
 | |
| 842 | int_bounds, expr_assigns, formula} = | |
| 843 |         (out ("\n" ^ block_comment comment ^
 | |
| 844 | implode (map (fn (key, value) => key ^ ": " ^ value ^ "\n") | |
| 845 | settings) ^ | |
| 846 | "univ: " ^ atom_seq_name (univ_card, 0) ^ "\n" ^ | |
| 847 | implode (map string_for_tuple_assign tuple_assigns) ^ | |
| 50487 | 848 | implode (map string_for_bound bounds) ^ | 
| 33192 | 849 | (if int_bounds = [] then | 
| 850 | "" | |
| 851 | else | |
| 852 | "int_bounds: " ^ | |
| 853 | commas (map int_string_for_bound int_bounds) ^ "\n")); | |
| 72183 | 854 | List.app (fn b => (out_assign b; out ";")) expr_assigns; | 
| 33192 | 855 | out "solve "; out_outmost_f formula; out ";\n") | 
| 856 | in | |
| 35695 | 857 |     out ("// This file was generated by Isabelle (most likely Nitpick)\n" ^
 | 
| 43085 
0a2f5b86bdd7
first step in sharing more code between ATP and Metis translation
 blanchet parents: 
41793diff
changeset | 858 | "// " ^ ATP_Util.timestamp () ^ "\n"); | 
| 72183 | 859 | List.app out_problem problems | 
| 33192 | 860 | end | 
| 861 | ||
| 35718 | 862 | (** Parsing of solution **) | 
| 863 | ||
| 33192 | 864 | fun is_ident_char s = | 
| 34936 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 865 | Symbol.is_ascii_letter s orelse Symbol.is_ascii_digit s orelse | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 866 | s = "_" orelse s = "'" orelse s = "$" | 
| 33192 | 867 | |
| 868 | fun strip_blanks [] = [] | |
| 869 |   | strip_blanks (" " :: ss) = strip_blanks ss
 | |
| 870 | | strip_blanks [s1, " "] = [s1] | |
| 871 | | strip_blanks (s1 :: " " :: s2 :: ss) = | |
| 872 | if is_ident_char s1 andalso is_ident_char s2 then | |
| 873 | s1 :: " " :: strip_blanks (s2 :: ss) | |
| 874 | else | |
| 875 | strip_blanks (s1 :: s2 :: ss) | |
| 876 | | strip_blanks (s :: ss) = s :: strip_blanks ss | |
| 877 | ||
| 38198 | 878 | val scan_nat = | 
| 879 | Scan.repeat1 (Scan.one Symbol.is_ascii_digit) | |
| 53093 | 880 | >> (the o Int.fromString o implode) | 
| 50487 | 881 | val scan_rel_name = | 
| 38126 | 882 | ($$ "s" |-- scan_nat >> pair 1 | 
| 883 | || $$ "r" |-- scan_nat >> pair 2 | |
| 884 | || ($$ "m" |-- scan_nat --| $$ "_") -- scan_nat) -- Scan.option ($$ "'") | |
| 885 | >> (fn ((n, j), SOME _) => (n, ~j - 1) | |
| 50487 | 886 | | ((n, j), NONE) => (n, j)) | 
| 33192 | 887 | val scan_atom = $$ "A" |-- scan_nat | 
| 38198 | 888 | fun parse_non_empty_list scan = scan ::: Scan.repeat ($$ "," |-- scan) | 
| 889 | fun parse_list scan = parse_non_empty_list scan || Scan.succeed [] | |
| 890 | val parse_tuple = $$ "[" |-- parse_list scan_atom --| $$ "]" | |
| 891 | val parse_tuple_set = $$ "[" |-- parse_list parse_tuple --| $$ "]" | |
| 50487 | 892 | val parse_assignment = (scan_rel_name --| $$ "=") -- parse_tuple_set | 
| 893 | val parse_instance = | |
| 38126 | 894 | Scan.this_string "relations:" | 
| 50487 | 895 |   |-- $$ "{" |-- parse_list parse_assignment --| $$ "}"
 | 
| 33192 | 896 | |
| 50487 | 897 | val extract_instance = | 
| 35336 | 898 | fst o Scan.finite Symbol.stopper | 
| 899 | (Scan.error (!! (fn _ => | |
| 38198 | 900 |                                 raise SYNTAX ("Kodkod.extract_instance",
 | 
| 35336 | 901 | "ill-formed Kodkodi output")) | 
| 50487 | 902 | parse_instance)) | 
| 40627 
becf5d5187cc
renamed raw "explode" function to "raw_explode" to emphasize its meaning;
 wenzelm parents: 
40411diff
changeset | 903 | o strip_blanks o raw_explode | 
| 33192 | 904 | |
| 905 | val problem_marker = "*** PROBLEM " | |
| 906 | val outcome_marker = "---OUTCOME---\n" | |
| 907 | val instance_marker = "---INSTANCE---\n" | |
| 908 | ||
| 909 | fun read_section_body marker = | |
| 910 | Substring.string o fst o Substring.position "\n\n" | |
| 911 | o Substring.triml (size marker) | |
| 912 | ||
| 50487 | 913 | fun read_next_instance s = | 
| 33192 | 914 | let val s = Substring.position instance_marker s |> snd in | 
| 915 | if Substring.isEmpty s then | |
| 916 |       raise SYNTAX ("Kodkod.read_next_instance", "expected \"INSTANCE\" marker")
 | |
| 917 | else | |
| 50487 | 918 | read_section_body instance_marker s |> extract_instance | 
| 33192 | 919 | end | 
| 920 | ||
| 50487 | 921 | fun read_next_outcomes j (s, ps, js) = | 
| 33192 | 922 | let val (s1, s2) = Substring.position outcome_marker s in | 
| 34936 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 923 | if Substring.isEmpty s2 orelse | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 924 | not (Substring.isEmpty (Substring.position problem_marker s1 | 
| 
c4f04bee79f3
some work on Nitpick's support for quotient types;
 blanchet parents: 
34124diff
changeset | 925 | |> snd)) then | 
| 33192 | 926 | (s, ps, js) | 
| 927 | else | |
| 928 | let | |
| 929 | val outcome = read_section_body outcome_marker s2 | |
| 930 | val s = Substring.triml (size outcome_marker) s2 | |
| 931 | in | |
| 932 | if String.isSuffix "UNSATISFIABLE" outcome then | |
| 50487 | 933 | read_next_outcomes j (s, ps, j :: js) | 
| 33192 | 934 | else if String.isSuffix "SATISFIABLE" outcome then | 
| 50487 | 935 | read_next_outcomes j (s, (j, read_next_instance s2) :: ps, js) | 
| 33192 | 936 | else | 
| 937 |           raise SYNTAX ("Kodkod.read_next_outcomes",
 | |
| 938 | "unknown outcome " ^ quote outcome) | |
| 939 | end | |
| 940 | end | |
| 941 | ||
| 50487 | 942 | fun read_next_problems (s, ps, js) = | 
| 33192 | 943 | let val s = Substring.position problem_marker s |> snd in | 
| 944 | if Substring.isEmpty s then | |
| 945 | (ps, js) | |
| 946 | else | |
| 947 | let | |
| 948 | val s = Substring.triml (size problem_marker) s | |
| 949 | val j_plus_1 = s |> Substring.takel (not_equal #" ") |> Substring.string | |
| 950 | |> Int.fromString |> the | |
| 951 | val j = j_plus_1 - 1 | |
| 50487 | 952 | in read_next_problems (read_next_outcomes j (s, ps, js)) end | 
| 33192 | 953 | end | 
| 954 |   handle Option.Option => raise SYNTAX ("Kodkod.read_next_problems",
 | |
| 955 | "expected number after \"PROBLEM\"") | |
| 956 | ||
| 72188 
b155681b9f6a
removed obsolete created_temp_dir: ISABELLE_TMP is always present for the running Isabelle/ML process;
 wenzelm parents: 
72183diff
changeset | 957 | |
| 35718 | 958 | (** Main Kodkod entry point **) | 
| 959 | ||
| 72188 
b155681b9f6a
removed obsolete created_temp_dir: ISABELLE_TMP is always present for the running Isabelle/ML process;
 wenzelm parents: 
72183diff
changeset | 960 | fun serial_string_and_temporary_dir overlord = | 
| 
b155681b9f6a
removed obsolete created_temp_dir: ISABELLE_TMP is always present for the running Isabelle/ML process;
 wenzelm parents: 
72183diff
changeset | 961 |   if overlord then ("", getenv "ISABELLE_HOME_USER")
 | 
| 
b155681b9f6a
removed obsolete created_temp_dir: ISABELLE_TMP is always present for the running Isabelle/ML process;
 wenzelm parents: 
72183diff
changeset | 962 | else (serial_string (), getenv "ISABELLE_TMP") | 
| 35718 | 963 | |
| 35814 | 964 | (* The fudge term below is to account for Kodkodi's slow start-up time, which | 
| 965 | is partly due to the JVM and partly due to the ML "bash" function. *) | |
| 966 | val fudge_ms = 250 | |
| 967 | ||
| 72200 | 968 | fun uncached_solve_any_problem overlord deadline max_threads0 max_solutions problems = | 
| 33192 | 969 | let | 
| 34121 
5e831d805118
get rid of polymorphic equality in Nitpick's code + a few minor cleanups
 blanchet parents: 
33982diff
changeset | 970 | val j = find_index (curry (op =) True o #formula) problems | 
| 33192 | 971 | val indexed_problems = if j >= 0 then | 
| 972 | [(j, nth problems j)] | |
| 973 | else | |
| 35187 
3acab6c90d4a
don't destroy "Suc" in Nitpick and fix logic of Kodkod filtering (accidentally flipped in previous change)
 blanchet parents: 
35185diff
changeset | 974 | filter_out (is_problem_trivially_false o snd) | 
| 
3acab6c90d4a
don't destroy "Suc" in Nitpick and fix logic of Kodkod filtering (accidentally flipped in previous change)
 blanchet parents: 
35185diff
changeset | 975 | (0 upto length problems - 1 ~~ problems) | 
| 33192 | 976 | val triv_js = filter_out (AList.defined (op =) indexed_problems) | 
| 977 | (0 upto length problems - 1) | |
| 978 | val reindex = fst o nth indexed_problems | |
| 72191 
d436ba9ac9aa
proper treatment of timeout: <= 0 means already timed out, but for $KODKODI/bin/kodkodi it would mean NO timeout;
 wenzelm parents: 
72188diff
changeset | 979 | |
| 72200 | 980 | val max_threads = | 
| 981 | if max_threads0 = 0 | |
| 982 | then Options.default_int \<^system_option>\<open>kodkod_max_threads\<close> | |
| 983 | else max_threads0 | |
| 984 | ||
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 985 | val external_process = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 986 | not (Options.default_bool \<^system_option>\<open>kodkod_scala\<close>) orelse overlord | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 987 | val timeout0 = Time.toMilliseconds (deadline - Time.now ()) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 988 | val timeout = if external_process then timeout0 - fudge_ms else timeout0 | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 989 | |
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 990 | val solve_all = max_solutions > 1 | 
| 33192 | 991 | in | 
| 992 | if null indexed_problems then | |
| 35333 
f61de25f71f9
distinguish between Kodkodi warnings and errors in Nitpick;
 blanchet parents: 
35309diff
changeset | 993 | Normal ([], triv_js, "") | 
| 72191 
d436ba9ac9aa
proper treatment of timeout: <= 0 means already timed out, but for $KODKODI/bin/kodkodi it would mean NO timeout;
 wenzelm parents: 
72188diff
changeset | 994 | else if timeout <= 0 then TimedOut triv_js | 
| 33192 | 995 | else | 
| 996 | let | |
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 997 | val kki = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 998 | let | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 999 | val buf = Unsynchronized.ref Buffer.empty | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1000 | fun out s = Unsynchronized.change buf (Buffer.add s) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1001 | val _ = write_problem out (map snd indexed_problems) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1002 | in Buffer.content (! buf) end | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1003 | val (rc, out, err) = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1004 | if external_process then | 
| 33192 | 1005 | let | 
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1006 | val (serial_str, temp_dir) = serial_string_and_temporary_dir overlord | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1007 | fun path_for suf = Path.explode (temp_dir ^ "/kodkodi" ^ serial_str ^ "." ^ suf) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1008 | val kki_path = path_for "kki" | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1009 | val out_path = path_for "out" | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1010 | val err_path = path_for "err" | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1011 | |
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1012 | fun remove_temporary_files () = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1013 | if overlord then () | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1014 | else List.app (ignore o try File.rm) [kki_path, out_path, err_path] | 
| 33192 | 1015 | in | 
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1016 | let | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1017 | val _ = File.write kki_path kki | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1018 | val rc = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1019 |                   Isabelle_System.bash ("cd " ^ Bash.string temp_dir ^ ";\n\
 | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1020 | \\"$KODKODI/bin/kodkodi\"" ^ | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1021 |                     (" -max-msecs " ^ string_of_int timeout) ^
 | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1022 | (if solve_all then " -solve-all" else "") ^ | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1023 | " -max-solutions " ^ string_of_int max_solutions ^ | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1024 | (if max_threads > 0 then " -max-threads " ^ string_of_int max_threads else "") ^ | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1025 | " < " ^ File.bash_path kki_path ^ | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1026 | " > " ^ File.bash_path out_path ^ | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1027 | " 2> " ^ File.bash_path err_path) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1028 | val out = File.read out_path | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1029 | val err = File.read err_path | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1030 | val _ = remove_temporary_files () | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1031 | in (rc, out, err) end | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1032 | handle exn => (remove_temporary_files (); Exn.reraise exn) | 
| 33192 | 1033 | end | 
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1034 | else | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1035 | (timeout, (solve_all, (max_solutions, (max_threads, kki)))) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1036 | |> let open XML.Encode in pair int (pair bool (pair int (pair int string))) end | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1037 | |> YXML.string_of_body | 
| 73419 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
72333diff
changeset | 1038 | |> \<^scala>\<open>kodkod\<close> | 
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1039 | |> YXML.parse_body | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1040 | |> let open XML.Decode in triple int string string end | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1041 | |
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1042 | val (ps, nontriv_js) = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1043 | read_next_problems (Substring.full out, [], []) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1044 | |>> rev ||> rev | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1045 | |> apfst (map (apfst reindex)) |> apsnd (map reindex) | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1046 | val js = triv_js @ nontriv_js | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1047 | |
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1048 | val first_error = | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1049 | trim_split_lines err | 
| 72203 | 1050 | |> map | 
| 1051 | (perhaps (try (unsuffix ".")) #> | |
| 1052 | perhaps (try (unprefix "Solve error: ")) #> | |
| 1053 | perhaps (try (unprefix "Error: "))) | |
| 1054 | |> find_first (fn line => line <> "" andalso line <> "EXIT") | |
| 72196 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1055 | |> the_default "" | 
| 
6dba090358d2
invoke Nitpick/Kodkod via Isabelle/Scala (instead of external process);
 wenzelm parents: 
72191diff
changeset | 1056 | in | 
| 72330 | 1057 | if not (null ps) orelse rc = 0 then Normal (ps, js, first_error) | 
| 1058 | else if rc = 2 then TimedOut js | |
| 1059 | else if rc = 130 then raise Exn.Interrupt | |
| 1060 | else Error (if first_error = "" then "Unknown error" else first_error, js) | |
| 33192 | 1061 | end | 
| 1062 | end | |
| 1063 | ||
| 35814 | 1064 | val cached_outcome = | 
| 1065 | Synchronized.var "Kodkod.cached_outcome" | |
| 1066 | (NONE : ((int * problem list) * outcome) option) | |
| 1067 | ||
| 41793 
c7a2669ae75d
tweaked Nitpick based on C++ memory model example
 blanchet parents: 
40743diff
changeset | 1068 | fun solve_any_problem debug overlord deadline max_threads max_solutions | 
| 
c7a2669ae75d
tweaked Nitpick based on C++ memory model example
 blanchet parents: 
40743diff
changeset | 1069 | problems = | 
| 35814 | 1070 | let | 
| 38189 | 1071 | fun do_solve () = | 
| 1072 | uncached_solve_any_problem overlord deadline max_threads max_solutions | |
| 1073 | problems | |
| 35814 | 1074 | in | 
| 41793 
c7a2669ae75d
tweaked Nitpick based on C++ memory model example
 blanchet parents: 
40743diff
changeset | 1075 | if debug orelse overlord then | 
| 35814 | 1076 | do_solve () | 
| 1077 | else | |
| 1078 | case AList.lookup (fn ((max1, ps1), (max2, ps2)) => | |
| 1079 | max1 = max2 andalso length ps1 = length ps2 andalso | |
| 1080 | forall problems_equivalent (ps1 ~~ ps2)) | |
| 1081 | (the_list (Synchronized.value cached_outcome)) | |
| 1082 | (max_solutions, problems) of | |
| 1083 | SOME outcome => outcome | |
| 1084 | | NONE => | |
| 1085 | let val outcome = do_solve () in | |
| 1086 | (case outcome of | |
| 39326 | 1087 | Normal (_, _, "") => | 
| 35814 | 1088 | Synchronized.change cached_outcome | 
| 1089 | (K (SOME ((max_solutions, problems), outcome))) | |
| 1090 | | _ => ()); | |
| 1091 | outcome | |
| 1092 | end | |
| 1093 | end | |
| 1094 | ||
| 33192 | 1095 | end; |