this repo has no description
1%-----------------------------------------------------------------------------% 2% MiniZinc standard library. 3%-----------------------------------------------------------------------------% 4% This file contains declarations of all functions, predicates and annotations 5% available in the base MiniZinc language. 6 7/*** 8 @groupdef MAIN The MiniZinc library 9*/ 10 11/*** 12 @groupdef annotations Annotations 13 14 These annotations control evaluation and solving behaviour. 15*/ 16 17 18/*** 19 @groupdef annotations.general General annotations 20*/ 21 22/** @group annotations.general Declare function as total, i.e. it does not put 23 any constraints on its arguments. */ 24annotation promise_total; 25 26/** @group annotations.export Always export function to intermediate representation to ensure 27 availability for later use. */ 28annotation export; 29 30/** @group annotations.general Declare that expression may have undefined result (to avoid warnings) */ 31annotation maybe_partial; 32 33/** @group annotations.general Declare that the annotated variable should be added to the output 34of the model. This annotation only has an effect when the model does not have an output item. */ 35annotation add_to_output; 36 37/** @group annotations.general Declare that the annotated variable should be only used for output. 38 This annotation can be used to define variables that are required for solution checkers, or 39 that are necessary for the output item. The annotated variable must be par. 40 */ 41annotation output_only; 42 43/** @group annotations.general Declare that the annotated variable is required for checking solutions. */ 44annotation mzn_check_var; 45 46/** @group annotations.general Declare that the annotated variable is required for checking solutions and has an enum type. */ 47annotation mzn_check_enum_var(set of int); 48 49/** @group annotations.general Declare a name for the annotated expression. */ 50annotation mzn_expression_name(string); 51 52/** @group annotations.general Declare a name for the annotated constraint. */ 53annotation mzn_constraint_name(string); 54 55 56/** @group annotations.general Declare the annotated variable as being functionally defined. 57 This annotation is introduced into FlatZinc code by the compiler. */ 58annotation is_defined_var; 59/** @group annotations.general Declare a variable as being introduced by the compiler. */ 60annotation var_is_introduced; 61/** @group annotations.general Declare variable: \a c as being functionally defined 62 by the annotated constraint. This annotation is introduced into FlatZinc code by the compiler. */ 63annotation defines_var(var $t: c); 64/** @group annotations.general Declare that the annotated array should be printed by 65 the solver with the given index sets \a a. This annotation is introduced into FlatZinc code by 66 the compiler. */ 67annotation output_array(array[$u] of set of int:a); 68/** @group annotations.general Declare that the annotated variable should be printed by 69 the solver. This annotation is introduced into FlatZinc code by 70 the compiler. */ 71annotation output_var; 72/** @group annotations.general Declare that the annotated expression is used to map 73 an expression back from FlatZinc to MiniZinc. */ 74annotation is_reverse_map; 75/** @group annotations.general Document the function or variable declaration item with 76 the string \a s. */ 77annotation doc_comment(string: s); 78/** @group annotations.general Representation of the call-stack when the annotated item 79 was introduced, as a string \a s. Can be used to uniquely identify variables and constraints across different 80 compilations of a model that may have different names. This annotations is introduced into 81 FlatZinc code by the compiler and is retained if --keep-paths argument is used. */ 82annotation mzn_path(string: s); 83/** @group annotations.general With debug build of mzn2fzn, call MiniZinc::mzn_break_here when 84 flattening this expression to make debugging easier. This annotation is ignored by the 85 release build.*/ 86annotation mzn_break_here; 87/** @group annotations.general Used to attach a name \a s to an expression, this should also propagate to 88 any sub-expressions or decomposition of the annotated expression. String annotations on expressions 89 are re-written as expression_name annotations */ 90annotation expression_name(string: s); 91/** @group annotations.general Used to attach a name \a s to a constraint and its decomposition. String 92 annotations on constraint keywords are re-written as constraint_name annotations */ 93annotation constraint_name(string: s); 94 95/** @group annotations.general Used internally by the compiler */ 96annotation mzn_rhs_from_assignment; 97 98/** @group annotations.general Marks a constraint as a recorded domain changing constraint (when mzn2fzn 99 called with -g flag */ 100annotation domain_change_constraint; 101 102/*** 103 @groupdef annotations.prop Propagation strength annotations 104*/ 105 106/** @group annotations.prop Annotate a constraint to use domain propagation */ 107annotation domain; 108/** @group annotations.prop Annotate a constraint to use bounds propagation */ 109annotation bounds; 110 111 112/*** 113 @groupdef annotations.search Search annotations 114*/ 115 116/** @group annotations.search Sequentially perform the searches specified in array \a s */ 117annotation seq_search(array[int] of ann: s); 118 119/** @group annotations.search Specify search on variables \a x, with variable selection 120 strategy \a select, value choice strategy \a choice, and exploration strategy 121 \a explore. If \a x is a multi-dimensional array, it is coerced to one-dimensional 122 in row-major order (as with the array1d function). 123*/ 124annotation int_search( 125 array[$X] of var int: x, 126 ann: select, 127 ann: choice, 128 ann: explore, 129); 130 131/** @group annotations.search Specify search on variables \a x, with variable selection 132 strategy \a select, and value choice strategy \a choice. 133 If \a x is a multi-dimensional array, it is coerced to one-dimensional 134 in row-major order (as with the array1d function). 135*/ 136annotation int_search( 137 array[$X] of var int: x, 138 ann: select, 139 ann: choice 140) = int_search(x,select,choice,complete); 141 142/** @group annotations.search Specify search on variables \a x, with variable selection 143 strategy \a select, value choice strategy \a choice, and exploration strategy 144 \a explore. 145 If \a x is a multi-dimensional array, it is coerced to one-dimensional 146 in row-major order (as with the array1d function). 147*/ 148annotation bool_search( 149 array[$X] of var bool: x, 150 ann: select, 151 ann: choice, 152 ann: explore 153); 154 155/** @group annotations.search Specify search on variables \a x, with variable selection 156 strategy \a select, and value choice strategy \a choice. 157 If \a x is a multi-dimensional array, it is coerced to one-dimensional 158 in row-major order (as with the array1d function). 159*/ 160annotation bool_search( 161 array[$X] of var bool: x, 162 ann: select, 163 ann: choice 164) = bool_search(x,select,choice,complete); 165 166/** @group annotations.search Specify search on variables \a x, 167 with precision \a prec, variable selection 168 strategy \a select, value choice strategy \a choice, and exploration strategy 169 \a explore. 170 If \a x is a multi-dimensional array, it is coerced to one-dimensional 171 in row-major order (as with the array1d function). 172*/ 173annotation float_search( 174 array[$X] of var float: x, 175 float: prec, 176 ann: select, 177 ann: choice, 178 ann: explore 179); 180 181/** @group annotations.search Specify search on variables \a x, 182 with precision \a prec, variable selection 183 strategy \a select, and value choice strategy \a choice. 184 If \a x is a multi-dimensional array, it is coerced to one-dimensional 185 in row-major order (as with the array1d function). 186*/ 187annotation float_search( 188 array[$X] of var float: x, 189 float: prec, 190 ann: select, 191 ann: choice 192) = float_search(x,prec,select,choice,complete); 193 194/** @group annotations.search Specify search on variables \a x, with variable selection 195 strategy \a select, value choice strategy \a choice, and exploration strategy 196 \a explore. 197 If \a x is a multi-dimensional array, it is coerced to one-dimensional 198 in row-major order (as with the array1d function). 199*/ 200annotation set_search( 201 array[$X] of var set of int: x, 202 ann: select, 203 ann: choice, 204 ann: explore 205); 206 207/** @group annotations.search Specify search on variables \a x, with variable selection 208 strategy \a select, and value choice strategy \a choice. 209 If \a x is a multi-dimensional array, it is coerced to one-dimensional 210 in row-major order (as with the array1d function). 211*/ 212annotation set_search( 213 array[$X] of var set of int: x, 214 ann: select, 215 ann: choice 216) = set_search(x,select,choice,complete); 217 218/*** 219 @groupdef annotations.search.varsel Variable selection annotations 220*/ 221 222/** @group annotations.search.varsel Search variables in the given order */ 223annotation input_order; 224/** @group annotations.search.varsel Choose the variable with the smallest domain */ 225annotation first_fail; 226/** @group annotations.search.varsel Choose the variable with the largest domain */ 227annotation anti_first_fail; 228/** @group annotations.search.varsel Choose the variable with the smallest value in its domain */ 229annotation smallest; 230/** @group annotations.search.varsel Choose the variable with the largest value in its domain */ 231annotation largest; 232/** @group annotations.search.varsel Choose the variable with the largest number of attached constraints */ 233annotation occurrence; 234/** @group annotations.search.varsel Choose the variable with the smallest domain, 235 breaking ties using the number of attached constraints */ 236annotation most_constrained; 237/** @group annotations.search.varsel Choose the variable with largest difference 238 between the two smallest values in its domain */ 239annotation max_regret; 240/** @group annotations.search.varsel Choose the variable with largest domain, divided 241 by the number of attached constraints weighted by how often they have caused failure */ 242annotation dom_w_deg; 243/** @group annotations.search.varsel Choose the variable with the highest impact so 244 far during the search */ 245annotation impact; 246 247/*** 248 @groupdef annotations.search.choice Value choice annotations 249*/ 250 251/** @group annotations.search.choice Assign values in ascending order */ 252annotation indomain; 253/** @group annotations.search.choice Assign the smallest value in the domain */ 254annotation indomain_min; 255/** @group annotations.search.choice Assign the largest value in the domain */ 256annotation indomain_max; 257/** @group annotations.search.choice Assign the value in the domain closest to 258 the mean of its current bounds */ 259annotation indomain_middle; 260/** @group annotations.search.choice Assign the middle value in the domain */ 261annotation indomain_median; 262/** @group annotations.search.choice Assign a random value from the domain */ 263annotation indomain_random; 264/** @group annotations.search.choice Bisect the domain, excluding the upper half first */ 265annotation indomain_split; 266/** @group annotations.search.choice Bisect the domain, randomly selecting which half to exclude first */ 267annotation indomain_split_random; 268/** @group annotations.search.choice Bisect the domain, excluding the lower half first */ 269annotation indomain_reverse_split; 270/** @group annotations.search.choice 271 If the domain consists of several contiguous intervals, reduce the 272 domain to the first interval. Otherwise bisect the domain. 273 */ 274annotation indomain_interval; 275/** @group annotations.search.choice Exclude the smallest value from the domain */ 276annotation outdomain_min; 277/** @group annotations.search.choice Exclude the largest value from the domain */ 278annotation outdomain_max; 279/** @group annotations.search.choice Exclude the middle value from the domain */ 280annotation outdomain_median; 281/** @group annotations.search.choice Exclude a random value from the domain */ 282annotation outdomain_random; 283 284/*** 285 @groupdef annotations.search.explore Exploration strategy annotations 286*/ 287 288/** @group annotations.search.explore Perform a complete search */ 289annotation complete; 290 291/*** 292 @groupdef annotations.search.restart Restart annotations 293*/ 294 295/** @group annotations.search.restart Restart with Luby sequence scaled by \a scale */ 296annotation restart_luby(int: scale); 297/** @group annotations.search.restart Restart with geometric sequence with parameters \a base and \a scale */ 298annotation restart_geometric(float: base, int: scale); 299/** @group annotations.search.restart Restart with linear sequence scaled by \a scale */ 300annotation restart_linear(int: scale); 301/** @group annotations.search.restart Restart after constant number of nodes \a scale */ 302annotation restart_constant(int: scale); 303/** @group annotations.search.restart Do not restart */ 304annotation restart_none; 305 306/*** 307 @groupdef annotations.warmstart Warm start annotations 308 309 To be put on the solve item, similar to search annotations. 310 A variable can be mentioned several times and in different 311 annotations but only one of the values is taken 312*/ 313 314/** @group annotations.warmstart Specify an array \a w of warm_start annotations 315 or other warm_start_array annotations. Can be useful to keep the annotation 316 order in FlatZinc for manual updating. 317 318 Note: if you have search annotations as well, put warm_starts into seq_search 319 in order to have precedence between both, which may matter. 320*/ 321annotation warm_start_array( array[int] of ann: w ); 322 323/** @group annotations.warmstart Specify warm start values \a v for an array of booleans \a x */ 324annotation warm_start( array[int] of var bool: x, array[int] of bool: v ); 325/** @group annotations.warmstart Specify warm start values \a v for an array of integers \a x */ 326annotation warm_start( array[int] of var int: x, array[int] of int: v ); 327/** @group annotations.warmstart Specify warm start values \a v for an array of floats \a x */ 328annotation warm_start( array[int] of var float: x, array[int] of float: v ); 329/** @group annotations.warmstart Specify warm start values \a v for an array of sets \a x */ 330annotation warm_start( array[int] of var set of int: x, array[int] of set of int: v ); 331 332 333/*** 334 @groupdef annotations.warmstart.optvals Warm start annotations with optional values 335 336 The value arrays can contain <> elements (absent values). 337 The following decompositions eliminate those elements 338 because FlatZinc 1.6 does not support optionals. 339*/ 340 341/** @group annotations.warmstart.optvals Specify warm start values \a v for an array of booleans \a x */ 342annotation warm_start( array[int] of var bool: x, array[int] of opt bool: v ) = 343 if 0==length(x) \/ 0==length(v) then 344 warm_start( x, [] ) 345 else 346 warm_start( [ x[i] | i in index_set(x) where 347 i-min(index_set(x))+min(index_set(v))>length(v) \/ 348 occurs( v[ i-min(index_set(x))+min(index_set(v)) ] ) ], 349 [ deopt(v[i]) | i in index_set(v) where occurs(v[i]) ] ) 350 endif; 351/** @group annotations.warmstart.optvals Specify warm start values \a v for an array of integers \a x */ 352annotation warm_start( array[int] of var int: x, array[int] of opt int: v ) = 353 if 0==length(x) \/ 0==length(v) then 354 warm_start( x, [] ) 355 else 356 warm_start( [ x[i] | i in index_set(x) where 357 i-min(index_set(x))+min(index_set(v))>length(v) \/ 358 occurs( v[ i-min(index_set(x))+min(index_set(v)) ] ) ], 359 [ deopt(v[i]) | i in index_set(v) where occurs(v[i]) ] ) 360 endif; 361/** @group annotations.warmstart.optvals Specify warm start values \a v for an array of floats \a x */ 362annotation warm_start( array[int] of var float: x, array[int] of opt float: v ) = 363 if 0==length(x) \/ 0==length(v) then 364 warm_start( x, [] ) 365 else 366 warm_start( [ x[i] | i in index_set(x) where 367 i-min(index_set(x))+min(index_set(v))>length(v) \/ 368 occurs( v[ i-min(index_set(x))+min(index_set(v)) ] ) ], 369 [ deopt(v[i]) | i in index_set(v) where occurs(v[i]) ] ) 370 endif; 371/** @group annotations.warmstart.optvals Specify warm start values \a v for an array of sets \a x */ 372annotation warm_start( array[int] of var set of int: x, array[int] of opt set of int: v ) = 373 if 0==length(x) \/ 0==length(v) then 374 warm_start( x, [] ) 375 else 376 warm_start( [ x[i] | i in index_set(x) where 377 i-min(index_set(x))+min(index_set(v))>length(v) \/ 378 occurs( v[ i-min(index_set(x))+min(index_set(v)) ] ) ], 379 [ deopt(v[i]) | i in index_set(v) where occurs(v[i]) ] ) 380 endif; 381 382 383 384/*** 385 @groupdef optiontypes Option type support 386 387 These functions and predicates implement the standard library for working 388 with option types. Note that option type support is still incomplete. 389*/ 390 391/** @group optiontypes Return value of \a x if \a x is not absent. Aborts 392 when evaluated on absent value. */ 393function $T: deopt(opt $T: x); 394 395/** @group optiontypes Return value \a x unchanged (since \a x is guaranteed 396 to be non-optional). */ 397function var $T: deopt(var $T: x) = x; 398 399/** @group optiontypes Test if \a x is not absent (always returns true) */ 400test occurs(var $T: x) = true; 401/** @group optiontypes Test if \a x is not absent */ 402test occurs(opt $T: x); 403/** @group optiontypes Test if \a x is absent (always returns false) */ 404test absent(var $T: x) = false; 405/** @group optiontypes Test if \a x is absent */ 406test absent(opt $T: x) = not occurs(x); 407 408/*** 409 @groupdef optiontypes.bool Option type support for Booleans 410*/ 411 412/** @group optiontypes.bool True iff \a x is not absent */ 413function var bool : occurs(var opt bool: x) ::promise_total = 414 let { 415 var bool : b = occurs_internal(x); 416 var bool : dx = deopt_internal(x); 417 constraint (x = reverse_map(b,dx)) :: is_reverse_map; 418 } in b; 419 420/** @group optiontypes.bool Return value of \a x (assumes that \a x is not absent) */ 421function var bool : deopt(var opt bool : x) ::promise_total = 422 let { 423 var bool : b = occurs_internal(x); 424 var bool : dx = deopt_internal(x); 425 constraint (x = reverse_map(b,dx)) :: is_reverse_map; 426 } in dx; 427 428/** @group optiontypes.bool True iff \a x is absent */ 429predicate absent(var opt bool: x) = not occurs(x); 430 431function var bool: occurs_internal(var opt bool: x) ::promise_total = 432 let { var bool : b; } in b; 433function var bool : deopt_internal(var opt bool : x) ::promise_total = 434 let { var bool: y } in y; 435 436function var opt bool: reverse_map(var bool: occ, var bool: d); 437function opt bool: reverse_map(bool: occ, bool: d) ::promise_total = 438 if occ then d else <> endif; 439 440predicate bool_opt_eq(var opt bool: x, var opt bool: y) = 441 deopt(x)=deopt(y) /\ occurs(x)=occurs(y); 442 443/** @group optiontypes.bool True iff both \a b0 and \a b1 are absent or 444 both are present and have the same value. */ 445predicate bool_eq(var opt bool: b0, var opt bool: b1) = 446 (absent(b0) /\ absent(b1)) 447 \/ (occurs(b0) /\ occurs(b1) /\ deopt(b0)=deopt(b1)); 448 449/** @group optiontypes.bool True iff \a b0 occurs and is equal to \a b1 */ 450predicate bool_eq(var opt bool: b0, var bool: b1) = 451 occurs(b0) /\ deopt(b0)=b1; 452 453 /** @group optiontypes.bool True iff \a b1 occurs and is equal to \a b0 */ 454predicate bool_eq(var bool: b0, var opt bool: b1) = 455 occurs(b1) /\ deopt(b1)=b0; 456 457/** @group optiontypes.bool True iff for any \p i, \a x[i] is absent or true */ 458predicate forall (array[int] of var opt bool: x) = 459 forall ([absent(x[i]) \/ deopt(x[i]) | i in index_set(x)]); 460 461/** @group optiontypes.bool True iff for at least one \p i, \a x[i] occurs and is true */ 462predicate exists (array[int] of var opt bool: x) = 463 exists ([occurs(x[i]) /\ deopt(x[i]) | i in index_set(x)]); 464 465% /** @group optiontypes.bool True iff \a x is absent or false */ 466% function var bool: 'not'(var opt bool: x) = absent(x) \/ not deopt(x); 467 468% /** @group optiontypes.bool Return absent if \a idx is absent, otherwise return \a x[\a idx] */ 469% function var opt bool: element(var opt int: idx, array[int] of var bool: x) = 470% if absent(idx) then <> else element(deopt(idx),x) endif; 471 472% /** @group optiontypes.bool Return absent if \a idx1 or \a idx2 is absent, otherwise return \a x[\a idx1, \a idx2] */ 473% function var opt bool: element(var opt int: idx1, var opt int: idx2, array[int,int] of var bool: x) = 474% if absent(idx1) \/ absent(idx2) then <> else element(deopt(idx1),deopt(idx2),x) endif; 475 476% /** @group optiontypes.bool Return \a x[\a idx] */ 477% function var opt bool: element(var int: idx, array[int] of var opt bool: x) = 478% let { 479% var opt bool: r; 480% constraint occurs(r) = element(idx,array1d(index_set(x),[occurs(x[i]) | i in index_set(x)])); 481% constraint deopt(r) = element(idx,array1d(index_set(x),[deopt(x[i]) | i in index_set(x)])); 482% } in r; 483 484% /** @group optiontypes.bool Return \a x[\a idx1, \a idx2] */ 485% function var opt bool: element(var int: idx1, var int: idx2, array[int,int] of var opt bool: x) = 486% let { 487% var opt bool: r; 488% constraint occurs(r) = element(idx1,idx2, 489% array2d(index_set_1of2(x),index_set_2of2(x),[occurs(x[i,j]) | i in index_set_1of2(x), j in index_set_2of2(x)])); 490% constraint deopt(r) = element(idx1,idx2, 491% array2d(index_set_1of2(x),index_set_2of2(x),[deopt(x[i,j]) | i in index_set_1of2(x), j in index_set_2of2(x)])); 492% } in r; 493 494% /** @group optiontypes.bool Return absent if \a idx is absent, otherwise return \a x[\a idx] */ 495% function var opt bool: element(var opt int: idx, array[int] of var opt bool: x) = 496% if absent(idx) then <> else element(deopt(idx),x) endif; 497 498% /** @group optiontypes.bool Return absent if \a idx1 or \a idx2 is absent, otherwise return \a x[\a idx1, \a idx2] */ 499% function var opt bool: element(var opt int: idx1, var opt int: idx2, array[int,int] of var opt bool: x) = 500% if absent(idx1) \/ absent(idx2) then <> else element(deopt(idx1),deopt(idx2),x) endif; 501 502 503 504/*** 505 @groupdef optiontypes.int Option type support for integers 506*/ 507 508/** @group optiontypes.int True iff \a x is not absent */ 509function var bool : occurs(var opt int : x) ::promise_total = 510 let { 511 var bool : b = occurs_internal(x); 512 var int : dx = deopt_internal(x); 513 constraint (x = reverse_map(b,dx)) :: is_reverse_map; 514 } in b; 515 516/** @group optiontypes.bool Return value of \a x (assumes that \a x is not absent) */ 517function var int : deopt(var opt int : x) ::promise_total = 518 let { 519 var bool : b = occurs_internal(x); 520 var int : dx = deopt_internal(x); 521 constraint (x = reverse_map(b,dx)) :: is_reverse_map; 522 } in dx; 523 524/** @group optiontypes.bool True iff \a x is absent */ 525function var bool: absent(var opt int: x) ::promise_total = not occurs(x); 526 527function var bool: occurs_internal(var opt int: x) ::promise_total = 528 let { var bool : b; } in b; 529function var int : deopt_internal(var opt int : x) ::promise_total = 530 let { var lb(x)..ub(x): y } in y; 531 532function var opt int: reverse_map(var bool: occ, var int: d); 533function opt int: reverse_map(bool: occ, int: d) ::promise_total = 534 if occ then d else <> endif; 535 536predicate var_dom(var opt int:x, set of int: s) = 537 let { 538 var int: dx = deopt(x); 539 set of int: new_dom = dom(dx) intersect s; 540 } in if new_dom = {} then absent(x) else dx in new_dom endif; 541 542predicate var_dom(array[$T] of var opt int: x, set of int: d) = 543 let { array[int] of var opt int: xx = array1d(x) } 544 in forall (i in index_set(xx)) (var_dom(xx[i],d)); 545 546predicate int_opt_eq(var opt int: x, var opt int: y) = 547 deopt(x) = deopt(y) /\ occurs(x) = occurs(y); 548 549/** @group optiontypes.bool Search annotation for optional Boolean variables */ 550annotation bool_search(array[int] of var opt bool: x, ann: a1, ann: a2, ann: a3) = 551 bool_search([if occurs(x[i]) then deopt(x[i]) else false endif | i in index_set(x)],a1,a2,a3); 552 553/** @group optiontypes.bool Search annotation for optional Boolean variables */ 554annotation bool_search(array[int] of var opt bool: x, ann: a1, ann: a2) = 555 bool_search([if occurs(x[i]) then deopt(x[i]) else false endif | i in index_set(x)],a1,a2); 556 557/** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 558 occur and the value of \a x is greater than the value of \a y. */ 559function var bool: '>'(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) > deopt(y); 560/** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 561 occur and the value of \a x is greater than or equal to the value of \a y. */ 562function var bool: '>='(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) >= deopt(y); 563% /** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 564% occur and the value of \a x is less than the value of \a y. */ 565% function var bool: '<'(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) < deopt(y); 566% /** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 567% occur and the value of \a x is less than or equal to the value of \a y. */ 568% function var bool: '<='(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) <= deopt(y); 569 570/** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 571 occur and the value of \a x is greater than the value of \a y. */ 572function bool: '>'(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) > deopt(y); 573/** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 574 occur and the value of \a x is greater than or equal to the value of \a y. */ 575function bool: '>='(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) >= deopt(y); 576% /** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 577% occur and the value of \a x is less than the value of \a y. */ 578% function bool: '<'(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) < deopt(y); 579% /** @group optiontypes.int Weak comparison: true iff either \a x or \a y is absent, or both 580% occur and the value of \a x is less than or equal to the value of \a y. */ 581% function bool: '<='(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) <= deopt(y); 582 583% /** @group optiontypes.int Return minimum of elements in \a x that are not absent, or 584% absent if all elements in \a x are absent. */ 585/* 586function var opt int: min(array[int] of var opt int: x) ::promise_total = 587 let { 588 var opt lb_array(x)..ub_array(x): m; 589 var lb_array(x)..ub_array(x): xmax; 590 constraint if ub(xmax) != infinity then xmax = ub(xmax) else forall (i in index_set(x)) (xmax >= deopt(x[i])) endif; 591 constraint occurs(m) <-> exists (i in index_set(x)) (occurs(x[i])); 592 constraint occurs(m) -> 593 deopt(m) = min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]); 594 } in m; 595*/ 596 597% /** @group optiontypes.int Return maximum of elements in \a x that are not absent, or 598% absent if all elements in \a x are absent. 599/* 600function var opt int: max(array[int] of var opt int: x) ::promise_total = 601 let { 602 var opt lb_array(x)..ub_array(x): m; 603 var lb_array(x)..ub_array(x): xmin; 604 constraint if lb(xmin) != -infinity then xmin = lb(xmin) else forall (i in index_set(x)) (xmin <= deopt(x[i])) endif; 605 constraint occurs(m) <-> exists (i in index_set(x)) (occurs(x[i])); 606 constraint occurs(m) -> 607 deopt(m) = max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]); 608 } in m; 609*/ 610 611/** @group optiontypes.int Weak addition. Return sum of \a x and \a y if both 612are present, otherwise return absent. */ 613function var opt int: '~+'(var opt int: x, var opt int: y) ::promise_total = 614 let { 615 int: l = if lb(x)=-infinity \/ lb(y)=-infinity then -infinity else lb(x)+lb(y) endif; 616 int: u = if ub(x)=infinity \/ ub(y)=infinity then infinity else ub(x)+ub(y) endif; 617 var opt l..u: result; 618 constraint absent(x) \/ absent(y) -> result = <>; 619 constraint absent(x) \/ absent(y) \/ result = deopt(x)+deopt(y); 620 } in result; 621 622/** @group optiontypes.int Weak subtraction. Return difference of \a x and \a y if both 623are present, otherwise return absent. */ 624function var opt int: '~-'(var opt int: x, var opt int: y) ::promise_total = 625 let { 626 int: l = if lb(x)=-infinity \/ ub(y)=infinity then -infinity else lb(x)-ub(y) endif; 627 int: u = if ub(x)=infinity \/ lb(y)=-infinity then infinity else ub(x)-lb(y) endif; 628 var opt l..u: result; 629 constraint absent(x) \/ absent(y) -> result = <>; 630 constraint absent(x) \/ absent(y) \/ result = deopt(x)-deopt(y); 631 } in result; 632 633/** @group optiontypes.int Weak multiplication. Return product of \a x and \a y if both 634are present, otherwise return absent. */ 635function var opt int: '~*'(var opt int: x, var opt int: y) ::promise_total = 636 if absent(x) \/ absent(y) then <> 637 else deopt(x)*deopt(y) endif; 638 639/** @group optiontypes.int Weak equality. True if either \a x or \a y are absent, or 640present and equal.*/ 641function var bool: '~='(var opt int: x, var opt int: y) ::promise_total = 642 absent(x) \/ absent(y) \/ deopt(x)=deopt(y); 643 644/** @group optiontypes.int Return optional 0/1 integer that is absent iff \a x 645 is absent, and 1 iff \a x occurs and is true. */ 646function var opt int: bool2int(var opt bool: x) ::promise_total = 647 let { 648 var opt 0..1: xi; 649 constraint absent(xi)=absent(x); 650 constraint deopt(xi)=bool2int(deopt(x)); 651 } in xi; 652 653/** @group optiontypes.int True iff both \a x and \a y are absent or 654 both are present and have the same value. */ 655predicate int_eq(var opt int: x, var opt int: y) = 656 (absent(x) /\ absent(y)) 657 \/ (occurs(x) /\ occurs(y) /\ (deopt(x)=deopt(y))::maybe_partial); 658 659/** @group optiontypes.int True iff only one of \a x and \a y is absent or 660 both are present and have different values. */ 661predicate int_ne(var opt int : x, var opt int : y) = 662 (absent(x) != absent(y)) 663 \/ (occurs(x) /\ occurs(y) /\ (deopt(x)!=deopt(y))::maybe_partial); 664 665% /** @group optiontypes.int Optional addition. Return sum of \a x and \a y, with absent replaced by 0. */ 666% function var int: '+'(var opt int: x, var opt int: y) ::promise_total = 667% if occurs(x) then deopt(x) else 0 endif + if occurs(y) then deopt(y) else 0 endif; 668 669% /** @group optiontypes.int Optional addition. Return sum of \a x and \a y, with absent replaced by 0. */ 670% function int: '+'(opt int: x, opt int: y) ::promise_total = 671% if occurs(x) then deopt(x) else 0 endif + if occurs(y) then deopt(y) else 0 endif; 672 673% /** @group optiontypes.int Optional subtraction. Return difference of \a x and \a y, with absent replaced by 0. */ 674% function var int: '-'(var opt int: x, var opt int: y) ::promise_total = 675% if occurs(x) then deopt(x) else 0 endif - if occurs(y) then deopt(y) else 0 endif; 676 677% /** @group optiontypes.int Optional subtraction. Return difference of \a x and \a y, with absent replaced by 0. */ 678% function int: '-'(opt int: x, opt int: y) ::promise_total = 679% if occurs(x) then deopt(x) else 0 endif - if occurs(y) then deopt(y) else 0 endif; 680 681% /** @group optiontypes.int Optional multiplication. Return product of \a x and \a y, with absent replaced by 1. */ 682% function var int: '*'(var opt int: x, var opt int: y) ::promise_total = 683% if occurs(x) then deopt(x) else 1 endif * if occurs(y) then deopt(y) else 1 endif; 684 685% /** @group optiontypes.int Optional multiplication. Return product of \a x and \a y, with absent replaced by 1. */ 686% function int: '*'(opt int: x, opt int: y) ::promise_total = 687% if occurs(x) then deopt(x) else 1 endif * if occurs(y) then deopt(y) else 1 endif; 688 689% /** @group optiontypes.int Optional division. Return \a x div \a y, with absent replaced by 1. */ 690% function var int: 'div'(var opt int: x, var opt int: y) ::promise_total = 691% if occurs(x) then deopt(x) else 1 endif div if occurs(y) then deopt(y) else 1 endif; 692 693% /** @group optiontypes.int Optional division. Return \a x div \a y, with absent replaced by 1. */ 694% function int: 'div'(opt int: x, opt int: y) ::promise_total = 695% if occurs(x) then deopt(x) else 1 endif div if occurs(y) then deopt(y) else 1 endif; 696 697/** @group optiontypes.int Optional modulo. Return \a x mod \a y, with absent replaced by 1. */ 698function var int: 'mod'(var opt int: x, var opt int: y) ::promise_total = 699 if occurs(x) then deopt(x) else 1 endif mod if occurs(y) then deopt(y) else 1 endif; 700 701/** @group optiontypes.int Optional modulo. Return \a x mod \a y, with absent replaced by 1. */ 702function int: 'mod'(opt int: x, opt int: y) ::promise_total = 703 if occurs(x) then deopt(x) else 1 endif mod if occurs(y) then deopt(y) else 1 endif; 704 705/** @group optiontypes.int Return sum of non-absent elements of \a x. */ 706function var int: sum(array[int] of var opt int: x) = 707 sum (i in index_set(x)) (let { var int: dx = deopt(x[i]) } in if occurs(x[i]) then dx else 0 endif); 708 709/** @group optiontypes.int Return sum of non-absent elements of \a x. */ 710function int: sum(array[int] of opt int: x) = 711 sum (i in index_set(x)) (if occurs(x[i]) then deopt(x[i]) else 0 endif); 712 713/** @group optiontypes.int Return product of non-absent elements of \a x. */ 714function var int: product(array[int] of var opt int: x) = 715 product (i in index_set(x)) (let { var int: dx = deopt(x[i]) } in if occurs(x[i]) then dx else 1 endif); 716 717/** @group optiontypes.int Return product of non-absent elements of \a x. */ 718function int: product(array[int] of opt int: x) = 719 product (i in index_set(x)) (if occurs(x[i]) then deopt(x[i]) else 1 endif); 720 721% /** @group optiontypes.int Return absent if \a idx is absent, otherwise return \a x[\a idx] */ 722% function var opt int: element(var opt int: idx, array[int] of var int: x) = 723% if absent(idx) then <> else element(deopt(idx),x) endif; 724% 725% /** @group optiontypes.int Return absent if \a idx1 or \a idx2 is absent, otherwise return \a x[\a idx1, \a idx2] */ 726% function var opt int: element(var opt int: idx1, var opt int: idx2, array[int,int] of var int: x) = 727% if absent(idx1) \/ absent(idx2) then <> else element(deopt(idx1),deopt(idx2),x) endif; 728% 729% /** @group optiontypes.int Return \a x[\a idx] */ 730% function var opt int: element(var int: idx, array[int] of var opt int: x) = 731% let { 732% var opt int: r; 733% constraint occurs(r) = element(idx,array1d(index_set(x),[occurs(x[i]) | i in index_set(x)])); 734% constraint deopt(r) = element(idx,array1d(index_set(x),[deopt(x[i]) | i in index_set(x)])); 735% } in r; 736% 737% /** @group optiontypes.int Return \a x[\a idx1, \a idx2] */ 738% function var opt int: element(var int: idx1, var int: idx2, array[int,int] of var opt int: x) = 739% let { 740% var opt int: r; 741% constraint occurs(r) = element(idx1,idx2, 742% array2d(index_set_1of2(x),index_set_2of2(x),[occurs(x[i,j]) | i in index_set_1of2(x), j in index_set_2of2(x)])); 743% constraint deopt(r) = element(idx1,idx2, 744% array2d(index_set_1of2(x),index_set_2of2(x),[deopt(x[i,j]) | i in index_set_1of2(x), j in index_set_2of2(x)])); 745% } in r; 746% 747% /** @group optiontypes.int Return absent if \a idx is absent, otherwise return \a x[\a idx] */ 748% function var opt int: element(var opt int: idx, array[int] of var opt int: x) = 749% if absent(idx) then <> else element(deopt(idx),x) endif; 750% 751% /** @group optiontypes.int Return absent if \a idx1 or \a idx2 is absent, otherwise return \a x[\a idx1, \a idx2] */ 752% function var opt int: element(var opt int: idx1, var opt int: idx2, array[int,int] of var opt int: x) = 753% if absent(idx1) \/ absent(idx2) then <> else element(deopt(idx1),deopt(idx2),x) endif; 754 755/** @group optiontypes.int Search annotation for optional integer variables */ 756annotation int_search(array[int] of var opt int: x, ann: a1, ann: a2, ann: a3) = 757 int_search([if occurs(x[i]) then deopt(x[i]) else 0 endif | i in index_set(x)],a1,a2,a3); 758 759/** @group optiontypes.int Search annotation for optional integer variables */ 760annotation int_search(array[int] of var opt int: x, ann: a1, ann: a2) = 761 int_search([if occurs(x[i]) then deopt(x[i]) else 0 endif | i in index_set(x)],a1,a2); 762 763/* Internal function used to optimize over option type objective */ 764 765function var int: objective_deopt_(var opt int: x, bool: direction) = 766 let { 767 int: worst = if direction then lb(x)-1 else ub(x)+1 endif; 768 } in if occurs(x) then deopt(x) else worst endif; 769 770/* TODO: predicate to temporarily replace the output items */ 771 772predicate output_this(array[int] of var int: arr); 773predicate solve_this(int: mode, var int: objective, array[int] of var int: x, int: varsel, int: valsel); 774predicate solve_this(int: mode, var int: objective); 775 776function int: sol(var int: x); 777 778/*** 779 @groupdef options Compiler options 780*/ 781 782/* @group options Whether to only generate domains that are contiguous ranges */ 783/* opt bool: mzn_opt_only_range_domains; */ 784 785/* @group options Check whether to only generate domains that are contiguous ranges */ 786/* test mzn_check_only_range_domains() = */ 787/* if absent(mzn_opt_only_range_domains) then false */ 788/* else deopt(mzn_opt_only_range_domains) endif; */ 789 790/* @group options If defined, this can be used to check that the MiniZinc compiler supports all the features used in the model. */ 791/* opt int: mzn_min_version_required; */ 792 793/* constraint assert(absent(mzn_min_version_required) \/ deopt(mzn_min_version_required) <= mzn_compiler_version(), "This model requires MiniZinc version "++mzn_version_to_string(deopt(mzn_min_version_required))++" but you are running version "++mzn_version_to_string(mzn_compiler_version())); */ 794 795predicate set_in(array[$T] of var int: X, set of int: s) = forall(x in array1d(X)) (x in s); 796predicate int_eq(array[$T] of var int: X, int: s) = forall(x in array1d(X)) (x = s); 797predicate float_eq(array[$T] of var int: X, float: s) = forall(x in array1d(X)) (x = s); 798predicate int_le(array[$T] of var int: X, int: s) = forall(x in array1d(X)) (x <= s); 799predicate int_le(int:s, array[$T] of var int: X) = forall(x in array1d(X)) (x >= s); 800predicate float_le(array[$T] of var float: X, float: s) = forall(x in array1d(X)) (x <= s); 801predicate float_le(float:s, array[$T] of var float: X) = forall(x in array1d(X)) (x >= s); 802 803include "builtins.mzn";