lec15.mws

L-15 MCS 320 Monday 26 September 2005

> restart;

1. Mathematical Functions

We will see three different ways to turn a formula into a function.

> expT := 30 + 40*exp(-0.2*t); # cooling off

expT := 30+40*exp(-.2*t)

If we wish to evaluate this formula, we can work in three ways:

1.1. using a macro

What we used so far is the substitution, e.g. for t = 1.5:

> subs(t=1.5,expT);

30+40*exp(-.30)

> evalf(%);

59.63272883

> macro(mt = evalf @ subs); # same syntax as alias

mt

The "mt" is defined as the composition of subs, followed by evalf.

We apply this composition to the formula expT, with argument "t = 1.5".

> mt(t=1.5,expT)

59.63272883

> ;

The advantage of this approach is that it relates very much to the substitution, with an explicit binding between the values and the names of the formal parameters.

1.2. as a procedure

At the end of the first part of the course, we have seen the "codegen" package.

> f := codegen[makeproc](expT,t);

f := proc (t) 30+40*exp(-.2*t) end proc

> f(1.5);

59.63272883

With the definition of f, we have the conventional notion of a function.  On input we have a value, on output we obtain a value.  Unlike the macro, we do not need to give an equality on input.  We do not need to know the name of the formal variable.

> f(time);

30+40*exp(-.2*time)

Unlike the conventional functions which take values on input and return values, in symbolic computing, we may give symbols to functions and recover formulas.

> f(3/2);

59.63272883

Notice that because of the -0.2 in the definition of the formula it does not return an exact result.

1.3. using the unapply

Perhaps the most convenient way to turn a formula into a function is via the unapply.

> g := unapply(expT,t);

g := proc (t) options operator, arrow; 30+40*exp(-.2*t) end proc

> g(1.5);

59.63272883

Also here we can undo the unapply, by evaluating at a formal variable and recover the formula:

> g(time); # apply the function to a formal variable time

30+40*exp(-.2*time)

2. The arrow operator

The arrow operator is very close to the mathematical notation of a function.

We can type in the definition of a function with the arrow operator, very similar as we would write it on paper:

> h := t -> 30 + 40*exp(-0.2*t);

h := proc (t) options operator, arrow; 30+40*exp(-.2*t) end proc

> h(1.5);

59.63272883

If the formula was too long, we could have typed:

> h2 := t -> expT;

h2 := proc (t) options operator, arrow; expT end proc

> h2(1.5);

30+40*exp(-.2*t)

The problem with this approach is that, when we defined h2, the formula expT was not evaluated, it was not connected to the formal variable t.

This problem motivates the existence of the "unapply" next to the arrow operator.

> h3 := x -> evalf(subs(t=x,expT));

h3 := proc (x) options operator, arrow; evalf(subs(t = x, expT)) end proc

> h3(1.5);

59.63272883

With the subs, we forced the evaluation of the formula.  With the evalf, we create a floating-point value.

An illustration in several variables is the multiprecision evaluation.  Suppose we want to give as an additional parameter, the number of digits we want to see in the result.

> e := (x,n) -> evalf(subs(t=x,expT),n);

e := proc (x, n) options operator, arrow; evalf(subs(t = x, expT), n) end proc

> e(1.5,20);

59.632728827268714643

3. Piecewise defined functions

Not all functions have one recipe, but are defined as piecewise functions.

Suppose we want to define a hat function:

> hat := proc(x)

>  description "a simple hat function":

>  if x < 1 then

>    return 0;

>  elif x < 2 then

>    return 1;

>  else

>    return 0;

>  end if;

> end proc;

hat := proc (x) description

> plot(hat,0..3,scaling=constrained);

[Plot]

While this definition as a procedure works well for evaluating, it does not work for integration:

> int(hat(t),t=0..3);

Error, (in hat) cannot determine if this expression is true or false: t < 1

> int(hat,x=0..3);

3*hat

> diff(hat,x);

0

Maple cannot compute the area under the hat if the procedure definition is used.

> phat := piecewise(x<1,0,x<2,1,0);

phat := PIECEWISE([0, x < 1], [1, x < 2], [0, otherwise])

> int(phat,x=0..3);

1

> diff(phat,x);

PIECEWISE([undefined, x = 1], [undefined, x = 2], [0, otherwise])

The advantage of using piecewise is that operations like diff and int work.

For derivation of procedures, we have automatic differentiation, see later.