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 |
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); |
| > | evalf(%); |
| > | macro(mt = evalf @ subs); # same syntax as alias |
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) |
| > | ; |
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(1.5); |
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); |
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); |
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(1.5); |
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 |
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(1.5); |
If the formula was too long, we could have typed:
| > | h2 := t -> expT; |
| > | h2(1.5); |
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(1.5); |
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(1.5,20); |
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; |
| > | plot(hat,0..3,scaling=constrained); |
![[Plot]](images/lec15_22.gif)
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); |
| > | diff(hat,x); |
Maple cannot compute the area under the hat if the procedure definition is used.
| > | phat := piecewise(x<1,0,x<2,1,0); |
| > | int(phat,x=0..3); |
| > | diff(phat,x); |
The advantage of using piecewise is that operations like diff and int work.
For derivation of procedures, we have automatic differentiation, see later.