Retrieving solution status and values¶
Status of the solution¶
A feasible solution is an assignment of values to decisions variables such that:
- all constraints are satisfied
- no objective has undefined value. Undefined values can occur when performing illegal mathematical operations (square root of negative number for instance) or accessing outside the bounds of an array.
Note that some values can be undefined in a feasible solution, provided that all
objectives have valid values. For instance a conditional expression
x > 0 ? sqrt(x) : sqrt(-x)
always has one of its branches undefined, but its
output is always valid.
At the end of the search, the status of the solution can be one of the following:
INCONSISTENT
if the solver was able to prove that no feasible solution can be foundINFEASIBLE
if no feasible solution has been found yetFEASIBLE
if a feasible solution has been computedOPTIMAL
if a feasible solution has been found whose optimality has been proven (objective value within 0.01% of computed bound for each objective).
This status can be retrieved at any time after the model has been closed.
// it allows you to access to the current solution, for instance in the output() function
function output() {
println("Status is " + lsSolution.status);
// you can also compare the status to its possible values
if (lsSolution.status == "INCONSISTENT") ...
else if (lsSolution.status == "INFEASIBLE") ...
else if (lsSolution.status == "FEASIBLE") ...
else if (lsSolution.status == "OPTIMAL") ...
}
# with ls an object of type LocalSolver
print("Status is " + ls.solution.status)
# you can also compare the status to its possible values
if ls.solution.status == LSSolutionStatus.INCONSISTENT:
...
elif ls.solution.status == LSSolutionStatus.INFEASIBLE:
...
elif ls.solution.status == LSSolutionStatus.FEASIBLE:
...
elif ls.solution.status == LSSolutionStatus.OPTIMAL:
...
// with ls an object of type LocalSolver
std::cout << "Status is " << ls.getSolution().getStatus() << std::endl;
// you can also compare the status to its possible values
if (ls.getSolution().getStatus() == SS_INCONSISTENT) ...
else if (ls.getSolution().getStatus() == SS_INFEASIBLE) ...
else if (ls.getSolution().getStatus() == SS_FEASIBLE) ...
else if (ls.getSolution().getStatus() == SS_OPTIMAL) ...
// with ls an object of type LocalSolver
Console.Writeline("Status is " + ls.GetSolution().GetStatus());
// you can also compare the status to its possible values
if (ls.GetSolution().GetStatus() == SolutionStatus.Inconsistent) ...
else if (ls.GetSolution().GetStatus() == SolutionStatus.Infeasible) ...
else if (ls.GetSolution().GetStatus() == SolutionStatus.Feasible) ...
else if (ls.GetSolution().GetStatus() == SolutionStatus.Optimal) ...
// with ls an object of type LocalSolver
System.out.println("Status is " + ls.getSolution().getStatus());
// you can also compare the status to its possible values
if (ls.getSolution().getStatus() == SolutionStatus.Inconsistent) ...
else if (ls.getSolution().getStatus() == SolutionStatus.Infeasible) ...
else if (ls.getSolution().getStatus() == SolutionStatus.Feasible) ...
else if (ls.getSolution().getStatus() == SolutionStatus.Optimal) ...
Values of numeric variables and expressions¶
Numeric variables and expressions are expressions of the mathematical model
whose value is a boolean and integer of a floating point number. Three methods
are available on expressions to identify these expressions: isBool()
,
isInt()
and isDouble()
(or in Python is_bool
, is_int
and
is_double
and in C# IsBool()
, IsInt()
and IsDouble()
).
As mentioned above, an expression can have an undefined value, what can be
detected with function is_undefined
(Python), isUndefined
(LSP/Java/C++) or IsUndefined
(C#).
function output() {
// with x an ls expression
if (x.isUndefined()) throw "X was expected to have a valid value";
println("x is boolean" ? + (x.isBool() ? "YES": "NO"));
println("value of x is "+ x.value);
}
# with x an object of type LSExpression
if x.is_undefined():
raise Exception("X was expected to have a valid value")
print("x is boolean ? " + ("YES" if x.is_bool() else "NO"))
print("value of x is " + x.value)
// with x an object of type LSExpression
if (x.isUndefined()) throw "X was expected to have a valid value";
std::cout << "x is boolean ? "<< (x.isBool() ? "YES" : "NO") << std::endl;
// same method to retrieve int and bool values
std::cout << "value of x is "<< (x.isDouble() ? x.getDoubleValue() : x.getIntValue() << std::endl;
// with x an object of type LSExpression
if (x.IsUndefined()) throw new Exception("X was expected to have a valid value");
Console.Writeline("x is boolean ? " + (x.isBool() ? "YES": "NO"));
// same method to retrieve int and bool values
Console.Writeline("value of x is " + (x.IsDouble() ? x.GetDoubleValue() : x.GetIntValue());
// with x an object of type LSExpression
if (x.isUndefined()) throw new Exception("X was expected to have a valid value");
System.out.println("x is boolean ? " + (x.isBool() ? "YES": "NO"));
// same method to retrieve int and bool values
System.out.println("value of x is " + (x.isDouble() ? x.getDoubleValue() : x.getIntValue());
Values of collection and array variables and expressions¶
Some expressions of a LocalSolver model do not take numeric values. For instance the value of a set or a list is a collection of integers. Similarly the value of an array expression is an array of values.
Before retrieving the value of the expression, the user can check its type using the necessary methods available on LSExpression objects. The values of these expressions are of type LSCollection (for set and list) or LSArray (for arrays).
These types can be printed directly (the output is formatted with brackets e.g. [4, 8, 7, 2]) or the user can retrieve its values one by one.
function output() {
// with mycoll a set or list expression
local coll = mycoll.value;
println("Collection values = " + coll);
println("Collection size = " + coll.count());
// note that indexing starts at 0 and that the values of a set
// are given in increasing order
println("Collection 8th value = " + coll[7]);
// with myarray an array expression
local arrayvals = myarray.value;
println("Array value = " + arrayvals);
println("Array size = " + arrayvals.count());
println("Array 8th value = " + arrayvals[7]));
}
# with mycoll a set or list expression
coll = mycoll.value
print("Collection values = " + coll)
print("Collection size = " + coll.count())
# note that indexing starts at 0 and that the values of a set
# are given in increasing order
print("Collection 8th value = " + coll[7])
# with myarray an array expression
arrayvals = myarray.value
print("Array value = " + arrayvals)
print("Array size = " + arrayvals.count())
print("Array 8th value is double = " + arrayvals.is_double(7))
print("Array 8th value = " + arrayvals[7])
// with mycoll a set or list expression
LSCollection coll = mycoll.getCollectionValue();
std::cout << "Collection values = " << coll.toString() << std::endl;
std::cout << "Collection size = " << coll.count() << std::endl;
// note that indexing starts at 0 and that the values of a set
// are given in increasing order
std::cout << "Collection 8th value = " << coll[7] << std::endl;
// with myarray an array expression
LSArray arrayvals = myarray.getArrayValue();
std::cout << "Array value = " << arrayvals.toString() << std::endl;
std::cout << "Array size = " << arrayvals.count() << std::endl;
std::cout << "Array 8th value is double = " << arrayvals.isDouble(7) << std::endl;
std::cout << "Array 8th value = " << arrayvals[7] << std::endl;
// with mycoll a set or list expression
LSCollection coll = mycoll.GetCollectionValue();
Console.Writeline("Collection values = " + coll);
Console.Writeline("Collection size = " + coll.Count());
// note that indexing starts at 0 and that the values of a set
// are given in increasing order
Console.Writeline("Collection 8th value = " + coll[7]);
// with myarray an array expression
LSArray arrayvals = myarray.GetArrayValue();
Console.Writeline("Array value = " + arrayvals);
Console.Writeline("Array size = " + arrayvals.Count());
Console.Writeline("Array 8th value is double = " + arrayvals.IsDouble(7));
Console.Writeline("Array 8th value = " + arrayvals[7]);
// with mycoll a set or list expression
LSCollection coll = mycoll.getCollectionValue();
System.out.println("Collection values = " + coll);
System.out.println("Collection size = " + coll.count());
// note that indexing starts at 0 and that the values of a set
// are given in increasing order
System.out.println("Collection 8th value = " + coll.get(7));
LSArray arrayvals = arr.getArrayValue();
System.out.println("Array value = " + arrayvals);
System.out.println("Array size = " + arrayvals.count());
System.out.println("Array 8th value is double = " + arrayvals.isDouble(7));
System.out.println("Array 8th value = " + arrayvals.getDoubleValue(7));
Values of interval variables and expressions¶
The value of an interval decision variable or a range expression is an interval characterized by a start value, an end value, and a size.
Before retrieving the value of the expression, the user can check its type using the necessary methods available on LSExpression objects. The values of these expressions are of type LSInterval.
These types can be printed directly (the output is formatted with points e.g. 5…10) or the user can retrieve its charateristics (start, end, size) one by one.
function output() {
// with myinterval an interval or range expression
local inter = myinterval.value;
println("Interval = " + inter);
println("Interval size = " + inter.count());
println("Interval start = " + inter.start);
println("Interval end = " + inter.end);
}
# with myinterval an interval or range expression
inter = myinterval.value
print("Interval value = " + inter)
print("Interval size = " + inter.count())
print("Interval start = " + inter.start())
print("Interval end = " + inter.end())
// with myinterval an interval or range expression
LSInterval inter = myinterval.getIntervalValue();
std::cout << "Interval value = " << inter.toString() << std::endl;
std::cout << "Interval size = " << inter.count() << std::endl;
std::cout << "Interval start = " << inter.start() << std::endl;
std::cout << "Interval end = " << inter.end() << std::endl;
// with myinterval an interval or range expression
LSInterval inter = myinterval.GetIntervalValue();
Console.Writeline("Interval value = " + inter);
Console.Writeline("Interval size = " + inter.Count());
Console.Writeline("Interval start = " + inter.Start());
Console.Writeline("Interval end = " + inter.End());
// with myinterval an interval or range expression
LSInterval inter = myinterval.getIntervalValue();
System.out.println("Interval value = " + inter);
System.out.println("Interval size = " + inter.count());
System.out.println("Interval start = " + inter.start());
System.out.println("Interval end = " + inter.end());