More advanced features
Topics covered in this chapter:
Other constraint types
In addition to inequality constraints (which include equations and ranged rows), there are a number of other constraints that Xpress supports:
- Special ordered set constraints restrict the number of variables that can be non-zero.
- Indicator constraints conditionally enable or disable inequality constraints, based on the values of binary variables.
- Piecewise linear constraints set one variable to the result of evaluating a piecewise linear function for another variable.
- General constraints model things like absolute value, maximum or minimum of variables and values, and logical and/or between binary variables.
Creation of these constraints is described in detail below.
Special ordered set (SOS) constraints
Special ordered set (SOS) constraints specify how many and which variables in a set of variables can be non-zero. For an SOS constraint of type 1 only one variable in the set can be non-zero. For an SOS constraint of type 2 at most two variables in the set can be non-zero and non-zero variables must be adjacent.
The ordering of variables within a set is given by weights assigned to variables: variables are ordered by increasing weight values and two different variables cannot have the same weight. In many cases the order in which variables are passed to functions is already the intended one. In that case the weight argument to the functions can be null. The function will then assume weights 1, 2, ...
Note that weights are not only used for ordering. Instead the actual weight values may be used by the solver algorithm when taking branching or other decisions in the solution process. Refer to the solver documentation for more details.
One way to create SOS constraints is by using the static sos(), sos1(), or sos2() function of the SOSConstraint class:
// Create an SOS1 for { x, y, z } with default weights. import static com.dashoptimization&nssep;objects.SOS.sos; import static com.dashoptimization&nssep;objects.SOS.sos1; import static com.dashoptimization&nssep;objects.SOS.sos2; prob.addConstraint(sos(SetType.SOS1, new Variable[]{ x, y, z }, null, "SOS constraint")); // Create the same SOS1 prob.addConstraint(sos1(new Variable[]{ x, y, z }, null, "SOS constraint")); // Create an SOS2 for { x, y, z } with default weights. prob.addConstraint(sos2(new Variable[]{ x, y, z }, null, "SOS constraint"));
Indicator constraints
In Xpress, indicator constraints are not represented as explicit constraints. Instead they are defined by combining an inequality r with a binary variable b. Once these two are combined, the solver will enforce a condition that if b is set then r is satisfied. If b is not set then r may be violated.
Note that the condition on variable b may be complemented. In that case r is only enforced if b is not set.
In order to set indicator variables for certain inequality constraints, use function XpressProblem.setIndicatorVariable():
Variable b = ...; Inequality r1 = ...; Inequality r2 = ...; prob.setIndicatorVariable(b, true, r1); prob.setIndicatorVariable(b, false, r2);
The above code will enforce r1 if variable b is set (has value 1) and enforce r2 if b is not set (has value 0).
The XpressProblem class also has a setIndicatorVariables function with which multiple indicators can be set with a single function call.
Another way to set indicator variables for inequalities is by using the ifThen and ifNotThen function of the Variable class. These functions create an indicator constraint with the given variable as indicator variable:
prob.addConstraint(b.ifThen(r1)); // enforce r1 if b is set prob.addConstraint(b.ifNotThen(r2)); // enforce r2 if b is not set
Piecewise linear constraints
A piecewise linear constraint is a constraint of the form
resultant = PWL(breakpoints)(argument)
Here resultant and argument are variables and PWL(breakpoints) is a piecewise linear function specified by the given breakpoints. See the documentation of function XPRSaddpwlcons for a detailed explanation of how breakpoints are specified.
Piecewise linear constraints can be created using the pwlOf member function of class Variable (assuming that resultant and argument are instances of Variable:
double[] breakX = ...; double[] breakY = ...; prob.addConstraint(resultant.pwlOf(argument, breakX, breakY)); Breakpoint[] breaks = ...; prob.addConstraint(resultant.pwlOf(argument, breaks));
General constraints
A general constraint is a constraint of the form
resultant = function(y1, y2, ..., v1, v2, ...)
where resultant is a variable, function is a function like "min", "max", "abs", "or", "and", yi are variables and vi are constant values.
General constraints can be created by invoking an appropriate member function on the resultant variable:
Variable x, y1, y2, y3; prob.addConstraint(x.absOf(y)); // add x = |y| prob.addConstraint(x.orOf(y1, y2)); // add x = y1 or y2 prob.addConstraint(x.andOf(y1, y2, y3)); // add x = y1 and y2 and y3 prob.addConstraint(x.maxOf(y1, y2, 4)); // add x = max(y1, y2, 4.0) prob.addConstraint(x.minOf(y1, 2)); // add x = min(y1, 2.0)
Performance considerations
While building small to medium-sized problems, there is usually no need to consider which way is the fastest to create the problem. The speed of different strategies does not matter.
When building models with hundreds of thousands or even millions of elements, it is important to know that some methods are faster than others:
- Building linear expressions
- The most efficient way to build a linear expression is by creating an instance of LinExpression and then add the terms to this instance. In order to be as fast as possible, use the LinTermList class rather than the LinTermMap class (note that there are some caveats about this class, see above and in the reference documentation).
- Building quadratic expressions
- As with linear expressions, the most efficient way to build a quadratic expression is using QuadExpression ( QuadTermList).
- Bulk operators are faster than single operations
-
Consider this loop:
for (int i = 0; i < n; ++i) prob.addConstraint(...);
This adds constraints one by one to the model. A more efficient way to do this is to add all constraints in one shot:prob.addConstraints(n, i -> ...);
This adds exactly the same constraints in the same order but reduces interaction with the low-level code.
Accessing the matrix
Class XpressProblem is a subclass of XPRSprob. The latter provides a direct matrix-based interface to the solver. Any function in XPRSprob directly maps to a function call in the C implementation of the solver. Since XpressProblem is a subclass of XPRSprob, all these functions are also available when modeling with objects. In order to interact with a function in XPRSprob, you need the indices of the objects. These can be obtained using the getIndex() function of classes like Variable, Inequality, SOS, PWL, GeneralConstraint.
© 2001-2024 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.