this repo has no description
at develop 49 kB view raw
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