Experiments for incremental chapter

This commit is contained in:
Jip J. Dekker 2021-07-20 14:35:04 +10:00
parent 80b32f11e7
commit 584b9ef664
No known key found for this signature in database
GPG Key ID: 517DF4A00618C9C3
3 changed files with 205 additions and 228 deletions

View File

@ -46,6 +46,8 @@
\newacronym{ram}{RAM}{Random Access Memory}
\newacronym{rcpsp}{RCPSP}{Resource-Constrained Project Scheduling problem}
\newacronym{root}{\textit{root}}{root context}
\newacronym[see={[Glossary:]{gls-sat}}]{sat}{SAT\glsadd{gls-sat}}{Boolean Satisfiability}

View File

@ -1,23 +1,24 @@
%************************************************
\chapter{Incremental Processing}\label{ch:incremental}
\chapter{Incremental Constraint Modelling}\label{ch:incremental}
%************************************************
\glsreset{rbmo}
\glsreset{incremental-rewriting}
\input{chapters/5_incremental_preamble}
\section{Modelling of Restart Based Meta-Optimisation}\label{sec:6-modelling}
This section introduces a \minizinc{} extension that enables modellers to define \gls{meta-optimisation} methods in \minizinc{}.
This section introduces a \minizinc{} extension that enables modellers to define \gls{meta-optimisation} algorithms in \minizinc{}.
This extension is based on the construct introduced in \minisearch{} \autocite{rendl-2015-minisearch}, as summarised below.
\subsection{Meta-Optimisation in MiniSearch}\label{sec:6-minisearch}
\minisearch{} introduced a \minizinc{} extension that enables modellers to express \gls{meta-optimisation} inside a \minizinc{} model.
A \gls{meta-optimisation} method in \minisearch{} typically solves a given \minizinc{} model, performs some calculations on the solution, adds new \constraints{} and then solves again.
A \gls{meta-optimisation} algorithm in \minisearch{} typically solves a given \minizinc{} model, performs some calculations on the solution, adds new \constraints{} and then solves again.
Most \gls{meta-optimisation} definitions in \minisearch{} consist of two parts.
The first part is a declarative definition of any restriction to the \gls{search-space} that the \gls{meta-optimisation} method can apply, called a \gls{neighbourhood}.
The first part is a declarative definition of any restriction to the \gls{search-space} that the \gls{meta-optimisation} algorithm can apply, called a \gls{neighbourhood}.
In \minisearch{} these definitions can make use of the following function.
\begin{mzn}
@ -43,7 +44,7 @@ For example, \mzninline{uniform_neighbourhood(x, 0.2)} would result in each vari
\caption{\label{lst:6-lns-minisearch} A simple \gls{lns} \gls{meta-optimisation} implemented in \minisearch{}}
\end{listing}
The second part of a \minisearch{} \gls{meta-optimisation} is the \gls{meta-optimisation} method itself.
The second part of a \minisearch{} \gls{meta-optimisation} is the \gls{meta-optimisation} algorithm itself.
\Cref{lst:6-lns-minisearch} shows a basic \minisearch{} implementation of a basic \gls{lns}, called \mzninline{lns}.
It performs a fixed number of iterations, each invoking the \gls{neighbourhood} predicate \mzninline{uniform_neighbourhood} in a fresh scope.
This means that the \constraints{} only affect the current loop iteration.
@ -51,16 +52,16 @@ It then searches for a solution (\mzninline{minimize_bab}) with a given timeout.
If the search does return a new solution, then it commits to that solution and it becomes available to the \mzninline{sol} function in subsequent iterations.
The \mzninline{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.
Although \minisearch{} enables the modeller to express \glspl{neighbourhood} in a declarative way, the definition of the \gls{meta-optimisation} methods is rather unintuitive and difficult to debug, leading to unwieldy code for defining even simple methods.
Although \minisearch{} enables the modeller to express \glspl{neighbourhood} in a declarative way, the definition of the \gls{meta-optimisation} algorithm is rather unintuitive and difficult to debug, leading to unwieldy code for defining even simple algorithm.
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.
This leads to a significant communication overhead.
To address these two issues, we propose to keep modelling \glspl{neighbourhood} as predicates, but define \gls{meta-optimisation} methods from an imperative perspective.
To address these two issues, we propose to keep modelling \glspl{neighbourhood} as predicates, but define \gls{meta-optimisation} algorithm from an imperative perspective.
We define a few additional \minizinc{} \glspl{annotation} and functions that
\begin{itemize}
\item allow us to express important aspects of the meta-optimisation methods in a more convenient way,
\item allow us to express important aspects of the meta-optimisation algorithm in a more convenient way,
\item and enable a simple \gls{rewriting} scheme that requires no additional communication with and only small, simple extensions of the target \solver{}.
\end{itemize}
@ -100,13 +101,13 @@ Finally, the \mzninline{restart_limit} stops the search after a fixed number of
behaviour}
\end{listing}
\subsection{Advanced Meta-Optimisation Methods}
\subsection{Advanced Meta-Optimisation Algorithms}
Although using just a \gls{restart} \glspl{annotation} by themselves allows us to run the basic \gls{lns}, more advanced \gls{meta-optimisation} methods will require more than reapplying the same \gls{neighbourhood} time after time.
Although using just a \gls{restart} \glspl{annotation} by themselves allows us to run the basic \gls{lns}, more advanced \gls{meta-optimisation} algorithms will require more than reapplying the same \gls{neighbourhood} time after time.
It is, for example, often beneficial to use several \gls{neighbourhood} definitions within the same \instance{}.
Different \glspl{neighbourhood} may be able to improve different aspects of a \gls{sol} at different phases of the search.
Adaptive \gls{lns} \autocite{ropke-2006-adaptive, pisinger-2007-heuristic} is a variant of \gls{lns} that keeps track of the \glspl{neighbourhood} that led to improvements and favours them for future iterations.
This method has proven to be a highly successful approach to \gls{lns}.
This has proven to be a highly successful approach to \gls{lns}.
However, even a simpler scheme that applies several \glspl{neighbourhood} in a round-robin fashion can be effective.
In \minisearch{}, these adaptive or round-robin approaches can be implemented using ``state variables'', which support destructive update (overwriting the value they store).
@ -114,7 +115,7 @@ In this way, the \minisearch{} strategy can store values to be used in later ite
We use the ``\solver{} state'' instead.
All values are stored in normal \variables{}.
We then access them using two simple functions that reveal the solver state of the previous \gls{restart}.
This approach is sufficient for expressing many \gls{meta-optimisation} methods, and its implementation is much simpler.
This approach is sufficient for expressing many \gls{meta-optimisation} algorithms, and its implementation is much simpler.
\paragraph{State access and initialisation}
@ -193,7 +194,7 @@ For adaptive \gls{lns}, a simple strategy is to change the size of the \gls{neig
\subsection{Optimisation strategies}
The \gls{meta-optimisation} methods we have seen so far rely on the default behaviour of \minizinc{} \solvers{} to use a \gls{bnb} method for optimisation: when a new \gls{sol} is found, the \solver{} adds a \constraint{} to the remainder of the search to only accept better \glspl{sol}, as defined by the \gls{objective} in the \mzninline{minimize} or \mzninline{maximize} clause of the \mzninline{solve} item.
The \gls{meta-optimisation} algorithms we have seen so far rely on the default behaviour of \minizinc{} \solvers{} to use \gls{bnb} for optimisation: when a new \gls{sol} is found, the \solver{} adds a \constraint{} to the remainder of the search to only accept better \glspl{sol}, as defined by the \gls{objective} in the \mzninline{minimize} or \mzninline{maximize} clause of the \mzninline{solve} item.
When combined with \glspl{restart} and \gls{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.
@ -234,28 +235,12 @@ Using the same methods it is also possible to describe optimisation strategies w
An example of such a strategy is lexicographic search.
Lexicographic search can be employed when there is a strict order between the importance of different \variables{}.
It required that, once a \gls{sol} is found, each subsequent \gls{sol} must either improve the first \gls{objective}, or have the same value for the first \gls{objective} and improve the second \gls{objective}, or have the same value for the first two \glspl{objective} and improve the third \gls{objective}, and so on.
We can model this strategy using \gls{rbmo} as follows.
A predicate that implements lexicographic search is shown in \cref{lst:inc-lex-min}.
\begin{mzn}
predicate lex_minimize(array[int] of var int: o) =
let {
var min(index_set(o))..max(index_set(o))+1: stage;
} in if status() = START then
stage = min(index_set(o))
elseif status() = UNSAT then
stage = lastval(stage) + 1
else /* status() = SAT */
stage = lastval(stage)
/\ o[stage] < sol(o[stage])
endif
/\ _objective = o[stage];
/\ forall(i in min(index_set(o))..stage-1) (
o[i] = sol(o[i])
)
/\ if stage > max(index_set(o)) then
complete()
endif;
\end{mzn}
\begin{listing}
\mznfile{assets/listing/inc_lex_min.mzn}
\caption{\label{lst:inc-lex-min}A predicate implementing lexicographic search.}
\end{listing}
The lexicographic search changes the \gls{objective} at each stage in the evaluation.
Initially, the search is in stage one: it tries to find an \gls{opt-sol} for the first \gls{objective}.
@ -299,12 +284,12 @@ Otherwise, we record that we have one more \gls{sol}.
We store the \gls{sol} values in \mzninline{s1} and \mzninline{s2} \glspl{array}.
Before each \gls{restart} we add \constraints{} removing Pareto dominated \glspl{sol}, based on each previous \gls{sol}.
\section{Rewriting of Meta-Optimisation Methods}\label{sec:6-solver-extension}
\section{Rewriting of Meta-Optimisation Algorithms}\label{sec:6-solver-extension}
The \glspl{neighbourhood} defined in the previous section can be executed with \minisearch{} by adding support for the \mzninline{status} and \mzninline{last_val} built-in functions, and by defining the main \gls{restart} loop.
The \minisearch{} evaluator will then call a \solver{} to produce a \gls{sol}, and evaluate the \gls{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 \gls{rewriting} and solving separate, by embedding the entire \gls{meta-optimisation} method into the \gls{slv-mod}.
While this is a viable approach, our goal is to keep \gls{rewriting} and solving separate, by embedding the entire \gls{meta-optimisation} algorithms into the \gls{slv-mod}.
This section introduces such a \gls{rewriting} approach.
It only requires simple modifications of the \gls{rewriting} process, and the produced \gls{slv-mod} can be executed by standard \gls{cp} \solvers{} with a small set of simple extensions.
@ -320,7 +305,7 @@ This essentially \textbf{turns the new functions into \gls{native} \constraints{
The \gls{neighbourhood} predicate can then be added as a \constraint{} to the \gls{slv-mod}.
The evaluation is performed by hijacking the solver's own capabilities: It will automatically perform the evaluation of the new functions by propagating the \gls{native} \constraints{}.
To compile a \gls{meta-optimisation} method to a \gls{slv-mod}, the \gls{rewriting} process performs the following four simple steps.
To compile a \gls{meta-optimisation} algorithms to a \gls{slv-mod}, the \gls{rewriting} process performs the following four simple steps.
\begin{enumerate}
\item It replaces the annotation \mzninline{::on_restart("X")} with a call to predicate \mzninline{X}.
@ -391,7 +376,7 @@ We will now show the minimal extensions required from a \solver{} to interpret t
First, the \solver{} needs to parse and support the \gls{restart} \glspl{annotation} 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{last_val}, random number functions like \mzninline{float_uniform}, and \mzninline{complete}.
In addition, for the new \constraints{} the \solver{} is extended using the following methods.
In addition, for the new \constraints{} the \solver{} is extended using the following algorithms.
\begin{description}
\item[\mzninline{status(s)}] Record the status of the previous \gls{restart}, and fix \mzninline{s} to the recorded status.
@ -413,7 +398,7 @@ Typically, this means the solver must not propagate these \constraints{} until i
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 \gls{gecode} (214 new lines of code) and \gls{chuffed} (173 new lines of code).
For example, consider the model from \cref{lst:6-basic-complete} again that uses the following \gls{meta-optimisation} method.
For example, consider the model from \cref{lst:6-basic-complete} again that uses the following \gls{meta-optimisation} algorithms.
\begin{mzn}
basic_lns(uniform_neighbourhood(x, 0.2))}
@ -461,9 +446,10 @@ The \mzninline{sol} \constraints{} will simply not propagate anything in case no
\section{An Incremental Constraint Modelling Interface}%
\label{sec:6-incremental-compilation}
A universal approach to incremental solving methods and \gls{meta-optimisation} is to allow incremental changes to an \instance{} of a \cmodel{}.
A universal approach to the incremental usage of \cmls{}, and \gls{meta-optimisation}, is to allow incremental changes to an \instance{} of a \cmodel{}.
To solve these changing \instances{}, they have to be rewritten repeatedly to \glspl{slv-mod}.
In this section we extend our architecture with a incremental constraint modelling interface that allows the modeller to change an \instance{}, while minimising the required \gls{rewriting}.
In this section we extend our architecture with an incremental constraint modelling interface that allows the modeller to change an \instance{}.
For changes made using this interface, the architecture can employ \gls{incremental-rewriting} to minimise the required \gls{rewriting}.
As such, the \microzinc{} \interpreter{} is extended to be able \textbf{add} and \textbf{remove} \nanozinc{} \constraints{} from/to an existing \nanozinc{} program.
Adding new \constraints{} is straightforward.
@ -573,67 +559,158 @@ We therefore define the following three interfaces, using which we can apply the
\section{Experiments}\label{sec:inc-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.
In this section we present two experiments to test the efficiency and potency of the incremental methods introduced in this chapter.
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.
In our first experiment, we consider the effectiveness \gls{meta-optimisation} within during solving.
In particular, we investigate a round-robin \gls{lns} implemented using \gls{rbmo}.
On three different \minizinc{} models we compare this approach with solving the \instances{} directly using 2 different \solvers{}.
For one of the \solvers{}, we also compare with an oracle approach that can directly apply the exact same \gls{neighbourhood} as our \gls{rbmo}, without the need for computation.
As such, we show that the use of \gls{rbmo} introduces a insignificant computational overhead.
\subsection{Incremental Flattening and Solving}
Our second experiment compares the performance of using \minizinc{} incrementally.
We compare our two methods, \gls{rbmo} and the incremental constraint modelling interface, against the baseline of continuously \gls{rewriting} and reinitialising the \solver{}.
For this comparison compare the time that is required to (repeatedly) rewrite an \instance{} and the time required by the \solver{}.
The first model contains a lexicographic objective.
The second model is shared between the two experiments and uses a round-robin \gls{lns} approach.
We compare the application of a fixed number of \glspl{neighbourhood}.
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 \gls{gecode} \gls{solver}, version 6.1.2, connected using the fully incremental \gls{api}\@.
A description of the used computational environment, \minizinc{} instances, and versioned software has been included in \cref{ch:benchmarks}.
\paragraph{\glsentrytext{gbac}} The \glsaccesslong{gbac} problem \autocite{chiarandini-2012-gbac} consists 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 (\gls{lns}) is a useful meta-heuristic for quickly finding high quality solutions to this problem.
In \gls{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.
\subsection{Meta-Optimisation Solving}
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 \gls{gbac} problem:
We will now show that a solver that evaluates the rewritten \gls{meta-optimisation} specifications can (a) be effective and (b) incur only a small overhead compared to a dedicated implementation of the \glspl{neighbourhood}.
To measure the overhead, we implemented \gls{rbmo} in \gls{gecode} \autocite{gecode-2021-gecode}.
The resulting solver has been instrumented to also output the \domains{} of all \variables{} after propagating the new \gls{native} \constraints{}.
We implemented another extension to \gls{gecode} that simply reads the stream of \variable{} \domains{} for each \gls{restart}, essentially ``replaying'' the \gls{meta-optimisation} without incurring any overhead for evaluating the \glspl{neighbourhood} or handling the additional \variables{} and \constraints{}.
Note that this is a conservative estimate of the overhead: this extension has to perform less work than any real \gls{meta-optimisation} implementation.
In addition, we also present benchmark results for the standard release of \gls{gecode}; as well as the development version of \gls{chuffed}; and \gls{chuffed} performing \gls{rbmo}.
These experiments illustrate that the \gls{meta-optimisation} implementations indeed perform well compared to the standard \solvers{}.
We ran experiments for three models from the MiniZinc Challenge \autocite{stuckey-2010-challenge, stuckey-2014-challenge} (\texttt{gbac}, \texttt{steelmillslab}, and \texttt{rcpsp-wet}).
The \instances{} are rewritten using the \minizinc{} 2.5.5 \compiler{}, adjusted to rewrite \gls{rbmo} specifications.
For each model we use a round-robin \gls{lns} approach, shown in \cref{lst:6-round-robin}, of two \glspl{neighbourhood}: a \gls{neighbourhood} that destroys 20\% of the main \variables{} (\cref{lst:6-lns-minisearch-pred}) and a structured \gls{neighbourhood} for the model (described below).
For each solving method we show the cumulative integral of the objective values for all \instances{} of the model.
The underlying search strategy used is the fixed search strategy defined in the model.
The restart strategy uses the following \glspl{annotation}.
\begin{mzn}
predicate random_allocation(array[int] of int: sol) =
forall(i in courses) (
(uniform(0,99) < 80) -> (period_of[i] == sol[i])
);
predicate free_period() =
let {
int: period = uniform(periods)
} in forall(i in courses where sol(period_of[i]) != period) (
period_of[i] = sol(period_of[i])
);
::restart_constant(250) ::restart_on_solution
\end{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.
The benchmarks are repeated with 10 different random seeds and the average is shown.
The overall time out for each run is 120 seconds.
In a non-incremental architecture, we would re-flatten the original model plus the neighbourhood \constraint{} for each iteration of the \gls{lns}.
In the incremental \nanozinc\ architecture, we can easily express \gls{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:6-gbac}.
The incremental \nanozinc\ translation shows a 12x speedup compared to re-compiling the model from scratch in each iteration.
For this particular problem, incrementally instructing the target solver (\gls{gecode}) does not lead to a significant reduction in runtime.
\subsubsection{GBAC}%
\label{ssubsec:inc-exp-gbac1}
\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''.
The \gls{gbac} problem comprises courses having a specified number of credits and lasting a certain number of periods, load limits of courses for each period, prerequisites for courses, and preferences of teaching periods for professors.
A detailed description of the problem is given in \autocite{chiarandini-2012-gbac}.
The main decisions are to assign courses to periods, which is done via the \variables{} \mzninline{period_of} in the \minizinc{} model.
\cref{lst:6-free-period} shows the neighbourhood chosen, which randomly picks one period and frees all courses that are assigned to it.
\minizinc\ \glspl{solver} 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{}
\begin{listing}[b]
\mznfile{assets/listing/6_gbac_neighbourhood.mzn}
\caption{\label{lst:6-free-period}\gls{gbac}: \gls{neighbourhood} freeing all courses in a period.}
\end{listing}
\begin{mzn}
constraint exposure < e \/ (exposure = e /\ shots < s)
\end{mzn}
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_gecode_gbac.pdf}
\caption{\label{subfig:inc-obj-gecode-gbac}\gls{gecode}}
\end{subfigure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_chuffed_gbac.pdf}
\caption{\label{subfig:inc-obj-chuffed-gbac}\gls{chuffed}}
\end{subfigure}
\caption{\label{fig:inc-obj-gbac}\gls{gbac}: integral of cumulative objective value of solving 5 \instances{}.}
\end{figure}
\noindent{}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{}.
The result for the \gls{gbac} in \cref{fig:inc-obj-gbac} show that the overhead introduced by \gls{gecode} using \gls{rbmo} with regards to the replaying the \glspl{neighbourhood} is quite low.
The lines in the graph do not show any significant differences or delays.
Both their result are much better than the baseline \gls{gecode} \solver{}.
Since learning is not very effective for \gls{gbac}, the performance of \gls{chuffed} is similar to \gls{gecode}.
The use of \gls{lns} again significantly improves over standard \gls{chuffed}.
\subsubsection{Steel Mill Slab}
The steel mill slab design problem consists of cutting slabs into smaller ones, so that all orders are fulfilled while minimising the wastage.
The steel mill only produces slabs of certain sizes, and orders have both a size and a colour.
We have to assign orders to slabs, with at most two different colours on each slab.
The model uses the \variables{} \mzninline{assign} for deciding which order is assigned to which slab.
\Cref{lst:6-free-bin} shows a structured \gls{neighbourhood} that randomly selects a slab and frees the orders assigned to it in the incumbent \gls{sol}.
These orders can then be freely reassigned to any other slab.
\begin{listing}
\mznfile{assets/listing/6_steelmillslab_neighbourhood.mzn}
\caption{\label{lst:6-free-bin}Steel mill slab: \gls{neighbourhood} that frees
all orders assigned to a selected slab.}
\end{listing}
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_gecode_steelmillslab.pdf}
\caption{\label{subfig:inc-obj-gecode-steelmillslab}\gls{gecode}}
\end{subfigure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_chuffed_steelmillslab.pdf}
\caption{\label{subfig:inc-obj-chuffed-steelmillslab}\gls{chuffed}}
\end{subfigure}
\caption{\label{fig:inc-obj-steelmillslab}Steel mill slab: integral of cumulative objective value of solving 5 \instances{}.}
\end{figure}
\Cref{subfig:inc-obj-gecode-steelmillslab} again only show minimal overhead for the \gls{rbmo} compared to replaying the \glspl{neighbourhood}.
For this problem a solution with zero wastage is always optimal.
As such the \gls{lns} approaches are sometimes able to prove a \gls{sol} is optimal and might finish before the time out.
This is the case for \gls{chuffed} instances, where almost all \instances{} are solved using the \gls{rbmo} method.
As expected, the \gls{lns} approaches find better solutions quicker for \gls{gecode}.
However, We do see that, given enough time, baseline \gls{gecode} will eventually find better \glspl{sol}.
% RCPSP/wet
\subsubsection{RCPSP/wet}
The \gls{rcpsp} with Weighted Earliness and Tardiness cost, is a classic scheduling problem in which tasks need to be scheduled subject to precedence \constraints{} and cumulative resource restrictions.
The objective is to find an optimal schedule that minimises the weighted cost of the earliness and tardiness for tasks that are not completed by their proposed deadline.
The \variables{} in \gls{array} \mzninline{s} represent the start times of each task in the model.
\Cref{lst:6-free-timeslot} shows our structured \gls{neighbourhood} for this model.
It randomly selects a time interval of one-tenth the length of the planning horizon and frees all tasks starting in that time interval, which allows a reshuffling of these tasks.
\begin{listing}
\mznfile{assets/listing/6_rcpsp_neighbourhood.mzn}
\caption{\label{lst:6-free-timeslot}\Gls{rcpsp}/wet: \gls{neighbourhood} freeing
all tasks starting in the drawn interval.}
\end{listing}
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_gecode_rcpspw.pdf}
\caption{\label{subfig:inc-obj-gecode-rcpspw}\gls{gecode}}
\end{subfigure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_chuffed_rcpspw.pdf}
\caption{\label{subfig:inc-obj-chuffed-rcpspw}\gls{chuffed}}
\end{subfigure}
\caption{\label{fig:inc-obj-rcpspw}\gls{rcpsp}/wet: integral of cumulative objective value of solving 5 \instances{}.}
\end{figure}
\Cref{fig:inc-obj-rcpspw} shows once more that \gls{rbmo} has little overhead over the replaying approach.
These approaches perform significantly better than the baseline \gls{gecode} \solver{}.
The baseline \gls{chuffed} \solver{} performs well and improves its \gls{sol} longer than the baseline \gls{gecode} \solver{}.
However, \gls{lns} makes \gls{chuffed} much more robust.
\subsection{Incremental Rewriting and Solving}
To demonstrate the advantage that dedicated incremental methods for \minizinc{} offer, we present a runtime evaluation of two \gls{meta-optimisation} algorithms implemented using the two methods presented in this chapter.
We consider the use of lexicographic search and round-robin \gls{lns}, each evaluated on a different \minizinc{} model.
We compare our methods against a naive system that repeatedly programmatically changes an \instance{}, rewrites the full \instances{}, and starts a new \solver{} instance.
The solving in our tests is performed by the \gls{gecode} \gls{solver}.
When using our incremental interface, it is connected using the fully incremental \gls{api}.
The naive system and incremental interface use our architecture prototype to rewrite the \instances{}.
The \gls{rbmo} \instances{} are rewritten using the \minizinc{} 2.5.5 \compiler{}, adjusted to rewrite \gls{rbmo} specifications.
We compare the time that is required to (repeatedly) rewrite an \instance{} and the time taken by the \solver{}.
Each test is performed 10 times and the average time is shown.
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
@ -647,148 +724,46 @@ Since each added lexicographic \constraint{} is strictly stronger than the previ
\caption{\label{fig:inc-cmp} A comparison of the two new incremental techniques and a recompilation strategy.}
\end{figure}
As shown in \cref{fig:6-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\%.
\subsubsection{Radiation}
\subsection{Compiling neighbourhoods}
Our first model 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{} does not support lexicographical objectives directly, but a lexicographic search can be modelled in \minizinc{}, shown in \cref{lst:inc-lex-min}.
\todo{Decide what to do with these}
% Table column headings
\newcommand{\intobj}{\int}
\newcommand{\minobj}{\min}
\newcommand{\devobj}{\sigma}
\newcommand{\nodesec}{n/s}
\newcommand{\gecodeStd}{\textsf{gecode}}
\newcommand{\gecodeReplay}{\textsf{gecode-replay}}
\newcommand{\gecodeMzn}{\textsf{gecode-fzn}}
\newcommand{\chuffedStd}{\textsf{chuffed}}
\newcommand{\chuffedMzn}{\textsf{chuffed-fzn}}
The results are shown in \cref{subfig:inc-cmp-lex}.
They show that both incremental methods have a clear advantage over are naive baseline approach.
Although some additional time is spend \gls{rewriting} the \gls{rbmo} models compared to the incremental, it is minimal.
The \gls{rewriting} of the \gls{rbmo} \instances{} would likely take less time when using the new prototype architecture.
Between all the methods, solving time is very similar.
\gls{rbmo} seems to have a slight advantage.
No benefit can be noticed from the use of the incremental solver \gls{api}.
We will now show that a solver that evaluates the compiled \flatzinc\ \gls{lns} specifications can (a) be effective and (b) incur only a small overhead compared to a dedicated implementation of the neighbourhoods.
\subsubsection{GBAC}
To measure the overhead, we implemented our new approach in \gls{gecode}~\autocite{gecode-2021-gecode}.
The resulting solver (\gecodeMzn{} in the tables below) has been instrumented to also output the domains of all model variables after propagating the new special \constraints{}.
We implemented another extension to \gls{gecode} (\gecodeReplay) that simply reads the stream of variable domains for each restart, essentially replaying the \gls{lns} of \gecodeMzn\ without incurring any overhead for evaluating the neighbourhoods or handling the additional variables and \constraints{}.
Note that this is a conservative estimate of the overhead: \gecodeReplay\ has to perform less work than any real \gls{lns} implementation.
We now revisit the model and method from \cref{ssubsec:inc-exp-gbac1} and compare the efficiency of using round-robin \gls{lns}.
Instead setting a time limit, we limit the number of \glspl{restart} that the \solver{} makes.
As such, we limit the number of \glspl{neighbourhood} that are computed and applied to the \instance{}.
It should be noted that the \gls{rbmo} method is not guaranteed to apply the exact same \glspl{neighbourhood}, due to the difference in random number generator.
In addition, we also present benchmark results for the standard release of \gls{gecode} 6.0 without \gls{lns} (\gecodeStd); as well as \chuffedStd{}, the development version of \gls{chuffed}; and \chuffedMzn{}, \gls{chuffed} performing \gls{lns} with \flatzinc\ neighbourhoods.
These experiments illustrate that the \gls{lns} implementations indeed perform well compared to the standard solvers.
Details of the computational environment and resources used in our experiments are outlined in \cref{ch:benchmarks}.
{lns} benchmarks are repeated with 10 different random seeds and the average is shown.
The overall timeout for each run is 120 seconds.
\Cref{subfig:inc-cmp-lex} shows the results of applying 1000 \glspl{neighbourhood}.
In this case there is an even more pronounced difference between the incremental methods and the naive method.
It is surprising to see that the application of 1000 \glspl{neighbourhood} using \gls{incremental-rewriting}, still performs very similar to \gls{rewriting} the \gls{rbmo} method.
Again, solving times are similar between all method.
Once again we do not see any real advantage of the use of the incremental \solver{} \gls{api}.
The advantage in solve time using \gls{rbmo} is more pronounced here, but it is hard to draw conclusions since the \glspl{neighbourhood} of this method are not exactly the same.
We ran experiments for three models from the MiniZinc Challenge~\autocite{stuckey-2010-challenge, stuckey-2014-challenge} (\texttt{gbac}, \texttt{steelmillslab}, and \texttt{rcpsp-wet}).
The best objective found during the \minizinc\ Challenge is shown for every instance (\textbf{best known}).
\subsection{Summary}
For each solving method we measured the average integral of the model objective after finding the initial solution (\(\intobj\)), the average best objective found (\(\minobj\)), and the standard deviation of the best objective found in percentage (\%), which is shown as the superscript on \(\minobj\) when running \gls{lns}.
%and the average number of nodes per one second (\nodesec).
The underlying search strategy used is the fixed search strategy defined in the model.
For each model we use a round-robin evaluation (\cref{lst:6-round-robin}) of two neighbourhoods: a neighbourhood that destroys \(20\%\) of the main decision variables (\cref{lst:6-lns-minisearch-pred}) and a structured neighbourhood for the model (described below).
The restart strategy is
The results of our experiments show that there is a clear benefit from the use of incremental methods in \cmls{}.
\begin{mzn}
::restart_constant(250) ::restart_on_solution
\end{mzn}
The \gls{meta-optimisation} algorithms that can be applied using \gls{rbmo} show a significant improvement over the \solvers{} normal search.
It is shown this method is very efficient and does not under perform even when compared to a unrealistic version of the methods that do not require any computations.
\subsubsection{\texttt{gbac}}
% GBAC
\begin{listing}[b]
\mznfile{assets/listing/6_gbac_neighbourhood.mzn}
\caption{\label{lst:6-free-period}\texttt{gbac}: neighbourhood freeing all courses in a period.}
\end{listing}
The \gls{gbac} problem comprises courses having a specified number of credits and lasting a certain number of periods, load limits of courses for each period, prerequisites for courses, and preferences of teaching periods for professors.
A detailed description of the problem is given in~\autocite{chiarandini-2012-gbac}.
The main decisions are to assign courses to periods, which is done via the variables \mzninline{period_of} in the model.
\cref{lst:6-free-period} shows the neighbourhood chosen, which randomly picks one period and frees all courses that are assigned to it.
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_gecode_gbac.pdf}
\caption{\label{subfig:inc-obj-gecode-gbac}\gls{gecode}}
\end{subfigure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_chuffed_gbac.pdf}
\caption{\label{subfig:inc-obj-chuffed-gbac}\gls{chuffed}}
\end{subfigure}
\caption{\label{fig:inc-obj-gbac} \todo{GBAC benchmarks description}}
\end{figure}
The results for \texttt{gbac} in \cref{tab:6-gbac} show that the overhead introduced by \gecodeMzn\ w.r.t.
\gecodeReplay{} is quite low, and both their results are much better than the baseline \gecodeStd{}.
Since learning is not very effective for \gls{gbac}, the performance of \chuffedStd\ is inferior to \gls{gecode}.
However, \gls{lns} again significantly improves over standard \gls{chuffed}.
\subsubsection{\texttt{steelmillslab}}
\begin{listing}
\mznfile{assets/listing/6_steelmillslab_neighbourhood.mzn}
\caption{\label{lst:6-free-bin}\texttt{steelmillslab}: Neighbourhood that frees
all orders assigned to a selected slab.}
\end{listing}
The Steel Mill Slab design problem consists of cutting slabs into smaller ones, so that all orders are fulfilled while minimising the wastage.
The steel mill only produces slabs of certain sizes, and orders have both a size and a colour.
We have to assign orders to slabs, with at most two different colours on each slab.
The model uses the variables \mzninline{assign} for deciding which order is assigned to which slab.
\Cref{lst:6-free-bin} shows a structured neighbourhood that randomly selects a slab and frees the orders assigned to it in the incumbent solution.
These orders can then be freely reassigned to any other slab.
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_gecode_steelmillslab.pdf}
\caption{\label{subfig:inc-obj-gecode-steelmillslab}\gls{gecode}}
\end{subfigure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_chuffed_steelmillslab.pdf}
\caption{\label{subfig:inc-obj-chuffed-steelmillslab}\gls{chuffed}}
\end{subfigure}
\caption{\label{fig:inc-obj-steelmillslab} \todo{steelmillslab benchmarks description}}
\end{figure}
For this problem a solution with zero wastage is always optimal.
The use of \gls{lns} makes these instances easy, as all the \gls{lns} approaches find optimal solutions.
As \cref{tab:6-steelmillslab} shows, \gecodeMzn\ is again slightly slower than \gecodeReplay\ (the integral is slightly larger).
While \chuffedStd\ significantly outperforms \gecodeStd\ on this problem, once we use \gls{lns}, the learning in \chuffedMzn\ is not advantageous compared to \gecodeMzn\ or \gecodeReplay{}.
Still, \chuffedMzn\ outperforms \chuffedStd\ by always finding an optimal solution.
% RCPSP/wet
\subsubsection{\texttt{rcpsp-wet}}
\begin{listing}
\mznfile{assets/listing/6_rcpsp_neighbourhood.mzn}
\caption{\label{lst:6-free-timeslot}\texttt{rcpsp-wet}: Neighbourhood freeing
all tasks starting in the drawn interval.}
\end{listing}
The Resource-Constrained Project Scheduling problem with Weighted Earliness and Tardiness cost, is a classic scheduling problem in which tasks need to be scheduled subject to precedence \constraints{} and cumulative resource restrictions.
The objective is to find an optimal schedule that minimises the weighted cost of the earliness and tardiness for tasks that are not completed by their proposed deadline.
The decision variables in \gls{array} \mzninline{s} represent the start times of each task in the model.
\Cref{lst:6-free-timeslot} shows our structured neighbourhood for this model.
It randomly selects a time interval of one-tenth the length of the planning horizon and frees all tasks starting in that time interval, which allows a reshuffling of these tasks.
\begin{figure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_gecode_rcpspw.pdf}
\caption{\label{subfig:inc-obj-gecode-rcpspw}\gls{gecode}}
\end{subfigure}
\begin{subfigure}[b]{0.49\linewidth}
\includegraphics[width=\columnwidth]{assets/img/inc_obj_chuffed_rcpspw.pdf}
\caption{\label{subfig:inc-obj-chuffed-rcpspw}\gls{chuffed}}
\end{subfigure}
\caption{\label{fig:inc-obj-rcpspw} \todo{RCPSP-Wet benchmarks description}}
\end{figure}
\cref{tab:6-rcpsp-wet} shows that \gecodeReplay\ and \gecodeMzn\ perform almost identically, and substantially better than baseline \gecodeStd\ for these instances.
The baseline learning solver, \chuffedStd{}, is the best overall on the easy examples, but \gls{lns} makes it much more robust.
The poor performance of \chuffedMzn\ on the last instance is due to the fixed search, which limits the usefulness of no-good learning.
\subsubsection{Summary}
The results show that \gls{lns} outperforms the baseline solvers, except for benchmarks where we can quickly find and prove optimality.
However, the main result from these experiments is that the overhead introduced by our \flatzinc\ interface, when compared to an optimal \gls{lns} implementation, is relatively small.
We have additionally calculated the rate of search nodes explored per second and, across all experiments, \gecodeMzn\ achieves around 3\% fewer nodes per second than \gecodeReplay{}.
This overhead is caused by propagating the additional \constraints{} in \gecodeMzn{}.
Overall, the experiments demonstrate that the compilation approach is an effective and efficient way of adding \gls{lns} to a modelling language with minimal changes to the solver.
The incremental interface offers a great alternative when \solvers{} are not extended for \gls{rbmo}.
\Gls{incremental-rewriting} saves a significant amount of time, compared to repeatedly \gls{rewriting} the full \instance{}.
In our experiments, after the initial \gls{rewriting} of the \instance{} the additional \gls{rewriting} to apply a \gls{neighbourhood} often becomes insignificant compared to the time required by the \solver{}.
However, the incremental \solver{} \gls{api}, used in this approach, did not show any benefit.
Although we are still convinced of its usefulness, it was not visible in the results of our experiments.
It might be considered whether these use cases (or its implementation) limited its effect in any way, or whether its effect will be more pronounced in other types of \solvers{}, where more information can be saved.

View File

@ -1,5 +1,5 @@
\noindent{}In previous chapters we explored \gls{rewriting} as a definitive linear process, but to solve real-world problems \gls{meta-optimisation} algorithms are often used.
These methods usually require solving similar problems repeatedly, with only slight modifications, thousands of times.
These algorithms usually require solving similar problems repeatedly, with only slight modifications, thousands of times.
Examples of these methods are:
\begin{itemize}
@ -24,8 +24,8 @@ Examples of these methods are:
All of these examples have in common that a \instance{} is solved, new \constraints{} are added, the resulting \instance{} is solved again, and the \constraints{} may be removed again.
The usage of these methods is not new to \cmls{} and they have proven to be very useful \autocite{schrijvers-2013-combinators, rendl-2015-minisearch, schiendorfer-2018-minibrass, ek-2020-online, ingmar-2020-diverse}.
In its most basic form, a simple scripting language is sufficient to implement these methods, by repeatedly \gls{rewriting} and solving the adjusted \instances{}.
The usage of these algorithms is not new to \cmls{} and they have proven to be very useful \autocite{schrijvers-2013-combinators, rendl-2015-minisearch, schiendorfer-2018-minibrass, ek-2020-online, ingmar-2020-diverse}.
In its most basic form, a simple scripting language is sufficient to implement these algorithms, by repeatedly \gls{rewriting} and solving the adjusted \instances{}.
While improvements of the \gls{rewriting} process, such as the ones discussed in previous chapters, can increase the performance of these approaches, the overhead of rewriting an almost identical model may still prove prohibitive.
It warrants direct support from the \cml{} architecture.
In this chapter we introduce two methods to provide this support:
@ -36,7 +36,7 @@ In this chapter we introduce two methods to provide this support:
The \solver{} will then incrementally execute the methods through the use of \solver{} \glspl{restart}
This method avoids the need of repeatedly \gls{rewriting} the \instance{} all together.
\item Alternatively, we extend our architecture with an incremental interface for adding and removing \constraints{}.
Although this method does not avoid repeatedly \gls{rewriting} the \instance{}, the \gls{rewriting} is reduced to the changes to the \instance{}.
Although this method does not avoid repeatedly \gls{rewriting} the \instance{}, it uses \gls{incremental-rewriting} to reduce the \gls{rewriting} to the changes to the \instance{}.
This approach can be used when an incremental method cannot be described using \gls{rbmo} or when the required extensions are not available for the target \solver{}.
\end{itemize}