*X*- Parameter/domain of the piecewise function
*Points*- Collection (a la collection_to_list/2) of points defining the piecewise function
*Y*- Result/interval of piecewise the function

This predicate imposes the constraint Y = f(X), where f is a piecewise linear function defined by Points. Points must be (after processing by collection_to_list/2) a list of elements of the form (X, Y), sorted by increasing X values. The function is constructed by performing linear interpolation between consecutive points, and extrapolating the first and last linear segments to infinity.

Discontinuities are allowed, by specifying more than one point with the same X coordinate. However, since the constraint is a function, one must specify which of the given Y values is the true value of the function at that point. This is done by annotating which of the adjacent line segments is ``open'' at that end (i.e. does not include the end point). There are three allowed forms of discontinuity:

(X1, Y1), (X2, Y2a), (>(X2), Y2b), (X3, Y3)

(X1, Y1), (<(X2), Y2a), (X2, Y2b), (X3, Y3)

(X1, Y1), (<(X2), Y2a), (X2, Y2b), (>(X2), Y2c), (X3, Y3)

In the first form, the segment specified by the first two points is defined over the interval [X1 .. X2] while that specified by the last two is defined over the interval (X2 .. X3]. That is, the first interval is closed at X2, the second is open at X2 (i.e. only includes points strictly greater than X2), and thus the value of the function at X2 is Y2a.

In the second form, the reverse is true. The first segment is over the interval [X1 .. X2) (points less than X2), the second is over the interval [X2 .. X3], and the value of the function at X2 is Y2b.

The final form is a double discontinuity. Both adjacent segments are open - [X1 .. X2), (X2 .. X3] - and at X2 the value of the function is Y2b, taken from neither segment.

Note that a segment can be open at both ends, if it has discontinuities at both ends. For example, if the list of points is

[(0, 0), (10, 0), (>(10), 1), (<(20), 1), (20, 2), (30, 2)]

then the function has value 0 for all values of X up to and including 10, it has value 2 for all values of X from 20 onwards, and has value 1 in between.

Other notes:

A piecewise linear constraint is expected to have at least two points (though if it only has two, then a standard linear constraint would do, and likely be more efficient). If there is only one point, then there is no way to determine the gradient to use to extend the function to other values of X. As a result, the value of the function is not defined for all other values of X. Similarly, if the first or last points in the specification of the piecewise constraint are involved in discontinuities, then the corresponding extensions to infinity are undefined; it is recommended that the user either provide a valid extension by supplying an extra point, or exclude those values of X by imposing an appropriate bound. (In any event, the first and last points must be closed; an open discontinuity is not permitted at either end.)

Whilst the piecewise constraint accepts bounded reals in its arguments, the current implementation does not fully support bounded reals of non-zero width (i.e. those which do not correspond to a single floating point value). As a result, use of such bounded reals is not recommended at this time.