this repo has no description
at develop 26 kB view raw
1.. _sec-search: 2 3Search 4====== 5 6.. index:: 7 single: annotation 8 9By default in MiniZinc there is no declaration of how 10we want to search for solutions. This leaves the search 11completely up to the underlying solver. 12But sometimes, particularly for combinatorial integer problems, 13we may want to specify how the search should be undertaken. 14This requires us to communicate to the solver a :index:`search` strategy. 15Note that the search strategy is *not* really part 16of the model. 17Indeed it is not required that each solver implements all 18possible search strategies. 19MiniZinc uses a consistent approach to communicating extra information 20to the constraint solver using *annotations*. 21 22Finite Domain Search 23-------------------- 24 25.. index:: 26 single: search; finite domain 27 28Search in a finite domain solver involves examining the 29remaining possible values of variables and choosing to 30constrain some variables further. 31The search then adds a new constraint that 32restricts the remaining values 33of the variable 34(in effect guessing where the solution might lie), 35and then applies propagation to determine what other values 36are still possible in solutions. 37In order to guarantee completeness, the search leaves another 38choice which is the negation of the new constraint. 39The search ends either when 40the finite domain solver detects that all constraints are satisfied, 41and hence a solution has been found, or that the constraints are 42unsatisfiable. 43When unsatisfiability is detected 44the search must proceed down a different set of 45choices. Typically finite domain solvers use :index:`depth first search <search; depth first>` 46where they undo the last choice made and then try to make a new choice. 47 48.. literalinclude:: examples/nqueens.mzn 49 :language: minizinc 50 :name: ex-queens 51 :caption: Model for n-queens (:download:`nqueens.mzn <examples/nqueens.mzn>`). 52 53A simple example of a finite domain problem is the :math:`n` queens 54problem which requires that we 55place :math:`n` queens on an :math:`n \times n` chessboard so that none can 56attack another. 57The variable :mzn:`q[i]` records in which row the queen in column :mzn:`i` 58is placed. The :mzn:`alldifferent` constraints ensure 59that no two queens are on the same row, or diagonal. 60A typical (partial) search tree 61for :mzn:`n = 9` is illustrated in :numref:`fig-9q-a`. 62We first set :mzn:`q[1] = 1`, this removes values from the domains of other 63variables, so that e.g. :mzn:`q[2]` cannot take the values 1 or 2. 64We then set :mzn:`q[2] = 3`, this further removes values from the domains 65of other variables. We set :mzn:`q[3] = 5` (its earliest possible value). 66The state of the chess board after these three decisions is shown in 67:numref:`fig-9q-b` where the queens indicate the position 68of the queens fixed already and 69the stars indicate positions where we cannot place a queen 70since it would be able to take an already placed queen. 71 72.. _fig-9q-a: 73 74.. figure:: figures/tree-4.* 75 76 Partial search trees for 9 queens 77 78.. _fig-9q-b: 79 80.. figure:: figures/chess9x9-3.* 81 82 The state after the addition of ``q[1] = 1``, ``q[2] = 4``, ``q[3] = 5`` 83 84.. _fig-9q-c: 85 86.. figure:: figures/chess9x9-4.* 87 88 The initial propagation on adding further ``q[6] = 4`` 89 90A search strategy determines which choices to make. The decisions we have 91made so far follow the simple strategy of picking the 92first variable which is not fixed yet, and try to set it to its least 93possible value. Following this strategy the next decision would be 94:mzn:`q[4] = 7`. 95An alternate strategy for variable selection is to choose the variable whose 96current set of possible values (*domain*) is smallest. 97Under this so called *first-fail* 98variable selection strategy the next decision would be 99:mzn:`q[6] = 4`. 100If we make this decision, then initially propagation removes the additional 101values shown in :numref:`fig-9q-c`. But this leaves only one value for 102:mzn:`q[8]`, :mzn:`q[8] = 7`, so this is forced, but then this leaves only one 103possible value for :mzn:`q[7]` and :mzn:`q[9]`, that is 2. Hence a constraint must be 104violated. We have detected unsatisfiability, and the solver must backtrack 105undoing the last decision :mzn:`q[6] = 4` and adding its negation :mzn:`q[6] != 4` 106(leading us to state (c) in the tree in :numref:`fig-9q-a`) 107which forces :mzn:`q[6] = 8`. This removes some values from the domain 108and then we again reinvoke the search strategy to decide what to do. 109 110Many finite domain searches are defined in this way: 111choose a variable to constrain further, and then choose how to 112constrain it further. 113 114Search Annotations 115------------------ 116 117.. index:: 118 single: search; annotation 119 single: solve 120 121Search annotations in MiniZinc 122specify how to search in order to find a solution to the 123problem. The annotation is attached to the solve item, after the keyword 124:mzn:`solve`. 125The search annotation 126 127.. literalinclude:: examples/nqueens.mzn 128 :language: minizinc 129 :lines: 11-12 130 131appears on the solve item. Annotations are attached to parts of 132the model using the connector :mzn:`::`. 133This search annotation means that we should search by selecting from 134the array of integer variables :mzn:`q`, the variable with the smallest 135current domain (this is the :mzn:`first_fail` rule), and try setting 136it to its smallest possible value 137(:mzn:`indomain_min` 138value selection). 139 140 141 142.. % \begin{tabular}{|c|c|c|c|c|c|c|c|c|} 143.. % \hline 144.. % Q & . & . & . & . & . & . & . & . \\ \hline 145.. % . & . & . & & & . & & & \\ \hline 146.. % . & Q & . & . & . & . & . & . & . \\ \hline 147.. % . & . & . & . & & & & & \\ \hline 148.. % . & . & Q & . & . & . & . & . & . \\ \hline 149.. % . & . & . & . & . & . & & & \\ \hline 150.. % . & . & . & & . & . & . & & \\ \hline 151.. % . & . & . & & & . & . & . & \\ \hline 152.. % . & . & . & & & & . & . & . \\ \hline 153.. % \end{tabular} 154 155.. defblock:: Basic search annotations 156 157 .. index:: 158 single: int_search 159 single: bool_search 160 single: set_search 161 162 There are three basic search annotations corresponding to different 163 basic variable types: 164 165 - :mzndef:`int_search( <variables>, <varchoice>, <constrainchoice> )` 166 where :mzndef:`<variables>` is a one dimensional array of :mzn:`var int`, 167 :mzndef:`<varchoice>` is a variable choice annotation discussed below, 168 :mzndef:`<constrainchoice>` is a choice of how to constrain a variable, discussed 169 below. 170 - :mzndef:`bool_search( <variables>, <varchoice>, <constrainchoice> )` 171 where :mzndef:`<variables>` is a one dimensional array of :mzn:`var bool` 172 and the rest are as above. 173 - :mzndef:`set_search( <variables>, <varchoice>, <constrainchoice> )` 174 where :mzndef:`<variables>` is a one dimensional array of :mzn:`var set of int` 175 and the rest are as above. 176 - :mzndef:`float_search( <variables>, <precision>, <varchoice>, <constrainchoice> )` 177 where :mzndef:`<variables>` is a one dimensional array of :mzn:`var float`, 178 :mzndef:`<precision>` is a fixed float specifying the :math:`\epsilon` below which 179 two float values are considered equal, 180 and the rest are as above. 181 182 .. index:: 183 single: search; variable choice 184 single: input_order 185 single: first_fail 186 single: smallest 187 single: dom_w_deg 188 189 Example variable choice annotations are: 190 191 - :mzn:`input_order`: choose in order from the array 192 - :mzn:`first_fail`: choose the variable with the smallest domain size, and 193 - :mzn:`smallest`: choose the variable with the smallest value in its domain. 194 - :mzn:`dom_w_deg`: choose the variable with the smallest value of domain 195 size divided by weighted degree, which is the number of times it has been 196 in a constraint that caused failure earlier in the search. 197 198 .. index:: 199 single: search; constrain choice 200 single: indomain_min 201 single: indomain_median 202 single: indomain_random 203 single: indomain_split 204 205 Example ways to constrain a variable are: 206 207 - :mzn:`indomain_min`: assign the variable its smallest domain value, 208 - :mzn:`indomain_median`: assign the variable its median domain value (or the smaller of the two middle values in case of an even number of elements in the domain), 209 - :mzn:`indomain_random`: assign the variable a random value from its domain, and 210 - :mzn:`indomain_split` bisect the variables domain excluding the upper half. 211 212 For backwards compatibility with older version of MiniZinc, the search 213 annotations can be called with an additional argument that represents the 214 search strategy to use. The only such strategy that is currently supported is 215 :mzn:`complete`, meaning an exhaustive exploration of the search space. With 216 the additional argument, an annotation might then look like this: 217 :mzn:`::int_search(x, input_order, indomain_min, complete)`. 218 219 For a complete list of variable and constraint choice annotations 220 see the FlatZinc specification in the MiniZinc reference 221 documentation. 222 223We can construct more complex search strategies using search 224constructor annotations. There is only one such annotation at present: 225 226.. index:: 227 single: search; sequential 228 single: seq_search 229 230.. code-block:: minizinc 231 232 seq_search([ <search-ann>, ..., <search-ann> ]) 233 234The sequential search constructor first undertakes the search given 235by the first annotation in its list, when all variables in this annotation 236are fixed it undertakes the second search annotation, etc. until all 237search annotations are complete. 238 239Consider the jobshop scheduling model shown in :numref:`ex-jobshop3`. 240We could replace the solve item with 241 242.. code-block:: minizinc 243 244 solve :: seq_search([ 245 int_search(s, smallest, indomain_min), 246 int_search([end], input_order, indomain_min)]) 247 minimize end 248 249which tries to set start times :mzn:`s` by choosing the job that can start 250earliest and setting it to that time. When all start times are complete 251the end time :mzn:`end` may not be fixed. Hence we set it to 252its minimal possible value. 253 254Annotations 255----------- 256 257.. index:: 258 single: annotation 259 260Annotations are a first class object in MiniZinc. We 261can declare new annotations in a model, and declare and assign 262to annotation variables. 263 264.. defblock:: Annotations 265 266 .. index:: 267 single: ann 268 269 Annotations have a type :mzn:`ann`. 270 You can declare an annotation 271 :index:`parameter` (with optional assignment): 272 273 .. code-block:: minizincdef 274 275 ann : <ident>; 276 ann : <ident> = <ann-expr> ; 277 278 and assign to an annotation variable just as any other parameter. 279 280 :index:`Expressions <expression>`, :index:`variable declarations <variable; declaration>`, 281 and :mzn:`solve` items can all 282 be annotated using the :mzn:`::` operator. 283 284 We can declare a new :index:`annotation` 285 using the :mzn:`annotation` :index:`item <item; annotation>`: 286 287 .. code-block:: minizincdef 288 289 annotation <annotation-name> ( <arg-def>, ..., <arg-def> ) ; 290 291.. literalinclude:: examples/nqueens-ann.mzn 292 :language: minizinc 293 :name: ex-queens-ann 294 :caption: Annotated model for n-queens (:download:`nqueens-ann.mzn <examples/nqueens-ann.mzn>`). 295 296The program in :numref:`ex-queens-ann` illustrates the use of annotation 297declarations, annotations and annotation variables. 298We declare a new annotation :mzn:`bitdomain` which is meant to tell 299the solver that variables domains should be represented via bit arrays 300of size :mzn:`nwords`. 301The annotation is attached to the declarations of the variables :mzn:`q`. 302Each of the :mzn:`alldifferent` constraints is annotated with 303the built in annotation :mzn:`domain` 304which instructs the solver to use 305the domain propagating version of :mzn:`alldifferent` if it has one. 306An annotation variable :mzn:`search_ann` is declared and used 307to define the search strategy. We can give the value to the search 308strategy in a separate data file. 309 310Example search annotations might be the following (where 311we imagine each line is in a separate data file) 312 313.. code-block:: minizinc 314 315 search_ann = int_search(q, input_order, indomain_min); 316 search_ann = int_search(q, input_order, indomain_median); 317 search_ann = int_search(q, first_fail, indomain_min); 318 search_ann = int_search(q, first_fail, indomain_median); 319 search_ann = int_search(q, input_order, indomain_random); 320 321The first just tries the queens in order setting them to the 322minimum value, the second tries the queens variables in order, but sets 323them to their median value, the third tries the queen variable with smallest 324domain and sets it to the minimum value, and the final strategy 325tries the queens variable with smallest domain setting it to its median 326value. 327 328Different search strategies can make a significant difference in 329how easy it is to find solutions. 330A small comparison of the number of failures made to find the first solution 331of the n-queens problems using the 5 different search strategies 332is shown in the table below (where --- means more than 100,000 failures). 333Clearly the right search strategy can make a significant difference, and variables selection is more important than value selection, except that for this 334problem random value selection is very powerful. 335 336.. cssclass:: table-nonfluid table-bordered 337 338+-----+-----------+--------------+--------+-----------+--------------+ 339| n | input-min | input-median | ff-min | ff-median | input-random | 340+=====+===========+==============+========+===========+==============+ 341| 10 | 22 | 2 | 5 | 0 | 6 | 342+-----+-----------+--------------+--------+-----------+--------------+ 343| 15 | 191 | 4 | 4 | 12 | 39 | 344+-----+-----------+--------------+--------+-----------+--------------+ 345| 20 | 20511 | 32 | 27 | 16 | 2 | 346+-----+-----------+--------------+--------+-----------+--------------+ 347| 25 | 2212 | 345 | 51 | 25 | 2 | 348+-----+-----------+--------------+--------+-----------+--------------+ 349| 30 | --- | 137 | 22 | 66 | 9 | 350+-----+-----------+--------------+--------+-----------+--------------+ 351| 35 | --- | 1722 | 52 | 12 | 12 | 352+-----+-----------+--------------+--------+-----------+--------------+ 353| 40 | --- | --- | 16 | 44 | 2 | 354+-----+-----------+--------------+--------+-----------+--------------+ 355| 45 | --- | --- | 41 | 18 | 6 | 356+-----+-----------+--------------+--------+-----------+--------------+ 357 358.. number of nodes ?? 359 Different search strategies can make a significant difference in 360 how easy it is to find solutions. 361 A small comparison of the number of nodes made to find the first solution 362 of the n-queens problems using the 5 different search strategies 363 is shown in the table below (where --- means more than 100,000 nodes). 364 Clearly the right search strategy can make a significant difference, and 365 variables selection is more important than value selection, except that for this 366 problem random value selection is very powerful. 367 368 +-----+-----------+--------------+--------+-----------+--------------+ 369 | n | input-min | input-median | ff-min | ff-median | input-random | 370 +=====+===========+==============+========+===========+==============+ 371 | 10 | 49 | 11 | 17 | 7 | 17 | 372 +-----+-----------+--------------+--------+-----------+--------------+ 373 | 15 | 391 | 20 | 16 | 34 | 89 | 374 +-----+-----------+--------------+--------+-----------+--------------+ 375 | 20 | 41033 | 80 | 65 | 46 | 19 | 376 +-----+-----------+--------------+--------+-----------+--------------+ 377 | 25 | 4439 | 709 | 120 | 66 | 23 | 378 +-----+-----------+--------------+--------+-----------+--------------+ 379 | 30 | --- | 297 | 67 | 152 | 40 | 380 +-----+-----------+--------------+--------+-----------+--------------+ 381 | 35 | --- | 3470 | 132 | 50 | 50 | 382 +-----+-----------+--------------+--------+-----------+--------------+ 383 | 40 | --- | --- | 64 | 116 | 34 | 384 +-----+-----------+--------------+--------+-----------+--------------+ 385 | 45 | --- | --- | 120 | 71 | 47 | 386 +-----+-----------+--------------+--------+-----------+--------------+ 387 | 50 | --- | --- | 395 | 42 | 90 | 388 +-----+-----------+--------------+--------+-----------+--------------+ 389 390 391 392Restart 393------- 394 395.. index:: 396 single: search; restart 397 398Any kind of depth first search for solving optimization problems 399suffers from the problem that wrong decisions made at the top of 400the search tree can take an exponential amount of search to undo. 401One common way to ameliorate this problem is to restart the search 402from the top thus having a chance to make different decisions. 403 404MiniZinc includes annotations to control restart behaviour. These 405annotations, like other search annotations, are attached to the 406solve item of the model. 407 408 409.. defblock:: Restart search annotations 410 411 .. index:: 412 single: restart_luby 413 single: restart_geometric 414 single: restart_linear 415 single: restart_constant 416 single: restart_none 417 418 The different restart annotations control how frequently a restart occurs. 419 Restarts occur when a limit in nodes is reached, where search returns to the 420 top of the search tree and begins again. The possibilities are 421 422 - :mzndef:`restart_constant(<scale>)` where :mzndef:`<scale>` is an integer 423 defining after how many nodes to restart. 424 - :mzndef:`restart_linear(<scale>)` where :mzndef:`<scale>` is an integer 425 defining the initial number of nodes before the first restart. The second 426 restart gets twice as many nodes, the third gets three times, etc. 427 - :mzndef:`restart_geometric(<base>,<scale>)` where :mzndef:`<base>` is a 428 float and :mzndef:`<scale>` is an integer. The :mzn:`k` th restart has a 429 node limit of :mzn:`<scale> * <base>^k`. 430 - :mzndef:`restart_luby(<scale>)` where :mzndef:`<scale>` is an integer. 431 The :mzn:`k` th restart gets :mzn:`<scale>*L[k]` where :mzn`L[k]` is the 432 :mzn:`k` th number in the Luby sequence. The Luby sequence looks like 433 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8 ..., that is it repeats two copies of the 434 sequence ending in :mzn:`2^i` before adding the number :mzn:`2^{i+1}`. 435 - :mzndef:`restart_none` don't apply any restart 436 (useful for setting a :mzn:`ann` parameter that controls restart). 437 438 439 Solvers behaviour where two or more restart annotations are used is 440 undefined. 441 442Restart search is much more robust in finding solutions, since it can avoid 443getting stuck in a non-productive area of the search. Note that restart 444search does not make much sense if the underlying search strategy does 445not do something different the next time it starts at the top. 446For example the search annotation 447 448.. code-block:: minizinc 449 450 solve :: int_search(q, input_order, indomain_min); 451 :: restart_linear(1000) 452 satisfy 453 454does not very much sense since the underlying search is deterministic and 455each restart will just redo the same search as the previous search. 456Some solvers record the parts of the search tree that have already been 457searched and avoid them. This will mean deterministic restarts will simply 458effectively continue the search from the previous position. This gives 459no benefit to restarts, whose aim is to change decisions high in the search 460tree. 461 462The simplest way to ensure that something is different in each restart 463is to use some randomization, either in variable choice or value choice. 464Alternatively some variable selection strategies make use of information 465gathered from earlier search and hence will give different behaviour, for 466example :mzn:`dom_w_deg`. 467 468To see the effectiveness of restart lets examine the n-queens problem again 469with the underlying search strategy 470 471.. code-block:: minizinc 472 473 int_search(q, first_fail, indomain_random); 474 475with one of four restart strategies 476 477.. code-block:: minizinc 478 479 r1 = restart_constant(100); 480 r2 = restart_linear(100); 481 r3 = restart_geometric(1.5,100); 482 r4 = restart_luby(100); 483 r5 = restart_none; 484 485.. cssclass:: table-nonfluid table-bordered 486 487+-----+-----------+--------------+-----------+-----------+------+ 488| n | constant | linear | geometric | luby | none | 489+=====+===========+==============+===========+===========+======+ 490| 10 | 35 | 35 | 35 | 35 | 14 | 491+-----+-----------+--------------+-----------+-----------+------+ 492| 15 | 36 | 36 | 36 | 36 | 22 | 493+-----+-----------+--------------+-----------+-----------+------+ 494| 20 | 15 | 15 | 15 | 16 | | 495+-----+-----------+--------------+-----------+-----------+------+ 496| 25 | 2212 | 345 | 51 | 25 | | 497+-----+-----------+--------------+-----------+-----------+------+ 498| 30 | --- | 137 | 22 | 66 | | 499+-----+-----------+--------------+-----------+-----------+------+ 500| 35 | --- | 1722 | 52 | 12 | | 501+-----+-----------+--------------+-----------+-----------+------+ 502| 40 | 148 | 148 | 194 | 148 | 15 | 503+-----+-----------+--------------+-----------+-----------+------+ 504| 100 | 183 | 183 | 183 | 183 | 103 | 505+-----+-----------+--------------+-----------+-----------+------+ 506| 500 | 1480 | 1480 | 1480 | 1480 | 1434 | 507+-----+-----------+--------------+-----------+-----------+------+ 508| 1000| 994 | 994 | 994 | 994 | 994 | 509+-----+-----------+--------------+-----------+-----------+------+ 510 511THE CURRENT EXPERIMENT IS USELESS! 512 513.. _sec_warm_starts: 514 515Warm Starts 516----------- 517 518In many cases when solving an optimization or satisfaction 519problem we may have solved a 520previous version of the problem which is very similar. In this case it 521can be advantageous to use the previous solution found when searching for 522solution to the new problem. This is currently supported by some MIP backends. 523 524The warm start annotations are attached to the solve item, just like other 525search annotations. 526 527 528.. defblock:: Warm start search annotations 529 530 .. index:: 531 single: warm_start 532 533 The different restart annotations control how frequently a restart occurs. 534 Restarts occur when a limit in nodes is reached, where search returns to the 535 top of the search tree and begins again. The possibilities are 536 537 - :mzndef:`warm_start(<vars>,<vals>)` where :mzndef:`<vars>` is a one 538 dimensional array of integer variables, and :mzndef:`<vals>` is a 539 one dimensional array of integer of the same length giving the warm start values 540 for each integer variable in :mzn:`<vars>`. 541 - :mzndef:`warm_start(<vars>,<vals>)` where :mzndef:`<vars>` is a one 542 dimensional array of float variables, and :mzndef:`<vals>` is a 543 one dimensional array of floats of the same length giving the warm start values 544 for each float variable in :mzn:`<vars>`. 545 - :mzndef:`warm_start(<vars>,<vals>)` where :mzndef:`<vars>` is a one 546 dimensional array of Boolean variables, and :mzndef:`<vals>` is a 547 one dimensional array of Booleans of the same length giving the warm start values 548 for each Boolean variable in :mzn:`<vars>`. 549 - :mzndef:`warm_start(<vars>,<vals>)` where :mzndef:`<vars>` is a one 550 dimensional array of set variables, and :mzndef:`<vals>` is a 551 one dimensional array of sets of integers of the same length giving the warm start values 552 for each set variable in :mzn:`<vars>`. 553 554 555The warm start annotation can be used by the solver as part of value selection. For example, if the selected 556variable :mzn:`v[i]` has in its current domain the warm start value :mzn:`w[i]` then this is 557the value selected for the variable. If not the solver uses the existing value selection rule 558applicable to that variable. 559The order of warm_starts, relative to other search annotations, can be 560important (especially for CP), so they all might need to be put into a ``seq_search`` as below: 561 562.. code-block:: minizinc 563 564 array[1..3] of var 0..10: x; 565 array[1..3] of var 0.0..10.5: xf; 566 var bool: b; 567 array[1..3] of var set of 5..9: xs; 568 constraint b+sum(x)==1; 569 constraint b+sum(xf)==2.4; 570 constraint 5==sum( [ card(xs[i]) | i in index_set(xs) ] ); 571 solve 572 :: warm_start_array( [ %%% Can be on the upper level 573 warm_start( x, [<>,8,4] ), %%% Use <> for missing values 574 warm_start( xf, array1d(-5..-3, [5.6,<>,4.7] ) ), 575 warm_start( xs, array1d( -3..-2, [ 6..8, 5..7 ] ) ) 576 ] ) 577 :: seq_search( [ 578 warm_start_array( [ %%% Now included in seq_search to keep order 579 warm_start( x, [<>,5,2] ), %%% Repeated warm_starts allowed but not specified 580 warm_start( xf, array1d(-5..-3, [5.6,<>,4.7] ) ), 581 warm_start( xs, array1d( -3..-2, [ 6..8, 5..7 ] ) ) 582 ] ), 583 warm_start( [b], [true] ), 584 int_search(x, first_fail, indomain_min) 585 ] ) 586 minimize x[1] + b + xf[2] + card( xs[1] intersect xs[3] ); 587 588If you'd like to provide a most complete warmstart information, please provide values for all 589variables which are output when there is no output item or when compiled with ``--output-mode dzn``. 590.. Still, this excludes auxiliary variables introduced by ``let`` expressions. To capture them, you can customize 591the output item, or try the FlatZinc level, see below. 592 593.. 594 Using Warm Starts At The FlatZinc Level 595 +++++++++++++++++++++++++++++++++++++++ 596 597 You can insert warm start information in the FlatZinc in the same way for all non-fixed variables. 598 Just make sure the fzn interpreter outputs their values by annotating them as ``output_var(_array)`` 599 and capture the fzn output by, e.g., piping to ``solns2out --output-raw <file_raw.dzn>``. 600 You can also insert high-level output into FZN warm start. When compiling the initial model, add 601 empty warm start annotations for all important variables - they will be kept in FZN. In the next solve, 602 fill the values. To fix the order of annotations, put them into a ``warm_start_array``. 603 604 AUTOMATE, e.g., adding a solution in dzn format as a warm start during parsing? 605 606 A MORE REALISTIC EXAMPLE OF THEIR USE (jobshop???)