37 Integrals step-by-step
The setting for anti-differentiation (and its close cousin, integration) is that we have a function
Chapter 35 showed some ways to visualize the construction of an
In Chapter 36, we dealt with one of the limitations of finding
The non-uniqueness of
- The net change in
from to . - The definite integral of
from to , written .
These two things, the net change and the definite integral, are really one and the same, a fact we describe by writing
In this chapter, we will introduce a simple numerical method for calculating from
37.1 Euler method
The starting point for this method is the definition of the derivative of
To translate this into a numerical method for computing
- First, since the problem setting is that we don’t (yet) know
, let’s refer to things we do know. In particular, we know . - Again, recognizing that we don’t yet know
, let’s re-write the expression using something that we do know: . Stated more precisely, is something we get to make up to suit our convenience. (A common choice is .) - Let’s replace the symbol
with the symbol . Both of them mean “a little bit of” and makes explicit that we mean “a little bit of .” - we will substitute the limit
with an understanding that will be something “small.” How small? we will deal with that question when we have to tools to answer it.
With these changes, we have
Let’s consider finding the anti-derivative of
37.2 Area
The quantity
We will start the visualization with a simple graph of
Per the usual graphical convention, a position along the vertical axis corresponds to a possible output of
The
In this sort of visualization, an integral is the accumulation of many of these
## Warning in is.na(x): is.na() applied to non-(list or vector) of type
## 'expression'
## Warning in is.na(x): is.na() applied to non-(list or vector) of type
## 'expression'
## Warning in is.na(x): is.na() applied to non-(list or vector) of type
## 'expression'
As always in calculus, we imagine
37.3 The Euler Step
The previous section a visualization of an integral in terms of an area on a graph. As you know, a definite integral
A definite integral produces a quantity, not a function. The anti-derivative function constructed by using quantities like
-2 | 10.62 |
-1.5 | 6.47 |
-1 | 3.51 |
-0.5 | 2.02 |
0 | 2.4 |
0.5 | 3.18 |
1.0 | 5.14 |
To start, we will need to create a series of
In previous chapters of this book we have worked with data tables, but always the data table was given to us, we did not have to construct it.1 Now we need to construct the data frame with the Picket()
, which constructs a data table like the one shown above. You provide two arguments: the domain for h
in the argument list). For instance, to construct the Picket()
this way:
<- Picket(bounds(t = -2:1), h=0.5)
Pts
Pts## # A tibble: 6 × 3
## t preweight weight
## <dbl> <dbl> <dbl>
## 1 -2 1 0.5
## 2 -1.5 1 0.5
## 3 -1 1 0.5
## 4 -0.5 1 0.5
## 5 0 1 0.5
## 6 0.5 1 0.5
As you can see, the data table produced by Picket()
has the weight
. We haven’t explained weight
yet, but you can see that it is the same value we specified as h
.
The name Picket()
is motivated by the shape of a picket fence. The pickets are evenly spaced, which keeps things simple but is not a requirement.
Note that the picket does not say anything at all about the function
The next step in using the picket to perform anti-differentiation is to apply the function vals
to the data table.
Adding a new column is a common task when dealing with data. We will do this with a new function, mutate()
, whose specific function is adding new columns (or modifying old ones). Here’s the command to apply t
and call the new column vals
:
# Find the height of the pickets
<- Pts %>%
Pts mutate(vals = f(t))
With this modification, the data table looks like:
## # A tibble: 6 × 4
## t preweight weight vals
## <dbl> <dbl> <dbl> <dbl>
## 1 -2 1 0.5 -9.12
## 2 -1.5 1 0.5 -7.27
## 3 -1 1 0.5 -4.50
## 4 -0.5 1 0.5 -1.46
## 5 0 1 0.5 1.28
## 6 0.5 1 0.5 3.31
Now that we know the value of the function at each of the pickets, the next step is to multiply the value by the spacing between pickets. That spacing, which we set with the argument h = 0.5
in our original call to Picket()
is in the column called weight
. we will call the result of the multiplication step
. Note that the following R command incorporates the previous calculation of vals
; we are looking to build up a single command that will do all the work.
# Multiply the height by the picket spacing
<- Pts %>%
Pts mutate(vals = f(t),
step = vals * weight)
Pts## # A tibble: 6 × 5
## t preweight weight vals step
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 -2 1 0.5 -9.12 -4.56
## 2 -1.5 1 0.5 -7.27 -3.63
## 3 -1 1 0.5 -4.50 -2.25
## 4 -0.5 1 0.5 -1.46 -0.732
## 5 0 1 0.5 1.28 0.639
## 6 0.5 1 0.5 3.31 1.66
We used the name step
to identify the product of the height and spacing of the pickets to help you think about the overall calculation as accumulating a series of steps. Each step provides a little more information about the anti-derivative that we will now calculate. In terms of the area metaphor for integration, each step is the area of one vertical bar of the sort presented in the previous section.
We will call these Euler steps, a term that will be especially appropriate when, in Block 6, we use integration to calculate the trajectories of systems—such as a ball in flight—that change in time.
The final step in constructing the anti-derivative is to add up the steps. This is simple addition. But we will arrange the addition one step at a time. That is, for the second row, the result will be the sum of the first two steps. For the third row, the result will be the sum of the first three steps. And so on. The name for this sort of accumulation of the previous steps is called a cumulative sum. Another name for a cumulative sum is a “running sum”: the sum-so-far as we move down the column of steps. Cumulative sums are computed in R by using cumsum()
. Here, we are calling the result of the cumulative sum F
to emphasize that it is the result of anti-differentiating F
column, but the table with both t
and F
columns. That is, the table has a column for the input as well as the output. That is what it takes to be a function.
# Doing everything in one command
<-
Pts Picket(bounds(t = -2:1), h=0.5) %>%
mutate(vals = f(t),
step = vals * weight,
F = cumsum(step))
## # A tibble: 6 × 6
## t preweight weight vals step F
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 -2 1 0.5 -9.12 -4.56 -4.56
## 2 -1.5 1 0.5 -7.27 -3.63 -8.19
## 3 -1 1 0.5 -4.50 -2.25 -10.4
## 4 -0.5 1 0.5 -1.46 -0.732 -11.2
## 5 0 1 0.5 1.28 0.639 -10.5
## 6 0.5 1 0.5 3.31 1.66 -8.88
We can summarize the steps in this Euler approach to numerical integration graphically:
{#fig-euler-integration1, fig-align=‘center’ width=90%}
Figure 37.5 shows a dynamic version of the process of constructing an anti-derivative by Euler steps. The integrand
PROVIDE LINK TO MOVIE IN PDF version.
37.4 Better numerics (optional)
Except as a textbook exercise, you will likely never have to compute a numerical anti-derivative from scratch as we did in the previous section. This is a good thing. To understand why, you have to know one of the important features of modern technical work. That feature is: We never work alone in technical matters. There is always a set of people whose previous work we are building on, even if we never know the names of those people. This is because technology is complicated and it is evidently beyond the reach of any human to master all the salient aspects of each piece of technology being incorporated into the work we consider our own.
Of course this is true for computers, since no individual can build a useful computer from first principles. It is also true for software. One detail in particular is relevant to us here. Computer arithmetic of the sort used in the previous section—particularly addition—is prone to error when adding up lots and lots of small bits. This means that it is not always sensible to choose very small
Fortunately, there are specialists in numerical mathematics who work on ways to improve the accuracy of calculations for mid-sized antiD()
and Integrate()
and so the details are, for us, unimportant. But they are only unimportant because they have been taken care of.
To illustrate how considerably more accuracy can be gained in calculating an anti-derivative, consider that the rectangular bars drawn in the previous sections are intended to approximate the “area” under the function. With this in mind, we can replace the rectangular bars with more suitable shapes that stay closer to the function over the finite extend of each
One widely used method, called Gauss-Legendre quadrature can calculate a large segment of an integral accurately (under conditions that are common in practice) with just five evaluations of the integrand
The locations and weights may seem like a wizard parody of mathematics, but those precise values are founded in an advanced formulation of polynomials rooted in the theory of linear combinations to which you will be introduced in Block 5. Needless to say, you can hardly be expected to have any idea where they come from. That is why it is useful to build on the work of experts in specialized areas. It is particularly helpful when such expertise is incorporated into software that faithfully and reliably implements the methods. The lesson to take to heart: Use professional software systems that have been extensively vetted.
37.5 Exercises
Exercise 37.01
The output of a function, being a quantity, has dimension and units. Suppose the dimension of the output of a function
The anti-derivative function
Recall that in constructing the anti-derivative using the Euler method, we multiply the values of
Suppose you know the acceleration
Part A What is the dimension of
Suppose you know the power consumed by an appliance
Part B What will be the dimension of
energy force acceleration length
Exercise 37.02
This activity uses the “Graph-antiD” web app which enables you to visualize the anti-derivative function in terms of areas. To use the app, click-drag-and-release to mark part of the domain of the function being displayed.
Add a picture of the app and a link to it.
To answer these questions correctly, you must set the “Shape of function” box to 864.
Part A A. From the graph, roughly estimate
-46 -26 0 3 19 26
Part B B. to construct the anti-derivative whose value at time
-120 -80 -50 0 50 80 120
Part C C. Examining the stock at time
-25 -15 0 15 25
Part D D. You start with a stock of 100 units at time
- -1.2
- -0.3
- 0.5
- 1.2
- 1.8
- The stock will never fall so low.
Part E E. Your stock finally runs out at time
- There was never such a time.
Part F F. After decreasing for a long time, the stock finally starts to increase from about
- The derivative is at a minimum.
- The derivative is negative
- The derivative is near zero.
- The derivative becomes positive and stays positive.
- The derivative is at a maximum.
Part G G. Find the argmin
is also the argmin of . is decreasing at its steepest rate. is increasing at its slowest rate. is increasing at its steepest rate. is the argmax of
Part H H. What is the average flow into stock over the period
-30 -20 0 10
Part I I. Which of the following is an interval when the average flow is approximately zero?
- None of the above
Part J J. From the graph, estimate
- -120
- -60
- 60
- 120
- None of these answers are close to being right.
Exercise 37.03
Consider this function,
Assume that the “area” of each small box on the graph is the product of 1 Watt
Part A What is
-3.2 -1.4 0 2.5 3.3 6.1
Part B Which is bigger, A or B?
- A
- B
- They are the same size
Part C Which is bigger, A or B?
- A
- B
- They are the same size
Consider the function
Part D Which is bigger,
- They are the same size
- Trick question! There can be no such function
since is a function of
Part E Is
positive zero negative
Part F At what value of
2 3 4 5 6 7 8
Part G At what value of
1 2 3 4 5 6
Part H Which is bigger,
Here are four different graphs.
slice_plot(F(x) - F(4) ~ x, bounds(x=0:10)) %>%
gf_labs(title = "(A)")
slice_plot(F(4) - F(x) ~ x, bounds(x=0:10)) %>%
gf_labs(title = "(B)")
slice_plot(F(6) - F(x) ~ x, bounds(x=0:10)) %>%
gf_labs(title = "(C)")
slice_plot(abs(F(4) - F(x)) ~ x, bounds(x=0:10)) %>%
gf_labs(title = "(D)")
Part I Which of the graphs shows
A B C D
Exercise 37.04
Using the Euler method find
0 | 0.399 | 0.5 |
0.01 | 0.242 | |
0.02 | 0.054 | |
0.03 | 0.399 |
Exercise 37.05
Consider this sequence: 4, 5, 3, 1, 2
Part A What is the sum?
14 15 16 17
Part B What is the cumulative sum?
- The sequence 4, 9, 12, 13, 15
- The sequence 2, 3, 6, 11, 15
- The sequence 0, 4, 9, 13, 15
Part C Which entry in the cumulative sum matches the sum?
The first The last None of them All of them
Exercise 37.06
The result of applying the Euler method to a function is also another function, but it comes in the form of a vector of numbers all ready to be displayed graphically. So keep in mind the the function produced by Euler will be known only over a specified domain, just as the graph of a function covers only the specified domain. For instance, here is the graph of the natural logarithm function over the domain
slice_plot(log(x) ~ x, bounds(x=1:21), npts=11) %>%
gf_point()
The command in the sandbox is a little different than the usual slice_plot()
. We’ve added on two things:
An argument
npts=11
which says to use 11 discrete values of the input in plotting the graph.A second graphics layer that shows a dot at each input point where
slice_plot()
evaluated the function. Behind the seemingly smooth curves thatslice_plot()
produces is really a discrete set of points each of which is the output of the function at some numerical input.
In our typical use of slice_plot()
we leave out the dots and show only the straight line segments that connect the positions where the dots would be plotted. If the positions are spaced closely enough, your eye will not see the joints between successive straight lines and you will perceive the graph as a smooth curve.
Part A For the graph of the log function over the domain npts=11
(that is, the initial command shown in the sandbox), what is the horizontal spacing between the discrete
0.5 1 2 4 5
Now take away the npts=
argument. This will implicitly set npts
to a default value, which is what we have been using for most plots in this course.
Part B What is the default value of npts
in slice_plot()
?
25 50 100 200 500 1000
We could use a much larger value for npts
, but there is no reason so long as a smaller value produces a graph faithful to the function being graphed.
Keeping the domain the same, npts
:
Part C How large should npts
be in order for each of the 67 cycles in the graph to come close enough to -1 and 1 that you cannot easily see the discrepancy?
125 150 200 400 800 1600 3200
Exercise 37.07
Methods such as Euler are tedious, ideal for the computer. So let’s look at some basic R functions for implementing the Euler Method when we know the function to be anti-differentiated cumsum()
, the “cumulative sum.” This does something very simple. The cumulative sum of the sequence 1, 2, 3, 4 is another sequence: 1, 3, 6, 10.
The following code has commands for using cumsum()
to approximate the anti-derivative of a function
<- makeFun(sin(2*pi*x/0.3) ~ x) # the function to be anti-differentiated.
f <- 1 # the lower bound.
a <- 2 # the upper bound.
b <- 0.01 # the step size
h <- seq(a, b, by = h) # all of the discrete x values based on a, b, and h
x_discrete <- f(x_discrete) # all of the values of f(x) when the discrete x values are used as the input
f_discrete <- cumsum(h * f_discrete) # the discrete values of the anti-derivative, F(x)
F_discrete gf_point(F_discrete ~ x_discrete) %>%
slice_plot(f(x) ~ x, color = "gray", bounds(x=c(a,b)))
Here is a function:
<- makeFun(exp(-0.2*(x^2))~x) g
Using a SANDBOX, find and plot the anti-derivative of
Your task: Describe the shape of
Exercise 37.08
The graphic, from The Economist news magazine, shows the number of elective treatments (e.g. minor surgery, etc.) by the British National Health Service over the period January 2019 to April 2021. The point of the graph is to show the extent to which people avoided medical treatment due to the Covid-19 pandemic, which started to become severe in March 2020. (The January/February treatment numbers for 2020 line up pretty exactly with the 2019 numbers.)
::include_graphics(normalizePath("www/NHS.png")) knitr
Part A According to the graphic, how many fewer treatements were there in the 12 months of 2020 compared to the 12 months of 2019? (Choose the best of the following answers.)
About 500,000 About 2,000,000 About 6,000,000 About 10,000,000
The root of the word “data” is the Latin for “given”.↩︎