Work on half-reif experiments
This commit is contained in:
parent
6fd413b2ed
commit
cfd29fc909
@ -300,6 +300,12 @@
|
||||
description={},
|
||||
}
|
||||
|
||||
\newglossaryentry{qcp-max}{
|
||||
name={QCP-max},
|
||||
description={},
|
||||
}
|
||||
|
||||
|
||||
\newglossaryentry{reification}{
|
||||
name={reification},
|
||||
description={},
|
||||
|
@ -2,6 +2,8 @@
|
||||
\chapter{Background}\label{ch:background}
|
||||
%************************************************
|
||||
|
||||
\jip{TODO:\ Mention something about LCG.}
|
||||
|
||||
\noindent{}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,
|
||||
|
@ -1023,38 +1023,21 @@ of model output expressions and annotations. We will release our implementation
|
||||
under an open-source license and can make it available to the reviewers upon
|
||||
request.
|
||||
|
||||
The implementation is not optimised for performance yet, but was created as a
|
||||
faithful implementation of the developed concepts, in order to evaluate their
|
||||
suitability and provide a solid baseline for future improvements. In the
|
||||
following we present experimental results on basic flattening performance as
|
||||
well as incremental flattening and solving that demonstrate the efficiency
|
||||
gains that are possible thanks to the new architecture.
|
||||
The implementation is not optimised for performance yet, but was created as a faithful implementation of the developed concepts, in order to evaluate their suitability and provide a solid baseline for future improvements.
|
||||
In the following we present experimental results on basic flattening performance as well as incremental flattening and solving that demonstrate the efficiency gains that are possible thanks to the new architecture.
|
||||
|
||||
We selected 20 models from the annual \minizinc\ challenge and compiled 5
|
||||
instances of each model to \flatzinc{}, using the current \minizinc\ release
|
||||
version 2.4.3 and the new prototype system. In both cases we use the standard
|
||||
\minizinc\ library of global constraints (\ie\ we decompose those constraints
|
||||
rather than using solver built-ins, in order to stress-test the flattening). We
|
||||
measured pure flattening time, \ie\ without time required to parse and type check
|
||||
in version 2.4.3, and without time required for compilation to \microzinc\ in
|
||||
the new system (compilation is usually very fast). Times are averages of 10
|
||||
runs.\footnote{All models obtained from
|
||||
\url{https://github.com/minizinc/minizinc-benchmarks}:
|
||||
\texttt{\justify{}accap, amaze, city-position, community-detection,
|
||||
depot-placement, freepizza, groupsplitter, kidney-exchange, median-string,
|
||||
multi-knapsack, nonogram, nside, problem, rcpsp-wet, road-cons, roster,
|
||||
stack-cuttingstock, steelmillslab, train, triangular, zephyrus}.}
|
||||
We selected 20 models from the annual \minizinc\ challenge and compiled 5 instances of each model to \flatzinc{}, using the current \minizinc\ release version 2.5.5 and the new prototype system.
|
||||
In both cases we use the standard \minizinc\ library of global constraints (\ie\ we decompose those constraints rather than using solver built-ins, in order to stress-test the flattening).
|
||||
We measured pure flattening time, \ie\ without time required to parse and type check in version 2.5.5, and without time required for compilation to \microzinc\ in the new system (compilation is usually very fast).
|
||||
Times are averages of 10 runs.\footnote{All models obtained from \url{https://github.com/minizinc/minizinc-benchmarks}: \texttt{\justify{}accap, amaze, city-position, community-detection, depot-placement, freepizza, groupsplitter, kidney-exchange, median-string, multi-knapsack, nonogram, nside, problem, rcpsp-wet, road-cons, roster, stack-cuttingstock, steelmillslab, train, triangular, zephyrus}.}
|
||||
|
||||
\Cref{sfig:4-compareruntime} compares the flattening time for each of the 100
|
||||
instances. Points below the line indicate that the new system is faster. On
|
||||
average, the new system achieves a speed-up of \(2.3\), with very few instances
|
||||
not achieving any speedup. In terms of memory performance
|
||||
(\cref{sfig:4-comparemem}), version 2.4.3 can sometimes still outperform the new
|
||||
prototype. We have identified that the main memory bottlenecks are our currently
|
||||
unoptimised implementations of \gls{cse} lookup tables and argument vectors.
|
||||
\Cref{sfig:4-compareruntime} compares the flattening time for each of the 100 instances.
|
||||
Points below the line indicate that the new system is faster.
|
||||
On average, the new system achieves a speed-up of \(2.3\), with very few instances not achieving any speedup.
|
||||
In terms of memory performance (\cref{sfig:4-comparemem}), version 2.4.3 can sometimes still outperform the new prototype.
|
||||
We have identified that the main memory bottlenecks are our currently unoptimised implementations of \gls{cse} lookup tables and argument vectors.
|
||||
|
||||
These are very encouraging results, given that we are comparing a largely
|
||||
unoptimised prototype to a mature piece of software.
|
||||
These are very encouraging results, given that we are comparing a largely unoptimised prototype to a mature piece of software.
|
||||
|
||||
\begin{figure}[t]
|
||||
\centering
|
||||
|
@ -222,6 +222,9 @@ This adds a new binary clause for every literal in the original \gls{cnf}.
|
||||
This overhead can be avoided when using \gls{half-reif}.
|
||||
\jip{TODO: it would be great to conclude here that all these clauses are unnecessary in a positive context, since \(b\) would never be set to false.}
|
||||
|
||||
According to the principles above, decomposition libraries for the full \minizinc{} language have been implemented for \gls{mip} and \gls{sat} solvers.
|
||||
In \cref{sec:half-experiments} we asses the effects when flattening with \gls{half-reif}.
|
||||
|
||||
\section{Context Analysis}%
|
||||
\label{sec:half-context}
|
||||
|
||||
@ -791,5 +794,129 @@ In the case where a variable has one incoming edge, but it is marked as used in
|
||||
\section{Experiments}
|
||||
\label{sec:half-experiments}
|
||||
|
||||
We now present experimental evaluation of the presented \gls{half-reif} techniques.
|
||||
First, to show the benefit of implementing propagators for half-reified constraint, we compare their performance against their decompositions.
|
||||
To do this, we recreate two experiments presented by Feydy et al.\ in the original \gls{half-reif} paper in a modern \gls{cp} solver, \gls{chuffed}.
|
||||
In the experiment, we use propagators implemented according to the principles described in this paper.
|
||||
No new algorithm has been devised to perform the propagation.
|
||||
The propagator of the original constraint is merely adjusted to influence and watch a control \variable{}.
|
||||
|
||||
Additionally, we assess the effects of automatically detecting and introducing \glspl{half-reif} during the flattening process. We flatten and solve
|
||||
|
||||
A description of the used computational environment, \minizinc{} instances, and versioned software has been included in \cref{ch:benchmarks}.
|
||||
|
||||
\subsection{Propagators}
|
||||
\label{sec:half-exp-prop}
|
||||
|
||||
Our first experiment considers the \gls{qcp-max} quasi-group completion problem.
|
||||
In this problem, we need to decide the value of an \((n \times n)\) matrix of integer \variables, with domains \mzninline{1..n}.
|
||||
The aim of the problem is to create as many rows and columns where all \variables{} take a unique value.
|
||||
In each instance certain values have already been fixed.
|
||||
It is, thus, not always possible for all rows and columns to contain only distinct values.
|
||||
|
||||
In \minizinc{} counting the number of rows/columns with all different values can be accomplished by reifying the \mzninline{all_different} constraint.
|
||||
Since the goal of the problem is to maximise the number of \mzninline{all_different} \constraints{} that hold, these constraints are never forced to be \mzninline{false}.
|
||||
This means these constraints in a \posc{} context and can be half-reified.
|
||||
|
||||
\Cref{tab:half-qcp} shows the comparison of two solving configurations in \gls{chuffed} for the \gls{qcp-max} problem.
|
||||
The results are grouped based on their size of the instance.
|
||||
For each group we show the number of instances solved by the configuration and the average time used for this process.
|
||||
|
||||
The first configuration uses a newly created propagator for half-reified \mzninline{all_different} \constraints{}.
|
||||
This propagator is an adjusted version from the existing bounds consistent \mzninline{all_different} propagator in chuffed.
|
||||
The implementation of the propagator was already split into parts that \emph{check} the violation of the constraint and parts that \emph{prune} the \glspl{domain} of \variables{}.
|
||||
Therefore, the transformation described in \cref{sec:half-propagation} can be directly applied.
|
||||
Since \gls{chuffed} is a \gls{lcg} \solver{}, the explanations created by the propagator have to be adjusted as well.
|
||||
These adjustments happen in a similar fashion to the adjustments of the general algorithm: explanations used for the violation of the \constraint{} can now be used to set the control variable to \mzninline{false} and the explanations given to prune a variable are appended by requirement that the control variable is \mzninline{true}.
|
||||
|
||||
The second configuration uses the following decomposition for the \mzninline{all_different} constraint.
|
||||
|
||||
\begin{mzn}
|
||||
predicate all_different(array[int] of var int: x) =
|
||||
forall(i,j in index_set(x) where i < j)(
|
||||
x[i] != x[j]
|
||||
);
|
||||
\end{mzn}
|
||||
|
||||
The \mzninline{!=} constraints produced by this redefinition are reified.
|
||||
Their conjunction, then represent the reification of the \mzninline{all_different} constraint.
|
||||
|
||||
\begin{table}
|
||||
\begin{center}
|
||||
\input{assets/table/half_qcp}
|
||||
|
||||
\caption{\label{tab:half-qcp} \gls{qcp-max} problems: number of solved instances and average time (in seconds) with a 300s timeout.}
|
||||
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
The results in \cref{tab:half-qcp} show that the usage of the specialised propagator has a significant advantage over the use of the decomposition.
|
||||
Although it only allows us to solve a single extra instance, there is a significant reduction in solving time for most instances.
|
||||
Note that the qcp-15 instances are the only exception.
|
||||
It appears that none of the instances in this group proved to be a real challenge to either method and we see similar solve times between the two methods.
|
||||
|
||||
For our second experiment we consider a variation on the prize collecting travelling salesman problem \autocite{balas-1989-pctsp} referred to as \emph{prize collecting path}.
|
||||
In the problem we are given a graph with weighted edges, both positive and negative.
|
||||
The aim of the problem is to find the optimal acyclic path from a given start node that maximises the weights on the path.
|
||||
It is not required to visit every node.
|
||||
|
||||
In this experiment we can show how \gls{half-reif} can reduce the overhead of handling partial functions correctly.
|
||||
The \minizinc{} model for this problem contains a unsafe array lookup \mzninline{pos[next[i]]}, where the domain of \mzninline{next[i]} is larger than the index set of \mzninline{pos}.
|
||||
We compare safe decomposition of this \mzninline{element} constraint against a propagator of its \gls{half-reif}.
|
||||
The decomposition creates a new variable that takes the value of the index only when it is within the index set of the array.
|
||||
Otherwise, it will set its surrounding context to \mzninline{false}.
|
||||
The \gls{half-reif} implicitly performs the same task by setting its control \variable{} to \mzninline{false} whenever the result of the \mzninline{element} constraint does not match the value of the index variable.
|
||||
Again, for the implementation of the propagator of the \gls{half-reif} constraint we adjust the regular propagator as described above.
|
||||
|
||||
\begin{table}[tb]
|
||||
\begin{center}
|
||||
|
||||
\input{assets/table/half_prize}
|
||||
|
||||
\caption{\label{tab:half-prize} Prize collecting paths: number of solved instances and average time (in seconds) and with a 300s timeout.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
The results of the experiment are shown in \cref{tab:half-prize}.
|
||||
Although the performance on smaller instances is similar, the dedicated propagator consistently outperforms the usage of the decomposition.
|
||||
The difference in performance becomes more pronounced in the bigger instances.
|
||||
In the 32-4-8 group, we even see that usage of the propagator allows us to solve an additional three instances.
|
||||
|
||||
\subsection{Decomposition experiments}
|
||||
\label{sec:half-exp-decomp}
|
||||
|
||||
To verify the effectiveness of the half reification implementation within the \minizinc{} distribution we compare the results of the current version of the \minizinc{} translator (rev.\jip{add revision}) against the equivalent version for which we have implemented half reification.
|
||||
We use the model instances used by the \minizinc{} challenges \autocite{stuckey-2010-challenge,stuckey-2014-challenge} from 2019 and 2020. The performance of the generated \flatzinc{} models will be tested using Gecode, flattened with its own library, and Gurobi and CBC, flattened with the linear library.
|
||||
|
||||
\begin{table} [tb]
|
||||
\caption{\label{tab:hr-flat-results} Flattening results: Average changes in the
|
||||
generated the \flatzinc{} models}
|
||||
\begin{center}
|
||||
\begin{tabular}{|l|r||r|r|r||r|}
|
||||
\hline
|
||||
Library & Nr. Instances & Full Reifications
|
||||
& Constraints & Variables & Chains Compressed \\
|
||||
\hline
|
||||
Gecode & 274 & -38.19\% & -6.29\% & -8.66\% & 21.35\% \\
|
||||
\hline
|
||||
Linear & 346 & - 33.11\% & -13.77\% & -3.70\% & 11.63\% \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{table}
|
||||
\jip{Better headers for \cref{tab:hr-flat-results} and update with current results}
|
||||
|
||||
\Cref{tab:hr-flat-results} shows the average change on the number of full reification, constraints, and variables between the \flatzinc\ models generated by the different versions of the translator using the different libraries.
|
||||
We find that the number full reifications is reduced by a significant amount.
|
||||
Together with the chain compression mechanism this has a positive effect on the number of constraints and the number of variables.
|
||||
|
||||
\jip{Add something regarding the chain compression. Is this the right
|
||||
statistic? (Compressions in terms of reifications)}
|
||||
|
||||
We ran our experiments on a computer with a 3.40GHz Intel i7-3770 CPU and 16Gb of memory running the Ubuntu 16.04.3 LTS operating system.
|
||||
|
||||
\jip{Scatter plot of the runtimes + discussion!}
|
||||
|
||||
|
||||
\section{Summary}
|
||||
\label{sec:half-experiments}
|
||||
\label{sec:half-summary}
|
||||
|
@ -3,17 +3,80 @@
|
||||
\label{ch:benchmarks}
|
||||
%************************************************
|
||||
|
||||
\noindent{}All experiments included in this thesis were conducted on a dedicated node in a
|
||||
computation cluster. The machine operates using a \textbf{Intel Xeon 8260}
|
||||
\gls{cpu}, which has 24 non-hyperthreaded cores, and has access to
|
||||
\textbf{268.55 GB} of \gls{ram}. Each experimental test was given exclusive
|
||||
access to a single \gls{cpu} core and access to sufficient \gls{ram}.
|
||||
\noindent{}All experiments included in this thesis were conducted on a dedicated node in a computational cluster.
|
||||
The machine operates using a \textbf{Intel Xeon 8260} \gls{cpu}, which has 24 non-hyperthreaded cores, and has access to \textbf{268.55 GB} of \gls{ram}.
|
||||
Each experimental test was given exclusive access to a single \gls{cpu} core and access to sufficient \gls{ram}.
|
||||
|
||||
\section{Software}%
|
||||
\label{sec:bench-soft}
|
||||
|
||||
\subsection{MiniZinc Flattener}
|
||||
|
||||
In this thesis we use three different versions of the \minizinc\ flattening tool
|
||||
|
||||
\subsection{MiniZinc Solvers}
|
||||
|
||||
\paragraph{Gecode}
|
||||
\paragraph{Chuffed}
|
||||
\paragraph{IBM CPLEX}
|
||||
\paragraph{Gurobi}
|
||||
|
||||
\section{MiniZinc Models}%
|
||||
\label{sec:bench-models}
|
||||
|
||||
\section{Other Programs}%
|
||||
\paragraph{QCP-Max} This problem was introduced in by Feydy et al. in the original paper on \gls{half-reif} \autocite{feydy-2011-half-reif}. \jip{...}
|
||||
|
||||
\begin{mzn}
|
||||
include "all_different.mzn";
|
||||
|
||||
int: n; % size
|
||||
array[1..n,1..n] of 0..n: s; % 0 = unfixed 1..n = fixed
|
||||
array[1..n,1..n] of var 1..n: q; % qcp array;
|
||||
|
||||
constraint forall(i,j in 1..n where s[i,j] > 0)(q[i,j] = s[i,j]);
|
||||
|
||||
solve maximize
|
||||
sum(i in 1..n)(all_different([q[i,j] | j in 1..n])) +
|
||||
sum(j in 1..n)(all_different([q[i,j] | i in 1..n]));
|
||||
\end{mzn}
|
||||
|
||||
\paragraph{Prize Collecting Path} This problem was introduced in by Feydy et al. in the original paper on \gls{half-reif} \autocite{feydy-2011-half-reif}. \jip{...}
|
||||
|
||||
\begin{mzn}
|
||||
include "alldifferent_except_0.mzn";
|
||||
|
||||
int: n; % size
|
||||
array[1..n,0..n] of int: p; % prize for edge (i,j), p[i,0] = 0
|
||||
|
||||
array[1..n] of var 0..n: next; % next posn in tour
|
||||
array[1..n] of var 0..n: pos; % posn on node i in path, 0=notin
|
||||
array[1..n] of var int: prize = [p[i,next[i]] | i in 1..n];
|
||||
% prize for outgoing edge
|
||||
|
||||
constraint forall(i in 1..n)(
|
||||
(pos[i] = 0 <-> next[i] = 0) /\
|
||||
(next[i] > 1 -> pos[next[i]] = pos[i] + 1)
|
||||
);
|
||||
|
||||
constraint alldifferent_except_0(next) /\ pos[1] = 1;
|
||||
|
||||
solve minimize sum(i in 1..n)(prize[i]);
|
||||
\end{mzn}
|
||||
|
||||
\begin{mzn}
|
||||
include "subcircuit.mzn";
|
||||
|
||||
int: n; % size
|
||||
array[1..n,1..n] of int: p; % prize for edge (i,j), p[i,i] = 0
|
||||
|
||||
array[1..n] of var 0..n: next; % next posn in tour
|
||||
array[1..n] of var int: prize = [p[i,next[i]] | i in 1..n];
|
||||
% prize for outgoing edge
|
||||
|
||||
constraint subcircuit(next);
|
||||
|
||||
solve minimize sum(i in 1..n)(prize[i]);
|
||||
\end{mzn}
|
||||
|
||||
\section{Benchmark Environments}%
|
||||
\label{sec:bench-programs}
|
||||
|
Reference in New Issue
Block a user