Grammar pass over Half Reification
This commit is contained in:
parent
e3a864effe
commit
31770d0c98
@ -92,21 +92,21 @@ Since Boolean expressions in \minizinc{} can be used in, for example, integer ex
|
|||||||
\end{example}
|
\end{example}
|
||||||
|
|
||||||
To systematically analyse whether Boolean expressions can be \gls{half-reified}, we study the \emph{monotonicity} of \constraints{} \wrt{} an expression.
|
To systematically analyse whether Boolean expressions can be \gls{half-reified}, we study the \emph{monotonicity} of \constraints{} \wrt{} an expression.
|
||||||
A relation \( r( a_{n}, \ldots{}, a_{i}, \ldots{} , a_{m}) \) is said to be \emph{monotone} with regards to its argument \(a_{i}\) when given two possible values for \(a_{i}\), \(x\) and \(y\), if \(x > y\), then \(r( a_{n}, \ldots{}, x, \ldots{} , a_{m}) \geq{} r( a_{n}, \ldots{}, y, \ldots{} , a_{m})\), independent of other arguments.
|
A relation \( r( a_{n}, \ldots{}, a_{i}, \ldots{} , a_{m}) \) is said to be \emph{monotone} \wrt{} its argument \(a_{i}\) when given two possible values for \(a_{i}\), \(x\) and \(y\), if \(x > y\), then \(r( a_{n}, \ldots{}, x, \ldots{} , a_{m}) \geq{} r( a_{n}, \ldots{}, y, \ldots{} , a_{m})\), independent of other arguments.
|
||||||
Contrariwise, a relation \( r( a_{n}, \ldots{}, a_{i}, \ldots{} , a_{m}) \) is said to be \emph{antitone} with regards to its argument \(a_{i}\) if given two possible values for \(a_{i}\), \(x\) and \(y\), if \(x > y\), then \(r( a_{n}, \ldots{}, x, \ldots{} , a_{m}) \leq{} r( a_{n}, \ldots{}, y, \ldots{} , a_{m}) \), independent of the other arguments.
|
Contrariwise, a relation \( r( a_{n}, \ldots{}, a_{i}, \ldots{} , a_{m}) \) is said to be \emph{antitone} \wrt{} its argument \(a_{i}\) if given two possible values for \(a_{i}\), \(x\) and \(y\), if \(x > y\), then \(r( a_{n}, \ldots{}, x, \ldots{} , a_{m}) \leq{} r( a_{n}, \ldots{}, y, \ldots{} , a_{m}) \), independent of the other arguments.
|
||||||
Where, for clarification, we assume \( \text{false} < \text{true} \).
|
Where, for clarification, we assume \( \text{false} < \text{true} \).
|
||||||
|
|
||||||
Using these definitions, we introduce extra distinctions in the context of expressions.
|
Using these definitions, we introduce extra distinctions in the context of expressions.
|
||||||
Before, we would merely distinguish between \rootc{} context and non-\rootc{} context.
|
Before, we would merely distinguish between \rootc{} context and non-\rootc{} context.
|
||||||
Now, we will categorise the latter into the following three contexts.
|
Now, we will categorize the latter into the following three contexts.
|
||||||
|
|
||||||
\begin{description}
|
\begin{description}
|
||||||
|
|
||||||
\item[\posc{}] An expression is in \posc{} context when its enclosing \constraint{} (in \rootc{} context) is \textbf{monotone} \wrt{} the expression.
|
\item[\posc{}] An expression is in \posc{} context when the enclosing \constraint{} (in \rootc{} context) is \textbf{monotone} \wrt{} the expression.
|
||||||
|
|
||||||
\item[\negc{}] An expression is in \negc{} context when its enclosing \constraint{} (in \rootc{} context) is \textbf{antitone} \wrt{} the expression.
|
\item[\negc{}] An expression is in \negc{} context when the enclosing \constraint{} (in \rootc{} context) is \textbf{antitone} \wrt{} the expression.
|
||||||
|
|
||||||
\item[\mixc{}] An expression is in \mixc{} context when its enclosing \constraint{} (in \rootc{} context) it is \textbf{neither} monotone, nor antitone \wrt{} the expression.
|
\item[\mixc{}] An expression is in \mixc{} context when the enclosing \constraint{} (in \rootc{} context) it is \textbf{neither} monotone, nor antitone \wrt{} the expression.
|
||||||
|
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
@ -172,13 +172,13 @@ Logically, there are three tasks that a \gls{propagator} for any \constraint{} m
|
|||||||
When creating a \gls{propagator} for the \gls{half-reif} of a \constraint{}, it can be constructed from these tasks.
|
When creating a \gls{propagator} for the \gls{half-reif} of a \constraint{}, it can be constructed from these tasks.
|
||||||
The \gls{half-reified} \gls{propagator} is dependent on an additional argument \(b\), the \gls{cvar}.
|
The \gls{half-reified} \gls{propagator} is dependent on an additional argument \(b\), the \gls{cvar}.
|
||||||
The Boolean \variable{} can be in three states, it can currently not have been assigned a value, it can be assigned true, or it can be assigned false.
|
The Boolean \variable{} can be in three states, it can currently not have been assigned a value, it can be assigned true, or it can be assigned false.
|
||||||
Given \(check\), \(prune\), \(entailed\), and \(b\) \cref{alg:half-prop} shows pseudo code for the \gls{propagation} of the \gls{half-reif} of the \constraint{}.
|
Given \(check\), \(prune\), \(entailed\), and \(b\) \cref{alg:half-prop} shows pseudocode for the \gls{propagation} of the \gls{half-reif} of the \constraint{}.
|
||||||
|
|
||||||
\begin{algorithm}[t]
|
\begin{algorithm}[t]
|
||||||
|
|
||||||
\KwIn{The functions \(check\), \(prune\), and \(entailed\) that form the for non-\gls{reified} propagator of \constraint{} \(c\) and a Boolean \gls{cvar} \(b\).
|
\KwIn{The functions \(check\), \(prune\), and \(entailed\) that form the for non-\gls{reified} propagator of \constraint{} \(c\) and a Boolean \gls{cvar} \(b\).
|
||||||
}
|
}
|
||||||
\KwResult{This pseudo code propagates the \gls{half-reif} of \(c\) (\ie{} \(b \implies\ c\)) and returns whether the \constraint is entailed.}
|
\KwResult{This pseudocode propagates the \gls{half-reif} of \(c\) (\ie{} \(b \implies\ c\)) and returns whether the \constraint is entailed.}
|
||||||
|
|
||||||
\BlankLine{}
|
\BlankLine{}
|
||||||
\If{\(b \text{ is unassigned}\)}{
|
\If{\(b \text{ is unassigned}\)}{
|
||||||
@ -192,7 +192,7 @@ Given \(check\), \(prune\), \(entailed\), and \(b\) \cref{alg:half-prop} shows p
|
|||||||
\Return{} \(entailed()\)\;
|
\Return{} \(entailed()\)\;
|
||||||
}
|
}
|
||||||
\Return{} \(\text{false}\)\;
|
\Return{} \(\text{false}\)\;
|
||||||
\caption{\label{alg:half-prop} \gls{propagation} pseudo code for the \gls{half-reif} of a \constraint{} \(c\), based on the \gls{propagator} for \(c\).}
|
\caption{\label{alg:half-prop} \gls{propagation} pseudocode for the \gls{half-reif} of a \constraint{} \(c\), based on the \gls{propagator} for \(c\).}
|
||||||
\end{algorithm}
|
\end{algorithm}
|
||||||
|
|
||||||
Logically, the creation of \glspl{propagator} for \glspl{half-reif} can always follow this simple principle.
|
Logically, the creation of \glspl{propagator} for \glspl{half-reif} can always follow this simple principle.
|
||||||
@ -202,19 +202,19 @@ Instead, this process can be implicit.
|
|||||||
The \gls{propagator} merely prunes the \glspl{domain} of the \variables{}.
|
The \gls{propagator} merely prunes the \glspl{domain} of the \variables{}.
|
||||||
When a \gls{domain} is found to be empty, then the \gls{propagator} declares the current state \gls{unsat}.
|
When a \gls{domain} is found to be empty, then the \gls{propagator} declares the current state \gls{unsat}.
|
||||||
It is not possible to construct the \gls{half-reified} \gls{propagator} from such an implicit \(check\) operation.
|
It is not possible to construct the \gls{half-reified} \gls{propagator} from such an implicit \(check\) operation.
|
||||||
Instead a new explicit \(check\) method has to be devised to implement the \gls{propagator} of the \gls{half-reif} \constraint{}.
|
Instead, a new explicit \(check\) method has to be devised to implement the \gls{propagator} of the \gls{half-reif} \constraint{}.
|
||||||
|
|
||||||
In comparison, a \gls{propagator} for the \gls{reif} of \(c\) cannot be created from these three logical task.
|
In comparison, a \gls{propagator} for the \gls{reif} of \(c\) cannot be created from these three logical task.
|
||||||
In addition, we require the logical task from a \gls{propagator} of \(\neg{} c\): \(checkNeg\), \(pruneNeg\), and \(entailedNeg\).
|
In addition, we require the logical task from a \gls{propagator} of \(\neg{} c\): \(checkNeg\), \(pruneNeg\), and \(entailedNeg\).
|
||||||
Using these additional functions, we can define an algorithm for the \gls{propagator}, shown in \cref{alg:reif-prop}
|
Using these additional functions, we can define an algorithm for the \gls{propagator}, shown in \cref{alg:reif-prop}
|
||||||
Although this might seem reasonable for small \constraints{}, such as integer equality, for many \glspl{global} their negation is hard to define.
|
Although this might seem reasonable for small \constraints{}, such as integer equality, for many \glspl{global} their negation is hard to define.
|
||||||
\todo{insert good example of global constraint.}
|
\todo{Insert good example of global constraint.}
|
||||||
|
|
||||||
\begin{algorithm}[t]
|
\begin{algorithm}[t]
|
||||||
|
|
||||||
\KwIn{The functions \(check\), \(prune\), and \(entailed\) that form the for non-\gls{reified} propagator of \(c\), The functions \(checkNeg\), \(pruneNeg\), and \(entailedNeg\) that form the for non-\gls{reified} \gls{propagator} of \(\neg{} c\), and a Boolean \gls{cvar} \(b\).
|
\KwIn{The functions \(check\), \(prune\), and \(entailed\) that form the for non-\gls{reified} propagator of \(c\), The functions \(checkNeg\), \(pruneNeg\), and \(entailedNeg\) that form the for non-\gls{reified} \gls{propagator} of \(\neg{} c\), and a Boolean \gls{cvar} \(b\).
|
||||||
}
|
}
|
||||||
\KwResult{This pseudo code propagates the \gls{reif} of \(c\) (\ie{} \(b \leftrightarrow{} c\)) and returns whether the \constraint{} is entailed.}
|
\KwResult{This pseudocode propagates the \gls{reif} of \(c\) (\ie{} \(b \leftrightarrow{} c\)) and returns whether the \constraint{} is entailed.}
|
||||||
|
|
||||||
\BlankLine{}
|
\BlankLine{}
|
||||||
\If{\(b \text{ is unassigned}\)}{
|
\If{\(b \text{ is unassigned}\)}{
|
||||||
@ -234,7 +234,7 @@ Although this might seem reasonable for small \constraints{}, such as integer eq
|
|||||||
\Return{} \(entailedNeg()\)\;
|
\Return{} \(entailedNeg()\)\;
|
||||||
}
|
}
|
||||||
\Return{} \(\text{false}\)\;
|
\Return{} \(\text{false}\)\;
|
||||||
\caption{\label{alg:reif-prop} \Gls{propagation} pseudo code for the \gls{reif} of a \constraint{} \(c\), based on the \glspl{propagator} for \(c\) and \(\neg{} c\).}
|
\caption{\label{alg:reif-prop} \Gls{propagation} pseudocode for the \gls{reif} of a \constraint{} \(c\), based on the \glspl{propagator} for \(c\) and \(\neg{} c\).}
|
||||||
\end{algorithm}
|
\end{algorithm}
|
||||||
|
|
||||||
\Gls{half-reified} \glspl{propagator} have certain advantages over \gls{reified} \glspl{propagator}, but also may suffer certain penalties.
|
\Gls{half-reified} \glspl{propagator} have certain advantages over \gls{reified} \glspl{propagator}, but also may suffer certain penalties.
|
||||||
@ -246,7 +246,7 @@ When a full \gls{reif} is required, we can still use \gls{half-reified} \glspl{p
|
|||||||
A full \gls{reif} \mzninline{x <-> pred(...)} can be propagated using its \gls{half-reified} \gls{propagator}, \mzninline{x -> pred(...)}, the \gls{half-reified} \gls{propagator} of its negation, \mzninline{y -> not pred(...)}, and the \constraint{} \mzninline{x <-> not y}.
|
A full \gls{reif} \mzninline{x <-> pred(...)} can be propagated using its \gls{half-reified} \gls{propagator}, \mzninline{x -> pred(...)}, the \gls{half-reified} \gls{propagator} of its negation, \mzninline{y -> not pred(...)}, and the \constraint{} \mzninline{x <-> not y}.
|
||||||
This does not lose \gls{propagation} strength.
|
This does not lose \gls{propagation} strength.
|
||||||
For Booleans appearing in \posc{} context we can make the \gls{propagator} of the negated \gls{half-reif} run at the lowest priority, since it will never detect if the state is \gls{unsat}.
|
For Booleans appearing in \posc{} context we can make the \gls{propagator} of the negated \gls{half-reif} run at the lowest priority, since it will never detect if the state is \gls{unsat}.
|
||||||
Similarly in \negc{} context we can make the propagator \mzninline{b -> pred(...)} run at the lowest priority.
|
Similarly, in \negc{} context we can make the propagator \mzninline{b -> pred(...)} run at the lowest priority.
|
||||||
This means that the \glspl{cvar} are still fixed at the same time, but there is less overhead.
|
This means that the \glspl{cvar} are still fixed at the same time, but there is less overhead.
|
||||||
|
|
||||||
In \cref{sec:half-experiments} we assess the implementation of \glspl{propagator} for the \glspl{half-reif} of \mzninline{all_different} and \mzninline{element} based on these principles.
|
In \cref{sec:half-experiments} we assess the implementation of \glspl{propagator} for the \glspl{half-reif} of \mzninline{all_different} and \mzninline{element} based on these principles.
|
||||||
@ -264,7 +264,7 @@ If, however, a \gls{reif} is replaced by a \gls{half-reif}, then only one of the
|
|||||||
\begin{example}
|
\begin{example}
|
||||||
|
|
||||||
Consider the \gls{reif} of the \constraint{} \mzninline{i <= 4} using the \gls{cvar} \mzninline{b}, where \mzninline{i} can take values in the domain \mzninline{0..10}.
|
Consider the \gls{reif} of the \constraint{} \mzninline{i <= 4} using the \gls{cvar} \mzninline{b}, where \mzninline{i} can take values in the domain \mzninline{0..10}.
|
||||||
If the target \solver{} is a \gls{mip} \solver{}, then this \gls{reif} would be linearised.
|
If the target \solver{} is a \gls{mip} \solver{}, then this \gls{reif} would be linearized.
|
||||||
It would take the following form.
|
It would take the following form.
|
||||||
|
|
||||||
\begin{mzn}
|
\begin{mzn}
|
||||||
@ -318,7 +318,7 @@ Expressions bound to an identifier can be used multiple times in expressions tha
|
|||||||
If \mzninline{x} is only used in a \posc{} context, then the call itself is in a \posc{} context as well.
|
If \mzninline{x} is only used in a \posc{} context, then the call itself is in a \posc{} context as well.
|
||||||
As such, the call could then be \gls{half-reified}.
|
As such, the call could then be \gls{half-reified}.
|
||||||
|
|
||||||
Although this is the case in the left side of the conjunction, the other side uses \mzninline{x} in a \negc{} context.
|
Although this is the case on the left side of the conjunction, the other side uses \mzninline{x} in a \negc{} context.
|
||||||
This means that \mzninline{pred(a, b, c)} is in a \mixc{} context and must be fully \gls{reified}.
|
This means that \mzninline{pred(a, b, c)} is in a \mixc{} context and must be fully \gls{reified}.
|
||||||
\end{example}
|
\end{example}
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ In this scenario, we prefer to create the full \gls{reif} as it decreases the nu
|
|||||||
|
|
||||||
When taking into account the possible undefinedness of an expression, every expression in a \minizinc{} model has two different contexts: the context in which the expression itself occurs, its \emph{value context}, and the context in which the partiality of the expression is captured, its \emph{partiality context}.
|
When taking into account the possible undefinedness of an expression, every expression in a \minizinc{} model has two different contexts: the context in which the expression itself occurs, its \emph{value context}, and the context in which the partiality of the expression is captured, its \emph{partiality context}.
|
||||||
As described in \cref{subsec:back-mzn-partial}, \minizinc{} uses \glspl{rel-sem} for partial functions.
|
As described in \cref{subsec:back-mzn-partial}, \minizinc{} uses \glspl{rel-sem} for partial functions.
|
||||||
This means that if a function if the result of a function is undefined, then its nearest enclosing Boolean expression becomes false.
|
This means that if the result of a function is undefined, then its nearest enclosing Boolean expression becomes false.
|
||||||
In practice, this means that a condition that tests if the function will return a value is added to the nearest enclosing Boolean expression.
|
In practice, this means that a condition that tests if the function will return a value is added to the nearest enclosing Boolean expression.
|
||||||
The partiality context is the context in which this condition is placed.
|
The partiality context is the context in which this condition is placed.
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ The partiality context is the context in which this condition is placed.
|
|||||||
\end{mzn}
|
\end{mzn}
|
||||||
|
|
||||||
In this fragment, we study the context of the division expression \mzninline{y div x}.
|
In this fragment, we study the context of the division expression \mzninline{y div x}.
|
||||||
The expression itself return a integer \variable{} and it used on the left-hand side of a less than \constraint{}.
|
The expression itself return an integer \variable{}, and it used on the left-hand side of a less than \constraint{}.
|
||||||
This result is therefore in a \negc{} context: it is only forced to take a smaller value.
|
This result is therefore in a \negc{} context: it is only forced to take a smaller value.
|
||||||
This is its value context.
|
This is its value context.
|
||||||
|
|
||||||
@ -467,7 +467,7 @@ However, we currently do not provide such analysis and annotate functions by han
|
|||||||
\end{listing}
|
\end{listing}
|
||||||
|
|
||||||
\begin{algorithm}
|
\begin{algorithm}
|
||||||
\KwIn{A \minizinc\ operator \(op\) and calling context \(ctx\)}
|
\KwIn{A \minizinc{} operator \(op\) and calling context \(ctx\)}
|
||||||
|
|
||||||
\KwOut{A tuple containing the contexts of the arguments \(\tuple{ctx_{1}, \ldots{}, ctx_{n}}\)}
|
\KwOut{A tuple containing the contexts of the arguments \(\tuple{ctx_{1}, \ldots{}, ctx_{n}}\)}
|
||||||
|
|
||||||
@ -582,12 +582,12 @@ Since all expressions in well-formed \microzinc{} are total, the \constraint{} c
|
|||||||
And, unlike \minizinc{}, the \constraint{} is not dependent on the context of the \gls{let}.
|
And, unlike \minizinc{}, the \constraint{} is not dependent on the context of the \gls{let}.
|
||||||
The \constraint{}'s expression is evaluated in \rootc{} context.
|
The \constraint{}'s expression is evaluated in \rootc{} context.
|
||||||
|
|
||||||
The (Assign) rule reasons about declarations that have a right hand side.
|
The (Assign) rule reasons about declarations that have a right-hand side.
|
||||||
The expression that is assigned to the identifier must be evaluated in the combined context of its usages.
|
The expression that is assigned to the identifier must be evaluated in the combined context of its usages.
|
||||||
As previously discussed, the contexts in which the identifier was used can be retrieved using the ``collectCtx'' function.
|
As previously discussed, the contexts in which the identifier was used can be retrieved using the ``collectCtx'' function.
|
||||||
These contexts are then combined using a ``join'' function.
|
These contexts are then combined using a ``join'' function.
|
||||||
This function repeatedly applies the symmetric join operation described by \cref{fig:half-join}.
|
This function repeatedly applies the symmetric join operation described by \cref{fig:half-join}.
|
||||||
The right hand expression of the item is then evaluated in the resulting context.
|
The right-hand expression of the item is then evaluated in the resulting context.
|
||||||
|
|
||||||
\begin{figure*}
|
\begin{figure*}
|
||||||
\begin{center}
|
\begin{center}
|
||||||
@ -696,7 +696,7 @@ Otherwise, it will act as a normal \rootc{} context.
|
|||||||
\Cref{fig:half-analysis-maybe-root} shows the additional inference rules for \gls{array} access and \gls{conditional} expressions.
|
\Cref{fig:half-analysis-maybe-root} shows the additional inference rules for \gls{array} access and \gls{conditional} expressions.
|
||||||
Looking back at \cref{ex:half-maybe-root}, these additional rules and updated join operation will ensure that the first case will correctly use \rootc{} context calls.
|
Looking back at \cref{ex:half-maybe-root}, these additional rules and updated join operation will ensure that the first case will correctly use \rootc{} context calls.
|
||||||
For the second case, however, it detects that \mzninline{p} is used in both \posc{} and \mayberootc{} context.
|
For the second case, however, it detects that \mzninline{p} is used in both \posc{} and \mayberootc{} context.
|
||||||
Therefore, it will output the \posc{} call for the right hand side of \mzninline{p}, even when \mzninline{b} evaluates to \mzninline{true}.
|
Therefore, it will output the \posc{} call for the right-hand side of \mzninline{p}, even when \mzninline{b} evaluates to \mzninline{true}.
|
||||||
At compile time, this is the only correct context to use.
|
At compile time, this is the only correct context to use.
|
||||||
We will, however, discuss how to adjust contexts dynamically during \gls{rewriting} in \cref{subsec:half-dyn-context}.
|
We will, however, discuss how to adjust contexts dynamically during \gls{rewriting} in \cref{subsec:half-dyn-context}.
|
||||||
|
|
||||||
@ -754,13 +754,13 @@ During the \gls{rewriting} process the contexts assigned to the different expres
|
|||||||
|
|
||||||
\end{example}
|
\end{example}
|
||||||
|
|
||||||
As this example shows, the use of \gls{half-reif} can form so called \glspl{implication-chain}.
|
As this example shows, the use of \gls{half-reif} can form so-called \glspl{implication-chain}.
|
||||||
This happens when the right hand side of an implication is \gls{half-reified} and a \gls{cvar} is created to represent the expression.
|
This happens when the right-hand side of an implication is \gls{half-reified} and a \gls{cvar} is created to represent the expression.
|
||||||
Instead, we could have used the left hand side of the implication as the \gls{cvar} of the \gls{half-reified} \constraint{}.
|
Instead, we could have used the left-hand side of the implication as the \gls{cvar} of the \gls{half-reified} \constraint{}.
|
||||||
In next section, we present a new post-processing method we call \gls{chain-compression}.
|
In next section, we present a new post-processing method we call \gls{chain-compression}.
|
||||||
It can be used to eliminate these \glspl{implication-chain}.
|
It can be used to eliminate these \glspl{implication-chain}.
|
||||||
|
|
||||||
The \gls{rewriting} with \gls{half-reif} also interacts with some of the optimisation methods used during the \gls{rewriting} process.
|
The \gls{rewriting} with \gls{half-reif} also interacts with some simplification methods used during the \gls{rewriting} process.
|
||||||
Most importantly, \gls{half-reif} has to be considered when using \gls{cse}, and \gls{propagation} can change the context of an expression.
|
Most importantly, \gls{half-reif} has to be considered when using \gls{cse}, and \gls{propagation} can change the context of an expression.
|
||||||
In \cref{subsec:half-cse} we will discuss how \gls{cse} can be adjusted to handle \gls{half-reif}.
|
In \cref{subsec:half-cse} we will discuss how \gls{cse} can be adjusted to handle \gls{half-reif}.
|
||||||
Finally, in \cref{subsec:half-dyn-context} we will discuss how the context in which an expression is evaluated can be adjusted during the \gls{rewriting} process.
|
Finally, in \cref{subsec:half-dyn-context} we will discuss how the context in which an expression is evaluated can be adjusted during the \gls{rewriting} process.
|
||||||
@ -770,7 +770,7 @@ Finally, in \cref{subsec:half-dyn-context} we will discuss how the context in wh
|
|||||||
|
|
||||||
\Gls{rewriting} with \gls{half-reif} will in many cases result in \glspl{implication-chain}: \mzninline{b1 -> b2 /\ b2 -> c}, where \texttt{b2} has no other occurrences.
|
\Gls{rewriting} with \gls{half-reif} will in many cases result in \glspl{implication-chain}: \mzninline{b1 -> b2 /\ b2 -> c}, where \texttt{b2} has no other occurrences.
|
||||||
In this case the conjunction can be replaced by \mzninline{b1 -> c} and \texttt{b2} can be removed from the \cmodel{}.
|
In this case the conjunction can be replaced by \mzninline{b1 -> c} and \texttt{b2} can be removed from the \cmodel{}.
|
||||||
The case shown in the example can be generalised to
|
The case shown in the example can be generalized to
|
||||||
|
|
||||||
\begin{mzn}
|
\begin{mzn}
|
||||||
constraint b1 -> b2 /\ forall(i in N)(b2 -> c[i])
|
constraint b1 -> b2 /\ forall(i in N)(b2 -> c[i])
|
||||||
@ -790,7 +790,7 @@ The vertices \(V\) represent the \variables{} in the \instance{}.
|
|||||||
An edge \((x,y) \in E\) represents the presence of an implication \mzninline{x -> y} in the instance.
|
An edge \((x,y) \in E\) represents the presence of an implication \mzninline{x -> y} in the instance.
|
||||||
Additionally, the algorithm requires vertices to be marked when their corresponding \variables{} are used in other \constraints{} in the \cmodel{}.
|
Additionally, the algorithm requires vertices to be marked when their corresponding \variables{} are used in other \constraints{} in the \cmodel{}.
|
||||||
The goal of the algorithm is now to identify and remove vertices that are not marked and have only one incoming edge.
|
The goal of the algorithm is now to identify and remove vertices that are not marked and have only one incoming edge.
|
||||||
\Cref{alg:half-compression} provides a formal specification of the \gls{chain-compression} method in pseudo code.
|
\Cref{alg:half-compression} provides a formal specification of the \gls{chain-compression} method in pseudocode.
|
||||||
|
|
||||||
\begin{algorithm}
|
\begin{algorithm}
|
||||||
\KwIn{An implication \constraint{} graph \(G=\tuple{V, E}\) and a set \(M
|
\KwIn{An implication \constraint{} graph \(G=\tuple{V, E}\) and a set \(M
|
||||||
@ -896,7 +896,7 @@ Since a \constraint{} and its negation cannot both hold at the same time, this i
|
|||||||
\label{subsec:half-dyn-context}
|
\label{subsec:half-dyn-context}
|
||||||
|
|
||||||
In \cref{subsec:half-?root} we discussed the fact that the correct context of an expression is not always known when analysing \microzinc{}.
|
In \cref{subsec:half-?root} we discussed the fact that the correct context of an expression is not always known when analysing \microzinc{}.
|
||||||
The context may depends on data that is only known at an \instance{} level.
|
The context may depend on data that is only known at an \instance{} level.
|
||||||
The same situation can be caused by \gls{propagation}.
|
The same situation can be caused by \gls{propagation}.
|
||||||
|
|
||||||
\begin{example}
|
\begin{example}
|
||||||
@ -962,13 +962,13 @@ A description of the used computational environment, \minizinc{} instances, and
|
|||||||
\label{sec:half-exp-prop}
|
\label{sec:half-exp-prop}
|
||||||
|
|
||||||
Our first experiment considers the QCP-max quasi-group completion problem.
|
Our first experiment considers the 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}.
|
In this problem, we need to decide the value of a \((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 as possible where all \variables{} take a unique value.
|
The aim of the problem is to create as many rows and columns as possible where all \variables{} take a unique value.
|
||||||
In each \instance{} certain values have already been fixed.
|
In each \instance{} certain values have already been fixed.
|
||||||
It is not always possible for all rows and columns to contain only distinct values.
|
It is 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 using a \gls{reified} \mzninline{all_different} \constraint{}.
|
In \minizinc{} counting the number of rows/columns with all different values can be accomplished using a \gls{reified} \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}.
|
Since the goal of the problem is to maximize the number of \mzninline{all_different} \constraints{} that hold, these \constraints{} are never forced to be \mzninline{false}.
|
||||||
This means these \constraints{} are in \posc{} context and can be \gls{half-reified}.
|
This means these \constraints{} are in \posc{} context and can be \gls{half-reified}.
|
||||||
|
|
||||||
\Cref{tab:half-qcp} shows the comparison of two solving configurations in \gls{chuffed} for the QCP-max problem.
|
\Cref{tab:half-qcp} shows the comparison of two solving configurations in \gls{chuffed} for the QCP-max problem.
|
||||||
@ -980,7 +980,7 @@ This \gls{propagator} is an adjusted version from the existing \gls{bounds-con}
|
|||||||
The implementation of the \gls{propagator} was already split into parts that check the violation of the \constraint{} and parts that prune the \glspl{domain} of the \variables{}.
|
The implementation of the \gls{propagator} was already split into parts that check the violation of the \constraint{} and parts that prune the \glspl{domain} of the \variables{}.
|
||||||
Therefore, the transformation described in \cref{sec:half-propagation} can be directly applied.
|
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 \gls{propagator} have to be adjusted as well.
|
Since \gls{chuffed} is a \gls{lcg} \solver{}, the explanations created by the \gls{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\glsadd{violated} of the \constraint{} can now be used to set the \gls{cvar} to \mzninline{false}, and the explanations given to prune a \variable{} are extended with a literal that ensures the \gls{cvar} is \mzninline{true}.
|
These adjustments happen similar to the adjustments of the general algorithm: explanations used for the violation\glsadd{violated} of the \constraint{} can now be used to set the \gls{cvar} to \mzninline{false}, and the explanations given to prune a \variable{} are extended with a literal that ensures the \gls{cvar} is \mzninline{true}.
|
||||||
|
|
||||||
In our second configuration the \mzninline{all_different} \constraint{} is enforced using the \gls{decomp} shown in \cref{lst:half-alldiff}.
|
In our second configuration the \mzninline{all_different} \constraint{} is enforced using the \gls{decomp} shown in \cref{lst:half-alldiff}.
|
||||||
The \mzninline{!=} \constraints{} produced by this redefinition are \gls{reified}.
|
The \mzninline{!=} \constraints{} produced by this redefinition are \gls{reified}.
|
||||||
@ -1001,14 +1001,14 @@ Their conjunction then represent the \gls{reif} of the \mzninline{all_different}
|
|||||||
\end{center}
|
\end{center}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
The results in \cref{tab:half-qcp} show that the specialised \gls{propagator} has a significant advantage over the use of the \gls{decomp}.
|
The results in \cref{tab:half-qcp} show that the specialized \gls{propagator} has a significant advantage over the use of the \gls{decomp}.
|
||||||
Although it only allows us to solve one extra instance, there is a significant reduction in solving time for most \instances{}.
|
Although it only allows us to solve one extra instance, there is a significant reduction in solving time for most \instances{}.
|
||||||
Note that the qcp-15 \instances{} are the only exception.
|
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.
|
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.
|
||||||
|
|
||||||
In addition, we consider a variation on the prize collecting travelling salesman problem \autocite{balas-1989-pctsp} referred to as the ``prize collecting path'' problem.
|
In addition, we consider a variation on the prize collecting travelling salesman problem \autocite{balas-1989-pctsp} referred to as the ``prize collecting path'' problem.
|
||||||
In the problem we are given a graph with weighted edges, both positive and negative.
|
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.
|
The aim of the problem is to find the optimal acyclic path from a given start node that maximizes the weights on the path.
|
||||||
It is not required to visit every node.
|
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.
|
In this experiment we can show how \gls{half-reif} can reduce the overhead of handling partial functions correctly.
|
||||||
@ -1016,7 +1016,7 @@ The \minizinc{} model for this problem contains an \gls{array} lookup \mzninline
|
|||||||
We compare safe \gls{decomp} of this \mzninline{element} \constraint{} against a \gls{propagator} of its \gls{half-reif}.
|
We compare safe \gls{decomp} of this \mzninline{element} \constraint{} against a \gls{propagator} of its \gls{half-reif}.
|
||||||
The \gls{decomp} creates a new \variable{} that takes the value of the index only when it is within the index set of the \gls{array}.
|
The \gls{decomp} creates a new \variable{} that takes the value of the index only when it is within the index set of the \gls{array}.
|
||||||
Otherwise, it will set its surrounding context to \mzninline{false}.
|
Otherwise, it will set its surrounding context to \mzninline{false}.
|
||||||
The \gls{half-reif} implicitly performs the same task by setting its \gls{cvar} to \mzninline{false} whenever the resulting \variable{} does not not equal the element to which the index \variable{} points, or when the index points outside the \gls{array}.
|
The \gls{half-reif} implicitly performs the same task by setting its \gls{cvar} to \mzninline{false} whenever the resulting \variable{} does not equal the element to which the index \variable{} points, or when the index points outside the \gls{array}.
|
||||||
Again, for the implementation of the \gls{propagator} of the \gls{half-reif} \constraint{} we adjust the direct \gls{propagator} as described above.
|
Again, for the implementation of the \gls{propagator} of the \gls{half-reif} \constraint{} we adjust the direct \gls{propagator} as described above.
|
||||||
|
|
||||||
\begin{table}
|
\begin{table}
|
||||||
@ -1076,7 +1076,7 @@ The \gls{rewriting} statistics for the \gls{gecode} \solver{} library, shown in
|
|||||||
Although the total number of \constraints{} remains stable, we see that well over half of all \glspl{reif} are replaced by \glspl{half-reif}.
|
Although the total number of \constraints{} remains stable, we see that well over half of all \glspl{reif} are replaced by \glspl{half-reif}.
|
||||||
This replacement happens mostly 1-for-1; the difference between the number of \glspl{half-reif} introduced and the number of \glspl{reif} reduced is only 20. In comparison, the number of implications removed by \gls{chain-compression} looks small, but this number is highly dependent on the \minizinc{} model.
|
This replacement happens mostly 1-for-1; the difference between the number of \glspl{half-reif} introduced and the number of \glspl{reif} reduced is only 20. In comparison, the number of implications removed by \gls{chain-compression} looks small, but this number is highly dependent on the \minizinc{} model.
|
||||||
In many models, no implications can be removed, but for some problems an implication is removed for every \gls{half-reif} that is introduced.
|
In many models, no implications can be removed, but for some problems an implication is removed for every \gls{half-reif} that is introduced.
|
||||||
Finally, the overhead of the introduction of \gls{half-reif} and the newly introduced optimisation techniques is minimal.
|
Finally, the overhead of the introduction of \gls{half-reif} and the newly introduced optimization techniques is minimal.
|
||||||
|
|
||||||
The \Cref{subtab:half-flat-lin} paints an equally positive picture of \glspl{half-reif} for linearization.
|
The \Cref{subtab:half-flat-lin} paints an equally positive picture of \glspl{half-reif} for linearization.
|
||||||
Since both \glspl{reif} and \glspl{half-reif} are decomposed during the \gls{rewriting} process, \gls{half-reif} is able to remove almost 7.5\% of the overall \constraints{}.
|
Since both \glspl{reif} and \glspl{half-reif} are decomposed during the \gls{rewriting} process, \gls{half-reif} is able to remove almost 7.5\% of the overall \constraints{}.
|
||||||
@ -1084,7 +1084,7 @@ The ratio of \glspl{reif} that is replaced with \glspl{half-reif} is not as high
|
|||||||
This is caused by the fact that the linearization process requires full \gls{reif} in the decomposition of many \glspl{global}.
|
This is caused by the fact that the linearization process requires full \gls{reif} in the decomposition of many \glspl{global}.
|
||||||
Similar to \gls{gecode}, the number of implications that is removed is dependent on the problem.
|
Similar to \gls{gecode}, the number of implications that is removed is dependent on the problem.
|
||||||
Lastly, the \gls{rewriting} time slightly increases for the linearization process.
|
Lastly, the \gls{rewriting} time slightly increases for the linearization process.
|
||||||
Since there are many more \constraints{}, the introduced optimisation mechanisms have a slightly higher overhead.
|
Since there are many more \constraints{}, the introduced optimization mechanisms have a slightly higher overhead.
|
||||||
|
|
||||||
Finally, statistics for \gls{rewriting} the \instances{} for a \gls{maxsat} \solver{} are shown in \cref{subtab:half-flat-bool}.
|
Finally, statistics for \gls{rewriting} the \instances{} for a \gls{maxsat} \solver{} are shown in \cref{subtab:half-flat-bool}.
|
||||||
Unlike linearization, \gls{half-reif} does not significantly reduce the number of \constraints{} and, although still significant, the number of \glspl{reif} is reduced by only slightly over ten percent.
|
Unlike linearization, \gls{half-reif} does not significantly reduce the number of \constraints{} and, although still significant, the number of \glspl{reif} is reduced by only slightly over ten percent.
|
||||||
@ -1094,7 +1094,7 @@ Even when we do not automatically introduce \glspl{half-reif}, they are still in
|
|||||||
Furthermore, \gls{chain-compression} does not seem to have any effect.
|
Furthermore, \gls{chain-compression} does not seem to have any effect.
|
||||||
Since all \glspl{half-reif} are defined in terms of clauses, the implications normally removed using \gls{chain-compression} are instead aggregated into bigger clauses.
|
Since all \glspl{half-reif} are defined in terms of clauses, the implications normally removed using \gls{chain-compression} are instead aggregated into bigger clauses.
|
||||||
Surprisingly, \gls{half-reif} slightly reduces the \gls{rewriting} time as it reduces the workload.
|
Surprisingly, \gls{half-reif} slightly reduces the \gls{rewriting} time as it reduces the workload.
|
||||||
The relatively small changes shown might indicate that additional work might be warranted in the Booleanisation library.
|
The relatively small changes shown might indicate that additional work might be warranted in the \gls{booleanization} library.
|
||||||
It might be possible to create more dedicated \glspl{decomp} for \gls{half-reified} \constraints{}, and to analyse the library to see if \glspl{annotation} could be added to more function arguments to retain \posc{} contexts.
|
It might be possible to create more dedicated \glspl{decomp} for \gls{half-reified} \constraints{}, and to analyse the library to see if \glspl{annotation} could be added to more function arguments to retain \posc{} contexts.
|
||||||
|
|
||||||
\begin{table}
|
\begin{table}
|
||||||
@ -1117,7 +1117,7 @@ It might be possible to create more dedicated \glspl{decomp} for \gls{half-reifi
|
|||||||
The results shown in this table are very mixed.
|
The results shown in this table are very mixed.
|
||||||
For \gls{gecode}, \gls{half-reif} does not seem to impact its solving performance.
|
For \gls{gecode}, \gls{half-reif} does not seem to impact its solving performance.
|
||||||
We would have hoped that \glspl{propagators} for \glspl{half-reif} would be more efficient and reduce the number of \glspl{propagator} scheduled in general.
|
We would have hoped that \glspl{propagators} for \glspl{half-reif} would be more efficient and reduce the number of \glspl{propagator} scheduled in general.
|
||||||
However, neither number of \instances{} solved, nor the solving time required improved.
|
However, neither number of \instances{} solved, nor the required solving time improved.
|
||||||
A single \instance{}, however, is negatively impacted by the change; an \gls{opt-sol} for this \instance{} is no longer found.
|
A single \instance{}, however, is negatively impacted by the change; an \gls{opt-sol} for this \instance{} is no longer found.
|
||||||
We expect that this \instance{} has benefited from the increased Boolean \gls{propagation} that is caused by full \gls{reif}.
|
We expect that this \instance{} has benefited from the increased Boolean \gls{propagation} that is caused by full \gls{reif}.
|
||||||
Overall, these results do not show any significant positive or negative effects in \gls{gecode}'s performance when using \gls{half-reif}.
|
Overall, these results do not show any significant positive or negative effects in \gls{gecode}'s performance when using \gls{half-reif}.
|
||||||
|
@ -2,20 +2,20 @@
|
|||||||
\minizinc{} allows us to write complex \constraints{} that in the process of \gls{rewriting} result in multiple \constraints{} that reason about each other.
|
\minizinc{} allows us to write complex \constraints{} that in the process of \gls{rewriting} result in multiple \constraints{} that reason about each other.
|
||||||
However, using a \gls{reif} \(b \leftrightarrow{} c\), that determines whether a \constraint{} \(c\) holds, can slow the \solver{} down.
|
However, using a \gls{reif} \(b \leftrightarrow{} c\), that determines whether a \constraint{} \(c\) holds, can slow the \solver{} down.
|
||||||
Even in \gls{cp} \solvers{}, not many \glspl{reif} are \gls{native} to the \solvers{}, and the \glspl{propagator}, for the ones that are, are often weak.
|
Even in \gls{cp} \solvers{}, not many \glspl{reif} are \gls{native} to the \solvers{}, and the \glspl{propagator}, for the ones that are, are often weak.
|
||||||
Generally, the \glspl{decomp} of \gls{reified} \constraint{} also result a large number of \gls{native} \constraints{} and \variables{}.
|
Generally, the \glspl{decomp} of \gls{reified} \constraint{} also result numerous \gls{native} \constraints{} and \variables{}.
|
||||||
It is thus important that \gls{rewriting} avoids the use of \gls{reif}, whenever it is not required.
|
It is thus important that \gls{rewriting} avoids the use of \gls{reif}, whenever it is not required.
|
||||||
|
|
||||||
In this chapter we present an extended \gls{reif} analysis to help minimise the required \solver{} effort.
|
In this chapter we present an extended \gls{reif} analysis to help minimize the required \solver{} effort.
|
||||||
Not only does it consider if a \constraint{} must be \gls{reified} or not, but it also considers whether it could instead be \gls{half-reified}.
|
Not only does it consider if a \constraint{} must be \gls{reified} or not, but it also considers whether it could instead be \gls{half-reified}.
|
||||||
|
|
||||||
The notion of \gls{half-reif} \(b \rightarrow{} c\) for a \constraint{} \(c\) was introduced by \textcite{feydy-2011-half-reif}.
|
The notion of \gls{half-reif} \(b \rightarrow{} c\) for a \constraint{} \(c\) was introduced by \textcite{feydy-2011-half-reif}.
|
||||||
It is shown \gls{half-reif} can mitigate some of the problems and expenses of the use of \gls{reif}.
|
It is shown \gls{half-reif} can mitigate some problems and expenses of the use of \gls{reif}.
|
||||||
It is not always possible, however, to use a \gls{half-reif} instead of a \gls{reif}.
|
It is not always possible, however, to use a \gls{half-reif} instead of a \gls{reif}.
|
||||||
The authors identify the conditions required for its usage and provide an algorithm that rewrites a subset of the \minizinc{} language using the technique.
|
The authors identify the conditions required for its usage and provide an algorithm that rewrites a subset of the \minizinc{} language using the technique.
|
||||||
Crucially, because of the omission of \gls{let} and multiple occurrences of identifiers, this algorithm does not directly generalise to the full \minizinc{} language.
|
Crucially, because of the omission of \gls{let} and multiple occurrences of identifiers, this algorithm does not directly generalize to the full \minizinc{} language.
|
||||||
This chapter re-evaluates \gls{half-reif} and extends the \gls{rewriting} process to fully support \gls{half-reif} in \minizinc{}.
|
This chapter re-evaluates \gls{half-reif} and extends the \gls{rewriting} process to fully support \gls{half-reif} in \minizinc{}.
|
||||||
|
|
||||||
This chapter is organised as follows.
|
This chapter is organized as follows.
|
||||||
In \cref{sec:half-intro,sec:half-propagation} we introduce the core concepts of \gls{half-reif} and \glspl{propagator} for \gls{half-reified} \constraints{}, as discussed by \textcite{feydy-2011-half-reif}.
|
In \cref{sec:half-intro,sec:half-propagation} we introduce the core concepts of \gls{half-reif} and \glspl{propagator} for \gls{half-reified} \constraints{}, as discussed by \textcite{feydy-2011-half-reif}.
|
||||||
An additional benefit of \gls{half-reif} is that its \gls{decomp} can be significantly smaller than the \gls{decomp} of a \gls{reif}.
|
An additional benefit of \gls{half-reif} is that its \gls{decomp} can be significantly smaller than the \gls{decomp} of a \gls{reif}.
|
||||||
\Cref{sec:half-decomposition} shows the benefits of \gls{half-reif} when writing \glspl{decomp} for \gls{mip} and \gls{sat} \solvers{}.
|
\Cref{sec:half-decomposition} shows the benefits of \gls{half-reif} when writing \glspl{decomp} for \gls{mip} and \gls{sat} \solvers{}.
|
||||||
|
Reference in New Issue
Block a user