Initial import from LNS paper
This commit is contained in:
parent
e29db0e8fc
commit
c48148ffaf
@ -26,6 +26,77 @@
|
||||
programming},
|
||||
}
|
||||
|
||||
@inproceedings{michel-2005-comet,
|
||||
author = {Laurent Michel and Pascal Van Hentenryck},
|
||||
editor = {Peter van Beek},
|
||||
title = {The Comet Programming Language and System},
|
||||
booktitle = {Principles and Practice of Constraint Programming - {CP}
|
||||
2005, 11th International Conference, {CP} 2005, Sitges, Spain,
|
||||
October 1-5, 2005, Proceedings},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
volume = 3709,
|
||||
pages = {881--881},
|
||||
publisher = {Springer},
|
||||
year = 2005,
|
||||
url = {https://doi.org/10.1007/11564751_119},
|
||||
doi = {10.1007/11564751_119},
|
||||
timestamp = {Tue, 14 May 2019 10:00:45 +0200},
|
||||
biburl = {https://dblp.org/rec/conf/cp/MichelH05a.bib},
|
||||
bibsource = {dblp computer science bibliography, https://dblp.org}
|
||||
}
|
||||
|
||||
@article{pisinger-2007-heuristic,
|
||||
author = {David Pisinger and Stefan Ropke},
|
||||
title = {A general heuristic for vehicle routing problems},
|
||||
journal = {Comput. Oper. Res.},
|
||||
volume = 34,
|
||||
number = 8,
|
||||
pages = {2403--2435},
|
||||
year = 2007,
|
||||
url = {https://doi.org/10.1016/j.cor.2005.09.012},
|
||||
doi = {10.1016/j.cor.2005.09.012},
|
||||
timestamp = {Tue, 18 Feb 2020 13:56:22 +0100},
|
||||
biburl = {https://dblp.org/rec/journals/cor/PisingerR07.bib},
|
||||
bibsource = {dblp computer science bibliography, https://dblp.org}
|
||||
}
|
||||
|
||||
@inproceedings{rendl-2015-minisearch,
|
||||
author = {Andrea Rendl and Tias Guns and Peter J. Stuckey and Guido
|
||||
Tack},
|
||||
editor = {Gilles Pesant},
|
||||
title = {MiniSearch: {A} Solver-Independent Meta-Search Language for
|
||||
MiniZinc},
|
||||
booktitle = {Principles and Practice of Constraint Programming - 21st
|
||||
International Conference, {CP} 2015, Cork, Ireland, August 31
|
||||
- September 4, 2015, Proceedings},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
volume = 9255,
|
||||
pages = {376--392},
|
||||
publisher = {Springer},
|
||||
year = 2015,
|
||||
url = {https://doi.org/10.1007/978-3-319-23219-5_27},
|
||||
doi = {10.1007/978-3-319-23219-5_27},
|
||||
timestamp = {Sun, 25 Oct 2020 23:13:15 +0100},
|
||||
biburl = {https://dblp.org/rec/conf/cp/RendlGST15.bib},
|
||||
bibsource = {dblp computer science bibliography, https://dblp.org}
|
||||
}
|
||||
|
||||
@article{ropke-2006-adaptive,
|
||||
author = {Stefan Ropke and David Pisinger},
|
||||
title = {An Adaptive Large Neighborhood Search Heuristic for the
|
||||
Pickup and Delivery Problem with Time Windows},
|
||||
journal = {Transp. Sci.},
|
||||
volume = 40,
|
||||
number = 4,
|
||||
pages = {455--472},
|
||||
year = 2006,
|
||||
url = {https://doi.org/10.1287/trsc.1050.0135},
|
||||
doi = {10.1287/trsc.1050.0135},
|
||||
timestamp = {Tue, 08 Sep 2020 13:28:27 +0200},
|
||||
biburl = {https://dblp.org/rec/journals/transci/RopkeP06.bib},
|
||||
bibsource = {dblp computer science bibliography, https://dblp.org}
|
||||
}
|
||||
|
||||
@book{silvano-1990-knapsack,
|
||||
author = {Martello, Silvano and Toth, Paolo},
|
||||
title = {Knapsack Problems: Algorithms and Computer Implementations},
|
||||
@ -34,3 +105,23 @@
|
||||
publisher = {John Wiley \& Sons, Inc.},
|
||||
address = {USA}
|
||||
}
|
||||
|
||||
@inproceedings{stuckey-2013-functions,
|
||||
author = {Peter J. Stuckey and Guido Tack},
|
||||
editor = {Carla P. Gomes and Meinolf Sellmann},
|
||||
title = {MiniZinc with Functions},
|
||||
booktitle = {Integration of {AI} and {OR} Techniques in Constraint
|
||||
Programming for Combinatorial Optimization Problems, 10th
|
||||
International Conference, {CPAIOR} 2013, Yorktown Heights, NY,
|
||||
USA, May 18-22, 2013. Proceedings},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
volume = 7874,
|
||||
pages = {268--283},
|
||||
publisher = {Springer},
|
||||
year = 2013,
|
||||
url = {https://doi.org/10.1007/978-3-642-38171-3_18},
|
||||
doi = {10.1007/978-3-642-38171-3_18},
|
||||
timestamp = {Tue, 14 May 2019 10:00:47 +0200},
|
||||
biburl = {https://dblp.org/rec/conf/cpaior/StuckeyT13.bib},
|
||||
bibsource = {dblp computer science bibliography, https://dblp.org}
|
||||
}
|
||||
|
@ -17,11 +17,18 @@
|
||||
name={decision variable},
|
||||
description={TODO},
|
||||
}
|
||||
\newglossaryentry{minizinc}{
|
||||
name={MiniZinc},
|
||||
\newglossaryentry{flatzinc}{
|
||||
name={Flat\-Zinc},
|
||||
description={TODO},
|
||||
}
|
||||
\newglossaryentry{minisearch}{
|
||||
name={Mini\-Search},
|
||||
description={TODO},
|
||||
}
|
||||
\newglossaryentry{minizinc}{
|
||||
name={Mini\-Zinc},
|
||||
description={TODO},
|
||||
}
|
||||
\newcommand{\minizinc}{\gls{minizinc}}
|
||||
\newglossaryentry{solver}{
|
||||
name={solver},
|
||||
description={TODO},
|
||||
|
@ -1,4 +1,4 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{c}{\PYZpc{} Problem parameters}
|
||||
\PY{k+kt}{enum}\PY{l+s}{ }\PY{n+nv}{TOYS}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{p}{\PYZob{}}\PY{n+nv}{football}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{tennisball}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{stuffed\PYZus{}lama}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{stuffed\PYZus{}elephant}\PY{g+gr}{\PYZcb{}}\PY{p}{;}
|
||||
\PY{k+kt}{array}\PY{p}{[}\PY{n+nv}{TOYS}\PY{g+gr}{]}\PY{l+s}{ }\PY{k+kt}{of}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{toy\PYZus{}joy}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{p}{[}\PY{l+m}{63}\PY{p}{,}\PY{l+s}{ }\PY{l+m}{12}\PY{p}{,}\PY{l+s}{ }\PY{l+m}{50}\PY{p}{,}\PY{l+s}{ }\PY{l+m}{100}\PY{g+gr}{]}\PY{p}{;}
|
||||
@ -14,4 +14,4 @@
|
||||
|
||||
\PY{c}{\PYZpc{} Goal}
|
||||
\PY{k}{solve}\PY{l+s}{ }\PY{k}{maximize}\PY{l+s}{ }\PY{n+nv}{total\PYZus{}joy}\PY{p}{;}
|
||||
\end{Verbatim}
|
||||
\end{BVerbatim}
|
||||
|
8
assets/mzn/6_adaptive.mzn
Normal file
8
assets/mzn/6_adaptive.mzn
Normal file
@ -0,0 +1,8 @@
|
||||
predicate adaptiveUniform(array[int] of var int: x, float: initialDestrRate) =
|
||||
let { var float: rate; } in
|
||||
if status() = START then rate = initialDestrRate
|
||||
elseif status() = UNSAT then rate = min(lastval(rate)-0.02,0.6)
|
||||
else rate = max(lastval(rate)+0.02,0.95)
|
||||
endif /\
|
||||
forall(i in index_set(x))
|
||||
(if uniform(0.0,1.0) > rate then x[i] = sol(x[i]) else true endif);
|
10
assets/mzn/6_adaptive.mzntex
Normal file
10
assets/mzn/6_adaptive.mzntex
Normal file
@ -0,0 +1,10 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{adaptiveUniform}\PY{p}{(}\PY{k+kt}{array}\PY{p}{[}\PY{k+kt}{int}\PY{g+gr}{]}\PY{l+s}{ }\PY{k+kt}{of}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{x}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{initialDestrRate}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{let}\PY{l+s}{ }\PY{p}{\PYZob{}}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{rate}\PY{p}{;}\PY{l+s}{ }\PY{g+gr}{\PYZcb{}}\PY{l+s}{ }\PY{o}{in}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{if}\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nv}{START}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nv}{rate}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nv}{initialDestrRate}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{elseif}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nv}{UNSAT}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nv}{rate}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nb}{min}\PY{p}{(}\PY{n+nf}{lastval}\PY{p}{(}\PY{n+nv}{rate}\PY{g+gr}{)}\PY{o}{\PYZhy{}}\PY{l+m}{0.02}\PY{p}{,}\PY{l+m}{0.6}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{n+nv}{rate}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nb}{max}\PY{p}{(}\PY{n+nf}{lastval}\PY{p}{(}\PY{n+nv}{rate}\PY{g+gr}{)}\PY{o}{+}\PY{l+m}{0.02}\PY{p}{,}\PY{l+m}{0.95}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{endif}\PY{l+s}{ }\PY{o}{/\PYZbs{}}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{forall}\PY{p}{(}\PY{n+nv}{i}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{n+nb}{index\PYZus{}set}\PY{p}{(}\PY{n+nv}{x}\PY{g+gr}{)}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{p}{(}\PY{k}{if}\PY{l+s}{ }\PY{n+nf}{uniform}\PY{p}{(}\PY{l+m}{0.0}\PY{p}{,}\PY{l+m}{1.0}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{\PYZgt{}}\PY{l+s}{ }\PY{n+nv}{rate}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nv}{x}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nf}{sol}\PY{p}{(}\PY{n+nv}{x}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{g+gr}{)}\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{l}{true}\PY{l+s}{ }\PY{k}{endif}\PY{g+gr}{)}\PY{p}{;}
|
||||
\end{BVerbatim}
|
8
assets/mzn/6_basic_complete.mzn
Normal file
8
assets/mzn/6_basic_complete.mzn
Normal file
@ -0,0 +1,8 @@
|
||||
array[1..n] of var 1..n: x; % decision variables
|
||||
var int: cost; % objective function
|
||||
% ... some constraints defining the problem
|
||||
% The user-defined LNS strategy
|
||||
predicate my_lns() = basic_lns(uniformNeighbourhood(x,0.2));
|
||||
% Solve using my\_lns, restart every 500 nodes, overall timeout 120 seconds
|
||||
solve ::on_restart("my_lns") ::restart_constant(500) ::timeout(120)
|
||||
minimize cost;
|
10
assets/mzn/6_basic_complete.mzntex
Normal file
10
assets/mzn/6_basic_complete.mzntex
Normal file
@ -0,0 +1,10 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k+kt}{array}\PY{p}{[}\PY{l+m}{1}\PY{o}{..}\PY{n+nv}{n}\PY{g+gr}{]}\PY{l+s}{ }\PY{k+kt}{of}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{l+m}{1}\PY{o}{..}\PY{n+nv}{n}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{x}\PY{p}{;}\PY{l+s}{ }\PY{l+s}{ }\PY{c}{\PYZpc{} decision variables}
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{cost}\PY{p}{;}\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{c}{\PYZpc{} objective function}
|
||||
\PY{c}{\PYZpc{} ... some constraints defining the problem}
|
||||
\PY{c}{\PYZpc{} The user-defined LNS strategy}
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{my\PYZus{}lns}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nf}{basic\PYZus{}lns}\PY{p}{(}\PY{n+nf}{uniformNeighbourhood}\PY{p}{(}\PY{n+nv}{x}\PY{p}{,}\PY{l+m}{0.2}\PY{g+gr}{)}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} Solve using my\_lns, restart every 500 nodes, overall timeout 120 seconds}
|
||||
\PY{k}{solve}\PY{l+s}{ }\PY{p}{:}\PY{p}{:}\PY{n+nf}{on\PYZus{}restart}\PY{p}{(}\PY{l+s}{\PYZdq{}}\PY{l+s}{my\PYZus{}lns}\PY{l+s}{\PYZdq{}}\PY{l+s}{) ::restart\PYZus{}constant(500) ::timeout(120)}
|
||||
\PY{l+s}{ minimize cost;}
|
||||
\end{BVerbatim}
|
16
assets/mzn/6_basic_complete_transformed.mzn
Normal file
16
assets/mzn/6_basic_complete_transformed.mzn
Normal file
@ -0,0 +1,16 @@
|
||||
var 1..5: s;@ \Vlabel{line:6:status:start}@
|
||||
constraint status(s);
|
||||
var bool b1;
|
||||
constraint int_ne_reif(s,1,b1); % b1 <-> status()!=START @\Vlabel{line:6:status:end}@
|
||||
|
||||
var 0.0..1.0: rnd1;@\Vlabel{line:6:x1:start}@
|
||||
constraint float_uniform(0.0,1.0,rnd1);
|
||||
var bool: b2;
|
||||
constraint float_gt_reif(rnd1,0.2,b2);
|
||||
var bool: b3;
|
||||
constraint bool_and(b1,b2,b3);
|
||||
var 1..3: x1;
|
||||
constraint int_sol(x[1],x1);@\Vlabel{line:6:x1}@
|
||||
% (status()!=START /\ uniform(0.0,1.0)>0.2) -> x[1]=sol(x[1])
|
||||
constraint int_eq_imp(x[1],x1,b3); @\Vlabel{line:6:x1:end}@
|
||||
@...@
|
18
assets/mzn/6_basic_complete_transformed.mzntex
Normal file
18
assets/mzn/6_basic_complete_transformed.mzntex
Normal file
@ -0,0 +1,18 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{l+m}{1}\PY{o}{..}\PY{l+m}{5}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{s}\PY{p}{;}\PY{esc}{ \Vlabel{line:6:status:start}}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{n+nv}{s}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{bool}\PY{l+s}{ }\PY{n+nv}{b1}\PY{p}{;}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{int\PYZus{}ne\PYZus{}reif}\PY{p}{(}\PY{n+nv}{s}\PY{p}{,}\PY{l+m}{1}\PY{p}{,}\PY{n+nv}{b1}\PY{g+gr}{)}\PY{p}{;}\PY{l+s}{ }\PY{c}{\PYZpc{} b1 <-> status()!=START }\PY{esc}{\Vlabel{line:6:status:end}}
|
||||
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{l+m}{0.0}\PY{o}{..}\PY{l+m}{1.0}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{rnd1}\PY{p}{;}\PY{esc}{\Vlabel{line:6:x1:start}}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{float\PYZus{}uniform}\PY{p}{(}\PY{l+m}{0.0}\PY{p}{,}\PY{l+m}{1.0}\PY{p}{,}\PY{n+nv}{rnd1}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{bool}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{b2}\PY{p}{;}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{float\PYZus{}gt\PYZus{}reif}\PY{p}{(}\PY{n+nv}{rnd1}\PY{p}{,}\PY{l+m}{0.2}\PY{p}{,}\PY{n+nv}{b2}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{bool}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{b3}\PY{p}{;}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{bool\PYZus{}and}\PY{p}{(}\PY{n+nv}{b1}\PY{p}{,}\PY{n+nv}{b2}\PY{p}{,}\PY{n+nv}{b3}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{k+kt}{var}\PY{l+s}{ }\PY{l+m}{1}\PY{o}{..}\PY{l+m}{3}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{x1}\PY{p}{;}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{int\PYZus{}sol}\PY{p}{(}\PY{n+nv}{x}\PY{p}{[}\PY{l+m}{1}\PY{g+gr}{]}\PY{p}{,}\PY{n+nv}{x1}\PY{g+gr}{)}\PY{p}{;}\PY{esc}{\Vlabel{line:6:x1}}
|
||||
\PY{c}{\PYZpc{} (status()!=START /\ uniform(0.0,1.0)>0.2) -> x[1]=sol(x[1])}
|
||||
\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{int\PYZus{}eq\PYZus{}imp}\PY{p}{(}\PY{n+nv}{x}\PY{p}{[}\PY{l+m}{1}\PY{g+gr}{]}\PY{p}{,}\PY{n+nv}{x1}\PY{p}{,}\PY{n+nv}{b3}\PY{g+gr}{)}\PY{p}{;}\PY{l+s}{ }\PY{esc}{\Vlabel{line:6:x1:end}}
|
||||
\PY{esc}{...}
|
||||
\end{BVerbatim}
|
3
assets/mzn/6_hill_climbing.mzn
Normal file
3
assets/mzn/6_hill_climbing.mzn
Normal file
@ -0,0 +1,3 @@
|
||||
predicate hill_climbing() =
|
||||
if status()=START then true
|
||||
else _objective < sol(_objective) endif;
|
5
assets/mzn/6_hill_climbing.mzntex
Normal file
5
assets/mzn/6_hill_climbing.mzntex
Normal file
@ -0,0 +1,5 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{hill\PYZus{}climbing}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{if}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{o}{=}\PY{n+nv}{START}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{l}{true}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{l+s}{\PYZus{}}\PY{l+s}{o}\PY{l+s}{b}\PY{l+s}{j}\PY{l+s}{e}\PY{l+s}{c}\PY{l+s}{t}\PY{l+s}{i}\PY{l+s}{v}\PY{l+s}{e}\PY{l+s}{ }\PY{o}{\PYZlt{}}\PY{l+s}{ }\PY{n+nf}{sol}\PY{p}{(}\PY{l+s}{\PYZus{}}\PY{l+s}{o}\PY{l+s}{b}\PY{l+s}{j}\PY{l+s}{e}\PY{l+s}{c}\PY{l+s}{t}\PY{l+s}{i}\PY{l+s}{v}\PY{l+s}{e}\PY{g+gr}{)}\PY{l+s}{ }\PY{k}{endif}\PY{p}{;}
|
||||
\end{BVerbatim}
|
8
assets/mzn/6_lns_minisearch.mzn
Normal file
8
assets/mzn/6_lns_minisearch.mzn
Normal file
@ -0,0 +1,8 @@
|
||||
function ann: lns(var int: obj, array[int] of var int: vars,
|
||||
int: iterations, float: destrRate, int: exploreTime) =
|
||||
repeat (i in 1..iterations) ( scope(
|
||||
if has_sol() then post(uniformNeighbourhood(vars,destrRate))
|
||||
else true endif /\
|
||||
time_limit(exploreTime, minimize_bab(obj)) /\
|
||||
commit() /\ print()
|
||||
) /\ post(obj < sol(obj)) );
|
10
assets/mzn/6_lns_minisearch.mzntex
Normal file
10
assets/mzn/6_lns_minisearch.mzntex
Normal file
@ -0,0 +1,10 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{function}\PY{l+s}{ }\PY{k+kt}{ann}\PY{p}{:}\PY{l+s}{ }\PY{n+nf}{lns}\PY{p}{(}\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{obj}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{array}\PY{p}{[}\PY{k+kt}{int}\PY{g+gr}{]}\PY{l+s}{ }\PY{k+kt}{of}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{vars}\PY{p}{,}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{iterations}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{destrRate}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{exploreTime}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{n+nv}{repeat}\PY{l+s}{ }\PY{p}{(}\PY{n+nv}{i}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{l+m}{1}\PY{o}{..}\PY{n+nv}{iterations}\PY{g+gr}{)}\PY{l+s}{ }\PY{p}{(}\PY{l+s}{ }\PY{n+nf}{scope}\PY{p}{(}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{if}\PY{l+s}{ }\PY{n+nf}{has\PYZus{}sol}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nf}{post}\PY{p}{(}\PY{n+nf}{uniformNeighbourhood}\PY{p}{(}\PY{n+nv}{vars}\PY{p}{,}\PY{n+nv}{destrRate}\PY{g+gr}{)}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{l}{true}\PY{l+s}{ }\PY{k}{endif}\PY{l+s}{ }\PY{o}{/\PYZbs{}}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{n+nf}{time\PYZus{}limit}\PY{p}{(}\PY{n+nv}{exploreTime}\PY{p}{,}\PY{l+s}{ }\PY{n+nf}{minimize\PYZus{}bab}\PY{p}{(}\PY{n+nv}{obj}\PY{g+gr}{)}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{/\PYZbs{}}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{n+nf}{commit}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{/\PYZbs{}}\PY{l+s}{ }\PY{n+nf}{print}\PY{p}{(}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{/\PYZbs{}}\PY{l+s}{ }\PY{n+nf}{post}\PY{p}{(}\PY{n+nv}{obj}\PY{l+s}{ }\PY{o}{\PYZlt{}}\PY{l+s}{ }\PY{n+nf}{sol}\PY{p}{(}\PY{n+nv}{obj}\PY{g+gr}{)}\PY{g+gr}{)}\PY{l+s}{ }\PY{g+gr}{)}\PY{p}{;}
|
||||
\end{BVerbatim}
|
3
assets/mzn/6_lns_minisearch_pred.mzn
Normal file
3
assets/mzn/6_lns_minisearch_pred.mzn
Normal file
@ -0,0 +1,3 @@
|
||||
predicate uniformNeighbourhood(array[int] of var int: x, float: destrRate) =
|
||||
forall(i in index_set(x))
|
||||
(if uniform(0.0,1.0) > destrRate then x[i] = sol(x[i]) else true endif);
|
5
assets/mzn/6_lns_minisearch_pred.mzntex
Normal file
5
assets/mzn/6_lns_minisearch_pred.mzntex
Normal file
@ -0,0 +1,5 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{uniformNeighbourhood}\PY{p}{(}\PY{k+kt}{array}\PY{p}{[}\PY{k+kt}{int}\PY{g+gr}{]}\PY{l+s}{ }\PY{k+kt}{of}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{x}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{destrRate}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{forall}\PY{p}{(}\PY{n+nv}{i}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{n+nb}{index\PYZus{}set}\PY{p}{(}\PY{n+nv}{x}\PY{g+gr}{)}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{p}{(}\PY{k}{if}\PY{l+s}{ }\PY{n+nf}{uniform}\PY{p}{(}\PY{l+m}{0.0}\PY{p}{,}\PY{l+m}{1.0}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{\PYZgt{}}\PY{l+s}{ }\PY{n+nv}{destrRate}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nv}{x}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nf}{sol}\PY{p}{(}\PY{n+nv}{x}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{g+gr}{)}\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{l}{true}\PY{l+s}{ }\PY{k}{endif}\PY{g+gr}{)}\PY{p}{;}
|
||||
\end{BVerbatim}
|
18
assets/mzn/6_restart_ann.mzn
Normal file
18
assets/mzn/6_restart_ann.mzn
Normal file
@ -0,0 +1,18 @@
|
||||
% post predicate "pred" whenever the solver restarts
|
||||
annotation on_restart(string: pred);
|
||||
% restart after fixed number of nodes
|
||||
annotation restart_constant(int: nodes);
|
||||
% restart with scaled Luby sequence
|
||||
annotation restart_luby(int: scale);
|
||||
% restart with scaled geometric sequence ($scale*base^n$ in the $n$-th iteration)
|
||||
annotation restart_geometric(float: base, int: scale);
|
||||
% restart with linear sequence ($scale*n$ in the $n$-th iteration)
|
||||
annotation restart_linear(int: scale);
|
||||
% restart on each solution
|
||||
annotation restart_on_solution;
|
||||
% restart without branch-and-bound constraints on the objective
|
||||
annotation restart_without_objective;
|
||||
% overall time limit for search
|
||||
annotation timeout(int: seconds);
|
||||
% overall limit on number of restarts
|
||||
annotation restart_limit(int: n_restarts);
|
20
assets/mzn/6_restart_ann.mzntex
Normal file
20
assets/mzn/6_restart_ann.mzntex
Normal file
@ -0,0 +1,20 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{c}{\PYZpc{} post predicate "pred" whenever the solver restarts}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{on\PYZus{}restart}\PY{p}{(}\PY{k+kt}{string}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{pred}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} restart after fixed number of nodes}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{restart\PYZus{}constant}\PY{p}{(}\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{nodes}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} restart with scaled Luby sequence}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{restart\PYZus{}luby}\PY{p}{(}\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{scale}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} restart with scaled geometric sequence ($scale*base^n$ in the $n$-th iteration)}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{restart\PYZus{}geometric}\PY{p}{(}\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{base}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{scale}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} restart with linear sequence ($scale*n$ in the $n$-th iteration)}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{restart\PYZus{}linear}\PY{p}{(}\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{scale}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} restart on each solution}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nv}{restart\PYZus{}on\PYZus{}solution}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} restart without branch-and-bound constraints on the objective}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nv}{restart\PYZus{}without\PYZus{}objective}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} overall time limit for search}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{timeout}\PY{p}{(}\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{seconds}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{c}{\PYZpc{} overall limit on number of restarts}
|
||||
\PY{k}{annotation}\PY{l+s}{ }\PY{n+nf}{restart\PYZus{}limit}\PY{p}{(}\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{n\PYZus{}restarts}\PY{g+gr}{)}\PY{p}{;}
|
||||
\end{BVerbatim}
|
7
assets/mzn/6_round_robin.mzn
Normal file
7
assets/mzn/6_round_robin.mzn
Normal file
@ -0,0 +1,7 @@
|
||||
predicate round_robin(array[int] of var bool: nbhs) =
|
||||
let { int: N = length(nbhs);
|
||||
var -1..N-1: select; % Neighbourhood selection
|
||||
} in if status()=START then select= -1
|
||||
else select= (lastval(select) + 1) mod N
|
||||
endif /\
|
||||
forall(i in 1..N) (select=i-1 -> nbhs[i]);@\Vlabel{line:6:roundrobin:post}@
|
9
assets/mzn/6_round_robin.mzntex
Normal file
9
assets/mzn/6_round_robin.mzntex
Normal file
@ -0,0 +1,9 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{round\PYZus{}robin}\PY{p}{(}\PY{k+kt}{array}\PY{p}{[}\PY{k+kt}{int}\PY{g+gr}{]}\PY{l+s}{ }\PY{k+kt}{of}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{bool}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{nbhs}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{let}\PY{l+s}{ }\PY{p}{\PYZob{}}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{N}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nb}{length}\PY{p}{(}\PY{n+nv}{nbhs}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{o}{\PYZhy{}}\PY{l+m}{1}\PY{o}{..}\PY{n+nv}{N}\PY{o}{\PYZhy{}}\PY{l+m}{1}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{select}\PY{p}{;}\PY{l+s}{ }\PY{c}{\PYZpc{} Neighbourhood selection}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{g+gr}{\PYZcb{}}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{l+s}{ }\PY{k}{if}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{o}{=}\PY{n+nv}{START}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nv}{select}\PY{o}{=}\PY{l+s}{ }\PY{o}{\PYZhy{}}\PY{l+m}{1}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{n+nv}{select}\PY{o}{=}\PY{l+s}{ }\PY{p}{(}\PY{n+nf}{lastval}\PY{p}{(}\PY{n+nv}{select}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{+}\PY{l+s}{ }\PY{l+m}{1}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{mod}\PY{l+s}{ }\PY{n+nv}{N}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{endif}\PY{l+s}{ }\PY{o}{/\PYZbs{}}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{forall}\PY{p}{(}\PY{n+nv}{i}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{l+m}{1}\PY{o}{..}\PY{n+nv}{N}\PY{g+gr}{)}\PY{l+s}{ }\PY{p}{(}\PY{n+nv}{select}\PY{o}{=}\PY{n+nv}{i}\PY{o}{\PYZhy{}}\PY{l+m}{1}\PY{l+s}{ }\PY{o}{\PYZhy{}\PYZgt{}}\PY{l+s}{ }\PY{n+nv}{nbhs}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{g+gr}{)}\PY{p}{;}\PY{esc}{\Vlabel{line:6:roundrobin:post}}
|
||||
\end{BVerbatim}
|
7
assets/mzn/6_simulated_annealing.mzn
Normal file
7
assets/mzn/6_simulated_annealing.mzn
Normal file
@ -0,0 +1,7 @@
|
||||
predicate simulated_annealing(float: initTemp, float: coolingRate) =
|
||||
let { var float: temp; } in
|
||||
if status()=START then temp = initTemp
|
||||
else
|
||||
temp = lastval(temp)*(1-coolingRate) /\ % cool down
|
||||
_objective < sol(_objective) - ceil(log(uniform(0.0,1.0)) * temp)
|
||||
endif;
|
9
assets/mzn/6_simulated_annealing.mzntex
Normal file
9
assets/mzn/6_simulated_annealing.mzntex
Normal file
@ -0,0 +1,9 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{simulated\PYZus{}annealing}\PY{p}{(}\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{initTemp}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{coolingRate}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{let}\PY{l+s}{ }\PY{p}{\PYZob{}}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{temp}\PY{p}{;}\PY{l+s}{ }\PY{g+gr}{\PYZcb{}}\PY{l+s}{ }\PY{o}{in}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{if}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{o}{=}\PY{n+nv}{START}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nv}{temp}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nv}{initTemp}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{else}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{n+nv}{temp}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{n+nf}{lastval}\PY{p}{(}\PY{n+nv}{temp}\PY{g+gr}{)}\PY{o}{*}\PY{p}{(}\PY{l+m}{1}\PY{o}{\PYZhy{}}\PY{n+nv}{coolingRate}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{/\PYZbs{}}\PY{l+s}{ }\PY{c}{\PYZpc{} cool down}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{\PYZus{}}\PY{l+s}{o}\PY{l+s}{b}\PY{l+s}{j}\PY{l+s}{e}\PY{l+s}{c}\PY{l+s}{t}\PY{l+s}{i}\PY{l+s}{v}\PY{l+s}{e}\PY{l+s}{ }\PY{o}{\PYZlt{}}\PY{l+s}{ }\PY{n+nf}{sol}\PY{p}{(}\PY{l+s}{\PYZus{}}\PY{l+s}{o}\PY{l+s}{b}\PY{l+s}{j}\PY{l+s}{e}\PY{l+s}{c}\PY{l+s}{t}\PY{l+s}{i}\PY{l+s}{v}\PY{l+s}{e}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{\PYZhy{}}\PY{l+s}{ }\PY{n+nb}{ceil}\PY{p}{(}\PY{n+nb}{log}\PY{p}{(}\PY{n+nf}{uniform}\PY{p}{(}\PY{l+m}{0.0}\PY{p}{,}\PY{l+m}{1.0}\PY{g+gr}{)}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{*}\PY{l+s}{ }\PY{n+nv}{temp}\PY{g+gr}{)}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{k}{endif}\PY{p}{;}
|
||||
\end{BVerbatim}
|
5
assets/mzn/6_state_access.mzn
Normal file
5
assets/mzn/6_state_access.mzn
Normal file
@ -0,0 +1,5 @@
|
||||
% Report the status of the solver (before restarting).
|
||||
enum STATUS = {START, UNKNOWN, UNSAT, SAT, OPT} @\label{ann:enum_status}@
|
||||
function STATUS: status(); @\label{ann:status}@
|
||||
% Provide access to the last assigned value of variable x.
|
||||
function int: lastval(var int: x);
|
7
assets/mzn/6_state_access.mzntex
Normal file
7
assets/mzn/6_state_access.mzntex
Normal file
@ -0,0 +1,7 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{c}{\PYZpc{} Report the status of the solver (before restarting).}
|
||||
\PY{k+kt}{enum}\PY{l+s}{ }\PY{n+nv}{STATUS}\PY{l+s}{ }\PY{o}{=}\PY{l+s}{ }\PY{p}{\PYZob{}}\PY{n+nv}{START}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{UNKNOWN}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{UNSAT}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{SAT}\PY{p}{,}\PY{l+s}{ }\PY{n+nv}{OPT}\PY{g+gr}{\PYZcb{}}\PY{l+s}{ }\PY{esc}{\label{ann:enum_status}}
|
||||
\PY{k}{function}\PY{l+s}{ }\PY{n+nv}{STATUS}\PY{p}{:}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{p}{;}\PY{l+s}{ }\PY{esc}{\label{ann:status}}
|
||||
\PY{c}{\PYZpc{} Provide access to the last assigned value of variable x.}
|
||||
\PY{k}{function}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nf}{lastval}\PY{p}{(}\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{x}\PY{g+gr}{)}\PY{p}{;}
|
||||
\end{BVerbatim}
|
5
assets/mzn/6_status.mzn
Normal file
5
assets/mzn/6_status.mzn
Normal file
@ -0,0 +1,5 @@
|
||||
predicate status(var int: stat); @\Vlabel{line:6:status}@
|
||||
function var STATUS: status() =
|
||||
let { var STATUS: stat;
|
||||
constraint status(stat);
|
||||
} in stat;
|
7
assets/mzn/6_status.mzntex
Normal file
7
assets/mzn/6_status.mzntex
Normal file
@ -0,0 +1,7 @@
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{k}{predicate}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{stat}\PY{g+gr}{)}\PY{p}{;}\PY{l+s}{ }\PY{esc}{\Vlabel{line:6:status}}
|
||||
\PY{k}{function}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{n+nv}{STATUS}\PY{p}{:}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{let}\PY{l+s}{ }\PY{p}{\PYZob{}}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{n+nv}{STATUS}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{stat}\PY{p}{;}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{constraint}\PY{l+s}{ }\PY{n+nf}{status}\PY{p}{(}\PY{n+nv}{stat}\PY{g+gr}{)}\PY{p}{;}
|
||||
\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{g+gr}{\PYZcb{}}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{n+nv}{stat}\PY{p}{;}
|
||||
\end{BVerbatim}
|
3
assets/mzn/minilns/assign_random.mzn
Normal file
3
assets/mzn/minilns/assign_random.mzn
Normal file
@ -0,0 +1,3 @@
|
||||
predicate assign_random(array[int] of var int: X, int: R) =
|
||||
forall (i in index_set(X))
|
||||
(if uniform(1,100) < R then X[i] = sol(X[i]) else true endif);
|
3
assets/mzn/minilns/basic.mzn
Normal file
3
assets/mzn/minilns/basic.mzn
Normal file
@ -0,0 +1,3 @@
|
||||
predicate basic_LNS() =
|
||||
(status() != START) -> nbh(X);
|
||||
|
19
assets/mzn/minilns/restart.mzn
Normal file
19
assets/mzn/minilns/restart.mzn
Normal file
@ -0,0 +1,19 @@
|
||||
% A search annotation that supplies a function to be executed on restart
|
||||
ann: on_restart(string: pred); @\Vlabel{ann:on_restart}@
|
||||
% An annotation for FlatZinc that accesses solver state
|
||||
ann: solver_state;
|
||||
% The 'status' function reports the status of the solver (before restarting).
|
||||
enum STATUS = {START, UNKNOWN, UNSAT, SAT, OPT} @\Vlabel{ann:enum_status}@
|
||||
function var STATUS: status(); @\Vlabel{ann:status}@
|
||||
% The 'sol' functions provides access to solution values of model variables.
|
||||
% The sol functions are meaningful when the solver status is not START.
|
||||
function var bool: sol(var bool: x); @\Vlabel{ann:sol1}@
|
||||
function var float: sol(var float: x); @\Vlabel{ann:sol2}@
|
||||
function var int: sol(var int: x); @\Vlabel{ann:sol3}@
|
||||
function var set of int: sol(var set of int: x); @\Vlabel{ann:sol4}@
|
||||
% The 'lastval' functions provides access to the last assigned value of variables.
|
||||
% The lastval functions are meaningful when the solver status is not START.
|
||||
function var bool: lastval(var bool: x);
|
||||
function var float: lastval(var float: x);
|
||||
function var int: lastval(var int: x);
|
||||
function var set of int: lastval(var set of int: x);
|
@ -1,3 +1,4 @@
|
||||
\hfuzz=1.5pt
|
||||
\usepackage{csquotes}
|
||||
\usepackage[australian]{babel}
|
||||
\usepackage{hyperref}
|
||||
@ -36,9 +37,7 @@ BoldItalicFont=*-BoldItalic,
|
||||
]
|
||||
%% Mathmatical font
|
||||
\usepackage{unicode-math}
|
||||
\setmathfont[
|
||||
Scale=1.4
|
||||
]{GFSNeohellenicMath.otf}
|
||||
\setmathfont{GFSNeohellenicMath.otf}
|
||||
|
||||
% References
|
||||
\usepackage[
|
||||
@ -48,6 +47,7 @@ style=apa,
|
||||
|
||||
% Glossary / Acronyms
|
||||
\usepackage[acronym,toc]{glossaries}
|
||||
\glsdisablehyper
|
||||
\defglsentryfmt[main]{\ifglsused{\glslabel}{\glsgenentryfmt}{\textit{\glsgenentryfmt}}}
|
||||
\makeglossaries{}
|
||||
|
||||
@ -55,23 +55,30 @@ style=apa,
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage{color}
|
||||
\input{assets/pygments_header.tex}
|
||||
\newcommand{\highlightfile}[1]{\input{#1tex}}
|
||||
\DeclareNewTOC[
|
||||
type=program,
|
||||
type=listing,
|
||||
float,
|
||||
name=Program,
|
||||
name=Listing,
|
||||
counterwithin=chapter,
|
||||
atbegin={%
|
||||
\centering
|
||||
\scriptsize
|
||||
}
|
||||
]{program}
|
||||
\crefname{program}{program}{programs}
|
||||
\DeclareNewTOC[
|
||||
type=model,
|
||||
float,
|
||||
name=Model,
|
||||
counterwithin=chapter,
|
||||
atbegin={%
|
||||
\scriptsize
|
||||
|
||||
\crefname{listing}{listing}{listings}
|
||||
\newcommand{\Vlabel}[1]{\label[line]{#1}\hypertarget{#1}{}}
|
||||
\newcommand{\lref}[1]{\hyperlink{#1}{\FancyVerbLineautorefname~\ref*{#1}}}
|
||||
\newcommand{\lrefrange}[2]{\FancyVerbLineautorefname{}s~\hyperlink{#1}{\ref*{#1}}--\hyperlink{#2}{\ref*{#2}}}
|
||||
\newcommand{\Lrefrange}[2]{Lines~\hyperlink{#1}{\ref*{#1}}--\hyperlink{#2}{\ref*{#2}}}
|
||||
|
||||
% TODO: What am I doing with this?
|
||||
\newcommand*\justify{%
|
||||
\fontdimen2\font=0.4em% interword space
|
||||
\fontdimen3\font=0.2em% interword stretch
|
||||
\fontdimen4\font=0.1em% interword shrink
|
||||
\fontdimen7\font=0.1em% extra space
|
||||
\hyphenchar\font=`\-% allowing hyphenation
|
||||
}
|
||||
]{model}
|
||||
\crefname{model}{model}{models}
|
||||
\newcommand{\mzninline}[1]{\texttt{\small\justify\detokenize{#1}}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
|
||||
\PY{n}{toys\PYZus{}joy} \PY{o}{=} \PY{p}{[}\PY{l+m+mi}{63}\PY{p}{,} \PY{l+m+mi}{12}\PY{p}{,} \PY{l+m+mi}{50}\PY{p}{,} \PY{l+m+mi}{100}\PY{p}{]}
|
||||
\PY{n}{toys\PYZus{}space} \PY{o}{=} \PY{p}{[}\PY{l+m+mi}{32}\PY{p}{,} \PY{l+m+mi}{8}\PY{p}{,} \PY{l+m+mi}{16}\PY{p}{,} \PY{l+m+mi}{40}\PY{p}{]}
|
||||
\PY{n}{space\PYZus{}left} \PY{o}{=} \PY{l+m+mi}{64}
|
||||
@ -27,4 +27,4 @@
|
||||
\PY{n}{table}\PY{p}{[}\PY{n}{i}\PY{p}{]}\PY{p}{[}\PY{n}{j}\PY{p}{]} \PY{o}{=} \PY{n}{table}\PY{p}{[}\PY{n}{i} \PY{o}{\PYZhy{}} \PY{l+m+mi}{1}\PY{p}{]}\PY{p}{[}\PY{n}{j}\PY{p}{]}
|
||||
|
||||
\PY{n}{optimal\PYZus{}joy} \PY{o}{=} \PY{n}{table}\PY{p}{[}\PY{n}{num\PYZus{}toys}\PY{p}{]}\PY{p}{[}\PY{n}{space\PYZus{}left}\PY{p}{]}
|
||||
\end{Verbatim}
|
||||
\end{BVerbatim}
|
||||
|
4
assets/shorthands.tex
Normal file
4
assets/shorthands.tex
Normal file
@ -0,0 +1,4 @@
|
||||
\newcommand{\eg}{e.g.}
|
||||
\newcommand{\flatzinc}{\gls{flatzinc}}
|
||||
\newcommand{\minisearch}{\gls{minisearch}}
|
||||
\newcommand{\minizinc}{\gls{minizinc}}
|
@ -22,33 +22,33 @@ amount of space left in the car, so we cannot bring all the toys. Since Audrey
|
||||
gets enjoys playing with some toys more than others, we can now try and pick the
|
||||
toys that bring Audrey the most amount of joy, but still fit in the car.
|
||||
|
||||
\begin{program}[ht]
|
||||
\input{assets/py/2_dyn_knapsack.pytex}
|
||||
\caption{\label{prog:dyn-knapsack} A Python program that solves a 0-1 knapsack
|
||||
\begin{listing}[ht]
|
||||
\highlightfile{assets/py/2_dyn_knapsack.py}
|
||||
\caption{\label{lst:2-dyn-knapsack} A Python program that solves a 0-1 knapsack
|
||||
problem using dynamic programming}
|
||||
\end{program}
|
||||
\end{listing}
|
||||
|
||||
A well educated reader in optimisation problems might immediately recognise that
|
||||
this is a variation on the widely known \textit{knapsack problem}, more
|
||||
specifically a \textit{0-1 knapsack problem}
|
||||
\autocite[13--67]{silvano-1990-knapsack}. A commonly used solution to this
|
||||
problem is based on dynamic programming. An implementation of this approach is
|
||||
shown in \cref{prog:dyn-knapsack}. In a naive recursive approach we would try
|
||||
shown in \cref{lst:2-dyn-knapsack}. In a naive recursive approach we would try
|
||||
all different combinations of toys to find the combination that will give the
|
||||
most joy, but using a dynamic programming approach this exponential behaviour
|
||||
(on the number of toys) can be avoided.
|
||||
|
||||
\begin{model}[ht]
|
||||
\input{assets/mzn/2_knapsack.mzntex}
|
||||
\caption{\label{model:knapsack} A \minizinc\ model describing a 0-1 knapsack
|
||||
\begin{listing}[ht]
|
||||
\highlightfile{assets/mzn/2_knapsack.mzn}
|
||||
\caption{\label{lst:2-mzn-knapsack} A \minizinc\ model describing a 0-1 knapsack
|
||||
problem}
|
||||
\end{model}
|
||||
\end{listing}
|
||||
|
||||
A constraint model offers a different view of the problem. Instead of specifying
|
||||
the manner in which we can find the solution, we give a concise description of
|
||||
the problem in terms of what we already know, the \glspl{problem-parameter},
|
||||
what we wish to know, the \glspl{decision-variable}, and the relationships that
|
||||
should exists between them, the \glspl{constraint}. \Cref{model:knapsack} shows
|
||||
should exists between them, the \glspl{constraint}. \Cref{lst:2-mzn-knapsack} shows
|
||||
a \minizinc\ model of the knapsack problem, where the different elements of the
|
||||
constraint model are separated. Although a constraint model does not contain any
|
||||
instructions to find a suitable solutions, these models can generally be given
|
||||
|
@ -1,3 +1,529 @@
|
||||
%************************************************
|
||||
\chapter{Incremental Solving}\label{ch:incremental}
|
||||
%************************************************
|
||||
|
||||
\section{Modelling of Neighbourhoods and Meta-heuristics}
|
||||
\label{section:2-modelling-nbhs}
|
||||
%
|
||||
% Start with a brief review of most common neighbourhoods and then explain:
|
||||
% \begin{itemize}
|
||||
% \item Random built in with integers
|
||||
% \begin{itemize}
|
||||
% \item Explain the built in
|
||||
% \item Give an example of use (use model)
|
||||
% \item Limitations if any
|
||||
% \end{itemize}
|
||||
|
||||
% \item Solution based one
|
||||
% \begin{itemize}
|
||||
% \item Explain the built in
|
||||
% \item Give an example of use (use model)
|
||||
% \item Limitations if any
|
||||
% \end{itemize}
|
||||
% \end{itemize}
|
||||
|
||||
% End with future work for other built ins (hint which ones would be useful).
|
||||
|
||||
Most LNS literature discusses neighbourhoods in terms of ``destroying'' part of
|
||||
a solution that is later repaired. However, from a declarative modelling point
|
||||
of view, it is more natural to see neighbourhoods as adding new constraints and
|
||||
variables that need to be applied to the base model, \eg forcing variables to
|
||||
take the same value as in the previous solution.
|
||||
|
||||
This section introduces a \minizinc\ extension that enables modellers to define
|
||||
neighbourhoods using the $\mathit{nbh(a)}$ approach described above. This
|
||||
extension is based on the constructs introduced in
|
||||
\minisearch\~\autocite{rendl-2015-minisearch}, as summarised below.
|
||||
|
||||
\subsection{LNS in \glsentrytext{minisearch}}
|
||||
|
||||
\minisearch\ introduced a \minizinc\ extension that enables modellers to express
|
||||
meta-searches inside a \minizinc\ model. A meta-search in \minisearch\ typically
|
||||
solves a given \minizinc\ model, performs some calculations on the solution, adds
|
||||
new constraints and then solves again.
|
||||
|
||||
An LNS definition in \minisearch\ consists of two parts. The first part is a
|
||||
declarative definition of a neighbourhood as a \minizinc\ predicate that posts
|
||||
the constraints that should be added with respect to a previous solution. This
|
||||
makes use of the \minisearch\ function: \mzninline{function int: sol(var int:
|
||||
x)}, which returns the value that variable \mzninline{x} was assigned to in
|
||||
the previous solution (similar functions are defined for Boolean, float and set
|
||||
variables). In addition, a neighbourhood predicate will typically make use of
|
||||
the random number generators available in the \minizinc\ standard library.
|
||||
\Cref{lst:6-lns-minisearch-pred} shows a simple random neighbourhood. For each
|
||||
decision variable \mzninline{x[i]}, it draws a random number from a uniform
|
||||
distribution and, if it exceeds threshold \mzninline{destrRate}, posts
|
||||
constraints forcing \mzninline{x[i]} to take the same value as in the previous
|
||||
solution. For example, \mzninline{uniformNeighbourhood(x, 0.2)} would result in
|
||||
each variable in the array \mzninline{x} having a 20\% chance of being
|
||||
unconstrained, and an 80\% chance of being assigned to the value it had in the
|
||||
previous solution.
|
||||
|
||||
\begin{listing}
|
||||
\highlightfile{assets/mzn/6_lns_minisearch_pred.mzn}
|
||||
\caption{\label{lst:6-lns-minisearch-pred} A simple random LNS predicate
|
||||
implemented in \minisearch{}}
|
||||
\end{listing}
|
||||
|
||||
\begin{listing}
|
||||
\highlightfile{assets/mzn/6_lns_minisearch.mzn}
|
||||
\caption{\label{lst:6-lns-minisearch} A simple LNS metaheuristic implemented
|
||||
in \minisearch{}}
|
||||
\end{listing}
|
||||
|
||||
The second part of a \minisearch\ LNS is the meta-search itself. The most basic
|
||||
example is that of function \mzninline{lns} in \cref{lst:6-lns-minisearch}. It
|
||||
performs a fixed number of iterations, each invoking the neighbourhood predicate
|
||||
\mzninline{uniformNeighbourhood} in a fresh scope (so that the constraints only
|
||||
affect the current loop iteration). It then searches for a solution
|
||||
(\mzninline{minimize_bab}) with a given timeout, and if the search does return a
|
||||
new solution, it commits to that solution (so that it becomes available to the
|
||||
\mzninline{sol} function in subsequent iterations). The \texttt{lns} function
|
||||
also posts the constraint \mzninline{obj < sol(obj)}, ensuring the objective
|
||||
value in the next iteration is strictly better than that of the current
|
||||
solution.
|
||||
|
||||
\paragraph{Limitations of the \minisearch\ approach.}
|
||||
|
||||
Although \minisearch\ enables the modeller to express \emph{neighbourhoods} in a
|
||||
declarative way, the definition of the \emph{meta-search} is rather unintuitive
|
||||
and difficult to debug, leading to unwieldy code for defining simple restarting
|
||||
strategies. Furthermore, the \minisearch\ implementation requires either a close
|
||||
integration of the backend solver into the \minisearch\ system, or it drives the
|
||||
solver through the regular text-file based \flatzinc\ interface, leading to a
|
||||
significant communication overhead.
|
||||
|
||||
To address these two issues for LNS, we propose to keep modelling neighbourhoods
|
||||
as predicates, but define a small number of additional \minizinc\ built-in
|
||||
annotations and functions that (a) allow us to express important aspects of the
|
||||
meta-search in a more convenient way, and (b) enable a simple compilation scheme
|
||||
that requires no additional communication with and only small, simple extensions
|
||||
of the backend solver.
|
||||
|
||||
The approach we follow here is therefore to \textbf{extend \flatzinc}, such that
|
||||
the definition of neighbourhoods can be communicated to the solver together with
|
||||
the problem instance. This maintains the loose coupling of \minizinc\ and
|
||||
solver, while avoiding the costly communication and cold-starting of the
|
||||
black-box approach.
|
||||
|
||||
\subsection{Restart annotations}
|
||||
|
||||
Instead of the complex \minisearch\ definitions, we propose to add support for
|
||||
simple meta-searches that are purely based on the notion of \emph{restarts}. A
|
||||
restart happens when a solver abandons its current search efforts, returns to
|
||||
the root node of the search tree, and begins a new exploration. Many CP solvers
|
||||
already provide support for controlling their restarting behaviour, e.g.\ they
|
||||
can periodically restart after a certain number of nodes, or restart for every
|
||||
solution. Typically, solvers also support posting additional constraints upon
|
||||
restarting (e.g Comet~\autocite{michel-2005-comet}) that are only valid for the
|
||||
particular restart (i.e., they are ``retracted'' for the next restart).
|
||||
|
||||
In its simplest form, we can therefore implement LNS by specifying a
|
||||
neighbourhood predicate, and annotating the \mzninline{solve} item to indicate
|
||||
the predicate should be invoked upon each restart:
|
||||
|
||||
\mzninline{solve ::on_restart(myNeighbourhood) minimize cost;}
|
||||
|
||||
Note that \minizinc\ currently does not support passing functions or predicates
|
||||
as arguments. Calling the predicate, as in
|
||||
\mzninline{::on_restart(myNeighbourhood())}, would not have the correct
|
||||
semantics, since the predicate needs to be called for \emph{each} restart. As a
|
||||
workaround, we currently pass the name of the predicate to be called for each
|
||||
restart as a string (see the definition of the new \mzninline{on_restart}
|
||||
annotation in \cref{lst:6-restart-ann}).
|
||||
|
||||
The second component of our LNS definition is the \emph{restarting strategy},
|
||||
defining how much effort the solver should put into each neighbourhood (i.e.,
|
||||
restart), and when to stop the overall search.
|
||||
|
||||
We propose adding new search annotations to \minizinc\ to control this behaviour
|
||||
(see \cref{lst:6-restart-ann}). The \mzninline{restart_on_solution} annotation
|
||||
tells the solver to restart immediately for each solution, rather than looking
|
||||
for the best one in each restart, while \mzninline{restart_without_objective}
|
||||
tells it not to add branch-and-bound constraints on the objective. The other
|
||||
\mzninline{restart_X} annotations define different strategies for restarting the
|
||||
search when no solution is found. The \mzninline{timeout} annotation gives an
|
||||
overall time limit for the search, whereas \mzninline{restart_limit} stops the
|
||||
search after a fixed number of restarts.
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_restart_ann.mzn}
|
||||
\caption{\label{lst:6-restart-ann} New annotations to control the restarting
|
||||
behaviour}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Neighbourhood selection}
|
||||
|
||||
It is often beneficial to use several neighbourhood definitions for a problem.
|
||||
Different neighbourhoods may be able to improve different aspects of a solution,
|
||||
at different phases of the search. Adaptive LNS \autocite{ropke-2006-adaptive,
|
||||
pisinger-2007-heuristic}, which keeps track of the neighbourhoods that led to
|
||||
improvements and favours them for future iterations, is the prime example for
|
||||
this approach. A simpler scheme may apply several neighbourhoods in a
|
||||
round-robin fashion.
|
||||
|
||||
In \minisearch\, adaptive or round-robin approaches can be implemented using
|
||||
\emph{state variables}, which support destructive update (overwriting the value
|
||||
they store). In this way, the \minisearch\ strategy can store values to be used
|
||||
in later iterations. We use the \emph{solver state} instead, i.e., normal
|
||||
decision variables, and define two simple built-in functions to access the
|
||||
solver state \emph{of the previous restart}. This approach is sufficient for
|
||||
expressing neighbourhood selection strategies, and its implementation is much
|
||||
simpler.
|
||||
|
||||
\paragraph{State access and initialisation}
|
||||
|
||||
The state access functions are defined in \cref{lst:6-state-access}. Function
|
||||
\mzninline{status} returns the status of the previous restart, namely:
|
||||
\mzninline{START} (there has been no restart yet); \mzninline{UNSAT} (the
|
||||
restart failed); \mzninline{SAT} (the restart found a solution); \mzninline{OPT}
|
||||
(the restart found and proved an optimal solution); and \mzninline{UNKNOWN} (the
|
||||
restart did not fail or find a solution). Function \mzninline{lastval} (which,
|
||||
like \mzninline{sol}, has versions for all basic variable types) allows
|
||||
modellers to access the last value assigned to a variable (the value is
|
||||
undefined if \mzninline{status()=START}).
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_state_access.mzn}
|
||||
\caption{\label{lst:6-state-access} Functions for accessing previous solver
|
||||
states}
|
||||
\end{listing}
|
||||
|
||||
In order to be able to initialise the variables used for state access, we
|
||||
reinterpret \mzninline{on_restart} so that the predicate is also called for the
|
||||
initial search (i.e., before the first ``real'' restart) with the same
|
||||
semantics, that is, any constraint posted by the predicate will be retracted for
|
||||
the next restart.
|
||||
|
||||
\paragraph{Parametric neighbourhood selection predicates}
|
||||
|
||||
We define standard neighbourhood selection strategies as predicates that are
|
||||
parametric over the neighbourhoods they should apply. For example, since
|
||||
\mzninline{on_restart} now also includes the initial search, we can define a
|
||||
strategy \mzninline{basic_lns} that applies a neighbourhood only if the current
|
||||
status is not \mzninline{START}:
|
||||
|
||||
\mzninline{predicate basic_lns(var bool: nbh) = (status()!=START -> nbh);}
|
||||
|
||||
In order to use this predicate with the \mzninline{on_restart} annotation, we
|
||||
cannot simply pass \mzninline{basic_lns(uniformNeighbourhood(x,0.2))}. First of
|
||||
all, calling \mzninline{uniformNeighbourhood} like that would result in a
|
||||
\emph{single} evaluation of the predicate, since \minizinc\ employs a
|
||||
call-by-value evaluation strategy. Furthermore, the \mzninline{on_restart}
|
||||
annotation only accepts the name of a nullary predicate. Therefore, users have
|
||||
to define their overall strategy in a new predicate. \Cref{lst:6-basic-complete}
|
||||
shows a complete example of a basic LNS model.
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_basic_complete.mzn}
|
||||
\caption{\label{lst:6-basic-complete} Complete LNS example}
|
||||
\end{listing}
|
||||
|
||||
We can also define round-robin and adaptive strategies using these primitives.
|
||||
%\paragraph{Round-robin LNS}
|
||||
\Cref{lst:6-round-robin} defines a round-robin LNS meta-heuristic, which cycles
|
||||
through a list of \mzninline{N} neighbourhoods \mzninline{nbhs}. To do this, it
|
||||
uses the decision variable \mzninline{select}. In the initialisation phase
|
||||
(\mzninline{status()=START}), \mzninline{select} is set to \mzninline{-1}, which
|
||||
means none of the neighbourhoods is activated. In any following restart,
|
||||
\mzninline{select} is incremented modulo \mzninline{N}, by accessing the last
|
||||
value assigned in a previous restart (\mzninline{lastval(select)}). This will
|
||||
activate a different neighbourhood for each restart
|
||||
(\lref{line:6:roundrobin:post}).
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_round_robin.mzn}
|
||||
\caption{\label{lst:6-round-robin} A predicate providing the round robin
|
||||
meta-heuristic}
|
||||
\end{listing}
|
||||
|
||||
%\paragraph{Adaptive LNS}
|
||||
For adaptive LNS, a simple strategy is to change the size of the neighbourhood
|
||||
depending on whether the previous size was successful or not.
|
||||
\Cref{lst:6-adaptive} shows an adaptive version of the
|
||||
\mzninline{uniformNeighbourhood} that increases the number of free variables
|
||||
when the previous restart failed, and decreases it when it succeeded, within the
|
||||
bounds $[0.6,0.95]$.
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_adaptive.mzn}
|
||||
\caption{\label{lst:6-adaptive} A simple adaptive neighbourhood}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Meta-heuristics}
|
||||
|
||||
The LNS strategies we have seen so far rely on the default behaviour of
|
||||
\minizinc\ solvers to use branch-and-bound for optimisation: when a new solution
|
||||
is found, the solver adds a constraint to the remainder of the search to only
|
||||
accept better solutions, as defined by the objective function in the
|
||||
\mzninline{minimize} or \mzninline{maximize} clause of the \mzninline{solve}
|
||||
item. When combined with restarts and LNS, this is equivalent to a simple
|
||||
hill-climbing meta-heuristic.
|
||||
|
||||
We can use the constructs introduced above to implement alternative
|
||||
meta-heuristics such as simulated annealing. In particular, we use
|
||||
\mzninline{restart_without_objective} to tell the solver not to add the
|
||||
branch-and-bound constraint on restart. It will still use the declared objective
|
||||
to decide whether a new solution is the globally best one seen so far, and only
|
||||
output those (to maintain the convention of \minizinc\ solvers that the last
|
||||
solution printed at any point in time is the currently best known one).
|
||||
%
|
||||
With \mzninline{restart_without_objective}, the restart predicate is now
|
||||
responsible for constraining the objective function. Note that a simple
|
||||
hill-climbing (for minimisation) can still be defined easily in this context as:
|
||||
|
||||
{
|
||||
\centering
|
||||
\scriptsize
|
||||
\highlightfile{assets/mzn/6_hill_climbing.mzn}
|
||||
}
|
||||
|
||||
It takes advantage of the fact that the declared objective function is available
|
||||
through the built-in variable \mzninline{_objective}.
|
||||
%
|
||||
A simulated annealing strategy is also easy to
|
||||
express:
|
||||
|
||||
{
|
||||
\centering
|
||||
\scriptsize
|
||||
\highlightfile{assets/mzn/6_simulated_annealing.mzn}
|
||||
}
|
||||
|
||||
\section{Compilation of Neighbourhoods} \label{section:compilation}
|
||||
|
||||
The neighbourhoods defined in the previous section can be executed with
|
||||
\minisearch\ by adding support for the \mzninline{status} and
|
||||
\mzninline{lastval} built-in functions, and by defining the main restart loop.
|
||||
The \minisearch{} evaluator will then call a solver to produce a solution, and
|
||||
evaluate the neighbourhood predicate, incrementally producing new \flatzinc\ to
|
||||
be added to the next round of solving.
|
||||
%
|
||||
While this is a viable approach, our goal is to keep the compiler and solver
|
||||
separate, by embedding the entire LNS specification into the \flatzinc\ that is
|
||||
passed to the solver.
|
||||
%
|
||||
This section introduces such a compilation approach. It only requires simple
|
||||
modifications of the \minizinc\ compiler, and the compiled \flatzinc\ can be
|
||||
executed by standard CP solvers with a small set of simple extensions.
|
||||
|
||||
\subsection{Compilation overview}
|
||||
|
||||
The neighbourhood definitions from the previous section have an important
|
||||
property that makes them easy to compile to standard \flatzinc: they are defined
|
||||
in terms of standard \minizinc\ expressions, with the exception of a few new
|
||||
built-in functions. When the neighbourhood predicates are evaluated in the
|
||||
\minisearch\ way, the \minisearch\ runtime implements those built-in functions,
|
||||
computing the correct value whenever a predicate is evaluated.
|
||||
%
|
||||
Instead, the compilation scheme presented below uses a limited form of
|
||||
\emph{partial evaluation}: parameters known at compile time will be fully
|
||||
evaluated; those only known during the solving, such as the result of a call to
|
||||
any of the new functions (\mzninline{sol}, \mzninline{status}, etc.), are
|
||||
replaced by decision variables. This essentially \textbf{turns the new built-in
|
||||
functions into constraints} that have to be supported by the target solver.
|
||||
The neighbourhood predicate can then be added as a constraint to the model. The
|
||||
evaluation is performed by hijacking the solver's own capabilities: It will
|
||||
automatically perform the evaluation of the new functions by propagating the new
|
||||
constraints.
|
||||
|
||||
To compile an LNS specification to standard \flatzinc, the \minizinc\ compiler
|
||||
performs four simple steps:
|
||||
|
||||
\begin{enumerate}
|
||||
\item Replace the annotation \mzninline{::on_restart("X")} with a call to
|
||||
predicate \mzninline{X}.
|
||||
\item Inside predicate \mzninline{X} and any other predicate called
|
||||
recursively from \mzninline{X}: treat any call to built-in functions
|
||||
\mzninline{sol}, \mzninline{status}, and \mzninline{lastval} as
|
||||
returning a \mzninline{var} instead of a \mzninline{par} value; and
|
||||
rename calls to random functions, e.g., \mzninline{uniform} to
|
||||
\mzninline{uniform_nbh}, in order to distinguish them from their
|
||||
standard library versions.
|
||||
\item Convert any expression containing a call from step 2 to \mzninline{var}
|
||||
to ensure the functions are compiled as constraints, rather than
|
||||
statically evaluated by the \minizinc\ compiler.
|
||||
\item Compile the resulting model using an extension of the \minizinc\
|
||||
standard library that provides declarations for these built-in
|
||||
functions, as defined below.
|
||||
\end{enumerate}
|
||||
|
||||
These transformations will not change the code of many neighbourhood
|
||||
definitions, since the built-in functions are often used in positions that
|
||||
accept both parameters and variables. For example, the
|
||||
\mzninline{uniformNeighbourhood} predicate from \cref{lst:6-lns-minisearch-pred}
|
||||
uses \mzninline{uniform(0.0,1.0)} in an \mzninline{if} expression, and
|
||||
\mzninline{sol(x[i])} in an equality constraint. Both expressions can be
|
||||
translated to \flatzinc\ when the functions return a \mzninline{var}.
|
||||
|
||||
\subsection{Compiling the new built-ins}
|
||||
|
||||
We can compile models that contain the new built-ins by extending the \minizinc\
|
||||
standard library as follows.
|
||||
|
||||
\paragraph{\mzninline{status}}
|
||||
|
||||
\Cref{lst:6-status} shows the definition of the \mzninline{status} function. It
|
||||
simply replaces the functional form by a predicate \mzninline{status} (declared
|
||||
in \lref{line:6:status}), which constrains its local variable argument
|
||||
\mzninline{stat} to take the status value.
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_status.mzn}
|
||||
\caption{\label{lst:6-status} MiniZinc definition of the \mzninline{status} function}
|
||||
\end{listing}
|
||||
|
||||
|
||||
\paragraph{\mzninline{sol} and \mzninline{lastval}}
|
||||
|
||||
Since \mzninline{sol} is overloaded for different variable types and \flatzinc\
|
||||
does not support overloading, we produce type-specific built-ins for every type
|
||||
of solver variable (\mzninline{int_sol(x, xi)}, \mzninline{bool_sol(x, xi)},
|
||||
etc.). The resolving of the \mzninline{sol} function into these specific
|
||||
built-ins is done using an overloaded definition like the one shown
|
||||
in~\Cref{lst:6-int-sol} for integer variables. If the value of the variable in
|
||||
question becomes known at compile time, we use that value instead. Otherwise, we
|
||||
replace the function call with a type specific \mzninline{int_sol} predicate,
|
||||
which is the constraint that will be executed by the solver.
|
||||
%
|
||||
\begin{listing}[t]
|
||||
\centering
|
||||
% \begin{mzn}
|
||||
% predicate int_sol(var int: x, var int: xi);
|
||||
% function int: sol(var int: x) = if is_fixed(x) then fix(x)
|
||||
% else let { var lb(x)..ub(x): xi;
|
||||
% constraint int_sol(x,xi);
|
||||
% } in xi;
|
||||
% endif;
|
||||
% \end{mzn}
|
||||
\caption{\label{lst:6-int-sol} MiniZinc definition of the \mzninline{sol}
|
||||
function for integer variables}
|
||||
\end{listing}
|
||||
%
|
||||
To improve the compilation of the model further, we use the declared bounds of
|
||||
the argument (\mzninline{lb(x)..ub(x)}) to constrain the variable returned by
|
||||
\mzninline{sol}. This bounds information is important for the compiler to be
|
||||
able to generate the most efficient \flatzinc\ code for expressions involving
|
||||
\mzninline{sol}. The compilation of \mzninline{lastval} is similar to that for
|
||||
\mzninline{sol}.
|
||||
|
||||
\paragraph{Random number functions}
|
||||
|
||||
Calls to the random number functions have been renamed by appending
|
||||
\texttt{\_nbh}, so that the compiler does not simply evaluate them statically.
|
||||
The definition of these new functions follows the same pattern as for
|
||||
\mzninline{sol}, \mzninline{status}, and \mzninline{lastval}. The MiniZinc
|
||||
definition of the \mzninline{uniform_nbh} function is shown in
|
||||
\Cref{lst:6-int-rnd}.%
|
||||
\footnote{Random number functions need to be marked as \mzninline{::impure} for
|
||||
the compiler not to apply Common Subexpression Elimination
|
||||
(CSE)~\autocite{stuckey-2013-functions} if they are called multiple times with
|
||||
the same arguments.}%
|
||||
Note that the function accepts variable arguments \mzninline{l} and
|
||||
\mzninline{u}, so that it can be used in combination with other functions, such
|
||||
as \mzninline{sol}.
|
||||
|
||||
\begin{listing}[t]
|
||||
\centering
|
||||
% \begin{mzn}
|
||||
% predicate float_uniform(var float:l, var float: u, var float: r);
|
||||
% function var float: uniform_nbh(var float: l, var float: u) :: impure =
|
||||
% let { var lb(l)..ub(u): rnd;
|
||||
% constraint float_uniform(l,u,rnd):
|
||||
% } in rnd;
|
||||
% \end{mzn}
|
||||
\caption{\label{lst:6-int-rnd} MiniZinc definition of the
|
||||
\mzninline{uniform_nbh} function for floats}
|
||||
\end{listing}
|
||||
|
||||
|
||||
\subsection{Solver support for LNS \glsentrytext{flatzinc}}
|
||||
|
||||
We will now show the minimal extensions required from a solver to interpret the
|
||||
new \flatzinc\ constraints and, consequently, to execute LNS definitions
|
||||
expressed in \minizinc.
|
||||
|
||||
First, the solver needs to parse and support the restart annotations
|
||||
of~\cref{lst:6-restart-ann}. Many solvers already support all this
|
||||
functionality. Second, the solver needs to be able to parse the new constraints
|
||||
\mzninline{status}, and all versions of \mzninline{sol}, \mzninline{lastval},
|
||||
and random number functions like \mzninline{float_uniform}. In addition, for the
|
||||
new constraints the solver needs to:
|
||||
\begin{itemize}
|
||||
\item \mzninline{status(s)}: record the status of the previous restart, and
|
||||
fix \mzninline{s} to the recorded status.
|
||||
\item \mzninline{sol(x,sx)} (variants): constrain \mzninline{sx} to be equal
|
||||
to the value of \mzninline{x} in the incumbent solution. If there is no
|
||||
incumbent solution, it has no effect.
|
||||
\item \mzninline{lastval(x,lx)} (variants): constrain \mzninline{lx} to take
|
||||
the last value assigned to \mzninline{x} during search. If no value was
|
||||
ever assigned, it has no effect. Note that many solvers (in particular
|
||||
SAT and LCG solvers) already track \mzninline{lastval} for their
|
||||
variables for use in search. To support LNS a solver must at least track
|
||||
the \emph{lastval} of each of the variables involved in such a
|
||||
constraint. This is straightforward by using the \mzninline{lastval}
|
||||
propagator itself. It wakes up whenever the first argument is fixed, and
|
||||
updates the last value (a non-backtrackable value).
|
||||
\item random number functions: fix their variable argument to a random number
|
||||
in the appropriate probability distribution.
|
||||
\end{itemize}
|
||||
|
||||
Importantly, these constraints need to be propagated in a way that their effects
|
||||
can be undone for the next restart. Typically, this means the solver must not
|
||||
propagate these constraints in the root node of the search.
|
||||
|
||||
Modifying a solver to support this functionality is straightforward if it
|
||||
already has a mechanism for posting constraints during restarts. We have
|
||||
implemented these extensions for both Gecode (110 new lines of code) and Chuffed
|
||||
(126 new lines of code).
|
||||
|
||||
For example, consider the model from \cref{lst:6-basic-complete} again.
|
||||
\Cref{lst:6-flat-pred} shows a part of the \flatzinc\ that arises from compiling
|
||||
\mzninline{basic_lns(uniformNeighbourhood(x, 0.2))}, assuming that
|
||||
\mzninline{index_set(x) = 1..n}.
|
||||
|
||||
\Lrefrange{line:6:status:start}{line:6:status:end} define a Boolean variable
|
||||
\mzninline{b1} that is true iff the status is not \mzninline{START}. The second
|
||||
block of code (\lrefrange{line:6:x1:start}{line:6:x1:end}) represents the
|
||||
decomposition of the expression
|
||||
|
||||
\mzninline{(status() != START /\ uniform(0.0,1.0) > 0.2) -> x[1] = sol(x[1])}
|
||||
%
|
||||
which is the result of merging the implication from the \mzninline{basic_lns}
|
||||
predicate with the \mzninline{if} expression from
|
||||
\mzninline{uniformNeighbourhood}. The code first introduces and constrains a
|
||||
variable for the random number, then adds two Boolean variables: \mzninline{b2}
|
||||
is constrained to be true iff the random number is greater than 0.2; while
|
||||
\mzninline{b3} is constrained to be the conjunction \mzninline{status()!=START
|
||||
/\ uniform(0.0,1.0)>0.2}. \lref{line:6:x1} constrains \mzninline{x1} to be the
|
||||
value of \mzninline{x[1]} in the previous solution. Finally, the half-reified
|
||||
constraint in \lref{line:6:x1:end} implements \mzninline{b3 -> x[1]=sol(x[1])}.
|
||||
We have omitted the similar code generated for \mzninline{x[2]} to
|
||||
\mzninline{x[n]}. Note that the \flatzinc\ shown here has been simplified for
|
||||
presentation.
|
||||
|
||||
\begin{listing}[t]
|
||||
\highlightfile{assets/mzn/6_basic_complete_transformed.mzn}
|
||||
\caption{\label{lst:6-flat-pred} \flatzinc\ that results from compiling \\
|
||||
\mzninline{basic_lns(uniformNeighbourhood(x,0.2))}.}
|
||||
\end{listing}
|
||||
|
||||
The first time the solver is invoked, it sets \mzninline{s} to 1
|
||||
(\mzninline{START}). Propagation will fix \mzninline{b1} to \mzninline{false}
|
||||
and \mzninline{b3} to \mzninline{false}. Therefore, the implication in
|
||||
\lref{line:6:x1:end} is not activated, leaving \mzninline{x[1]} unconstrained.
|
||||
The neighbourhood constraints are effectively switched off.
|
||||
|
||||
When the solver restarts, all of the special propagators are re-executed.
|
||||
Now \mzninline{s} is not 1, and \mzninline{b1} will be set to
|
||||
\mzninline{true}. The \mzninline{float_random} propagator assigns
|
||||
\mzninline{rnd1} a new random value and, depending on whether it is greater
|
||||
than \mzninline{0.2}, the Boolean variables \mzninline{b2}, and consequently
|
||||
\mzninline{b3} will be assigned. If it is \mzninline{true}, the constraint
|
||||
in line \lref{line:6:x1:end} will become active and assign \mzninline{x[1]}
|
||||
to its value in the previous solution.
|
||||
|
||||
Furthermore, it is not strictly necessary to guard \mzninline{int_uniform}
|
||||
against being invoked before \mzninline{status()!=START}, since the
|
||||
\mzninline{sol} constraints will simply not propagate anything in case no
|
||||
solution has been recorded yet, but we use this simple example to illustrate
|
||||
how these Boolean conditions are compiled and evaluated.
|
||||
|
@ -9,6 +9,7 @@ DIV=calc,
|
||||
|
||||
\input{assets/packages}
|
||||
\input{assets/layout}
|
||||
\input{assets/shorthands}
|
||||
|
||||
% Bibliography preamble
|
||||
\addbibresource{assets/bibliography/references.bib}
|
||||
|
Reference in New Issue
Block a user