Discontinuous piecewise-linear functions
Describes the use of discontinuous piecewise-linear functions in OPL.
OPL also allows you to write discontinuous piecewise-linear functions.
This is the case when, in the syntax of a piecewise-linear function
with slopes and breakpoints, two successive breakpoints are identical
and the value associated with the second one is considered to be a step
instead
of a slope
. The CPLEX and the CP Optimizer engines behave differently
with respect to what limit they consider as the discontinuity value.
Because CPLEX allows either of these limits, note that the anchor
point used to ground the breakpoints and slopes must not reside at
the discontinuity. Otherwise, the piecewise-linear function would
not be uniquely defined.
Behavior with the CPLEX engine
Example 1: the sign function
The following piecewise function:
piecewise{0 -> 0;2 -> 0; 0}(1,1) x;
has a slope of 0 up to breakpoint 0, then a step of 2 at this breakpoint, then a slope of 0. It takes the value 1 at point 1. This piecewise represents the function sign() which returns the sign (1 or -1) of its argument, as represented in Figure 1 below.
![Diagram of the discontinuous function “sign”](../images/discontpwl4.jpg)
Then this model
dvar float x;
dvar float signx;
dvar float y;
dvar float signy;
maximize x;
subject to {
x == 2;
signx == piecewise{0->0; 2->0; 0}(1,1) x;
y == -2;
signy == piecewise{0->0; 2->0; 0}(1,1) y;
}
gives the following output:
Final solution with objective 2.0000:
x = 2.0000;
signx = 1.0000;
y = -2.0000;
signy = -1.0000;
Figure 1 shows that the value of the sign function at the breakpoint is either -1 (on the left-hand slope) or 1 (on the right-hand slope).
For example, this model takes this into account and sets the constraint x==y; on both values.
dvar float x;
dvar float signx;
dvar float y;
dvar float signy;
maximize signx-signy;
subject to {
x == y;
signx == piecewise{0->0; 2->0; 0}(1,1) x;
signy == piecewise{0->0; 2->0; 0}(1,1) y;
}
This model solves with the following output:
Final solution with objective 2:
signx = 1;
signy = -1;
x = 0;
y = 0;
Example 2: discontinuous cost
The following piecewise function
piecewise{0->0; 10->0; 0->10; 5->10; 0->20; 5->20; 0} (5,10) unit;
represents a discontinuous cost.
This function is illustrated in Figure 2, Discontinuous costs, for the values summarized in Table 1.
Values of Unit | Cost |
---|---|
<0 | 0 |
0 to 10 | 10 |
10 to 20 | 15 |
>20 | 20 |
![Diagram of a discontinuous pwl costs function](../images/discontcost5.jpg)
Different behavior with the CP Optimizer engine
Consider the following model:
//using CP;
dvar int x in -10..10;
dvar int signx;
dvar int y in -10..10;
dvar int signy;
maximize signx-signy;
subject to {
x == y;
signx == piecewise{0->0; 2->0; 0}(1,1) x;
signy == piecewise{0->0; 2->0; 0}(1,1) y;
}
execute
{
writeln(signx-signy);
}
Depending on which solving engine you write for, you get a different result because CPLEX and CP Optimizer do not handle limit values in the same way.
If you comment out the using CP; statement, the model is solved by the CPLEX engine and the result is 2 because CPLEX handles symmetry in such a way that it interprets either limit as the discontinuity value.
However, if you uncomment the using CP; statement, the model is solved by the CP Optimizer engine and the result is 0 because CP Optimizer considers the left limit as the discontinuity value.