Small introduction and spell checking
This commit is contained in:
parent
87ff8426f3
commit
1ab2442c8d
@ -4,6 +4,7 @@
|
|||||||
\newacronym[see={[Glossary:]{gls-cse}}]{cse}{CSE\glsadd{gls-cse}}{Common Subexpression Elimination}
|
\newacronym[see={[Glossary:]{gls-cse}}]{cse}{CSE\glsadd{gls-cse}}{Common Subexpression Elimination}
|
||||||
\newacronym[see={[Glossary:]{gls-csp}}]{csp}{CSP\glsadd{gls-csp}}{Constraint Satisfaction Problem}
|
\newacronym[see={[Glossary:]{gls-csp}}]{csp}{CSP\glsadd{gls-csp}}{Constraint Satisfaction Problem}
|
||||||
\newacronym[see={[Glossary:]{gls-cop}}]{cop}{COP\glsadd{gls-cop}}{Constraint Optimisation Problem}
|
\newacronym[see={[Glossary:]{gls-cop}}]{cop}{COP\glsadd{gls-cop}}{Constraint Optimisation Problem}
|
||||||
|
\newacronym[see={[Glossary:]{gls-lcg}}]{lcg}{LCG\glsadd{gls-lcg}}{Lazy Clause Generation}
|
||||||
\newacronym[see={[Glossary:]{gls-lns}}]{lns}{LNS\glsadd{gls-lns}}{Large Neighbourhood Search}
|
\newacronym[see={[Glossary:]{gls-lns}}]{lns}{LNS\glsadd{gls-lns}}{Large Neighbourhood Search}
|
||||||
\newacronym[see={[Glossary:]{gls-mip}}]{mip}{MIP\glsadd{gls-mip}}{Mixed Integer Programming}
|
\newacronym[see={[Glossary:]{gls-mip}}]{mip}{MIP\glsadd{gls-mip}}{Mixed Integer Programming}
|
||||||
\newacronym[see={[Glossary:]{gls-sat}}]{sat}{SAT\glsadd{gls-sat}}{Boolean Satisfiability}
|
\newacronym[see={[Glossary:]{gls-sat}}]{sat}{SAT\glsadd{gls-sat}}{Boolean Satisfiability}
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
description={},
|
description={},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\newglossaryentry{chuffed}{
|
||||||
|
name={Chuffed},
|
||||||
|
description={},
|
||||||
|
}
|
||||||
|
|
||||||
\newglossaryentry{comprehension}{
|
\newglossaryentry{comprehension}{
|
||||||
name={comprehension},
|
name={comprehension},
|
||||||
description={},
|
description={},
|
||||||
@ -79,6 +84,10 @@
|
|||||||
description={},
|
description={},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\newglossaryentry{gecode}{
|
||||||
|
name={Gecode},
|
||||||
|
description={},
|
||||||
|
}
|
||||||
\newglossaryentry{generator}{
|
\newglossaryentry{generator}{
|
||||||
name={generator},
|
name={generator},
|
||||||
description={},
|
description={},
|
||||||
@ -104,6 +113,11 @@
|
|||||||
description={},
|
description={},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\newglossaryentry{gls-lcg}{
|
||||||
|
name={lazy clause generation},
|
||||||
|
description={},
|
||||||
|
}
|
||||||
|
|
||||||
\newglossaryentry{gls-lns}{
|
\newglossaryentry{gls-lns}{
|
||||||
name={large neighbourhood search},
|
name={large neighbourhood search},
|
||||||
description={},
|
description={},
|
||||||
|
@ -555,9 +555,48 @@ expressions in the \gls{solver} model.
|
|||||||
\section{The Current \glsentrytext{minizinc} Interpreter}%
|
\section{The Current \glsentrytext{minizinc} Interpreter}%
|
||||||
\label{sec:back-mzn-interpreter}
|
\label{sec:back-mzn-interpreter}
|
||||||
|
|
||||||
|
For version 2.5.5 of the \minizinc\ bundle, the \texttt{minizinc} executable is
|
||||||
|
officially provided tool to solve \minizinc\ instances. A modeller provides the
|
||||||
|
\texttt{minizinc} executable with a \minizinc\ model, the ground data required
|
||||||
|
to instantiate the model, and a \gls{solver} definition. Primarily the
|
||||||
|
\gls{solver} definition defines the \minizinc\ library used to flatten the
|
||||||
|
\minizinc\ instance and the way in which the \gls{solver} is to be executed. The
|
||||||
|
process of the \texttt{minizinc} executable can be categorised into the
|
||||||
|
following stages:
|
||||||
|
|
||||||
|
\begin{description}
|
||||||
|
\item[Parsing] \texttt{minizinc} parses the input data, the \minizinc\ model,
|
||||||
|
and the \gls{solver} library.
|
||||||
|
\item[Type checking] \texttt{minizinc} ensures the type consistency of the
|
||||||
|
\minizinc\ model, making sure that the types of all expressions match their
|
||||||
|
declarations and is allowed in the locations where they are used. \\ In the
|
||||||
|
process of type checking the model, all identifiers and calls are connected to
|
||||||
|
the declaration that they refer to.
|
||||||
|
\item[Flattening] \jip{TODO: This should have something}
|
||||||
|
\item[Optimisation] Given the generated \flatzinc{} model, \texttt{minizinc}
|
||||||
|
will try optimise this model to try and reduce the number of
|
||||||
|
\glspl{constraint} and size of the \glspl{domain} of \glspl{variable} in the
|
||||||
|
\flatzinc\ model.
|
||||||
|
\item[Solving] The optimised \flatzinc\ model is given to the \gls{solver}.
|
||||||
|
Any solutions found by the \gls{solver} are communicated back to the user.
|
||||||
|
\end{description}
|
||||||
|
|
||||||
|
\jip{TODO: Description of the flattening process}
|
||||||
|
|
||||||
|
\jip{TODO: Description of the techniques used during the optimisation phase}
|
||||||
|
|
||||||
\section{Other Constraint Modelling Languages}%
|
\section{Other Constraint Modelling Languages}%
|
||||||
\label{sec:back-other-languages}
|
\label{sec:back-other-languages}
|
||||||
|
|
||||||
|
\subsection{AMPL}%
|
||||||
|
\label{sub:back-ampl}
|
||||||
|
|
||||||
|
\subsection{OPL}%
|
||||||
|
\label{sub:back-}
|
||||||
|
|
||||||
|
\subsection{Essence}%
|
||||||
|
\label{sub:back-essence}
|
||||||
|
|
||||||
\section{ACD Term Rewriting}%
|
\section{ACD Term Rewriting}%
|
||||||
\label{sec:back-term}
|
\label{sec:back-term}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
%************************************************
|
%************************************************
|
||||||
|
|
||||||
Rewriting a high-level constraint model down into an equivalent solver-level
|
Rewriting a high-level constraint model down into an equivalent solver-level
|
||||||
constraint model might often seems like a simple term rewriting system. In
|
constraint model might often seem like a simple term rewriting system. In
|
||||||
reality, however, simple rewriting of the model will often result in sub-optimal
|
reality, however, simple rewriting of the model will often result in sub-optimal
|
||||||
solver-level model and this might result in exponentially more work for the
|
solver-level model and this might result in exponentially more work for the
|
||||||
solver. To combat this problem many techniques have been developed to create
|
solver. To combat this problem many techniques have been developed to create
|
||||||
@ -35,7 +35,7 @@ tool chain allows us to:
|
|||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
The new architecture is shown in \Cref{sfig:4-newarch}. A constraint model is
|
The new architecture is shown in \Cref{sfig:4-newarch}. A constraint model is
|
||||||
first compiled to byte code (called \microzinc), independent of the data. The
|
first compiled to byte code (called \microzinc{}), independent of the data. The
|
||||||
byte code is interpreted with the data to produce \nanozinc\ code, an extension
|
byte code is interpreted with the data to produce \nanozinc\ code, an extension
|
||||||
of the existing \flatzinc\ format. The interpreter can even be made incremental:
|
of the existing \flatzinc\ format. The interpreter can even be made incremental:
|
||||||
in \cref{ch:incremental} we discuss how in meta optimisation, no recompilation
|
in \cref{ch:incremental} we discuss how in meta optimisation, no recompilation
|
||||||
@ -78,15 +78,15 @@ presents our conclusions.
|
|||||||
This section introduces the two sub-languages of \minizinc\ at the core of the
|
This section introduces the two sub-languages of \minizinc\ at the core of the
|
||||||
new abstract machine model we have developed.
|
new abstract machine model we have developed.
|
||||||
|
|
||||||
\microzinc\ is a simplified subset of \minizinc\ that only contains function
|
\microzinc{} is a simplified subset of \minizinc\ that only contains function
|
||||||
declarations and a restricted expression language, but it extends \minizinc{}'s
|
declarations and a restricted expression language, but it extends \minizinc{}'s
|
||||||
type system with tuples. Models written in \minizinc\ can be translated into
|
type system with tuples. Models written in \minizinc\ can be translated into
|
||||||
\microzinc.
|
\microzinc{}.
|
||||||
|
|
||||||
\nanozinc\ is similar to \flatzinc\ in that it contains only simple variable
|
\nanozinc{} is similar to \flatzinc\ in that it contains only simple variable
|
||||||
declarations and flat constraints. However, while all function calls in
|
declarations and flat constraints. However, while all function calls in
|
||||||
\flatzinc\ need to be solver-level primitives, \nanozinc\ calls can refer to
|
\flatzinc\ need to be solver-level primitives, \nanozinc\ calls can refer to
|
||||||
functions implemented in \microzinc. Furthermore, \nanozinc\ allows for
|
functions implemented in \microzinc{}. Furthermore, \nanozinc\ allows for
|
||||||
constraints to be bound to a specific variable and constraints and variables
|
constraints to be bound to a specific variable and constraints and variables
|
||||||
declarations can be interleaved.
|
declarations can be interleaved.
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ and where expressions have \mzninline{par} type.
|
|||||||
|
|
||||||
<gen-exp> ::= <ident> "in" <exp> ["," <ident> "in" <exp> ]*
|
<gen-exp> ::= <ident> "in" <exp> ["," <ident> "in" <exp> ]*
|
||||||
\end{grammar}
|
\end{grammar}
|
||||||
\caption{\label{fig:4-uzn-syntax}Syntax of \microzinc.}
|
\caption{\label{fig:4-uzn-syntax}Syntax of \microzinc{}.}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\newcommand{\sep}{\rhd}
|
\newcommand{\sep}{\rhd}
|
||||||
@ -149,17 +149,17 @@ explained in detail in \cref{sec:4-nanozinc}, for now you can ignore them).
|
|||||||
|
|
||||||
<nzn-bind> ::= "└──" <nzn-con>
|
<nzn-bind> ::= "└──" <nzn-con>
|
||||||
\end{grammar}
|
\end{grammar}
|
||||||
\caption{\label{fig:4-nzn-syntax}Syntax of \nanozinc.}
|
\caption{\label{fig:4-nzn-syntax}Syntax of \nanozinc{}.}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\subsection{\glsentrytext{minizinc} to
|
\subsection{\glsentrytext{minizinc} to
|
||||||
\glsentrytext{microzinc}/\glsentrytext{nanozinc}}
|
\glsentrytext{microzinc}/\glsentrytext{nanozinc}}
|
||||||
|
|
||||||
The translation from \minizinc\ to \microzinc\ involves the following steps:
|
The translation from \minizinc\ to \microzinc{} involves the following steps:
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Transform all expressions that are valid in \minizinc\ but not in
|
\item Transform all expressions that are valid in \minizinc\ but not in
|
||||||
\microzinc. This includes simple cases such as replacing operator
|
\microzinc{}. This includes simple cases such as replacing operator
|
||||||
expressions like \mzninline{x+y} by function calls
|
expressions like \mzninline{x+y} by function calls
|
||||||
\mzninline{int_plus(x,y)}. As mentioned above, more complex rules for
|
\mzninline{int_plus(x,y)}. As mentioned above, more complex rules for
|
||||||
rewriting conditionals with variables, such as \mzninline{if x then A
|
rewriting conditionals with variables, such as \mzninline{if x then A
|
||||||
@ -180,17 +180,17 @@ The translation from \minizinc\ to \microzinc\ involves the following steps:
|
|||||||
if boolean variable exists.
|
if boolean variable exists.
|
||||||
|
|
||||||
\item Lift the partiality in expressions into the surrounding context to
|
\item Lift the partiality in expressions into the surrounding context to
|
||||||
implement \minizinc{}'s relational semantics. In contrast to \minizinc,
|
implement \minizinc{}'s relational semantics. In contrast to
|
||||||
the evaluation of \microzinc\ will implement strict semantics for
|
\minizinc{}, the evaluation of \microzinc\ will implement strict
|
||||||
partial expressions, whereas \minizinc\ uses relational semantics.
|
semantics for partial expressions, whereas \minizinc\ uses relational
|
||||||
Stuckey and Tack have extensively examined this problems and describe
|
semantics. Stuckey and Tack have extensively examined these problems and
|
||||||
how to transform any partial function into a total function.
|
describe how to transform any partial function into a total function.
|
||||||
\autocite*{stuckey-2013-functions}. A general approach for describing
|
\autocite*{stuckey-2013-functions}. A general approach for describing
|
||||||
the partially in \minizinc\ functions in \microzinc\ functions is to
|
the partially in \microzinc\ functions is to make the function return
|
||||||
make the function return both a boolean variable that indicates the
|
both a boolean variable that indicates the totality of the input
|
||||||
totality of the input variables and the resulting value of the function
|
variables and the resulting value of the function that is adjusted that
|
||||||
that is adjusted that is adjusted to return a predefined value when it
|
is adjusted to return a predefined value when it would normally be
|
||||||
would normally be undefined. For example, The function
|
undefined. For example, The function
|
||||||
|
|
||||||
\begin{mzn}
|
\begin{mzn}
|
||||||
function var int: element(array of int: a, var int: x);
|
function var int: element(array of int: a, var int: x);
|
||||||
@ -230,14 +230,14 @@ The translation from \minizinc\ to \microzinc\ involves the following steps:
|
|||||||
every call, the function dispatch in \microzinc\ is determined
|
every call, the function dispatch in \microzinc\ is determined
|
||||||
statically.
|
statically.
|
||||||
|
|
||||||
It is important, however, that the correct version of functions that
|
It is important, however, that the correct version of a function is
|
||||||
allow for both variable and parameter arguments is chosen. And, as we
|
chosen when it allows for both variable and parameter parameters. And,
|
||||||
will later discuss in more detail, is possible for variables to be fixed
|
as we will later discuss in more detail, is possible for variables to be
|
||||||
to a single value, at which point they can be treated as parameters. The
|
fixed to a single value, at which point they can be treated as
|
||||||
ensure the correct version of the function is used, functions can be
|
parameters. To ensure the correct version of the function is used,
|
||||||
defined to, at runtime, check if a variable is fixed and, if so,
|
functions are changed to, at runtime, check if a variable is fixed and,
|
||||||
dispatch to the parameter version of the function. If we for example
|
if so, dispatch to the parameter version of the function. If we for
|
||||||
have a \minizinc\ function \mzninline{f} that is overloaded on
|
example have a \minizinc\ function \mzninline{f} that is overloaded on
|
||||||
\mzninline{var int} and \mzninline{int}, then the \microzinc\
|
\mzninline{var int} and \mzninline{int}, then the \microzinc\
|
||||||
transformation might look like:
|
transformation might look like:
|
||||||
|
|
||||||
@ -315,8 +315,9 @@ The translation from \minizinc\ to \microzinc\ involves the following steps:
|
|||||||
|
|
||||||
Each call in a \nanozinc\ program is either a call to a solver-level predicate,
|
Each call in a \nanozinc\ program is either a call to a solver-level predicate,
|
||||||
or it has a corresponding \microzinc\ function definition. The goal of partial
|
or it has a corresponding \microzinc\ function definition. The goal of partial
|
||||||
evaluation is to transform the \nanozinc\ program into (essentially) \flatzinc,
|
evaluation is to transform the \nanozinc\ program into (essentially)
|
||||||
\ie\ a program where all calls are calls to solver-level predicates.
|
\flatzinc{}, \ie\ a program where all calls are calls to solver-level
|
||||||
|
predicates.
|
||||||
|
|
||||||
To achieve this, we define the semantics of \microzinc\ as a rewriting system
|
To achieve this, we define the semantics of \microzinc\ as a rewriting system
|
||||||
that produces \nanozinc\ calls. Each non-primitive call in a \nanozinc\ program
|
that produces \nanozinc\ calls. Each non-primitive call in a \nanozinc\ program
|
||||||
@ -435,7 +436,7 @@ suitable alpha renaming.
|
|||||||
\tuple{\ensuremath{\texttt{constraint}~\ptinline{F}(a_1, \ldots, a_k), \Env}}}
|
\tuple{\ensuremath{\texttt{constraint}~\ptinline{F}(a_1, \ldots, a_k), \Env}}}
|
||||||
\end{prooftree}
|
\end{prooftree}
|
||||||
\caption{\label{fig:4-rewrite-to-nzn-calls} Rewriting rules for partial evaluation
|
\caption{\label{fig:4-rewrite-to-nzn-calls} Rewriting rules for partial evaluation
|
||||||
of \microzinc\ calls to \nanozinc.}
|
of \microzinc\ calls to \nanozinc{}.}
|
||||||
\end{figure*}
|
\end{figure*}
|
||||||
|
|
||||||
The rules in \cref{fig:4-rewrite-to-nzn-calls} handle function calls. The first
|
The rules in \cref{fig:4-rewrite-to-nzn-calls} handle function calls. The first
|
||||||
@ -497,7 +498,7 @@ considered primitives, and as such simply need to be transferred into the
|
|||||||
\infer2[(ItemC)]{\Sem{\(\mbox{constraint}~C\texttt{;} \mathbf{I} \mid{} \mathbf{X}\)}{\Prog, \Env, \Ctx} \Rightarrow\ \tuple{x, \Env''}}
|
\infer2[(ItemC)]{\Sem{\(\mbox{constraint}~C\texttt{;} \mathbf{I} \mid{} \mathbf{X}\)}{\Prog, \Env, \Ctx} \Rightarrow\ \tuple{x, \Env''}}
|
||||||
\end{prooftree}
|
\end{prooftree}
|
||||||
\caption{\label{fig:4-rewrite-to-nzn-let} Rewriting rules for partial evaluation
|
\caption{\label{fig:4-rewrite-to-nzn-let} Rewriting rules for partial evaluation
|
||||||
of \microzinc\ let expressions to \nanozinc.}
|
of \microzinc\ let expressions to \nanozinc{}.}
|
||||||
\end{figure*}
|
\end{figure*}
|
||||||
|
|
||||||
The rules in \cref{fig:4-rewrite-to-nzn-let} considers let expressions. Starting
|
The rules in \cref{fig:4-rewrite-to-nzn-let} considers let expressions. Starting
|
||||||
@ -561,7 +562,7 @@ notation.
|
|||||||
\tuple{\mbox{concat} [ A_v~|~v \in{} S ], \Env{} \cup{} \bigcup{}_{v \in{} S} \Env{}_{v}}}
|
\tuple{\mbox{concat} [ A_v~|~v \in{} S ], \Env{} \cup{} \bigcup{}_{v \in{} S} \Env{}_{v}}}
|
||||||
\end{prooftree}
|
\end{prooftree}
|
||||||
\caption{\label{fig:4-rewrite-to-nzn-other} Rewriting rules for partial evaluation
|
\caption{\label{fig:4-rewrite-to-nzn-other} Rewriting rules for partial evaluation
|
||||||
of other \microzinc\ expressions to \nanozinc.}
|
of other \microzinc\ expressions to \nanozinc{}.}
|
||||||
\end{figure*}
|
\end{figure*}
|
||||||
|
|
||||||
Finally, the rules in \cref{fig:4-rewrite-to-nzn-other} handle the evaluation of
|
Finally, the rules in \cref{fig:4-rewrite-to-nzn-other} handle the evaluation of
|
||||||
@ -586,7 +587,7 @@ Our prototype implementation of the \microzinc/\nanozinc\ framework consists of
|
|||||||
the following components.
|
the following components.
|
||||||
|
|
||||||
The \textbf{compiler} translates \minizinc\ into a \textbf{byte code} encoding of
|
The \textbf{compiler} translates \minizinc\ into a \textbf{byte code} encoding of
|
||||||
\microzinc. The compiler currently supports a significant subset of the full
|
\microzinc{}. The compiler currently supports a significant subset of the full
|
||||||
\minizinc\ language, with the missing features (such as multi-dimensional arrays
|
\minizinc\ language, with the missing features (such as multi-dimensional arrays
|
||||||
and complex output statements) requiring additional engineering effort but no
|
and complex output statements) requiring additional engineering effort but no
|
||||||
new technology.
|
new technology.
|
||||||
@ -594,14 +595,14 @@ new technology.
|
|||||||
The \textbf{interpreter} evaluates \microzinc\ byte code and \nanozinc\ programs
|
The \textbf{interpreter} evaluates \microzinc\ byte code and \nanozinc\ programs
|
||||||
based on the rewrite system introduced in this section. It can read parameter
|
based on the rewrite system introduced in this section. It can read parameter
|
||||||
data from a file or via an API\@. The interpreter constructs the call to the
|
data from a file or via an API\@. The interpreter constructs the call to the
|
||||||
\mzninline{main} function, and then performs the rewriting into flat \nanozinc.
|
\mzninline{main} function, and then performs the rewriting into flat \nanozinc{}.
|
||||||
Memory management is implemented using reference counting, which lends itself
|
Memory management is implemented using reference counting, which lends itself
|
||||||
well to the optimisations discussed in the next section. The interpreter is
|
well to the optimisations discussed in the next section. The interpreter is
|
||||||
written in around 3.5kLOC of C++ to enable easy embedding into applications and
|
written in around 3.5kLOC of C++ to enable easy embedding into applications and
|
||||||
other programming languages.
|
other programming languages.
|
||||||
|
|
||||||
The framework includes \textbf{interfaces} to multiple solvers. It can
|
The framework includes \textbf{interfaces} to multiple solvers. It can
|
||||||
pretty-print the \nanozinc\ code to standard \flatzinc, so that any solver
|
pretty-print the \nanozinc\ code to standard \flatzinc{}, so that any solver
|
||||||
currently compatible with \minizinc\ can be used. Additionally, a direct C++ API
|
currently compatible with \minizinc\ can be used. Additionally, a direct C++ API
|
||||||
can be used to connect solvers directly, in order to enable incremental
|
can be used to connect solvers directly, in order to enable incremental
|
||||||
solving. This topic is revisited in \cref{ch:incremental}.
|
solving. This topic is revisited in \cref{ch:incremental}.
|
||||||
@ -667,11 +668,11 @@ prepended by \texttt{└── }).
|
|||||||
independent of the value of \mzninline{b}. The constraint \mzninline{abs(x) >
|
independent of the value of \mzninline{b}. The constraint \mzninline{abs(x) >
|
||||||
y} is therefore not required. However, the rewriting has to choose a
|
y} is therefore not required. However, the rewriting has to choose a
|
||||||
particular order in which arguments are evaluated, so it is always possible
|
particular order in which arguments are evaluated, so it is always possible
|
||||||
that it already evaluated the left hand side before ``noticing'' that the
|
that it already evaluated the left-hand side before ``noticing'' that the
|
||||||
disjunction is true.
|
disjunction is true.
|
||||||
|
|
||||||
If the system now simplifies the constraint \mzninline{bool_or(b, c)} to
|
If the system now simplifies the constraint \mzninline{bool_or(b, c)} to
|
||||||
\mzninline{true}, the identifier \mzninline{b} will become unused outside of
|
\mzninline{true}, the identifier \mzninline{b} will become unused outside
|
||||||
its auxiliary definitions, since it was only referenced from the
|
its auxiliary definitions, since it was only referenced from the
|
||||||
\mzninline{bool_or} call. Removing \mzninline{b} leads will also its defining
|
\mzninline{bool_or} call. Removing \mzninline{b} leads will also its defining
|
||||||
constraint, \mzninline{int_gt_reif}, being removed. This in turn means that
|
constraint, \mzninline{int_gt_reif}, being removed. This in turn means that
|
||||||
@ -689,10 +690,10 @@ prepended by \texttt{└── }).
|
|||||||
other parts of the model not shown here and therefore not removed.
|
other parts of the model not shown here and therefore not removed.
|
||||||
\end{example}
|
\end{example}
|
||||||
|
|
||||||
Note how how counting usage of variables outside its auxiliary definitions
|
Note how counting usage of variables outside its auxiliary definitions allows us
|
||||||
allows us to remove the \mzninline{z} variable --- we could not simply have
|
to remove the \mzninline{z} variable --- we could not simply have counted the
|
||||||
counted the usage of \mzninline{z} in all constraints since the constraint used
|
usage of \mzninline{z} in all constraints since the constraint used to define
|
||||||
to define it, \mzninline{int_abs(x, z)}, would have kept it alive.
|
it, \mzninline{int_abs(x, z)}, would have kept it alive.
|
||||||
|
|
||||||
It is important to notice the difference between constraints that appear at the
|
It is important to notice the difference between constraints that appear at the
|
||||||
top level and constraints that appear as part of the auxiliary definitions of a
|
top level and constraints that appear as part of the auxiliary definitions of a
|
||||||
@ -855,7 +856,7 @@ arguments). These links do not take part in the reference counting.
|
|||||||
|
|
||||||
Adding \gls{propagation} and simplification into the rewriting system means
|
Adding \gls{propagation} and simplification into the rewriting system means
|
||||||
that the system becomes non-confluent, and some orders of execution may produce
|
that the system becomes non-confluent, and some orders of execution may produce
|
||||||
``better'', \ie\ more compact or more efficient, \nanozinc.
|
``better'', \ie\ more compact or more efficient, \nanozinc{}.
|
||||||
|
|
||||||
\begin{example}
|
\begin{example}
|
||||||
The following example is similar to code found in the \minizinc\ libraries of
|
The following example is similar to code found in the \minizinc\ libraries of
|
||||||
@ -901,7 +902,7 @@ can then be fully simplified by \gls{propagation}, before the Boolean and
|
|||||||
reified constraints are rewritten into lower-level linear primitives suitable
|
reified constraints are rewritten into lower-level linear primitives suitable
|
||||||
for MIP\@.
|
for MIP\@.
|
||||||
|
|
||||||
\subsection{Common Subexpression Elimination}\label{sec:4-cse}
|
\subsection{Common Sub-expression Elimination}\label{sec:4-cse}
|
||||||
|
|
||||||
The simplifications introduced above remove definitions from the model when we
|
The simplifications introduced above remove definitions from the model when we
|
||||||
can detect that they are no longer needed. In some cases, it is even possible to
|
can detect that they are no longer needed. In some cases, it is even possible to
|
||||||
@ -946,9 +947,9 @@ in the following example.
|
|||||||
straightforward approach to ensure that the same instantiation of a function
|
straightforward approach to ensure that the same instantiation of a function
|
||||||
is only evaluated once is through memorisation. After the evaluation of a
|
is only evaluated once is through memorisation. After the evaluation of a
|
||||||
\microzinc\ call, the instantiated call and its result are stored in a lookup
|
\microzinc\ call, the instantiated call and its result are stored in a lookup
|
||||||
table, the \gls{cse} table. Before a call is evaluated the \gls{cse} table is
|
table, the \gls{cse} table. Then before any consequent call is evaluated the
|
||||||
consulted. If the call is found, then the accompanying result is used;
|
\gls{cse} table is consulted. If the call is found, then the accompanying
|
||||||
otherwise, the evaluation proceeds as normal.
|
result is used; otherwise, the evaluation proceeds as normal.
|
||||||
|
|
||||||
In our example, the evaluation of \mzninline{pythagoras(i, i)} would proceed
|
In our example, the evaluation of \mzninline{pythagoras(i, i)} would proceed
|
||||||
as normal to evaluate \mzninline{x = pow(i, 2)}. However, the expression
|
as normal to evaluate \mzninline{x = pow(i, 2)}. However, the expression
|
||||||
@ -958,19 +959,19 @@ in the following example.
|
|||||||
|
|
||||||
It is worth noting that the \gls{cse} approach based on memorisation also covers
|
It is worth noting that the \gls{cse} approach based on memorisation also covers
|
||||||
the static example above, where the compiler can enforce sharing of common
|
the static example above, where the compiler can enforce sharing of common
|
||||||
subexpressions before evaluation begins. However, since the static analysis is
|
sub-expressions before evaluation begins. However, since the static analysis is
|
||||||
cheap and can potentially avoid many dynamic table lookups, it is valuable to
|
cheap and can potentially avoid many dynamic table look-ups, it is valuable to
|
||||||
combine both approaches. The static approach can be further improved by
|
combine both approaches. The static approach can be further improved by
|
||||||
\emph{inlining} function calls, since that may expose more calls as being
|
\emph{inlining} function calls, since that may expose more calls as being
|
||||||
syntactically equal.
|
syntactically equal.
|
||||||
|
|
||||||
|
|
||||||
\jip{TODO: \gls{cse} will be discussed in the background. How can we make this
|
\jip{TODO: \gls{cse} will be discussed in the background. How can we make this
|
||||||
more specific to how it works in \nanozinc}
|
more specific to how it works in \nanozinc{}.}
|
||||||
|
|
||||||
\paragraph{Reification}
|
\paragraph{Reification}
|
||||||
|
|
||||||
Many constraint modelling languages, including \minizinc, not only enable
|
Many constraint modelling languages, including \minizinc{}, not only enable
|
||||||
constraints to be globally enforced, but typically also support constraints to
|
constraints to be globally enforced, but typically also support constraints to
|
||||||
be \emph{reified} into a Boolean variable. Reification means that a variable
|
be \emph{reified} into a Boolean variable. Reification means that a variable
|
||||||
\mzninline{b} is constrained to be true if and only if a corresponding
|
\mzninline{b} is constrained to be true if and only if a corresponding
|
||||||
@ -978,7 +979,7 @@ constraint \mzninline{c(...)} holds. We have already seen reification in
|
|||||||
\cref{ex:4-absreif}: the truth of constraint \mzninline{abs(x) > y} was bound to
|
\cref{ex:4-absreif}: the truth of constraint \mzninline{abs(x) > y} was bound to
|
||||||
a Boolean variable \mzninline{b1}, which was then used in a disjunction. We say
|
a Boolean variable \mzninline{b1}, which was then used in a disjunction. We say
|
||||||
that the same constraint can be used in \emph{root context} as well as in a
|
that the same constraint can be used in \emph{root context} as well as in a
|
||||||
\emph{reified context}. In \minizinc, almost all constraints can be used in both
|
\emph{reified context}. In \minizinc{}, almost all constraints can be used in both
|
||||||
contexts. However, reified constraints are often defined in the library in terms
|
contexts. However, reified constraints are often defined in the library in terms
|
||||||
of complicated decompositions into simpler constraints, or require specialised
|
of complicated decompositions into simpler constraints, or require specialised
|
||||||
algorithms in the target solvers. In either case, it can be very beneficial for
|
algorithms in the target solvers. In either case, it can be very beneficial for
|
||||||
@ -992,13 +993,14 @@ reification (or in fact any evaluation). We can harness \gls{cse} to store the
|
|||||||
evaluation context when a constraint is added, and detect when the same
|
evaluation context when a constraint is added, and detect when the same
|
||||||
constraint is used in both contexts. Whenever a lookup in the \gls{cse} table is
|
constraint is used in both contexts. Whenever a lookup in the \gls{cse} table is
|
||||||
successful, action can be taken depending on both the current and stored
|
successful, action can be taken depending on both the current and stored
|
||||||
evaluation context. If the stored expression was in root context, the constant
|
evaluation context. If the stored expression was in root context, then the
|
||||||
\mzninline{true} can be used, independent of the current context. If the stored
|
constant \mzninline{true} can be used, independent of the current context.
|
||||||
expression was in reified context and the current context is reified, the stored
|
Otherwise, if the stored expression was in reified context and the current
|
||||||
result variable can be used. If the stored expression was in reified context and
|
context is reified, then the stored result variable can be used. Finally, if the
|
||||||
the current context is root context, then the previous result can be replaced by
|
stored expression was in reified context and the current context is root
|
||||||
the constant \mzninline{true} (and all its dependencies removed) and the
|
context, then the previous result can be replaced by the constant
|
||||||
evaluation will proceed as normal with the root context constraint.
|
\mzninline{true} (and all its dependencies removed) and the evaluation will
|
||||||
|
proceed as normal with the root context constraint.
|
||||||
\begin{example}
|
\begin{example}
|
||||||
Consider the fragment:
|
Consider the fragment:
|
||||||
|
|
||||||
@ -1011,19 +1013,19 @@ evaluation will proceed as normal with the root context constraint.
|
|||||||
|
|
||||||
If we process the top-level constraints in order we create a reified call to
|
If we process the top-level constraints in order we create a reified call to
|
||||||
\mzninline{q(x)} for the original call. Suppose processing the second
|
\mzninline{q(x)} for the original call. Suppose processing the second
|
||||||
constraint we discover \mzninline{t(x,y)} is \mzninline{true}, setting
|
constraint we discover \mzninline{t(x,y)} is \mzninline{true}, fixing
|
||||||
\mzninline{b1}. When we process \mzninline{q(x)} in the call
|
\mzninline{b1}. When we then process \mzninline{q(x)} in instantiation of the
|
||||||
\mzninline{t(x,y)} we find it is the root context. So \gls{cse} needs to set
|
call \mzninline{p(x,y)}, we find it is the root context. So \gls{cse} needs to
|
||||||
\mzninline{b0} to \mzninline{true}.
|
set \mzninline{b0} to \mzninline{true}.
|
||||||
\end{example}
|
\end{example}
|
||||||
|
|
||||||
\minizinc\ distinguishes not only between root and reified contexts, but in
|
\minizinc{} distinguishes not only between root and reified contexts, but in
|
||||||
addition recognises constraints in \emph{positive} contexts, also known as
|
addition recognises constraints in \emph{positive} contexts, also known as
|
||||||
\emph{half-reified} \autocite{feydy-2011-half-reif}. A full explanation and
|
\emph{half-reified} \autocite{feydy-2011-half-reif}. A full explanation and
|
||||||
discussion of half-reification can be found in \cref{ch:half_reif}.
|
discussion of half-reification can be found in \cref{ch:half_reif}.
|
||||||
|
|
||||||
\jip{TODO: Reification should also be discussed in the background. How can we
|
\jip{TODO: Reification should also be discussed in the background. How can we
|
||||||
make this more specific to how it works in \nanozinc}
|
make this more specific to how it works in \nanozinc{}.}
|
||||||
|
|
||||||
\subsection{Constraint Aggregation}%
|
\subsection{Constraint Aggregation}%
|
||||||
\label{subsec:rew-aggregation}
|
\label{subsec:rew-aggregation}
|
||||||
@ -1047,11 +1049,11 @@ operators. For example the evaluation of the linear constraint \mzninline{x +
|
|||||||
|
|
||||||
These \nanozinc\ definitions are correct, but, at least for \gls{mip} solvers,
|
These \nanozinc\ definitions are correct, but, at least for \gls{mip} solvers,
|
||||||
the existence of the intermediate variables is likely to have a negative impact
|
the existence of the intermediate variables is likely to have a negative impact
|
||||||
on the solvers performance. These solves would likely performed better had they
|
on the \gls{solver}'s performance. These \glspl{solver} would likely perform
|
||||||
received the linear constraint \mzninline{int_lin_le([1,2,-1], [x,y,z], 0)}
|
better had they received the linear constraint \mzninline{int_lin_le([1,2,-1],
|
||||||
directly. Since many solvers support linear constraints, it is often an
|
[x,y,z], 0)} directly. Since many solvers support linear constraints, it is
|
||||||
additional burden to have intermediate values that have to be given a value in
|
often an additional burden to have intermediate values that have to be given a
|
||||||
the solution.
|
value in the solution.
|
||||||
|
|
||||||
This can be resolved using the \gls{aggregation} of constraints. When we
|
This can be resolved using the \gls{aggregation} of constraints. When we
|
||||||
aggregate constraints we combine constraints connected through functional
|
aggregate constraints we combine constraints connected through functional
|
||||||
@ -1060,25 +1062,25 @@ intermediate variables. For example, the arithmetic definitions can be combined
|
|||||||
into linear constraints, Boolean logic can be combined into clauses, and
|
into linear constraints, Boolean logic can be combined into clauses, and
|
||||||
counting constraints can be combined into global cardinality constraints.
|
counting constraints can be combined into global cardinality constraints.
|
||||||
|
|
||||||
In \nanozinc, we are able to aggregate constraints during partial evaluation. To
|
In \nanozinc{}, we are able to aggregate constraints during partial evaluation. To
|
||||||
aggregate a certain kind of constraint, the solver must the constraint as a
|
aggregate a certain kind of constraint, the solver must the constraint as a
|
||||||
solver-level primitive. These constraints will now be kept as temporary
|
solver-level primitive. These constraints will now be kept as temporary
|
||||||
functional definitions in the \nanozinc\ program. Once a top-level (relational)
|
functional definitions in the \nanozinc\ program. Once a top-level (relational)
|
||||||
constraint is posted that uses the temporary functional definitions as one of
|
\gls{constraint} is posted that uses the temporary functional definitions as one of
|
||||||
its arguments, the interpreter will employ dedicated \gls{aggregation} logic to
|
its arguments, the interpreter will employ dedicated \gls{aggregation} logic to
|
||||||
visit the functional definitions and combine their constraints. The top-level
|
visit the functional definitions and combine their constraints. The top-level
|
||||||
constraint constraint is then replaced by the combined constraint. When the
|
\gls{constraint} is then replaced by the combined \gls{constraint}. When the
|
||||||
intermediate variables become unused, they will be removed using the normal
|
intermediate variables become unused, they will be removed using the normal
|
||||||
mechanisms.
|
mechanisms.
|
||||||
|
|
||||||
\jip{TODO: Aggregation is also part of the background. How can we make this more
|
\jip{TODO: Aggregation is also part of the background. How can we make this more
|
||||||
specific to how it works in \nanozinc}
|
specific to how it works in \nanozinc{}.}
|
||||||
|
|
||||||
\section{Experiments}\label{sec:4-experiments}
|
\section{Experiments}\label{sec:4-experiments}
|
||||||
|
|
||||||
We have created a prototype implementation of the architecture presented in the
|
We have created a prototype implementation of the architecture presented in the
|
||||||
preceding sections. It consists of a compiler from \minizinc\ to \microzinc, and
|
preceding sections. It consists of a compiler from \minizinc\ to \microzinc{}, and
|
||||||
an incremental \microzinc\ interpreter producing \nanozinc. The system supports
|
an incremental \microzinc\ interpreter producing \nanozinc{}. The system supports
|
||||||
a significant subset of the full \minizinc\ language; notable features that are
|
a significant subset of the full \minizinc\ language; notable features that are
|
||||||
missing are support for set and float variables, option types, and compilation
|
missing are support for set and float variables, option types, and compilation
|
||||||
of model output expressions and annotations. We will release our implementation
|
of model output expressions and annotations. We will release our implementation
|
||||||
@ -1093,7 +1095,7 @@ well as incremental flattening and solving that demonstrate the efficiency
|
|||||||
gains that are possible thanks to the new architecture.
|
gains that are possible thanks to the new architecture.
|
||||||
|
|
||||||
We selected 20 models from the annual \minizinc\ challenge and compiled 5
|
We selected 20 models from the annual \minizinc\ challenge and compiled 5
|
||||||
instances of each model to \flatzinc, using the current \minizinc\ release
|
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
|
version 2.4.3 and the new prototype system. In both cases we use the standard
|
||||||
\minizinc\ library of global constraints (\ie\ we decompose those constraints
|
\minizinc\ library of global constraints (\ie\ we decompose those constraints
|
||||||
rather than using solver built-ins, in order to stress-test the flattening). We
|
rather than using solver built-ins, in order to stress-test the flattening). We
|
||||||
@ -1123,13 +1125,13 @@ unoptimised prototype to a mature piece of software.
|
|||||||
\begin{subfigure}[b]{.48\columnwidth}
|
\begin{subfigure}[b]{.48\columnwidth}
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=\columnwidth]{assets/img/4_compare_runtime}
|
\includegraphics[width=\columnwidth]{assets/img/4_compare_runtime}
|
||||||
\caption{\label{sfig:4-compareruntime}flattening run time (ms)}
|
\caption{\label{sfig:4-compareruntime}Flattening run time (ms)}
|
||||||
\end{subfigure}%
|
\end{subfigure}%
|
||||||
\hspace{0.04\columnwidth}%
|
\hspace{0.04\columnwidth}%
|
||||||
\begin{subfigure}[b]{.48\columnwidth}
|
\begin{subfigure}[b]{.48\columnwidth}
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=\columnwidth]{assets/img/4_compare_memory}
|
\includegraphics[width=\columnwidth]{assets/img/4_compare_memory}
|
||||||
\caption{\label{sfig:4-comparemem}flattening memory (MB)}
|
\caption{\label{sfig:4-comparemem}Flattening memory (MB)}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{\label{fig:4-runtime}Performance on flattening 100 MiniZinc Challenge
|
\caption{\label{fig:4-runtime}Performance on flattening 100 MiniZinc Challenge
|
||||||
instances. \minizinc\ 2.4.3 (x-axis) vs new architecture (y-axis), log-log
|
instances. \minizinc\ 2.4.3 (x-axis) vs new architecture (y-axis), log-log
|
||||||
@ -1139,10 +1141,10 @@ unoptimised prototype to a mature piece of software.
|
|||||||
\section{Summary}%
|
\section{Summary}%
|
||||||
\label{sec:rew-summary}
|
\label{sec:rew-summary}
|
||||||
|
|
||||||
In this chapter, we introduced a systematic view of the execution of \minizinc,
|
In this chapter, we introduced a systematic view of the execution of \minizinc{},
|
||||||
revisiting the rewriting from high-level \minizinc\ to solver-level \flatzinc.
|
revisiting the rewriting from high-level \minizinc\ to solver-level \flatzinc{}.
|
||||||
We first introduced introduced the intermediate languages \microzinc\ and
|
We first introduced the intermediate languages \microzinc{} and
|
||||||
\nanozinc\ and explained how \minizinc\ can be transformed into a set of
|
\nanozinc{} and explained how \minizinc\ can be transformed into a set of
|
||||||
\microzinc\ definitions and a \nanozinc\ program. We then, crucially, discussed
|
\microzinc\ definitions and a \nanozinc\ program. We then, crucially, discussed
|
||||||
how to partially evaluate a \nanozinc\ program using \microzinc\ definitions and
|
how to partially evaluate a \nanozinc\ program using \microzinc\ definitions and
|
||||||
present formal definitions of the rewriting rules applied during partial
|
present formal definitions of the rewriting rules applied during partial
|
||||||
@ -1151,7 +1153,7 @@ evaluation.
|
|||||||
Continuously applying these rules would result in a correct solver-level model,
|
Continuously applying these rules would result in a correct solver-level model,
|
||||||
but it is unlikely to be the best model for the solver. We, therefore, discuss
|
but it is unlikely to be the best model for the solver. We, therefore, discuss
|
||||||
multiple techniques to improve the solver-level constraint model during the
|
multiple techniques to improve the solver-level constraint model during the
|
||||||
partial evaluation of \nanozinc. First, we introduce a novel technique to
|
partial evaluation of \nanozinc{}. First, we introduce a novel technique to
|
||||||
eliminate all unused variables and constraints: we track all constraints that
|
eliminate all unused variables and constraints: we track all constraints that
|
||||||
are introduced only to define a variable. This means we can keep an accurate
|
are introduced only to define a variable. This means we can keep an accurate
|
||||||
count of when a variable becomes unused by counting only the references to a
|
count of when a variable becomes unused by counting only the references to a
|
||||||
@ -1160,7 +1162,7 @@ variable in constraints that do not help define it. Then, we discuss the use of
|
|||||||
technique can help shrink the domains of the decision variable or even combine
|
technique can help shrink the domains of the decision variable or even combine
|
||||||
variables known to be equal. When a redefinition of a constraint requires the
|
variables known to be equal. When a redefinition of a constraint requires the
|
||||||
introspection into the current domain of a variable, it is often important to
|
introspection into the current domain of a variable, it is often important to
|
||||||
have the tightest possible domain. Hence, we discuss how in choosing the the
|
have the tightest possible domain. Hence, we discuss how in choosing the
|
||||||
next \nanozinc\ constraint to rewrite, the interpreter can sometimes delay the
|
next \nanozinc\ constraint to rewrite, the interpreter can sometimes delay the
|
||||||
rewriting of certain constraints to ensure the most amount of information is
|
rewriting of certain constraints to ensure the most amount of information is
|
||||||
available. \Gls{cse}, our next optimisation technique, ensures that we do not
|
available. \Gls{cse}, our next optimisation technique, ensures that we do not
|
||||||
@ -1171,7 +1173,7 @@ individual functional constraints can be collected and combined into an
|
|||||||
aggregated form. This allows us to avoid the existence of intermediate variables
|
aggregated form. This allows us to avoid the existence of intermediate variables
|
||||||
in some cases. This optimisation is very important for \gls{mip} solvers.
|
in some cases. This optimisation is very important for \gls{mip} solvers.
|
||||||
|
|
||||||
Finally, we test the described system using a experimental implementation. We
|
Finally, we test the described system using an experimental implementation. We
|
||||||
compare this experimental implementation against the current \minizinc\
|
compare this experimental implementation against the current \minizinc\
|
||||||
interpreter, version 2.5.3, and look at both runtime and its memory usage.
|
interpreter, version 2.5.3, and look at both runtime and its memory usage.
|
||||||
Although the experimental implementation there are instances where the
|
Although the experimental implementation there are instances where the
|
||||||
|
@ -9,7 +9,7 @@ modifications, thousands of times. Examples of these methods are:
|
|||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Multi-objective search \autocite{jones-2002-multi-objective}. Optimising
|
\item Multi-objective search \autocite{jones-2002-multi-objective}. Optimising
|
||||||
multiple objectives is often not supported directly in solvers. Instead
|
multiple objectives is often not supported directly in solvers. Instead,
|
||||||
it can be solved using a \gls{meta-search} approach: find a solution to
|
it can be solved using a \gls{meta-search} approach: find a solution to
|
||||||
a (single-objective) problem, then add more constraints to the original
|
a (single-objective) problem, then add more constraints to the original
|
||||||
problem and repeat.
|
problem and repeat.
|
||||||
@ -41,7 +41,7 @@ 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
|
constraints are added, the resulting instance is solved again, and constraints
|
||||||
may be removed again.
|
may be removed again.
|
||||||
|
|
||||||
The usage of these methods is not new to \gls{constraint-modelling} and they
|
The usage of these methods is not new to \gls{constraint-modelling}, and they
|
||||||
have proven to be very useful \autocite{schrijvers-2013-combinators,
|
have proven to be very useful \autocite{schrijvers-2013-combinators,
|
||||||
rendl-2015-minisearch, schiendorfer-2018-minibrass, ek-2020-online,
|
rendl-2015-minisearch, schiendorfer-2018-minibrass, ek-2020-online,
|
||||||
ingmar-2020-diverse}. In its most basic form, a simple scripting language is
|
ingmar-2020-diverse}. In its most basic form, a simple scripting language is
|
||||||
@ -51,7 +51,7 @@ constraint models. While improvements of the compilation of constraint models,
|
|||||||
such as the ones discussed in previous chapters, can increase the performance of
|
such as the ones discussed in previous chapters, can increase the performance of
|
||||||
these approaches, the overhead of re-compiling an almost identical model may
|
these approaches, the overhead of re-compiling an almost identical model may
|
||||||
still prove prohibitive, warranting direct support from the
|
still prove prohibitive, warranting direct support from the
|
||||||
\gls{constraint-modelling} infrastructure. In this chapter we introduces two
|
\gls{constraint-modelling} infrastructure. In this chapter we introduce two
|
||||||
methods to provide this support:
|
methods to provide this support:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
@ -61,7 +61,7 @@ methods to provide this support:
|
|||||||
algorithms into efficient solver-level specifications based on solver
|
algorithms into efficient solver-level specifications based on solver
|
||||||
restarts, avoiding re-compilation all-together.
|
restarts, avoiding re-compilation all-together.
|
||||||
\item Alternatively, we can add an incremental interface for adding and
|
\item Alternatively, we can add an incremental interface for adding and
|
||||||
removing constraints to the infrastructure of the \cml. Although this
|
removing constraints to the infrastructure of the \cml{}. Although this
|
||||||
does not avoid the need for re-compilation, it can reduce the work to
|
does not avoid the need for re-compilation, it can reduce the work to
|
||||||
only the part of the constraint model that has changed. This approach
|
only the part of the constraint model that has changed. This approach
|
||||||
can be used when an algorithm cannot be described using restart-based
|
can be used when an algorithm cannot be described using restart-based
|
||||||
@ -70,7 +70,7 @@ methods to provide this support:
|
|||||||
|
|
||||||
The rest of the chapter is organised as follows. \Cref{sec:6-modelling}
|
The rest of the chapter is organised as follows. \Cref{sec:6-modelling}
|
||||||
discusses the declarative modelling of restart-based \gls{meta-search}
|
discusses the declarative modelling of restart-based \gls{meta-search}
|
||||||
algorithms that can be modelled directly in a \cml.
|
algorithms that can be modelled directly in a \cml{}.
|
||||||
\Cref{sec:6-solver-extension} introduces the method to compile these
|
\Cref{sec:6-solver-extension} introduces the method to compile these
|
||||||
\gls{meta-search} specifications into efficient solver-level specifications that
|
\gls{meta-search} specifications into efficient solver-level specifications that
|
||||||
only require a small extension of existing \glspl{solver}.
|
only require a small extension of existing \glspl{solver}.
|
||||||
@ -83,8 +83,8 @@ Finally, \Cref{sec:6-conclusion} presents the conclusions.
|
|||||||
|
|
||||||
\section{Modelling of Restart-Based Meta-Search}\label{sec:6-modelling}
|
\section{Modelling of Restart-Based Meta-Search}\label{sec:6-modelling}
|
||||||
|
|
||||||
This section introduces a \minizinc\ extension that enables modellers to define
|
This section introduces a \minizinc{} extension that enables modellers to define
|
||||||
\gls{meta-search} algorithms in \cmls. This extension is based on the construct
|
\gls{meta-search} algorithms in \cmls{}. This extension is based on the construct
|
||||||
introduced in \minisearch\ \autocite{rendl-2015-minisearch}, as summarised
|
introduced in \minisearch\ \autocite{rendl-2015-minisearch}, as summarised
|
||||||
below.
|
below.
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ below.
|
|||||||
% variables that need to be applied to the base model, \eg\ forcing variables to
|
% variables that need to be applied to the base model, \eg\ forcing variables to
|
||||||
% take the same value as in the previous solution.
|
% take the same value as in the previous solution.
|
||||||
|
|
||||||
\minisearch\ introduced a \minizinc\ extension that enables modellers to express
|
\minisearch{} introduced a \minizinc{} extension that enables modellers to express
|
||||||
meta-searches inside a \minizinc\ model. A meta-search in \minisearch\ typically
|
meta-searches inside a \minizinc\ model. A meta-search in \minisearch\ typically
|
||||||
solves a given \minizinc\ model, performs some calculations on the solution,
|
solves a given \minizinc\ model, performs some calculations on the solution,
|
||||||
adds new constraints and then solves again.
|
adds new constraints and then solves again.
|
||||||
@ -157,9 +157,9 @@ To address these two issues, we propose to keep modelling neighbourhoods as
|
|||||||
predicates, but define \gls{meta-search} algorithms from an imperative
|
predicates, but define \gls{meta-search} algorithms from an imperative
|
||||||
perspective.
|
perspective.
|
||||||
|
|
||||||
define a small number of additional \minizinc\ built-in annotations and
|
We define a few additional \minizinc\ built-in annotations and functions that
|
||||||
functions that (a) allow us to express important aspects of the meta-search in a
|
(a) allow us to express important aspects of the meta-search in a more
|
||||||
more convenient way, and (b) enable a simple compilation scheme that requires no
|
convenient way, and (b) enable a simple compilation scheme that requires no
|
||||||
additional communication with and only small, simple extensions of the backend
|
additional communication with and only small, simple extensions of the backend
|
||||||
solver.
|
solver.
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ The second component of our \gls{lns} definition is the \emph{restarting
|
|||||||
strategy}, defining how much effort the solver should put into each
|
strategy}, defining how much effort the solver should put into each
|
||||||
neighbourhood (\ie\ restart), and when to stop the overall search.
|
neighbourhood (\ie\ restart), and when to stop the overall search.
|
||||||
|
|
||||||
We propose adding new search annotations to \minizinc\ to control this behaviour
|
We propose adding new search annotations to the \minizinc\ language to control this behaviour
|
||||||
(see \cref{lst:6-restart-ann}). The \mzninline{restart_on_solution} annotation
|
(see \cref{lst:6-restart-ann}). The \mzninline{restart_on_solution} annotation
|
||||||
tells the solver to restart immediately for each solution, rather than looking
|
tells the solver to restart immediately for each solution, rather than looking
|
||||||
for the best one in each restart, while \mzninline{restart_without_objective}
|
for the best one in each restart, while \mzninline{restart_without_objective}
|
||||||
@ -220,7 +220,7 @@ search after a fixed number of restarts.
|
|||||||
|
|
||||||
Although using just a restart annotations by themselves allows us to run the
|
Although using just a restart annotations by themselves allows us to run the
|
||||||
basic \gls{lns} algorithm, more advanced \gls{meta-search} algorithms will
|
basic \gls{lns} algorithm, more advanced \gls{meta-search} algorithms will
|
||||||
require more then reapplying the same \gls{neighbourhood} time after time. It
|
require more than reapplying the same \gls{neighbourhood} time after time. It
|
||||||
is, for example, often beneficial to use several \gls{neighbourhood} definitions
|
is, for example, often beneficial to use several \gls{neighbourhood} definitions
|
||||||
for a problem. Different \glspl{neighbourhood} may be able to improve different
|
for a problem. Different \glspl{neighbourhood} may be able to improve different
|
||||||
aspects of a solution, at different phases of the search. Adaptive \gls{lns}
|
aspects of a solution, at different phases of the search. Adaptive \gls{lns}
|
||||||
@ -273,8 +273,7 @@ status is not \mzninline{START}:
|
|||||||
\mznfile{assets/mzn/6_basic_lns.mzn}
|
\mznfile{assets/mzn/6_basic_lns.mzn}
|
||||||
|
|
||||||
In order to use this predicate with the \mzninline{on_restart} annotation, we
|
In order to use this predicate with the \mzninline{on_restart} annotation, we
|
||||||
cannot simply pass \mzninline{basic_lns(uniform_neighbourhood(x, 0.2))}. First
|
cannot simply pass \mzninline{basic_lns(uniform_neighbourhood(x, 0.2))}. Calling \mzninline{uniform_neighbourhood} like that would result in a
|
||||||
of all, calling \mzninline{uniform_neighbourhood} like that would result in a
|
|
||||||
\emph{single} evaluation of the predicate, since \minizinc\ employs a
|
\emph{single} evaluation of the predicate, since \minizinc\ employs a
|
||||||
call-by-value evaluation strategy. Furthermore, the \mzninline{on_restart}
|
call-by-value evaluation strategy. Furthermore, the \mzninline{on_restart}
|
||||||
annotation only accepts the name of a nullary predicate. Therefore, users have
|
annotation only accepts the name of a nullary predicate. Therefore, users have
|
||||||
@ -299,7 +298,7 @@ activate a different neighbourhood for each restart
|
|||||||
|
|
||||||
\begin{listing}
|
\begin{listing}
|
||||||
\mznfile{assets/mzn/6_round_robin.mzn}
|
\mznfile{assets/mzn/6_round_robin.mzn}
|
||||||
\caption{\label{lst:6-round-robin} A predicate providing the round robin
|
\caption{\label{lst:6-round-robin} A predicate providing the round-robin
|
||||||
meta-heuristic}
|
meta-heuristic}
|
||||||
\end{listing}
|
\end{listing}
|
||||||
|
|
||||||
@ -330,7 +329,7 @@ We can use the constructs introduced above to implement alternative
|
|||||||
meta-heuristics such as simulated annealing. In particular, we use
|
meta-heuristics such as simulated annealing. In particular, we use
|
||||||
\mzninline{restart_without_objective} to tell the solver not to add the
|
\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
|
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
|
to decide whether a new solution is globally the best one seen so far, and only
|
||||||
output those (to maintain the convention of \minizinc\ solvers that the last
|
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).
|
solution printed at any point in time is the currently best known one).
|
||||||
|
|
||||||
@ -345,9 +344,9 @@ through the built-in variable \mzninline{_objective}. A more interesting example
|
|||||||
is a simulated annealing strategy. When using this strategy, the solutions that
|
is a simulated annealing strategy. When using this strategy, the solutions that
|
||||||
the solver finds are no longer required to steadily improve in quality. Instead,
|
the solver finds are no longer required to steadily improve in quality. Instead,
|
||||||
we ask the solver to find a solution that is a significant improvement over the
|
we ask the solver to find a solution that is a significant improvement over the
|
||||||
previous solution. Over time we decrease the amount by which we require the
|
previous solution. Over time, we decrease the amount by which we require the
|
||||||
solution needs to improve until we are just looking for any improvements. This
|
solution needs to improve until we are just looking for any improvements. This
|
||||||
\gls{meta-search} can help improving the qualities of solutions quickly and
|
\gls{meta-search} can help improve the qualities of solutions quickly and
|
||||||
thereby reaching the optimal solution quicker. This strategy is also easy to
|
thereby reaching the optimal solution quicker. This strategy is also easy to
|
||||||
express using our restart-based modelling:
|
express using our restart-based modelling:
|
||||||
|
|
||||||
@ -365,29 +364,29 @@ on. We can model this strategy restarts as such:
|
|||||||
\mznfile{assets/mzn/6_lex_minimize.mzn}
|
\mznfile{assets/mzn/6_lex_minimize.mzn}
|
||||||
|
|
||||||
The lexicographic objective changes the objective at each stage in the
|
The lexicographic objective changes the objective at each stage in the
|
||||||
evaluation. Initially the stage is 1. Otherwise is we have an UNSAT result, then
|
evaluation. Initially the stage is 1. Otherwise, is we have an unsatisfiable
|
||||||
the last stage has been completed (proved optimal). We increase the stage by one
|
result, then the last stage has been completed (proved optimal). We increase the
|
||||||
if we have stages to go otherwise we finish. Otherwise if the last all was SAT
|
stage by one if we have stages to go otherwise we finish. Otherwise, if the last
|
||||||
we maintain the same stage, and store the objective value (for this stage) in
|
all was SAT we maintain the same stage, and store the objective value (for this
|
||||||
the \mzninline{best} array. For normal computation we fix all the earlier stage
|
stage) in the \mzninline{best} array. For normal computation we fix all the
|
||||||
variables to their best value. If we are not in the first run for a stage we add
|
earlier stage variables to their best value. If we are not in the first run for
|
||||||
the branch and bound cut to try to find better solutions. Finally we set the
|
a stage we add the branch and bound cut to try to find better solutions.
|
||||||
objective to be the objective for the current stage.
|
Finally, we set the objective to be the objective for the current stage.
|
||||||
|
|
||||||
There is not always a clear order of importance for different objectives in a
|
There is not always a clear order of importance for different objectives in a
|
||||||
problem. In these cases we might instead look for a number of diverse solutions
|
problem. In these cases we might instead look for a number of diverse solutions
|
||||||
and allow the user to pick the most acceptable options. The following fragment
|
and allow the user to pick the most acceptable options. The following fragment
|
||||||
shows a \gls{meta-search} for the pareto optimality of a pair of objectives:
|
shows a \gls{meta-search} for the Pareto optimality of a pair of objectives:
|
||||||
|
|
||||||
\mznfile{assets/mzn/6_pareto_optimal.mzn}
|
\mznfile{assets/mzn/6_pareto_optimal.mzn}
|
||||||
|
|
||||||
In this implementation we keep track of the number of solutions found so far
|
In this implementation we keep track of the number of solutions found so far
|
||||||
using \mzninline{nsol}. There is a maximum number we can handle
|
using \mzninline{nsol}. There is a maximum number we can handle
|
||||||
(\mzninline{ms}). At the start the number of solutions is 0. If we find no
|
(\mzninline{ms}). At the start the number of solutions is 0. If we find no
|
||||||
solutions we finish the entire search. Otherwise we record that we have one more
|
solutions, then we finish the entire search. Otherwise, we record that we have
|
||||||
solution. We store the solution values in \mzninline{s1} and \mzninline{s2}
|
one more solution. We store the solution values in \mzninline{s1} and
|
||||||
arrays. Before each restart we add constraints removing pareto dominated
|
\mzninline{s2} arrays. Before each restart we add constraints removing Pareto
|
||||||
solutions, based on each previous solution.
|
dominated solutions, based on each previous solution.
|
||||||
|
|
||||||
\section{Compilation of Meta-Search Specifications}\label{sec:6-solver-extension}
|
\section{Compilation of Meta-Search Specifications}\label{sec:6-solver-extension}
|
||||||
|
|
||||||
@ -410,10 +409,10 @@ executed by standard \gls{cp} solvers with a small set of simple extensions.
|
|||||||
|
|
||||||
The neighbourhood definitions from the previous section have an important
|
The neighbourhood definitions from the previous section have an important
|
||||||
property that makes them easy to compile to standard \flatzinc: they are defined
|
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
|
in terms of standard \minizinc\ expressions, except for a few new built-in
|
||||||
built-in functions. When the neighbourhood predicates are evaluated in the
|
functions. When the neighbourhood predicates are evaluated in the \minisearch\
|
||||||
\minisearch\ way, the \minisearch\ runtime implements those built-in functions,
|
way, the \minisearch\ runtime implements those built-in functions, computing the
|
||||||
computing the correct value whenever a predicate is evaluated.
|
correct value whenever a predicate is evaluated.
|
||||||
|
|
||||||
Instead, the compilation scheme presented below uses a limited form of
|
Instead, the compilation scheme presented below uses a limited form of
|
||||||
\emph{partial evaluation}: parameters known at compile time will be fully
|
\emph{partial evaluation}: parameters known at compile time will be fully
|
||||||
@ -426,8 +425,8 @@ evaluation is performed by hijacking the solver's own capabilities: It will
|
|||||||
automatically perform the evaluation of the new functions by propagating the new
|
automatically perform the evaluation of the new functions by propagating the new
|
||||||
constraints.
|
constraints.
|
||||||
|
|
||||||
To compile an \gls{lns} specification to standard \flatzinc, the \minizinc\ compiler
|
To compile a \gls{lns} specification to standard \flatzinc{}, the \minizinc\
|
||||||
performs four simple steps:
|
compiler performs four simple steps:
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Replace the annotation \mzninline{::on_restart("X")} with a call to
|
\item Replace the annotation \mzninline{::on_restart("X")} with a call to
|
||||||
@ -506,13 +505,12 @@ Calls to the random number functions have been renamed by appending
|
|||||||
The definition of these new functions follows the same pattern as for
|
The definition of these new functions follows the same pattern as for
|
||||||
\mzninline{sol}, \mzninline{status}, and \mzninline{last_val}. The MiniZinc
|
\mzninline{sol}, \mzninline{status}, and \mzninline{last_val}. The MiniZinc
|
||||||
definition of the \mzninline{uniform_nbh} function is shown in
|
definition of the \mzninline{uniform_nbh} function is shown in
|
||||||
\Cref{lst:6-int-rnd}.%
|
\Cref{lst:6-int-rnd}. \footnote{Random number functions need to be marked as
|
||||||
\footnote{Random number functions need to be marked as \mzninline{::impure} for
|
\mzninline{::impure} for the compiler not to apply \gls{cse}
|
||||||
the compiler not to apply \gls{cse} \autocite{stuckey-2013-functions} if they
|
\autocite{stuckey-2013-functions} if they are called multiple times with the
|
||||||
are called multiple times with the same arguments.}%
|
same arguments.} Note that the function accepts variable arguments \mzninline{l}
|
||||||
Note that the function accepts variable arguments \mzninline{l} and
|
and \mzninline{u}, so that it can be used in combination with other functions,
|
||||||
\mzninline{u}, so that it can be used in combination with other functions, such
|
such as \mzninline{sol}.
|
||||||
as \mzninline{sol}.
|
|
||||||
|
|
||||||
\begin{listing}
|
\begin{listing}
|
||||||
\mznfile{assets/mzn/6_uniform_slv.mzn}
|
\mznfile{assets/mzn/6_uniform_slv.mzn}
|
||||||
@ -524,7 +522,7 @@ as \mzninline{sol}.
|
|||||||
|
|
||||||
We will now show the minimal extensions required from a solver to interpret the
|
We will now show the minimal extensions required from a solver to interpret the
|
||||||
new \flatzinc\ constraints and, consequently, to execute \gls{lns} definitions
|
new \flatzinc\ constraints and, consequently, to execute \gls{lns} definitions
|
||||||
expressed in \minizinc.
|
expressed in \minizinc{}.
|
||||||
|
|
||||||
First, the solver needs to parse and support the restart annotations
|
First, the solver needs to parse and support the restart annotations
|
||||||
of~\cref{lst:6-restart-ann}. Many solvers already support all this
|
of~\cref{lst:6-restart-ann}. Many solvers already support all this
|
||||||
@ -541,13 +539,13 @@ new constraints the solver needs to:
|
|||||||
\item \mzninline{last_val(x, lx)} (variants): constrain \mzninline{lx} to take
|
\item \mzninline{last_val(x, lx)} (variants): constrain \mzninline{lx} to take
|
||||||
the last value assigned to \mzninline{x} during search. If no value was
|
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
|
ever assigned, it has no effect. Note that many solvers (in particular
|
||||||
SAT and LCG solvers) already track \mzninline{last_val} for their
|
\gls{sat} and \gls{lcg} solvers) already track \mzninline{last_val} for their
|
||||||
variables for use in search. To support \gls{lns} a solver must at least
|
variables for use in search. To support \gls{lns} a solver must at least
|
||||||
track the \emph{last value} of each of the variables involved in such a
|
track the \emph{last value} of each of the variables involved in such a
|
||||||
constraint. This is straightforward by using the \mzninline{last_val}
|
constraint. This is straightforward by using the \mzninline{last_val}
|
||||||
propagator itself. It wakes up whenever the first argument is fixed, and
|
propagator itself. It wakes up whenever the first argument is fixed, and
|
||||||
updates the last value (a non-backtrackable value).
|
updates the last value (a non-backtrackable value).
|
||||||
\item random number functions: fix their variable argument to a random number
|
\item Random number functions: fix their variable argument to a random number
|
||||||
in the appropriate probability distribution.
|
in the appropriate probability distribution.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
@ -557,8 +555,8 @@ propagate these constraints in the root node of the search.
|
|||||||
|
|
||||||
Modifying a solver to support this functionality is straightforward if it
|
Modifying a solver to support this functionality is straightforward if it
|
||||||
already has a mechanism for posting constraints during restarts. We have
|
already has a mechanism for posting constraints during restarts. We have
|
||||||
implemented these extensions for both Gecode (110 new lines of code) and Chuffed
|
implemented these extensions for both \gls{gecode} (110 new lines of code) and
|
||||||
(126 new lines of code).
|
\gls{chuffed} (126 new lines of code).
|
||||||
|
|
||||||
For example, consider the model from \cref{lst:6-basic-complete} again.
|
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
|
\Cref{lst:6-flat-pred} shows a part of the \flatzinc\ that arises from compiling
|
||||||
@ -590,7 +588,7 @@ presentation.
|
|||||||
|
|
||||||
\begin{listing}
|
\begin{listing}
|
||||||
\mznfile{assets/mzn/6_basic_complete_transformed.mzn}
|
\mznfile{assets/mzn/6_basic_complete_transformed.mzn}
|
||||||
\caption{\label{lst:6-flat-pred} \flatzinc\ that results from compiling \\
|
\caption{\label{lst:6-flat-pred} \flatzinc{} that results from compiling \\
|
||||||
\mzninline{basic_lns(uniformNeighbourhood(x,0.2))}.}
|
\mzninline{basic_lns(uniformNeighbourhood(x,0.2))}.}
|
||||||
\end{listing}
|
\end{listing}
|
||||||
|
|
||||||
@ -600,7 +598,7 @@ and \mzninline{b3} to \mzninline{false}. Therefore, the implication in
|
|||||||
\lref{line:6:x1:end} is not activated, leaving \mzninline{x[1]} unconstrained.
|
\lref{line:6:x1:end} is not activated, leaving \mzninline{x[1]} unconstrained.
|
||||||
The neighbourhood constraints are effectively switched off.
|
The neighbourhood constraints are effectively switched off.
|
||||||
|
|
||||||
When the solver restarts, all of the special propagators are re-executed. Now
|
When the solver restarts, all the special propagators are re-executed. Now
|
||||||
\mzninline{s} is not 1, and \mzninline{b1} will be set to \mzninline{true}. The
|
\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
|
\mzninline{float_random} propagator assigns \mzninline{rnd1} a new random value
|
||||||
and, depending on whether it is greater than \mzninline{0.2}, the Boolean
|
and, depending on whether it is greater than \mzninline{0.2}, the Boolean
|
||||||
@ -614,9 +612,10 @@ against being invoked before the first solution is found, since the
|
|||||||
solution has been recorded yet, but we use this simple example to illustrate how
|
solution has been recorded yet, but we use this simple example to illustrate how
|
||||||
these Boolean conditions are compiled and evaluated.
|
these Boolean conditions are compiled and evaluated.
|
||||||
|
|
||||||
\section{An Incremental Interface for Constraint Modelling Languages}\label{sec:6-incremental-compilation}
|
\section{An Incremental Interface for Constraint Modelling Languages}%
|
||||||
|
\label{sec:6-incremental-compilation}
|
||||||
|
|
||||||
As an alternative approach to run \gls{meta-search} algorithm we propose the
|
As an alternative approach to run \gls{meta-search} algorithm, we propose the
|
||||||
possibility of incremental flattening. The execution of any
|
possibility of incremental flattening. The execution of any
|
||||||
|
|
||||||
In order to support incremental flattening, the \nanozinc\ interpreter must be
|
In order to support incremental flattening, the \nanozinc\ interpreter must be
|
||||||
@ -649,7 +648,7 @@ structure~\autocite{warren-1983-wam}. The trail records all changes to the
|
|||||||
\nanozinc\ program:
|
\nanozinc\ program:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item the addition or removal of new variables or constraints,
|
\item The addition or removal of new variables or constraints,
|
||||||
\item changes made to the domains of variables,
|
\item changes made to the domains of variables,
|
||||||
\item additions to the \gls{cse} table, and
|
\item additions to the \gls{cse} table, and
|
||||||
\item substitutions made due to equality propagation.
|
\item substitutions made due to equality propagation.
|
||||||
|
Reference in New Issue
Block a user