9 Assembling functions
When we need a new function for some purpose, we practically always build it out of existing functions. For illustrate, a function like
In this chapter, we will review four general frameworks for combining functions: linear combination of functions, function composition, function multiplication, and “piecewise” splitting of the domain. You have almost certainly seen all four of these frameworks in your previous mathematical studies, although you might not have known that they have names.
9.1 Linear combination
One of the most widely used sorts of combination is called a linear combination. The mathematics of linear combination is, it happens, at the core of the use of math in a large variety of real-world applications, whether that be constructing a Google-like search engine or analyzing medical data to see if a treatment has a positive effect.
To illustrate how linear combination is used to create new functions, consider polynomials, for instance,
There are three pattern-book functions in this polynomial. In polynomials the functions being combined are all power-law functions:
There are other places where you have seen linear combinations:
- The parameterized sinusoid
is a linear combination of the functions and . The linear combination is . - The parameterized exponential
The functions being combined are and . The scalars are, again, and . - The straight-line function, such as
and . The functions being combined are and , the scalars are and .
There are a few reasons for us to be introducing linear combinations here.
- You will see linear combinations everywhere once you know to look for them.
- There is a highly refined mathematical theory of linear combinations that gives us powerful ways to think about them as well as computer software that can quickly find the best scalars to use to match input-output data.
- The concept of linear combination generalizes the simple idea that we have been calling “scaling the output.” From now on, we will use the linear-combination terminology and avoid the narrower idea of “scaling the output.”
- Many physical systems are described by linear combinations. For instance, the motion of a vibrating molecule, a helicopter in flight, or a building shaken by an earthquake are described in terms of simple “modes” which are linearly combined to make up the entire motion. More down to Earth, the timbre of a musical instrument is set by the scalars in a linear combination of pure tones.
- Many modeling tasks can be put into the framework of choosing an appropriate set of simple functions to combine and then figuring out the best scalars to use in the combination. (Generally, the computer does the figuring.)
9.2 Function composition
To compose two functions,
For instance, suppose you have recorded the outdoor temperature over the course of a day and packaged this into a function
It is important to distinguish the above time
9.3 Function multiplication
Multiplication is the third in our repertoire of methods for making new functions. With two functions
It is essential to distinguish between function multiplication and function composition:
In function composition, the order of the functions matters:
In function multiplication, the order does not matter because multiplication is commutative, that is, if
In function composition, only one of the functions—the interior function is applied to the overall input,
In multiplication, each of the functions is applied to the input individually. Then their outputs are multiplied to produce the overall output.
Transient vibration
A guitar string is plucked to produce a note. The sound is, of course, vibrations of the air created by vibrations of the string.
After plucking, the note fades away. An important model of this is a sinusoid (of the correct period to correspond to the frequency of the note) times an exponential.
Function multiplication is used so often in modeling that you will see it in many modeling situations. Here’s one example that is important in physics and communication: the wave packet. Overall, the wave packet is a localized oscillation as in Figure 9.2. The packet can be modeled with the product of two pattern-book functions: a gaussian times a sinusoid.
Functions constructed as a product of simple functions can look like this in tradition notation:
and like this in computer notation:
<- makeFun(sin(t)*exp(-t) ~ t) h
9.4 Splitting the domain
Consider the familiar absolute-value function:
Written this way, the definition of
Can we assemble
One way to construct the sharp transition is to view
A function defined separately on different pieces of its domain is called a piecewise function. In the conventional mathematical notation, there is a large
Another piecewise function widely used in technical work, but not as familiar as
The Heaviside function is defined on the same two pieces of the number line as
The vertical gap between the two pieces of the Heaviside function is called a discontinuity. Intuitively, you cannot draw a discontinuous function without lifting the pencil from the paper. The Heaviside’s discontinuity occurs at input
9.4.1 Computing notation
The usual mathematical notation for piecewise functions, spread out over multiple lines that are connected with a tall brace, is an obvious non-candidate for computer notation. In R, the stitching together of the two pieces can be done with the function ifelse()
. The name is remarkably descriptive. The ifelse()
function takes three arguments. The first is a question to be asked, the second is the value to return if the answer is “yes,” and the third is the value to return for a “no” answer.
To define
3 < 2
In mathematics notation,
In computing notation, 3 < 2
or x < 2
is not a declaration, it is an imperative statement that directs the computer to do the calculation to find out if the statement is true or false, or, as written in R, TRUE
or FALSE
.
Remember that the tilde-expressions given as input to makeFun()
are declarative, not imperative. makeFun()
stores the tilde expression exactly as is, with symbols such as x
being names rather than quantities. makeFun()
packages up the stored tilde expression in the form of an R function. The assignment command Heaviside <- ...
gives the name Heaviside
to the function created by makeFun()
.
Only when you apply the function created by makeFun()
to an input quantity will the tilde-expression be turned into an imperative statement that asks the question 0 <= x
and then chooses the second or third argument to ifelse()
as the result.
Here’s a definition of Heaviside()
written with ifelse()
.
<- makeFun(ifelse(0 <= x, 1, 0) ~ x) Heaviside
Table 9.1 shows computer notation for some common sorts of questions.
R notation | English |
---|---|
x > 2 |
“Is |
y >= 3 |
“Is |
x == 4 |
“Is |
2 < x & x < 5 |
“Is |
x < 2 | x > 6 |
“Is |
abs(x-5) < 2 |
“Is |
9.5 Computing outside the domain
Each of our pattern-book functions, with two exceptions, has a domain that is the entire number line
The two exceptions are:
- the logarithm function, which is defined only for
. - some of the power-law functions:
.- When
is negative, the output of the function is undefined when . You can see why with a simple example: . Most students had it drilled into them that “division by zero is illegal,” and , a double law breaker. - When
is not an integer, that is the domain of the power-law function does not include negative inputs. To see why, consider the function .
- When
It can be tedious to make sure that you are on the right side of the law when dealing with functions whose domain is not the whole number line. The designers of the hardware that does computer arithmetic, after several decades of work, found a clever system to make it easier. It is a standard part of such hardware that whenever a function is handed an input that is not part of that function’s domain, one of two special “numbers” is returned. To illustrate:
sqrt(-3)
## [1] NaN
-2)^0.9999
(## [1] NaN
1/0
## [1] Inf
NaN
stands for “not a number.” Just about any calculation involving NaN
will generate NaN
as a result, even those involving multiplication by zero or cancellation by subtraction or division.1 For instance:
0 * NaN
## [1] NaN
NaN - NaN
## [1] NaN
NaN / NaN
## [1] NaN
Division by zero produces Inf
, whose name is reminiscent of “infinity.” Inf
infiltrates any calculation in which it takes part:
3 * Inf
## [1] Inf
sqrt(Inf)
## [1] Inf
0 * Inf
## [1] NaN
Inf + Inf
## [1] Inf
Inf - Inf
## [1] NaN
1/Inf
## [1] 0
To see the benefits of the NaN
/ Inf
system let’s plot out the logarithm function over the graphics domain NaN
provides some room for politeness.
9.6 Drill
Part 1 Which of the following tilde-expressions could be used to generate the graph in Figure 9.7?
ifelse(abs(x) > 1, x^3, x) ~ x
ifelse(x > 0, sin(x), x) ~ x
ifelse(abs(x) > 1, x, x^3) ~ x
ifelse(abs(x) > 1, x, exp(x^2)) ~ x
ifelse(x > 1, 1, x^2) ~ x
Part 2 Which of the following tilde-expressions could be used to generate the graph in Figure 9.8?
ifelse(abs(x) > 1, x^3, x) ~ x
ifelse(x > 0, sin(x), x) ~ x
ifelse(abs(x) > 1, x, x^3) ~ x
ifelse(abs(x) > 1, x, exp(x^2)) ~ x
ifelse(x > 1, 1, x^2) ~ x
Part 3 Which of the following tilde-expressions could be used to generate the graph in Figure 9.9?
ifelse(abs(x) > 1, x^3, x) ~ x
ifelse(x > 0, sin(x), x) ~ x
ifelse(abs(x) > 1, x, x^3) ~ x
ifelse(abs(x) > 1, x, exp(x^2)) ~ x
ifelse(x > 1, 1, x^2) ~ x
Part 4 Which of the following tilde-expressions could be used to generate the graph in Figure 9.10?
ifelse(abs(x) > 1, x^3, x) ~ x
ifelse(x > 0, sin(x), x) ~ x
ifelse(abs(x) > 1, x, x^3) ~ x
ifelse(abs(x) > 1, x, exp(x^2)) ~ x
ifelse(x > 1, 1, x^2) ~ x
Part 5 Which of the following tilde-expressions could be used to generate the graph in Figure 9.11?
ifelse(abs(x) > 1, x^3, x) ~ x
ifelse(x > 0, sin(x), x) ~ x
ifelse(abs(x) > 1, x, x^3) ~ x
ifelse(abs(x) > 1, x, exp(x^2)) ~ x
ifelse(x > 1, 1, x^2) ~ x
9.7 Exercises
Exercise 9.01
The function bigger()
is defined piecewise in terms of two extremely simple functions. Each of the two simple functions has a contour plot with contours that are parallel. The piecewise combination of the simple functions has a more complicated contour plot, with each simple function’s parallel contours showing up in half of the domain. We will call these “pieces” of the domain.
<-
bigger makeFun(ifelse(y > x, y, x) ~ x + y)
contour_plot(bigger(x,y) ~ x+y,
bounds(x=c(-2,2), y=c(-2,2)))
Part A Which of the following best describes the two pieces of the domain?
- One is above and to the left of the line of identity (that is,
) and the other is below and to the right of that line. - One is
and the other - One is
and the other
Task: Write a mathematical formula for
Exercise 9.02
The Heaviside function has two asymptotes.
Are they horizontal or vertical asymptotes?
What are their values?
Problem with Modeling Exercises/shark-rise-kitchen.Rmd
Problem with Modeling Exercises/beach-ride-table.Rmd
Exercise 9.11
Figure 9.12 comes from the monitoring app for a photovoltaic (solar electricity) array on two consecutive days in June 2022. The vertical axis is in kilowatts (power). The overall pattern for June 4 is a hump function with a peak around 13:00 falling to zero at 6am and 9pm. (13:00 is roughly solar noon, due to daylight savings time.) We’ll call this function sun(t). June 3 shows a more complex pattern, due to passing clouds that diminish the available sunlight.
A reasonable model for the June 3 pattern is the hump function sun(t) multiplied by an irregular function of time representing the clouds. Let’s call it cloudiness(t), imagining that the range is from 0 (dark, obscuring clouds) to 1 (no clouds at all). The power produced is therefore
power(t)
Using Figure 9.12, sketch out the graph of cloudiness(t) for June 3.
One that does produce a number is
NaN^0
.↩︎