this repo has no description
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???)