From 6a5fe8d077f359b7734bb3e4258ece73bd928a1e Mon Sep 17 00:00:00 2001 From: "Jip J. Dekker" Date: Wed, 10 Feb 2021 13:58:42 +1100 Subject: [PATCH] Add initial incremental section from Abstract Machine paper --- assets/bibliography/references.bib | 141 +++++++++++ assets/glossary.tex | 8 + assets/img/4_comparememory.pdf | Bin 0 -> 10284 bytes assets/img/4_compareruntime.pdf | Bin 0 -> 9452 bytes assets/img/6_gbac.png | Bin 0 -> 23554 bytes assets/img/6_radiation.png | Bin 0 -> 28862 bytes assets/mzn/6_abs_reif_result.mzn | 4 + assets/mzn/6_abs_reif_result.mzntex | 6 + assets/mzn/6_abs_reif_trail.mzn | 14 ++ assets/mzn/6_abs_reif_trail.mzntex | 16 ++ assets/mzn/6_gbac_neighbourhood.mzn | 4 + assets/mzn/6_gbac_neighbourhood.mzntex | 6 + assets/mzn/6_incremental.mzn | 2 + assets/mzn/6_incremental.mzntex | 4 + assets/mzn/6_sol_function.mzn | 8 + assets/mzn/6_sol_function.mzntex | 10 + assets/mzn/6_uniform_neighbourhood.mzn | 6 + assets/mzn/6_uniform_neighbourhood.mzntex | 8 + assets/packages.tex | 18 +- assets/shorthands.tex | 2 + chapters/4_rewriting.tex | 67 ++++++ chapters/6_incremental.tex | 278 ++++++++++++++++++++-- 22 files changed, 574 insertions(+), 28 deletions(-) create mode 100644 assets/img/4_comparememory.pdf create mode 100644 assets/img/4_compareruntime.pdf create mode 100644 assets/img/6_gbac.png create mode 100644 assets/img/6_radiation.png create mode 100644 assets/mzn/6_abs_reif_result.mzn create mode 100644 assets/mzn/6_abs_reif_result.mzntex create mode 100644 assets/mzn/6_abs_reif_trail.mzn create mode 100644 assets/mzn/6_abs_reif_trail.mzntex create mode 100644 assets/mzn/6_gbac_neighbourhood.mzn create mode 100644 assets/mzn/6_gbac_neighbourhood.mzntex create mode 100644 assets/mzn/6_incremental.mzn create mode 100644 assets/mzn/6_incremental.mzntex create mode 100644 assets/mzn/6_sol_function.mzn create mode 100644 assets/mzn/6_sol_function.mzntex create mode 100644 assets/mzn/6_uniform_neighbourhood.mzn create mode 100644 assets/mzn/6_uniform_neighbourhood.mzntex diff --git a/assets/bibliography/references.bib b/assets/bibliography/references.bib index 2312d46..93e0d3c 100644 --- a/assets/bibliography/references.bib +++ b/assets/bibliography/references.bib @@ -1,3 +1,37 @@ +@article{baatar-2011-radiation, + author = {Davaatseren Baatar and Natashia Boland and Sebastian Brand + and Peter J. Stuckey}, + title = {{CP} and {IP} approaches to cancer radiotherapy delivery + optimization}, + journal = {Constraints An Int. J.}, + volume = 16, + number = 2, + pages = {173--194}, + year = 2011, + url = {https://doi.org/10.1007/s10601-010-9104-1}, + doi = {10.1007/s10601-010-9104-1}, + timestamp = {Fri, 13 Mar 2020 10:58:27 +0100}, + biburl = {https://dblp.org/rec/journals/constraints/BaatarBBS11.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@article{chiarandini-2012-gbac, + author = {Marco Chiarandini and Luca Di Gaspero and Stefano Gualandi + and Andrea Schaerf}, + title = {The balanced academic curriculum problem revisited}, + journal = {J. Heuristics}, + volume = 18, + number = 1, + pages = {119--148}, + year = 2012, + url = {https://doi.org/10.1007/s10732-011-9158-2}, + doi = {10.1007/s10732-011-9158-2}, + timestamp = {Fri, 30 Nov 2018 13:23:27 +0100}, + biburl = + {https://dblp.org/rec/journals/heuristics/ChiarandiniGGS12.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + @article{freuder-1997-holygrail, author = {Eugene C. Freuder}, title = {In Pursuit of the Holy Grail}, @@ -13,6 +47,51 @@ bibsource = {dblp computer science bibliography, https://dblp.org} } +@inproceedings{hebrard-2005-diverse, + author = {Emmanuel Hebrard and Brahim Hnich and Barry O'Sullivan and + Toby Walsh}, + editor = {Manuela M. Veloso and Subbarao Kambhampati}, + title = {Finding Diverse and Similar Solutions in Constraint + Programming}, + booktitle = {Proceedings, The Twentieth National Conference on + Artificial Intelligence and the Seventeenth Innovative + Applications of Artificial Intelligence Conference, July 9-13, + 2005, Pittsburgh, Pennsylvania, {USA}}, + pages = {372--377}, + publisher = {{AAAI} Press / The {MIT} Press}, + year = 2005, + url = {http://www.aaai.org/Library/AAAI/2005/aaai05-059.php}, + timestamp = {Mon, 10 Dec 2012 15:34:42 +0100}, + biburl = {https://dblp.org/rec/conf/aaai/HebrardHOW05.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@book{jaillet-2021-online, + title = {Online Optimization}, + author = {Jaillet, P. and Wagner, M.R.}, + isbn = 9780387717715, + series = {International Series in Operations Research \& Management + Science}, + year = 2021, + publisher = {Springer US} +} + +@article{jones-2002-multi-objective, + author = {Dylan F. Jones and S. Keyvan Mirrazavi and Mehrdad Tamiz}, + title = {Multi-objective meta-heuristics: An overview of the current + state-of-the-art}, + journal = {Eur. J. Oper. Res.}, + volume = 137, + number = 1, + pages = {1--9}, + year = 2002, + url = {https://doi.org/10.1016/S0377-2217(01)00123-0}, + doi = {10.1016/S0377-2217(01)00123-0}, + timestamp = {Fri, 21 Feb 2020 13:15:05 +0100}, + biburl = {https://dblp.org/rec/journals/eor/JonesMT02.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + @book{marriott-1998-clp, location = {Cambridge, Mass}, title = {Programming with constraints: an introduction}, @@ -97,6 +176,60 @@ bibsource = {dblp computer science bibliography, https://dblp.org} } +@article{schiendorfer-2018-minibrass, + author = {Alexander Schiendorfer and Alexander Knapp and Gerrit + Anders and Wolfgang Reif}, + title = {MiniBrass: Soft constraints for MiniZinc}, + journal = {Constraints An Int. J.}, + volume = 23, + number = 4, + pages = {403--450}, + year = 2018, + url = {https://doi.org/10.1007/s10601-018-9289-2}, + doi = {10.1007/s10601-018-9289-2}, + timestamp = {Mon, 26 Oct 2020 09:00:47 +0100}, + biburl = + {https://dblp.org/rec/journals/constraints/SchiendorferKAR18.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@article{schrijvers-2013-combinators, + author = {Tom Schrijvers and Guido Tack and Pieter Wuille and Horst + Samulowitz and Peter J. Stuckey}, + title = {Search combinators}, + journal = {Constraints An Int. J.}, + volume = 18, + number = 2, + pages = {269--305}, + year = 2013, + url = {https://doi.org/10.1007/s10601-012-9137-8}, + doi = {10.1007/s10601-012-9137-8}, + timestamp = {Fri, 13 Mar 2020 10:58:29 +0100}, + biburl = + {https://dblp.org/rec/journals/constraints/SchrijversTWSS13.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@inproceedings{shaw-1998-local-search, + author = {Paul Shaw}, + editor = {Michael J. Maher and Jean{-}Francois Puget}, + title = {Using Constraint Programming and Local Search Methods to + Solve Vehicle Routing Problems}, + booktitle = {Principles and Practice of Constraint Programming - CP98, + 4th International Conference, Pisa, Italy, October 26-30, + 1998, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = 1520, + pages = {417--431}, + publisher = {Springer}, + year = 1998, + url = {https://doi.org/10.1007/3-540-49481-2_30}, + doi = {10.1007/3-540-49481-2_30}, + timestamp = {Tue, 14 May 2019 10:00:45 +0200}, + biburl = {https://dblp.org/rec/conf/cp/Shaw98.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}, @@ -125,3 +258,11 @@ biburl = {https://dblp.org/rec/conf/cpaior/StuckeyT13.bib}, bibsource = {dblp computer science bibliography, https://dblp.org} } + +@article{warren-1983-wam, + title = {An abstract Prolog instruction set}, + author = {Warren, David HD}, + journal = {Technical note 309}, + year = 1983, + publisher = {SRI International} +} diff --git a/assets/glossary.tex b/assets/glossary.tex index 9fdf8e2..53ba33c 100644 --- a/assets/glossary.tex +++ b/assets/glossary.tex @@ -21,6 +21,10 @@ name={Flat\-Zinc}, description={TODO}, } +\newglossaryentry{microzinc}{ + name={Micro\-Zinc}, + description={TODO}, +} \newglossaryentry{minisearch}{ name={Mini\-Search}, description={TODO}, @@ -29,6 +33,10 @@ name={Mini\-Zinc}, description={TODO}, } +\newglossaryentry{nanozinc}{ + name={Nano\-Zinc}, + description={TODO}, +} \newglossaryentry{solver}{ name={solver}, description={TODO}, diff --git a/assets/img/4_comparememory.pdf b/assets/img/4_comparememory.pdf new file mode 100644 index 0000000000000000000000000000000000000000..73c2a32dd4bf1aa5a4413fb3f4b1a97826980a13 GIT binary patch literal 10284 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 UaYX#ijF6BZKY*TIR!t7@KVIQrd;kCd literal 0 HcmV?d00001 diff --git a/assets/img/4_compareruntime.pdf b/assets/img/4_compareruntime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bd1ad7a0109ec07cc87c5c03b5744b74f803aaf9 GIT binary patch literal 9452 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 literal 0 HcmV?d00001 diff --git a/assets/img/6_gbac.png b/assets/img/6_gbac.png new file mode 100644 index 0000000000000000000000000000000000000000..8b2fab966cc848110546723e3634a46a5a2733da GIT binary patch literal 23554 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 X!AOwMA0Vg0z{kYM;$-;==ji_d@>any literal 0 HcmV?d00001 diff --git a/assets/img/6_radiation.png b/assets/img/6_radiation.png new file mode 100644 index 0000000000000000000000000000000000000000..ce5d16f31e25f8d68ac2d73bdfca64edafc33625 GIT binary patch literal 28862 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 U>^zg4JOlUvt^Z(^=j|W (period_of[i] == sol[i]) +); diff --git a/assets/mzn/6_gbac_neighbourhood.mzntex b/assets/mzn/6_gbac_neighbourhood.mzntex new file mode 100644 index 0000000..2a4bb3c --- /dev/null +++ b/assets/mzn/6_gbac_neighbourhood.mzntex @@ -0,0 +1,6 @@ +\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}{random\PYZus{}allocation}\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}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{sol}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{=} +\PY{k}{forall}\PY{p}{(}\PY{n+nv}{i}\PY{l+s}{ }\PY{o}{in}\PY{l+s}{ }\PY{n+nv}{courses}\PY{g+gr}{)}\PY{l+s}{ }\PY{p}{(} +\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{p}{(}\PY{n+nf}{uniform}\PY{p}{(}\PY{l+m}{0,99}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{\PYZlt{}}\PY{l+s}{ }\PY{l+m}{80}\PY{g+gr}{)}\PY{l+s}{ }\PY{o}{\PYZhy{}\PYZgt{}}\PY{l+s}{ }\PY{p}{(}\PY{n+nv}{period\PYZus{}of}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{l+s}{ }\PY{o}{==}\PY{l+s}{ }\PY{n+nv}{sol}\PY{p}{[}\PY{n+nv}{i}\PY{g+gr}{]}\PY{g+gr}{)} +\PY{g+gr}{)}\PY{p}{;} +\end{BVerbatim} diff --git a/assets/mzn/6_incremental.mzn b/assets/mzn/6_incremental.mzn new file mode 100644 index 0000000..0b4775a --- /dev/null +++ b/assets/mzn/6_incremental.mzn @@ -0,0 +1,2 @@ +constraint x < 10; +constraint y < x; diff --git a/assets/mzn/6_incremental.mzntex b/assets/mzn/6_incremental.mzntex new file mode 100644 index 0000000..dd0b0c7 --- /dev/null +++ b/assets/mzn/6_incremental.mzntex @@ -0,0 +1,4 @@ +\begin{BVerbatim}[commandchars=\\\{\},numbers=left,firstnumber=1,stepnumber=1,codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}] +\PY{k}{constraint}\PY{l+s}{ }\PY{n+nv}{x}\PY{l+s}{ }\PY{o}{\PYZlt{}}\PY{l+s}{ }\PY{l+m}{10}\PY{p}{;} +\PY{k}{constraint}\PY{l+s}{ }\PY{n+nv}{y}\PY{l+s}{ }\PY{o}{\PYZlt{}}\PY{l+s}{ }\PY{n+nv}{x}\PY{p}{;} +\end{BVerbatim} diff --git a/assets/mzn/6_sol_function.mzn b/assets/mzn/6_sol_function.mzn new file mode 100644 index 0000000..9086230 --- /dev/null +++ b/assets/mzn/6_sol_function.mzn @@ -0,0 +1,8 @@ +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; diff --git a/assets/mzn/6_sol_function.mzntex b/assets/mzn/6_sol_function.mzntex new file mode 100644 index 0000000..95b1ce5 --- /dev/null +++ b/assets/mzn/6_sol_function.mzntex @@ -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}{int\PYZus{}sol}\PY{p}{(}\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}{var}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{xi}\PY{g+gr}{)}\PY{p}{;} +\PY{k}{function}\PY{l+s}{ }\PY{k+kt}{int}\PY{p}{:}\PY{l+s}{ }\PY{n+nf}{sol}\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{l+s}{ }\PY{o}{=} +\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{if}\PY{l+s}{ }\PY{n+nb}{is\PYZus{}fixed}\PY{p}{(}\PY{n+nv}{x}\PY{g+gr}{)}\PY{l+s}{ }\PY{k}{then}\PY{l+s}{ }\PY{n+nb}{fix}\PY{p}{(}\PY{n+nv}{x}\PY{g+gr}{)} +\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{else}\PY{l+s}{ }\PY{k}{let}\PY{l+s}{ }\PY{p}{\PYZob{}} +\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{n+nb}{lb}\PY{p}{(}\PY{n+nv}{x}\PY{g+gr}{)}\PY{l+s}{.}\PY{l+s}{.}\PY{n+nb}{ub}\PY{p}{(}\PY{n+nv}{x}\PY{g+gr}{)}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{xi}\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{k}{constraint}\PY{l+s}{ }\PY{n+nf}{int\PYZus{}sol}\PY{p}{(}\PY{n+nv}{x}\PY{p}{,}\PY{n+nv}{xi}\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}{xi}\PY{p}{;} +\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{l+s}{ }\PY{k}{endif}\PY{p}{;} +\end{BVerbatim} diff --git a/assets/mzn/6_uniform_neighbourhood.mzn b/assets/mzn/6_uniform_neighbourhood.mzn new file mode 100644 index 0000000..650360a --- /dev/null +++ b/assets/mzn/6_uniform_neighbourhood.mzn @@ -0,0 +1,6 @@ +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; diff --git a/assets/mzn/6_uniform_neighbourhood.mzntex b/assets/mzn/6_uniform_neighbourhood.mzntex new file mode 100644 index 0000000..7aef44b --- /dev/null +++ b/assets/mzn/6_uniform_neighbourhood.mzntex @@ -0,0 +1,8 @@ +\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}{float\PYZus{}uniform}\PY{p}{(}\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{n+nv}{l}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{u}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{r}\PY{g+gr}{)}\PY{p}{;} +\PY{k}{function}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nf}{uniform\PYZus{}nbh}\PY{p}{(}\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{l}\PY{p}{,}\PY{l+s}{ }\PY{k+kt}{var}\PY{l+s}{ }\PY{k+kt}{float}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{u}\PY{g+gr}{)}\PY{l+s}{ }\PY{p}{:}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{impure}\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{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{n+nb}{lb}\PY{p}{(}\PY{n+nv}{l}\PY{g+gr}{)}\PY{l+s}{.}\PY{l+s}{.}\PY{n+nb}{ub}\PY{p}{(}\PY{n+nv}{u}\PY{g+gr}{)}\PY{p}{:}\PY{l+s}{ }\PY{n+nv}{rnd}\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{k}{constraint}\PY{l+s}{ }\PY{n+nf}{float\PYZus{}uniform}\PY{p}{(}\PY{n+nv}{l}\PY{p}{,}\PY{n+nv}{u}\PY{p}{,}\PY{n+nv}{rnd}\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}{rnd}\PY{p}{;} +\end{BVerbatim} diff --git a/assets/packages.tex b/assets/packages.tex index 3c0fadb..e4c26fe 100644 --- a/assets/packages.tex +++ b/assets/packages.tex @@ -36,6 +36,8 @@ ItalicFont=*-Italic, BoldItalicFont=*-BoldItalic, ] %% Mathmatical font +\usepackage{amsmath} +\usepackage{amssymb} \usepackage{unicode-math} \setmathfont{GFSNeohellenicMath.otf} @@ -47,10 +49,19 @@ style=apa, % Glossary / Acronyms \usepackage[acronym,toc]{glossaries} -\glsdisablehyper +\glsdisablehyper{} \defglsentryfmt[main]{\ifglsused{\glslabel}{\glsgenentryfmt}{\textit{\glsgenentryfmt}}} \makeglossaries{} +% Graphics +\usepackage{graphicx} +\usepackage{subcaption} + +% Example environment +\newcounter{example}[chapter] +\newenvironment{example}[1][]{\refstepcounter{example}\par\medskip \noindent + \textbf{Example~\theexample. #1} \rmfamily}{\hfill \ensuremath{\square}} + % Code formatting \usepackage{fancyvrb} \usepackage{color} @@ -61,11 +72,12 @@ type=listing, float, name=Listing, counterwithin=chapter, -atbegin={% +listname={List of Source Listings}, +atbegin={ \centering \scriptsize } -]{program} +]{listing} \crefname{listing}{listing}{listings} \newcommand{\Vlabel}[1]{\label[line]{#1}\hypertarget{#1}{}} diff --git a/assets/shorthands.tex b/assets/shorthands.tex index 27aecaa..90d0939 100644 --- a/assets/shorthands.tex +++ b/assets/shorthands.tex @@ -1,4 +1,6 @@ \newcommand{\eg}{e.g.} \newcommand{\flatzinc}{\gls{flatzinc}} +\newcommand{\microzinc}{\gls{microzinc}} \newcommand{\minisearch}{\gls{minisearch}} \newcommand{\minizinc}{\gls{minizinc}} +\newcommand{\nanozinc}{\gls{nanozinc}} diff --git a/chapters/4_rewriting.tex b/chapters/4_rewriting.tex index 0f1c14d..3cc87c7 100644 --- a/chapters/4_rewriting.tex +++ b/chapters/4_rewriting.tex @@ -1,3 +1,70 @@ %************************************************ \chapter{Rewriting Constraint Modelling Languages}\label{ch:rewriting} %************************************************ + +\section{Experiments} + +We have created a prototype implementation of the architecture presented in the +preceding sections. It consists of a compiler from \minizinc\ to \microzinc, and +an incremental \microzinc\ interpreter producing \nanozinc. The system supports +a significant subset of the full \minizinc\ language; notable features that are +missing are support for set and float variables, option types, and compilation +of model output expressions and annotations. We will release our implementation +under an open-source license and can make it available to the reviewers upon +request. + +The implementation is not optimised for performance yet, but was created as a +faithful implementation of the developed concepts, in order to evaluate their +suitability and provide a solid baseline for future improvements. In the +following we present experimental results on basic flattening performance as +well as incremental flattening and solving that demonstrate the efficiency +gains that are possible thanks to the new architecture. + +\subsection{Basic Flattening} + +As a first experiment, we selected 20 models from the annual \minizinc\ +challenge and compiled 5 instances of each model to \flatzinc, using the current +\minizinc\ release version 2.4.3 and the new prototype system. In both cases we +use the standard \minizinc\ library of global constraints (i.e., we decompose +those constraints rather than using solver built-ins, in order to stress-test +the flattening). We measured pure flattening time, i.e., without time required +to parse and typecheck in version 2.4.3, and without time required for +compilation to \microzinc\ in the new system (compilation is usually very fast). +Times are averages of 10 runs. \footnote{All models obtained from + \url{https://github.com/minizinc/minizinc-benchmarks}: + \texttt{\justify{}accap, amaze, city-position, community-detection, + depot-placement, freepizza, groupsplitter, kidney-exchange, median-string, + multi-knapsack, nonogram, nside, problem, rcpsp-wet, road-cons, roster, + stack-cuttingstock, steelmillslab, train, triangular, zephyrus}.} + +\Cref{sfig:compareruntime} compares the flattening time for each of the 100 +instances. Points below the line indicate that the new system is faster. On +average, the new system achieves a speed-up of $2.3$, with very few instances +not achieving any speedup. In terms of memory performance +(\Cref{sfig:comparemem}), version 2.4.3 can sometimes still outperform the new +prototype. We have identified that the main memory bottlenecks are our currently +unoptimised implementations of CSE lookup tables and argument vectors. + +These are very encouraging results, given that we are comparing a largely +unoptimised prototype to a mature piece of software. + +\begin{figure}[t] + \centering + \begin{subfigure}[b]{.48\columnwidth} + \centering + \includegraphics[width=\columnwidth]{assets/img/4_compareruntime} + \caption{flattening run time (ms)} + \label{sfig:compareruntime} + \end{subfigure}% + \hspace{0.04\columnwidth}% + \begin{subfigure}[b]{.48\columnwidth} + \centering + \includegraphics[width=\columnwidth]{assets/img/4_comparememory} + \caption{flattening memory (MB)} + \label{sfig:comparemem} + \end{subfigure} + \caption{Performance on flattening 100 MiniZinc Challenge instances. + \minizinc\ 2.4.3 (x-axis) vs new architecture (y-axis), log-log plot. Dots + below the line indicate the new system is better.} + \label{fig:runtime} +\end{figure} diff --git a/chapters/6_incremental.tex b/chapters/6_incremental.tex index ffe433e..d0d13fa 100644 --- a/chapters/6_incremental.tex +++ b/chapters/6_incremental.tex @@ -1,6 +1,250 @@ -\chapter{Incremental Solving}\label{ch:incremental} +\chapter{Incremental Processing}\label{ch:incremental} %************************************************ +Many applications require solving almost the same combinatorial problem +repeatedly, with only slight modifications, thousands of times. For example: + +\begin{itemize} + \item Multi-objective problems~\autocite{jones-2002-multi-objective} are often + not supported directly in solvers. They can be solved using a + meta-search approach: find a solution to a (single-objective) problem, + then add more constraints to the original problem and repeat. + \item Large Neighbourhood Search~\autocite{shaw-1998-local-search} is a very + successful meta-heuristic. After finding a (sub-optimal) solution to a + problem, constraints are added to restrict the search in the + neighbourhood of that solution. When a new solution is found, the + constraints are removed, and constraints for a new neighbourhood are + added. + \item In Online Optimisation~\autocite{jaillet-2021-online}, a problem + instance is continuously updated with new data, such as newly available + jobs to be scheduled or customer requests to be processed. + \item Diverse Solution Search~\autocite{hebrard-2005-diverse} aims at + providing a set of solutions that are sufficiently different from each + other, in order to give human decision makers an overview of the + solution space. Diversity can be achieved by repeatedly solving a + problem instance with different objectives. + \item In Interactive Search~\autocite{}, a user provides feedback + on decisions made by the solver. The feedback is added back into the + problem, and a new solution is generated. Users may also take back some + earlier feedback and explore different aspects of the problem. +\end{itemize} + +All of these examples have in common that a problem instance is solved, new +constraints are added, the resulting instance is solved again, and constraints +may be removed again. + +The usage of these methods is not new to \minizinc\ and they have proven to be +very useful \autocite{rendl-2015-minisearch, schrijvers-2013-combinators, + dekker-2018-mzn-lns, schiendorfer-2018-minibrass}. In its most basic form, a +simple scripting language is sufficient to implement these methods, by +repeatedly calling on \minizinc\ to flatten and solve the updated problems. +While the techniques presented so far in this paper should already improve the +performance of these approaches, the overhead of re-flattening an almost +identical model may still prove prohibitive, warranting direct support for +adding and removing constraints in the \minizinc\ abstract machine. In this +section, we will see that our proposed architecture can be made +\emph{incremental}, significantly improving efficiency for these iterative +solving approaches. + +\section{Incremental Flattening} + +In order to support incremental flattening, the \nanozinc\ interpreter must be +able to process \nanozinc\ calls \emph{added} to an existing \nanozinc\ program, +as well as to \emph{remove} calls from an existing \nanozinc\ program. Adding new +calls is straightforward, since \nanozinc\ is already processed call-by-call. + +Removing a call, however, is not so simple. When we remove a call, all effects +the call had on the \nanozinc\ program have to be undone, including results of +propagation, CSE and other simplifications. + +\begin{example}\label{ex:6-incremental} +Consider the following \minizinc\ fragment: + +\highlightfile{assets/mzn/6_incremental.mzn} + +After evaluating the first constraint, the domain of \mzninline{x} is changed to +be less than 10. Evaluating the second constraint causes the domain of +\mzninline{y} to be less than 9. If we now, however, try to remove the first +constraint, it is not just the direct inference on the domain of \mzninline{x} +that has to be undone, but also any further effects of those changes -- in this +case, the changes to the domain of \mzninline{y}. +\end{example} + +Due to this complex interaction between calls, we only support the removal of +calls in reverse chronological order, also known as \textit{backtracking}. The +common way of implementing backtracking is using a \textit{trail} data +structure~\autocite{warren-1983-wam}. The trail records all changes to the +\nanozinc\ program: + +\begin{itemize} + \item the addition or removal of new variables or constraints, + \item changes made to the domains of variables, + \item additions to the CSE table, and + \item substitutions made due to equality propagation. +\end{itemize} + +These changes can be caused by the evaluation of a call, propagation, or CSE. +When a call is removed, the corresponding changes can now be undone by +reversing any action recorded on the trail up to the point where the call was +added. + +In order to limit the amount of trailing required, the programmer must create +explicit \textit{choice points} to which the system state can be reset. In +particular, this means that if no choice point was created before the initial +model was flattened, then this flattening can be performed without any +trailing. + +\begin{example}\label{ex:6-trail} + Let us look again at the resulting \nanozinc\ code from \Cref{ex:absreif}: + + % \highlightfile{assets/mzn/6_abs_reif_result.mzn} + + Assume that we added a choice point before posting the constraint + \mzninline{c}. Then the trail stores the \emph{inverse} of all modifications + that were made to the \nanozinc\ as a result of \mzninline{c} (where + $\mapsfrom$ denotes restoring an identifier, and $\lhd$ \texttt{+}/\texttt{-} + respectively denote attaching and detaching constraints): + + % \highlightfile{assets/mzn/6_abs_reif_trail.mzn} + + To reconstruct the \nanozinc\ program at the choice point, we simply apply + the changes recorded in the trail, in reverse order. +\end{example} + +\section{Incremental Solving} + +Ideally, the incremental changes made by the interpreter would also be applied +incrementally to the solver. This requires the solver to support both the +dynamic addition and removal of variables and constraints. While some solvers +can support this functionality, most solvers have limitations. The system can +therefore support solvers with different levels of an incremental interface: + +\begin{itemize} + \item Using a non-incremental interface, the solver is reinitialised with the + updated \nanozinc\ program every time. In this case, we still get a + performance benefit from the improved flattening time, but not from + incremental solving. + \item Using a \textit{warm-starting} interface, the solver is reinitialised + with the updated program as above, but it is also given a previous solution + to initialise some internal data structures. In particular for mathematical + programming solvers, this can result in dramatic performance gains compared + to ``cold-starting'' the solver every time. + \item Using a fully incremental interface, the solver is instructed to apply + the changes made by the interpreter. In this case, the trail data structure + is used to compute the set of \nanozinc\ changes since the last choice + point. +\end{itemize} + +\section{Experiments} + +We have created a prototype implementation of the architecture presented in the +preceding sections. It consists of a compiler from \minizinc\ to \microzinc, and +an incremental \microzinc\ interpreter producing \nanozinc. The system supports +a significant subset of the full \minizinc\ language; notable features that are +missing are support for set and float variables, option types, and compilation +of model output expressions and annotations. We will release our implementation +under an open-source license and can make it available to the reviewers upon +request. + +The implementation is not optimised for performance yet, but was created as a +faithful implementation of the developed concepts, in order to evaluate their +suitability and provide a solid baseline for future improvements. In the +following we present experimental results on basic flattening performance as +well as incremental flattening and solving that demonstrate the efficiency +gains that are possible thanks to the new architecture. + +\subsection{Incremental Flattening and Solving} + +To demonstrate the advantage that the incremental processing of \minizinc\ +offers, we present a runtime evaluation of two meta-heuristics implemented using +our prototype interpreter. For both meta-heuristics, we evaluate the performance +of fully re-evaluating and solving the instance from scratch, compared to the +fully incremental evaluation and solving. The solving in both tests is performed +by the Gecode solver, version 6.1.2, connected using the fully incremental API. + +\paragraph{GBAC} +The Generalised Balanced Academic Curriculum (GBAC) problem +\autocite{chiarandini-2012-gbac} is comprised of scheduling the courses in a +curriculum subject to load limits on the number of courses for each period, +prerequisites for courses, and preferences of teaching periods by teaching +staff. It has been shown~\autocite{dekker-2018-mzn-lns} that Large Neighbourhood +Search (LNS) is a useful meta-heuristic for quickly finding high quality +solutions to this problem. In LNS, once an initial (sub-optimal) solution is +found, constraints are added to the problem that restrict the search space to a +\textit{neighbourhood} of the previous solution. After this neighbourhood has +been explored, the constraints are removed, and constraints for a different +neighbourhood are added. This is repeated until a sufficiently high solution +quality has been reached. + +We can model a neighbourhood in \minizinc\ as a predicate that, given the values +of the variables in the previous solution, posts constraints to restrict the +search. The following predicate defines a suitable neighbourhood for the GBAC +problem: + +\highlightfile{assets/mzn/6_gbac_neighbourhood.mzn} + +When this predicate is called with a previous solution \mzninline{sol}, then +every \mzninline{period_of} variable has an $80\%$ chance to be fixed to its +value in the previous solution. With the remaining $20\%$, the variable is +unconstrained and will be part of the search for a better solution. + +In a non-incremental architecture, we would re-flatten the original model plus +the neighbourhood constraint for each iteration of the LNS. In the incremental +\nanozinc\ architecture, we can easily express LNS as a repeated addition and +retraction of the neighbourhood constraints. We implemented both approaches +using the \nanozinc\ prototype, with the results shown in \Cref{fig:gbac}. The +incremental \nanozinc\ translation shows a 12x speedup compared to re-compiling +the model from scratch in each iteration. For this particular problem, +incrementality in the target solver (Gecode) does not lead to a significant +reduction in runtime. + +\begin{figure} + \centering + \includegraphics[width=0.5\columnwidth]{assets/img/6_gbac} + \caption{\label{fig:gbac}A run-time performance comparison between incremental + processing (Incr.) and re-evaluation (Redo) of 5 GBAC \minizinc\ instances + in the application of LNS on a 3.4 GHz Quad-Core Intel Core i5 using the + Gecode 6.1.2 solver. Each run consisted of 2500 iterations of applying + neighbourhood predicates. Reported times are averages of 10 runs.} +\end{figure} + +\paragraph{Radiation} +Our second experiment is based on a problem of planning cancer radiation therapy +treatment using multi-leaf collimators \autocite{baatar-2011-radiation}. Two +characteristics mark the quality of a solution: the amount of time the patient +is exposed to radiation, and the number of ``shots'' or different angles the +treatment requires. However, the first characteristic is considered more +important than the second. The problem therefore has a lexicographical +objective: a solution is better if it requires a strictly shorter exposure time, +or the same exposure time but a lower number of ``shots''. + +\minizinc\ solvers do not support lexicographical objectives directly, but we +can instead repeatedly solve a model instance and add a constraint to ensure +that the lexicographical objective improves. When the solver proves that no +better solution can be found, the last solution is known to be optimal. Given +two variables \mzninline{exposure} and \mzninline{shots}, once we have found a +solution with \mzninline{exposure=e} and \mzninline{shots=s}, we can add the +constraint \mzninline{exposure < e \/ (exposure = e /\ shots < s)}, expressing +the lexicographic ordering, and continue the search. Since each added +lexicographic constraint is strictly stronger than the previous one, we never +have to retract previous constraints. + +\begin{figure} + \centering + \includegraphics[width=0.5\columnwidth]{assets/img/6_radiation} + \caption{\label{fig:radiation}A run-time performance comparison between + incremental processing (Incr.) and re-evaluation (Redo) of 9 Radiation + \minizinc\ instances in the application of Lexicographic objectives on a 3.4 + GHz Quad-Core Intel Core i5 using the Gecode 6.1.2 solver. Each test was run + to optimality and was conducted 20 times to provide an average.} +\end{figure} + +As shown in \cref{fig:radiation}, the incremental processing of the added +\mzninline{lex_less} calls is a clear improvement over the re-evaluation of the +whole model. The translation shows a 13x speedup on average, and even the time +spent solving is reduced by 33\%. + + \section{Modelling of Neighbourhoods and Meta-heuristics} \label{section:2-modelling-nbhs} % @@ -38,8 +282,8 @@ extension is based on the constructs introduced in \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. +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 @@ -386,17 +630,9 @@ 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} + \highlightfile{assets/mzn/6_sol_function.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 @@ -423,19 +659,11 @@ Note that the function accepts variable arguments \mzninline{l} and 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} + \highlightfile{assets/mzn/6_uniform_neighbourhood.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