this repo has no description
at develop 25 kB view raw
1.. _sec-modelling: 2 3MiniZinc基本模型 4=========================== 5 6.. highlight:: minizinc 7 :linenothreshold: 5 8 9在此节中,我们利用两个简单的例子来介绍一个MiniZinc模型的基本结构。 10 11第一个实例 12----------------- 13 14.. _fig-aust: 15 16.. figure:: figures/aust.* 17 18 澳大利亚各州 19 20作为我们的第一个例子,假设我们要去给 :numref:`fig-aust` 中的澳大利亚地图涂色。 21它包含了七个不同的州和地区,而每一块都要被涂一个颜色来保证相邻的区域有不同的颜色。 22 23 24.. literalinclude:: examples/aust.mzn 25 :language: minizinc 26 :caption: 一个用来给澳大利亚的州和地区涂色的MiniZinc模型 :download:`aust.mzn <examples/aust.mzn>` 27 :name: ex-aust 28 29我们可以很容易的用MiniZinc给此问题建模。此模型在 :numref:`ex-aust` 中给出。 30 31模型中的第一行是注释。注释开始于 ``%`` 来表明此行剩下的部分是注释。 32MiniZinc同时也含有C语言风格的由 ``/*`` 开始和 ``*/`` 结束的块注释。 33 34模型中的下一部分声明了模型中的变量。 35此行 36 37:: 38 39 int: nc = 3; 40 41定义了一个问题的 :index:`参数` 来代表可用的颜色个数。 42在很多编程语言中,参数和变量是类似的。它们必须被声明并且指定一个类型 :index:`type` 43在此例中,类型是 :mzn:`int` 44通过 :index:`赋值`,它们被设了值。 45MiniZinc允许变量声明时被赋值(就像上面那一行)或者单独给出一个赋值语句。 46因此下面的表示跟上面的只一行表示是相等的 47 48:: 49 50 int: nc; 51 nc = 3; 52 53和很多编程语言中的变量不一样的是,这里的参数只可以被赋 *唯一* 的值。 54如果一个参数出现在了多于一个的赋值中,就会出现错误。 55 56基本的 :index:`参数类型 <single: type; parameter>` 包括 :index:`整型 <integer>` (:mzn:`int`), 57浮点型(:mzn:`float`), :index:`布尔型 <Boolean>` (:mzn:`bool`) 以及 :index:`字符串型 <string>` (:mzn:`string`)。 58同时也支持数组和集合。 59 60.. index:: 61 see: decision variable; variable 62 63MiniZinc模型同时也可能包含另一种类型的变量 *决策变量*:index:`决策变量 <variable>` 是数学的或者逻辑的变量。 64和一般的编程语言中的参数和变量不同,建模者不需要给决策变量一个值。 65而是在开始时,一个决策变量的值是不知道的。只有当MiniZinc模型被执行的时候, 66求解系统才来决定决策变量是否可以被赋值从而满足模型中的约束。若满足,则被赋值。 67 68在我们的模型例子中,我们给每一个区域一个 *决策变量* ``wa``, ``nt``, ``sa``, ``q``, ``nsw``, ``v````t`` 69它们代表了会被用来填充区域的(未知)颜色。 70 71.. index:: 72 single: domain 73 74对于每一个决策变量,我们需要给出变量可能的取值集合。这个被称为变量的 *定义域* 。 75定义域部分可以在 :index:`变量声明 <variable; declaration>` 的时候同时给出, 76这时决策变量的 :index:`类型` 就会从定义域中的数值的类型推断出。 77 78MiniZinc中的决策变量的类型可以为布尔型,整型,浮点型或者集合。 79同时也可以是元素为决策变量的数组。 80在我们的MiniZinc模型例子中,我们使用整型去给不用的颜色建模。通过使用 :mzn:`var` 声明, 81我们的每一个决策变量 82被声明为定义域为一个整数类型的范围表示 :mzn:`1..nc` 83来表明集合 :math:`\{ 1, 2, \dots, nc \}` 84所有数值的类型为整型,所以模型中的所有的变量是整型决策变量。 85 86.. defblock:: 标识符 87 88 用来命名参数和变量的标识符是一列由大小写字母,数字以及 89 下划线 ``_`` 字符组成的字符串。它们必须开始于一个字母字符。因此 ``myName_2`` 是一个有效的标识符。 90 MiniZinc(和Zinc)的 *关键字* 不允许被用为标识符名字。它们在 :ref:`spec-identifiers` 中被列出。 91 所有的MiniZinc *操作符* 都不能被用做标识符名字。它们在 :ref:`spec-Operators` 中被列出。 92 93MiniZinc仔细地区别了以下两种模型变量:参数和决策变量。利用决策变量创建的表达式类型比利用参数可以创建的表达式类型更局限。 94但是,在任何可以用决策变量的地方,同类型的参数变量也可以被应用。 95 96.. defblock:: 整型变量声明 97 98 一个 :index:`整型参数变量 <variable; declaration; integer>` 可以被声明为以下两种方式: 99 100 .. code-block:: minizincdef 101 102 int : <变量名> 103 <l> .. <u> : <变量名> 104 105 :mzndef:`<l>`:mzndef:`<u>` 是固定的整型表达式。 106 107 一个整型决策变量被声明为以下两种方式: 108 109 .. code-block:: minizincdef 110 111 var int : <变量名> 112 var <l>..<u> : <变量名> 113 114 :mzndef:`<l>`:mzndef:`<u>` 是固定的整型表达式。 115 116参数和决策变量形式上的区别在于对变量的 *实例化* 117变量的实例化和类型的结合被叫为 :index:`类型-实例化` 118既然你已经开始使用MiniZinc,毫无疑问的你会看到很多 *类型-实例化* 的错误例子。 119 120.. index:: 121 single: constraint 122 123模型的下一部分是 *约束* 124它们详细说明了决策变量想要组成一个模型的有效解必须要满足的布尔型表达式。 125在这个例子中我们有一些决策变量之间的不等式。它们规定如果两个区域是相邻的,则它们必须有不同的颜色。 126 127.. defblock:: 关系操作符 128 129 MiniZinc提供了以下关系操作符 :index:`关系操作符 <operator; relational>` 130 131 .. index:: 132 single: = 133 single: == 134 single: != 135 single: < 136 single: <= 137 single: > 138 single: >= 139 140 相等 (``=`` or ``==``), 不等 141 (``!=``), 142 小于 (``<``), 143 大于 (``>``), 144 小于等于 (``<=``), and 145 和大于等于 (``>=``). 146 147模型中的下一行: 148 149:: 150 151 solve satisfy; 152 153表明了它是什么类型的问题。 154在这个例子中,它是一个 :index:`满足` 问题: 155我们希望给决策变量找到一个值使得约束被满足,但具体是哪一个值却没有所谓。 156 157.. index:: 158 single: output 159 160模型的最后一个部分是 *输出* 语句。它告诉MiniZinc当模型被运行并且找到一个解 :index:`解` 的时候, 161要输出什么。 162 163.. defblock:: 输出和字符串 164 165 .. index:: 166 single: output 167 single: string 168 single: show 169 170 一个输出语句跟着一 *串* 字符。 171 它们通常或者是写在双引号之间的字符串常量 :index:`字符串常量 <string; literal>` 并且 172 对特殊字符用类似C语言的标记法,或者是 :mzn:`show(e)` 格式的表达式, 173 其中 :mzn:`e` 是MiniZinc表达式。例子中的 ``\n`` 代表换行符, ``\t`` 代表制表符。 174 175 数字的 :mzn:`show` 有各种不同方式的表示: 176 :mzn:`show_int(n,X)` 177 在至少$|n|$个字符里输出整型 ``X`` 的值,若 :math:`n > 0` 则右对齐,否则则左对齐; 178 :mzn:`show_float(n,d,X)` 在至少 :math:`|n|` 个字符里输出 179 浮点型 ``X`` 的值,若 :math:`n > 0` 则右对齐,否则则左对齐,并且小数点后有 :math:`d` 个字符。 180 181 :index:`字符串常量 <string; literal>` 必须在同一行中。长的字符串常量可以利用字符串连接符 ``++`` 182 来分成几行。例如,字符串常量 183 184 :: 185 186 "Invalid datafile: Amount of flour is non-negative" 187 188 和字符串常量表达式 189 190 :: 191 192 "Invalid datafile: " ++ 193 "Amount of flour is non-negative" 194 195 是相等的。 196 197 MiniZinc支持内插字符串 :index:`内插字符串 <string; literal; interpolated>` 198 表达式可以直接插入字符串常量中。 :mzn:`"\(e)"` 形式的子字符串 199 会被替代为 :mzn:`show(e)` 。例如,:mzn:`"t=\(t)\n"` 产生 200:mzn:`"t=" ++ show(t) ++ "\n"` 一样的字符串。 201 202 一个模型可以包含多个输出语句。在这种情况下,所有输出会根据它们在模型中出现的顺序连接。 203 204我们可以通过点击MiniZinc IDE中的 *Run* 按钮,或者输入 205 206.. code-block:: bash 207 208 $ minizinc --solver Gecode aust.mzn 209 210来评估我们的模型。 211其中 :download:`aust.mzn <examples/aust.mzn>` 是包含我们的MiniZinc模型的文件名字。 212我们必须使用文件扩展名 ``.mzn`` 来表明一个MiniZinc模型。 213带有 ``--solver Gecode`` 选项的命令 ``minizinc`` 使用Gecode有限域求解器去评估我们的模型。如果你使用的是MiniZinc二进制发布,这个求解器实际上是预设的,所以你也可以运行 ``minizinc aust.mzn`` 214 215当我们运行上面的命令后,我们得到如下的结果: 216 217.. code-block:: none 218 219 wa=2 nt=3 sa=1 220 q=2 nsw=3 v=2 221 t=1 222 ---------- 223 224 225.. index:: 226 single: solution; separator ---------- 227 22810个破折号 ``----------`` 这行是自动被MiniZinc输出的,用来表明一个解已经被找到。 229 230算术优化实例 231---------------------------------- 232 233我们的第二个例子来自于要为了本地的校园游乐会烤一些蛋糕的需求。 234我们知道如何制作两种蛋糕。 \footnote{警告: 请不要在家里使用这些配方制作} 235一个香蕉蛋糕的制作需要250克自发酵的面粉,2个捣碎的香蕉,75克糖和100克黄油。 236一个巧克力蛋糕的制作需要200克自发酵的面粉,75克可可粉,150克糖和150克黄油。 237一个巧克力蛋糕可以卖\$4.50,一个香蕉蛋糕可以卖\$4.00。我们一共有4千克的自发酵面粉, 2386个香蕉,2千克的糖,500克的黄油和500克的可可粉。 239问题是对每一种类型的蛋糕,我们需要烤多少给游乐会来得到最大的利润。 240一个可能的MiniZinc模型在 :numref:`ex-cakes` 中给出。 241 242.. literalinclude:: examples/cakes.mzn 243 :language: minizinc 244 :caption: 决定为了校园游乐会要烤多少香蕉和巧克力蛋糕的模型。 (:download:`cakes.mzn <examples/cakes.mzn>`) 245 :name: ex-cakes 246 247.. index:: 248 single: expression; arithmetic 249 250第一个新特征是 *arithmetic expressions* 的使用。 251 252.. defblock:: 整数算术操作符 253 254 .. index:: 255 single: operator; integer 256 single: + 257 single: - 258 single: div 259 single: * 260 single: mod 261 262 MiniZinc提供了标准的整数算术操作符。 263 加 (``+``), 264 减 (``-``), 265 乘 (``*``), 266 整数除 (:mzn:`div`) 267 268 整数模 (:mzn:`mod`). 269 同时也提供了一元操作符 ``+````-`` 270 271 整数模被定义为输出和被除数 :math:`a` 一样正负的 :math:`a` :mzn:`mod` :math:`b` 值。整数除被定义为使得 272 :math:`a = b ` ``*`` :math:`(a` :mzn:`div` :math:`b) + (a` :mzn:`mod` :math:`b)` 值。 273 274 MiniZinc 提供了标准的整数函数用来取绝对值 (:mzn:`abs`) 和幂函数 (:mzn:`pow`). 275 例如 :mzn:`abs(-4)`:mzn:`pow(2,5)` 分别求得数值 276 ``4````32`` 277 278 算术常量的语法是相当标准的。整数常量可以是十进制,十六进制或者八进制。例如 ``0``, ``5``, 279 ``123``, ``0x1b7``, ``0o777`` 280 281.. index:: 282 single: optimization 283 single: objective 284 single: maximize 285 single: minimize 286 287例子中的第二个新特征是优化。这行 288 289:: 290 291 solve maximize 400 * b + 450 * c; 292 293指出我们想找一个可以使solve语句中的表达式(我们叫做 *目标* )最大化的解。 294这个目标可以为任何类型的算术表达式。我们可以把关键字 :mzn:`maximize` 295换为 :mzn:`minimize` 来表明一个最小化问题。 296 297当我们运行上面这个模型时,我们得到以下的结果: 298 299.. code-block:: none 300 301 no. of banana cakes = 2 302 no. of chocolate cakes = 2 303 ---------- 304 ========== 305 306.. index:: 307 single: solution; end `==========` 308 309一旦系统证明了一个解是最优解,这一行 ``==========`` 在最优化问题中会自动被输出。 310 311.. index:: 312 single: data file 313 314数据文件和谓词 315------------------------ 316 317此模型的一个缺点是如果下一次我们希望解决一个相似的问题,即我们需要为学校烤蛋糕(这是经常发生的), 318我们需要改变模型中的约束来表明食品间拥有的原料数量。如果我们想重新利用此模型,我们最好使得每个原料的数量作为 319模型的参数,然后在模型的最上层设置它们的值。 320 321更好的办法是在一个单独的 *数据文件* 中设置这些参数的值。 322MiniZinc(就像很多其他的建模语言一样)允许使用数据文件来设置在原始模型中声明的 323参数的值。 324通过运行不同的数据文件,使得同样的模型可以很容易地和不同的数据一起使用。 325 326数据文件的文件扩展名必须是 ``.dzn`` ,来表明它是一个MiniZinc数据文件。 327一个模型可以被任何多个数据文件运行(但是每个变量/参数在每个文件中只能被赋一个值) 328 329.. literalinclude:: examples/cakes2.mzn 330 :language: minizinc 331 :caption: 独立于数据的用来决定为了校园游乐会要烤多少香蕉和巧克力蛋糕的模型。(:download:`cakes2.mzn <examples/cakes2.mzn>`) 332 :name: ex-cakes2 333 334我们的新模型在 :numref:`ex-cakes2` 中给出。 335我们可以用下面的命令来运行 336 337.. code-block: bash 338 339 $ minizinc cakes2.mzn pantry.dzn 340 341数据文件 :download:`pantry.dzn <examples/pantry.dzn>`:numref:`fig-pantry1` 中给出。我们得到和 :download:`cakes.mzn <examples/cakes.mzn>` 同样的结果。 342运行下面的命令 343 344.. code-block:: bash 345 346 $ minizinc cakes2.mzn pantry2.dzn 347 348利用另外一个 :numref:`fig-pantry2` 中定义的数据集,我们得到如下结果 349 350.. code-block:: none 351 352 no. of banana cakes = 3 353 no. of chocolate cakes = 8 354 ---------- 355 ========== 356 357如果我们从 :download:`cakes.mzn <examples/cakes.mzn>` 中去掉输出语句,MiniZinc会使用默认的输出。 358这种情况下得到的输出是 359 360.. code-block:: none 361 362 b = 3; 363 c = 8; 364 ---------- 365 ========== 366 367.. defblock:: 默认输出 368 369 一个没有输出语句的MiniZinc模型会给每一个决策变量以及它的值一个输出行,除非决策变量已经在声明的时候被赋了一个表达式。 370 注意观察此输出是如何呈现一个正确的数据文件格式的。 371 372.. literalinclude:: examples/pantry.dzn 373 :language: minizinc 374 :caption: :download:`cakes2.mzn <examples/cakes2.mzn>` 的数据文件例子 (:download:`pantry.dzn <examples/pantry.dzn>`) 375 :name: fig-pantry1 376 377.. literalinclude:: examples/pantry2.dzn 378 :language: minizinc 379 :caption: :download:`cakes2.mzn <examples/cakes2.mzn>` 的数据文件例子 (:download:`pantry2.dzn <examples/pantry2.dzn>`) 380 :name: fig-pantry2 381 382通过使用 :index:`命令行标示 <data file;command line>` 383``-D`` *string* 384小的数据文件可以被直接输入而不是必须要创建一个 ``.dzn`` 文件, 385其中 *string* 是数据文件里面的内容。 386 387.. code-block:: bash 388 389 $ minizinc cakes2.mzn -D \ 390 "flour=4000;banana=6;sugar=2000;butter=500;cocoa=500;" 391 392会给出和 393 394.. code-block:: bash 395 396 $ minizinc cakes2.mzn pantry.dzn 397 398一模一样的结果。 399 400数据文件只能包含给模型中的决策变量和参数赋值的语句。 401 402.. index:: 403 single: assert 404 405防御性编程建议我们应该检查数据文件中的数值是否合理。 406在我们的例子中,检查所有原料的份量是否是非负的并且若不正确则产生一个运行错误,这是明智的。 407MiniZinc提供了一个内置的布尔型操作符 *断言* 用来检查参数值。格式是 :mzn:`assert(B,S)` 408布尔型表达式 ``B`` 被检测。若它是假的,运行中断。此时字符串表达式 ``S`` 作为错误信息被输出。 409如果我们想当面粉的份量是负值的时候去检测出并且产生合适的错误信息,我们可以直接加入下面的一行 410 411:: 412 413 constraint assert(flour >= 0,"Amount of flour is non-negative"); 414 415到我们的模型中。注意 *断言* 表达式是一个布尔型表达式,所以它被看做是一种类型的约束。我们可以加入类似的行来检测其他原料的份量是否是非负值。 416 417实数求解 418------------------- 419 420MiniZinc also supports "real number" constraint solving using 421floating point variables and constraints. Consider a problem of taking out a short loan 422for one year to be repaid in 4 quarterly instalments. 423A model for this is shown in :numref:`ex-loan`. It uses a simple interest 424calculation to calculate the balance after each quarter. 425 426通过使用浮点数求解,MiniZinc也支持“实数”约束求解。考虑一个要在4季度分期偿还的一年短期贷款问题。 427此问题的一个模型在 :numref:`ex-loan` 中给出。它使用了一个简单的计算每季度结束后所欠款的利息计算方式。 428 429.. literalinclude:: examples/loan.mzn 430 :language: minizinc 431 :caption: 确定一年借款每季度还款关系的模型(:download:`loan.mzn <examples/loan.mzn>`) 432 :name: ex-loan 433 434注意我们声明了一个浮点型变量 ``f`` ,它和整型变量很类似。只是这里我们 435使用关键字 :mzn:`float` 而不是 :mzn:`int` 436 437我们可以用同样的模型来回答一系列不同的问题。第一个问题是:如果我以利息 4384\%借款\$1000并且每季度还款\$260,我最终还欠款多少?这个问题在数据文件 :download:`loan1.dzn <examples/loan1.dzn>` 中被编码。 439 440由于我们希望用实数求解,我们需要使用一个可以支持这种问题类型的求解器。Gecode(Minizinc捆绑二进制发布预设的求解器)支持浮点型变量,一个混合整数线性求解器可能更加适合这种类型的问题。 441MiniZinc发布包含了这样的一个求解器。我们可以通过从求解器IDE菜单( *Run* 按钮下面的三角形)选择 ``COIN-BC`` 来使用, 或者在命令行中运行命令 ``minizinc --solver cbc`` : 442 443.. code-block:: bash 444 445 $ minizinc --solver cbc loan.mzn loan1.dzn 446 447输出是 448 449.. code-block:: none 450 451 Borrowing 1000.00 at 4.0% interest, and repaying 260.00 452 per quarter for 1 year leaves 65.78 owing 453 ---------- 454 455第二个问题是如果我希望用4\%的利息来借款\$1000并且在最后的时候一点都不欠款,我需要在每季度还款多少? 456这个问题在数据文件 :download:`loan2.dzn <examples/loan2.dzn>` 中被编码。 457运行命令 458 459.. code-block:: bash 460 461 $ minizinc --solver cbc loan.mzn loan2.dzn 462 463后的输出是 464 465.. code-block:: none 466 467 Borrowing 1000.00 at 4.0% interest, and repaying 275.49 468 per quarter for 1 year leaves 0.00 owing 469 ---------- 470 471第三个问题是如果我可以每个季度返还\$250, 我可以用4\%的利息来借款多少并且在最后的时候一点都不欠款? 472这个问题在数据文件 :download:`loan3.dzn <examples/loan3.dzn>` 中被编码。 473运行命令 474 475.. code-block:: bash 476 477 $ minizinc --solver cbc loan.mzn loan3.dzn 478 479后的输出是 480 481.. code-block:: none 482 483 Borrowing 907.47 at 4.0% interest, and repaying 250.00 484 per quarter for 1 year leaves 0.00 owing 485 ---------- 486 487.. literalinclude:: examples/loan1.dzn 488 :language: minizinc 489 :caption: :download:`loan.mzn <examples/loan.mzn>` 的数据文件例子(:download:`loan1.dzn <examples/loan1.dzn>`) 490 491.. literalinclude:: examples/loan2.dzn 492 :language: minizinc 493 :caption: :download:`loan.mzn <examples/loan.mzn>` 的数据文件例子(:download:`loan2.dzn <examples/loan2.dzn>`) 494 495.. literalinclude:: examples/loan3.dzn 496 :language: minizinc 497 :caption: :download:`loan.mzn <examples/loan.mzn>` 的数据文件例子(:download:`loan3.dzn <examples/loan3.dzn>`) 498 499 500.. defblock:: 浮点算术操作符 501 502 .. index: 503 single: operator; float 504 single: + 505 single: - 506 single: * 507 single: / 508 single: abs 509 single: sqrt 510 single: ln 511 single: log2 512 single: log10 513 single: exp 514 single: sin 515 single: cos 516 single: tan 517 single: asin 518 single: acos 519 single: atan 520 single: sinh 521 single: cosh 522 single: tanh 523 single: asinh 524 single: acosh 525 single: atanh 526 single: pow 527 528 MiniZinc提供了标准的浮点算术操作符: 529 加 (``+``), 530 减 (``-``), 531 乘 (``*``) 532 和浮点除 (``/``)。 533 同时也提供了一元操作符 ``+`` 和 ``-`` 。 534 535 MiniZinc不会自动地强制转换整数为浮点数。内建函数 :mzn:`int2float` 被用来达到此目的。注意强制转换的一个后果是表达式 :mzn:`a / b` 总是被认为是一个浮点除。 如果你需要一个整数除,请确定使用 :mzn:`div` 操作符。 536 537 MiniZinc同时也包含浮点型函数来计算: 538 绝对值 (``abs``), 539 平方根 (``sqrt``), 540 自然对数 (``ln``), 541 底数为2的对数 (``log2``), 542 底数为10的对数 (``log10``), 543 $e$的幂 (``exp``), 544 正弦 (``sin``), 545 余弦 (``cos``), 546 正切 (``tan``), 547 反正弦 (``asin``), 548 反余弦 (``acos``), 549 反正切 (``atan``), 550 双曲正弦 (``sinh``), 551 双曲余弦 (``cosh``), 552 双曲正切 (``tanh``), 553 双曲反正弦 (``asinh``), 554 双曲反余弦 (``acosh``), 555 双曲反正切 (``atanh``), 556 和唯一的二元函数次方 (``pow``),其余的都是一元函数。 557 558 算术常量的语法是相当标准的。浮点数常量的例子有 ``1.05``, ``1.3e-5`` 和 ``1.3E+5`` 。 559 560.. \pjs{Should do multiple solutions????} 561 562模型的基本结构 563-------------------------- 564 565我们现在可以去总结MiniZinc模型的基本结构了。 566它由多个项组成,每一个在其最后都有一个分号 ``;`` 567项可以按照任何顺序出现。例如,标识符在被使用之前不需要被声明。 568 569有八种类型的项 :index:`items <item>` 570 571- :index:`引用项 <item; include>` 允许另外一个文件的内容被插入模型中。 572 它们有以下形式: 573 574 .. code-block:: minizincdef 575 576 include <文件名>; 577 578 其中 :mzndef:`<文件名>` 是一个字符串常量。 579 它们使得大的模型可以被分为小的子模型以及包含库文件中定义的约束。 580 我们会在 :numref:`ex-smm` 中看到一个例子。 581 582- :index:`变量声明 <item; variable declaration>` 声明新的变量。 583 这种变量是全局变量,可以在模型中的任何地方被提到。 584 变量有两种。在模型中被赋一个固定值的参数变量以及只有在模型被求解的时候才会 585 被赋值的决策变量。 586 我们称参数是 :index:`固定的` ,决策变量是 :index:`不固定的` 587 变量可以选择性地被赋一个值来作为声明的一部分。形式是: 588 589 .. index: 590 single: expression; type-inst 591 single: par 592 single: var 593 594 .. code-block:: minizincdef 595 596 <类型-实例化 表达式>: <变量> [ = ] <表达式>; 597 598 :mzndef:`<类型-实例化 表达式>` 599 给了变量的类型和实例化。 这些是MiniZinc比较复杂的其中一面。 600 用 :mzn:`par` 来实例化声明 601 参数,用 :mzn:`var` 来实例化声明决策变量。 602 如果没有明确的实例化声明,则变量是一个参数。类型可以为基类型,一个 :index:`整数或者浮点数范围 <range>`,或者一个数组或集合。 603 基类型有 604 :mzn:`float`, 605 :mzn:`int`, 606 :mzn:`string`, 607 :mzn:`bool`, 608 :mzn:`ann` 609 。其中只有 610 :mzn:`float`, :mzn:`int` and :mzn:`bool` 可以被决策变量使用。 611 基类型 :mzn:`ann` 是一个 :index:`注解` -- 612 我们会在 :ref:`sec-search` 中讨论注解。 613 :index:`整数范围表达式 <range; integer>` 可以被用来代替类型 :mzn:`int`. 614 类似的, :index:`浮点数范围表达式 <range; float>` 615 可以被用来代替类型 :mzn:`float` 。 616 这些通常被用来定义一个整型决策变量的定义域,但也可以被用来限制一个整型参数的范围。 617 变量声明的另外一个用处是定义 :index:`枚举类型`, ---我们会在 :ref:`sec-enum` 中讨论。 618 619- :index:`赋值项 <item; assignment>` 给一个变量赋一个值。它们有以下形式: 620 621 .. code-block:: minizincdef 622 623 <变量> = <表达式>; 624 625 数值可以被赋给决策变量。在这种情况下,赋值相当于加入 :mzndef:`constraint <变量> = <表达式>` ; 626 627- :index:`约束项 <item; constraint>` 是模型的核心。它们有以下形式: 628 629 .. code-block:: minizincdef 630 631 constraint <布尔型表达式>; 632 633 我们已经看到了使用算术比较的简单约束以及内建函数 :mzn:`assert` 操作符。 在下一节我们会看到更加复杂的约束例子。 634 635- :index:`求解项 <item; solve>` 详细说明了到底要找哪种类型的解。 636 正如我们看到的,它们有以下三种形式: 637 638 .. code-block:: minizincdef 639 640 solve satisfy; 641 solve maximize <算术表达式>; 642 solve minimize <算术表达式>; 643 644 一个模型必须有且只有一个求解项。 645 646- :index:`输出项 <item; output>` 用来恰当的呈现模型运行后的结果。 647 它们有下面的形式: 648 649 .. code-block:: minizincdef 650 651 output [ <字符串表达式>, ..., <字符串表达式> ]; 652 653 如果没有输出项,MiniZinc会默认输出所有没有被以赋值项的形式赋值的决策变量值。 654 655- :index:`枚举类型声明 <item; enum>`. 656 我们会在 :ref:`sec-arrayset`:ref:`sec-enum` 中讨论。 657 658- :index:`谓词函数和测试项 <item; predicate>` 被用来定义新的约束,函数和布尔测试。我们会在 :ref:`sec-predicates` 中讨论。 659 660 661- :index:`注解项 <item; annotation>` 用来定义一个新的注解。我们会在 :ref:`sec-search` 中讨论。