496 lines
22 KiB
TeX
496 lines
22 KiB
TeX
%************************************************
|
|
\chapter{Review of Literature}\label{ch:background}
|
|
%************************************************
|
|
|
|
A goal shared between all programming languages is to provide a certain level of
|
|
abstraction: an assembly language allows you to abstract from the binary
|
|
instructions and memory positions; Low-level imperial languages, like FORTRAN,
|
|
were the first to allow you to abstract from the processor architecture of the
|
|
target machine; and nowadays writing a program requires little knowledge of the
|
|
actual workings of the hardware.
|
|
|
|
Freuder states that the ``Holy Grail'' of programming languages would be where
|
|
the user merely states the problem, and the computer solves it and that
|
|
\gls{constraint-modelling} is one of the biggest steps towards this goal to this
|
|
day \autocite*{freuder-1997-holygrail}. Different from imperative (and even
|
|
other declarative) languages, in a \cml\ the modeller does not describe how to
|
|
solve the problem, but rather provides the problem requirements. You could say
|
|
that a constraint model actually describes the solution to the problem.
|
|
|
|
In a constraint model, instead of specifying the manner in which we can find the
|
|
solution, we give a concise description of the problem. We describe what we
|
|
already know, the \glspl{parameter}, what we wish to know, the \glspl{variable},
|
|
and the relationships that should exist between them, the \glspl{constraint}.
|
|
|
|
This type of combinatorial problem is typically called a \gls{csp}. Many \cmls\
|
|
also support the modelling of \gls{cop}, where a \gls{csp} is augmented with an
|
|
\gls{objective} \(z\). In this case the goal is to find an solution that
|
|
satisfies all \glspl{constraint} while minimising (or maximising) \(z\).
|
|
|
|
Although a constraint model does not contain any instructions to find a suitable
|
|
solution, dedicated solving programs exist
|
|
|
|
these models can generally be given to a dedicated solving program, or
|
|
\gls{solver} for short, that can find a solution that fits the requirements of
|
|
the model.
|
|
|
|
\begin{listing}
|
|
\pyfile{assets/py/2_dyn_knapsack.py}
|
|
\caption{\label{lst:2-dyn-knapsack} A Python program that solves a 0-1 knapsack
|
|
problem using dynamic programming}
|
|
\end{listing}
|
|
|
|
\begin{example}%
|
|
\label{ex:back-knapsack}
|
|
|
|
Let us consider the following scenario: Packing for a weekend trip, I have to
|
|
decide which toys to bring for my dog, Audrey. We only have a small amount of
|
|
space left in the car, so we cannot bring all the toys. Since Audrey gets
|
|
enjoys playing with some toys more than others, we can now try and pick the
|
|
toys that bring Audrey the most amount of joy, but still fit in the car.
|
|
|
|
One way to solve this problem is to try all combinations of toys, but this is
|
|
time intensive and quickly grows with the number of toys considered (which one
|
|
would quickly realise trying to pack a car \(2^{|\text{toys}|}\) different
|
|
ways).
|
|
|
|
An educated reader in optimisation problems might recognise that this is a
|
|
variation on the widely known \gls{knapsack}, more specifically a \textit{0--1
|
|
knapsack problem} \autocite[13--67]{silvano-1990-knapsack}. A commonly used
|
|
solution to this problem is based on dynamic programming. An implementation of
|
|
this approach is shown in \cref{lst:2-dyn-knapsack}. The use of dynamic
|
|
programming avoid the exponential growth of the problem when increasing the
|
|
number of toys.
|
|
|
|
Although expert knowledge can sometimes bring you an efficient solution to a
|
|
known problem, it should be noted that not all problems will easily map to
|
|
well known (and studied) problems. Even when part of a problem finds an
|
|
equivalent in a well studied problem, the overall problem might still contain
|
|
requirements that impair you from using known algorithms to solve the problem.
|
|
For example, if wanted to bring toys with different colours, then the
|
|
algorithm in \cref{lst:2-dyn-knapsack} would have to be drastically changed.
|
|
\Gls{constraint-modelling} can offer a more flexible alternative that requires
|
|
less expert knowledge.
|
|
|
|
The following set of equations describe this knapsack problem as a \gls{cop}:
|
|
|
|
\begin{equation*}
|
|
\text{maximise}~z~\text{subject to}~
|
|
\begin{cases}
|
|
S \subseteq T \\
|
|
z = \sum_{i \in S} joy(i) \\
|
|
\sum_{i \in S} space(i) < C \\
|
|
\end{cases}
|
|
\end{equation*}
|
|
|
|
In these equations \(S\) is set \gls{variable}. It contains the selection of
|
|
toys that will be packed for the trip. \(z\) is the objective \gls{variable}
|
|
that is maximised to find the optimal selections of toys to pack. The
|
|
\gls{parameter} \(T\) is the set of all the toys. The \(joy\) and \(space\)
|
|
functions are \glspl{parameter} used to map toys, \( t \in T\), to a value
|
|
depicting the amount of enjoyment and space required respectively. Finally,
|
|
the \gls{parameter} \(C\) is that depicts the total space that is left in the
|
|
car before packing the toys.
|
|
|
|
This constraint model gives a abstract mathematical definition of the
|
|
\gls{cop} that would be easy to adjust to changes in the requirements. To
|
|
solve instances of this problem, however, these instances have to be
|
|
transformed into input accepted by a \gls{solver}. \cmls\ are designed to
|
|
allow the modeller to express combinatorial problems in a similar fashion to
|
|
the above mathematical definition and generate a definition that can be used
|
|
by dedicated solvers.
|
|
|
|
\end{example}
|
|
|
|
In the remainder of this chapter we will first, in \cref{sec:back-minizinc}
|
|
introduce \minizinc\ as the leading \cml\ used within this thesis.
|
|
\cref{sec:back-mzn-interpreter} explains the process that the current \minizinc\
|
|
interpreter uses to translate a \minizinc\ model into a solver-level constraint
|
|
model. Then, \cref{sec:back-other-languages} introduces alternative \cmls\ and
|
|
compares their functionality to \minizinc{}. Finally, \cref{sec:back-term} and
|
|
\cref{sec:back-clp} survey the closely related fields of \gls{term-rewriting}
|
|
and \gls{clp}.
|
|
|
|
\section{\glsentrytext{minizinc}}%
|
|
\label{sec:back-minizinc}
|
|
|
|
\minizinc\ is a high-level, solver- and data-independent modelling language for
|
|
discrete satisfiability and optimisation problems
|
|
\autocite{nethercote-2007-minizinc}. Its expressive language and extensive
|
|
library of constraints allow users to easily model complex problems.
|
|
|
|
\begin{listing}
|
|
\mznfile{assets/mzn/back_knapsack.mzn}
|
|
\caption{\label{lst:back-mzn-knapsack} A \minizinc\ model describing a 0-1 knapsack
|
|
problem}
|
|
\end{listing}
|
|
|
|
\begin{example}%
|
|
\label{ex:back-mzn-knapsack}
|
|
|
|
Let us introduce the language by modelling the problem from
|
|
\cref{ex:back-knapsack}. A \minizinc\ model encoding this problem is shown in
|
|
\cref{lst:back-mzn-knapsack}.
|
|
|
|
The model starts with the declaration of the \glspl{parameter}.
|
|
\Lref{line:back:knap:toys} declares an enumerated type that represents all
|
|
possible toys, \(T\) in the mathematical model in the example.
|
|
\Lref{line:back:knap:joy,line:back:knap:space} declare arrays mapping from
|
|
toys to integer values, these represent the functional mappings \(joy\) and
|
|
\(space\). Finally, \lref{line:back:knap:left} declares an integer
|
|
\gls{parameter} to represent the car capacity as an equivalent to \(C\).
|
|
|
|
The model then declares its \glspl{variable}. \Lref{line:back:knap:sel}
|
|
declares the main \gls{variable} \mzninline{selection}, which represents the
|
|
selection of toys to be packed. \(S\) in our earlier model. We also declare
|
|
the variable \mzninline{total_joy}, on \lref{line:back:knap:tj}, which is
|
|
functionally defined to be the summation of all the joy for the toy picked in
|
|
our selection.
|
|
|
|
Finally, the model contains a constraint, on \lref{line:back:knap:con}, to
|
|
ensure we do not exceed the given capacity and states the goal for the solver:
|
|
to maximise the value of the variable \mzninline{total_joy}.
|
|
\end{example}
|
|
|
|
One might note that, although more textual and explicit, the \minizinc\ model
|
|
definition is very similar to our earlier mathematical definition.
|
|
|
|
Given ground assignments to input \glspl{parameter}, a \minizinc\ model is
|
|
translated (via a process called \emph{flattening}) into a set of variables and
|
|
primitive constraints.
|
|
|
|
Given the assignments
|
|
|
|
\begin{mzn}
|
|
TOYS = {football, tennisball, stuffed_elephant};
|
|
toy_joy = [63, 12, 100];
|
|
toy_space = [32, 8, 40];
|
|
space_left = 44;
|
|
\end{mzn}
|
|
|
|
the following model is the result of flattening:
|
|
|
|
\begin{mzn}
|
|
var 0..1: selection_0;
|
|
var 0..1: selection_1;
|
|
var 0..1: selection_2;
|
|
var 0..175: total_joy:: is_defined_var;
|
|
constraint int_lin_le([32,8,40],[selection_0,selection_1,selection_2],44);
|
|
constraint int_lin_eq([63,12,100,-1],[selection_0,selection_1,selection_2,total_joy],0):: defines_var(total_joy);
|
|
solve maximize total_joy;
|
|
\end{mzn}
|
|
|
|
This \emph{flat} problem will be passed to some \gls{solver}, which will attempt
|
|
to determine an assignment to each decision variable \mzninline{solection_i} and
|
|
\mzninline{total_joy} that satisfies all constraints and maximises
|
|
\mzninline{total_joy}, or report that there is no such assignment.
|
|
|
|
\subsection{Model Structure}%
|
|
\label{subsec:back-mzn-structure}
|
|
|
|
|
|
|
|
\subsection{MiniZinc Types}%
|
|
\label{subsec:back-mzn-type}
|
|
|
|
\jip{TODO:\@ Here we talk about the different types in \minizinc. The main types
|
|
used in \minizinc\ are Booleans, integers, floating point numbers, sets of
|
|
integers, enumerated types. These types can be used both as normal
|
|
\glspl{parameter} and as \glspl{variable}. \minizinc\ is allows all these
|
|
types to be contained in arrays. Unlike other languages, arrays can have a
|
|
user defined index set. Although the index can start at any value the set is
|
|
forced to be a range. \minizinc\ also has an annotation type, annotations can
|
|
be either a declared name or a function call. These annotations can be
|
|
attached to \minizinc\ expressions, declarations, or constraints. }
|
|
|
|
\jip{This should explain array types}
|
|
|
|
\subsection{MiniZinc Expressions}%
|
|
\label{subsec:back-mzn-expr}
|
|
|
|
One of the powers of the \minizinc\ language is the extensive expression
|
|
language that it offers to help modellers create models that are intuitive to
|
|
read, but are transformed to fit the structure best suited to the chosen
|
|
\gls{solver}. We will now briefly discussed the most important \minizinc\
|
|
expressions and the general methods employed when flattening them. For a
|
|
detailed overview of all \minizinc\ you can consult the full syntactic structure
|
|
of the \minizinc\ expressions in \minizinc\ 2.5.5 can be found in
|
|
\cref{sec:mzn-grammar-expressions}. Nethercote et al.\ and Mariott et al.\ offer
|
|
a detailed discussion of the expression language of \minizinc\ and its
|
|
predecessor \zinc\ respectively
|
|
\autocite*{nethercote-2007-minizinc,marriott-2008-zinc}.
|
|
|
|
\Glspl{global} are the basic building blocks in the \minizinc\ language. These
|
|
expressions capture common (complex) relations between variables. \Glspl{global}
|
|
in the \minizinc\ language are used as function calls. An example of a
|
|
\gls{global} is
|
|
|
|
\begin{mzn}
|
|
predicate knapsack(
|
|
array [int] of int: w,
|
|
array [int] of int: p,
|
|
array [int] of var int: x,
|
|
var int: W,
|
|
var int: P,
|
|
);
|
|
\end{mzn}
|
|
|
|
This \gls{global} expresses the knapsack relationship, where the
|
|
\glspl{parameter} \mzninline{w} are the weights of the items, \mzninline{p} are
|
|
the profit for each items, the \glspl{variable} in \mzninline{x} represent the
|
|
amount of time the items are present in the knapsack, and \mzninline{W} and
|
|
\mzninline{P}, repectively, represent the weight and profit of the knapsack.
|
|
|
|
Note that the usage of this \gls{global} might have simplified the \minizinc\
|
|
model in \cref{ex:back-mzn-knapsack}:
|
|
|
|
\begin{mzn}
|
|
constraint knapsack(toy_space, toy_joy, set2bool(selection), total_joy, space);
|
|
\end{mzn}
|
|
|
|
The usage of this \gls{global} has the additional benefit that the knapsack
|
|
structure of the problem is then known to the \gls{solver} which might implement
|
|
special handling of the relationship.
|
|
|
|
Although \minizinc\ contains a extensive library of \glspl{global}, many
|
|
problems contain constraints that aren't covered by a \gls{global}. There are
|
|
many other expression forms in \minizinc\ that can help modellers express a
|
|
constraint.
|
|
|
|
\Gls{operator} symbols in \minizinc\ are used as short hands for \minizinc\
|
|
functions that can be used to transform or combine other expressions. For
|
|
example the constraint
|
|
|
|
\begin{mzn}
|
|
constraint not (a + b < c);
|
|
\end{mzn}
|
|
|
|
contains the infix \glspl{operator} \mzninline{+} and \mzninline{<}, and the
|
|
prefix \gls{operator} \mzninline{not}.
|
|
|
|
These \glspl{operator} will be evaluated using the addition, less-than
|
|
comparison, and Boolean negation functions respectively. Although the
|
|
\gls{operator} syntax for \glspl{variable} and \glspl{parameter} is the same,
|
|
different (overloaded) versions of these functions will be used during
|
|
flattening. For \glspl{parameter} types the result of the function can be
|
|
directly computed, but when flattening these functions with \glspl{variable}
|
|
types a new variable for its result must be introduced and a constraints
|
|
enforcing the functional relationship.
|
|
|
|
The choice between different expressions can often be expressed using a
|
|
\gls{conditional} expression, sometimes better known as an ``if-then-else''
|
|
expressions. You could, for example, force that the absolute value of
|
|
\mzninline{a} is bigger than \mzninline{b} using the constraint
|
|
|
|
\begin{mzn}
|
|
constraint if b >= 0 then a > b else b < a endif;
|
|
\end{mzn}
|
|
|
|
In \minizinc\ the result of an \gls{conditional} expression is, however, not
|
|
contained to Boolean types. The condition in the expression, the ``if'', must be
|
|
of a Boolean type, but as long as the different sides of the \gls{conditional}
|
|
expression are the same type it is a valid conditional expression. This can be
|
|
used to, for example, define an absolute value function for integer
|
|
\gls{parameter}:
|
|
|
|
\begin{mzn}
|
|
function int: abs(int: a) =
|
|
if a >= 0 then a else -a endif;
|
|
\end{mzn}
|
|
|
|
When the condition does not contain any \glspl{variable}, then the flattening of
|
|
a \gls{conditional} expression will result in one of the side of the
|
|
expressions. If, however, the condition does contain a \glspl{variable}, then
|
|
the result of the condition cannot be defined during the flattening. Instead,
|
|
the expression will introduce a new variable for the result of the expression
|
|
and a constraint to enforce the functional relationship. In \minizinc\ special
|
|
\mzninline{if_then_else} \glspl{global} are available to implement this
|
|
relationship.
|
|
|
|
For the selection of an element from an \gls{array}, instead of between
|
|
different expressions, the \minizinc\ language uses an \gls{array} access syntax
|
|
similar to most other languages. The expression \mzninline{a[i]} selects the
|
|
element with index \mzninline{i} from the array \mzninline{a}. Note this is not
|
|
necessarily the \(\mzninline{i}^{\text{th}}\) element because \minizinc\ allows
|
|
modellers to provide a custom index set.
|
|
|
|
Like the previous expressions, the selector \mzninline{i} can be both a
|
|
\gls{parameter} or a \gls{variable}. If the expression is a \gls{variable}, then
|
|
the expression is flattened as being an \mzninline{element} function. Otherwise,
|
|
the flattening will replace the \gls{array} access expression by the element
|
|
referenced by expression.
|
|
|
|
\Gls{array} \glspl{comprehension} are expressions can be used to compose
|
|
\gls{array} objects. This allows modellers to create \glspl{array} that are not
|
|
given directly as input to the model or are a declared collection of variables.
|
|
|
|
\Gls{generator} expressions, \mzninline{[E | G where F]}, consist of three
|
|
parts:
|
|
|
|
\begin{description}
|
|
\item[\mzninline{G}] The generator expression which assigns the values of
|
|
collections to identifiers,
|
|
\item[\mzninline{F}] an optional filtering condition, which has to evaluate to
|
|
\mzninline{true} for the iteration to be included in the array,
|
|
\item[\mzninline{E}] and the expression that is evaluation for each iteration
|
|
when the filtering condition succeeds.
|
|
\end{description}
|
|
|
|
The following example composes a array that contains the doubled even values of
|
|
an \gls{array} \mzninline{x}.
|
|
|
|
\begin{minizinc}
|
|
[ xi * 2 | xi in x where x mod 2 == 0]
|
|
\end{minizinc}
|
|
|
|
The evaluated expression will be added to the new array. This means that the
|
|
type of the array will primarily depend on the type of the expression. However,
|
|
in recent versions of \minizinc\ both the collections over which we iterate and
|
|
the filtering condition could have a \gls{variable} type. Since we then cannot
|
|
decise during flattening if an element is present in the array, the elements
|
|
will be made of an \gls{optional} type. This means that the solver still will
|
|
decide if the element is present in the array or if it takes a special
|
|
``absent'' value (\mzninline{<>}).
|
|
|
|
Finally, \glspl{let} are the primary scoping mechanism in the \minizinc\
|
|
language, together with function definitions. A \gls{let} allows a modeller to
|
|
provide a list of definitions, flattened in order, that can be used in its
|
|
resulting definition. There are three main purposes for \glspl{let}:
|
|
|
|
\begin{enumerate}
|
|
\item To name an intermediate expression so it can be used multiple times (or
|
|
to simplify the expression). For example, the constraint
|
|
|
|
\begin{mzn}
|
|
constraint let { var int: tmp = x div 2; } in tmp mod 2 == 0 \/ tmp = 0;
|
|
\end{mzn}
|
|
|
|
constrains that half of \mzninline{x} is even or zero.
|
|
|
|
\item To introduce a scoped \gls{variable}. For example, the constraint
|
|
|
|
\begin{mzn}
|
|
let {var -2..2: slack;} in x + slack = y;
|
|
\end{mzn}
|
|
|
|
constrains that \mzninline{x} and \mzninline{y} are at most two apart.
|
|
|
|
\item To constrain the resulting expression. For example, the following function
|
|
|
|
\begin{mzn}
|
|
function var int: int_times(var int: x, var int: y) =
|
|
let {
|
|
var int: z;
|
|
constraint pred_int_times(x, y, z);
|
|
} in z;
|
|
\end{mzn}
|
|
|
|
returns a new \gls{variable} \mzninline{z} that is constrained to be the
|
|
multiplication of \mzninline{x} and \mzninline{y} by the relational
|
|
multiplication constraint \mzninline{pred_int_times}.
|
|
\end{enumerate}
|
|
|
|
An important detail in flattening \glspl{let} is that any variables that are
|
|
introduced might need to be renamed in the resulting solver level model.
|
|
Different from top-level definitions, the variables declared in \glspl{let} can
|
|
be flattened multiple times when used in loops, function definitions (that are
|
|
called multiple times), and \gls{array} \glspl{comprehension}. In these cases the
|
|
flattener must assign any variables in the \gls{let} a new name and use this
|
|
name in any subsequent definitions and in the resulting expression.
|
|
|
|
\subsection{Handling Undefined Expressions}%
|
|
\label{subsec:back-mzn-partial}
|
|
|
|
Some expressions in the \cmls\ do not always have a well-defined result.
|
|
Examples of such expressions in \minizinc\ are:
|
|
|
|
\begin{itemize}
|
|
\item Division (or modulus) when the divisor is zero: \\ \mzninline{x div 0 =
|
|
@??@}
|
|
|
|
\item Array access when the index is outside of the given index set: \\
|
|
\mzninline{array1d(1..3, [1,2,3])[0] = @??@}
|
|
|
|
\item Finding the minimum or maximum or an empty set: \\ \mzninline{min({})
|
|
=@??@}
|
|
|
|
\item Computing the square root of a negative value: \\ \mzninline{sqrt(-1) =
|
|
@??@}
|
|
|
|
\end{itemize}
|
|
|
|
The existence of undefined expressions can cause confusion in \cmls. There is
|
|
both the question of what happens when an undefined expression is evaluated and
|
|
at what point during the process undefined values will be resolved, during
|
|
flattening or at solving time.
|
|
|
|
Frisch and Stuckey define three semantic models to deal with the undefinedness
|
|
in \cmls\ \autocite*{frisch-2009-undefinedness}:
|
|
|
|
\begin{description}
|
|
|
|
\item[Strict] \cmls\ employing a ``strict'' undefinedness semantic do not
|
|
allow any undefined behaviour during the evaluation of the constraint model.
|
|
If during the flattening or solving process an expression is found to be
|
|
undefined, then any expressions in which it is used is also marked as
|
|
undefined. In the end, this means that the occurrence of a single undefined
|
|
expression will mark the full model as undefined.
|
|
|
|
\item[Kleene] The ``Kleene'' semantic treat undefined expressions as
|
|
expressions for which not enough information is available. This if an
|
|
expression contains undefined sub-expression, it will only be marked as
|
|
undefined if the value of the sub-expression is required to compute its
|
|
result. Take for example the expression \mzninline{false -> E}. Here, when
|
|
\mzninline{E} is undefined the result of the expression can still be said to
|
|
be \mzninline{true}, since the value of \mzninline{E} does not influence the
|
|
result of the expression. However, if we take the expression \mzninline{true
|
|
/\ E}, then when \mzninline{E} is undefined the overall expression is also
|
|
undefined since the value of the expression cannot be determined.
|
|
|
|
\item[Relational] The ``relational'' semantic follows from the fact that all
|
|
expressions in \cmls\ will eventually become part of a relational
|
|
constraint. So even though a (functional) expression in itself might not
|
|
have a well-defined result, we can still decide whether its surrounding
|
|
relationship holds. For example, the expression \mzninline{x div 0} is
|
|
undefined, but the relationship \mzninline{int_div(x,0,y)} can be said to be
|
|
\mzninline{false}. It can be said that the relational semantic will make the
|
|
closest relational expression that contains an undefined expression
|
|
\mzninline{false}.
|
|
|
|
\end{description}
|
|
|
|
In practice, it is often natural to guard against undefined behaviour using
|
|
Boolean logic. Relational semantics therefore often feel the most natural for
|
|
the users of constraint modelling languages. This is why the \minizinc\ uses
|
|
relational semantics during its evaluation.
|
|
|
|
For example, one might deal with a zero divisor using a disjunction:
|
|
|
|
\begin{mzn}
|
|
constraint d == 0 \/ a div d < 3;
|
|
\end{mzn}
|
|
|
|
In this case we expect the undefinedness of the division to be contained within
|
|
the second part of the disjunction. This corresponds to ``relational''
|
|
semantics. \jip{TODO:\@ This also corresponds to Kleene semantics, maybe I
|
|
should use a different example}
|
|
|
|
Frisch and Stuckey also show that different \glspl{solver} often employ
|
|
different semantics \autocite*{frisch-2009-undefinedness}. It is
|
|
therefore important that, during the flattening process, any potentially
|
|
undefined expression gets replaced by an equivalent model that is still valid
|
|
under a strict semantic. Essentially eliminating the existence of undefined
|
|
expressions in the \gls{solver} model.
|
|
|
|
\section{The Current \glsentrytext{minizinc} Interpreter}%
|
|
\label{sec:back-mzn-interpreter}
|
|
|
|
\section{Other Constraint Modelling Languages}%
|
|
\label{sec:back-other-languages}
|
|
|
|
\section{ACD Term Rewriting}%
|
|
\label{sec:back-term}
|
|
|
|
\section{Constraint Logic Programming}%
|
|
\label{sec:back-clp}
|