Geometry /

This part explains construction of piecewise functions, i.e. functions defined over sets. To understand the basic concepts, you should be familiar with the construction of sets, constrution of unions of sets, and construction of functions.

- Single function over the set
- Piecewise Affine Function
- Piecewise Quadratic Function
- Piecewise Function

Function over the set can be constructed by attaching the `Function`

object to an object derived from the `ConvexSet`

class. Consider a quadratic function ` y = x^2 - 2*x +1 `

defined over the interval ` -1 <= x <= 2 `

. To represent such a function over the set in MPT, it is required to construct corresponding `Function`

object and `ConvexSet`

object and then add the function to the set using `addFunction`

method:

F = QuadFunction(1, -2, 1);

S = Polyhedron('lb', -1, 'ub', 2);

S.addFunction(F,'alpha')

S = Polyhedron('lb', -1, 'ub', 2);

S.addFunction(F,'alpha')

When adding the `Function`

object to the `ConvexSet`

object, it is required to provide the name of the function to be used for referencing. In the above example the quadratic function will be stored under the name "alpha". The name of the function is obligatory in order to distinguish multiple functions over the set. When the function has been attached, the object still behaves as a convex set and all methods applicable for `ConvexSet`

class can be used, including additional methods for functions over sets. For instance, to plot the set one can use the `plot`

method

S.plot()

that applies for objects derived from the `ConvexSet`

class. To plot the function over the set, the specific method `fplot`

applies

S.fplot()

To plot both, the set and the function over the set, it is required to provide some arguments for the `fplot`

method:

S.fplot('show_set', true, 'color', 'blue', 'linewidth', 2, 'linestyle', '--')

For more help on plotting functions over sets, type

help ConvexSet/fplot

Multiple functions can be attached to a set. In the following example two functions are attached to an interval [0, 2]

f1 = Function( @(x)exp(0.3*x) )

f2 = AffFunction(0.3,1)

P = Polyhedron('lb', 0, 'ub', 2);

P.addFunction(f1, 'a')

P.addFunction(f2, 'b')

f2 = AffFunction(0.3,1)

P = Polyhedron('lb', 0, 'ub', 2);

P.addFunction(f1, 'a')

P.addFunction(f2, 'b')

The stored function objects are accessible by index using the `Func`

property or can be extracted via the `getFunction`

method by pointing to their names

P.getFunction('a')

P.getFunction('b')

P.getFunction('b')

Referencing to the function name is useful for plotting the specific function over the set

P.fplot('a','color','green','linewidth', 2);

hold on

P.fplot('b','color','blue', 'linewidth', 2, 'linestyle', '--');

P.plot('color', 'red', 'linewidth', 2)

legend(2,'a', 'b')

hold on

P.fplot('b','color','blue', 'linewidth', 2, 'linestyle', '--');

P.plot('color', 'red', 'linewidth', 2)

legend(2,'a', 'b')

The evaluation of the function for a particular point is achieved via `feval`

method and the function must be referenced by its name. For instance, to evaluate the function "a" for a point 0.5 can be done as follows

P.feval(0.5, 'a')

Piecewise affine (PWA) function can be represented as union of sets that have attached an affine function. In the previous section you can learn how to construct single function over a set. Merging multiple affine functions over sets to a compact form of the `PolyUnion`

object represents a piecewise affine function over polyhedra. As an example, consider a saturated controller `u(x) = 1 if -5 <= x<= -1, u(x) = -x if -1 <= x <= 1, u(x) = -1 if 1 <= x <= 5 `

. To create PWA function the corresponding intervals are defined as `Polyhedron`

objects:

R(1) = Polyhedron('lb', -5, 'ub', -1);

R(2) = Polyhedron('lb', -1, 'ub', 1);

R(3) = Polyhedron('lb', 1, 'ub', 5);

R(2) = Polyhedron('lb', -1, 'ub', 1);

R(3) = Polyhedron('lb', 1, 'ub', 5);

Secondly, the function objects are created and attached to the intervals under the same name

f(1) = AffFunction(0, 1);

f(2) = AffFunction(-1);

f(3) = AffFunction(0, -1);

R(1).addFunction(f(1), 'u');

R(2).addFunction(f(2), 'u');

R(3).addFunction(f(3), 'u');

f(2) = AffFunction(-1);

f(3) = AffFunction(0, -1);

R(1).addFunction(f(1), 'u');

R(2).addFunction(f(2), 'u');

R(3).addFunction(f(3), 'u');

Thirdly, the functions over sets are merged to a single `PolyUnion`

object. If some properties of the union are known at the time of constructing the `PolyUnion`

object, one can associate them directly to the constructor:

U = PolyUnion('Set', R, 'Convex', true, 'Overlaps', false, 'Bounded', true, 'FullDim', true, 'Connected', true)

The PWA function can be plotted using overloaded `fplot`

function that applies for `PolyUnion`

objects:

U.fplot('u', 'linewidth', 2)

axis([-8 8 -2 2])

xlabel('x')

ylabel('u')

axis([-8 8 -2 2])

xlabel('x')

ylabel('u')

Evaluation of PWA functions proceeds via overloaded `feval`

function. If there is only one function attached to a set, one does not have to refer to the name

U.feval(3)

Note that for two points -1,1 there exist two functions values because these points lie at the connection of the intervals. When evaluation of PWA function is invoked for such a point, two values are returned

U.feval(-1)

U.feval(1)

U.feval(1)

To get rid of multiple values, it is **always** recommended to use the extended evaluation syntax that considers the tie-break criterion to decide which value to use. For instance, if an anonymous function ` @(x)0 `

is used as a tie-breaking function, it takes always the first choice

U.feval(-1, 'tiebreak', @(x)0 )

Consider a PWA function that is defined over two regions which are overlapping.

P(1) = Polyhedron('lb', -3, 'ub', 2 );

P(1).addFunction( AffFunction(-0.8, 1), 'a' );

P(2) = Polyhedron('lb', -2, 'ub', 3);

P(2).addFunction( AffFunction(0.8, 1), 'a' );

U = PolyUnion('Set', P, 'Overlaps', true)

U.fplot()

P(1).addFunction( AffFunction(-0.8, 1), 'a' );

P(2) = Polyhedron('lb', -2, 'ub', 3);

P(2).addFunction( AffFunction(0.8, 1), 'a' );

U = PolyUnion('Set', P, 'Overlaps', true)

U.fplot()

Note that evaluation of such a function could return two different values for a point that is shared in two intervals. This case can be resolved by a tie-breaking function which in this example takes the minimum of the same function 'a'

U.feval(-1, 'a')

U.feval(-1, 'a', 'tiebreak', 'a')

U.feval(-1, 'a', 'tiebreak', 'a')

Piecewise quadratic (PWQ) function can be represented as an union of quadratic functions over polyhedra. Consider the following function `y(x) = 0.3*|x-1|^2 + |x+2|`

over the interval [-5, 5]. The function can be decomposed to three intervals:

`y1 = 0.3*x^2 - 1.6*x - 1.7 if [-5, -2]`

`y2 = 0.3*x^2 + 0.4*x + 2.3 if [-2, 1]`

`y3 = 0.3*x^2 + 0.4*x + 2.3 if [1, 5]`

where the two intervals share the same function value. Such a function can be modeled in MPT with the help of `Polyhedron`

, `QuadFunction`

and `PolyUnion`

objects:

S(1) = Polyhedron('lb', -5, 'ub', -2 );

S(1).addFunction( QuadFunction(0.3, -1.6, -1.7), 'q' );

S(2) = Polyhedron('lb', -2, 'ub', 1);

S(2).addFunction( QuadFunction(0.3, 0.4, 2.3), 'q' );

S(3) = Polyhedron('lb', 1, 'ub', 5);

S(3).addFunction( QuadFunction(0.3, 0.4, 2.3), 'q' );

U = PolyUnion('Set', S, 'Overlaps', false, 'Convex', true, 'FullDim', true, 'Bounded', true)

U.fplot()

S(1).addFunction( QuadFunction(0.3, -1.6, -1.7), 'q' );

S(2) = Polyhedron('lb', -2, 'ub', 1);

S(2).addFunction( QuadFunction(0.3, 0.4, 2.3), 'q' );

S(3) = Polyhedron('lb', 1, 'ub', 5);

S(3).addFunction( QuadFunction(0.3, 0.4, 2.3), 'q' );

U = PolyUnion('Set', S, 'Overlaps', false, 'Convex', true, 'FullDim', true, 'Bounded', true)

U.fplot()

Evaluation of PWQ function is achieved using the overloaded `feval`

method as for PWA functions:

U.feval(0.6)

The piecewise function represents any general function defined over polyhedra. Consider the following partition comprising of three regions in two-dimensional space:

P(1) = Polyhedron([0 0; 2 2; 0 4]);

P(2) = Polyhedron([0 0; 4 0; 4 2; 2 2]);

P(3) = Polyhedron([0 4; 4 4; 4 2; 2 2]);

P(2) = Polyhedron([0 0; 4 0; 4 2; 2 2]);

P(3) = Polyhedron([0 4; 4 4; 4 2; 2 2]);

To each of the polyhedra a function is assigned under the same name "g", then the `PolyUnion`

object is created and the function over the union is plotted.

F1 = AffFunction([2.8 3.3]);

P(1).addFunction(F1, 'g');

F2 = QuadFunction(0.2*eye(2), [-3.2, 2.9], 11.2);

P(2).addFunction(F2, 'g');

F3 = Function(@(x) 0.4*x(1)^2 + 0.8*sqrt(x(1)+x(2)) - 1.3*x(1)*x(2) + 14.2 );

P(3).addFunction(F3, 'g');

U = PolyUnion('Set', P, 'Overlaps', false, 'Convex', true)

U.fplot()

P(1).addFunction(F1, 'g');

F2 = QuadFunction(0.2*eye(2), [-3.2, 2.9], 11.2);

P(2).addFunction(F2, 'g');

F3 = Function(@(x) 0.4*x(1)^2 + 0.8*sqrt(x(1)+x(2)) - 1.3*x(1)*x(2) + 14.2 );

P(3).addFunction(F3, 'g');

U = PolyUnion('Set', P, 'Overlaps', false, 'Convex', true)

U.fplot()

Back to computational geometry overview.