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