this repo has no description
at develop 49 kB view raw
1More Complex Models 2=================== 3 4In the last section we introduced the basic structure of a MiniZinc 5model. In this section we introduce the array and set data structures, 6enumerated types and 7more complex constraints. 8 9.. _sec-arrayset: 10 11Arrays and Sets 12--------------- 13 14Almost always we are interested in building models where the number of 15constraints and variables is dependent on the input data. 16In order to do so we will usually use :index:`arrays <array>`. 17 18Consider a simple finite element model for modelling temperatures on a 19rectangular sheet of metal. We approximate the temperatures across the 20sheet by breaking the sheet into a finite number of elements in a 21two-dimensional matrix. 22A model is shown in :numref:`ex-laplace`. 23It declares the width ``w`` and height ``h`` 24of the finite element model. 25The declaration 26 27.. literalinclude:: examples/laplace.mzn 28 :language: minizinc 29 :lines: 5-9 30 31declares four fixed sets of integers describing the dimensions of the finite 32element model: ``HEIGHT`` is the whole height of the model, while ``CHEIGHT`` is 33the centre of the height omitting the top and bottom, 34``WIDTH`` is the whole width of the model, while 35``CWIDTH`` is the centre of the width omitting the left and right sides. 36Finally a two dimensional array of float variables ``t`` 37with rows numbered 38:math:`0` to :math:`h` (``HEIGHT``) and columns :math:`0` to :math:`w` (``WIDTH``), 39to represent the temperatures at each 40point in the metal plate. 41We can access the element of the array in the :math:`i^{th}` row and :math:`j^{th}` column 42using an expression :mzn:`t[i,j]`. 43 44 45Laplace's 46equation states that when the plate reaches a steady state 47the temperature at each internal point is the average of its orthogonal 48neighbours. The constraint 49 50.. literalinclude:: examples/laplace.mzn 51 :language: minizinc 52 :lines: 16-18 53 54ensures that each internal point :math:`(i,j)` is the 55average of its four orthogonal neighbours. 56The constraints 57 58.. literalinclude:: examples/laplace.mzn 59 :language: minizinc 60 :lines: 20-24 61 62restrict the temperatures on each edge to be equal, and 63gives these temperatures names: ``left``, ``right``, ``top`` 64and ``bottom``. 65While the constraints 66 67.. literalinclude:: examples/laplace.mzn 68 :language: minizinc 69 :lines: 26-30 70 71ensure that the corners (which are irrelevant) are set to 0.0. 72We can determine the temperatures in a plate broken into 5 :math:`\times` 5 73elements with left, right and bottom temperature 0 and top temperature 100 74with the model shown in :numref:`ex-laplace`. 75 76 77.. literalinclude:: examples/laplace.mzn 78 :language: minizinc 79 :name: ex-laplace 80 :caption: Finite element plate model for determining steady state temperatures (:download:`laplace.mzn <examples/laplace.mzn>`). 81 82Running the command 83 84.. code-block:: bash 85 86 $ minizinc --solver cbc laplace.mzn 87 88gives the output 89 90.. code-block:: none 91 92 -0.00 100.00 100.00 100.00 -0.00 93 -0.00 42.86 52.68 42.86 -0.00 94 -0.00 18.75 25.00 18.75 -0.00 95 -0.00 7.14 9.82 7.14 -0.00 96 -0.00 -0.00 -0.00 -0.00 -0.00 97 ---------- 98 99.. defblock:: Sets 100 101 .. index:: 102 single: set 103 104 Set variables are declared with a declaration of the form 105 106 .. code-block:: minizincdef 107 108 set of <type-inst> : <var-name> ; 109 110 where sets of integers, enums (see later), floats or Booleans are allowed. 111 The only type allowed for decision variable sets are variable sets of 112 integers or enums. 113 Set literals are of the form 114 115 .. code-block:: minizincdef 116 117 { <expr-1>, ..., <expr-n> } 118 119 or are :index:`range` expressions over either integers, enums or floats of the form 120 121 .. code-block:: minizincdef 122 123 <expr-1> .. <expr-2> 124 125 The standard :index:`set operations <operator; set>` 126 are provided: element membership 127 (:mzn:`in`), 128 (non-strict) subset relationship (:mzn:`subset`), 129 (non-strict) superset relationship (:mzn:`superset`), union 130 (:mzn:`union`), 131 intersection (:mzn:`intersect`), 132 set difference (:mzn:`diff`), 133 symmetric set difference (:mzn:`symdiff`) 134 and the number of elements in the 135 set (:mzn:`card`). 136 137 As we have seen set variables and set literals (including ranges) can be 138 used as an implicit type in variable declarations in which case the variable 139 has the type of the elements in the set and the variable is implicitly 140 constrained to be a member of the set. 141 142 143Our cake baking problem is an example of a very simple kind of production 144planning problem. In this kind of problem we wish to determine how much of 145each kind of product to make to maximise the profit where manufacturing a 146product consumes varying amounts of some fixed resources. We can generalise 147the MiniZinc model in :numref:`ex-cakes2` to handle this kind of problem 148with a model that is generic in the kinds of resources and products. The 149model is shown in :numref:`ex-prod-planning` and a sample data file (for 150the cake baking example) is shown in :numref:`fig-prod-planning-data`. 151 152 153.. literalinclude:: examples/prod-planning.mzn 154 :language: minizinc 155 :name: ex-prod-planning 156 :caption: Model for simple production planning (:download:`prod-planning.mzn <examples/prod-planning.mzn>`). 157 158.. literalinclude:: examples/prod-planning-data.dzn 159 :language: minizinc 160 :name: fig-prod-planning-data 161 :caption: Example data file for the simple production planning problem (:download:`prod-planning-data.dzn <examples/prod-planning-data.dzn>`). 162 163The new feature in this model is the use of :index:`enumerated 164types <type; enumerated>`. 165These allow us to treat the choice of resources and products as parameters to 166the model. 167The first item in the model 168 169.. code-block:: minizinc 170 171 enum Products; 172 173declares ``Products`` as an *unknown* set of products. 174 175.. defblock:: Enumerated Types 176 177 .. index:: 178 single: enumerated type 179 single enum 180 181 Enumerated types, which we shall refer to as ``enums``, 182 are declared with a declaration of the form 183 184 .. code-block:: minizincdef 185 186 enum <var-name> ; 187 188 An enumerated type is defined by an assignment of the form 189 190 191 .. code-block:: minizincdef 192 193 enum <var-name> = { <var-name-1>, ..., <var-name-n> } ; 194 195 where :mzndef:`<var-name-1>`, ..., :mzndef:`<var-name-n>` are the elements of 196 the enumerated type, with name :mzndef:`<var-name>`. 197 Each of the elements of the enumerated type is also effectively declared by 198 this definition as a new constant of that type. 199 The declaration and definition can be combined into one line as usual. 200 201The second item declares an array of integers: 202 203.. code-block:: minizinc 204 205 array[Products] of int: profit; 206 207The :index:`index set <array; index set>` 208of the array ``profit`` is ``Products``. 209This means that only elements of the set ``Products`` 210can be used to index the array. 211 212The elements of an enumerated type of :math:`n` elements 213act very similar to the integers :math:`1\dots n`. They can be compared, they are 214ordered, by the order they appear in the enumerated type definition, 215they can be iterated over, they can appear as indices of arrays, in fact 216they can appear anywhere an integer can appear. 217 218In the example data file we have initialized the array using a list of 219integers 220 221.. code-block:: minizinc 222 223 Products = { BananaCake, ChocolateCake }; 224 profit = [400,450]; 225 226meaning the profit for a banana cake is 400, while for a chocolate cake it 227is 450. Internally ``BananaCake`` will be treated like the integer 1, 228while ``ChocolateCake`` will be treated like the integer 2. 229The expression :mzn:`[400,500]` represents a literal one-dimensional array. In MiniZinc, the index set of literal arrays always starts at 1 (this is similar to other mathematically inspired languages such as MATLAB, Julia or Mathematica). 230While MiniZinc does not provide an explicit list type, one-dimensional 231arrays with an index set :mzn:`1..n` behave like lists, and we will sometimes 232refer to them as :index:`lists <list>`. 233 234In a similar fashion, in the next two items we declare a set of resources 235``Resources``, and an array ``capacity`` which gives the amount of 236each resource that is available. 237 238More interestingly, the item 239 240.. code-block:: minizinc 241 242 array[Products, Resources] of int: consumption; 243 244declares a 2-D array ``consumption``. The value of 245:mzn:`consumption[p,r]` is the amount of resource :mzn:`r` required to 246produce one unit of product :mzn:`p`. Note that the first index is the row 247and the second is the column. 248 249The data file contains an example initialization of a 2-D array: 250 251.. code-block:: minizinc 252 253 consumption= [| 250, 2, 75, 100, 0, 254 | 200, 0, 150, 150, 75 |]; 255 256Notice how the delimiter ``|`` is used to separate rows. As for one-dimensional array literals, indexing of two-dimensional array literals also starts at 1. 257 258.. defblock:: Arrays 259 260 .. index: 261 single: array 262 263 Thus, MiniZinc provides one- and multi-dimensional arrays 264 which are declared using the type: 265 266 .. code-block:: minizincdef 267 268 array [ <index-set-1>, ..., <index-set-n> ] of <type-inst> 269 270 MiniZinc requires that the array declaration contains the index set of each 271 dimension and that the index set is either an integer range, a set 272 variable initialised to an integer range, or an :index:`enumeration type <enumerated type>`. 273 Arrays can contain any of the base 274 types: integers, enums, Booleans, floats or strings. These can be fixed or unfixed 275 except for strings which can only be parameters. Arrays can also contain 276 sets but they cannot contain arrays. 277 278 :index:`One-dimensional array literals <array; literal; 1D>` are of form 279 280 .. code-block:: minizincdef 281 282 [ <expr-1>, ..., <expr-n> ] 283 284 and their index sets are :mzn:`1..n`, 285 while :index:`two-dimensional array literals <array; literal; 2D>` are of form 286 287 .. code-block:: minizincdef 288 289 [| <expr-1-1>, ..., <expr-1-n> | 290 ... | 291 <expr-m-1>, ..., <expr-m-n> |] 292 293 where the array has ``m`` rows and ``n`` columns, with index sets :mzn:`1..m` for the first and :mzn:`1..n` for the second dimension. 294 295 The family of built-in functions :mzn:`array1d`, 296 :mzn:`array2d`, etc, 297 can be used to initialise an array of any dimension from a list (or more 298 exactly a one-dimensional array). The call: 299 300 .. code-block:: minizincdef 301 302 array<n>d(<index-set-1>, ..., <index-set-n>, <list>) 303 304 returns an ``n`` dimensional array with index sets given by the first ``n`` 305 arguments and the last argument contains the elements of the array. For 306 instance, :mzn:`array2d(1..3, 1..2, [1, 2, 3, 4, 5, 6])` is equivalent to 307 :mzn:`[|1, 2 |3, 4 |5, 6|]`. 308 309 Array elements are :index:`accessed <array; access>` using bracket syntax: :mzn:`a[i,j]` gives the 310 element at row index :math:`i^{th}` and column index :math:`j^{th}`. 311 312 .. \pjs{New array functions!} 313 314 315 The concatenation operator ``++`` 316 can be used to concatenate two 317 one-dimensional arrays together. The result is a list, i.e. a 318 one-dimensional array whose elements are indexed from 1. For instance 319 :mzn:`[4000, 6] ++ [2000, 500, 500]` evaluates to :mzn:`[4000, 6, 2000, 500, 500]`. 320 The built-in function 321 :mzn:`length` returns the length 322 of a one-dimensional array. 323 324The next item in the model defines the parameter :mzn:`mproducts`. This is 325set to an upper-bound on the number of products of any type that can be 326produced. This is quite a complex example of nested 327array comprehensions and aggregation operators. We shall introduce these 328before we try to understand this item and the rest of the model. 329 330First, MiniZinc provides list comprehensions similar to those provided in 331many functional programming languages, or Python. For example, the list comprehension 332:mzn:`[i + j | i, j in 1..3 where j < i]` evaluates to :mzn:`[2 + 1, 3 + 1, 3 + 2]` 333which is :mzn:`[3, 4, 5]`. Of course :mzn:`[3, 4, 5]` is 334simply an array with index set :mzn:`1..3`. 335 336MiniZinc also provides set comprehensions which have a similar syntax: for 337instance, :mzn:`{i + j | i, j in 1..3 where j < i}` evaluates to the set 338:mzn:`{3, 4, 5}`. 339 340.. defblock:: List and Set Comprehensions 341 342 .. index: 343 single: comprehension 344 single: comprehension; list 345 346 The generic form of a list comprehension is 347 348 .. code-block:: minizincdef 349 350 [ <expr> | <generator-exp> ] 351 352 The expression :mzndef:`<expr>` specifies how to construct elements in the 353 output list from the elements generated by :mzndef:`<generator-exp>`. 354 The generator :mzndef:`<generator-exp>` consists of a comma separated sequence of 355 generator expressions optionally followed by a Boolean expression. The two forms are 356 357 .. code-block:: minizincdef 358 359 <generator> 360 <generator> where <bool-exp> 361 362 The optional :mzndef:`<bool-exp>` in the second form acts as a filter on 363 the generator expression: only elements satisfying the Boolean expression 364 are used to construct elements in the output list. A :index:`generator <comprehension; generator>` 365 :mzndef:`<generator>` 366 has the form 367 368 .. code-block:: minizincdef 369 370 <identifier>, ..., <identifier> in <array-exp> 371 372 Each identifier is an *iterator* 373 which takes the values 374 of the array expression in turn, with the last identifier varying most rapidly. 375 376 The generators of a list comprehension and :mzndef:`<bool-exp>` 377 usually do not involve decision variables. 378 If they do involve decision variables 379 then the list produced is a list of :mzndef:`var opt <T>` where :mzndef:`<T>` is the type 380 of the :mzndef:`<expr>`. See the discussion of :index:`option types <option type>` 381 in :ref:`sec-optiontypes` for more details. 382 383 :index:`Set comprehensions <comprehension; set>` 384 are almost identical to list comprehensions: the only 385 difference is the use of ``{`` and ``}`` to enclose the 386 expression rather than ``[`` and ``]``. 387 The elements generated by a set comprehension must be 388 :index:`fixed`, i.e. free of decision variables. 389 Similarly the generators and optional :mzndef:`<bool-exp>` 390 for set comprehensions must be fixed. 391 392 393.. index:: 394 single: forall 395 396Second, MiniZinc provides a number of built-in functions that take a 397one-dimensional array and aggregate the elements. Probably the most useful 398of these is :mzn:`forall`. 399This takes an array of Boolean expressions 400(that is, constraints) and returns a single Boolean expression which is the 401logical conjunction of the Boolean expressions in the array. 402 403For example, consider the expression 404 405.. code-block:: minizinc 406 407 forall( [a[i] != a[j] | i,j in 1..3 where i < j]) 408 409where ``a`` is an arithmetic array with index set ``1..3``. This 410constrains the elements in ``a`` to be pairwise different. The list 411comprehension evaluates to :mzn:`[ a[1] != a[2], a[1] != a[3], a[2] != a[3] ]` 412and so the :mzn:`forall` function returns the logical 413conjunction :mzn:`a[1] != a[2] /\ a[1] != a[3] /\ a[2] != a[3]`. 414 415.. defblock:: Aggregation functions 416 417 .. index:: 418 single: aggregation function 419 single: sum 420 single: product 421 single: min 422 single: max 423 single: forall 424 single: exists 425 single: xorall 426 single: iffall 427 single: aggregation function; sum 428 single: aggregation function; product 429 single: aggregation function; min 430 single: aggregation function; max 431 single: aggregation function; forall 432 single: aggregation function; exists 433 single: aggregation function; xorall 434 single: aggregation function; iffall 435 436 The *aggregation functions* for arithmetic arrays are: 437 :mzn:`sum` which adds the elements, :mzn:`product` which multiplies them together, 438 and :mzn:`min` and :mzn:`max` which respectively return the least and 439 greatest element in the array. When applied to an empty array, :mzn:`min` and 440 :mzn:`max` give a run-time error, :mzn:`sum` returns 0 and :mzn:`product` 441 returns 1. 442 443 MiniZinc provides four aggregation functions for arrays containing Boolean 444 expressions. As we have seen, the first of these, 445 :mzn:`forall`, returns 446 a single constraint which is the logical conjunction of the 447 constraints. 448 The second function, :mzn:`exists`, 449 returns the logical 450 disjunction of the constraints. Thus, :mzn:`forall` enforces that all 451 constraints in the array hold, while :mzn:`exists` ensures that at least 452 one of the constraints holds. 453 The third function, :mzn:`xorall`, 454 ensures that an odd number of constraints hold. 455 The fourth function, :mzn:`iffall`, 456 ensures that an even number of constraints holds. 457 458The third, and final, piece in the puzzle is that MiniZinc allows a special 459syntax for aggregation functions when used with an array 460comprehension. Instead of writing 461 462.. code-block:: minizinc 463 464 forall( [a[i] != a[j] | i,j in 1..3 where i < j]) 465 466the modeller can instead write the more mathematical looking 467 468.. code-block:: minizinc 469 470 forall (i,j in 1..3 where i < j) (a[i] != a[j]) 471 472The two expressions are completely equivalent: the modeller is free to use 473whichever they feel looks most natural. 474 475.. defblock:: Generator call expressions 476 477 .. index:: 478 single: generator call 479 single: expression; generator call 480 481 A *generator call expression* has form 482 483 .. code-block:: minizincdef 484 485 <agg-func> ( <generator-exp> ) ( <exp> ) 486 487 The round brackets around the generator expression 488 :mzndef:`<generator-exp>` and the constructor expression 489 :mzndef:`<exp>` are not optional: they must be there. This is 490 equivalent to writing 491 492 .. code-block:: minizincdef 493 494 <agg-func> ( [ <exp> | <generator-exp> ] ) 495 496 The :index:`aggregation function` :mzndef:`<agg-func>` is any MiniZinc 497 function expecting a single array as argument. 498 499 500We are now in a position to understand the rest of the simple production 501planning model shown in :numref:`ex-prod-planning`. For the moment ignore 502the item defining :mzn:`mproducts`. The item afterwards: 503 504.. code-block:: minizinc 505 506 array[Products] of var 0..mproducts: produce; 507 508defines a one-dimensional array :mzn:`produce` of decision variables. The 509value of :mzn:`produce[p]` will be set to the amount of product :mzn:`p` 510in the optimal solution. 511The next item 512 513.. code-block:: minizinc 514 515 array[Resources] of var 0..max(capacity): used; 516 517defines a set of auxiliary variables that record how much of each resource 518is used. 519The next two constraints 520 521.. code-block:: minizinc 522 523 constraint forall (r in Resources) 524 (used[r] = sum (p in Products) (consumption[p, r] * produce[p])); 525 constraint forall (r in Resources)(used[r] <= capacity[r] ); 526 527compute in :mzn:`used[r]` the total consumption of the 528resource :mzn:`r` and ensure it is less than the available amount. 529Finally, the item 530 531.. code-block:: minizinc 532 533 solve maximize sum (p in Products) (profit[p]*produce[p]); 534 535indicates that this is a maximisation problem and that the objective to be maximised is the total profit. 536 537 538We now return to the definition of :mzn:`mproducts`. For each product 539:mzn:`p` the expression 540 541.. code-block:: minizinc 542 543 (min (r in Resources where consumption[p,r] > 0) 544 (capacity[r] div consumption[p,r])) 545 546determines the maximum amount of :mzn:`p` that can be produced taking into 547account the amount of each resource :mzn:`r` and how much of :mzn:`r` is 548required to produce the product. Notice the use of the filter 549:mzn:`where consumption[p,r] > 0` to ensure that only resources required to make the 550product are considered so as to avoid a division by zero error. Thus, the 551complete expression 552 553.. code-block:: minizinc 554 555 int: mproducts = max (p in Products) 556 (min (r in Resources where consumption[p,r] > 0) 557 (capacity[r] div consumption[p,r])); 558 559computes the maximum amount of *any* product that can be produced, and 560so this can be used as an upper bound on the domain of the decision 561variables in :mzn:`produce`. 562 563Finally notice the output item is more complex, 564and uses :index:`list comprehensions <comprehension; list>` 565to create an understandable output. Running 566 567.. code-block:: bash 568 569 $ minizinc --solver gecode prod-planning.mzn prod-planning-data.dzn 570 571results in the output 572 573.. code-block:: none 574 575 BananaCake = 2; 576 ChocolateCake = 2; 577 Flour = 900; 578 Banana = 4; 579 Sugar = 450; 580 Butter = 500; 581 Cocoa = 150; 582 ---------- 583 ========== 584 585 586Global Constraints 587------------------ 588 589.. \index{constraint!global|see{global constraint}} 590.. \index{global constraint} 591 592MiniZinc includes a library of global constraints which can also be used 593to define models. An example is the :mzn:`alldifferent` 594constraint which requires 595all the variables appearing in its argument to be pairwise different. 596 597 598.. literalinclude:: examples/send-more-money.mzn 599 :language: minizinc 600 :name: ex-smm 601 :caption: Model for the cryptarithmetic problem SEND+MORE=MONEY (:download:`send-more-money.mzn <examples/send-more-money.mzn>`) 602 603The SEND+MORE=MONEY problem requires assigning a different 604digit to each letter so that the arithmetic constraint holds. 605The model shown in :numref:`ex-smm` uses the constraint expression 606:mzn:`alldifferent([S,E,N,D,M,O,R,Y])` 607to ensure that each letter takes a different digit value. 608The global constraint is made available 609in the model using include item 610 611.. code-block:: minizinc 612 613 include "alldifferent.mzn"; 614 615which makes 616the global constraint :mzn:`alldifferent` usable by the model. 617One could replace this line by 618 619.. code-block:: minizinc 620 621 include "globals.mzn"; 622 623which includes all globals. 624 625A list of all the global constraints 626defined for MiniZinc is included in the 627release documentation. See :ref:`sec-globals` for 628a description of some important global constraints. 629 630 631Conditional Expressions 632----------------------- 633 634.. \index{expression!conditional} 635 636MiniZinc provides a conditional *if-then-else-endif* 637expression. 638An example of its use is 639 640.. code-block:: minizinc 641 642 int: r = if y != 0 then x div y else 0 endif; 643 644which sets :mzn:`r` to :mzn:`x` divided by :mzn:`y` unless :mzn:`y` is zero in which case 645it sets it to zero. 646 647.. defblock:: Conditional expressions 648 649 .. index:: 650 single: expression; conditional 651 652 The form of a conditional expression is 653 654 .. code-block:: minizincdef 655 656 if <bool-exp> then <exp-1> else <exp-2> endif 657 658 It is a true expression rather than a control flow statement and so can be used in other expressions. 659 It evaluates to :mzndef:`<exp-1>` if the Boolean expression :mzndef:`<bool-exp>` is true and 660 :mzndef:`<exp-2>` otherwise. The type of the conditional expression is that of 661 :mzndef:`<exp-1>` and :mzndef:`<exp-2>` which must have the same 662 type. 663 664 If the :mzndef:`<bool-exp>` contains decision variables, then the 665 type-inst 666 of the expression is :mzndef:`var <T>` where :mzndef:`<T>` is the type of 667 :mzndef:`<exp-1>` and :mzndef:`<exp-2>` even if both 668 expressions are fixed. 669 670.. literalinclude:: examples/sudoku.mzn 671 :language: minizinc 672 :name: ex-sudoku 673 :caption: Model for generalized Sudoku problem (:download:`sudoku.mzn <examples/sudoku.mzn>`) 674 675 676.. literalinclude:: examples/sudoku.dzn 677 :language: minizinc 678 :name: ex-sudokud 679 :caption: Example data file for generalised Sudoku problem (:download:`sudoku.dzn <examples/sudoku.dzn>`) 680 681.. _fig-sudoku: 682 683.. figure:: figures/sudoku.* 684 685 The problem represented by data file :download:`sudoku.dzn <examples/sudoku.dzn>` 686 687Conditional expressions are very useful in building complex models, or 688complex output. Consider the model of Sudoku problems shown in 689:numref:`ex-sudoku`. The initial board positions are given by the 690:mzn:`start` parameter where 0 represents an empty 691board position. This is converted to constraints on the decision variables 692:mzn:`puzzle` using the conditional expression 693 694.. code-block:: minizinc 695 696 constraint forall(i,j in PuzzleRange)( 697 if start[i,j] > 0 then puzzle[i,j] = start[i,j] else true endif ); 698 699Conditional expressions are also very useful for 700defining complex :index:`output`. 701In the Sudoku model of :numref:`ex-sudoku` the expression 702 703.. code-block:: minizinc 704 705 if j mod S == 0 then " " else "" endif 706 707inserts an extra space between groups of size :mzn:`S`. 708The output expression also uses conditional expressions to 709add blank lines 710after each :mzn:`S` lines. The resulting output is highly readable. 711 712The remaining constraints ensure that the numbers appearing in each 713row and column and :math:`S \times S` subsquare are all different. 714 715.. index:: 716 single: runtime flag; -a 717 single: runtime flag; --all-solutions 718 single: solution; all 719 720One can use MiniZinc to search 721for all solutions to a satisfaction problem (:mzn:`solve satisfy`). In the MiniZinc IDE, this can be achieved by setting the number of solutions to zero in the "User-defined behavior" part of the solver configuration pane (see :numref:`ide_solver_config`). On the command line, one can use the flag ``-a`` 722or ``--all-solutions``. Running 723 724.. code-block:: bash 725 726 $ minizinc --solver gecode --all-solutions sudoku.mzn sudoku.dzn 727 728results in 729 730.. code-block:: none 731 732 5 9 3 7 6 2 8 1 4 733 2 6 8 4 3 1 5 7 9 734 7 1 4 9 8 5 2 3 6 735 736 3 2 6 8 5 9 1 4 7 737 1 8 7 3 2 4 9 6 5 738 4 5 9 1 7 6 3 2 8 739 740 9 4 2 6 1 8 7 5 3 741 8 3 5 2 4 7 6 9 1 742 6 7 1 5 9 3 4 8 2 743 ---------- 744 ========== 745 746The line ``==========`` 747is output when the system has output all possible 748solutions, here verifying that there is exactly one. 749 750.. _sec-enum: 751 752Enumerated Types 753---------------- 754 755.. index:: 756 single: type; enumerated 757 758Enumerated types allows us to build models that depend on a set of objects 759which are part of the data, or are named in the model, and hence make models 760easier to understand and debug. 761We have introduce enumerated types or enums briefly, in this subsection we 762will explore how we can use them more fully, and show some of the built in 763functions for dealing with enumerated types. 764 765Let's revisit the problem of coloring the graph of Australia from :ref:`sec-modelling`. 766 767 768.. literalinclude:: examples/aust-enum.mzn 769 :language: minizinc 770 :name: ex-aust-enum 771 :caption: Model for coloring Australia using enumerated types (:download:`aust-enum.mzn <examples/aust-enum.mzn>`). 772 773The model shown in :numref:`ex-aust-enum` declares an enumerated type 774:mzn:`Color` which must be defined in the data file. Each of the state 775variables is declared to take a value from this enumerated type. 776Running this program using 777 778.. code-block:: bash 779 780 $ minizinc --solver gecode -D"Color = { red, yellow, blue };" aust-enum.mzn 781 782might result in output 783 784.. code-block:: none 785 786 wa = blue; 787 nt = yellow; 788 sa = red; 789 q = blue; 790 nsw = yellow; 791 v = blue; 792 t = red; 793 794 795.. defblock:: Enumerated Type Variable Declarations 796 797 .. index:: 798 single: variable; declaration; enum 799 800 An enumerated type parameter is declared as either: 801 802 .. code-block:: minizincdef 803 804 <enum-name> : <var-name> 805 <l>..<u> : <var-name> 806 807 where :mzndef:`<enum-name>` is the name of an enumerated type, and 808 :mzndef:`<l>` and :mzndef:`<u>` are fixed enumerated type expressions of the same 809 enumerated type. 810 811 An enumerated type decision variable is declared 812 as either: 813 814 .. code-block:: minizincdef 815 816 var <enum-name> : <var-name> 817 var <l>..<u> : <var-name> 818 819 where :mzndef:`<enum-name>` is the name of an enumerated type, and 820 :mzndef:`<l>` and :mzndef:`<u>` are fixed enumerated type expressions of the same 821 enumerated type. 822 823A key behaviour of enumerated types is that they are automatically coerced 824to integers when they are used in a position expecting an integer. 825For example, this allows us to use global constraints defined on integers, 826such as 827 828.. code-block:: minizinc 829 830 global_cardinality_low_up([wa,nt,sa,q,nsw,v,t], 831 [red,yellow,blue],[2,2,2],[2,2,3]); 832 833This requires at least two states to be colored each color and three to be 834colored blue. 835 836 837.. defblock:: Enumerated Type Operations 838 839 There are a number of built in operations on enumerated types: 840 841 - :mzn:`enum_next(X,x)`: returns the next value after :mzn:`x` in the 842 enumerated type :mzn:`X`. This is a partial function, if :mzn:`x` is the last value in 843 the enumerated type :mzn:`X` then the function returns :math:`\bot` causing the Boolean 844 expression containing the expression to evaluate to :mzn:`false`. 845 - :mzn:`enum_prev(X,x)`: 846 returns the previous value before :mzn:`x` in the 847 enumerated type :mzn:`X`. Similarly :mzn:`enum_prev` is a partial function. 848 - :mzn:`to_enum(X,i)`: maps an integer expression :mzn:`i` to an 849 enumerated type value in type :mzn:`X` or evaluates to :math:`\bot` if :mzn:`i` is less 850 than or equal to 0 or greater than the number of elements in :mzn:`X`. 851 852 Note also that a number of standard functions are applicable to enumerated 853 types: 854 855 - :mzn:`card(X)`: returns the cardinality of an enumerated type :mzn:`X`. 856 - :mzn:`min(X)`: returns the minimum element of of an enumerated type :mzn:`X`. 857 - :mzn:`max(X)`: returns the maximum element of of an enumerated type :mzn:`X`. 858 859It is often useful to define an enumerated type by *extending* another enumerated type. A good example for this is adding a "don't care" value to a type. For instance, consider a typical assignment problem, where we have to assign chores to flatmates. The names of the flatmates are given as an enumerated type :mzn:`Flatmates`, and the chores as an enumerated type :mzn:`Chores`. 860 861In the case where not every flatmate needs to be assigned a job, and not every chore needs to be assigned to a flatmate, we need to introduce a value that signals "no assignment". We can then use the :mzn:`alldifferent_except` constraint to constrain the assignment. 862 863.. literalinclude:: examples/assignment-extend-enum.mzn 864 :language: minizinc 865 :name: ex-assignment-extend-enum 866 :caption: Model for an assignment problem using extended enumerated types (:download:`assignment-extend-enum.mzn <examples/assignment-extend-enum.mzn>`). 867 868The model is shown in :numref:`ex-assignment-extend-enum`. It introduces a new enumerated type :mzn:`ChoreOrNothing`, which is a combination of the :mzn:`Chores` type and a new constructor :mzn:`Nothing`. The :mzn:`Chores` type is *injected* into the new type via a *constructor function*. In this case, we chose the name :mzn:`C` for the constructor function, but you can use any valid identifier you like. The constructor function can then be used to coerce a value of type :mzn:`Chores` into a value of the new type :mzn:`ChoreOrNothing`. For example, we could write a constraint such as 869 870.. code-block:: minizinc 871 872 constraint assignment[Bert] = C(Vacuuming); 873 874This is required because the type :mzn:`ChoreOrNothing` is considered different from the type :mzn:`Chores` by the compiler, in order to avoid any ambiguities or accidental type conversions. The compiler also generates inverses of all constructor functions, to map back from the extended types into the base types. This can be seen in the output item, where :mzn:`C^-1` is used to map from :mzn:`ChoreOrNothing` back to :mzn:`Chores`. The inverse function can be written as ASCII using the :mzn:`^-1` notation, or using the unicode symbols :mzn:`⁻¹`, as in :mzn:`C⁻¹`. 875 876In the example above, we could have used option types, instead of adding a new value that acts essentially like the absent value :mzn:`<>`. However, extended enum types have some advantages in this scenario. For example, we can extend a type by multiple extra values (say, different reasons for not being assigned any chore). We can also combine multiple enumerated types into one. Consider the scenario in :numref:`ex-assignment-combine-enums` where we can assign chores to flatmates and/or robots. Flatmates have preferences for certain chores, while robots have integer benefits. The model also shows how to test if a value of the extended enum in fact belongs to the underlying enum: In the output item, the test :mzn:`w in F(Flatmates)` uses the :mzn:`F` constructor to translate the set :mzn:`Flatmates` into the :mzn:`Worker` type, which enables the use of the :mzn:`in` operator. 877 878.. literalinclude:: examples/assignment-combine-enums.mzn 879 :language: minizinc 880 :name: ex-assignment-combine-enums 881 :caption: Model for an assignment problem using combined enumerated types (:download:`assignment-combine-enums.mzn <examples/assignment-combine-enums.mzn>`). 882 883 884.. _sec-complex: 885 886Complex Constraints 887------------------- 888 889.. index:: 890 single: constraint; complex 891 892Constraints are the core of the MiniZinc model. 893We have seen simple relational expressions but constraints can be considerably more powerful than this. 894A constraint is allowed to be any Boolean expression. 895Imagine a scheduling problem in which we have 896two tasks that cannot overlap in time. 897If :mzn:`s1` and :mzn:`s2` are the corresponding start times 898and :mzn:`d1` and :mzn:`d2` are the corresponding 899durations 900we can express this as: 901 902.. code-block:: minizinc 903 904 constraint s1 + d1 <= s2 \/ s2 + d2 <= s1; 905 906which ensures that the tasks do not overlap. 907 908 909.. defblock:: Booleans 910 911 .. index:: 912 single: Boolean 913 single: expression; Boolean 914 single: true 915 single: false 916 single: operator; Boolean 917 single: bool2int 918 919 Boolean expressions in MiniZinc can be written using a standard mathematical syntax. 920 The Boolean literals are :mzn:`true` and 921 :mzn:`false` 922 and the Boolean 923 operators 924 are 925 conjunction, i.e. and (``/\``), 926 disjunction, i.e. or (``\/``), 927 only-if (:mzn:`<-`), 928 implies (:mzn:`->`), 929 if-and-only-if (:mzn:`<->`) and 930 negation (:mzn:`not`). 931 Booleans can be automatically coerced to integers, but to make this 932 coercion explicit the 933 built-in function :mzn:`bool2int` can be used: it 934 returns 1 if its argument is true and 0 otherwise. 935 936.. literalinclude:: examples/jobshop.mzn 937 :language: minizinc 938 :name: ex-jobshop 939 :caption: Model for job-shop scheduling problems (:download:`jobshop.mzn <examples/jobshop.mzn>`). 940 941.. literalinclude:: examples/jdata.dzn 942 :language: minizinc 943 :name: ex-jdata 944 :caption: Data for job-shop scheduling problems (:download:`jdata.dzn <examples/jdata.dzn>`). 945 946The job shop scheduling model given in :numref:`ex-jobshop` 947gives a realistic example of the use of this disjunctive modelling 948capability. In job shop scheduling we have a set of jobs, each consisting 949of a sequence of tasks on separate machines: so task :mzn:`[i,j]` is the 950task in the :math:`i^{th}` job performed on the :math:`j^{th}` machine. 951Each sequence of tasks must be completed in order, 952and no two tasks on the same machine can overlap in time. 953Even for small instances of this problem it can be quite challenging to find 954optimal solutions. 955 956The command 957 958.. code-block:: bash 959 960 $ minizinc --solver gecode --all-solutions jobshop.mzn jdata.dzn 961 962solves a small job shop scheduling problem, and illustrates the behaviour of 963``--all-solutions`` for optimisation problems (note that when running this in the MiniZinc IDE, ``--all-solutions`` is the default behaviour for optimisation problems). Here the solver outputs increasingly better solutions as it finds them, rather than all possible optimal 964solutions. The output from this command is: 965 966.. code-block:: none 967 968 end = 39 969 5 9 13 22 30 970 6 13 18 25 36 971 0 4 8 12 16 972 4 8 12 16 22 973 9 16 25 27 38 974 ---------- 975 end = 37 976 4 8 12 17 20 977 5 13 18 26 34 978 0 4 8 12 16 979 8 12 17 20 26 980 9 16 25 27 36 981 ---------- 982 end = 34 983 0 1 5 10 13 984 6 10 15 23 31 985 2 6 11 19 27 986 1 5 10 13 19 987 9 16 22 24 33 988 ---------- 989 end = 30 990 5 9 13 18 21 991 6 13 18 25 27 992 1 5 9 13 17 993 0 1 2 3 9 994 9 16 25 27 29 995 ---------- 996 ========== 997 998indicating an optimal solution with end time 30 is finally found, 999and proved optimal. 1000We can generate all *optimal solutions* 1001by adding a constraint that 1002:mzn:`end = 30` and changing the solve item to :mzn:`solve satisfy` 1003and then executing 1004 1005.. code-block:: bash 1006 1007 $ minizinc --solver gecode --all-solutions jobshop.mzn jobshop.dzn 1008 1009For this problem there are 3,444,375 optimal solutions. In the MiniZinc IDE, you would have to select "User-defined behavior" in the configuration pane and set the number of solutions to zero in order to display all solutions of this satisfaction problem. 1010 1011.. literalinclude:: examples/stable-marriage.mzn 1012 :language: minizinc 1013 :name: ex-stable-marriage 1014 :caption: Model for the stable marriage problem (:download:`stable-marriage.mzn <examples/stable-marriage.mzn>`). 1015 1016.. literalinclude:: examples/stable-marriage.dzn 1017 :language: minizinc 1018 :name: ex-sm-data 1019 :caption: Example data for the stable marriage problem (:download:`stable-marriage.dzn <examples/stable-marriage.dzn>`). 1020 1021Another powerful modelling feature in MiniZinc is 1022that decision variables 1023can be used for :index:`array access <array; access>`. 1024As an example, consider the 1025(old-fashioned) *stable marriage problem*. We have :mzn:`n` (straight) women and :mzn:`n` (straight) 1026men. Each man has a ranked list of women and vice versa. We want to find a 1027husband/wife for each women/man so that all marriages are *stable* in 1028the sense that: 1029 1030- whenever :mzn:`m` prefers another women :mzn:`o` to his wife :mzn:`w`, :mzn:`o` prefers her husband to :mzn:`m`, and 1031- whenever :mzn:`w` prefers another man :mzn:`o` to her husband :mzn:`m`, :mzn:`o` prefers his wife to :mzn:`w`. 1032 1033This can be elegantly modelled in 1034MiniZinc. 1035The model and sample data is shown in :numref:`ex-stable-marriage` and :numref:`ex-sm-data`. 1036 1037The first three items in the model declare the number of men/women and the 1038set of men and women. Here we introduce the use of *anonymous enumerated types*. 1039Both :mzn:`Men` and :mzn:`Women` are sets of size 1040:mzn:`n`, but we do not wish to mix them up so we use an anonymous enumerated 1041type. This allows MiniZinc to detect modelling errors where we use 1042:mzn:`Men` for :mzn:`Women` or vice versa. 1043 1044 1045The matrices :mzn:`rankWomen` and :mzn:`rankMen`, 1046respectively, give the women's ranking of the men and the men's ranking of the women. 1047Thus, the entry :mzn:`rankWomen[w,m]` 1048gives the ranking by woman :mzn:`w` of man :mzn:`m`. The lower the number in the ranking, the more the man or women is preferred. 1049 1050There are two arrays of decision variables: :mzn:`wife` and 1051:mzn:`husband`. These, respectively, contain the wife of each man and the 1052husband of each women. 1053 1054The first two constraints 1055 1056.. literalinclude:: examples/stable-marriage.mzn 1057 :language: minizinc 1058 :lines: 13-14 1059 1060ensure that the assignment of husbands and wives is consistent: :mzn:`w` is the 1061wife of :mzn:`m` implies :mzn:`m` is the husband of :mzn:`w` and vice versa. Notice how in 1062:mzn:`husband[wife[m]]` the index expression :mzn:`wife[m]` is a 1063decision variable, not a parameter. 1064 1065The next two constraints are a direct encoding of the stability condition: 1066 1067.. literalinclude:: examples/stable-marriage.mzn 1068 :language: minizinc 1069 :lines: 16-22 1070 1071This natural modelling of the stable marriage problem is made possible by 1072the ability to use decision variables as array indices and to construct 1073constraints using the standard Boolean connectives. 1074The alert reader may 1075be wondering at this stage, what happens if the array index variable takes a 1076value that is outside the index set of the array. MiniZinc treats this as 1077failure: an array access :mzn:`a[e]` implicitly adds the constraint 1078:mzn:`e in index_set(a)` 1079to the closest surrounding Boolean context where 1080:mzn:`index_set(a)` 1081gives the index set of :mzn:`a`. 1082 1083.. defblock:: Anonymous Enumerated Types 1084 1085 .. index:: 1086 single: type; enumerated; anonymous 1087 1088 An *anonymous enumerated type* 1089 is of the form :mzndef:`anon_enum(<n>)` where :mzndef:`<n>` is a fixed integer 1090 expression defining the size of the enumerated type. 1091 1092 An anonymous enumerated type is just like any other enumerated type except 1093 that we have no names for its elements. When printed out, they are given 1094 unique names based on the enumerated type name. 1095 1096Thus for example, consider the variable declarations 1097 1098.. code-block:: minizinc 1099 1100 array[1..2] of int: a= [2,3]; 1101 var 0..2: x; 1102 var 2..3: y; 1103 1104The constraint :mzn:`a[x] = y` 1105will succeed with :math:`x=1 \wedge y=2` and :math:`x=2 \wedge y=3`. 1106And the constraint :mzn:`not a[x] = y` will succeed with 1107:math:`x=0 \wedge y=2`, :math:`x=0 \wedge y=3`, :math:`x=1 \wedge y=3` and :math:`x=2 \wedge y=2`. 1108 1109In the case of invalid array accesses by a parameter, the formal semantics 1110of MiniZinc treats this as failure so as to ensure that the treatment of 1111parameters and decision variables is consistent, but a warning is issued 1112since it is almost always an error. 1113 1114.. literalinclude:: examples/magic-series.mzn 1115 :language: minizinc 1116 :name: ex-magic-series 1117 :caption: Model solving the magic series problem (:download:`magic-series.mzn <examples/magic-series.mzn>`). 1118 1119.. index:: 1120 single: bool2int 1121 single: constraint; higher order 1122 1123The coercion function 1124:mzn:`bool2int` 1125can be called with any Boolean 1126expression. This allows the MiniZinc 1127modeller to use so called *higher order constraints*. 1128As a simple example consider the *magic series problem*: 1129find a list of numbers :math:`s= [s_0,\ldots,s_{n-1}]` 1130such that :math:`s_i` is the number 1131of occurrences of :math:`i` in :math:`s`. An example is :math:`s = [1,2,1,0]`. 1132 1133A MiniZinc 1134model for this problem 1135is shown in :numref:`ex-magic-series`. The use of 1136:mzn:`bool2int` allows us to sum up the number of times the constraint 1137:mzn:`s[j]=i` is satisfied. 1138Executing the command 1139 1140.. code-block:: bash 1141 1142 $ minizinc --solver gecode --all-solutions magic-series.mzn -D "n=4;" 1143 1144leads to the output 1145 1146.. code-block:: none 1147 1148 s = [1, 2, 1, 0]; 1149 ---------- 1150 s = [2, 0, 2, 0]; 1151 ---------- 1152 ========== 1153 1154indicating exactly two solutions to the problem (the effect of ``--all-solutions`` can be achieved in the MiniZinc IDE using the "User-defined behavior" option in the solver configuration pane). 1155 1156Note that MiniZinc will automatically coerce Booleans 1157to integers and integers to floats when required. 1158We could replace the the constraint item in :numref:`ex-magic-series` 1159with 1160 1161.. code-block:: minizinc 1162 1163 constraint forall(i in 0..n-1) ( 1164 s[i] = (sum(j in 0..n-1)(s[j]=i))); 1165 1166and get identical results, since the Boolean expression 1167:mzn:`s[j] = i` will be automatically coerced to an 1168integer, effectively by the MiniZinc system automatically adding the 1169missing :mzn:`bool2int`. 1170 1171.. defblock:: Coercion 1172 1173 .. index:: 1174 single: coercion; automatic 1175 single: coercion; bool2int 1176 single: coercion; int2float 1177 1178 In MiniZinc one can *coerce* a Boolean value to 1179 an integer value using the :mzn:`bool2int` function. 1180 Similarly one can coerce an integer value to a float value using 1181 :mzn:`int2float`. 1182 The instantiation of the coerced value is the same as the argument, 1183 e.g. :mzn:`par bool` is coerced to :mzn:`par int`, while 1184 :mzn:`var bool` is coerced to :mzn:`var int`. 1185 1186 MiniZinc automatically coerces Boolean expressions to integer 1187 expressions and integer expressions to float expressions, 1188 by inserting :mzn:`bool2int` and :mzn:`int2float` in the model 1189 appropriately. 1190 Note that it will also coerce Booleans to floats using two steps. 1191 1192 1193Set Constraints 1194--------------- 1195 1196.. index:: 1197 single: constraint; set 1198 1199Another powerful modelling feature of MiniZinc 1200is that it allows sets 1201containing integers to be decision variables: 1202this means that when the model is evaluated the solver will find which elements are in the set. 1203 1204As a simple example, consider the *0/1 knapsack problem*. This is a 1205restricted form of the knapsack problem in which we can either choose to 1206place the item in the knapsack or not. Each item has a weight and a profit 1207and we want to find which choice of items leads to the maximum profit 1208subject to the knapsack not being too full. 1209 1210It is natural to model this in MiniZinc with a single decision variable: :mzn:`var set of ITEM: knapsack` 1211where :mzn:`ITEM` is the set of possible items. If the arrays 1212:mzn:`weight[i]` and :mzn:`profit[i]` respectively give the weight and 1213profit of item :mzn:`i`, and the maximum weight the knapsack can carry is 1214given by :mzn:`capacity` then a natural model is given in 1215:numref:`ex-knapsack-binary`. 1216 1217.. literalinclude:: examples/knapsack.mzn 1218 :language: minizinc 1219 :name: ex-knapsack-binary 1220 :caption: Model for the 0/1 knapsack problem (:download:`knapsack.mzn <examples/knapsack.mzn>`). 1221 1222Notice that the :mzn:`var` 1223keyword comes before the :mzn:`set` 1224declaration indicating that the 1225set itself is the decision variable. 1226This contrasts with an array in which the :mzn:`var` keyword 1227qualifies the elements in the array rather than the array itself since the 1228basic structure of the array is fixed, i.e. its index set. 1229 1230.. literalinclude:: examples/social-golfers.mzn 1231 :language: minizinc 1232 :name: ex-social-golfers 1233 :caption: Model for the social golfers problems (:download:`social-golfers.mzn <examples/social-golfers.mzn>`). 1234 1235 1236As a more complex example of set constraint consider the social golfers 1237problem shown in :numref:`ex-social-golfers`. 1238The aim is to schedule a golf tournament over :mzn:`weeks` 1239using :mzn:`groups` :math:`\times` :mzn:`size` golfers. Each week we have to 1240schedule :mzn:`groups` different groups each of size :mzn:`size`. 1241No two pairs of golfers should ever play in two groups. 1242 1243The variables in the model are sets of golfers :mzn:`Sched[i,j]` 1244for the :math:`i^{th}` week and :mzn:`j^{th}` group. 1245 1246The constraints shown in lines 11-32 1247first enforces an ordering on the first 1248set in each week to remove symmetry in swapping weeks. Next they 1249enforce an ordering on the sets in each week, and make each set have a 1250cardinality of :mzn:`size`. 1251They then ensure that each week is a partition of the set of golfers 1252using the global constraint 1253:mzn:`partition_set`. 1254Finally the last constraint ensures that no two players play in two 1255groups together (since the cardinality of the intersection of any two groups 1256is at most 1). 1257 1258.. index:: 1259 single: symmetry; breaking 1260 1261There are also symmetry breaking 1262initialisation constraints shown in lines 34-46: 1263the first week 1264is fixed to have all players in order; the second week is made up of the 1265first players of each of the first groups in the first week; finally the 1266model forces the first :mzn:`size` players to appear in their corresponding 1267group number for the remaining weeks. 1268 1269Executing the command 1270 1271.. code-block:: bash 1272 1273 $ minizinc --solver gecode social-golfers.mzn social-golfers.dzn 1274 1275where the data file defines a problem with 4 weeks, with 4 groups 1276of size 3 leads to the output 1277 1278.. code-block:: none 1279 1280 1..3 4..6 7..9 10..12 1281 {1,4,7} {2,9,12} {3,5,10} {6,8,11} 1282 {1,6,9} {2,8,10} {3,4,11} {5,7,12} 1283 {1,5,8} {2,7,11} {3,6,12} {4,9,10} 1284 ---------- 1285 1286Notice hows sets which are ranges may be output in range format. 1287 1288 1289Putting it all together 1290----------------------- 1291 1292We finish this section with a complex example illustrating most 1293of the features introduced in this chapter including 1294enumerated types, complex constraints, global constraints, 1295and complex output. 1296 1297.. literalinclude:: examples/wedding.mzn 1298 :language: minizinc 1299 :name: ex-wedding 1300 :caption: Planning wedding seating using enumerated types (:download:`wedding.mzn <examples/wedding.mzn>`). 1301 1302The model of :numref:`ex-wedding` arranges seats at the wedding table. 1303The table has 12 numbered seats in order around the table, 6 on each side. 1304Males must sit in odd numbered seats, and females in even. 1305Ed cannot sit at the end of the table because of a phobia, 1306and the bride and groom must 1307sit next to each other. The aim is to maximize the distance between known 1308hatreds. The distance between seats is the difference in seat number 1309if on the same side, otherwise its the distance to the opposite seat 1310+ 1. 1311 1312Note that in the output statement we consider each seat :mzn:`s` and search for a 1313guest :mzn:`g` who is assigned to that seat. We make use of the built in function 1314:mzn:`fix` which checks if a decision variable is fixed and returns its 1315fixed value, and otherwise aborts. 1316This is always safe to use in output statements, since by the 1317time the output statement is run all decision variables should be fixed. 1318 1319 1320Running 1321 1322.. code-block:: bash 1323 1324 $ minizinc --solver gecode wedding.mzn 1325 1326Results in the output 1327 1328.. code-block:: none 1329 1330 ted bride groom rona ed carol ron alice bob bridesmaid bestman clara 1331 ---------- 1332 ========== 1333 1334The resulting table placement is illustrated in :numref:`fig-wedding` 1335where the lines indicate hatreds. The total distance is 22. 1336 1337.. _fig-wedding: 1338 1339.. figure:: figures/wedding.* 1340 1341 Seating arrangement at the wedding table 1342 1343 1344.. \pjs{Move the fix definition elsewhere!} 1345 1346.. defblock:: Fix 1347 1348 .. index:: 1349 single: fix 1350 single: fixed 1351 1352 In output items the built-in function :mzn:`fix` checks that 1353 the value of a decision variable is fixed 1354 and coerces the instantiation from 1355 decision variable to parameter. 1356 1357.. % oil-blending 1358.. %arrays floats sum forall 1359.. %more complex datafile 1360.. 1361.. %suduko 1362.. %2-D array 1363.. %complex transformation from data file 1364.. 1365.. %jobshop 1366.. %disjunction, 1367.. 1368.. %talk about other complex constraints--IC example? 1369.. 1370.. %magic sequence 1371.. %reification 1372.. 1373.. %warehouse placement 1374.. %reification more complex example 1375.. 1376.. %0/1 knapsack 1377.. %set constraint 1378.. 1379.. %social golfers 1380.. %more complex set constraint 1381.. 1382.. %finish with larger example from Mark 1383