Previous Page Next Page Contents

piecewise -- the domain of conditionally defined objects

Introduction

piecewise([condition1, object1], [condition2, object2], ...) generates a conditionally defined object that equals object1 if condition1 is satisfied, object2 if condition2 is satisfied, etc.

Creating Elements

piecewise([condition1, object1], [condition2, object2], ...)

Parameters

condition1, condition2, ... - Boolean constants or expressions representing logical formulas
object1, object2, ... - arbitrary objects

Side Effects

Properties of identifiers set by assume are taken into account.

Related Functions

_case, _if, assume, bool, is

Details

Method _in: membership with piecewise on the left hand side

Method contains: apply the function contains to the objects in all branches

Method diff: (partial) differentiation

Method discont: determine the discontinuities of a piecewise defined function

Method piecewise::disregardPoints: heuristic for simplifying conditions

Method expand: apply the function expand to the objects in all branches

Method piecewise::getElement: get any element of a conditionally defined set

Method has: test for the existence of a subobject

Method int: definite and indefinite integration of a piecewise defined function

Method piecewise::isFinite: test whether a piecewise defined set is finite

Method normal: apply the function normal to the objects in all branches

Method piecewise::restrict: impose an additional condition

Method piecewise::set2expr: membership with piecewise on the right hand side

Method simplify: simplify a conditionally defined object

Method solve: solve a conditionally defined equation or inequality

Method piecewise::solveConditions: isolate a given identifier in all conditions

Method piecewise::Union: union of a system of sets

Method _concat: merge piecewise objects

Method piecewise::condition: the condition in a specific branch

Method piecewise::expression: the object in a specific branch

Method piecewise::insert: insert a branch at a given position

Method map: apply a function to the objects in all branches

Method piecewise::mapConditions: apply a function to the conditions in all branches

Method piecewise::mapMap: apply the function map to the objects in all branches

Method piecewise::remove: remove a branch

Method piecewise::selectConditions: select branches depending on their condition

Method piecewise::splitConditions: split branches depending on conditions

Method subs: substitution

Method zip: apply a binary operation pointwise

Example 1

We define f as the characteristic function of the interval [0,1]:

>> f := x -> piecewise([x < 0 or x > 1, 0], [x >= 0 or x <= 1, 1])
        x -> piecewise([x < 0 or 1 < x, 0], [0 <= x or x <= 1, 1])

None of the conditions can be evaluated to TRUE or FALSE, unless more is known about the variable x. When we evaluate f at some point, the conditions are checked again:

>> f(0), f(2), f(I)
                              1, 0, undefined

Example 2

piecewise performs a case analysis using the property mechanism. It checks whether the given conditions are mathematically true or false; it may also decide that not enough information is available. In the following example, it cannot be decided whether a is zero as long as no assumptions on a have been made:

>> delete a:
   p := piecewise([a = 0, 0], [a <> 0, 1/a])
                            /             1           \
                   piecewise| 0 if a = 0, - if a <> 0 |
                            \             a           /

In contrast, if-statements evaluate the conditions syntactically: a=0 is technically false since the identifier a and the integer 0 are different objects:

>> if a = 0 then 0 else 1/a end
                                     1
                                     -
                                     a

Moreover, piecewise takes properties of identifiers into account:

>> assume(a = 0):
   p;
   delete a, p:
                                     0

Example 3

Conditionally defined objects can be created by rewriting special functions:

>> f := rewrite(sign(x), piecewise)
               /
      piecewise| 1 if 0 < x, -1 if x < 0, 0 if x = 0,
               |
               \
      
                  x                          \
         -------------------- if not x in R_ |
               2        2 1/2                |
         (Im(x)  + Re(x) )                   /

In contrast to MuPAD, most people like to regard sign as a function defined for real numbers only. You might therefore want to restrict the domain of f:

>> f := piecewise::restrict(f, x in R_)
      piecewise(1 if x in ]0, infinity[, -1 if x in ]-infinity, 0[,
      
         0 if x in {0})

Conditionally defined arithmetical expressions allow roughly the same operations as ordinary arithmetical expressions. The result of an arithmetical operation is only defined at those points where all of the arguments are defined:

>> f + piecewise([x < 2, 5])
          piecewise(6 if 0 < x and x < 2, 4 if x < 0, 5 if x = 0)

Example 4

There are several methods for extracting branches, conditions, and objects. Consider the following conditionally defined object:

>> f := piecewise([x > 0, 1], [x < -3, x^2])
                                           2
                    piecewise(1 if 0 < x, x  if x < -3)

You can extract a specific condition or object:

>> piecewise::condition(f, 1), piecewise::expression(f, 2)
                                         2
                                 0 < x, x

The function op extracts whole branches:

>> op(f, 1)
                                1  if 0 < x

You can form another piecewise defined object out of those branches for which the condition satisfies a given selection criterion, or split the input into two piecewise defined objects, as the system functions select and split do it for lists:

>> piecewise::selectConditions(f, has, 0)
                           piecewise(1 if 0 < x)
>> piecewise::splitConditions(f, has, 0) 
                                           2
        [piecewise(1 if 0 < x), piecewise(x  if x < -3), undefined]

You can also create a copy of f with some branches added or removed:

>> piecewise::remove(f, 1)              
                                     2
                          piecewise(x  if x < -3)
>> piecewise::insert(f, [x > -3 and x < 0, sin(x)], 2)
                                                         2
      piecewise(1 if 0 < x, sin(x) if x < 0 and -3 < x, x  if x < -3)

Example 5

Most unary functions are overloaded for piecewise by mapping them to the objects in all branches of the input. This can also be achieved using map:

>> f := piecewise([x >= 0, arcsin(x)], [x < 0, arccos(x)]):
   sin(f)
                                         2     1/2
              piecewise(x if 0 <= x, (- x  + 1)    if x < 0)
>> map(f, sin)
                                         2     1/2
              piecewise(x if 0 <= x, (- x  + 1)    if x < 0)

This causes the following problem. If one of the conditions becomes true, e.g., by some assumption on x, then f evaluates to an object that is not of type piecewise. Applying sin then still works, but map maps the sine function to the operands of f. Hence map should be used with care:

>> assume(x < 0):
   sin(f);
   map(f, sin);
                                      2 1/2
                                (1 - x )
      
                              arccos(sin(x))
>> delete x:

The converse problem occurs if you want to apply the function map to the objects in all branches. The method mapMap should be used for this purpose.

Example 6

Sets may also be conditionally defined. Such sets are sometimes returned by solve:

>> S := solve(a*x = 0, x)
                   piecewise(C_ if a = 0, {0} if a <> 0)

The usual set-theoretic operations work for such sets:

>> S intersect Dom::Interval(3, 5)
                 piecewise(]3, 5[ if a = 0, {} if a <> 0)

Sometimes it is interesting to exclude the ``rare cases'' which only cover a small set of parameter values:

>> piecewise::disregardPoints(S)
                                    {0}

Example 7

Consider the following case distinction:

>> p1 := piecewise([a > 0, a^2], [a <= 0, -a^2]):
   p2 := piecewise([b > 0, a + b], [b = 0, p1 + b], [b < 0, a + b])
                                     2
      piecewise(a + b if 0 < b, b + a  if 0 < a and b = 0,
      
              2
         b - a  if b = 0 and a <= 0, a + b if b < 0)

Note that the system has moved the case analysis done in p1 to the top level automatically. However, some simplifications are still possible: the branches b>0 and b<0 can be collected, and in the case b=0 the identifier b may be replaced by the value 0:

>> simplify(p2)
                                  2
      piecewise(a + b if b <> 0, a  if 0 < a and b = 0,
      
            2
         - a  if b = 0 and a <= 0)

Background

Changes




Do you have questions or comments?


Copyright © SciFace Software GmbH & Co. KG 2000