this repo has no description
1Modelos más complejos
2=====================
3
4En la última sección presentamos la estructura básica de un modelo MiniZinc. En esta sección presentamos la matriz, las estructuras de datos establecidas, los tipos enumerados y las restricciones más complejas.
5
6.. _sec-arrayset:
7
8Las matrices y conjuntos
9------------------------
10
11Casi siempre estamos interesados en construir modelos donde el número de restricciones y variables depende de los datos de entrada. Para ello, usualmente utilizaremos index: `matrices <array>`.
12
13Consideremos un modelo simple de elementos finitos para modelar las temperaturas en una chapa de metal rectangular. Aproximamos las temperaturas a través de la hoja, rompiendo la hoja en un número finito de elementos en una matriz bidimensional.
14
15Un modelo es mostrado en :numref:`ex-laplace`.
16Declara el ancho ``w`` y la altura ``h`` del modelo de elementos finitos.
17
18La declaración
19
20.. literalinclude:: examples/laplace_es.mzn
21 :language: minizinc
22 :lines: 5-9
23
24declara cuatro conjuntos fijos de enteros que describen las dimensiones del modelo de elementos finitos:
25``HEIGHT`` es toda la altura del modelo, mientras que ``CHEIGHT`` es el centro de la altura omitiendo la parte superior e inferior,
26``WIDTH`` es el ancho total del modelo, mientras que ``CWIDTH`` es el centro de la anchura omitiendo la izquierda y derecha,
27
28Finalmente, una matriz bidimensional de variables flotantes ``t`` con filas numeradas :math:`0` to :math:`h` (``HEIGHT``) y columnas :math:`0` to :math:`w` (``WIDTH``), para representar las temperaturas en cada punto de la placa metálica.
29Podemos acceder al elemento de la matriz en la fila :math:`i^{th}` y columna :math:`j^{th}` usando una expresión :mzn:`t[i,j]`.
30
31
32La ecuación de Laplace indica que cuando la placa alcanza un estado estacionario la temperatura en cada punto interno es la media de sus vecinos ortogonales.
33
34La restricción
35
36.. literalinclude:: examples/laplace_es.mzn
37 :language: minizinc
38 :lines: 16-18
39
40Asegura que cada punto interno :math:`(i,j)` es el promedio de sus cuatro vecinos ortogonales.
41
42Las restricciones
43
44.. literalinclude:: examples/laplace_es.mzn
45 :language: minizinc
46 :lines: 20-24
47
48Restringir las temperaturas en cada borde para ser iguales, y da estos nombres de las temperaturas: ``left``, ``right``, ``top`` and ``bottom``.
49
50Si bien las limitaciones
51
52.. literalinclude:: examples/laplace_es.mzn
53 :language: minizinc
54 :lines: 26-30
55
56Asegurarse que las esquinas (que son irrelevantes) se ajustan a 0.0.
57Podemos determinar las temperaturas en una placa dividida en 5 :math:`\times` 5 elementos con temperatura izquierda, derecha e inferior 0 y temperatura superior 100 con el modelo mostrado en:numref:`ex-laplace`.
58
59
60.. literalinclude:: examples/laplace_es.mzn
61 :language: minizinc
62 :name: ex-laplace
63 :caption: Modelo de placa de elementos finitos para determinar las temperaturas en estado estable (:download:`laplace_es.mzn <examples/laplace_es.mzn>`).
64
65Ejecutando el comando
66
67.. code-block:: bash
68
69 $ mzn-cbc laplace_es.mzn
70
71Da la salida
72
73.. code-block:: none
74
75 0.00 100.00 100.00 100.00 0.00
76 0.00 42.86 52.68 42.86 0.00
77 0.00 18.75 25.00 18.75 0.00
78 0.00 7.14 9.82 7.14 0.00
79 0.00 0.00 0.00 0.00 0.00
80 ----------
81
82.. defblock:: Conjuntos
83
84 .. index::
85 single: set
86
87 Las variables de conjunto se declaran con una declaración de la forma
88
89 .. code-block:: minizincdef
90
91 set of <type-inst> : <var-name> ;
92
93 donde se permiten conjuntos de enteros, enumeraciones (ver más adelante), flotantes o booleanos.
94 El único tipo permitido para conjuntos de variables de decisión son conjuntos variables de enteros o enumeraciones.
95
96 Los literales establecidos son de la forma
97
98 .. code-block:: minizincdef
99
100 { <expr-1>, ..., <expr-n> }
101
102 o son expresiones :index:`range` sobre enteros, enumeraciones o flotantes de la forma
103
104 .. code-block:: minizincdef
105
106 <expr-1> .. <expr-2>
107
108 El estandar :index:`set operations <operator; set>` están provistos por:
109 pertenencia elemento (:mzn:`in`),
110 (no-estricto) relación de subconjuntos (:mzn:`subset`),
111 (no-estricto) relación superconjunto (:mzn:`superset`),
112 union (:mzn:`union`),
113 intersecciñon (:mzn:`intersect`),
114 diferencia de conjuntos (:mzn:`diff`),
115 diferencia de conjunto simétrico (:mzn:`symdiff`)
116 y la cantidad de elementos en el conjunto (:mzn:`card`).
117
118Como hemos visto, las variables establecidas y los literales establecidos (incluidos los rangos), se pueden usar como un tipo implícito en las declaraciones de variables. En cuyo caso la variable tiene el tipo de los elementos en el conjunto y la variable está implícitamente restringida para ser miembro del conjunto.
119
120Nuestro problema de horneado de pastele, es un ejemplo de un tipo muy simple de problema de planificación de la producción. En este tipo de problema, deseamos determinar qué cantidad de cada tipo de producto se debe hacer para maximizar los beneficios cuando la fabricación de un producto consume cantidades variables de algunos recursos fijos. Podemos generalizar el modelo MiniZinc en :numref:`ex-cakes2` para manejar este tipo de problema con un modelo que sea genérico en los tipos de recursos y productos. El modelo se muestra en :numref:`ex-prod-planning` y un archivo de datos de muestra (para el ejemplo de bicarbonato) se muestra en :numref:`fig-prod-planning-data`.
121
122
123.. literalinclude:: examples/simple-prod-planning_es.mzn
124 :language: minizinc
125 :name: ex-prod-planning
126 :caption: Modelo para planificación de producción simple (:download:`simple-prod-planning_es.mzn <examples/simple-prod-planning_es.mzn>`).
127
128.. literalinclude:: examples/simple-prod-planning-data_es.dzn
129 :language: minizinc
130 :name: fig-prod-planning-data
131 :caption: Archivo de datos de ejemplo para el problema simple de planificación de la producción (:download:`simple-prod-planning-data_es.dzn <examples/simple-prod-planning-data_es.dzn>`).
132
133La nueva característica de este modelo es el uso de :index:`enumerated types <type; enumerated>`.
134Esto nos permite tratar la elección de recursos y productos como parámetros para el modelo.
135El primer artículo en el modelo
136
137.. code-block:: minizinc
138
139 enum Products;
140
141Declara ``Products`` como un conjunto de productos *desconocido*.
142
143.. defblock:: Enumerated Types
144
145 .. index::
146 single: enumerated type
147 single enum
148
149 Los tipos enumerados, a los que nos referiremos como ``enumeraciones``, se declaran con una declaración de la forma:
150
151 .. code-block:: minizincdef
152
153 enum <var-name> ;
154
155 Un tipo enumerado se define mediante una asignación del formulario
156
157
158 .. code-block:: minizincdef
159
160 enum <var-name> = { <var-name-1>, ..., <var-name-n> } ;
161
162
163 Donde :mzndef:`<var-name-1>`, ..., :mzndef:`<var-name-n>` son los elementos del tipo enumerado, con el nombre :mzndef:`<var-name>`.
164 Cada uno de los elementos del tipo enumerado también es declarado efectivamente por esta definición como una nueva constante de ese tipo.
165 La declaración y la definición se pueden combinar en una línea como de costumbre.
166
167El segundo elemento declara una matriz de enteros:
168
169.. code-block:: minizinc
170
171 array[Products] of int: profit;
172
173El :index:`index set <array; index set>` del array ``profit`` es ``Products``.
174Esto significa que solo los elementos del conjunto ``Products`` se pueden usar para indexar la matriz.
175
176Los elementos de un tipo enumerado de :math:`n` elements actúan de forma muy similar a los enteros :math:`1 \dots n`. Se pueden comparar, están ordenados, por el orden en que aparecen en la definición del tipo enumerado, se pueden volver a procesar, pueden aparecer como índices de matrices, de hecho, pueden aparecer en cualquier lugar donde pueda aparecer un número entero.
177
178En el archivo de datos de ejemplo, hemos inicializado la matriz usando una lista de enteros
179
180.. code-block:: minizinc
181
182 Products = { BananaCake, ChocolateCake };
183 profit = [400,450];
184
185Lo que significa que la ganancia de un pastel de plátano es de 400, mientras que para un pastel de chocolate es de 450. Internamente, ``BananaCake`` se tratará como el número entero 1, mientras que ``ChocolateCake`` se tratará como el número entero 2.
186
187Aunque MiniZinc no proporciona un tipo de lista explícito, las matrices unidimensionales con un conjunto de índices :mzn:`1..n` se comportan como listas, y a veces nos referiremos a ellas como :index:`lists <list>`.
188
189De manera similar, en los siguientes dos elementos declaramos un conjunto de recursos ``Recursos``, y una matriz ``capacidad`` que da la cantidad de
190cada recurso que está disponible.
191
192Más interesante, el artículo
193
194.. code-block:: minizinc
195
196 array[Products, Resources] of int: consumption;
197
198Declara una matriz 2-D ``consumption``. El valor de :mzn:`consumption[p, r]` es la cantidad de recurso :mzn:`r` requerido para producir una unidad de producto :mzn:`p`. Tenga en cuenta que el primer índice es la fila y el segundo es la columna.
199
200El archivo de datos contiene una inicialización de ejemplo de una matriz 2-D:
201
202.. code-block:: minizinc
203
204 consumption= [| 250, 2, 75, 100, 0,
205 | 200, 0, 150, 150, 75 |];
206
207Observe cómo el delimitador ``|`` se usa para separar filas.
208
209.. defblock:: Arrays
210
211 .. index:
212 single: array
213
214
215 Por lo tanto, MiniZinc proporciona matrices de una y varias dimensiones que se declaran utilizando el tipo:
216
217 .. code-block:: minizincdef
218
219 array [ <index-set-1>, ..., <index-set-n> ] of <type-inst>
220
221 MiniZinc requiere que la declaración de matriz contenga el conjunto de índices de cada dimensión y que el conjunto de índices sea un rango entero, una variable establecida inicializada a un rango entero, o un :index:`enumeration type <enumerated type>`.
222
223 Las matrices pueden contener cualquiera de los tipos base: enteros, enumeraciones, booleanos, flotantes o cadenas. Estos pueden ser fijos o no, a excepción de cadenas que solo pueden ser parámetros. Las matrices también pueden contener conjuntos, pero no pueden contener matrices.
224
225 :index:`One-dimensional array literals <array; literal; 1D>` son de la forma:
226
227 .. code-block:: minizincdef
228
229 [ <expr-1>, ..., <expr-n> ]
230
231 Mientras que :index:`two-dimensional array literals <array; literal; 2D>` son de la forma:
232
233 .. code-block:: minizincdef
234
235 [| <expr-1-1>, ..., <expr-1-n> |
236 ... |
237 <expr-m-1>, ..., <expr-m-n> |]
238
239 Donde la matriz tiene columnas ``m`` y ``n``.
240
241 La familia de funciones incorporadas :mzn:`array1d`, :mzn:`array2d`, etc., se puede utilizar para inicializar una matriz de cualquier dimensión de una lista (o más exactamente una matriz unidimensional).
242
243 La llamada:
244
245 .. code-block:: minizincdef
246
247 array<n>d(<index-set-1>, ..., <index-set-n>, <list>)
248
249 returns an ``n`` dimensional array with index sets given by the first ``n``
250 arguments and the last argument contains the elements of the array. For
251 instance, :mzn:`array2d(1..3, 1..2, [1, 2, 3, 4, 5, 6])` is equivalent to
252 :mzn:`[|1, 2 |3, 4 |5, 6|]`.
253
254 Devuelve una matriz dimensional ``n`` con conjuntos de índices dados por los primeros argumentos ``n`` y el último argumento contiene los elementos de la matriz.
255 Por ejemplo, :mzn:`array2d (1..3, 1..2, [1, 2, 3, 4, 5, 6])` es equivalente a :mzn:`[| 1, 2 | 3, 4 | 5, 6 |]`.
256
257 Los elementos de la matriz son :index:`accessed <array; access>` de la forma habitual: :mzn:`a[i, j]` da el elemento en la fila :math:`i^{th}` y en la columna :math:`j^{th}`.
258
259 .. \pjs{New array functions!}
260
261 El operador de concatenación ``++`` se puede usar para concatenar dos matrices unidimensionales juntas. El resultado es una lista, es decir, una matriz unidimensional cuyos elementos están indexados desde 1.
262
263 Por ejemplo, :mzn:`[4000, 6] ++ [2000, 500, 500]` evalúa a :mzn:`[4000, 6 , 2000, 500, 500]`.
264
265 La función incorporada :mzn:`length` devuelve la longitud de una matriz unidimensional.
266
267El siguiente elemento en el modelo define el parámetro :mzn:`mproducts`. Esto se establece en un límite superior en la cantidad de productos de cualquier tipo que se pueden producir. Este es un ejemplo bastante complejo de comprensiones de conjuntos anidados y operadores de agregación. Los presentaremos antes de tratar de entender este artículo y el resto del modelo.
268
269En primer lugar, MiniZinc proporciona comprensiones de listas similares a las provistas en muchos lenguajes de programación funcionales, o Python. Por ejemplo, la lista de comprensión :mzn:`[i + j | i, j in 1..3 where j < i]` evalúa a :mzn:`[2 + 1, 3 + 1, 3 + 2]` que es :mzn:`[3, 4, 5]`. Por supuesto :mzn:`[3, 4, 5]` es simplemente una matriz con conjunto de índices :mzn:`1..3`.
270
271MiniZinc también proporciona conjuntos de comprensiones que tienen una sintaxis similar: por ejemplo, :mzn:`{i + j | i, j in 1..3 where j < i}` evalúa al conjunto :mzn:`{3, 4, 5}`.
272
273.. defblock:: Enumeraciones y Establecer comprensiones
274
275 .. index:
276 single: comprehension
277 single: comprehension; list
278
279 La forma genérica de una lista de comprensión es
280
281 .. code-block:: minizincdef
282
283 [ <expr> | <generator-exp> ]
284
285 La expresión :mzndef:`<expr>` especifica cómo construir elementos en la lista de salida a partir de los elementos generados por :mzndef:`<generator-exp>`. El generador :mzndef:`<generator-exp>` consiste en una secuencia separada por comas de expresiones generadoras opcionalmente, seguidas de una expresión booleana. Las dos formas son:
286
287 .. code-block:: minizincdef
288
289 <generator>, ..., <generator>
290 <generator>, ..., <generator> where <bool-exp>
291
292 El opcional :mzndef:`<bool-exp>` en la segunda forma actúa como un filtro en la expresión del generador. Solo los elementos que satisfacen la expresión booleana se usan para construir elementos en la lista de salida.
293 Un :index:`generator <comprehension; generator>` :mzndef:`<generator>` tiene la forma:
294
295 .. code-block:: minizincdef
296
297 <identifier>, ..., <identifier> in <array-exp>
298
299 Cada identificador es un *iterador* que toma los valores de la expresión de la matriz a su vez, con el último identificador que varía más rápidamente.
300
301 Los generadores de una lista de comprensión y :mzndef:`<bool-exp>` generalmente no involucran variables de decisión. Si implican variables de decisión, la lista producida es una lista de :mzndef:`var opt <T>` donde :mzndef:`<T>` es el tipo de :mzndef:`<expr>`. Vea la discusión de :index:`option types <option type>` en :ref:`sec-optiontypes` para más detalles.
302
303 :index:`Conjuntos de comprensiones <comprehension; set>` son casi idénticos a las comprensiones de la lista. La única diferencia es el uso de ``{`` y ``}`` para adjuntar la expresión en lugar de ``[`` y ``]``. Los elementos generados por una comprensión de conjunto deben ser :index:`fixed`, es decir, libre de variables de decisión. Del mismo modo, los generadores y opcional :mzndef:`<bool-exp>` para establecer las comprensiones deben ser corregidos.
304
305.. index::
306 single: forall
307
308En segundo lugar, MiniZinc proporciona una serie de funciones integradas que toman una matriz unidimensional y que agregan los elementos. Probablemente el más útil de estos es :mzn:``forall``. Esto toma una matriz de expresión booleana (es decir, restricciones) y devuelve una única expresión booleana que es la conjunción lógica de las expresiones booleanas en la matriz.
309
310Por ejemplo, considera la expresión:
311
312.. code-block:: minizinc
313
314 forall( [a[i] != a[j] | i,j in 1..3 where i < j])
315
316Donde ``a`` es una matriz aritmética con el conjunto de índices ``1..3``.
317Esto limita los elementos en ``a`` para que sean diferentes por pares. La lista de comprensión se evalúa como :mzn:`[a [1] != a[2], a[1] != a[3], a[2] != a[3]]` y entonces el :mzn:`forall` devuelve la conjunción de logica mzn:`a[1] != a[2] /\ a[1] != a[3] /\ a[2] != a[3]`.
318
319.. defblock:: Funciones de Agregación
320
321 .. index::
322 single: aggregation function
323 single: sum
324 single: product
325 single: min
326 single: max
327 single: forall
328 single: exists
329 single: xorall
330 single: iffall
331 single: aggregation function; sum
332 single: aggregation function; product
333 single: aggregation function; min
334 single: aggregation function; max
335 single: aggregation function; forall
336 single: aggregation function; exists
337 single: aggregation function; xorall
338 single: aggregation function; iffall
339
340 Las *funciones de agregación* para matrices aritméticas son:
341 :mzn:`sum` que agrega los elementos,
342 :mzn:`product` que las multiplica,
343 y :mzn:`min` y :mzn:`max` que devuelven respectivamente el menor y mayor elemento en la matriz.
344 Cuando se aplica a un conjunto vacío, :mzn:`min` y :mzn:`max` dan un error en tiempo de ejecución, :mzn:`sum` devuelve 0 y :mzn:`product` devuelve 1.
345
346 MiniZinc proporciona cuatro funciones de agregación para matrices que contienen expresiones booleanas. Como hemos visto, el primero de ellos, :mzn:`forall`, devuelve una única restricción que es la conjunción lógica de las restricciones.
347 La segunda función, :mzn:`exists`, devuelve la disyunción lógica de las restricciones. Por lo tanto, :mzn:`forall` impone que todas las restricciones en la matriz se mantengan, mientras que :mzn:`exists` asegura que al menos una de las restricciones se mantenga. La tercera función, :mzn:`xorall`, asegura que se mantenga un número impar de restricciones. La cuarta función, :mzn:`iffall`, garantiza que se mantenga un número par de restricciones.
348
349
350La tercera y última pieza del rompecabezas es que MiniZinc permite una sintaxis especial para funciones de agregación cuando se usa con una comprensión de matriz. En lugar de escribir:
351
352.. code-block:: minizinc
353
354 forall( [a[i] != a[j] | i,j in 1..3 where i < j])
355
356El modelador puede en cambio escribir el aspecto más matemático
357
358.. code-block:: minizinc
359
360 forall (i,j in 1..3 where i < j) (a[i] != a[j])
361
362Las dos expresiones son completamente equivalentes: el modelador es libre de usar el que parezca más natural.
363
364.. defblock:: Generador de Expresiones de Llamada
365
366 .. index::
367 single: generator call
368 single: expression; generator call
369
370 Una *expresión de llamada del generador* tiene forma:
371
372 .. code-block:: minizincdef
373
374 <agg-func> ( <generator-exp> ) ( <exp> )
375
376
377 Los corchetes alrededor de la expresión del generador :mzndef:`<generator-exp>` y la expresión del constructor :mzndef:`<exp>` no son opcionales, deben estar allí.
378 Esto es equivalente a escribir:
379
380 .. code-block:: minizincdef
381
382 <agg-func> ( [ <exp> | <generator-exp> ] )
383
384 El :index:`aggregation function` :mzndef:`<agg-func>` es cualquier función de MiniZinc que espera una única matriz como argumento.
385
386Ahora estamos en condiciones de comprender el resto del modelo de planificación de producción simple que se muestra en :numref:`ex-prod-planning`. Por el momento, ignore el elemento que define :mzn:`mproducts`. El elemento más tarde:
387
388.. code-block:: minizinc
389
390 array[Products] of var 0..mproducts: produce;
391
392Define una matriz unidimensional :mzn:`produce` de variables de decisión. El valor de :mzn:`produce[p]` se establecerá en la cantidad de producto :mzn:`p` en la solución óptima.
393
394El siguiente punto
395
396.. code-block:: minizinc
397
398 array[Resources] of var 0..max(capacity): used;
399
400Define un conjunto de variables auxiliares que registran la cantidad de cada recurso que se utiliza.
401Las siguientes dos restricciones
402
403.. code-block:: minizinc
404
405 constraint forall (r in Resources)
406 (used[r] = sum (p in Products) (consumption[p, r] * produce[p]));
407 constraint forall (r in Resources)(used[r] <= capacity[r] );
408
409
410Calcular en :mzn:`used[r]` el consumo total del recurso :mzn:`r` y garantizar que sea menor que la cantidad disponible.
411Finalmente, el artículo
412
413.. code-block:: minizinc
414
415 solve maximize sum (p in Products) (profit[p]*produce[p]);
416
417Indica que este es un problema de maximización y que el objetivo a maximizar es el beneficio total.
418
419Ahora volvemos a la definición de :mzn:`mproducts`. Para cada producto
420:mzn:`p` la expresión:
421
422.. code-block:: minizinc
423
424 (min (r in Resources where consumption[p,r] > 0)
425 (capacity[r] div consumption[p,r])
426
427Determina la cantidad máxima de :mzn:`p` que se puede producir teniendo en cuenta la cantidad de cada recurso :mzn:`r` y la cantidad de :mzn:`r` que se requiere para producir el producto. Tenga en cuenta el uso del filtro :mzn:`where consumption[p,r] > 0` para garantizar que solo los recursos necesarios para fabricar el producto se consideran a fin de evitar una división por error cero.
428
429Por lo tanto, la expresión completa:
430
431.. code-block:: minizinc
432
433 int: mproducts = max (p in Products)
434 (min (r in Resources where consumption[p,r] > 0)
435 (capacity[r] div consumption[p,r]));
436
437Calcula la cantidad máxima de *cualquier* producto que se puede producir, y así se puede usar como un límite superior en el dominio de las variables de decisión en :mzn:`produce`.
438
439Finalmente observe que el ítem de salida es más complejo y usa :index:`list comprehensions <comprehension; list>` para crear una salida comprensible.
440
441Ejecutando el código:
442
443.. code-block:: bash
444
445 $ mzn-gecode simple-prod-planning_es.mzn simple-prod-planning-data_es.dzn
446
447Resulta en la salida:
448
449.. code-block:: none
450
451 BananaCake = 2;
452 ChocolateCake = 2;
453 Flour = 900;
454 Banana = 4;
455 Sugar = 450;
456 Butter = 500;
457 Cocoa = 150;
458 ----------
459 ==========
460
461
462Restricciones Globales
463----------------------
464
465.. \index{constraint!global|see{global constraint}}
466.. \index{global constraint}
467
468
469MiniZinc incluye una biblioteca de restricciones globales que también se puede usar para definir modelos. Un ejemplo es la restricción :mzn:`alldifferent` que requiere que todas las variables que aparecen en su argumento sean diferentes por pares.
470
471.. literalinclude:: examples/send-more-money_es.mzn
472 :language: minizinc
473 :name: ex-smm
474 :caption: Modelo para el problema criptoaritméticos SEND + MORE = MONEY (:download:`send-more-money_es.mzn <examples/send-more-money_es.mzn>`)
475
476El problema SEND + MORE = MONEY requiere asignar un dígito diferente a cada letra para que la restricción aritmética se mantenga. El modelo que se muestra en :numref:`ex-smm` usa la expresión de restricción :mzn:`alldifferent([S,E,N,D,M,O,R,Y])` para garantizar que cada letra tome un dígito diferente valor. La restricción global está disponible en el modelo utilizando el elemento *include*
477
478.. code-block:: minizinc
479
480 include "alldifferent.mzn";
481
482Lo que hace que la restricción global :mzn:`alldifferent` sea utilizable por el modelo. Uno podría reemplazar esta línea por
483
484.. code-block:: minizinc
485
486 include "globals.mzn";
487
488Que incluye todos los globales.
489
490En la documentación de la versión se incluye una lista de todas las restricciones globales definidas para MiniZinc. Ver :ref:`sec-globals` para una descripción de algunas restricciones globales importantes.
491
492
493
494
495Expresiones condicionales
496-------------------------
497
498.. \index{expression!conditional}
499
500
501MiniZinc proporciona una expresión condicional *if-then-else-endif*.
502Un ejemplo de su uso es:
503
504.. code-block:: minizinc
505
506 int: r = if y != 0 then x div y else 0 endif;
507
508Que establece :mzn:`r` a :mzn:`x` dividido por :mzn:`y` a menos que :mzn:`y` sea cero, en cuyo caso lo pone a cero.
509
510.. defblock:: Expresiones condicionales
511
512 .. index::
513 single: expression; conditional
514
515 La forma de una expresión condicional es
516
517 .. code-block:: minizincdef
518
519 if <bool-exp> then <exp-1> else <exp-2> endif
520
521 Es una expresión verdadera en lugar de una declaración de flujo de control y, por lo tanto, se puede usar en otras expresiones. Se evalúa como :mzndef:`<exp-1>` si la expresión booleana :mzndef:`<bool-exp>` es verdadera y :mzndef:`<exp-2>` en caso contrario. El tipo de expresión condicional es el de :mzndef:`<exp-1>` y :mzndef:`<exp-2>` que debe tener el mismo tipo.
522
523 Si el :mzndef:`<bool-exp>` contiene variables de decisión, entonces el tipo-instansación (type-inst) de la expresión es :mzndef:`var <T>` donde :mzndef:`<T>` es el tipo de :mzndef:`<exp-1>` y :mzndef:`<exp-2>` incluso si ambas expresiones son correctas.
524
525.. literalinclude:: examples/sudoku_es.mzn
526 :language: minizinc
527 :name: ex-sudoku
528 :caption: Modelo para el problema generalizado de Sudoku (:download:`sudoku_es.mzn <examples/sudoku_es.mzn>`)
529
530
531.. literalinclude:: examples/sudoku_es.dzn
532 :language: minizinc
533 :name: ex-sudokud
534 :caption: Ejemplo de archivo de datos para el problema generalizado de Sudoku (:download:`sudoku_es.dzn <examples/sudoku_es.dzn>`)
535
536.. _fig-sudoku:
537
538.. figure:: figures/sudoku.*
539
540 El problema representado por el archivo de datos :download:`sudoku_es.dzn <examples/sudoku_es.dzn>`
541
542Las expresiones condicionales son muy útiles en la creación de modelos complejos, o en resultados complejos. Considere el modelo de problemas de Sudoku que se muestra en :numref:`ex-sudoku`. Las posiciones iniciales de la placa están dadas por el parámetro :mzn:`start`, donde 0 representa una posición de tablero vacío. Esto se convierte en restricciones en las variables de decisión :mzn:`puzzle` utilizando la expresión condicional
543
544.. code-block:: minizinc
545
546 constraint forall(i,j in PuzzleRange)(
547 if start[i,j] > 0 then puzzle[i,j] = start[i,j] else true endif );
548
549Las expresiones condicionales también son muy útiles para definir el complejo :index:`output`. En el modelo Sudoku de :numref:`ex-sudoku` la expresión
550
551.. code-block:: minizinc
552
553 if j mod S == 0 then " " else "" endif
554
555Inserta un espacio extra entre los grupos de tamaño :mzn:`S`. La expresión de salida también usa expresiones condicionales para agregar líneas en blanco después de cada una :mzn:`S` lines. El resultado resultante es altamente legible.
556
557Las restricciones restantes aseguran que los números que aparecen en cada fila, columna y :math:`S \times S` sub-cuadrado son todos diferentes.
558
559.. index::
560 single: runtime flag; -a
561 single: runtime flag; --all-solutions
562 single: solution; all
563
564One can use MiniZinc to search for all solutions to a satisfaction problem (:mzn:`solve satisfy`) by using the flag ``-a`` or ``--all-solutions``. Running
565
566Uno puede usar MiniZinc para buscar todas las soluciones a un problema de satisfacción (:mzn:`solve satisfy`) usando la bandera ``-a`` o ``--all-solutions``.
567Ejecutando
568
569.. code-block:: bash
570
571 $ mzn-g12fd --all-solutions sudoku_es.mzn sudoku_es.dzn
572
573Resulta en:
574
575.. code-block:: none
576
577 5 9 3 7 6 2 8 1 4
578 2 6 8 4 3 1 5 7 9
579 7 1 4 9 8 5 2 3 6
580
581 3 2 6 8 5 9 1 4 7
582 1 8 7 3 2 4 9 6 5
583 4 5 9 1 7 6 3 2 8
584
585 9 4 2 6 1 8 7 5 3
586 8 3 5 2 4 7 6 9 1
587 6 7 1 5 9 3 4 8 2
588 ----------
589 ==========
590
591La línea ``==========`` se emite cuando el sistema ha generado todas las soluciones posibles, y aquí verifica que hay exactamente una.
592
593
594.. _sec-enum:
595
596Tipos enumerados
597----------------
598
599.. index::
600 single: type; enumerated
601
602Los tipos enumerados nos permiten construir modelos que dependen de un conjunto de objetos que forman parte de los datos, o se nombran en el modelo, y por lo tanto hacen que los modelos sean más fáciles de comprender y depurar. Hemos introducido tipos enumerados o enumeraciones brevemente, en esta subsección exploraremos cómo podemos usarlos más completamente y mostraremos algunas de las funciones integradas para tratar con tipos enumerados.
603
604Volvamos al problema de colorear el gráfico de Australia en :ref:`sec-modelling`.
605
606
607.. literalinclude:: examples/aust-enum_es.mzn
608 :language: minizinc
609 :name: ex-aust-enum
610 :caption: Modelo para colorear Australia usando tipos enumerados (:download:`aust-enum_es.mzn <examples/aust-enum_es.mzn>`).
611
612El modelo que se muestra en :numref:`ex-aust-enum` declara un tipo enumerado :mzn:`Color` que debe definirse en el archivo de datos. Cada una de las variables de estado se declara para tomar un valor de este tipo enumerado.
613
614Ejecutando este programa usando:
615
616.. code-block:: bash
617
618 $ mzn-gecode -D "Color = { red, yellow, blue };" aust-enum_es.mzn
619
620Puede resultar en la salida:
621
622.. code-block:: none
623
624 wa = yellow;
625 nt = blue;
626 sa = red;
627 q = yellow;
628 nsw = blue;
629 v = yellow;
630 t = red;
631
632
633.. defblock:: Declaraciones de variables de Tipo Enumeradas
634
635 .. index::
636 single: variable; declaration; enum
637
638 Un parámetro de tipo enumerado se declara como:
639
640 .. code-block:: minizincdef
641
642 <enum-name> : <var-name>
643 <l>..<u> : <var-name>
644
645 Donde :mzndef:`<enum-name>` es el nombre de un tipo enumerado, :mzndef:`<l>` y :mzndef:`<u>` son expresiones de tipos enumerados fijos del mismo tipo enumerado.
646
647 Una variable de decisión de tipo enumerada se declara como:
648
649 .. code-block:: minizincdef
650
651 var <enum-name> : <var-name>
652 var <l>..<u> : <var-name>
653
654 Donde :mzndef:`<enum-name>` es el nombre de un tipo enumerado, :mzndef:`<l>` y :mzndef:`<u>` son expresiones de tipos enumerados fijos del mismo tipo enumerado.
655
656Un comportamiento clave de los tipos enumerados es que son coercionados automáticamente a enteros cuando se usan en una posición que espera un entero. Por ejemplo, esto nos permite usar restricciones globales definidas en enteros, como
657
658.. code-block:: minizinc
659
660 global_cardinality_low_up([wa,nt,sa,q,nsw,v,t],
661 [red,yellow,blue],[2,2,2],[2,2,3]);
662
663Esto requiere al menos dos estados para colorear cada color y tres para ser de color azul.
664
665.. defblock:: Operaciones de Tipo enumeradas
666
667 Hay una serie de operaciones integradas en tipos enumerados:
668
669 - :mzn:`enum_next(X, x)`: devuelve el siguiente valor después de :mzn:`x` en el tipo enumerado :mzn:`X`. Esta es una función parcial, si :mzn:`x` es el último valor en el tipo enumerado :mzn:`X` luego la función devuelve :math:`\bot` haciendo que la expresión booleana que contiene la expresión evalúe :mzn:`false`.
670 - :mzn:`enum_prev(X, x)`: devuelve el valor anterior antes de :mzn:`x` en el tipo enumerado :mzn:`X`. Del mismo modo :mzn:`enum_prev` es una función parcial.
671 - :mzn:`to_enum(X, i)`: asigna una expresión entera :mzn:`i` a un valor de tipo enumerado en tipo :mzn:`X` o evalúa a :math:`\bot` si :mzn:`i` es menor o igual que 0 o mayor que la cantidad de elementos en :mzn:`X`.
672
673Tenga en cuenta también que una serie de funciones estándar son aplicables a los tipos enumerados:
674
675 - :mzn:`card(X)`: devuelve la cardinalidad de un tipo enumerado :mzn:`X`.
676 - :mzn:`min(X)`: devuelve el elemento mínimo de un tipo enumerado :mzn:`X`.
677 - :mzn:`max(X)`: devuelve el elemento máximo de un tipo enumerado :mzn:`X`.
678
679.. _sec-complex:
680
681Restricciones complejas
682-----------------------
683
684.. index::
685 single: constraint; complex
686
687Las restricciones son el núcleo del modelo MiniZinc. Hemos visto expresiones relacionales simples, pero las restricciones pueden ser considerablemente más poderosas que esto. Se permite que una restricción sea cualquier expresión booleana. Imagine un problema de programación en el que tenemos dos tareas que no se pueden superponer en el tiempo. Si :mzn:`s1` y :mzn:`s2` son los tiempos de inicio correspondientes y :mzn:`d1` y :mzn:`d2` son las duraciones correspondientes, podemos expresar esto como:
688
689.. code-block:: minizinc
690
691 constraint s1 + d1 <= s2 \/ s2 + d2 <= s1;
692
693Que asegura que las tareas no se superponen.
694
695.. defblock:: Booleanos
696
697 .. index::
698 single: Boolean
699 single: expression; Boolean
700 single: true
701 single: false
702 single: operator; Boolean
703 single: bool2int
704
705 Las expresiones booleanas en MiniZinc se pueden escribir usando una sintaxis matemática estándar. Los literales booleanos son :mzn:`true`, :mzn:`false` y los operadores booleanos son conjunción, es decir, (``/\``), disyunción, es decir o (``\/``), only-if (:mzn:`<-`), implica (:mzn:`->`), if-and-only-if (:mzn:`<->`) y negación (:mzn:`not`). Los booleanos se pueden forzar automáticamente a enteros, pero para que esta coerción sea explícita la función incorporada :mzn:`bool2int` se puede usar: devuelve 1 si su argumento es verdadero y 0 en caso contrario.
706
707.. literalinclude:: examples/jobshop_es.mzn
708 :language: minizinc
709 :name: ex-jobshop
710 :caption: Modelo para problemas de planificación de tiendas de trabajo (:download:`jobshop_es.mzn <examples/jobshop_es.mzn>`).
711
712.. literalinclude:: examples/jdata_es.dzn
713 :language: minizinc
714 :name: ex-jdata
715 :caption: Datos para problemas de planificación de tiendas de trabajo (:download:`jdata_es.dzn <examples/jdata_es.dzn>`).
716
717El modelo de planificación de tiendas de trabajo dado en :numref:`ex-jobshop` brinda un ejemplo realista del uso de esta capacidad de modelado disyuntivo. En la planificación de tiendas de trabajo tenemos un conjunto de trabajos, cada uno de los cuales consiste en una secuencia de tareas en máquinas separadas: por lo que la tarea :mzn:`[i, j]` es la tarea en el trabajo :math:`i^{th}` realizado en la máquina :math:`j^{th}`. Cada secuencia de tareas debe completarse en orden, y no hay dos tareas en la misma máquina que puedan superponerse en el tiempo. Incluso pequeñas instancias de este problema pueden ser bastante desafiantes para encontrar soluciones óptimas.
718
719El comando
720
721.. code-block:: bash
722
723 $ mzn-gecode --all-solutions jobshop_es.mzn jdata_es.dzn
724
725Resuelve un pequeño problema de planificación de tiendas de trabajo e ilustra el comportamiento de \texttt{all-solutions} para problemas de optimización. Aquí el solucionador genera cada una de las mejores soluciones tal como la encuentra, en lugar de todas las soluciones óptimas posibles. El resultado de este comando es:
726
727.. code-block:: none
728
729 Fin = 39
730 5 9 13 22 30
731 6 13 18 25 36
732 0 4 8 12 16
733 4 8 12 16 22
734 9 16 25 27 38
735 ----------
736 Fin = 37
737 4 8 12 17 20
738 5 13 18 26 34
739 0 4 8 12 16
740 8 12 17 20 26
741 9 16 25 27 36
742 ----------
743 Fin = 34
744 0 1 5 10 13
745 6 10 15 23 31
746 2 6 11 19 27
747 1 5 10 13 19
748 9 16 22 24 33
749 ----------
750 Fin = 30
751 5 9 13 18 21
752 6 13 18 25 27
753 1 5 9 13 17
754 0 1 2 3 9
755 9 16 25 27 29
756 ----------
757 ==========
758
759Lo que indica que finalmente se encuentra una solución óptima con el tiempo de finalización 30, y resultó ser óptima. Podemos generar todas las *soluciones óptimas* agregando una restricción que :mzn:`end = 30` y cambiando el elemento de resolver a :mzn:`solve satisfy`.
760
761Posteriormente se debe de ejecutar el siguiente comando:
762
763.. code-block:: bash
764
765 $ mzn-gecode --all-solutions jobshop_es.mzn jobshop_es.dzn
766
767Para este problema, hay 3,444,375 soluciones óptimas.
768
769.. literalinclude:: examples/stable-marriage_es.mzn
770 :language: minizinc
771 :name: ex-stable-marriage
772 :caption: Modelo para el problema del matrimonio estable (:download:`stable-marriage_es.mzn <examples/stable-marriage_es.mzn>`).
773
774.. literalinclude:: examples/stable-marriage_es.dzn
775 :language: minizinc
776 :name: ex-sm-data
777 :caption: Datos de ejemplo para el problema de matrimonio estable (:download:`stable-marriage_es.dzn <examples/stable-marriage_es.dzn>`).
778
779Otra poderosa característica de modelado en MiniZinc es que las variables de decisión se pueden usar para :index:`array access <array; access>`. Como por ejemplo, considere el (anticuado) *problema de matrimonio estable*.
780Tenemos que :mzn:`n` (hétero) mujeres y :mzn:`n` (straight) men. Cada hombre tiene una lista clasificada de mujeres y viceversa. Queremos encontrar un esposo/esposa para cada mujer/hombre para que todos los matrimonios sean *estables* en el sentido de que:
781
782- Siempre que :mzn:`m` prefiera a otra mujer :mzn:`o` a su esposa :mzn:`w`, :mzn:`o` prefiere a su marido a :mzn:`m`.
783- Siempre que :mzn:`w` prefiera a otro hombre :mzn:`o` a su marido :mzn:`m`, :mzn:`o` prefiere a su mujer a :mzn:`w`.
784
785Esto se puede modelar elegantemente en MiniZinc.
786El modelo y los datos de muestra se muestran en :numref:`ex-stable-marriage` y :numref:`ex-sm-data`.
787
788Los tres primeros elementos en el modelo declaran el número de hombres/mujeres y el conjunto de hombres y mujeres. Aquí presentamos el uso de *tipos enumerados anónimos*. Ambos :mzn:`Men` y :mzn:`Women` son conjuntos de tamaño :mzn:`n`, pero no deseamos mezclarlos, así que utilizamos un tipo enumerado anónimo. Esto permite que MiniZinc detecte errores de modelado cuando usamos :mzn:`Men` para :mzn:`Women` o viceversa.
789
790Las matrices :mzn:`rankWomen` y :mzn:`rankMen`, respectivamente, dan el ranking de las mujeres de los hombres y el ranking de las mujeres de los hombres. Por lo tanto, la entrada :mzn:`rankWomen[w, m]` da la clasificación por mujer :mzn:`w` de hombre :mzn:`m`. Cuanto menor sea el número en el ranking, más se prefiere el hombre o la mujer.
791
792Hay dos matrices de variables de decisión :mzn:`wife` y :mzn:`husband`. Estos, respectivamente, contienen la esposa de cada hombre y el esposo de cada mujer.
793
794Las dos primeras restricciones:
795
796.. literalinclude:: examples/stable-marriage_es.mzn
797 :language: minizinc
798 :lines: 13-14
799
800Asegúrese de que la asignación de esposos y esposas sea consistente: :mzn:`w` es la esposa de :mzn:`m` implica que :mzn:`m` es el esposo de :mzn:`w` y viceversa. Observe cómo en :mzn:`husband[wife[m]]` la expresión de índice :mzn:`wife[m]` es una variable de decisión, no un parámetro.
801
802Las siguientes dos restricciones son una codificación directa de la condición de estabilidad:
803
804.. literalinclude:: examples/stable-marriage_es.mzn
805 :language: minizinc
806 :lines: 16-22
807
808
809Este modelado natural del problema del matrimonio estable es posible gracias a la capacidad de usar variables de decisión como índices de matriz y construir restricciones utilizando las conectivas booleanas estándar. El lector puede preguntarse en esta etapa, qué sucede si la variable de índice de matriz toma un valor que está fuera del conjunto de índices de la matriz. MiniZinc lo trata como una falla: un acceso de matriz :mzn:`a[e]` implícitamente agrega la restricción: :mzn:`e in index_set(a)` al contexto booleano circundante más cercano donde :mzn:`index_set(a)` da el conjunto de índices de :mzn:`a`.
810
811.. defblock:: Tipos enumerados anónimos
812
813 .. index::
814 single: type; enumerated; anonymous
815
816 Un *tipo enumerado anónimo* tiene la forma :mzndef:`anon_enum(<n>)` donde :mzndef:`<n>` es una expresión entera fija que define el tamaño del tipo enumerado.
817
818 Un tipo enumerado anónimo es como cualquier otro tipo enumerado excepto que no tenemos nombres para sus elementos. Cuando se imprimen, reciben nombres únicos basados en el nombre del tipo enumerado.
819
820Por lo tanto, por ejemplo, considere las declaraciones de variables
821
822.. code-block:: minizinc
823
824 array[1..2] of int: a= [2,3];
825 var 0..2: x;
826 var 2..3: y;
827
828La restricción :mzn:`a[x] = y` tendrá éxito con :math:`x=1 \wedge y=2` y :math:`x=2 \wedge y=3`. Y la restricción :mzn:`not a[x] = y` tendrá éxito con :math:`x=0 \wedge y=2`, :math:`x=0 \wedge y=3`, :math:`x=1 \wedge y=3` y :math:`x=2 \wedge y=2`.
829
830En el caso de los accesos de matriz no válida por un parámetro, la semántica formal de MiniZinc trata esto como un fallo para garantizar que el tratamiento de los parámetros y las variables de decisión sea coherente, pero se emite una advertencia ya que casi siempre es un error.
831
832.. literalinclude:: examples/magic-series_es.mzn
833 :language: minizinc
834 :name: ex-magic-series
835 :caption: Modelo que soluciona el problema de la serie mágica (:download:`magic-series_es.mzn <examples/magic-series_es.mzn>`).
836
837.. index::
838 single: bool2int
839 single: constraint; higher order
840
841La función de coerción :mzn:`bool2int` se puede invocar con cualquier expresión booleana. Esto permite que el modelador MiniZinc use las llamadas *restricciones de orden superior*. Como un simple ejemplo, considere el problema de *magic series*.
842Encuentre una lista de números :math:`s= [s_0,\ldots,s_{n-1}]` tal que :math:`s_i` es el número de ocurrencias de :math:`i` en :math:`s`. Un ejemplo es :math:`s = [1,2,1,0]`. Un modelo MiniZinc para este problema se muestra en :numref:`ex-magic-series`. El uso de :mzn:`bool2int` nos permite resumir el número de veces que se cumple la restricción :mzn:`s[j]=i`.
843
844Ejecutando el comando
845
846.. code-block:: bash
847
848 $ mzn-gecode --all-solutions magic-series_es.mzn -D "n=4;"
849
850Conduce a la salida
851
852.. code-block:: none
853
854 s = [1, 2, 1, 0];
855 ----------
856 s = [2, 0, 2, 0];
857 ----------
858 ==========
859
860Indicando exactamente dos soluciones al problema.
861
862Tenga en cuenta que MiniZinc forzará automáticamente booleanos a enteros y enteros a flotantes cuando sea necesario. Podríamos reemplazar el elemento de restricción en :numref:`ex-magic-series` con:
863
864.. code-block:: minizinc
865
866 constraint forall(i in 0..n-1) (
867 s[i] = (sum(j in 0..n-1)(s[j]=i)));
868
869Y obtenga resultados idénticos, ya que la expresión booleana :mzn:`s[j] = i` se forzará automáticamente a un entero, efectivamente mediante el sistema MiniZinc que agrega automáticamente la falta :mzn:`bool2int`.
870
871.. defblock:: Coercion
872
873 .. index::
874 single: coercion; automatic
875 single: coercion; bool2int
876 single: coercion; int2float
877
878 En MiniZinc uno puede *forzar* un valor booleano a un valor entero usando la función :mzn:`bool2int`. De manera similar, se puede forzar un valor entero a un valor flotante usando :mzn:`int2float`. La instanciación del valor coaccionado es el mismo que el argumento. Por ejemplo, :mzn:`par bool` se fuerza a :mzn:`par int`, mientras que :mzn:`var bool` se fuerza a :mzn:`var int` MiniZinc coacciona automáticamente expresiones booleanas a expresiones enteras y expresiones enteras a expresiones flotantes, insertando :mzn:`bool2int` y :mzn:`int2float` en el modelo de forma apropiada. Tenga en cuenta que también forzará booleanos a flotantes utilizando dos pasos.
879
880
881
882Establecer Restricciones
883------------------------
884
885.. index::
886 single: constraint; set
887
888Otra poderosa característica de modelado de MiniZinc es que permite que los conjuntos que contienen enteros sean variables de decisión. Esto significa que cuando se evalúa el modelo, el solucionador encontrará qué elementos están en el conjunto. Como un ejemplo simple, considere el problema *0/1 de la mochila*.
889
890Esta es una forma restringida del problema de la mochila en la que podemos elegir colocar el artículo en la mochila o no. Cada artículo tiene un peso y una ganancia y queremos encontrar qué opción de artículos conduce a la ganancia máxima sujeta a que la mochila no esté demasiado llena.
891
892Es natural modelar esto en MiniZinc con una única variable de decisión: :mzn:`var set of ITEM: knapsack` donde :mzn:`ITEM` es el conjunto de elementos posibles. Si los arreglos :mzn:`weight[i]` y :mzn:`profit[i]` respectivamente dan el peso y el beneficio del ítem :mzn:`i`, y el peso máximo que puede llevar la mochila viene dado por :mzn:`capacity` luego se da un modelo naural en :numref:`ex-knapsack-binary`.
893
894.. literalinclude:: examples/knapsack_es.mzn
895 :language: minizinc
896 :name: ex-knapsack-binary
897 :caption: Modelo para el problema de mochila 0/1 (:download:`knapsack_es.mzn <examples/knapsack_es.mzn>`).
898
899Observe que la palabra clave :mzn:`var` viene antes de la declaración :mzn:`set` que indica que el conjunto en sí es la variable de decisión.
900
901Esto contrasta con una matriz en la que la palabra clave :mzn:`var` califica los elementos en la matriz en lugar de la matriz en sí, ya que la estructura básica de la matriz es fija, es decir, su conjunto de índices.
902
903.. literalinclude:: examples/social-golfers_es.mzn
904 :language: minizinc
905 :name: ex-social-golfers
906 :caption: Modelo para los problemas de los golfistas sociales (:download:`social-golfers_es.mzn <examples/social-golfers_es.mzn>`).
907
908Como un ejemplo más complejo de restricción de conjuntos, considere el problema de los golfistas sociales que se muestra en :numref:`ex-social-golfers`. El objetivo es programar un torneo de golf sobre :mzn:`weeks` usando :mzn:`groups` :math:`\times` :mzn:`size` de golfistas. Cada semana tenemos que programar :mzn:`groups` diferentes grupos cada uno de tamaño :mzn:`size`. No hay dos pares de golfistas que jueguen en dos grupos
909
910Las variables en el modelo son conjuntos de golfistas :mzn:`Sched[i,j]` para el grupo de la semana :math:`i^{th}` del grupo :mzn:`j^{th}`.
911
912
913Las restricciones que se muestran en las líneas 11-32 primero imponen un orden en el primer conjunto de cada semana para eliminar la simetría en el intercambio de semanas. A continuación, imponen un orden en los conjuntos en cada semana y hacen que cada conjunto tenga una cardinalidad de :mzn:`size`. Luego se aseguran de que cada semana sea una partición del conjunto de golfistas que utilizan la restricción global :mzn:`partition_set`. Finalmente, la última restricción asegura que no hay dos jugadores que jueguen en dos grupos juntos (ya que la cardinalidad de la intersección de dos grupos es como máximo 1).
914
915.. index::
916 single: symmetry; breaking
917
918También hay restricciones de inicialización de ruptura de simetría que se muestran en las líneas 34-46: la primera semana se fija para tener todos los jugadores en orden; la segunda semana se compone de los primeros jugadores de cada uno de los primeros grupos en la primera semana; finalmente, el modelo obliga a los primeros jugadores :mzn:`size` a aparecer en su número de grupo correspondiente durante las semanas restantes.
919
920Ejecutando el comando:
921
922.. code-block:: bash
923
924 $ mzn-gecode social-golfers_es.mzn social-golfers_es.dzn
925
926Donde el archivo de datos define un problema con 4 semanas, con 4 grupos de tamaño 3 y que conduce a la salida:
927
928.. code-block:: none
929
930 1..3 4..6 7..9 10..12
931 { 1, 4, 7 } { 2, 5, 10 } { 3, 9, 11 } { 6, 8, 12 }
932 { 1, 5, 8 } { 2, 6, 11 } { 3, 7, 12 } { 4, 9, 10 }
933 { 1, 6, 9 } { 2, 4, 12 } { 3, 8, 10 } { 5, 7, 11 }
934 ----------
935
936Observe cómo conjuntos que son rangos pueden salir en formato de rango.
937
938
939Poniendolo Todo Junto
940---------------------
941
942Terminamos esta sección con un ejemplo complejo que ilustra la mayoría de las características presentadas en este capítulo, incluidos los tipos enumerados, las restricciones complejas, las restricciones globales y los resultados complejos.
943
944.. literalinclude:: examples/wedding_es.mzn
945 :language: minizinc
946 :name: ex-wedding
947 :caption: Planificación de asientos de bodas utilizando tipos enumerados (:download:`wedding_es.mzn <examples/wedding_es.mzn>`).
948
949El modelo de :numref:`ex-wedding` organiza los asientos en la mesa de la boda.
950La mesa tiene 12 asientos numerados en orden alrededor de la mesa, 6 en cada lado. Los hombres deben sentarse en asientos con números impares y las mujeres en parejas. Ed no puede sentarse al final de la mesa debido a una fobia, y la novia y el novio deben sentarse uno al lado del otro. El objetivo es maximizar la distancia entre los odios conocidos. La distancia entre asientos es la diferencia en el número de asiento si está en el mismo lado, de lo contrario es la distancia al asiento opuesto + 1.
951
952Tenga en cuenta que en la declaración de salida consideramos cada asiento :mzn:`s` y la búsqueda de un invitado :mzn:`g` que está asignado a ese asiento. Hacemos uso de la función incorporada :mzn:`fix` que verifica si una variable de decisión es fija y devuelve su valor fijo, y de lo contrario lo cancela. Esto es siempre seguro de usar en declaraciones de salida, ya que para el momento en que se ejecuta la declaración de salida, todas las variables de decisión deben ser corregidas.
953
954
955Ejecutando:
956
957.. code-block:: bash
958
959 $ mzn-gecode wedding_es.mzn
960
961Resultados en la salida:
962
963.. code-block:: none
964
965 ted bride groom rona ed carol ron alice bob bridesmaid bestman clara
966 ----------
967 ==========
968
969
970La colocación de la tabla resultante se ilustra en :numref:`fig-wedding` donde las líneas indican odios. La distancia total es 22.
971
972.. _fig-wedding:
973
974.. figure:: figures/wedding_es.*
975
976 Disposición de los asientos en la mesa de la boda
977
978
979.. \pjs{Move the fix definition elsewhere!}
980
981.. defblock:: Fijar (Fix)
982
983 .. index::
984 single: fix
985 single: fixed
986
987 En los elementos de salida, la función incorporada :mzn:`fix` comprueba que el valor de una variable de decisión sea fijo y coacciona la instanciación de la variable de decisión al parámetro.
988
989.. % oil-blending
990.. %arrays floats sum forall
991.. %more complex datafile
992..
993.. %suduko
994.. %2-D array
995.. %complex transformation from data file
996..
997.. %jobshop
998.. %disjunction,
999..
1000.. %talk about other complex constraints--IC example?
1001..
1002.. %magic sequence
1003.. %reification
1004..
1005.. %warehouse placement
1006.. %reification more complex example
1007..
1008.. %0/1 knapsack
1009.. %set constraint
1010..
1011.. %social golfers
1012.. %more complex set constraint
1013..
1014.. %finish with larger example from Mark