Infeasibility and inconsistency¶
When submitting a model to Hexaly Optimizer (calling method solve
), the
expected result is to obtain a feasible solution, and even sometimes an optimal
solution. However in some cases the returned solution can be infeasible in the
sense that the current assignement of values to variables violates some of the
constraints of the problem. Two solution statuses (see
getSolutionStatus) are defined for these infeasibility
cases:
INFEASIBLE
means that no feasible solution was found to the submitted problem but it could not be proven that no such solution exists. Maybe running a longer search would have produced a feasible solution.INCONSISTENT
means that the optimizer was able to prove that no feasible solution exists. In this case, Hexaly Optimizer offers a functionality for analyzing the causes of this inconsistency.
Note
Note that both statuses INFEASIBLE
and INCONSISTENT
can also be
encountered on problems where no constraint was defined. Indeed, a
solution where an objective takes an invalid value is considered infeasible.
For instance minimize sqrt(x)
implicitly requires that x takes a
non-negative value.
Analyzing inconsistencies¶
Analyzing an inconsistent model amounts to identifying a relatively small inconsistent subproblem. Such a subproblem or inconsistency core is said to be irreducible if it contains no smaller inconsistent subproblem.
The function computeInconsistency
computes such a core that is to say a set
of expressions (named causes) such that the problem restricted to these
expressions and their descendents is inconsistent. Calling this function
requires the model to be closed and the optimizer to be stopped. This
inconsistency core is returned as an HxInconsistency
object. This object
can be printed in a readable form so that the user can easily spot the origin
of the inconsistency. It also allows scanning the set of identified causes.
For example, the following model is inconsistent because limiting the cube of
y
to 250 prevents y
from taking values larger than 6, which makes the
constraint 3*x + y >= 20
impossible to satisfy:
function main() {
with(optimizer = hexaly.create()) {
x <- bool();
y <- int(0,100);
z <- bool();
t <- int(0,100);
constraint 3*x + y >= 20;
constraint pow(y,3) <= 250;
constraint 4*z + t <= 18;
maximize x*t + 8*z*y;
optimizer.model.close();
optimizer.solve();
}
}
The computation of the inconsistency core can be launched in the main mode with the following function:
iis = optimizer.computeInconsistency();
println(iis);
The resulting output on the standard console is the following:
...
Computing inconsistency core...
Irreducible inconsistency core found with 2 causes.
2 causes in inconsistency core:
constraint sum(prod(3, bool#0()), int#1(0, 100)) >= 20
constraint pow(int#1(0, 100), 3) <= 250
The two constraints responsible for the inconsistency are identified and displayed. Note that expressions are identified by their type and index. It is also possible to assign names to variables in the model function:
x.name = "x";
y.name = "y";
z.name = "z";
t.name = "t";
Having defined these names the inconsistency core reads as follows:
2 causes in inconsistency core:
pow(y, 3) <= 250
3 * x + y >= 20
In the APIs, the principle is the same.
Computing the inconsistency core is done through the
compute_inconsistency
method of the optimizer, which returns an
HxInconsistency
object.
This object can be converted to a string for display purposes. It is iterable, and contains the expressions in the inconsistency core.
# With optimizer a HexalyOptimizer object
iis = optimizer.compute_inconsistency()
print(iis)
# With process a user-defined function
for expr in iis:
process(expr)
Computing the inconsistency core is done through the
computeInconsistency
method of the optimizer, which returns an
HxInconsistency
object.
This object can be converted to a string for display purpose with
toString
. Individual expressions in the inconsistency core are
accessed with getCause
.
// With optimizer a HexalyOptimizer object
iis = optimizer.computeInconsistency();
std::cout << iis.toString() << std::endl;
// With process a user-defined function
for (int i = 0; i < iis.getNbCauses(); ++i) {
HxExpression expr = iis.getCause(i);
process(expr)
}
Computing the inconsistency core is done through the
ComputeInconsistency
method of the optimizer, which returns an
HxInconsistency
object.
This object can be converted to a string for display purpose. Individual
expressions in the inconsistency core are accessed with GetCause
.
// With optimizer a HexalyOptimizer object
iis = optimizer.ComputeInconsistency();
Console.WriteLine(iis);
// With Process a user-defined function
for (int i = 0; i < iis.GetNbCauses(); ++i) {
HxExpression expr = iis.GetCause(i);
Process(expr)
}
Computing the inconsistency core is done through the
computeInconsistency
method of the optimizer, which returns an
HxInconsistency
object.
This object can be converted to a string for display purpose. Individual
expressions in the inconsistency core are accessed with getCause
.
// With optimizer a HexalyOptimizer object
iis = optimizer.computeInconsistency();
System.out.println(iis);
// With process a user-defined function
for (int i = 0; i < iis.getNbCauses(); ++i) {
HxExpression expr = iis.getCause(i);
process(expr)
}