use quarto, not Pluto to render pages

This commit is contained in:
jverzani 2022-07-24 16:38:24 -04:00
parent 93c993206a
commit 7b37ca828c
879 changed files with 793311 additions and 2678 deletions

View File

@ -1,15 +0,0 @@
name: TagBot
on:
issue_comment:
types:
- created
workflow_dispatch:
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}

View File

@ -9,6 +9,7 @@ on:
jobs:
build:
if: ${{ false }} # disable documenter for now
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

25
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,25 @@
on:
push:
branches: main
name: Quarto Publish
jobs:
build-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Set up Quarto
uses: quarto-dev/quarto-actions/setup@v2
- name: Render and Publish
uses: quarto-dev/quarto-actions/publish@v2
with:
target: gh-pages
path: quarto/
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -16,7 +16,7 @@ const frontmatter = (
description = "Calculus with Julia: The `DifferentialEquations` suite",
tags = ["CalculusWithJulia", "odes", "the `differentialequations` suite"],
);
fig_size = (600, 400)
fig_size = (800, 600)
nothing
```
@ -152,12 +152,8 @@ end
The notation `du` is suggestive of both the derivative and a small increment. The mathematical formulation follows the derivative, the numeric solution uses a time step and increments the solution over this time step. The `Tsit5()` solver, used here, adaptively chooses a time step, `dt`; were the `Euler` method used, this time step would need to be explicit.
```julia; echo=false
note("""
The `sir!` function has the trailing `!` indicating -- by convention -- it *mutates* its first value, `du`. In this case, through an assignment, as in `du[1]=ds`. This could use some explanation. The *binding* `du` refers to the *container* holding the ``3`` values, whereas `du[1]` refers to the first value in that container. So `du[1]=ds` changes the first value, but not the *binding* of `du` to the container. That is, `du` mutates. This would be quite different were the call `du = [ds,di,dr]` which would create a new *binding* to a new container and not mutate the values in the original container.
""", title="Mutation not re-binding")
```
!!! note "Mutation not re-binding"
The `sir!` function has the trailing `!` indicating -- by convention -- it *mutates* its first value, `du`. In this case, through an assignment, as in `du[1]=ds`. This could use some explanation. The *binding* `du` refers to the *container* holding the ``3`` values, whereas `du[1]` refers to the first value in that container. So `du[1]=ds` changes the first value, but not the *binding* of `du` to the container. That is, `du` mutates. This would be quite different were the call `du = [ds,di,dr]` which would create a new *binding* to a new container and not mutate the values in the original container.
With the update function defined, the problem is setup and a solution found with in the same manner:
@ -289,12 +285,8 @@ end
This function ``W`` is just a constant above, but can be easily modified as desired.
```julia; echo=false
note("""
The "standard" trick is to take a second order ODE like ``u''(t)=u`` and turn this into two coupled ODEs by using a new name: ``v=u'(t)`` and then ``v'(t) = u(t)``. In this application, there are ``4`` equations, as we have *both* ``x''`` and ``y''`` being so converted. The first and second components of ``du`` are new variables, the third and fourth show the original equation.
""", title="A second-order ODE is a coupled first-order ODE")
```
!!! note "A second-order ODE is a coupled first-order ODE"
The "standard" trick is to take a second order ODE like ``u''(t)=u`` and turn this into two coupled ODEs by using a new name: ``v=u'(t)`` and then ``v'(t) = u(t)``. In this application, there are ``4`` equations, as we have *both* ``x''`` and ``y''`` being so converted. The first and second components of ``du`` are new variables, the third and fourth show the original equation.
The initial conditions are specified through:

View File

@ -18,7 +18,7 @@ const frontmatter = (
description = "Calculus with Julia: Euler's method",
tags = ["CalculusWithJulia", "odes", "euler's method"],
);
fig_size = (600, 400)
fig_size = (800, 600)
nothing
```
@ -829,6 +829,6 @@ choices = [
"The solution is identical to that of the approximation found by linearization of the sine term",
"The solution has a constant amplitude, but its period is slightly *shorter* than that of the approximate solution found by linearization",
"The solution has a constant amplitude, but its period is slightly *longer* than that of the approximate solution found by linearization"]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```

View File

@ -93,8 +93,11 @@ x'(t) = v(t) = v_0 + a (t - t_0), \quad x(t_0) = x_0.
Again, we can integrate to get an answer for any value $t$:
```math
x(t) - x(t_0) = \int_{t_0}^t \frac{dv}{dt} dt = (v_0t + \frac{1}{2}a t^2 - at_0 t) |_{t_0}^t =
(v_0 - at_0)(t - t_0) + \frac{1}{2} a (t^2 - t_0^2).
\begin{align*}
x(t) - x(t_0) &= \int_{t_0}^t \frac{dv}{dt} dt \\
&= (v_0t + \frac{1}{2}a t^2 - at_0 t) |_{t_0}^t \\
&= (v_0 - at_0)(t - t_0) + \frac{1}{2} a (t^2 - t_0^2).
\end{align*}
```
There are three constants: the initial value for the independent variable, $t_0$, and the two initial values for the velocity and position, $v_0, x_0$. Assuming $t_0 = 0$, we can simplify the above to get a formula familiar from introductory physics:
@ -174,13 +177,15 @@ A graph of the solution for $T_0=200$ and $T_a=72$ and $r=1/2$ is made
as follows. We've added a few line segments from the defining formula,
and see that they are indeed tangent to the solution found for the differential equation.
```julia; hold=true; echo=false
T0, Ta, r = 200, 72, 1/2
f(u, t) = -r*(u - Ta)
v(t) = Ta + (T0 - Ta) * exp(-r*t)
p = plot(v, 0, 6, linewidth=4, legend=false)
[plot!(p, x -> v(a) + f(v(a), a) * (x-a), 0, 6) for a in 1:2:5]
p
```julia; echo=false
let
T0, Ta, r = 200, 72, 1/2
f(u, t) = -r*(u - Ta)
v(t) = Ta + (T0 - Ta) * exp(-r*t)
p = plot(v, 0, 6, linewidth=4, legend=false)
[plot!(p, x -> v(a) + f(v(a), a) * (x-a), 0, 6) for a in 1:2:5]
p
end
```
@ -725,10 +730,8 @@ plot!(f, linewidth=5)
In general, if the first-order equation is written as $y'(x) = F(y,x)$, then we plot a "function" that takes $(x,y)$ and returns an $x$ value of $1$ and a $y$ value of $F(y,x)$, so the slope is $F(y,x)$.
```julia; echo=false
note(L"""The order of variables in $F(y,x)$ is conventional with the equation $y'(x) = F(y(x),x)$.
""")
```
!!! note
The order of variables in $F(y,x)$ is conventional with the equation $y'(x) = F(y(x),x)$.
The plots are also useful for illustrating solutions for different initial conditions:
@ -780,8 +783,8 @@ choices = [
"``[-1, 4]``",
"``[-1, 0]``",
"``[1-\\sqrt{5}, 1 + \\sqrt{5}]``"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
@ -891,8 +894,8 @@ eqn = diff(x^2*D(u)(x), x)
out = dsolve(eqn, u(x), ics=Dict(u(1)=>2, u(10) => 1)) |> rhs
out(5) # 10/9
choices = ["``10/9``", "``3/2``", "``9/10``", "``8/9``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -909,6 +912,6 @@ choices = [
"The limit does not exist, but the limit to `oo` gives a quadratic polynomial in `x`, mirroring the first part of that example.",
"The limit does not exist -- there is a singularity -- as seen by setting `gamma=0`."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -15,7 +15,7 @@ const frontmatter = (
description = "Calculus with Julia: The problem-algorithm-solve interface",
tags = ["CalculusWithJulia", "odes", "the problem-algorithm-solve interface"],
);
fig_size = (600, 400)
fig_size = (800, 600)
nothing
```

View File

@ -0,0 +1,107 @@
# Using interval arithemetic
Highlighted here is the use of interval arithmetic for calculus problems.
Unlike floating point math, where floating point values are an *approximation* to real numbers, interval arithmetic uses *interval* which are **guaranteed** to contain the given value. We use the `IntervalArithmetic` package and friends to work below, but note there is nothing magic about the concept.
## Basic XXX
## Using `IntervalRootFinding` to identify zeros of a function
The `IntervalRootFinding` package provides a more *rigorous* alternative to `find_zeros`. This packages leverages the interval arithmetic features of `IntervalArithmetic`.
The `IntervalRootFinding` package provides a function `roots`, with usage similar to `find_zeros`. Intervals are specified with the notation `a..b`. In the following, we *qualify* `roots` to not conflict with the `roots` function from `SymPy`, which has already been loaded:
```julia
import IntervalArithmetic
import IntervalRootFinding
```
```julia
u(x) = sin(x) - 0.1*x^2 + 1
𝑱 = IntervalArithmetic.Interval(-10, 10) # cumbersome -10..10; needed here: .. means something in CalculusWithJulia
rts = IntervalRootFinding.roots(u, 𝑱)
```
The "zeros" are returned with an enclosing interval and a flag, which for the above indicates a unique zero in the interval.
The intervals with a unique answer can be filtered and refined with a construct like the following:
```julia
[find_zero(u, (IntervalArithmetic.interval(I).lo, IntervalArithmetic.interval(I).hi)) for I in rts if I.status == :unique]
```
The midpoint of the returned interval can be found by composing the `mid` function with the `interval` function of the package:
```julia
[(IntervalArithmetic.mid ∘ IntervalArithmetic.interval)(I) for I in rts if I.status == :unique]
```
For some problems, `find_zeros` is more direct, as with this one:
```julia
find_zeros(u, (-10, 10))
```
Which can be useful if there is some prior understanding of the zeros expected to be found.
However, `IntervalRootFinding` is more efficient computationally and *offers a guarantee* on the values found.
For functions where roots are not "unique" a different output may appear:
```julia; hold=true;
f(x) = x*(x-1)^2
rts = IntervalRootFinding.roots(f, 𝑱)
```
The interval labeled `:unknown` contains a `0`, but it can't be proved by `roots`.
Interval arithmetic finds **rigorous** **bounds** on the range of `f` values over a closed interval `a..b` (the range is `f(a..b)`). "Rigorous" means the bounds are truthful and account for possible floating point issues. "Bounds" means the answer lies within, but the bound need not be the answer.
This allows one -- for some functions -- to answer affirmatively questions like:
* Is the function *always* positive on `a..b`? Negative? This can be done by checking if `0` is in the bound given by `f(a..b)`. If it isn't then one of the two characterizations is true.
* Is the function *strictly increasing* on `a..b`? Strictly decreasing? These questions can be answered using the (upcoming) [derivative](../derivatives/derivatives.html). If the derivative is positive on `a..b` then `f` is strictly increasing, if negative on `a..b` then `f` is strictly decreasing. Finding the derivative can be done within the `IntervalArithmetic` framework using [automatic differentiation](../derivatives/numeric_derivatives.html), a blackbox operation denoted `f'` below.
Combined, for some functions and some intervals these two questions can be answered affirmatively:
* the interval does not contain a zero (`0 !in f(a..b)`)
* over the interval, the function crosses the `x` axis *once* (`f(a..a)` and `f(b..b)` are one positive and one negative *and* `f` is strictly monotone, or `0 !in f'(a..b)`)
This allows the following (simplified) bisection-like algorithm to be used:
* consider an interval `a..b`
* if the function is *always* positive or negative, it can be discarded as no zero can be in the interval
* if the function crosses the `x` axis *once* over this interval **then** there is a "unique" zero in the interval and the interval can be marked so and set aside
* if neither of the above *and* `a..b` is not too small already, then *sub-divide* the interval and repeat the above with *both* smaller intervals
* if `a..b` is too small, stop and mark it as "unknown"
When terminated there will be intervals with unique zeros flagged and smaller intervals with an unknown status.
Compared to the *bisection* algorithm -- which only knows for some intervals if that interval has one or more crossings -- this algorithm gives a more rigorous means to get all the zeros in `a..b`.
For a last example of the value of this package, this function, which appeared in our discussion on limits, is *positive* for **every** floating point number, but has two zeros snuck in at values within the floating point neighbors of $15/11$
```julia
t(x) = x^2 + 1 +log(abs( 11*x-15 ))/99
```
The `find_zeros` function will fail on identifying any potential zeros of this function. Even the basic call of `roots` will fail, due to it relying on some smoothness of `f`. However, explicitly asking for `Bisection` shows the *potential* for one or more zeros near $15/11$:
```julia
IntervalRootFinding.roots(t, 𝑱, IntervalRootFinding.Bisection)
```
(The basic algorithm above can be sped up using a variant of [Newton's](../derivatives/newton_method.html) method, this variant assumes some "smoothness" in the function `f`, whereas this `f` is not continuous at the point ``x=15/11``.)

View File

@ -1,6 +1,8 @@
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
ImplicitPlots = "55ecb840-b828-11e9-1645-43f4a9f9ace7"
IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"
IntervalConstraintProgramming = "138f1668-1576-5ad7-91b9-7425abbf3153"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"

View File

@ -15,7 +15,7 @@ using Polynomials # some name clash with SymPy
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
fig_size=(600, 400)
fig_size=(800, 600)
const frontmatter = (
title = "Curve Sketching",
description = "Calculus with Julia: Curve Sketching",
@ -331,8 +331,8 @@ L"Just vertical asymptotes at $x=-1$ and $x=1$",
L"Vertical asymptotes at $x=-1$ and $x=1$ and a horizontal asymptote $y=1$",
L"Vertical asymptotes at $x=-1$ and $x=1$ and a slant asymptote"
]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
###### Question
@ -474,8 +474,8 @@ choices = [
"The exponential growth model",
"The limit does not exist",
"The limit is ``P_0``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
##### Question
@ -493,8 +493,8 @@ choices = [
"The function will have more curvature when the second derivative is large, so there needs to be more points to capture the shape",
"The function will be much larger (in absolute value) when the second derivative is large, so there needs to be more points to capture the shape",
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
##### Question
@ -514,8 +514,8 @@ choices = [
"An informative graph only needs to show one or two periods, as others can be inferred.",
"An informative graph need only show a part of the period, as the rest can be inferred.",
L"An informative graph needs to show several periods, as that will allow proper computation for the $y$ axis range."]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Why should asymptotics matter?
@ -526,8 +526,8 @@ L"A vertical asymptote can distory the $y$ range, so it is important to avoid to
L"A horizontal asymptote must be plotted from $-\infty$ to $\infty$",
"A slant asymptote must be plotted over a very wide domain so that it can be identified."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Monotonicity means increasing or decreasing. This is important for what reason?
@ -538,6 +538,6 @@ choices = [
"For monotonic regions, a function is basically a straight line",
"For monotonic regions, the function will have a vertical asymptote, so the region should not be plotted"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -19,7 +19,7 @@ const frontmatter = (
tags = ["CalculusWithJulia", "derivatives", "derivatives"],
);
fig_size=(600, 400)
fig_size=(800, 600)
nothing
```
@ -1199,16 +1199,16 @@ At which of these points $c= 1/2, 1, 3/2$ is the derivative negative?
```julia; hold=true; echo=false
choices = ["``1/2``", "``1``", "``3/2``"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
Which value looks bigger from reading the graph:
```julia; hold=true; echo=false
choices = ["``f(1)``", "``f(3/2)``"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
At $0.708 \dots$ and $1.65\dots$ the derivative has a common value. What is it?
@ -1229,8 +1229,8 @@ At $x = -2.5$ the derivative is postive or negative?
```julia; hold=true; echo=false
choices = ["positive", "negative"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -1238,16 +1238,16 @@ At $x=0$ the derivative is postive or negative?
```julia; hold=true; echo=false
choices = ["positive", "negative"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
At $x = 2.5$ the derivative is postive or negative?
```julia; hold=true; echo=false
choices = ["positive", "negative"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1256,8 +1256,8 @@ Compute the derivative of $e^x$ using `limit`. What do you get?
```julia; hold=true; echo=false
choices = ["``e^x``", "``x^e``", "``(e-1)x^e``", "``e x^{(e-1)}``", "something else"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1266,8 +1266,8 @@ Compute the derivative of $x^e$ using `limit`. What do you get?
```julia; hold=true; echo=false
choices = ["``e^x``", "``x^e``", "``(e-1)x^e``", "``e x^{(e-1)}``", "something else"]
ans = 5
radioq(choices, ans, keep_order=true)
answ = 5
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1276,8 +1276,8 @@ Compute the derivative of $e^{e\cdot x}$ using `limit`. What do you get?
```julia; hold=true; echo=false
choices = ["``e^x``", "``x^e``", "``(e-1)x^e``", "``e x^{(e-1)}``", "``e \\cdot e^{e\\cdot x}``", "something else"]
ans = 5
radioq(choices, ans, keep_order=true)
answ = 5
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1295,8 +1295,8 @@ choices = [
L" $1$, as this is clearly the analog of the limit of $\sin(h)/h$.",
L"Does not exist. The answer is $0/0$ which is undefined",
L" $0$, as this expression is the derivative of cosine at $0$. The answer follows, as cosine clearly has a tangent line with slope $0$ at $x=0$."]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -1310,8 +1310,8 @@ choices = [
"``f'(x) = f(x)``",
"``f'(x) = -f(x)``"
]
ans= 1
radioq(choices, ans)
answ= 1
radioq(choices, answ)
```
@ -1326,8 +1326,8 @@ choices = [
"``f''(x) = -g(x)``",
"``f''(x) = f(x)``",
"``f''(x) = -f(x)``"]
ans= 3
radioq(choices, ans)
answ= 3
radioq(choices, answ)
```
@ -1381,8 +1381,8 @@ L"If the graphs of $f$ and $g$ are translations up and down, the tangent line at
L"If the graphs of $f$ and $g$ are rescalings of each other through $g(x)=f(x/c)$, $c > 1$. Then the tangent line for corresponding points is the same.",
L"If the graphs of $f$ and $g$ are rescalings of each other through $g(x)=cf(x)$, $c > 1$. Then the tangent line for corresponding points is the same."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1409,8 +1409,8 @@ choices = [
"``f'(x) = -k^2 \\cdot f(x)``",
"``f''(x) = k^2 \\cdot f(x)``",
"``f''(x) = -k^2 \\cdot f(x)``"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
###### Question
@ -1424,8 +1424,8 @@ choices = [
"``f'(x) = -k^2 \\cdot f(x)``",
"``f''(x) = k^2 \\cdot f(x)``",
"``f''(x) = -k^2 \\cdot f(x)``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
##### Question

View File

@ -416,17 +416,19 @@ g' + 0 - 0 - 0 + g'-sign
Consider the function $f(x) = x^2$. Over this function we draw some
secant lines for a few pairs of $x$ values:
```julia; hold=true; echo=false
f(x) = x^2
seca(f,a,b) = x -> f(a) + (f(b) - f(a)) / (b-a) * (x-a)
p = plot(f, -2, 3, legend=false, linewidth=5, xlim=(-2,3), ylim=(-2, 9))
plot!(p,seca(f, -1, 2))
a,b = -1, 2; xs = range(a, stop=b, length=50)
plot!(xs, seca(f, a, b).(xs), linewidth=5)
plot!(p,seca(f, 0, 3/2))
a,b = 0, 3/2; xs = range(a, stop=b, length=50)
plot!(xs, seca(f, a, b).(xs), linewidth=5)
p
```julia; echo=false
let
f(x) = x^2
seca(f,a,b) = x -> f(a) + (f(b) - f(a)) / (b-a) * (x-a)
p = plot(f, -2, 3, legend=false, linewidth=5, xlim=(-2,3), ylim=(-2, 9))
plot!(p,seca(f, -1, 2))
a,b = -1, 2; xs = range(a, stop=b, length=50)
plot!(xs, seca(f, a, b).(xs), linewidth=5)
plot!(p,seca(f, 0, 3/2))
a,b = 0, 3/2; xs = range(a, stop=b, length=50)
plot!(xs, seca(f, a, b).(xs), linewidth=5)
p
end
```
The graph attempts to illustrate that for this function the secant
@ -573,11 +575,11 @@ One way to visualize the second derivative test is to *locally* overlay on a cri
```julia; hold=true;
f(x) = sin(x) + sin(2x) + sin(3x)
p = plot(f, 0, 2pi, legend=false, color=:blue, linewidth=3)
cps = fzeros(f', 0, 2pi)
h = 0.5
cps = find_zeros(f', (0, 2pi))
Δ = 0.5
for c in cps
parabola(x) = f(c) + (f''(c)/2) * (x-c)^2
plot!(parabola, c-h, c+h, color=:red, linewidth=5, alpha=0.6)
plot!(parabola, c - Δ, c + Δ, color=:red, linewidth=5, alpha=0.6)
end
p
```
@ -637,16 +639,18 @@ find_zeros(k'', -3, 3)
A car travels from a stop for 1 mile in 2 minutes. A graph of its
position as a function of time might look like any of these graphs:
```julia; hold=true; echo=false
v(t) = 30/60*t
w(t) = t < 1/2 ? 0.0 : (t > 3/2 ? 1.0 : (t-1/2))
y(t) = 1 / (1 + exp(-t))
y1(t) = y(2(t-1))
y2(t) = y1(t) - y1(0)
y3(t) = 1/y2(2) * y2(t)
plot(v, 0, 2, label="f1")
plot!(w, label="f2")
plot!(y3, label="f3")
```julia; echo=false
let
v(t) = 30/60*t
w(t) = t < 1/2 ? 0.0 : (t > 3/2 ? 1.0 : (t-1/2))
y(t) = 1 / (1 + exp(-t))
y1(t) = y(2(t-1))
y2(t) = y1(t) - y1(0)
y3(t) = 1/y2(2) * y2(t)
plot(v, 0, 2, label="f1")
plot!(w, label="f2")
plot!(y3, label="f3")
end
```
All three graphs have the same *average* velocity which is just the
@ -696,8 +700,8 @@ choices=[
"``(-5, -4.2)``",
"``(-5, -4.2)`` and ``(-2.5, 0)``",
"``(-4.2, -2.5)``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -718,8 +722,8 @@ choices=[
"``(-25.0, 0.0)``",
"``(-5.0, -4.0)`` and ``(-4, -3)``",
"``(-4.0, -3.0)``"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
###### Question
@ -740,8 +744,8 @@ choices=[
"``(-4.7, -3.0)``",
"``(-0.17, 0.17)``"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -763,8 +767,8 @@ choices=[
"``(-0.6, 0.6)``",
" ``(-3.0, -0.6)`` and ``(0.6, 3.0)``"
]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
@ -786,8 +790,8 @@ choices = [
"That the critical point at ``0`` is a relative maximum",
"That the critical point at ``0`` is a relative minimum"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -801,8 +805,8 @@ choices = [
" ``f(x)`` is continuous and differentiable at ``2`` and has a critical point",
" ``f(x)`` is continuous and differentiable at ``2`` and has a critical point that is a relative minimum by the second derivative test"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -810,22 +814,26 @@ radioq(choices, ans, keep_order=true)
Find the smallest critical point of $f(x) = x^3 e^{-x}$.
```julia; hold=true; echo=false
f(x)= x^3*exp(-x)
cps = find_zeros(D(f), -5, 10)
val = minimum(cps)
numericq(val)
```julia; echo=false
let
f(x)= x^3*exp(-x)
cps = find_zeros(D(f), -5, 10)
val = minimum(cps)
numericq(val)
end
```
###### Question
How many critical points does $f(x) = x^5 - x + 1$ have?
```julia; hold=true; echo=false
f(x) = x^5 - x + 1
cps = find_zeros(D(f), -3, 3)
val = length(cps)
numericq(val)
```julia; echo=false
let
f(x) = x^5 - x + 1
cps = find_zeros(D(f), -3, 3)
val = length(cps)
numericq(val)
end
```
###### Question
@ -833,11 +841,13 @@ numericq(val)
How many inflection points does $f(x) = x^5 - x + 1$ have?
```julia; hold=true; echo=false
f(x) = x^5 - x + 1
cps = find_zeros(D(f,2), -3, 3)
val = length(cps)
numericq(val)
```julia; echo=false
let
f(x) = x^5 - x + 1
cps = find_zeros(D(f,2), -3, 3)
val = length(cps)
numericq(val)
end
```
###### Question
@ -850,8 +860,8 @@ choices = [
"No, the second derivative test is possibly inconclusive",
"Yes"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -865,15 +875,17 @@ choices = [
"No, the second derivative test is possibly inconclusive if ``c=0``, but otherwise yes",
"Yes"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
```julia; hold=true; echo=false
f(x) = exp(-x) * sin(pi*x)
plot(D(f), 0, 3)
```julia; echo=false
let
f(x) = exp(-x) * sin(pi*x)
plot(D(f), 0, 3)
end
```
The graph shows $f'(x)$. Is it possible that $f(x) = e^{-x} \sin(\pi x)$?
@ -931,8 +943,8 @@ choices = [
"The critical points are at ``x=1`` (a relative minimum), ``x=2`` (not a relative extrema), and ``x=3`` (a relative minimum).",
"The critical points are at ``x=1`` (a relative minimum), ``x=2`` (a relative minimum), and ``x=3`` (a relative minimum).",
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
##### Question
@ -945,8 +957,8 @@ choices = [
"The function is decreasing over ``(-\\infty, 1)`` and increasing over ``(1, \\infty)``",
"The function is negative over ``(-\\infty, 1)`` and positive over ``(1, \\infty)``",
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
##### Question
@ -957,8 +969,8 @@ While driving we accelerate to get through a light before it turns red. However,
choices = ["A zero of the function",
"A critical point for the function",
"An inflection point for the function"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question

View File

@ -237,17 +237,12 @@ Not quite what we expect, perhaps, but substituting in ``f(x)/g(x)`` for ``y`` g
\frac{dy}{dx} = \frac{f'(x) - \frac{f(x)}{g(x)} g'(x)}{g(x)} = \frac{f'(x) g(x) - f(x) g'(x)}{g(x)^2}.
```
```julia; echo=false
note("""
In this example we mix notations using ``g'(x)`` to
represent a derivative of ``g`` with respect to ``x`` and ``dy/dx`` to
represent the derivative of ``y`` with respect to ``x``. This is done to
emphasize the value that we are solving for. It is just a convention
though, we could just as well have used the "prime" notation for each.
""")
```
!!! note
In this example we mix notations using ``g'(x)`` to
represent a derivative of ``g`` with respect to ``x`` and ``dy/dx`` to
represent the derivative of ``y`` with respect to ``x``. This is done to
emphasize the value that we are solving for. It is just a convention
though, we could just as well have used the "prime" notation for each.
##### Example: Graphing a tangent line
@ -399,17 +394,11 @@ Basically this includes all the same steps as if done "by hand." Some effort cou
values for the parameters been substituted initially, but not doing so
shows their dependence in the derivative.
```julia; echo=false
alert("The use of `lambdify(H)` is needed to turn the symbolic expression, `H`, into a function.")
```
!!! warning
The use of `lambdify(H)` is needed to turn the symbolic expression, `H`, into a function.
```julia; echo=false
note("""
While `SymPy` itself has the `plot_implicit` function for plotting implicit equations, this works only with `PyPlot`, not `Plots`, so we use the `ImplicitPlots` package in these examples.
""")
```
!!! note
While `SymPy` itself has the `plot_implicit` function for plotting implicit equations, this works only with `PyPlot`, not `Plots`, so we use the `ImplicitPlots` package in these examples.
## Higher order derivatives
@ -818,8 +807,8 @@ choices = [
"``b \\cdot (1 - (x/a)^n)^{1/n}``",
"``-(x/a)^n / (y/b)^n``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -863,8 +852,8 @@ choices = [
"``2xy / (x^2 + a^2)``",
"``a^3/(x^2 + a^2)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -885,8 +874,8 @@ Using Implicit differentiation, find when ``dy/dx = 0``.
```julia; hold=true; echo=false
choices = ["``y^2 = 3x/a``", "``y=3x^2/a``", "``y=a/(3x^2)``", "``y^2=a/(3x)``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
Substituting the correct value of ``y``, above, into the defining equation gives what value for ``x``:
@ -898,8 +887,8 @@ choices=[
"``x=(1/2) a^3 3^{1/3}``",
"``x=(1/3) a^2 2^{1/2}``"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -924,8 +913,8 @@ If ``y>0`` is the sign positive or negative?
```julia; hold=true; echo=false
choices = ["positive", "negative", "Can be both"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
If ``x>0`` is the sign positive or negative?
@ -933,16 +922,16 @@ If ``x>0`` is the sign positive or negative?
```julia; hold=true; echo=false
choices = ["positive", "negative", "Can be both"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
When ``x>0``, the graph of the equation is...
```julia; hold=true; echo=false
choices = ["concave up", "concave down", "both concave up and down"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```

View File

@ -15,7 +15,7 @@ using SymPy
using CalculusWithJulia.WeaveSupport
using Roots
fig_size=(600, 400)
fig_size=(800, 600)
const frontmatter = (
title = "L'Hospital's Rule",
description = "Calculus with Julia: L'Hospital's Rule",
@ -79,10 +79,10 @@ likely due to one of the Bernoulli brothers.
> ``\lim_{x \rightarrow c+}f(x)/g(x) = L``.
That is *if* the right limit of ``f(x)/g(x)`` is indeterminate of the form ``0/0``,
but the right limit of ``f'(x)/g'(x)`` is known, possibly by simple
continuity, then the right limit of ``f(x)/g(x)`` exists and is equal to that
of ``f'(x)/g'(x)``.
That is *if* the right limit of ``f(x)/g(x)`` is indeterminate of the
form ``0/0``, but the right limit of ``f'(x)/g'(x)`` is known,
possibly by simple continuity, then the right limit of ``f(x)/g(x)``
exists and is equal to that of ``f'(x)/g'(x)``.
The rule equally applies to *left limits* and *limits* at ``c``. Later it will see there are other generalizations.
@ -102,12 +102,8 @@ this answer is as it is, but we don't need to think in terms of
\approx x``, as ``\cos(0)`` appears as the coefficient.
```julia; echo=false
note("""
In [Gruntz](http://www.cybertester.com/data/gruntz.pdf), in a reference attributed to Speiss, we learn that L'Hospital was a French Marquis who was taught in ``1692`` the calculus of Leibniz by Johann Bernoulli. They made a contract obliging Bernoulli to leave his mathematical inventions to L'Hospital in exchange for a regular compensation. This result was discovered in ``1694`` and appeared in L'Hospital's book of ``1696``.
"""; title="Bernoulli-de l'Hospital")
```
!!! note
In [Gruntz](http://www.cybertester.com/data/gruntz.pdf), in a reference attributed to Speiss, we learn that L'Hospital was a French Marquis who was taught in ``1692`` the calculus of Leibniz by Johann Bernoulli. They made a contract obliging Bernoulli to leave his mathematical inventions to L'Hospital in exchange for a regular compensation. This result was discovered in ``1694`` and appeared in L'Hospital's book of ``1696``.
##### Examples
@ -121,10 +117,8 @@ In [Gruntz](http://www.cybertester.com/data/gruntz.pdf), in a reference attribut
= \lim_{x \rightarrow 0}\frac{a^x - 1}{x}.
```
```julia; echo=false
note("""Why rewrite in the "opposite" direction? Because the theorem's result -- ``L`` is the limit -- is only true if the related limit involving the derivative exists. We don't do this in the following, but did so here to emphasize the need for the limit of the ratio of the derivatives to exist.
""")
```
!!! note
Why rewrite in the "opposite" direction? Because the theorem's result -- ``L`` is the limit -- is only true if the related limit involving the derivative exists. We don't do this in the following, but did so here to emphasize the need for the limit of the ratio of the derivatives to exist.
- Consider this limit:
@ -270,7 +264,8 @@ known.
----
```julia; hold=true; echo=false; cache=true
```julia; echo=false; cache=true
let
## {{{lhopitals_picture}}}
function lhopitals_picture_graph(n)
@ -286,8 +281,8 @@ function lhopitals_picture_graph(n)
## get bounds
tl = (x) -> g(0) + m * (x - f(0))
lx = max(fzero(x -> tl(x) - (-0.05),-1000, 1000), -0.6)
rx = min(fzero(x -> tl(x) - (0.25),-1000, 1000), 0.2)
lx = max(find_zero(x -> tl(x) - (-0.05), (-1000, 1000)), -0.6)
rx = min(find_zero(x -> tl(x) - (0.25), (-1000, 1000)), 0.2)
xs = [lx, rx]
ys = map(tl, xs)
@ -319,7 +314,8 @@ gif(anim, imgfile, fps = 1)
plotly()
ImageFile(imgfile, caption)
ImageFile(imgfile, caption)
end
```
## Generalizations
@ -556,8 +552,8 @@ nothing
```
```julia; hold=true; echo=false
ans = 1
radioq(lh_choices, ans, keep_order=true)
answ = 1
radioq(lh_choices, answ, keep_order=true)
```
###### Question
@ -565,8 +561,8 @@ radioq(lh_choices, ans, keep_order=true)
This function ``f(x) = \sin(x)^{\sin(x)}`` is *indeterminate* at ``x=0``. What type?
```julia; hold=true; echo=false
ans =3
radioq(lh_choices, ans, keep_order=true)
answ =3
radioq(lh_choices, answ, keep_order=true)
```
###### Question
@ -574,8 +570,8 @@ radioq(lh_choices, ans, keep_order=true)
This function ``f(x) = (x-2)/(x^2 - 4)`` is *indeterminate* at ``x=2``. What type?
```julia; hold=true; echo=false
ans = 1
radioq(lh_choices, ans, keep_order=true)
answ = 1
radioq(lh_choices, answ, keep_order=true)
```
###### Question
@ -583,8 +579,8 @@ radioq(lh_choices, ans, keep_order=true)
This function ``f(x) = (g(x+h) - g(x-h)) / (2h)`` (``g`` is continuous) is *indeterminate* at ``h=0``. What type?
```julia; hold=true; echo=false
ans = 1
radioq(lh_choices, ans, keep_order=true)
answ = 1
radioq(lh_choices, answ, keep_order=true)
```
###### Question
@ -592,8 +588,8 @@ radioq(lh_choices, ans, keep_order=true)
This function ``f(x) = x \log(x)`` is *indeterminate* at ``x=0``. What type?
```julia; hold=true; echo=false
ans = 5
radioq(lh_choices, ans, keep_order=true)
answ = 5
radioq(lh_choices, answ, keep_order=true)
```
@ -610,8 +606,8 @@ choices = [
"Yes. It is of the form ``0/0``",
"No. It is not indeterminate"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -769,6 +765,6 @@ choices = [
"``0``",
"It does not exist"
]
ans =1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -641,8 +641,8 @@ choices = [
"``1 + x^{1/2}``",
"``1 + (1/2) \\cdot x``",
"``1 - (1/2) \\cdot x``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -657,8 +657,8 @@ choices = [
"``1 + x^k``",
"``1 + k \\cdot x``",
"``1 - k \\cdot x``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -672,8 +672,8 @@ choices = [
"``x``",
"``1 - x^2/2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -688,8 +688,8 @@ choices = [
"``1 + x``",
"``1 - x``"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -705,8 +705,8 @@ choices = [
"``1 + x``",
"``25``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -719,8 +719,8 @@ value of the tangent line at $(25, f(25))$ at $x=26$.
```julia; hold=true; echo=false
tgent(x) = 5 + x/10
ans = tgent(1) - sqrt(26)
numericq(ans)
answ = tgent(1) - sqrt(26)
numericq(answ)
```
###### Question
@ -730,8 +730,8 @@ An estimate of some quantity was $12.34$ the actual value was $12$. What was the
```julia; hold=true; echo=false
est = 12.34
act = 12.0
ans = (est -act)/act * 100
numericq(ans)
answ = (est -act)/act * 100
numericq(answ)
```
@ -744,8 +744,8 @@ tl(x) = x
x0 = 5 * pi/180
est = x0
act = sin(x0)
ans = (est -act)/act * 100
numericq(ans)
answ = (est -act)/act * 100
numericq(answ)
```
###### Question
@ -754,8 +754,8 @@ The side length of a square is measured roughly to be $2.0$ cm. The actual lengt
```julia; hold=true; echo=false
tl(x) = 4 + 4x
ans = tl(.2) - 4
numericq(abs(ans))
answ = tl(.2) - 4
numericq(abs(answ))
```

View File

@ -14,7 +14,7 @@ using CalculusWithJulia.WeaveSupport
using Printf
using SymPy
fig_size = (600, 400)
fig_size = (800, 600)
const frontmatter = (
title = "The mean value theorem for differentiable functions.",
@ -84,19 +84,14 @@ power rule: $f'(x) = 1/3 \cdot x^{-2/3}$, which has a vertical
asymptote at $x=0$.
```julia; echo=false
note("""
The `cbrt` function is used above, instead of `f(x) = x^(1/3)`, as the
latter is not defined for negative `x`. Though it can be for the exact
power `1/3`, it can't be for an exact power like `1/2`. This means the
value of the argument is important in determining the type of the
output - and not just the type of the argument. Having type-stable
functions is part of the magic to making `Julia` run fast, so `x^c` is
not defined for negative `x` and most floating point exponents.
""")
```
!!! note
The `cbrt` function is used above, instead of `f(x) = x^(1/3)`, as the
latter is not defined for negative `x`. Though it can be for the exact
power `1/3`, it can't be for an exact power like `1/2`. This means the
value of the argument is important in determining the type of the
output - and not just the type of the argument. Having type-stable
functions is part of the magic to making `Julia` run fast, so `x^c` is
not defined for negative `x` and most floating point exponents.
Lest you think that continuous functions always have derivatives
@ -128,14 +123,9 @@ must also be specified, for a relative maximum there just needs to
exist some interval, possibly really small, though it must be bigger
than a point.
```julia; echo=false
note("""
A hiker can appreciate the difference. A relative maximum would be the
crest of any hill, but an absolute maximum would be the summit.
""")
```
!!! note
A hiker can appreciate the difference. A relative maximum would be the
crest of any hill, but an absolute maximum would be the summit.
What does this have to do with derivatives?
@ -286,19 +276,14 @@ Here the maximum occurs at an endpoint. The critical point $c=0.67\dots$
does not produce a maximum value. Rather $f(0.67\dots)$ is an absolute
minimum.
```julia; echo=false
note(L"""
**Absolute minimum** We haven't discussed the parallel problem of
!!! note
**Absolute minimum** We haven't discussed the parallel problem of
absolute minima over a closed interval. By considering the function
$h(x) = - f(x)$, we see that the any thing true for an absolute
maximum should hold in a related manner for an absolute minimum, in
particular an absolute minimum on a closed interval will only occur
at a critical point or an end point.
""")
```
## Rolle's theorem
Let $f(x)$ be differentiable on $(a,b)$ and continuous on
@ -616,8 +601,8 @@ choices = [
"``h(x) = f(x) - g(x)``",
"``h(x) = f'(x) - g'(x)``"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -630,8 +615,8 @@ L"It isn't. The function $f(x) = x^2$ has two zeros and $f''(x) = 2 > 0$",
"By the Rolle's theorem, there is at least one, and perhaps more",
L"By the mean value theorem, we must have $f'(b) - f'(a) > 0$ when ever $b > a$. This means $f'(x)$ is increasing and can't double back to have more than one zero."
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -645,8 +630,8 @@ choices = [
"``c = 1 / (1/a + 1/b)``",
"``c = a + (\\sqrt{5} - 1)/2 \\cdot (b-a)``"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -660,8 +645,8 @@ choices = [
"``c = 1 / (1/a + 1/b)``",
"``c = a + (\\sqrt{5} - 1)/2 \\cdot (b-a)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -678,8 +663,8 @@ Why is it known that $g(x)$ goes to $0$ as $x$ goes to zero (from the right)?
choices = [L"The squeeze theorem applies, as $0 < g(x) < x$.",
L"As $f(x)$ goes to zero by Rolle's theorem it must be that $g(x)$ goes to $0$.",
L"This follows by the extreme value theorem, as there must be some $c$ in $[0,x]$."]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Since $g(x)$ goes to zero, why is it true that if $f(x)$ goes to $L$ as $x$ goes to zero that $f(g(x))$ must also have a limit $L$?
@ -688,6 +673,6 @@ Since $g(x)$ goes to zero, why is it true that if $f(x)$ goes to $L$ as $x$ goes
choices = ["It isn't true. The limit must be 0",
L"The squeeze theorem applies, as $0 < g(x) < x$",
"This follows from the limit rules for composition of functions"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```

View File

@ -498,8 +498,8 @@ choices = [
"The function oscillates too much to rely on the tangent line approximation far from the zero",
"We can find an answer"
]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
@ -525,6 +525,6 @@ choices = [
"The function oscillates too much to rely on the tangent line approximations far from the zero",
"We can find an answer"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```

View File

@ -14,7 +14,7 @@ using Roots
using CalculusWithJulia.WeaveSupport
using ImplicitPlots
fig_size = (600, 400)
fig_size = (800, 600)
const frontmatter = (
title = "Newton's method",
description = "Calculus with Julia: Newton's method",
@ -221,20 +221,15 @@ functions, convergence happens quickly.
```julia; echo=false
note("""
Newton looked at this same example in 1699 (B.T. Polyak, *Newton's
method and its use in optimization*, European Journal of Operational
Research. 02/2007; 181(3):1086-1096.) though his technique was
slightly different as he did not use the derivative, *per se*, but
rather an approximation based on the fact that his function was a
polynomial (though identical to the derivative). Raphson (1690)
proposed the general form, hence the usual name of the Newton-Raphson
method.
""")
```
!!! note
Newton looked at this same example in 1699 (B.T. Polyak, *Newton's
method and its use in optimization*, European Journal of Operational
Research. 02/2007; 181(3):1086-1096.) though his technique was
slightly different as he did not use the derivative, *per se*, but
rather an approximation based on the fact that his function was a
polynomial (though identical to the derivative). Raphson (1690)
proposed the general form, hence the usual name of the Newton-Raphson
method.
#### Examples
@ -634,13 +629,10 @@ This convergence to ``\alpha`` will be quadratic *if*:
not necessarily a good approximation to the actual zero, $\alpha$.
```julia; echo=false
note("""
The basic tradeoff: methods like Newton's are faster than the
bisection method in terms of function calls, but are not guaranteed to
converge, as the bisection method is.
""")
```
!!! note
The basic tradeoff: methods like Newton's are faster than the
bisection method in terms of function calls, but are not guaranteed to
converge, as the bisection method is.
What can go wrong when one of these isn't the case is illustrated next:
@ -802,8 +794,8 @@ If one step of Newton's method was used, what would be the value of $x_1$?
```julia; hold=true; echo=false
choices = ["``-2.224``", "``-2.80``", "``-0.020``", "``0.355``"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -827,8 +819,8 @@ L"It must be $x_1 > \alpha$",
L"It must be $x_1 < x_0$",
L"It must be $x_0 < x_1 < \alpha$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
----
@ -852,8 +844,8 @@ L"It must be $x_1 < \alpha$",
L"It must be $x_1 > x_0$",
L"It must be $\alpha < x_1 < x_0$"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
----
@ -866,8 +858,8 @@ L"As $f''(\xi)/2 \cdot(x-c)^2$ is non-negative, we must have $f(x) - (f(c) + f'(
L"As $f''(\xi) < 0$ it must be that $f(x) - (f(c) + f'(c)\cdot(x-c)) \geq 0$.",
L"This isn't true. The function $f(x) = x^3$ at $x=0$ provides a counterexample"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
This question can be used to give a proof for the previous two questions, which can be answered by considering the graphs alone. Combined, they say that if a function is increasing and concave up and ``\alpha`` is a zero, then if ``x_0 < \alpha`` it will be ``x_1 > \alpha``, and for any ``x_i > \alpha``, ``\alpha <= x_{i+1} <= x_\alpha``, so the sequence in Newton's method is decreasing and bounded below; conditions for which it is guaranteed mathematically there will be convergence.
@ -1050,8 +1042,8 @@ choices = [
"No. The initial guess is not close enough",
"No. The second derivative is too big",
L"No. The first derivative gets too close to $0$ for one of the $x_i$"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -1067,8 +1059,8 @@ choices = [
"No. The initial guess is not close enough",
"No. The second derivative is too big, or does not exist",
L"No. The first derivative gets too close to $0$ for one of the $x_i$"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1082,8 +1074,8 @@ choices = [
"No. The initial guess is not close enough",
"No. The second derivative is too big, or does not exist",
L"No. The first derivative gets too close to $0$ for one of the $x_i$"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1097,8 +1089,8 @@ choices = [
"No. The initial guess is not close enough",
"No. The second derivative is too big, or does not exist",
L"No. The first derivative gets too close to $0$ for one of the $x_i$"]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
@ -1114,8 +1106,8 @@ choices = [
"No. The initial guess is not close enough",
"No. The second derivative is too big, or does not exist",
L"No. The first derivative gets too close to $0$ for one of the $x_i$"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1177,8 +1169,8 @@ L"It doesn't fail, it converges to $0$",
L"The tangent lines for $|x| > 0.25$ intersect at $x$ values with $|x| > 0.25$",
L"The first derivative is $0$ at $1$"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -1261,14 +1253,14 @@ So we have a means to find $y(x)$, but it is implicit.
Using `find_zero`, find the value $x$ which maximizes `y` by finding a zero of `y'`. Use this to find the point $(x,y)$ with largest $y$ value.
```julia; hold=true; echo=false
xstar = find_zero(yp, 0.5)
xstar = find_zero(findy', 0.5)
ystar = findy(xstar)
choices = ["``(-0.57735, 1.15470)``",
"``(0,0)``",
"``(0, -0.57735)``",
"``(0.57735, 0.57735)``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
(Using automatic derivatives works for values identified with `find_zero` *as long as* the initial point has its type the same as that of `x`.)

View File

@ -210,13 +210,8 @@ fp = diff(f(x),x)
fp, fp(c), f'(c), (f(c+h) - f(c))/h
```
```julia;echo=false
note("""
The use of `'` to find derivatives provided by `CalculusWithJulia` is convenient, and used extensively in these notes, but it needs to be noted that it does **not conform** with the generic meaning of `'` within `Julia`'s wider package ecosystem and may cause issue with linear algebra operations; the symbol is meant for the adjoint of a matrix.
""")
```
!!! note
The use of `'` to find derivatives provided by `CalculusWithJulia` is convenient, and used extensively in these notes, but it needs to be noted that it does **not conform** with the generic meaning of `'` within `Julia`'s wider package ecosystem and may cause issue with linear algebra operations; the symbol is meant for the adjoint of a matrix.
## Questions

View File

@ -12,11 +12,11 @@ using SymPy
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
fig_size = (400, 400)
const frontmatter = (
title = "Optimization",
description = "Calculus with Julia: Optimization",
tags = ["CalculusWithJulia", "derivatives", "optimization"],
fig_size = (800, 600)
frontmatter = (
title = "Optimization",
description = "Calculus with Julia: Optimization",
tags = ["CalculusWithJulia", "derivatives", "optimization"],
);
nothing
@ -173,13 +173,8 @@ find_zeros(A', 0, 10) # find_zeros in `Roots`,
```julia; echo=false
note("""
Look at the last definition of `A`. The function `A` appears on both sides, though on the left side with one argument and on the right with two. These are two "methods" of a *generic* function, `A`. `Julia` allows multiple definitions for the same name as long as the arguments (their number and type) can disambiguate which to use. In this instance, when one argument is passed in then the last defintion is used (`A(b,h(b))`), whereas if two are passed in, then the method that multiplies both arguments is used. The advantage of multiple dispatch is illustrated: the same concept - area - has one function name, though there may be different ways to compute the area, so there is more than one implementation.
""")
```
!!! note
Look at the last definition of `A`. The function `A` appears on both sides, though on the left side with one argument and on the right with two. These are two "methods" of a *generic* function, `A`. `Julia` allows multiple definitions for the same name as long as the arguments (their number and type) can disambiguate which to use. In this instance, when one argument is passed in then the last defintion is used (`A(b,h(b))`), whereas if two are passed in, then the method that multiplies both arguments is used. The advantage of multiple dispatch is illustrated: the same concept - area - has one function name, though there may be different ways to compute the area, so there is more than one implementation.
#### Example: Norman windows
@ -582,7 +577,7 @@ both positive. What value $x$ in $[0,L]$ will minimize the total travel time?
We approach this symbolically with `SymPy`:
```julia;
@syms a::positive b::positive L::positive r0::positive r1::positive
@syms x::positive a::positive b::positive L::positive r0::positive r1::positive
d0 = sqrt(x^2 + a^2)
d1 = sqrt((L-x)^2 + b^2)
@ -913,8 +908,8 @@ choices = [
"It is also 20",
"``17.888``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1076,8 +1071,8 @@ Now if $Likhood(t) = \exp(-3t) \cdot \exp(-2t) \cdot \exp(-4t), \quad 0 \leq t \
choices=["It does work and the answer is x = 2.27...",
L" $Likhood(t)$ is not continuous on $0$ to $10$",
L" $Likhood(t)$ takes its maximum at a boundary point - not a critical point"];
ans = 3;
radioq(choices, ans)
answ = 3;
radioq(choices, answ)
```
##### Question
@ -1103,8 +1098,8 @@ choices=[
"The median, or middle number, of the values",
L"The square roots of the values squared, $(x_1^2 + \cdots x_n^2)^2$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1241,8 +1236,8 @@ choices = ["exactly four times",
L"exactly $\pi$ times",
L"about $2.6$ times as big",
"about the same"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1278,8 +1273,8 @@ choices = [
"``e/a``",
"``a \\cdot e``"
]
ans=2
radioq(choices, ans)
answ=2
radioq(choices, answ)
```
###### Question

View File

@ -12,7 +12,7 @@ using SymPy
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
fig_size=(600, 400)
fig_size=(800, 600)
const frontmatter = (
title = "Related rates",
description = "Calculus with Julia: Related rates",
@ -610,8 +610,8 @@ choices = [
"The rate of change of price will increase",
"The rate of change of price will be positive and will depend on the rate of change of excess demand."
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
(Theoretically, when demand exceeds supply, prices increase.)
@ -625,8 +625,8 @@ choices = [
"If the rate of change of unemployment is negative, the rate of change of wages will be negative.",
"If the rate of change of unemployment is negative, the rate of change of wages will be positive."
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
(Colloquially, "the rate of change of unemployment is negative" means the unemployment rate is going down, so there are fewer workers available to fill new jobs.)
@ -643,8 +643,8 @@ L"The rate of change of pressure is always increasing by $c$",
"If volume is constant, the rate of change of pressure is proportional to the temperature",
"If volume is constant, the rate of change of pressure is proportional to the rate of change of temperature",
"If pressure is held constant, the rate of change of pressure is proportional to the rate of change of temperature"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -735,8 +735,8 @@ choices = [
"``f(x) = x``",
"``f(x) = x^2``"
]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
###### Question
@ -763,8 +763,8 @@ choices = [
"``y = 1 - \\log(x)``",
"``y = x(2x - 1/x)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
If $dx/dt = -1$, what is $dy/dt$?
@ -776,6 +776,6 @@ choices = [
"``dy/dt = -2x - 1/x``",
"``dy/dt = 1``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```

View File

@ -14,7 +14,7 @@ using Unitful
using CalculusWithJulia.WeaveSupport
using Roots
fig_size = (600, 400)
fig_size = (800, 600)
const frontmatter = (
title = "Taylor Polynomials and other Approximating Polynomials",
description = "Calculus with Julia: Taylor Polynomials and other Approximating Polynomials",
@ -564,14 +564,9 @@ output. `SymPy` provides the `removeO` method to strip this. (It is called as `o
```julia; echo=false
note("""
!!! note
A Taylor polynomial of degree ``n`` consists of ``n+1`` terms and an error term. The "Taylor series" is an *infinite* collection of terms, the first ``n+1`` matching the Taylor polynomial of degree ``n``. The fact that series are *infinite* means care must be taken when even talking about their existence, unlike a Tyalor polynomial, which is just a polynomial and exists as long as a sufficient number of derivatives are available.
A Taylor polynomial of degree ``n`` consists of ``n+1`` terms and an error term.
The "Taylor series" is an *infinite* collection of terms, the first ``n+1`` matching the Taylor polynomial of degree ``n``. The fact that series are *infinite* means care must be taken when even talking about their existence, unlike a Tyalor polynomial, which is just a polynomial and exists as long as a sufficient number of derivatives are available.
""")
```
We define a function to compute Taylor polynomials from a function. The following returns a function, not a symbolic object, using `D`, from `CalculusWithJulia`, which is based on `ForwardDiff.derivative`, to find higher-order derivatives:
@ -965,8 +960,8 @@ choices = [
"``\\sum_{k=0}^{4} (-1)^k/(2k+1)! \\cdot x^{2k+1}``",
"``\\sum_{k=0}^{10} x^n/n!``"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -980,8 +975,8 @@ choices = [
"``\\sum_{k=0}^{4} (-1)^k/(2k+1)! \\cdot x^{2k+1}``",
"``\\sum_{k=0}^{10} x^n/n!``"
]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
@ -997,8 +992,8 @@ choices = [
"``\\sum_{k=0}^{4} (-1)^k/(2k+1)! \\cdot x^{2k+1}``",
"``\\sum_{k=0}^{10} x^n/n!``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1012,8 +1007,8 @@ choices = [
"``1/5!``",
"``2/15``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1028,8 +1023,8 @@ choices = [
"``x^2``",
"``x^2 \\cdot (x - x^3/3! + x^5/5!)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1048,8 +1043,8 @@ If this is true, then formally evaluating at $x=0$ gives $f(0) = a$, so $a$ is d
choices = ["``f''''(0) = e``",
"``f''''(0) = 4 \\cdot 3 \\cdot 2 e = 4! e``",
"``f''''(0) = 0``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -1069,8 +1064,8 @@ yesnoq(true)
```julia; hold=true; echo=false
choices =["It is increasing", "It is decreasing", "It both increases and decreases"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1078,8 +1073,8 @@ radioq(choices, ans)
```julia; hold=true; echo=false
choices=["A critical point", "An end point"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
* Which theorem tells you that for a *continuous* function over *closed* interval, a maximum value will exist?
@ -1089,8 +1084,8 @@ choices = [
"The intermediate value theorem",
"The mean value theorem",
"The extreme value theorem"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
* What is the *largest* possible value of the error:
@ -1099,8 +1094,8 @@ radioq(choices, ans)
choices = [
"``1/6!\\cdot e^1 \\cdot 1^6``",
"``1^6 \\cdot 1 \\cdot 1^6``"]
ans = 1
radioq(choices,ans)
answ = 1
radioq(choices,answ)
```
###### Question
@ -1115,8 +1110,8 @@ L"The function $e^x$ is increasing, so takes on its largest value at the endpoin
L"The function has a critical point at $x=1/2$",
L"The function is monotonic in $k$, so achieves its maximum at $k+1$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Assuming the above is right, find the smallest value $k$ guaranteeing a error no more than $10^{-16}$.

View File

@ -12,10 +12,10 @@ using ForwardDiff
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
title = "2D and 3D plots in Julia with Plots",
description = "Calculus with Julia: 2D and 3D plots in Julia with Plots",
tags = ["CalculusWithJulia", "differentiable_vector_calculus", "2d and 3d plots in julia with plots"],
frontmatter = (
title = "2D and 3D plots in Julia with Plots",
description = "Calculus with Julia: 2D and 3D plots in Julia with Plots",
tags = ["CalculusWithJulia", "differentiable_vector_calculus", "2d and 3d plots in julia with plots"],
);
nothing
```
@ -69,7 +69,8 @@ ts = range(0, 2pi, length=100)
plot(unzip(r₂.(ts))...)
```
As a convenience, `CalculusWithJulia` provides `plot_parametric` to produce this plot. The interval is specified with the `a..b` notation, the points to plot are adaptively chosen:
As a convenience, `CalculusWithJulia` provides `plot_parametric` to produce this plot. The interval is specified with the `a..b` notation of `IntervalSets` (which is available when the `CalculusWithJulia` package is loaded), the points to plot are adaptively chosen:
```julia
plot_parametric(0..2pi, r₂) # interval first
@ -340,7 +341,7 @@ surface(xs, ys, zs)
note("The above may not work with all backends for `Plots`, even if those that support 3D graphics.")
```
For convenience, the `plot_parametric` function from `CalculusWithJulia` can produce these plots using interval notation and a function:
For convenience, the `plot_parametric` function from `CalculusWithJulia` can produce these plots using interval notation, `a..b`, and a function:
```julia; hold=true
F(theta, phi) = [X(1, theta, phi), Y(1, theta, phi), Z(1, theta, phi)]

View File

@ -13,7 +13,7 @@ using QuadGK
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
frontmatter = (
title = "Polar Coordinates and Curves",
description = "Calculus with Julia: Polar Coordinates and Curves",
tags = ["CalculusWithJulia", "differentiable_vector_calculus", "polar coordinates and curves"],
@ -143,7 +143,7 @@ rs = r.(ts)
plot(ts, rs, proj=:polar, legend=false)
```
To avoid having to create values for $\theta$ and values for $r$, the `CalculusWithJulia` package provides a helper function, `plot_polar`. To distinguish it from other functions provided by `Plots`, the calling pattern is different. It specifies an interval to plot over by `a..b` and puts that first, followed by `r`. Other keyword arguments are passed onto a `plot` call.
To avoid having to create values for $\theta$ and values for $r$, the `CalculusWithJulia` package provides a helper function, `plot_polar`. To distinguish it from other functions provided by `Plots`, the calling pattern is different. It specifies an interval to plot over by `a..b` and puts that first (this notation for closed intervals is from `IntervalSets`), followed by `r`. Other keyword arguments are passed onto a `plot` call.
We will use this in the following, as the graphs are a bit more familiar and the calling pattern similar to how we have plotted functions.
@ -634,8 +634,8 @@ choices = [
"a circle",
"a line"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -649,8 +649,8 @@ choices = [
"a circle",
"a line"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -664,8 +664,8 @@ choices = [
"a circle",
"a line"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -681,8 +681,8 @@ choices = [
"``\\pi/2``",
"``1``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
###### Question

View File

@ -10,6 +10,11 @@ using SymPy
using Roots
using QuadGK
using JSON
```
Also, these methods from the `Contour` package:
```julia
import Contour: contours, levels, level, lines, coordinates
```
@ -155,9 +160,8 @@ surface(xs, ys, 𝒇)
The `surface` function will generate the surface.
```julia; echo=false
note("""Using `surface` as a function name is equivalent to `plot(xs, ys, f, seriestype=:surface)`.""")
```
!!! note
Using `surface` as a function name is equivalent to `plot(xs, ys, f, seriestype=:surface)`.
We can also use `surface(xs, ys, zs)` where `zs` is not a vector, but
rather a *matrix* of values corresponding to a grid described by the
@ -548,7 +552,6 @@ r2₁(t) = [γ₁(t)..., 0]
plot_parametric!(0..1/2, r2₁, linewidth=5, color=:black) # in the $x$-$y$ plane
```
The vector valued function `r3(t) = [γ(t)..., f(γ(t))]` takes the ``2``-dimensional path specified by $\vec\gamma(t)$ and adds a third, $x$, direction by composing the position with `f`. In this way, a ``2``-D path is visualized with a ``3``-D path. This viewpoint can be reversed, as desired.
However, the composition, $f\circ\vec\gamma$, is a univariate function, so this can also be visualized by
@ -709,11 +712,8 @@ partial_x(f, y) = x -> ForwardDiff.derivative(u -> f(u,y), x)
```
```julia; echo=false
note("""
For vector-valued functions, we can overide the syntax `'` using `Base.adjoint`, as `'` is treated as a postfix operator in `Julia` for the `adjoint` operation. The symbol `\\nabla` is also available in `Julia`, but it is not an operator, so can't be used as mathematically written `∇f` (this could be used as a name though). In `CalculusWithJulia` a definition is made so essentially `∇(f) = x -> ForwardDiff.gradient(f, x)`. It does require parentheses to be called, as in `∇(f)`.
""")
```
!!! note
For vector-valued functions, we can overide the syntax `'` using `Base.adjoint`, as `'` is treated as a postfix operator in `Julia` for the `adjoint` operation. The symbol `\\nabla` is also available in `Julia`, but it is not an operator, so can't be used as mathematically written `∇f` (this could be used as a name though). In `CalculusWithJulia` a definition is made so essentially `∇(f) = x -> ForwardDiff.gradient(f, x)`. It does require parentheses to be called, as in `∇(f)`.
#### Symbolic expressions
@ -1409,8 +1409,8 @@ From the graph, is the value of $f(1/2, 1)$ positive or negative?
```julia; hold=true; echo=false
choices = ["positive", "negative"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -1421,8 +1421,8 @@ choices = [
L"The line $x=0$",
L"The line $y=0$"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
Consider the contour plot
@ -1449,8 +1449,8 @@ L"is around $(0.7, 0)$ and with a value less than $-0.4$",
L"is around $(-2.0, 0)$ and with a value less than $-0.4$",
L"is around $(2.0, 0)$ and with a value less than $-0.4$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
From this graph, where is the surface steeper?
@ -1462,8 +1462,8 @@ L"near $(1/2, 0)$",
L"near $(3/4, 0)$",
L"near $(1, 0)$"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1483,8 +1483,8 @@ choices = [
L"Yes, the closed loops near $(-1.5, 0)$ and $(1.5, 0)$ will contain these",
L"No, the vertical lines parallel to $x=0$ show this function to be flat"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Imagine hiking on this surface within this region. Could you traverse from left to right without having to go up or down?
@ -1519,8 +1519,8 @@ choices = [
"running essentially parallel to the contour lines",
"running essentially perpendicular to the contour lines"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Why?
@ -1530,8 +1530,8 @@ choices = [
"By being essentially parallel, the steepness of the roadway can be kept to a passable level",
"By being essentially perpendicular, the road can more quickly climb up the mountain"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
The pass is at about 2700 meters. As shown towards the top and bottom of the figure the contour lines show increasing heights, and to the left and right decreasing heights. The shape of the [pass](https://en.wikipedia.org/wiki/Mountain_pass) would look like:
@ -1541,8 +1541,8 @@ choices = [
"A saddle-like shape, called a *col* or *gap*",
"A upside down bowl-like shape like the top of a mountain"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1561,8 +1561,8 @@ L"When $i(\vec{x}) = 0$",
L"When any of $f(\vec{x})$, $g(\vec{x})$, or $i(\vec{x})$ are zero",
L"The limit exists everywhere, as the function $f$, $g$, $h$, and $i$ have limits at $\vec{c}$ by assumption"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1602,8 +1602,8 @@ raw"`` \langle \cos(2y), \cos(y) \rangle``",
raw"`` \langle \sin(x), \sin(2x) \rangle``",
raw"`` \sin(x)\cos(2y)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Compute $f_y$
@ -1615,8 +1615,8 @@ raw"`` \langle 2\sin(x), \sin(2x) \rangle``",
raw"`` \langle -2\sin(2y), -\sin(y) \rangle``",
raw"`` - \sin(2x)\sin(y)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1654,16 +1654,16 @@ The gradient is:
```julia; hold=true; echo=false
choices = ["two dimensional", "three dimensional"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
The surface is:
```julia; hold=true; echo=false
choices = ["two dimensional", "three dimensional"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
The gradient points in the direction of greatest increase of $f$. If a person were on a hill described by $z=f(x,y)$, what three dimensional vector would they follow to go the steepest way up the hill?
@ -1674,8 +1674,8 @@ choices = [
raw"`` \langle -f_x, -f_y, 1 \rangle``",
raw"`` \langle f_x, f_y \rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
##### Question
@ -1700,8 +1700,8 @@ choices = [
raw"`` (f\circ\vec\gamma)(x,y)``",
raw"`` \vec\gamma(x,y)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
A climber leaves base camp at $t_0$. At time $t > t_0$, what describes her elevation?
@ -1712,8 +1712,8 @@ choices = [
raw"`` \vec\gamma(t)``",
raw"`` f(t)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
What does the vector-valued function $\vec{r}(t) = \langle x(t), y(t), (f\circ\vec\gamma(t))\rangle$ describe:
@ -1723,8 +1723,8 @@ choices = [
"The three dimensional position of the climber",
"The climbers gradient, pointing in the direction of greatest ascent"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
In the figure, the climbers are making a switch back, so as to avoid the steeper direct ascent. Mathematically $\nabla{f}(\vec\gamma(t)) \cdot \vec\gamma'(t)$ describes the directional derivative that they follow. Using $\|\vec{u}\cdot\vec{v}\| = \|\vec{u}\|\|\vec{v}\|\cos(\theta)$, does this route:
@ -1735,8 +1735,8 @@ choices = [
L"Keep $\cos(\theta)$ as close to $1$ as possible, so the slope taken is as big as possible",
L"Keep $̧\cos(\theta)$ as close to $0$ as possible, so that they climbers don't waste energy going up and down"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Suppose our climber reaches the top at time $t$. What would be $(f\circ\vec\gamma)'(t)$, assuming the derivative exists?
@ -1747,8 +1747,8 @@ choices = [
L"It would be $\langle f_x, f_y\rangle$ and point towards the sky, the direction of greatest ascent",
"It would not exist, as there would not be enough oxygen to compute it"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1765,8 +1765,8 @@ raw"`` |\hat{T} \cdot \hat{P}| \leq \cos(π/18)``",
raw"`` |\hat{T} \cdot \hat{P}| \leq \sin(\pi/18)``",
raw"`` |\hat{T} \cdot \hat{P}| \leq \pi/18``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
The normal to the surface $z=f(x,y)$ is *not* the normal to the trail tread. Suppose $\vec{N}(t)$ is a function that returns this. At the same point $\vec\gamma(t)$, let $\vec{M} = \langle -f_x, -f_y, 0\rangle$ be a vector in 3 dimensions pointing downhill. Let "hats" indicate unit vectors. The outward slope is $\pi/2$ minus the angle between $\hat{N}$ and $\hat{M}$. What condition will ensure this angle is $5$ degrees ($\pi/36$ radians)?
@ -1777,8 +1777,8 @@ choices = [
raw"`` |\hat{N} \cdot \hat{M}| \leq \sin(\pi/2 - \pi/18)``",
raw"`` |\hat{N} \cdot \hat{M}| \leq \pi/2 - \pi/18``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1797,8 +1797,8 @@ choices = [
raw"`` 2 \cos{\left (3 \right )} - 7 \sin{\left (3 \right )}``",
raw"`` 4 x^{2} y \sin{\left (x - y^{2} \right )} - x^{2} \sin{\left (x - y^{2} \right )} + 2 x \cos{\left (x - y^{2} \right )}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1813,8 +1813,8 @@ choices = [
"Yes, by definition",
L"No, not unless $\vec{v}$ were a unit vector"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -1831,8 +1831,8 @@ choices = [
raw"`` \langle 4x^3, 2z, 2y\rangle``",
raw"`` \langle x^3 + 2x + 2x, 2y+ y^3, 2x\rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
The value of $\vec\gamma'(t)$ is:
@ -1843,8 +1843,8 @@ choices = [
raw"`` 1 + 2y + 3t^2``",
raw"`` \langle 1,2, 3 \rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
The value of $(f\circ\vec\gamma)'(t)$ is found by:
@ -1855,8 +1855,8 @@ choices = [
L"Taking the dot product of $\nabla{f}(\vec\gamma'(t))$ and $\vec\gamma(t)$",
L"Taking the dot product of $\nabla{f}(x,y,z)$ and $\vec\gamma'(t)$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1887,8 +1887,8 @@ choices = [
"The green one",
"The red one"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1915,8 +1915,8 @@ choices = [
"The green one",
"The red one"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1947,8 +1947,8 @@ choices = [
L"Linear means $H$ is linear, so $g(\vec{x})$ describes a plane",
L"Linear means $H$ is the $0$ matrix, so the gradient couldn't have been $\vec{0}$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Suppose, $H$ has the magic property that for *any* vector $\vec{v}^tH\vec{v} < 0$. What does this imply:
@ -1959,8 +1959,8 @@ choices = [
L"That $g(\vec{x}) = f(\vec{c})$",
L"That $g(\vec{x}) \leq f(\vec{c})$"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1974,8 +1974,8 @@ choices = [
raw"`` \partial^4{f}/\partial{x^2}\partial{y^2}``",
raw"`` \partial^4{f}/\partial{x^1}\partial{y^3}``"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1993,8 +1993,8 @@ choices = [
raw"`` f_{yy}``"
]
x,y=1/2, 2
val, ans = findmax([6x*y, 3x^2, 6*y, 6x, 0])
radioq(choices, ans, keep_order=true)
val, answ = findmax([6x*y, 3x^2, 6*y, 6x, 0])
radioq(choices, answ, keep_order=true)
```
###### Question
@ -2024,15 +2024,15 @@ Whereas,
At $(0,0)$ what is $ \frac{\partial \frac{\partial f}{\partial x}}{ \partial y}$?
```julia; hold=true; echo=false
ans = -1
numericq(ans)
answ = -1
numericq(answ)
```
At $(0,0)$ what is $ \frac{\partial \frac{\partial f}{\partial y}}{ \partial x}$?
```julia; hold=true; echo=false
ans = 1
numericq(ans)
answ = 1
numericq(answ)
```
Away from $(0,0)$ the mixed partial is $\frac{x^{6} + 9 x^{4} y^{2} - 9 x^{2} y^{4} - y^{6}}{x^{6} + 3 x^{4} y^{2} + 3 x^{2} y^{4} + y^{6}}$.
@ -2043,8 +2043,8 @@ choices = [
L"This is not continuous at $(0,0)$, still the limit along the two paths $x=0$ and $y=0$ are equivalent.",
L"This is not continuous at $(0,0)$, as the limit along the two paths $x=0$ and $y=0$ are not equivalent."
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -2096,8 +2096,8 @@ L"The Burgers equation: $f_t + ff_x = f_{xx}$; describes waves at the beach whic
L"The KdV equation: $f_t + 6ff_x+ f_{xxx} = 0$; models water waves in a narrow channel",
L"The Schrodinger equation: $f_t = (i\hbar/(2m))f_xx$; used to describe a quantum particle of mass $m$"
]
ans = 3
radioq(ode_choices, ans, keep_order=true)
answ = 3
radioq(ode_choices, answ, keep_order=true)
```
@ -2106,8 +2106,8 @@ radioq(ode_choices, ans, keep_order=true)
What equation does the function $f(t, x) = sin(x-t) + sin(x+t)$ satisfy?
```julia; hold=true; echo=false
ans = 1
radioq(ode_choices, ans, keep_order=true)
answ = 1
radioq(ode_choices, answ, keep_order=true)
```
@ -2116,14 +2116,14 @@ radioq(ode_choices, ans, keep_order=true)
What equation does the function $f(t, x) = e^{-(x+t)^2}$ satisfy?
```julia; hold=true; echo=false
ans = 4
radioq(ode_choices, ans, keep_order=true)
answ = 4
radioq(ode_choices, answ, keep_order=true)
```
What equation does the function $f(x,y) = \cos(x) + \sin(y)$ satisfy?
```julia; hold=true; echo=false
ans = 5
radioq(ode_choices, ans, keep_order=true)
answ = 5
radioq(ode_choices, answ, keep_order=true)
```

View File

@ -8,6 +8,11 @@ using CalculusWithJulia
using Plots
using SymPy
using Roots
```
And the following from the `Contour` package:
```julia
import Contour: contours, levels, level, lines, coordinates
```
@ -109,8 +114,8 @@ pt = [a, b, 0]
scatter!(unzip([pt])...)
arrow!(pt, [1,0,0], linestyle=:dash)
arrow!(pt, [0,1,0], linestyle=:dash)
```
#### Alternate forms
The equation for the tangent plane is often expressed in a more explicit form. For $n=2$, if we set $dx = x-a$ and $dy=y-a$, then the equation for the plane becomes:
@ -915,8 +920,10 @@ Another might be the vertical squared distance to the line:
```math
d2(\alpha, \beta) = (y_1 - l(x_1))^2 + (y_2 - l(x_2))^2 + (y_3 - l(x_3))^2 =
(y1 - (\alpha + \beta x_1))^2 + (y3 - (\alpha + \beta x_3))^2 + (y3 - (\alpha + \beta x_3))^2
\begin{align*}
d2(\alpha, \beta) &= (y_1 - l(x_1))^2 + (y_2 - l(x_2))^2 + (y_3 - l(x_3))^2 \\
&= (y1 - (\alpha + \beta x_1))^2 + (y3 - (\alpha + \beta x_3))^2 + (y3 - (\alpha + \beta x_3))^2
\end{align*}
```
Another might be the *shortest* distance to the line:
@ -1011,8 +1018,8 @@ gammas₂ = [1.0]
for n in 1:5
xn = xs₂[end]
gamma = gammas₂[end]
xn1 = xn - gamma * gradient(f₂)(xn)
gamma = gammas₂[end]
xn1 = xn - gamma * gradient(f₂)(xn)
dx, dy = xn1 - xn, gradient(f₂)(xn1) - gradient(f₂)(xn)
gamman1 = abs( (dx ⋅ dy) / (dy ⋅ dy) )
@ -1133,10 +1140,8 @@ fxx, d
Consequently we have a local maximum at this critical point.
```julia; echo=false
note(""" The `Optim.jl` package provides efficient implementations of these two numeric methods, and others. """)
```
!!! note
The `Optim.jl` package provides efficient implementations of these two numeric methods, and others.
## Constrained optimization, Lagrange multipliers
@ -1557,11 +1562,13 @@ This theorem can be generalized to scalar functions, but the notation can be cum
Following [Folland](https://sites.math.washington.edu/~folland/Math425/taylor2.pdf) we use *multi-index* notation. Suppose $f:R^n \rightarrow R$, and let $\alpha=(\alpha_1, \alpha_2, \dots, \alpha_n)$. Then define the following notation:
```math
|\alpha| = \alpha_1 + \cdots + \alpha_n, \quad
\alpha! = \alpha_1!\alpha_2!\cdot\cdots\cdot\alpha_n!,\quad
\vec{x}^\alpha = x_1^{\alpha_1}x_2^{\alpha_2}\cdots x_n^{\alpha^n}, \quad
\partial^\alpha f = \partial_1^{\alpha_1}\partial_2^{\alpha_2}\cdots \partial_n^{\alpha_n} f =
\frac{\partial^{|\alpha|}f}{\partial x_1^{\alpha_1} \partial x_2^{\alpha_2} \cdots \partial x_n^{\alpha_n}}.
\begin{align*}
|\alpha| &= \alpha_1 + \cdots + \alpha_n, \\
\alpha! &= \alpha_1!\alpha_2!\cdot\cdots\cdot\alpha_n!, \\
\vec{x}^\alpha &= x_1^{\alpha_1}x_2^{\alpha_2}\cdots x_n^{\alpha^n}, \\
\partial^\alpha f &= \partial_1^{\alpha_1}\partial_2^{\alpha_2}\cdots \partial_n^{\alpha_n} f \\
& = \frac{\partial^{|\alpha|}f}{\partial x_1^{\alpha_1} \partial x_2^{\alpha_2} \cdots \partial x_n^{\alpha_n}}.
\endalign*}
```
This notation makes many formulas from one dimension carry over to higher dimensions. For example, the binomial theorem says:
@ -1781,8 +1788,8 @@ choices = [
raw"`` 2x + y - 2z = 1``",
raw"`` x + 2y + 3z = 6``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1798,8 +1805,8 @@ choices = [
raw"`` y^2 + y, x^2 + x``",
raw"`` \langle 2y + y^2, 2x + x^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Is this the Hessian of $f$?
@ -1830,8 +1837,8 @@ choices = [
L"The function $f$ has a saddle point, as $d < 0$",
L"Nothing can be said, as $d=0$"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -1885,8 +1892,8 @@ choices = [
L"Nothing can be said, as $d=0$",
L"The test does not apply, as $\nabla{f}$ is not $0$ at this point."
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
Which is true of $f$ at $(0, -1/2)$:
@ -1899,8 +1906,8 @@ choices = [
L"Nothing can be said, as $d=0$",
L"The test does not apply, as $\nabla{f}$ is not $0$ at this point."
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -1914,8 +1921,8 @@ choices = [
L"Nothing can be said, as $d=0$",
L"The test does not apply, as $\nabla{f}$ is not $0$ at this point."
]
ans = 5
radioq(choices, ans, keep_order=true)
answ = 5
radioq(choices, answ, keep_order=true)
```
@ -1962,8 +1969,8 @@ choices =[
"It is the determinant of the Hessian",
L"It isn't, $b^2-4ac$ is from the quadratic formula"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Which condition on $a$, $b$, and $c$ will ensure a *local maximum*:
@ -1974,8 +1981,8 @@ choices = [
L"That $a<0$ and $ac-b^2 > 0$",
L"That $ac-b^2 < 0$"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
Which condition on $a$, $b$, and $c$ will ensure a saddle point?
@ -1987,8 +1994,8 @@ choices = [
L"That $a<0$ and $ac-b^2 > 0$",
L"That $ac-b^2 < 0$"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -2016,8 +2023,8 @@ choices = [
raw"`` \langle 2x, y^2\rangle``",
raw"`` \langle x^2, 2y \rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Due to the form of the gradient of the constraint, finding when $\nabla{f} = \lambda \nabla{g}$ is the same as identifying when this ratio $|f_x/f_y|$ is $1$. The following solves for this by checking each point on the constraint:

View File

@ -170,15 +170,12 @@ zs = [Z(theta, phi) for theta in thetas, phi in phis]
surface(xs, ys, zs) ## see note
```
```julis; echo=false
note("""Only *some* backends for `Plots` will produce this type of plot. Both `plotly()` and `pyplot()` will, but not `gr()`.
""")
```
!!! note
Only *some* backends for `Plots` will produce this type of plot. Both `plotly()` and `pyplot()` will, but not `gr()`.
```julia; echo=false
note("""Note: PyPlot can be used directly to make these surface plots: `import PyPlot; PyPlot.plot_surface(xs,ys,zs)`""")
```
!!! note
PyPlot can be used directly to make these surface plots: `import PyPlot; PyPlot.plot_surface(xs,ys,zs).
Instead of the comprehension, broadcasting can be used
@ -856,8 +853,8 @@ choices = [
"Yes",
"No, it is the transpose"
]
ans=2
radioq(choices, ans, keep_order=true)
answ=2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -879,8 +876,8 @@ choices = [
"Yes",
"No, it is the transpose"
]
ans=1
radioq(choices, ans, keep_order=true)
answ=1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -907,8 +904,8 @@ choices = [
"The determinant of the Hessian.",
"The determinant of the gradient."
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -920,8 +917,8 @@ choices = [
"`det(hessian(F(lambda, phi), [lambda, phi]))`",
"`det(gradient(F(lambda, phi), [lambda, phi]))`"
]
ans=1
radioq(choices, ans, keep_order=true)
answ=1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -934,8 +931,8 @@ choices = [
raw"`` 2x^3y/ (z\cos(z) + \sin(z) + 1)``",
raw"`` 3x^2y^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -949,8 +946,8 @@ choices = [
raw"`` \frac{x \left(2 x^{2} - y^{2} z^{2}{\left (x,y \right )}\right)}{\left(x^{2} y^{2} - 2 z^{2}{\left (x,y \right )}\right) z{\left (x,y \right )}}``",
raw"`` \frac{x \left(2 x^{2} - z^{2}{\left (x,y \right )}\right)}{\left(x^{2} - 2 z^{2}{\left (x,y \right )}\right) z{\left (x,y \right )}}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -965,8 +962,8 @@ choices = [
raw"`` S/r``",
raw"`` R``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Let $\phi = r^k$. What is $\nabla{\phi}$?
@ -977,8 +974,8 @@ choices = [
raw"`` kr^k R``",
raw"`` k r^{k-2} S``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Based on your last answer, are all radial fields $R/r^n$, $n\geq 0$ gradients of scalar functions?
@ -995,8 +992,8 @@ choices = [
raw"`` S/r``",
raw"`` S``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Express $S/r^n = \langle F_x, F_y\rangle$. For which $n$ is $\partial{F_y}/\partial{x} - \partial{F_x}/\partial{y} = 0$?
@ -1008,8 +1005,8 @@ L"As the left-hand side becomes $(-n+2)r^{-n}$, only $n=2$.",
L"All $n \geq 0$",
L"No values of $n$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
(The latter is of interest, as only when the expression is $0$ will the vector field be the gradient of a scalar function.)

View File

@ -7,20 +7,26 @@ using CalculusWithJulia
using Plots
using SymPy
using Roots
using DifferentialEquations
using LinearAlgebra
using QuadGK
```
and
```julia
import DifferentialEquations
import DifferentialEquations: ODEProblem, Tsit5
```
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
title = "Vector-valued functions, ``f:R \\rightarrow R^n``",
description = "Calculus with Julia: Vector-valued functions, ``f:R \\rightarrow R^n``",
tags = ["CalculusWithJulia", "differentiable_vector_calculus", "vector-valued functions, ``f:R \\rightarrow r^n``"],
frontmatter = (
title = "Vector-valued functions, ``f:R \\rightarrow R^n``",
description = "Calculus with Julia: Vector-valued functions, ``f:R \\rightarrow R^n``",
tags = ["CalculusWithJulia", "differentiable_vector_calculus", "vector-valued functions, ``f:R \\rightarrow r^n``"],
);
import PlutoUI
nothing
```
@ -150,7 +156,6 @@ ts = range(0, 6pi, length=200)
plot(unzip(g.(ts))..., camera=(0, 90))
```
The graph of $h$ shows that this function parameterizes a line in space. The line segment for $-2 \leq t \leq 2$ is shown below:
```julia; hold=true
@ -163,18 +168,17 @@ plot(unzip(h.(ts))...)
While the `unzip` function is easy to understand as a function that reshapes data from one format into one that `plot` can use, it's usage is a bit cumbersome.
The `CalculusWithJulia` package provides a function `plot_parametric` which hides the use of `unzip` and the splatting within a function definition.
The function borrows a calling style for `Makie`. The interval to plot over is specified first using `a..b` notation (from `IntervalSets`), then the function is specified. Additional keyword arguments are passed along to `plot`.
The function borrows a calling style for `Makie`. The interval to plot
over is specified first using `a..b` notation (which specifies a
closed interval in the `IntervalSets` package), then the function is
specified. Additional keyword arguments are passed along to `plot`.
```julia;
plot_parametric(-2..2, h)
```
```julia; echo=false
note("""
Defining plotting functions in `Julia` for `Plots` is facilitated by the `RecipesBase` package. There are two common choices: creating a new function for plotting, as is done with `plot_parametric` and `plot_polar`; or creating a new type so that `plot` can dispatch to an appropriate plotting method. The latter would also be a reasonable choice, but wasn't taken here. In any case, each can be avoided by creating the appropriate values for `xs` and `ys` (and possibly `zs`).
""")
```
!!! note
Defining plotting functions in `Julia` for `Plots` is facilitated by the `RecipesBase` package. There are two common choices: creating a new function for plotting, as is done with `plot_parametric` and `plot_polar`; or creating a new type so that `plot` can dispatch to an appropriate plotting method. The latter would also be a reasonable choice, but wasn't taken here. In any case, each can be avoided by creating the appropriate values for `xs` and `ys` (and possibly `zs`).
##### Example
@ -313,76 +317,83 @@ In 1935 [Marcel Duchamp](https://arthur.io/art/marcel-duchamp/rotorelief-no-10-c
* each nested circle is drawn after its center is rotated by ``\theta`` radian;
* an animation captures the movement for display.
```julia; hold=true;
```julia
let
# https://exploratorium.tumblr.com/post/33140874462/marcel-duchamp-rotoreliefs-duchamp-recognized
# coordinates and colors selected by gimp from
# https://arthur.io/art/marcel-duchamp/rotorelief-no-10-cage-modele-depose-verso
circs = [466 548 513 505 556 554 # x₁,y₁,x₂,y₂,x₂,y₃
414 549 511 455 595 549
365 545 507 408 635 548
319 541 506 361 673 546
277 543 509 317 711 546
236 539 507 272 747 551
201 541 504 230 781 550
166 541 503 189 816 544
140 542 499 153 848 538
116 537 496 119 879 538
96 539 501 90 905 534
81 530 500 67 930 530
72 525 498 51 949 529
66 520 500 36 966 527
60 515 499 25 982 526
35 509 499 11 1004 525 # outer edge, c₀
]
circs = [466 548 513 505 556 554 # x₁,y₁,x₂,y₂,x₂,y₃
414 549 511 455 595 549
365 545 507 408 635 548
319 541 506 361 673 546
277 543 509 317 711 546
236 539 507 272 747 551
201 541 504 230 781 550
166 541 503 189 816 544
140 542 499 153 848 538
116 537 496 119 879 538
96 539 501 90 905 534
81 530 500 67 930 530
72 525 498 51 949 529
66 520 500 36 966 527
60 515 499 25 982 526
35 509 499 11 1004 525 # outer edge, c₀
]
greenblue= RGB(8/100, 58/100, 53/100)
grey = RGB(76/100, 74/100, 72/100)
white = RGB(88/100, 85/100, 81/100)
greenblue= RGB(8/100, 58/100, 53/100)
grey = RGB(76/100, 74/100, 72/100)
white = RGB(88/100, 85/100, 81/100)
# solve for center of circle, radius for each
@syms h::positive k::positive r::positive
function solve_i(i)
eqs = [(p[1] - h)^2 + (p[2]-k)^2 ~ r^2 for
p ∈ (circs[i,1:2], circs[i,3:4], circs[i,5:6])]
d = solve(eqs)[1]
(x=float(d[h]), y=float(d[k]), r=float(d[r]))
end
c₀, cs... = solve_i.(16:-1:1) # c₀ is centered
# solve for center of circle, radius for each
@syms h::positive k::positive r::positive
function solve_i(i)
eqs = [(p[1] - h)^2 + (p[2]-k)^2 ~ r^2 for
p ∈ (circs[i,1:2], circs[i,3:4], circs[i,5:6])]
d = solve(eqs)[1]
(x=float(d[h]), y=float(d[k]), r=float(d[r]))
end
c₀, cs... = solve_i.(16:-1:1) # c₀ is centered
function duchamp_rotorelief_10(θ)
p = plot(legend=false,
axis=nothing, xaxis=false, yaxis=false,
aspect_ratio=:equal)
function duchamp_rotorelief_10(θ)
p = plot(legend=false,
axis=nothing, xaxis=false, yaxis=false,
aspect_ratio=:equal)
O = [c₀.x, c₀.y]
θ̂ = [cos(θ), sin(θ)]
O = [c₀.x, c₀.y]
θ̂ = [cos(θ), sin(θ)]
circle!(O, c₀.r, # outer ring is c₀
linewidth=2,
color=grey, fill=white,
seriestype=:shape)
circle!(O, c₀.r, # outer ring is c₀
linewidth=2,
color=grey, fill=white,
seriestype=:shape)
for (i,c) ∈ enumerate(cs) # add nested rings
rᵢ = sqrt((c₀.x - c.x)^2+(c₀.y - c.y)^2)
P = O + rᵢ * θ̂ # rotate about origin by θ
circle!(P, c.r,
linewidth = i == 1 ? 1 : i <= 3 ? 2 : 3,
color=greenblue)
end
p
for (i,c) ∈ enumerate(cs) # add nested rings
rᵢ = sqrt((c₀.x - c.x)^2+(c₀.y - c.y)^2)
P = O + rᵢ * θ̂ # rotate about origin by θ
circle!(P, c.r,
linewidth = i == 1 ? 1 : i <= 3 ? 2 : 3,
color=greenblue)
end
p
# animate using Plots.@animate macro
anim = @animate for θ ∈ range(0, -2π, length=60)
duchamp_rotorelief_10(θ)
end
fname = tempname() * ".gif"
gif(anim, fname, fps = 40)
end
```
# animate using Plots.@animate macro
anim = @animate for θ ∈ range(0, -2π, length=60)
duchamp_rotorelief_10(θ)
end
fname = tempname() * ".gif"
gif(anim, fname, fps = 40)
PlutoUI.LocalResource(fname) # to display w/in Pluto
```julia; echo=false
#import PlutoUI
#PlutoUI.LocalResource(fname) # to display w/in Pluto
nothing
```
##### Example
@ -1279,6 +1290,7 @@ ts = range(t_span..., length=1001)
surface(unzip(r_0.(ts, θs'))...)
```
## Arc length
In [Arc length](../integrals/arc_length.html) there is a discussion of how to find the arc length of a parameterized curve in ``2`` dimensions. The general case is discussed by [Destafano](https://randomproofs.files.wordpress.com/2010/11/arc_length.pdf) who shows:
@ -1456,7 +1468,8 @@ Here, when $b$ gets large, the curve looks more and more "straight" and the tors
[Levi and Tabachnikov](https://projecteuclid.org/download/pdf_1/euclid.em/1259158427) consider the trajectories of the front and rear bicycle wheels. Recall the notation previously used: $\vec{F}(t)$ for the front wheel, and $\vec{B}(t)$ for the rear wheel trajectories. Consider now their parameterization by arc length, using $u$ for the arc-length parameter for $\vec{F}$ and $v$ for $\vec{B}$. We define $\alpha(u)$ to be the steering angle of the bicycle. This can be found as the angle between the tangent vector of the path of $\vec{F}$ with the vector $\vec{B} - \vec{F}$. Let $\kappa$ be the curvature of the front wheel and $k$ the curvature of the back wheel.
```julia; hold=true; echo=false
```julia; echo=false
let
a = 1
F(t) = [cos(pi/2 - t), 2sin(pi/2-t)]
p = (a, F)
@ -1486,6 +1499,7 @@ annotate!([(-.5,1.5,L"k"),
(.85, 1.3, L"\alpha")])
plt
end
```
Levi and Tabachnikov prove in their Proposition 2.4:
@ -1510,10 +1524,12 @@ when a curve is parameterized by arc length, the curvature is more directly comp
The tangent vector is of unit length, when parametrized by arc length. This implies its derivative will be orthogonal. If $\vec{r}(t)$ is a parameterization by arc length, then the curvature formula simplifies as:
```math
\kappa(s) = \frac{\| \vec{r}'(s) \times \vec{r}''(s) \|}{\|\vec{r}'(s)\|^3} =
\frac{\| \vec{r}'(s) \times \vec{r}''(s) \|}{1} =
\| \vec{r}'(s) \| \| \vec{r}''(s) \| \sin(\theta) =
1 \| \vec{r}''(s) \| 1 = \| \vec{r}''(s) \|.
\begin{align*}
\kappa(s) &= \frac{\| \vec{r}'(s) \times \vec{r}''(s) \|}{\|\vec{r}'(s)\|^3} \\
&= \frac{\| \vec{r}'(s) \times \vec{r}''(s) \|}{1} \\
&= \| \vec{r}'(s) \| \| \vec{r}''(s) \| \sin(\theta) \\
&= 1 \| \vec{r}''(s) \| 1 = \| \vec{r}''(s) \|.
\end{align*}
```
@ -1867,24 +1883,27 @@ Let ``r`` be the radius of a circle and for concreteness we position it at ``(-r
* Between angles ``\pi/2`` and until the horse's ``y`` position is ``0`` when the tether is taut the boundary of what can be eaten is described by the involute.
* The horse can't eat from withing the circle or radius ``r``.
```julia; hold=true; echo=false
r,R = 1, 10
R = max(R, pi*r) # R ≥ 1/2 circumference
```julia; echo=false
let
r,R = 1, 10
R = max(R, pi*r) # R ≥ 1/2 circumference
γ(θ) = -2r*cos(θ) * [cos(θ), sin(θ)] # parameterize the circle of radius r
involute(t) = γ(t) + γ'(t)/norm(γ'(t))* (R - quadgk(u -> norm(γ'(u)), pi/2, t)[1])
t₀ = find_zero(t -> round(involute(t)[2], digits=4), (3pi/4, pi))
γ(θ) = -2r*cos(θ) * [cos(θ), sin(θ)] # parameterize the circle of radius r
involute(t) = γ(t) + γ'(t)/norm(γ'(t))* (R - quadgk(u -> norm(γ'(u)), pi/2, t)[1])
t₀ = find_zero(t -> round(involute(t)[2], digits=4), (3pi/4, pi))
p = plot(; legend=false)
plot_polar!(0..(pi/2), t -> R) # unobstructed -> quarter circle
plot_parametric!((pi/2)..t₀, involute)
plot_parametric!((pi/2)..pi, γ)
plot!([0,R],[0,0])
p = plot(; legend=false)
plot_polar!(0..(pi/2), t -> R) # unobstructed -> quarter circle
plot_parametric!((pi/2)..t₀, involute)
plot_parametric!((pi/2)..pi, γ)
plot!([0,R],[0,0])
end
```
To solve for the area we parameterize the circle of radius ``r`` between ``\pi/2`` and when the involute would cross the ``x`` axis. We use `find_zero` to identify the value.
```julia; hold=true
```julia
let
r,R = 160/(2π), 160
R = max(R, pi*r) # R ≥ 1/2 circumference
γ(θ) = -2r*cos(θ) * [cos(θ), sin(θ)]
@ -1899,6 +1918,7 @@ x(t) = (h=1e-4; (involute(t+h)[1]-involute(t-h)[1])/(2h))
A₂ = quadgk(t -> -y(t)*x(t), pi/2, t₀)[1] # A₂ = -∫ y dx, as counterclockwise parameterization
A₃ = (1/2) * π * r^2
2 * (A₁ + A₂ - A₃)
end
```
The calculation for ``A_1`` and ``A_3`` are from the familiar formula for the area of a circle. However, ``A_2`` requires the formula for area above the ``x`` axis when the curve is parameterized: ``A = -\int_a^b y(t) x'(t) dt``, given how the curve is parameterized. As written, the automatic derivative of the numeric integral gives an error, so a central-difference approximation is used for ``x'(t)``.
@ -1920,8 +1940,8 @@ choices = [
q"[0.0782914, 0.292893 ]",
q"[0.181172, 0.5]",
q"[0.570796, 1.0]"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
And the position at $\pi/2$?
@ -1932,8 +1952,8 @@ choices = [
q"[0.0782914, 0.292893 ]",
q"[0.181172, 0.5]",
q"[0.570796, 1.0]"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -1946,8 +1966,8 @@ choices = [
" ``\\langle Rt - R\\sin(t),~ R - R\\cos(t) \\rangle``",
" ``\\langle -r\\sin(t),~ -r\\cos(t) \\rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1961,8 +1981,8 @@ choices = [
" ``1 - \\cos(t)``",
" ``1 + \\cos(t) + \\cos(2t)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1995,8 +2015,8 @@ q"[1,1]",
q"[2,0]",
q"[0,0]"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
What is the derivative at $t=\pi$?
@ -2008,8 +2028,8 @@ q"[1,1]",
q"[2,0]",
q"[0,0]"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -2023,8 +2043,8 @@ choices = [
" ``R``",
" ``R^2``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -2053,8 +2073,8 @@ choices = [
" ``1``",
" ``t + t^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Numerically find the arc length.
@ -2089,8 +2109,8 @@ choices = [
"greater than the curvature at ``t=0``",
"less than the curvature at ``t=0``",
"the same as the curvature at ``t=0``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
The curvature as $t\rightarrow \infty$ will be
@ -2101,8 +2121,8 @@ choices = [
" ``\\infty``",
" ``1``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
----
@ -2116,8 +2136,8 @@ choices = [
" ``2``",
" ``1``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -2132,8 +2152,8 @@ x0 = [0,0,5]
v0 = [120, -2, 2]
a = [0, 16, -32]
r(t) = x0 + v0*t + 1/2*a*t^2
ans = 60/v0[1]
numericq(ans)
answ = 60/v0[1]
numericq(answ)
```
At $t=1/4$ the ball is half-way to home. If the batter reads the ball at this point, where in the $y$ direction is the ball?
@ -2144,8 +2164,8 @@ v0 = [120, -2, 2]
a = [0, 16, -32]
r(t) = x0 + v0*t + 1/2*a*t^2
t = 1/4
ans = r(t)[2]
numericq(ans)
answ = r(t)[2]
numericq(answ)
```
At $t=1/2$ has the ball moved more than ``1/2`` foot in the $y$ direction?
@ -2156,8 +2176,8 @@ v0 = [120, -2, 2]
a = [0, 16, -32]
r(t) = x0 + v0*t + 1/2*a*t^2
t = 1/2
ans = abs(r(t)[2]) > 1/2
yesnoq(ans)
answ = abs(r(t)[2]) > 1/2
yesnoq(answ)
```
@ -2201,8 +2221,8 @@ choices = [
" ``2\\tan(\\theta)``",
" ``\\tan(\\theta)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Using the polar form of a circle, the length between the origin and $B$ is given by $2\cos(\theta-\pi/2) = 2\sin(\theta)$. Using this, what is the $y$ coordinate of $B$?
@ -2214,8 +2234,8 @@ choices = [
" ``2``",
" ``\\sin(\\theta)``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -2229,8 +2249,8 @@ choices = [
" ``t^n + t^{n+1}``",
" ``\\sqrt{n^2 + t^2}``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
For $n=2$, the arc length of $\vec{r}$ can be found exactly. What is the arc-length between $0 \leq t \leq a$?
@ -2241,8 +2261,8 @@ choices = [
" ``\\frac{2 a^{\\frac{5}{2}}}{5}``",
" ``\\sqrt{a^2 + 4}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -2257,30 +2277,32 @@ choices = [
" ``\\pi/2``",
" ``2``"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
```julia; hold=true; echo=false
t0, t1 = pi/12, pi/3
tspan = (t0, t1) # time span to consider
```julia; echo=false
let
t0, t1 = pi/12, pi/3
tspan = (t0, t1) # time span to consider
a = 1
r(theta) = -cos(theta) + 4*2cos(theta)*sin(theta)^2
F(t) = r(t) * [cos(t), sin(t)]
p = (a, F) # combine parameters
a = 1
r(theta) = -cos(theta) + 4*2cos(theta)*sin(theta)^2
F(t) = r(t) * [cos(t), sin(t)]
p = (a, F) # combine parameters
B0 = F(0) - [0, a] # some initial position for the back
prob = ODEProblem(bicycle, B0, tspan, p)
B0 = F(0) - [0, a] # some initial position for the back
prob = ODEProblem(bicycle, B0, tspan, p)
out = solve(prob, reltol=1e-6, Tsit5())
out = solve(prob, reltol=1e-6, Tsit5())
plt = plot(unzip(F, t0, t1)..., legend=false, color=:red)
plot!(plt, unzip(t->out(t), t0, t1)..., color=:blue)
plt = plot(unzip(F, t0, t1)..., legend=false, color=:red)
plot!(plt, unzip(t->out(t), t0, t1)..., color=:blue)
end
```
@ -2291,8 +2313,8 @@ choices = [
"The front wheel",
"The back wheel"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -2300,22 +2322,24 @@ radioq(choices, ans)
###### Question
```julia; hold=true; echo=false
t0, t1 = 0.0, pi/3
tspan = (t0, t1) # time span to consider
```julia; echo=false
let
t0, t1 = 0.0, pi/3
tspan = (t0, t1) # time span to consider
a = 1
r(t) = 3a * cos(2t)cos(t)
F(t) = r(t) * [cos(t), sin(t)]
p = (a, F) # combine parameters
a = 1
r(t) = 3a * cos(2t)cos(t)
F(t) = r(t) * [cos(t), sin(t)]
p = (a, F) # combine parameters
B0 = F(0) - [0, a] # some initial position for the back
prob = ODEProblem(bicycle, B0, tspan, p)
B0 = F(0) - [0, a] # some initial position for the back
prob = ODEProblem(bicycle, B0, tspan, p)
out = solve(prob, reltol=1e-6, Tsit5())
out = solve(prob, reltol=1e-6, Tsit5())
plt = plot(unzip(F, t0, t1)..., legend=false, color=:blue)
plot!(plt, unzip(t->out(t), t0, t1)..., color=:red)
plt = plot(unzip(F, t0, t1)..., legend=false, color=:blue)
plot!(plt, unzip(t->out(t), t0, t1)..., color=:red)
end
```
@ -2326,8 +2350,8 @@ choices = [
"The front wheel",
"The back wheel"
]
ans=2
radioq(choices, ans)
answ=2
radioq(choices, answ)
```
@ -2357,8 +2381,8 @@ If a car is on a straight road, then $\kappa=0$. Is the acceleration along the $
choices = [
"The ``\\hat{T}`` direction",
"The ``\\hat{N}`` direction"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Suppose no gas or brake is applied for a duration of time. The tangential acceleration will be $0$. During this time, which of these must be $0$?
@ -2369,8 +2393,8 @@ choices = [
" ``ds/dt``",
" ``d^2s/dt^2``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
In going around a corner (with non-zero curvature), which is true?
@ -2381,8 +2405,8 @@ choices = [
"The acceleration in the normal direction depends only on the curvature and not the speed (``ds/dt``)",
"The acceleration in the normal direction depends only on the speed (``ds/dt``) and not the curvature"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -2409,8 +2433,8 @@ choices = [
" ``1 + 2t``",
" ``1 - 2t``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
* Compute $k(t)$
@ -2422,8 +2446,8 @@ choices = [
" ``8t``",
" ``-8t``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
* Compute $X(t)$
@ -2435,8 +2459,8 @@ choices = [
" ``t - 2(8t)/(1-2t)``",
" ``t - 1(1+4t^2)/2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
* Compute $Y(t)$
@ -2448,8 +2472,8 @@ choices = [
" ``t^2 - 1(1+4t^2)/2``",
" ``t^2 - 2t(1+4t^2)/2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -2477,6 +2501,6 @@ choices = [
"An ellipse of the form ``\\langle a\\cos(t), b\\sin(t)``",
"A cyloid of the form ``c\\langle t + \\sin(t), 1 - \\cos(t)\\rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -363,9 +363,9 @@ Starting with three vectors, we can create three orthogonal vectors using projec
Let's begin with three vectors in $R^3$:
```julia;
u = [1, 2, 3]
v = [1, 1, 2]
w = [1, 2, 4]
u = [1, 2, 3]
v = [1, 1, 2]
w = [1, 2, 4]
```
We can find a vector from `v` orthogonal to `u` using:
@ -374,14 +374,14 @@ We can find a vector from `v` orthogonal to `u` using:
unit_vec(u) = u / norm(u)
projection(u, v) = (u ⋅ unit_vec(v)) * unit_vec(v)
v⃗⟂ = v⃗ - projection(v⃗, u⃗)
w⃗⟂ = w⃗ - projection(w⃗, u⃗) - projection(w⃗, v⃗⟂)
vₚ = v - projection(v, u)
wₚ = w - projection(w, u) - projection(w, vₚ)
```
We can verify the orthogonality through:
```julia;
u⃗ ⋅ v⃗⟂, u⃗ ⋅ w⃗⟂, v⃗⟂ ⋅ w⃗⟂
u ⋅ vₚ, u ⋅ wₚ, vₚ ⋅ wₚ
```
This only works when the three vectors do not all lie in the same plane. In general, this is the beginning of the [Gram-Schmidt](https://en.wikipedia.org/wiki/Gram-Schmidt_process) process for creating *orthogonal* vectors from a collection of vectors.
@ -839,11 +839,8 @@ The volume of a parallelepiped is the area of a base parallelogram times the hei
that is, the area of the parallelepiped. Wait, what about $(\vec{v}\times\vec{u})\cdot\vec{w}$? That will have an opposite sign. Yes, in the above, there is an assumption that $\vec{n}$ and $\vec{w}$ have a an angle between them within $[0, \pi/2]$, otherwise an absolute value must be used, as volume is non-negative.
```julia; echo=false
note(L"""
The triple-scalar product, $\vec{u}\cdot(\vec{v}\times\vec{w})$, gives the volume of the parallelepiped up to sign. If the sign of this is positive, the ``3`` vectors are said to have a *positive* orientation, if the triple-scalar product is negative, the vectors have a *negative* orientation.
""", title="Orientation")
```
!!! note "Orientation"
The triple-scalar product, $\vec{u}\cdot(\vec{v}\times\vec{w})$, gives the volume of the parallelepiped up to sign. If the sign of this is positive, the ``3`` vectors are said to have a *positive* orientation, if the triple-scalar product is negative, the vectors have a *negative* orientation.
#### Algebraic properties
@ -1046,8 +1043,8 @@ Are `v` and `w` orthogonal?
```julia; hold=true; echo=false
u,v,w = [1,2,3], [4,3,2], [5,2,1]
ans = dot(v,w) == 0
yesnoq(ans)
answ = dot(v,w) == 0
yesnoq(answ)
```
Find the angle between `u` and `w`:
@ -1068,8 +1065,8 @@ choices = [
"`[-1, 6, -7]`",
"`[-4, 14, -8]`"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Find the area of the parallelogram formed by `v` and `w`
@ -1114,8 +1111,8 @@ choices = [
"An object of type `Base.Iterators.Zip` that is only realized when used",
"A vector of values `[(1, 5), (2, 4), (3, 2)]`"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
What does `prod.(zip(u,v))` return?
@ -1125,8 +1122,8 @@ choices = [
"A vector of values `[5, 8, 6]`",
"An object of type `Base.Iterators.Zip` that when realized will produce a vector of values"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1143,8 +1140,8 @@ choices = [
"``0``",
"Can't say in general"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1167,8 +1164,8 @@ choices = [
"``x + 2y + z = 0``",
"``x + 2y + 3z = 6``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1181,8 +1178,8 @@ choices = [
" ``\\vec{v}`` is in plane ``P_1``, as it is orthogonal to ``\\vec{n}_1`` and ``P_2`` as it is orthogonal to ``\\vec{n}_2``, hence it is parallel to both planes.",
" ``\\vec{n}_1`` and ``\\vec{n_2}`` are unit vectors, so the cross product gives the projection, which must be orthogonal to each vector, hence in the intersection"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1195,8 +1192,8 @@ choices = [
"``\\langle 12, 12 \\rangle``",
"``12 \\langle 1, 0 \\rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
If the vector to 3 o'clock is removed, (call this $\langle 1, 0 \rangle$) what expresses the sum of *all* the remaining vectors?
@ -1207,8 +1204,8 @@ choices = [
"``\\langle 1, 0 \\rangle``",
"``\\langle 11, 11 \\rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1221,8 +1218,8 @@ choices = [
"``\\vec{u} + \\vec{v}``",
"``\\vec{u}\\cdot\\vec{v} + \\vec{v}\\cdot \\vec{v}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
As the two are equal, which interpretation is true?
@ -1233,8 +1230,8 @@ choices = [
"The vector ``\\vec{w}`` must also be a unit vector",
"the two are orthogonal"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -1251,8 +1248,8 @@ choices = [
"``\\vec{u}\\cdot\\vec{v} = 2``",
"``\\vec{u}\\cdot\\vec{v} = -(\\vec{u}\\cdot\\vec{u} \\vec{v}\\cdot\\vec{v})``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1274,8 +1271,8 @@ choices = [
"The vectors are *orthogonal*, so these are all zero",
"The vectors are all unit lengths, so these are all 1"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1311,8 +1308,8 @@ choices = [
"``n_1 (\\hat{v_1}\\times\\hat{N}) = n_2 (\\hat{v_2}\\times\\hat{N})``",
"``n_1 (\\hat{v_1}\\times\\hat{N}) = -n_2 (\\hat{v_2}\\times\\hat{N})``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1334,6 +1331,6 @@ choices = [
"``\\vec{a}``",
"``\\vec{a} + \\vec{b} + \\vec{c}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -62,10 +62,10 @@ nothing
The gradient of a scalar function $f:R^n \rightarrow R$ is a vector field of partial derivatives. In $R^2$, we have:
$$~
```math
\nabla{f} = \langle \frac{\partial{f}}{\partial{x}},
\frac{\partial{f}}{\partial{y}} \rangle.
~$$
```
It has the interpretation of pointing out the direction of greatest ascent for the surface $z=f(x,y)$.
@ -113,15 +113,15 @@ p
Consider the sides with outward normal $\hat{i}$. The contribution to the surface integral, $\oint_S (F\cdot\hat{N})dS$, could be *approximated* by
$$~
```math
\left(F(x + \Delta x, y, z) \cdot \hat{i}\right) \Delta y \Delta z,
~$$
```
whereas, the contribution for the face with outward normal $-\hat{i}$ could be approximated by:
$$~
```math
\left(F(x, y, z) \cdot (-\hat{i}) \right) \Delta y \Delta z.
~$$
```
The functions are being evaluated at a point on the face of the
surface. For Riemann integrable functions, any point in a partition
@ -129,11 +129,11 @@ may be chosen, so our choice will not restrict the generality.
The total contribution of the two would be:
$$~
```math
\left(F(x + \Delta x, y, z) \cdot \hat{i}\right) \Delta y \Delta z +
\left(F(x, y, z) \cdot (-\hat{i})\right) \Delta y \Delta z =
\left(F_x(x + \Delta x, y, z) - F_x(x, y, z)\right) \Delta y \Delta z,
~$$
```
as $F \cdot \hat{i} = F_x$.
@ -142,11 +142,11 @@ as $F \cdot \hat{i} = F_x$.
If this is repeated for the other two pair of matching faces, we get a definition for the *divergence*:
> The *divergence* of a vector field $F:R^3 \rightarrow R^3$ is given by
> $$~
> ```math
> \text{divergence}(F) =
> \lim \frac{1}{\Delta V} \oint_S F\cdot\hat{N} dS =
> \frac{\partial{F_x}}{\partial{x}} +\frac{\partial{F_y}}{\partial{y}} +\frac{\partial{F_z}}{\partial{z}}.
> ~$$
> ```
The limit expression for the divergence will hold for any smooth closed surface, $S$, converging on $(x,y,z)$, not just box-like ones.
@ -155,9 +155,9 @@ The limit expression for the divergence will hold for any smooth closed surface,
The derivation of the divergence is done for $n=3$, but could also have easily been done for two dimensions ($n=2$) or higher dimensions $n>3$. The formula in general would be: for $F(x_1, x_2, \dots, x_n): R^n \rightarrow R^n$:
$$~
```math
\text{divergence}(F) = \sum_{i=1}^n \frac{\partial{F_i}}{\partial{x_i}}.
~$$
```
----
@ -198,7 +198,7 @@ annotate!([
Let $F=\langle F_x, F_y\rangle$. For small enough values of $\Delta{x}$ and $\Delta{y}$ the line integral, $\oint_C F\cdot d\vec{r}$ can be *approximated* by $4$ terms:
$$~
```math
\begin{align}
\left(F(x,y) \cdot \hat{i}\right)\Delta{x} &+
\left(F(x+\Delta{x},y) \cdot \hat{j}\right)\Delta{y} +
@ -211,15 +211,15 @@ F_x(x, y+\Delta{y}) (-\Delta{x}) + F_y(x,y) (-\Delta{y})\\
(F_y(x + \Delta{x}, y) - F_y(x, y))\Delta{y} -
(F_x(x, y+\Delta{y})-F_x(x,y))\Delta{x}.
\end{align}
~$$
```
The Riemann approximation allows a choice of evaluation point for Riemann integrable functions, and the choice here lends itself to further analysis.
Were the above divided by $\Delta{x}\Delta{y}$, the area of the box, and a limit taken, partial derivatives appear to suggest this formula:
$$~
```math
\lim \frac{1}{\Delta{x}\Delta{y}} \oint_C F\cdot d\vec{r} =
\frac{\partial{F_y}}{\partial{x}} - \frac{\partial{F_x}}{\partial{y}}.
~$$
```
The scalar function on the right hand side is called the (two-dimensional) curl of $F$ and the left-hand side lends itself as a measure of the microscopic circulation of the vector field, $F:R^2 \rightarrow R^2$.
@ -303,31 +303,36 @@ p
Now we compute the *line integral*. Consider the top face, $S_1$, connecting $(x,y,z+\Delta z), (x + \Delta x, y, z + \Delta z), (x + \Delta x, y + \Delta y, z + \Delta z), (x, y + \Delta y, z + \Delta z)$, Using the *right hand rule*, parameterize the boundary curve, $C_1$, in a counter clockwise direction so the right hand rule yields the outward pointing normal ($\hat{k}$). Then the integral $\oint_{C_1} F\cdot \hat{T} ds$ is *approximated* by the following Riemann sum of $4$ terms:
$$~
F(x,y, z+\Delta{z}) \cdot \hat{i}\Delta{x} +
F(x+\Delta x, y, z+\Delta{z}) \cdot \hat{j} \Delta y +
F(x, y+\Delta y, z+\Delta{z}) \cdot (-\hat{i}) \Delta{x} +
F(x, y, z+\Delta{z}) \cdot (-\hat{j}) \Delta{y}.
~$$
```math
\begin{align*}
F(x,y, z+\Delta{z}) \cdot \hat{i}\Delta{x} &+ F(x+\Delta x, y, z+\Delta{z}) \cdot \hat{j} \Delta y \\
&+ F(x, y+\Delta y, z+\Delta{z}) \cdot (-\hat{i}) \Delta{x} \\
&+ F(x, y, z+\Delta{z}) \cdot (-\hat{j}) \Delta{y}.
\end{align*}
```
(The points $c_i$ are chosen from the endpoints of the line segments.)
$$~
\oint_{C_1} F\cdot \hat{T} ds \approx
(F_y(x+\Delta x, y, z+\Delta{z}) - F_y(x, y, z+\Delta{z})) \Delta{y} -
(F_x(x,y + \Delta{y}, z+\Delta{z}) - F_x(x, y, z+\Delta{z})) \Delta{x}
~$$
```math
\begin{align*}
\oint_{C_1} F\cdot \hat{T} ds
&\approx (F_y(x+\Delta x, y, z+\Delta{z}) \\
&- F_y(x, y, z+\Delta{z})) \Delta{y} \\
&- (F_x(x,y + \Delta{y}, z+\Delta{z}) \\
&- F_x(x, y, z+\Delta{z})) \Delta{x}
\end{align*}
```
As before, were this divided by the *area* of the surface, we have after rearranging and cancellation:
$$~
\frac{1}{\Delta{S_1}} \oint_{C_1} F \cdot \hat{T} ds \approx
\frac{F_y(x+\Delta x, y, z+\Delta{z}) - F_y(x, y, z+\Delta{z})}{\Delta{x}}
-
\frac{F_x(x, y+\Delta y, z+\Delta{z})-F_x(x, y, z+\Delta{z})}{\Delta{y}}.
~$$
```math
\begin{align*}
\frac{1}{\Delta{S_1}} \oint_{C_1} F \cdot \hat{T} ds &\approx
\frac{F_y(x+\Delta x, y, z+\Delta{z}) - F_y(x, y, z+\Delta{z})}{\Delta{x}}\\
&- \frac{F_x(x, y+\Delta y, z+\Delta{z}) - F_x(x, y, z+\Delta{z})}{\Delta{y}}.
\end{align*}
```
In the limit, as $\Delta{S} \rightarrow 0$, this will converge to $\partial{F_y}/\partial{x}-\partial{F_x}/\partial{y}$.
@ -336,56 +341,56 @@ Had the bottom of the box been used, a similar result would be found, up to a mi
Unlike the two dimensional case, there are other directions to consider and here
the other sides will yield different answers. Consider now the face connecting $(x,y,z), (x+\Delta{x}, y, z), (x+\Delta{x}, y, z + \Delta{z})$, and $ (x,y,z+\Delta{z})$ with outward pointing normal $-\hat{j}$. Let $S_2$ denote this face and $C_2$ describe its boundary. Orient this curve so that the right hand rule points in the $-\hat{j}$ direction (the outward pointing normal). Then, as before, we can approximate:
$$~
\begin{align}
```math
\begin{align*}
\oint_{C_2} F \cdot \hat{T} ds
&\approx
F(x,y,z) \cdot \hat{i} \Delta{x} +
F(x+\Delta{x},y,z) \cdot \hat{k} \Delta{z} +
F(x,y,z+\Delta{z}) \cdot (-\hat{i}) \Delta{x} +
F(x, y, z) \cdot (-\hat{k}) \Delta{z}\\
F(x,y,z) \cdot \hat{i} \Delta{x} \\
&+ F(x+\Delta{x},y,z) \cdot \hat{k} \Delta{z} \\
&+ F(x,y,z+\Delta{z}) \cdot (-\hat{i}) \Delta{x} \\
&+ F(x, y, z) \cdot (-\hat{k}) \Delta{z}\\
&= (F_z(x+\Delta{x},y,z) - F_z(x, y, z))\Delta{z} -
(F_x(x,y,z+\Delta{z}) - F(x,y,z)) \Delta{x}.
\end{align}
~$$
\end{align*}
```
Dividing by $\Delta{S}=\Delta{x}\Delta{z}$ and taking a limit will give:
$$~
```math
\lim \frac{1}{\Delta{S}} \oint_{C_2} F \cdot \hat{T} ds =
\frac{\partial{F_z}}{\partial{x}} - \frac{\partial{F_x}}{\partial{z}}.
~$$
```
Had, the opposite face with outward normal $\hat{j}$ been chosen, the answer would differ by a factor of $-1$.
Similarly, let $S_3$ be the face with outward normal $\hat{i}$ and curve $C_3$ bounding it with parameterization chosen so that the right hand rule points in the direction of $\hat{i}$. This will give
$$~
```math
\lim \frac{1}{\Delta{S}} \oint_{C_3} F \cdot \hat{T} ds =
\frac{\partial{F_z}}{\partial{y}} - \frac{\partial{F_y}}{\partial{z}}.
~$$
```
In short, depending on the face chosen, a different answer is given, but all have the same type.
> Define the *curl* of a $3$-dimensional vector field $F=\langle F_x,F_y,F_z\rangle$ by:
> $$~
> ```math
> \text{curl}(F) =
> \langle \frac{\partial{F_z}}{\partial{y}} - \frac{\partial{F_y}}{\partial{z}},
> \frac{\partial{F_x}}{\partial{z}} - \frac{\partial{F_z}}{\partial{x}},
> \frac{\partial{F_y}}{\partial{x}} - \frac{\partial{F_x}}{\partial{y}} \rangle.
> ~$$
> ```
If $S$ is some surface with closed boundary $C$ oriented so that the unit normal, $\hat{N}$, of $S$ is given by the right hand rule about $C$, then
$$~
```math
\hat{N} \cdot \text{curl}(F) = \lim \frac{1}{\Delta{S}} \oint_C F \cdot \hat{T} ds.
~$$
```
The curl has a formal representation in terms of a $3\times 3$ determinant, similar to that used to compute the cross product, that is useful for computation:
$$~
```math
\text{curl}(F) = \det\left[
\begin{array}{}
\hat{i} & \hat{j} & \hat{k}\\
@ -393,7 +398,7 @@ $$~
F_x & F_y & F_z
\end{array}
\right]
~$$
```
----
@ -419,18 +424,18 @@ curl(F::Function, pt) = curl(ForwardDiff.jacobian(F, pt))
The divergence, gradient, and curl all involve partial derivatives. There is a notation employed that can express the operations more succinctly. Let the [Del operator](https://en.wikipedia.org/wiki/Del) be defined in Cartesian coordinates by the formal expression:
> $$~
> ```math
> \nabla = \langle
> \frac{\partial}{\partial{x}},
> \frac{\partial}{\partial{y}},
> \frac{\partial}{\partial{z}}
> \rangle.
> ~$$
> ```
This is a *vector differential operator* that acts on functions and vector fields through the typical notation to yield the three operations:
$$~
\begin{align}
```math
\begin{align*}
\nabla{f} &= \langle
\frac{\partial{f}}{\partial{x}},
\frac{\partial{f}}{\partial{y}},
@ -440,13 +445,15 @@ $$~
\frac{\partial}{\partial{x}},
\frac{\partial}{\partial{y}},
\frac{\partial}{\partial{z}}
\rangle \cdot F =
\rangle \cdot F \\
&=
\langle
\frac{\partial}{\partial{x}},
\frac{\partial}{\partial{y}},
\frac{\partial}{\partial{z}}
\rangle \cdot
\langle F_x, F_y, F_z \rangle =
\langle F_x, F_y, F_z \rangle \\
&=
\frac{\partial{F_x}}{\partial{x}} +
\frac{\partial{F_y}}{\partial{y}} +
\frac{\partial{F_z}}{\partial{z}},\quad\text{the divergence;}\\
@ -464,15 +471,12 @@ $$~
F_x & F_y & F_z
\end{array}
\right],\quad\text{the curl}.
\end{align}
~$$
```julia; echo=false
note("""
Mathematically operators have not been seen previously, but the concept of an operation on a function that returns another function is a common one when using `Julia`. We have seen many examples (`plot`, `D`, `quadgk`, etc.). In computer science such functions are called *higher order* functions, as they accept arguments which are also functions.
""")
\end{align*}
```
!!! note
Mathematically operators have not been seen previously, but the concept of an operation on a function that returns another function is a common one when using `Julia`. We have seen many examples (`plot`, `D`, `quadgk`, etc.). In computer science such functions are called *higher order* functions, as they accept arguments which are also functions.
----
In the `CalculusWithJulia` package, the constant `\nabla[\tab]`, producing $\nabla$ implements this operator for functions and symbolic expressions.
@ -543,11 +547,9 @@ There is a subtle difference in usage. Symbolically the evaluation of
function evaluation, parentheses must be used in the numeric case.
```julia; echo=false
note("""
As mentioned, for the symbolic evaluations, a specification of three variables (here `x`, `y`, and `z`) is necessary. This use takes `free_symbols` to identify three free symbols which may not always be the case. (It wouldn't be for, say, `F(x,y,z) = [a*x,b*y,0]`, `a` and `b` constants.) In those cases, the notation accepts a tuple to specify the function or vector field and the variables, e.g. (`∇( (f(x,y,z), [x,y,z]) )`, as illustrated; `∇ × (F(x,y,z), [x,y,z])`; or `∇ ⋅ (F(x,y,z), [x,y,z])` where this is written using function calls to produce the symbolic expression in the first positional argument, though a direct expression could also be used. In these cases, the named versions `gradient`, `curl`, and `divergence` may be preferred.
""")
```
!!! note
As mentioned, for the symbolic evaluations, a specification of three variables (here `x`, `y`, and `z`) is necessary. This use takes `free_symbols` to identify three free symbols which may not always be the case. (It wouldn't be for, say, `F(x,y,z) = [a*x,b*y,0]`, `a` and `b` constants.) In those cases, the notation accepts a tuple to specify the function or vector field and the variables, e.g. (`∇( (f(x,y,z), [x,y,z]) )`, as illustrated; `∇ × (F(x,y,z), [x,y,z])`; or `∇ ⋅ (F(x,y,z), [x,y,z])` where this is written using function calls to produce the symbolic expression in the first positional argument, though a direct expression could also be used. In these cases, the named versions `gradient`, `curl`, and `divergence` may be preferred.
@ -588,9 +590,9 @@ p
Consider the limit definition of the divergence:
$$~
```math
\nabla\cdot{F} = \lim \frac{1}{\Delta{V}} \oint_S F\cdot\hat{N} dA.
~$$
```
In the vector field above, the shape along the curved edges has constant magnitude field. On the left curved edge, the length is smaller and the field is smaller than on the right. The flux across the left edge will be less than the flux across the right edge, and a net flux will exist. That is, there is divergence.
@ -747,37 +749,37 @@ Let $f$ and $g$ denote scalar functions, $R^3 \rightarrow R$ and $F$ and $G$ be
As with the sum rule of univariate derivatives, these operations satisfy:
$$~
```math
\begin{align}
\nabla(f + g) &= \nabla{f} + \nabla{g}\\
\nabla\cdot(F+G) &= \nabla\cdot{F} + \nabla\cdot{G}\\
\nabla\times(F+G) &= \nabla\times{F} + \nabla\times{G}.
\end{align}
~$$
```
### Product rule
The product rule $(uv)' = u'v + uv'$ has related formulas:
$$~
```math
\begin{align}
\nabla{(fg)} &= (\nabla{f}) g + f\nabla{g} = g\nabla{f} + f\nabla{g}\\
\nabla\cdot{fF} &= (\nabla{f})\cdot{F} + f(\nabla\cdot{F})\\
\nabla\times{fF} &= (\nabla{f})\times{F} + f(\nabla\times{F}).
\end{align}
~$$
```
### Rules over cross products
The cross product of two vector fields is a vector field for which the divergence and curl may be taken. There are formulas to relate to the individual terms:
$$~
```math
\begin{align}
\nabla\cdot(F \times G) &= (\nabla\times{F})\cdot G - F \cdot (\nabla\times{G})\\
\nabla\times(F \times G) &= F(\nabla\cdot{G}) - G(\nabla\cdot{F} + (G\cdot\nabla)F-(F\cdot\nabla)G\\
&= \nabla\cdot(BA^t - AB^t).
\end{align}
~$$
```
The curl formula is more involved.
### Vanishing properties
@ -785,9 +787,9 @@ The curl formula is more involved.
Surprisingly, the curl and divergence satisfy two vanishing properties. First
> The curl of a gradient field is $\vec{0}$
> $$~
> ```math
> \nabla \times \nabla{f} = \vec{0},
> ~$$
> ```
if the scalar function $f$ is has continuous second derivatives (so the mixed partials do not depend on order).
@ -800,14 +802,15 @@ The combination $\nabla\cdot\nabla{f}$ is defined and is called the Laplacian. T
Second,
> The divergence of a curl field is $0$:
>$$~
>```math
>\nabla \cdot(\nabla\times{F}) = 0.
> ~$$
> ```
This is not as clear, but can be seen algebraically as terms cancel. First:
$$~
\nabla\cdot(\nabla\times{F}) =
```math
\begin{align*}
\nabla\cdot(\nabla\times{F}) &=
\langle
\frac{\partial}{\partial{x}},
\frac{\partial}{\partial{y}},
@ -816,19 +819,20 @@ $$~
\frac{\partial{F_z}}{\partial{y}} - \frac{\partial{F_y}}{\partial{z}},
\frac{\partial{F_x}}{\partial{z}} - \frac{\partial{F_z}}{\partial{x}},
\frac{\partial{F_y}}{\partial{x}} - \frac{\partial{F_x}}{\partial{y}}
\rangle
=
\rangle \\
&=
\left(\frac{\partial^2{F_z}}{\partial{y}\partial{x}} - \frac{\partial^2{F_y}}{\partial{z}\partial{x}}\right) +
\left(\frac{\partial^2{F_x}}{\partial{z}\partial{y}} - \frac{\partial^2{F_z}}{\partial{x}\partial{y}}\right) +
\left(\frac{\partial^2{F_y}}{\partial{x}\partial{z}} - \frac{\partial^2{F_x}}{\partial{y}\partial{z}}\right)
~$$
\end{align*}
```
Focusing on one component function, $F_z$ say, we see this contribution:
$$~
```math
\frac{\partial^2{F_z}}{\partial{y}\partial{x}} -
\frac{\partial^2{F_z}}{\partial{x}\partial{y}}.
~$$
```
This is zero under the assumption that the second partial derivatives are continuous.
@ -887,12 +891,17 @@ This is because of how the line integrals are oriented so that the right-hand ru
The [invariance of charge](https://en.wikipedia.org/wiki/Maxwell%27s_equations#Charge_conservation) can be derived as a corollary of Maxwell's equation. The divergence of the curl of the magnetic field is $0$, leading to:
$$~
0 = \nabla\cdot(\nabla\times{B}) =
\mu_0(\nabla\cdot{J} + \epsilon_0 \nabla\cdot{\frac{\partial{E}}{\partial{t}}}) =
\mu_0(\nabla\cdot{J} + \epsilon_0 \frac{\partial}{\partial{t}}(\nabla\cdot{E}))
= \mu_0(\nabla\cdot{J} + \frac{\partial{\rho}}{\partial{t}}).
~$$
```mat
\begin{align*}
0 &= \nabla\cdot(\nabla\times{B}) \\
&=
\mu_0(\nabla\cdot{J} + \epsilon_0 \nabla\cdot{\frac{\partial{E}}{\partial{t}}}) \\
&=
\mu_0(\nabla\cdot{J} + \epsilon_0 \frac{\partial}{\partial{t}}(\nabla\cdot{E})) \\
&=
\mu_0(\nabla\cdot{J} + \frac{\partial{\rho}}{\partial{t}}).
\end{align*}
```
That is $\nabla\cdot{J} = -\partial{\rho}/\partial{t}$.
This says any change in the charge density in time ($\partial{\rho}/\partial{t}$) is balanced off by a divergence in the electric current density ($\nabla\cdot{J}$). That is, charge can't be created or destroyed in an isolated system.
@ -907,14 +916,14 @@ From [Wikipedia](https://en.wikipedia.org/wiki/Helmholtz_decomposition) we have
Let $F$ be a vector field on a **bounded** domain $V$ which is twice continuously differentiable. Let $S$ be the surface enclosing $V$. Then $F$ can be decomposed into a curl-free component and a divergence-free component:
$$~
```math
F = -\nabla(\phi) + \nabla\times A.
~$$
```
Without explaining why, these values can be computed using volume and
surface integrals:
$$~
```math
\begin{align}
\phi(\vec{r}') &=
\frac{1}{4\pi} \int_V \frac{\nabla \cdot F(\vec{r})}{\|\vec{r}'-\vec{r} \|} dV -
@ -922,16 +931,16 @@ $$~
A(\vec{r}') &= \frac{1}{4\pi} \int_V \frac{\nabla \times F(\vec{r})}{\|\vec{r}'-\vec{r} \|} dV +
\frac{1}{4\pi} \oint_S \frac{F(\vec{r})}{\|\vec{r}'-\vec{r} \|} \times \hat{N} dS.
\end{align}
~$$
```
If $V = R^3$, an unbounded domain, *but* $F$ *vanishes* faster than $1/r$, then the theorem still holds with just the volume integrals:
$$~
```math
\begin{align}
\phi(\vec{r}') &=\frac{1}{4\pi} \int_V \frac{\nabla \cdot F(\vec{r})}{\|\vec{r}'-\vec{r} \|} dV\\
A(\vec{r}') &= \frac{1}{4\pi} \int_V \frac{\nabla \times F(\vec{r})}{\|\vec{r}'-\vec{r}\|} dV.
\end{align}
~$$
```
## Change of variable
@ -942,7 +951,7 @@ Some details are [here](https://en.wikipedia.org/wiki/Curvilinear_coordinates),
We restrict to $n=3$ and use $(x,y,z)$ for Cartesian coordinates and $(u,v,w)$ for an *orthogonal* curvilinear coordinate system, such as spherical or cylindrical. If $\vec{r} = \langle x,y,z\rangle$, then
$$~
```math
\begin{align}
d\vec{r} &= \langle dx,dy,dz \rangle = J \langle du,dv,dw\rangle\\
&=
@ -953,55 +962,58 @@ d\vec{r} &= \langle dx,dy,dz \rangle = J \langle du,dv,dw\rangle\\
\frac{\partial{\vec{r}}}{\partial{v}} dv
\frac{\partial{\vec{r}}}{\partial{w}} dw.
\end{align}
~$$
```
The term ${\partial{\vec{r}}}/{\partial{u}}$ is tangent to the curve formed by *assuming* $v$ and $w$ are constant and letting $u$ vary. Similarly for the other partial derivatives. Orthogonality assumes that at every point, these tangent vectors are orthogonal.
As ${\partial{\vec{r}}}/{\partial{u}}$ is a vector it has a magnitude and direction. Define the scale factors as the magnitudes:
$$~
```math
h_u = \| \frac{\partial{\vec{r}}}{\partial{u}} \|,\quad
h_v = \| \frac{\partial{\vec{r}}}{\partial{v}} \|,\quad
h_w = \| \frac{\partial{\vec{r}}}{\partial{w}} \|.
~$$
```
and let $\hat{e}_u$, $\hat{e}_v$, and $\hat{e}_w$ be the unit, direction vectors.
This gives the following notation:
$$~
```math
d\vec{r} = h_u du \hat{e}_u + h_v dv \hat{e}_v + h_w dw \hat{e}_w.
~$$
```
From here, we can express different formulas.
For line integrals, we have the line element:
$$~
```math
dl = \sqrt{d\vec{r}\cdot d\vec{r}} = \sqrt{(h_ud_u)^2 + (h_vd_v)^2 + (h_wd_w)^2}.
~$$
```
Consider the surface for constant $u$. The vector $\hat{e}_v$ and $\hat{e}_w$ lie in the surface's tangent plane, and the surface element will be:
$$~
```math
dS_u = \| h_v dv \hat{e}_v \times h_w dw \hat{e}_w \| = h_v h_w dv dw \| \hat{e}_v \| = h_v h_w dv dw.
~$$
```
This uses orthogonality, so $\hat{e}_v \times \hat{e}_w$ is parallel to $\hat{e}_u$ and has unit length. Similarly, $dS_v = h_u h_w du dw$ and $dS_w = h_u h_v du dv$ .
The volume element is found by *projecting* $d\vec{r}$ onto the $\hat{e}_u$, $\hat{e}_v$, $\hat{e}_w$ coordinate system through $(d\vec{r} \cdot\hat{e}_u) \hat{e}_u$, $(d\vec{r} \cdot\hat{e}_v) \hat{e}_v$, and $(d\vec{r} \cdot\hat{e}_w) \hat{e}_w$. Then forming the triple scalar product to compute the volume of the parallelepiped:
$$~
```math
\begin{align*}
\left[(d\vec{r} \cdot\hat{e}_u) \hat{e}_u\right] \cdot
\left(
\left[(d\vec{r} \cdot\hat{e}_v) \hat{e}_v\right] \times
\left[(d\vec{r} \cdot\hat{e}_w) \hat{e}_w\right]
\right) =
(h_u h_v h_w) ( du dv dw ) (\hat{e}_u \cdot (\hat{e}_v \times \hat{e}_w) =
\right) &=
(h_u h_v h_w) ( du dv dw ) (\hat{e}_u \cdot (\hat{e}_v \times \hat{e}_w) \\
&=
h_u h_v h_w du dv dw,
~$$
\end{align*}
```
as the unit vectors are orthonormal, their triple scalar product is $1$ and $d\vec{r}\cdot\hat{e}_u = h_u du$, etc.
@ -1010,13 +1022,13 @@ as the unit vectors are orthonormal, their triple scalar product is $1$ and $d\v
We consider spherical coordinates with
$$~
```math
F(r, \theta, \phi) = \langle
r \sin(\phi) \cos(\theta),
r \sin(\phi) \sin(\theta),
r \cos(\phi)
\rangle.
~$$
```
The following figure draws curves starting at $(r_0, \theta_0, \phi_0)$ formed by holding $2$ of the $3$ variables constant. The tangent vectors are added in blue. The surface $S_r$ formed by a constant value of $r$ is illustrated.
@ -1061,7 +1073,7 @@ p
The tangent vectors found from the partial derivatives of $\vec{r}$:
$$~
```math
\begin{align}
\frac{\partial{\vec{r}}}{\partial{r}} &=
\langle \cos(\theta) \cdot \sin(\phi), \sin(\theta) \cdot \sin(\phi), \cos(\phi)\rangle,\\
@ -1070,17 +1082,19 @@ $$~
\frac{\partial{\vec{r}}}{\partial{\phi}} &=
\langle r\cdot\cos(\theta)\cdot\cos(\phi), r\cdot\sin(\theta)\cdot\cos(\phi), -r\cdot\sin(\phi) \rangle.
\end{align}
~$$
```
With this, we have $h_r=1$, $h_\theta=r\sin(\phi)$, and $h_\phi = r$. So that
$$~
dl = \sqrt{dr^2 + (r\sin(\phi)d\theta^2) + (rd\phi)^2},\quad
dS_r = r^2\sin(\phi)d\theta d\phi,\quad
dS_\theta = rdr d\phi,\quad
dS_\phi = r\sin(\phi)dr d\theta, \quad\text{and}\quad
dV = r^2\sin(\phi) drd\theta d\phi.
~$$
```math
\begin{align*}
dl &= \sqrt{dr^2 + (r\sin(\phi)d\theta^2) + (rd\phi)^2},\\
dS_r &= r^2\sin(\phi)d\theta d\phi,\\
dS_\theta &= rdr d\phi,\\
dS_\phi &= r\sin(\phi)dr d\theta, \quad\text{and}\\
dV &= r^2\sin(\phi) drd\theta d\phi.
\end{align*}
```
The following visualizes the volume and the surface elements.
@ -1132,25 +1146,27 @@ p
If $f$ is a scalar function then $df = \nabla{f} \cdot d\vec{r}$ by the chain rule. Using the curvilinear coordinates:
$$~
df =
```math
\begin{align*}
df &=
\frac{\partial{f}}{\partial{u}} du +
\frac{\partial{f}}{\partial{v}} dv +
\frac{\partial{f}}{\partial{w}} dw
=
\frac{\partial{f}}{\partial{w}} dw \\
&=
\frac{1}{h_u}\frac{\partial{f}}{\partial{u}} h_udu +
\frac{1}{h_v}\frac{\partial{f}}{\partial{v}} h_vdv +
\frac{1}{h_w}\frac{\partial{f}}{\partial{w}} h_wdw.
~$$
\end{align*}
```
But, as was used above, $d\vec{r} \cdot \hat{e}_u = h_u du$, etc. so $df$ can be re-expressed as:
$$~
```math
df = (\frac{1}{h_u}\frac{\partial{f}}{\partial{u}}\hat{e}_u +
\frac{1}{h_v}\frac{\partial{f}}{\partial{v}}\hat{e}_v +
\frac{1}{h_w}\frac{\partial{f}}{\partial{w}}\hat{e}_w) \cdot d\vec{r} =
\nabla{f} \cdot d\vec{r}.
~$$
```
The gradient is the part within the parentheses.
@ -1158,55 +1174,55 @@ The gradient is the part within the parentheses.
As an example, in cylindrical coordinates, we have $h_r =1$, $h_\theta=r$, and $h_z=1$, giving:
$$~
```math
\nabla{f} = \frac{\partial{f}}{\partial{r}}\hat{e}_r +
\frac{1}{r}\frac{\partial{f}}{\partial{\theta}}\hat{e}_\theta +
\frac{\partial{f}}{\partial{z}}\hat{e}_z
~$$
```
### The divergence in a new coordinate system
The divergence is a result of the limit of a surface integral,
$$~
```math
\nabla \cdot F = \lim \frac{1}{\Delta{V}}\oint_S F \cdot \hat{N} dS.
~$$
```
Taking $V$ as a box in the curvilinear coordinates, with side lengths $h_udu$, $h_vdv$, and $h_wdw$
the surface integral is computed by projecting $F$ onto each normal area element and multiplying by the area. The task is similar to how the the divergence was derived above, only now the terms are like $\partial{(F_uh_vh_w)}/\partial{u}$ due to the scale factors ($F_u$ is the u component of $F$.) The result is:
$$~
```math
\nabla\cdot F = \frac{1}{h_u h_v h_w}\left[
\frac{\partial{(F_uh_vh_w)}}{\partial{u}} +
\frac{\partial{(h_uF_vh_w)}}{\partial{v}} +
\frac{\partial{(h_uh_vF_w)}}{\partial{w}} \right].
~$$
```
----
For example, in cylindrical coordinates, we have
$$~
```math
\nabla \cdot F = \frac{1}{r}
\left[
\frac{\partial{F_r r}}{\partial{r}} +
\frac{\partial{F_\theta}}{\partial{\theta}} +
\frac{\partial{F_x}}{\partial{z}}
\right].
~$$
```
### The curl in a new coordinate system
The curl, like the divergence, can be expressed as the limit of an integral:
$$~
```math
(\nabla \times F) \cdot \hat{N} = \lim \frac{1}{\Delta{S}} \oint_C F \cdot d\vec{r},
~$$
```
where $S$ is a surface perpendicular to $\hat{N}$ with boundary $C$. For a small rectangular surface, the derivation is similar to above, only the scale factors are included. This gives, say, for the $\hat{e}_u$ normal, $\frac{\partial{(h_zF_z)}}{\partial{y}} - \frac{\partial{(h_yF_y)}}{\partial{z}}$. The following determinant form combines the terms compactly:
$$~
```math
\nabla\times{F} = \det \left[
\begin{array}{}
h_u\hat{e}_u & h_v\hat{e}_v & h_w\hat{e}_w \\
@ -1214,13 +1230,13 @@ h_u\hat{e}_u & h_v\hat{e}_v & h_w\hat{e}_w \\
h_uF_u & h_v F_v & h_w F_w
\end{array}
\right].
~$$
```
----
For example, in cylindrical coordinates, the curl is:
$$~
```math
\det\left[
\begin{array}{}
\hat{r} & r\hat{\theta} & \hat{k} \\
@ -1228,11 +1244,11 @@ $$~
F_r & rF_\theta & F_z
\end{array}
\right]
~$$
```
Applying this to the function $F(r,\theta, z) = \hat{\theta}$ we get:
$$~
```math
\text{curl}(F) = \det\left[
\begin{array}{}
\hat{r} & r\hat{\theta} & \hat{k} \\
@ -1247,7 +1263,7 @@ $$~
\end{array}
\right] =
\hat{k}.
~$$
```
As $F$ represents a vector field that rotates about the $z$ axis at a constant rate, the magnitude of the curl should be a constant and it should point in the $\hat{k}$ direction, as we found.
@ -1290,8 +1306,8 @@ raw" ``x y + x e^{x y} + \cos{\left (x \right )}``",
raw" ``x y + x e^{x y}``",
raw" ``x e^{x y} + \cos{\left (x \right )}``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -1306,8 +1322,8 @@ raw" ``xz``",
raw" ``-yz``",
raw" ``ye^{xy}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1320,8 +1336,8 @@ raw" ``0``",
raw" ``\vec{0}``",
raw" ``6``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -1329,21 +1345,21 @@ radioq(choices, ans)
In two dimension's the curl of a gradient field simplifies to:
$$~
```math
\nabla\times\nabla{f} = \nabla\times
\langle\frac{\partial{f}}{\partial{x}},
\frac{\partial{f}}{\partial{y}}\rangle =
\frac{\partial{\frac{\partial{f}}{\partial{y}}}}{\partial{x}} -
\frac{\partial{\frac{\partial{f}}{\partial{x}}}}{\partial{y}}.
~$$
```
```julia; hold=true; echo=false
choices = [
L"This is $0$ if the partial derivatives are continuous by Schwarz's (Clairault's) theorem",
L"This is $0$ for any $f$, as $\nabla\times\nabla$ is $0$ since the cross product of vector with itself is the $0$ vector."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1365,8 +1381,8 @@ choices=[
"The field is irrotational (curl free)",
"The field has a non-trivial curl and divergence"
]
ans=1
radioq(choices, ans, keep_order=true)
answ=1
radioq(choices, answ, keep_order=true)
```
@ -1388,8 +1404,8 @@ choices=[
"The field is irrotational (curl free)",
"The field has a non-trivial curl and divergence"
]
ans=2
radioq(choices, ans, keep_order=true)
answ=2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1403,8 +1419,8 @@ choices=[
"The field is irrotational (curl free)",
"The field has a non-trivial curl and divergence"
]
ans=3
radioq(choices, ans, keep_order=true)
answ=3
radioq(choices, answ, keep_order=true)
```
@ -1419,8 +1435,8 @@ choices=[
"The field is irrotational (curl free)",
"The field has a non-trivial curl and divergence"
]
ans=1
radioq(choices, ans, keep_order=true)
answ=1
radioq(choices, answ, keep_order=true)
```
@ -1431,7 +1447,7 @@ For spherical coordinates, $\Phi(r, \theta, \phi)=r \langle \sin\phi\cos\theta,\
The curl then will then be
$$~
```math
\nabla\times{F} = \det \left[
\begin{array}{}
\hat{e}_r & r\sin\phi\hat{e}_\theta & r\hat{e}_\phi \\
@ -1439,7 +1455,7 @@ $$~
F_r & r\sin\phi F_\theta & r F_\phi
\end{array}
\right].
~$$
```
For a *radial* function $F = h(r)e_r$. (That is $F_r = h(r)$, $F_\theta=0$, and $F_\phi=0$. What is the curl of $F$?
@ -1449,6 +1465,6 @@ raw" ``\vec{0}``",
raw" ``re_\phi``",
raw" ``rh'(r)e_\phi``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```

View File

@ -14,8 +14,8 @@ using HCubature
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
import PyPlot
pyplot()
#import PyPlot
#pyplot()
const frontmatter = (
@ -89,9 +89,9 @@ As with the one-dimensional case, $f$ is Riemann integrable over $R$ if the limi
When $f$ is Riemann integrable over a rectangular region $R$, we denote the limit by any of:
$$~
```math
\iint_R f(x) dV, \quad \iint_R fdV, \quad \iint_R f(x_1, \dots, x_n) dx_1 \cdot\cdots\cdot dx_n, \quad\iint_R f(\vec{x}) d\vec{x}.
~$$
```
A key fact, requiring proof, is:
@ -111,25 +111,25 @@ As with one-dimensional integrals, from the Riemann sum definition, several fami
* For integrable $f$ and $g$ and constants $a$ and $b$:
$$~
```math
\iint_R (af(x) + bg(x))dV = a\iint_R f(x)dV + b\iint_R g(x) dV.
~$$
```
**Disjoint:**
* If $R$ and $R'$ are *disjoint* rectangular regions (possibly sharing a boundary), then the integral over the union is defined by linearity:
$$~
```math
\iint_{R \cup R'} f(x) dV = \iint_R f(x)dV + \iint_{R'} f(x) dV.
~$$
```
**Monotonicity:**
* As $f$ is bounded, let $m \leq f(x) \leq M$ for all $x$ in $R$. Then
$$~
```math
m V(R) \leq \iint_R f(x) dV \leq MV(R).
~$$
```
* If $f$ and $g$ are integrable *and* $f(x) \leq g(x)$, then the integrals have the same property, namely $\iint_R f dV \leq \iint_R gdV$.
@ -234,7 +234,7 @@ The answer agrees with that known from the formula, $4 = (1/3)a^2 h$, but the a
We might try integrating a function with a condition:
```julia; hold=true
function f(x,y, r)
function f(x, y, r)
if x^2 + y^2 < r
sqrt(z - x^2 + y^2)
else
@ -246,16 +246,11 @@ end
**But** `hcubature` is **very** slow to integrate such functions. We will see our instincts are good -- this is the approach taken to discuss integrals over general regions -- but this is not practical here. There are two alternative approaches to be discussed: approach the integral *iteratively* or *transform* the circular region into a rectangular region and integrate. Before doing so, we discuss how the integral is developed for more general regions.
```julia; echo=false
note("""
The approach above takes a nice smooth function and makes it non smooth at the boundary. In general this is not a good idea for numeric solutions, as many algorithms work better with assumptions of smoothness.
""")
```
!!! note
The approach above takes a nice smooth function and makes it non smooth at the boundary. In general this is not a good idea for numeric solutions, as many algorithms work better with assumptions of smoothness.
```julia; echo=false
note("""
The `Quadrature` package provides a uniform interface for `QuadGK`, `HCubature`, and other numeric integration routines available in `Julia`.""")
```
!!! note
The `Quadrature` package provides a uniform interface for `QuadGK`, `HCubature`, and other numeric integration routines available in `Julia`.
## Integrals over more general regions
@ -350,10 +345,10 @@ $I(x) = \int_{-2}^2 f(x,y) dy$. Like partial derivatives, this integrates in $y
The question then: under what conditions will the three integrals be equal?
> [Fubini](https://math.okstate.edu/people/lebl/osu4153-s16/chapter10-ver1.pdf). Let $R \times S$ be a closed rectangular region in $R^n \times R^m$. Suppose $f$ is bounded. Define $f_x(y) = f(x,y)$ and $f^y(x) = f(x,y)$ where $x$ is in $R^n$ and $y$ in $R^m$. *If* $f_x$ and $f^y$ are integrable then
> $$~
> ```math
> \iint_{R\times S}fdV = \iint_R \left(\iint_S f_x(y) dy\right) dx
> = \iint_S \left(\iint_R f^y(x) dx\right) dy.
> ~$$
> ```
Similarly, if $f^y$ is integrable for all $y$, then $\iint_{R\times S}fdV =\iint_S \iint_R f(x,y) dx dy$.
@ -380,18 +375,18 @@ A domain, as described above, is known as a [normal](https://en.wikipedia.org/wi
For example, we return to the problem of a square pyramid, only now using symmetry, we integrate only over the triangular region between $0 \leq x \leq a/2$ and $0 \leq y \leq x$. The answer is then (the $8$ by symmetry)
$$~
```math
V = 8 \int_0^{a/2} \int_0^x h(l(x,y) - d(x,y))/l(x,y) dy dx.
~$$
```
But, using similar triangles, we have $d/x = l/(a/2)$ so $(l-d)/l = 1 - 2x/a$. Continuing, our answer becomes
$$~
```math
V = 8 \int_0^{a/2} (\int_0^x h(1-\frac{2x}{a}) dy) dx =
8 \int_0^{a/2} (h(1-2x/a) \cdot x) dx =
8 (hx^2_2 \big\lvert_{0}^{a/2} - \frac{2}{a}\frac{x^3}{3}\big\lvert_0^{a/2})=
8 h(\frac{a^2}{8} - \frac{2}{24}a^2) = \frac{a^2h}{3}.
~$$
```
@ -402,9 +397,9 @@ The `integrate` function of `SymPy` uses various algorithms to symbolically inte
For example, to perform the integral
$$~
```math
\int_a^b \int_{h(x)}^{g(x)} f(x,y) dy dx
~$$
```
the call would look like:
@ -585,9 +580,9 @@ integrate(rho(x,y), (y, h(x), g(x)), (x, -a, a))
Integrate $\int_0^1 \int_y^1 \cos(x^2) dx dy$ avoiding the *impossible* integral of $\cos(x^2)$. As the integrand is continuous, Fubini's Theorem allows the interchange of the variable of integraton. The region, $R$, is a triangle in the first quadrant below the line $y=x$ and left of the line $x=1$. So we have:
$$~
```math
\int_0^1 \int_0^x \cos(x^2) dy dx
~$$
```
We can integrate this, as the interior integral leaves $x \cos(x^2)$ to integrate:
@ -692,8 +687,9 @@ sin(1)/2
Triple integrals are identical in theory to double integrals, though the computations can be more involved and the regions more complicated to describe. The main regions (emphasized by Strang) to understand are: box, prism, cylinder, cone, tetrahedron, and sphere.
```julia; hold=true; echo=false
ts = range(0, pi/2, length=50)
```julia; echo=false
let
ts = range(0, pi/2, length=50)
O = [0,0,0]
bx, by,bz = [1, 0, 0], [0,2,0], [0,0,3]
@ -748,7 +744,8 @@ ts = range(0, pi/2, length=50)
push!(ps, p)
l = @layout [a b; c d; e]
plot(ps..., layout=l)
plot(ps..., layout=l)
end
```
@ -789,9 +786,9 @@ This is $1/6$th the volume of the box.
* Cone. Consider a cone formed by the function $z = f(x,y) = a - b(x^2+y^2)^{1/2}$ ($a,b > 0$) and the $x$-$y$ plane. This will have radius $r = a/b$ and height $a$. The volume is given by this integral:
$$~
```math
\int_{x=-r}^r \int_{y=-\sqrt{r^2 - x^2}}^{\sqrt{r^2-x^2}} \int_0^{a - b(x^2 + y^2)} 1 dz dy dx.
~$$
```
This integral is doable, but `SymPy` has trouble with it. We will return to this when cylindrical coordinates are defined.
@ -799,9 +796,9 @@ This integral is doable, but `SymPy` has trouble with it. We will return to this
* Sphere. The sphere $x^2 + y^2 + z^2 \leq 1$ has a known volume. Can we compute it using integration? In Cartesian coordinates, we can describe the region $x^2 + y^2 \leq 1$ and then the $z$-limits will follow:
$$~
```math
\int_{x=-1}^1 \int_{y=-\sqrt{1-x^2}}^{\sqrt{1-x^2}} \int_{z=-\sqrt{1 - x^2 - y^2}}^{\sqrt{1-x^2 - y^2}} 1 dz dy dx.
~$$
```
This integral is doable, but `SymPy` has trouble with it. We will return to this when spherical coordinates are defined.
@ -813,9 +810,9 @@ This integral is doable, but `SymPy` has trouble with it. We will return to this
The change of variables, or substitution, formula from first-semester calculus is expressed, under assumptions, by:
$$~
```math
\int_{g(R)} f(x) dx = \int_R (f\circ g)(u)g'(u) du.
~$$
```
The derivation comes from reversing the chain rule. When using it, we start on the right hand side and typically write $x = g(u)$ and from here derive an expression involving differentials: $dx = g'(u) du$ and the rest follows. In practice, this is used to simplify the integrand in the search for an antiderivative, as $(f\circ g)$ is generally more complicated than $f$ alone.
@ -827,23 +824,23 @@ In [Katz](http://www.jstor.org/stable/2689856) a review of the history of "chang
We view $R$ in two coordinate systems $(x,y)$ and $(u,v)$. We have that
$$~
```math
\begin{align}
dx &= A du + B dv\\
dy &= C du + D dv,
\end{align}
~$$
```
where $A = \partial{x}/\partial{u}$, $B = \partial{x}/\partial{v}$, $C= \partial{y}/\partial{u}$, and $D = \partial{y}/\partial{v}$. Lagrange, following Euler, first sets $x$ to be constant (as is done in iterated integration). Hence, $dx = 0$ and so $du = -C(B/A) dv$ and, after substitution, $dy = (D-C(B/A))dv$. Then Lagrange set $y$ to be a constant, so $dy = 0$ and hence $dv=0$ so $dx = Adu$. The area "element" $dx dy = A du \cdot (D - (B/A)) dv = (AD - BC) du dv$. Since areas and volumes are non-negative, the absolute value is used. With this, we have "$dxdy = |AD-BC|du dv$" as the analog of $dx = g'(u) du$.
The expression $AD - BC$ was also derived by Euler, by related means. Lagrange extended the analysis to 3 dimensions. Before doing so, it is helpful to understand the problem from a geometric perspective. Euler was attempting to understand the effects of the following change of variable:
$$~
```math
\begin{align}
x &= a + mt + \sqrt{1-m^2} v\\
y & = b + \sqrt{1-m^2}t -mv
\end{align}
~$$
```
Euler knew this to be a clockwise *rotation* by an angle $\theta$ with $\cos(\theta) = m$, a *reflection* through the $x$ axis, and a translation by $\langle a, b\rangle$. All these *should* preserve the area represented by $dx dy$, so he was *expecting* $dx dy = dt dv$.
@ -937,7 +934,7 @@ showG(G, 1, 1)
The arrows are the images of the standard unit vectors. We see some transformations leave these *orthogonal* and some change the respective lengths.
The area of the associated parallelogram can be found using the determinant of an accompanying matrix. For two dimensions, using the cross product formulation on the embedded vectors, the area is
$$~
```math
\| \det\left(\left[
\begin{array}{}
\hat{i} & \hat{j} & \hat{k}\\
@ -961,7 +958,7 @@ v_1 & v_2
\end{array}
\right]
\right)|.
~$$
```
Using the fact that the two vectors involved are columns in the Jacobian of the transformation, this is just $|\det(J_G)|$. For $3$ dimensions, the determinant gives the volume of the 3-dimensional parallelepiped in the same manner. This holds for higher dimensions.
@ -970,20 +967,16 @@ The absolute value of the determinant of the Jacobian
is the multiplying factor that is seen in the change of variable formula for all dimensions:
> [Change of variable](https://en.wikipedia.org/wiki/Integration_by_substitution#Substitution_for_multiple_variables) Let $U$ be an open set in $R^n$, $G:U \rightarrow R^n$ be an *injective* differentiable function with *continuous* partial derivatives. If $f$ is continuous and compactly supported, then
> $$~
> ```math
> \iint_{G(S)} f(\vec{x}) dV = \iint_S (f \circ G)(\vec{u}) |\det(J_G)(\vec{u})| dU.
> ~$$
> ```
For the one-dimensional case, there is no absolute value, but there the interval is reversed, producing "negative" area. This is not the case here, where $S$ is parameterized to give positive volume.
```julia; echo=false
note(L"""
!!! note
The term "functional determinant" is found for the value $\det(J_G)$, as is the notation $\partial(x_1, x_2, \dots x_n)/\partial(u_1, u_2, \dots, u_n)$.
The term "functional determinant" is found for the value $\det(J_G)$, as is the notation $\partial(x_1, x_2, \dots x_n)/\partial(u_1, u_2, \dots, u_n)$.
""")
```
### Two dimensional change of variables
@ -994,14 +987,14 @@ Now we see several examples of two-dimensional transformations.
We have [seen](../differentiable_vector_calculus/polar_coordinates.html) how to compute area in polar coordinates through the formula $A = \int (1/2) r^2(\theta) d\theta$. This formula can be derived as follows. Consider a region $R$ parameterized in polar coordinates by $r(\theta)$ for $a \leq \theta \leq b$. The area of this region would be $\iint_R fdA$. Let $G(r, \theta) = r \langle \cos\theta, \sin\theta\rangle$. Then
$$~
```math
J_G = \left[
\begin{array}{}
\cos(\theta) & - r\sin(\theta)\\
\sin(\theta) & r\cos(\theta)
\end{array}
\right],
~$$
```
with determinant $r$.
@ -1010,9 +1003,9 @@ That is, for *polar coordinates* $dx dy = r dr d\theta$ ($r \geq 0$).
So by the change of variable formula, we have:
$$~
```math
A = \iint_R 1 dx dy = \int_a^b \int_0^{r(\theta)} 1 r dr d\theta = \int_a^b \frac{r^2(\theta)}{2} d\theta.
~$$
```
The key is noting that the region, $S$, described by $\theta$ running from $a$ to $b$ and $r$ running from $0$ to $r(\theta)$, maps onto $R$ through the change of variables. As polar coordinates is just a renaming, this is clear to see.
@ -1020,21 +1013,21 @@ The key is noting that the region, $S$, described by $\theta$ running from $a$ t
Now consider finding the volume of a sphere using polar coordinates. We have, with $\rho$ being the radius:
$$~
```math
V = 2 \iint_R \sqrt{\rho^2 - x^2 - y^2} dy dx,
~$$
```
where $R$ is the disc of radius $\rho$. Using polar coordinates, we have $x^2 + y^2 = r^2$ and the expression becomes:
$$~
```math
V = 2 \int_0^{2\pi} \int_0^\rho \sqrt{\rho^2 - r^2} r dr d\theta = 2 \int_0^{2\pi} -(1 - r^2)^{3/2}\frac{1}{3} \mid_0^\rho d\theta = 2\int_0^{2\pi} \frac{\rho^3}{3}d\theta = \frac{4\pi\rho^3}{3}.
~$$
```
##### Linear transformations
Some [transformations](https://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_computer_graphics) from ``2``D computer graphics are represented in matrix notation:
$$~
```math
\left[
\begin{array}{}
x\\
@ -1053,7 +1046,7 @@ u\\
v
\end{array}
\right],
~$$
```
or $G(u,v) = \langle au+bv, cu+dv\rangle$. The Jacobian of this *linear* transformation is the matrix itself.
@ -1085,7 +1078,7 @@ showG(G)
* **Reflection** If $\vec{l} = \langle l_x, l_y \rangle$ with norm $\|\vec{l}\|$. The reflection through the line in the direction of $\vec{l}$ through the origin is defined, using a matrix, by:
$$~
```math
\frac{1}{\| \vec{l} \|^2}
\left[
\begin{array}{}
@ -1093,7 +1086,7 @@ l_x^2 - l_y^2 & 2 l_x l_y\\
2l_x l_y & l_y^2 - l_x^2
\end{array}
\right]
~$$
```
For some simple cases: $\langle l_x, l_y \rangle = \langle 1, 1\rangle$, the diagonal, this is $G(u,v) = (1/2) \langle 2v, 2u \rangle$; $\langle l_x, l_y \rangle = \langle 0, 1\rangle$ (the $y$-axis) this is $G(u,v) = \langle -u, v\rangle$.
@ -1126,7 +1119,7 @@ showG(G, lambda=1/3)
The determinant of the Jacobian is
$$~
```math
\det(J_G) = \det\left(
\left[
\begin{array}{}
@ -1135,12 +1128,12 @@ v & u
\end{array}
\right]
\right) = u.
~$$
```
So, $\iint_R f(x,y) dA = \int_0^1\int_0^1 f(u, uv) u du dv$. Here we illustrate with a generic monomial:
```julia;
@syms n::positive m::positive
@syms x y n::positive m::positive
monomial(x,y) = x^n*y^m
integrate(monomial(x,y), (y, 0, x), (x, 0, 1))
```
@ -1159,10 +1152,13 @@ What about other triangles, say the triangle bounded by $x=0$, $y=0$ and $y-x=1$
This can be seen as a reflection through the line $x=1/2$ of the triangle above. If $G_1$ represents the mapping from $U [0,1]\times[0,1]$ into the triangle of the last problem, and $G_2$ represents the reflection through the line $x=1/2$, then the transformation $G_2 \circ G_1$ will map the box $U$ into the desired region. By the chain rule, we have:
$$~
\int_{(G_2\circ G_1)(U))} f dx = \int_U (f\circ G_2 \circ G_1) |\det(J_{G_2 \circ G_1}| du =
```math
\begin{align*}
\int_{(G_2\circ G_1)(U))} f dx &= \int_U (f\circ G_2 \circ G_1) |\det(J_{G_2 \circ G_1}| du \\
&=
\int_U (f\circ G_2 \circ G_1) |\det(J_{G_2}(G_1(u))||\det J_{G_1}(u)| du.
~$$
\end{align*}
```
(In [Katz](http://www.jstor.org/stable/2689856) it is mentioned that Jacobi showed this in 1841.)
@ -1255,34 +1251,34 @@ plot(ps..., layout=l)
The center of mass is a balancing point of a region with density $\rho(x,y)$. In two dimensions it is a point $\langle \bar{x}, \bar{y}\rangle$. These are found by the following formulas:
$$~
```math
A = \iint_R \rho(x,y) dA, \quad \bar{x} = \frac{1}{A} \iint_R x \rho(x,y) dA, \quad
\bar{y} = \frac{1}{A} \iint_R y \rho(x,y) dA.
~$$
```
The $x$ value can be seen in terms of Fubini by integrating in $y$ first:
$$~
```math
\iint_R x \rho(x,y) dA = \int_{x=a}^b (\int_{y=h(x)}^{g(x)} \rho(x,y) dy) dx.
~$$
```
The inner integral is the mass of a slice at a value along the $x$ axis. The center of mass is formed then by the mass times the distance from the origin. The center of mass is a "balance" point, in the sense that $\iint_R (x - \bar{x}) dA = 0$ and $\iint_R (y-\bar{y})dA = 0$.
For example, the center of mass of the upper half *unit* disc will have a centroid with $\bar{x} = 0$, by symmetry. We can see this by integrating in *Cartesian* coordinates, as follows
$$~
```math
\iint_R x dA = \int_{y=0}^1 \int_{x=-\sqrt{1-y^2}}^{\sqrt{1 - y^2}} x dx dy.
~$$
```
The inner integral is $0$ as it an integral of an *odd* function over an interval symmetric about $0$.
The value of $\bar{y}$ is found using polar coordinate transformation from:
$$~
```math
\iint_R y dA = \int_{r=0}^1 \int_{\theta=0}^{\pi} (r\sin(\theta))r d\theta dr =
\int_{r=0}^1 r^2 dr \int_{\theta=0}^{\pi}\sin(\theta) = \frac{1}{3} \cdot 2.
~$$
```
The third equals sign uses separability. The answer for $\bar{ is this value divided by the area, or $2/(3\pi)$.
@ -1294,9 +1290,9 @@ Let $R$ be the half disc contained by $x^2 + y^2 = 1$ and $y \geq 0$. Let $\rho(
$R$ is best described in polar coordinates, so we try to compute
$$~
```math
\int_0^1 \int_{-\pi/2}^{\pi/2} (r\cos(\theta))^2 (r\cos(\theta))(r\sin(\theta)) r d\theta dr.
~$$
```
That requires integrating $\sin^2(\theta)\cos^3(\theta)$, a doable task, but best left to SymPy:
@ -1314,9 +1310,9 @@ integrate(x^2 * rho(x, y), (theta, -PI/2, PI/2), (r, 0, 1))
The counterclockwise rotation of the unit square is $G(u,v) = \langle \cos(\alpha)u-\sin(\alpha)v, \sin(\alpha)u + \cos(\alpha) v\rangle$. This comes from the above formula for clockwise rotation using $-\alpha$. This transformation has Jacobian determinant $1$, as the area is not deformed. With this, we have
$$~
```math
\iint_R x^2 dA = \iint_{G(U)} (f\circ G)(u) |\det(J_G(u))| dU,
~$$
```
which is computed with:
@ -1334,9 +1330,9 @@ Let $R$ be a ring with inner radius $4$ and outer radius $5$. Find its moment of
The integral to compute is:
$$~
```math
\iint_R x^2 dA,
~$$
```
with domain that is easy to describe in polar coordinates:
@ -1356,9 +1352,9 @@ The change of variables formula is no different between dimensions $2$ and $3$ (
Polar coordinates describe the $x$-$y$ plane in terms of a radius $r$ and angle $\theta$. *Cylindrical* coordinates describe the $x-y-z$ plane in terms of $r, \theta$, and $z$. A transformation is:
$$~
```math
G(r,\theta, z) = \langle r\cos(\theta), r\sin(\theta), z\rangle.
~$$
```
This has Jacobian determinant $r$, similar to polar coordinates.
@ -1368,18 +1364,18 @@ This has Jacobian determinant $r$, similar to polar coordinates.
Returning to the volume of a cone above the $x$-$y$ plane under $z = a - b(x^2 + y^2)^{12}$. This yielded the integral in Cartesian coordinates:
$$~
```math
\int_{x=-r}^r \int_{y=-\sqrt{r^2 - x^2}}^{\sqrt{r^2-x^2}} \int_0^{a - b(x^2 + y^2)} 1 dz dy dx,
~$$
```
where $r=a/b$. This is *much* simpler in Cylindrical coordinates, as the region is described by the rectangle in $(r, \theta)$: $[0, \sqrt{b/a}] \times [0, 2\pi]$ and the $z$ range is from $0$ to $a - b r$.
The volume then is:
$$~
```math
\int_{theta=0}^{2\pi} \int_{r=0}^{a/b} \int_{z=0}^{a - br} 1 r dz dr d\theta =
2\pi \int_{r=0}^{a/b} (a-br)r dr = \frac{\pi a^3}{3b^2}.
~$$
```
This is in agreement with $\pi r^2 h/3$.
@ -1437,13 +1433,13 @@ Spherical coordinates describe a point in space by a radius from the origin, $r$
The exact formula to relate $(\rho, \theta, \phi)$ to $(x,y,z)$ is given by
$$~
```math
G(\rho, \theta, \phi) = \rho \langle
\sin(\phi)\cos(\theta),
\sin(\phi)\sin(\theta),
\cos(\phi)
\rangle.
~$$
```
```julia; hold=true; echo=false
@ -1465,10 +1461,10 @@ det(G(ρ, theta, phi).jacobian([ρ, theta, phi])) |> simplify |> abs
Computing the volume of a sphere is a challenge (for SymPy) in Cartesian coordinates, but a breeze in spherical coordinates. Using $r^2\sin(\phi)$ as the multiplying factor, the volume is simply:
$$~
```math
\int_{\theta=0}^{2\pi} \int_{\phi=0}^{\pi} \int_{r=0}^R 1 \cdot r^2 \sin(\phi) dr d\phi d\theta =
\int_{\theta=0}^{2\pi} d\theta \int_{\phi=0}^{\pi} \sin(\phi)d\phi \int_{r=0}^R r^2 dr = (2\pi)(2)\frac{R^3}{3} = \frac{4\pi R^3}{3}.
~$$
```
@ -1478,9 +1474,9 @@ Compute the volume of the ellipsoid, $R$, described by $(x/a)^2 + (y/v)^2 + (z/c
We first change variables via $G(u,v,w) = \langle ua, vb, wc \rangle$. This maps the unit sphere, $S$, given by $u^2 + v^2 + w^2 \leq 1$ into the ellipsoid. Then
$$~
```math
\iint_R 1 dV = \iint_S 1 |\det(J_G)| dU
~$$
```
But the Jacobian is a constant:
@ -1499,17 +1495,17 @@ So the answer is $abc V(S) = 4\pi abc/3$
Suppose $f(x,y) = f_1(x)f_2(y)$ and $R = [a_1, b_1] \times [a_2,b_2]$ is a rectangular region. Is this true?
$$~
```math
\iint_R f dA = (\int_{a_1}^{b_1} f_1(x) dx) \cdot (\int_{a_2}^{b_2} f_2(y) dy).
~$$
```
```julia; hold=true; echo=false
choices = [
L"Yes. As an inner integral $\int_{a^2}^{b_2} f(x,y) dy = f_1(x) \int_{a_2}^{b_2} f_2(y) dy$.",
"No."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1517,9 +1513,9 @@ radioq(choices, ans)
Which integrals of the following are $0$ by symmetry? Let $R$ be the unit disc.
$$~
```math
a = \iint_R x dA, \quad b = \iint_R (x^2 + y^2) dA, \quad c = \iint_R xy dA
~$$
```
```julia; hold=true; echo=false
choices = [
@ -1527,8 +1523,8 @@ L"Both $a$ and $b$",
L"Both $a$ and $c$",
L"Both $b$ and $c$"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -1536,11 +1532,11 @@ radioq(choices, ans)
Let $R$ be the unit disc. Which integrals can be found from common geometric formulas (e.g., known formulas for the sphere, cone, pyramid, ellipse, ...)
$$~
```math
a = \iint_R (1 - (x^2+y2)) dA, \quad
b = \iint_R (1 - \sqrt{x^2 + y^2}) dA, \quad
c = \iint_R (1 - (x^2 + y^2)^2 dA
~$$
```
```julia; hold=true; echo=false
@ -1549,8 +1545,8 @@ L"Both $a$ and $b$",
L"Both $a$ and $c$",
L"Both $b$ and $c$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1567,8 +1563,8 @@ raw" ``\int_0^1 \int_0^{(1-x^3)^{1/3}} 1\cdot dy dx``",
raw" ``\int_0^1 \int_0^{(1-y^3)^{1/3}} 1\cdot dx dy``",
raw" ``\int_0^1 \int_0^{(1-y^3)^{1/3}} 1\cdot dy dx``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -1583,8 +1579,8 @@ raw" ``\int_0^b\int_{y/b}^{2-y/b} dx dy``",
raw" ``\int_0^2\int_0^{bx} dy dx``",
raw" ``\int_0^2 \int_0^{2b - bx} dy dx``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1598,8 +1594,8 @@ raw" ``\int_a^b \int_0^{f(x)} dy dx``",
raw" ``\int_a^b \int_0^{f(x)} dx dy``",
raw" ``\int_0^{f(x)} \int_a^b dx dy``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1613,8 +1609,8 @@ raw" ``G(u,v) = \langle u-v, u+v \rangle``",
raw" ``G(u,v) = \langle u^2-v^2, u^2+v^2 \rangle``",
raw" ``G(u,v) = \langle u-v, u \rangle``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1636,12 +1632,12 @@ Let $G(u, v) = \langle \cosh(u)\cos(v), \sinh(u)\sin(v) \rangle$. Compute the de
```julia; hold=true; echo=false
choices = [
raw" ``\sin^{2}{\left (v \right )} \cosh^{2}{\left (u \right )} + \cos^{2}{\left (v \right )} \sinh^{2}{\left (u \right )}",
raw" ``\sin^{2}{\left (v \right )} \cosh^{2}{\left (u \right )} + \cos^{2}{\left (v \right )} \sinh^{2}{\left (u \right )}``",
raw" ``1``",
raw" ``\sinh(u)\cosh(v)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1655,8 +1651,8 @@ L"It is $1$, as each is area preserving",
L"It is $r$, as the rotation uses polar coordinates",
L"It is $r^2 \sin(\phi)$, as the rotations use spherical coordinates"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1681,8 +1677,8 @@ L"The value $\bar{x}$ of the centroid",
L"The value $\bar{y}$ of the centroid",
L"The moment of inertia of $R$ about the $x$ axis"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
What does $B/A$ compute?
@ -1695,8 +1691,8 @@ L"The value $\bar{x}$ of the centroid",
L"The value $\bar{y}$ of the centroid",
L"The moment of inertia of $R$ about the $x$ axis"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -1710,6 +1706,6 @@ raw" ``dtdv``",
raw" ``(1-2m^2)dt dv``",
raw" ``m\sqrt{1-m^2}dt^2+(1-2m^2)dtdv -m\sqrt{1-m^2}dv^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -242,11 +242,9 @@ quadgk(t -> (Fₘ ∘ rₒ)(t) ⋅ rₒ'(t), 0, 1)
Still $0$. We will see next that this is not surprising if something about $F$ is known.
```julia; echo=false
note("""
The [Washington Post](https://www.washingtonpost.com/outlook/everything-you-thought-you-knew-about-gravity-is-wrong/2019/08/01/627f3696-a723-11e9-a3a6-ab670962db05_story.html") had an article by Richard Panek with the quote "Well, yes — depending on what we mean by 'attraction.' Two bodies of mass dont actually exert some mysterious tugging on each other. Newton himself tried to avoid the word 'attraction' for this very reason. All (!) he was trying to do was find the math to describe the motions both down here on Earth and up there among the planets (of which Earth, thanks to Copernicus and Kepler and Galileo, was one)." The point being the formula above is a mathematical description of the force, but not an explanation of how the force actually is transferred.
""")
```
!!! note
The [Washington Post](https://www.washingtonpost.com/outlook/everything-you-thought-you-knew-about-gravity-is-wrong/2019/08/01/627f3696-a723-11e9-a3a6-ab670962db05_story.html") had an article by Richard Panek with the quote "Well, yes — depending on what we mean by 'attraction.' Two bodies of mass dont actually exert some mysterious tugging on each other. Newton himself tried to avoid the word 'attraction' for this very reason. All (!) he was trying to do was find the math to describe the motions both down here on Earth and up there among the planets (of which Earth, thanks to Copernicus and Kepler and Galileo, was one)." The point being the formula above is a mathematical description of the force, but not an explanation of how the force actually is transferred.
#### Work in a *conservative* vector field
@ -432,11 +430,8 @@ p
The flow integral is typically computed for a closed (Jordan) curve, measuring the total flow out of a region. In this case, the integral is written $\oint_C (F\cdot\hat{N})ds$.
```julia; echo=false
note(L"""
For a Jordan curve, the positive orientation of the curve is such that the normal direction (proportional to $\hat{T}'$) points away from the bounded interior. For a non-closed path, the choice of parameterization will determine the normal and the integral for flow across a curve is dependent - up to its sign - on this choice.
""")
```
!!! note
For a Jordan curve, the positive orientation of the curve is such that the normal direction (proportional to $\hat{T}'$) points away from the bounded interior. For a non-closed path, the choice of parameterization will determine the normal and the integral for flow across a curve is dependent - up to its sign - on this choice.
##### Example
@ -725,10 +720,10 @@ In [Surface area](../integrals/surface_area.mmd) the following formula for the s
Consider the transformation $(x, \theta) \rightarrow \langle x, f(x)\cos(\theta), f(x)\sin(\theta)$. This maps the region $[a,b] \times [0, 2\pi]$ *onto* the surface of revolution. As such, the surface element would be:
```julia; hold=true
@syms f()::positive x::real theta::real
```julia
@syms 𝒇()::positive x::real theta::real
Phi(x, theta) = [x, f(x)*cos(theta), f(x)*sin(theta)]
Phi(x, theta) = [x, 𝒇(x)*cos(theta), 𝒇(x)*sin(theta)]
Jac = Phi(x, theta).jacobian([x, theta])
v1, v2 = Jac[:,1], Jac[:,2]
se = norm(v1 × v2)
@ -994,8 +989,8 @@ raw" ``\langle a, b, c\rangle / \| \langle a, b, c\rangle\|``",
raw" ``\langle a, b, c\rangle``",
raw" ``\langle d-a, d-b, d-c\rangle / \| \langle d-a, d-b, d-c\rangle\|``",
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Does it depend on $d$?
@ -1006,8 +1001,8 @@ L"No. Moving $d$ just shifts the plane up or down the $z$ axis, but won't change
L"Yes. Of course. Different values for $d$ mean different values for $x$, $y$, and $z$ are needed.",
L"Yes. The gradient of $F(x,y,z) = ax + by + cz$ will be normal to the level curve $F(x,y,z)=d$, and so this will depend on $d$."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1035,8 +1030,8 @@ raw" ``2\pi + 2\pi^2``",
raw" ``2\pi^2``",
raw" ``4\pi``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1062,8 +1057,8 @@ choices =[
L"It will be $0$, as $\nabla{f}$ is orthogonal to the level curve and $\vec{r}'$ is tangent to the level curve",
L"It will $f(b)-f(a)$ for any $b$ or $a$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1103,8 +1098,8 @@ choices = [
L"The field is a potential field, but the path integral around $0$ is not path dependent.",
L"The value of $d/dt(f\circ\vec{r})=0$, so the integral should be $0$."
]
ans =1
radioq(choices, ans)
answ =1
radioq(choices, answ)
```
The function $F = \nabla{f}$ is
@ -1114,8 +1109,8 @@ choices = [
"Not continuous everywhere",
"Continuous everywhere"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1165,8 +1160,8 @@ raw" ``\int_0^{2\pi} (a\cos(t)) \cdot (b\cos(t)) dt``",
raw" ``\int_0^{2\pi} (-b\sin(t)) \cdot (b\cos(t)) dt``",
raw" ``\int_0^{2\pi} (a\cos(t)) \cdot (a\cos(t)) dt``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -1182,8 +1177,8 @@ raw" ``\langle \cos(v), \sin(v), 1\rangle``",
raw" ``\langle -u\sin(v), u\cos(v), 0\rangle``",
raw" ``u\langle -\cos(v), -\sin(v), 1\rangle``"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
Compute $\vec{v}_2 = \partial{\Phi}/\partial{u}$
@ -1194,8 +1189,8 @@ raw" ``\langle \cos(v), \sin(v), 1\rangle``",
raw" ``\langle -u\sin(v), u\cos(v), 0\rangle``",
raw" ``u\langle -\cos(v), -\sin(v), 1\rangle``"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
Compute $\vec{v}_1 \times \vec{v}_2$
@ -1207,8 +1202,8 @@ raw" ``\langle \cos(v), \sin(v), 1\rangle``",
raw" ``\langle -u\sin(v), u\cos(v), 0\rangle``",
raw" ``u\langle -\cos(v), -\sin(v), 1\rangle``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -1288,8 +1283,8 @@ raw" ``\sqrt{2}/24``",
raw" ``2/\sqrt{24}``",
raw" ``1/12``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1315,6 +1310,6 @@ raw" ``0``",
raw" ``7/36``",
raw" ``1/60``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -114,24 +114,24 @@ Let's consider now what an integral over the boundary would mean. The region, or
With this choice of integral over the boundary, we can see much cancellation arises were we to compute this integral for each piece, as we would have with $a=x_0 < x_1 < \cdots x_{n-1} < x_n=b$:
$$~
```math
(F(x_1) - F(x_0)) + (F(x_2)-F(x_1)) + \cdots + (F(x_n) - F(x_{n-1})) = F(x_n) - F(x_0) = F(b) - F(a).
~$$
```
That is, with this definition for a boundary integral, the interior pieces of the microscopic approximation cancel and the total is just the integral over the oriented macroscopic boundary $\{a, b\}$.
But each microscopic piece can be reimagined, as
$$~
```math
F(x_{i}) - F(x_{i-1}) = \left(\frac{F(x_{i}) - F(x_{i-1})}{\Delta{x}}\right)\Delta{x}
\approx F'(x_i)\Delta{x}.
~$$
```
The approximation could be exact were the mean value theorem used to identify a point in the interval, but we don't pursue that, as the key point is the right hand side is a Riemann sum approximation for a *different* integral, in this case the integral $\int_a^b F'(x) dx$. Passing from the microscopic view to an infinitesimal view, the picture gives two interpretations, leading to the Fundamental Theorem of Calculus:
$$~
```math
\int_a^b F'(x) dx = F(b) - F(a).
~$$
```
The three theorems of this section, Green's theorem, Stokes' theorem, and the divergence theorem, can all be seen in this manner: the sum of microscopic boundary integrals leads to a macroscopic boundary integral of the entire region; whereas, by reinterpretation, the microscopic boundary integrals are viewed as Riemann sums, which in the limit become integrals of a *related* function over the region.
@ -166,14 +166,14 @@ p
Consider the boundary integral $\oint_c F\cdot\vec{T} ds$ around the smallest (green) squares. We have seen that the *curl* at a point in a direction is given in terms of the limit. Let the plane be the $x-y$ plane, and the $\hat{k}$ direction be the one coming out of the figure. In the derivation of the curl, we saw that the line integral for circulation around the square satisfies:
$$~
```math
\lim \frac{1}{\Delta{x}\Delta{y}} \oint_C F \cdot\hat{T}ds =
\frac{\partial{F_y}}{\partial{x}} - \frac{\partial{F_x}}{\partial{y}}.
~$$
```
If the green squares are small enough, then the line integrals satisfy:
$$~
```math
\oint_C F \cdot\hat{T}ds
\approx
\left(
@ -181,15 +181,15 @@ $$~
-
\frac{\partial{F_x}}{\partial{y}}
\right) \Delta{x}\Delta{y} .
~$$
```
We interpret the right hand side as a Riemann sum approximation for the $2$ dimensional integral of the function $f(x,y) = \frac{\partial{F_x}}{\partial{y}} - \frac{\partial{F_y}}{\partial{x}}=\text{curl}(F)$, the two-dimensional curl. Were the green squares continued to fill out the large blue square, then the sum of these terms would approximate the integral
$$~
```math
\iint_S f(x,y) dA = \iint_S
\left(\frac{\partial{F_y}}{\partial{x}} - \frac{\partial{F_x}}{\partial{y}}\right) dA
= \iint_S \text{curl}(F) dA.
~$$
```
However, the microscopic boundary integrals have cancellations that lead to a macroscopic boundary integral. The sum of $\oint_C F \cdot\hat{T}ds$ over the $4$ green squares will be equal to $\oint_{C_r} F\cdot\hat{T}ds$, where $C_r$ is the red square, as the interior line integral pieces will all cancel off. The sum of $\oint_{C_r} F \cdot\hat{T}ds$ over the $4$ red squares will equal $\oint_{C_b} F \cdot\hat{T}ds$, where $C_b$ is the oriented path around the blue square, as again the interior line pieces will cancel off. Etc.
@ -217,10 +217,10 @@ Some examples, following Strang, are:
Let $F(x,y) = \langle -y, x\rangle$. Then $\frac{\partial{F_y}}{\partial{x}} - \frac{\partial{F_x}}{\partial{y}}=2$, so
$$~
```math
\frac{1}{2}\oint_C F\cdot\hat{T}ds = \frac{1}{2}\oint_C (xdy - ydx) =
\iint_D dA = A(D).
~$$
```
This gives a means to compute the area of a region by integrating around its boundary.
@ -235,29 +235,29 @@ F(v) = F(v...)
r(t) = [a*cos(t),b*sin(t)]
@syms a::positive b::positive
@syms a::positive b::positive t
(1//2) * integrate( F(r(t)) ⋅ diff.(r(t),t), (t, 0, 2PI))
```
To compute the area of the triangle with vertices $(0,0)$, $(a,0)$ and $(0,b)$ we can orient the boundary counter clockwise. Let $A$ be the line segment from $(0,b)$ to $(0,0)$, $B$ be the line segment from $(0,0)$ to $(a,0)$, and $C$ be the other. Then
$$~
```math
\begin{align}
\frac{1}{2} \int_A F\cdot\hat{T} ds &=\frac{1}{2} \int_A -ydx = 0\\
\frac{1}{2} \int_B F\cdot\hat{T} ds &=\frac{1}{2} \int_B xdy = 0,
\end{align}
~$$
```
as on $A$, $y=0$ and $dy=0$ and on $B$, $x=0$ and $dx=0$.
On $C$ we have $\vec{r}(t) = (0, b) + t\cdot(1,-b/a) =\langle t, b-(bt)/a\rangle$ from $t=a$ to $0$
$$~
```math
\int_C F\cdot \frac{d\vec{r}}{dt} dt =
\int_a^0 \langle -b + (bt)/a), t\rangle\cdot\langle 1, -b/a\rangle dt
= \int_a^0 -b dt = -bt\mid_{a}^0 = ba.
~$$
```
Dividing by $1/2$ give the familiar answer $A=(1/2) a b$.
@ -274,12 +274,17 @@ For the two dimensional case the curl is a scalar. *If* $F = \langle F_x, F_y\ra
Now assume $\partial{F_y}/\partial{x} - \partial{F_x}/\partial{y} = 0$. Let $P$ and $Q$ be two points in the plane. Take any path, $C_1$ from $P$ to $Q$ and any return path, $C_2$, from $Q$ to $P$ that do not cross and such that $C$, the concatenation of the two paths, satisfies Green's theorem. Then, as $F$ is continuous on an open interval containing $D$, we have:
$$~
0 = \iint_D 0 dA =
\iint_D \left(\partial{F_y}/\partial{x} - \partial{F_x}/\partial{y}\right)dA =
\oint_C F \cdot \hat{T} ds =
```math
\begin{align*}
0 &= \iint_D 0 dA \\
&=
\iint_D \left(\partial{F_y}/\partial{x} - \partial{F_x}/\partial{y}\right)dA \\
&=
\oint_C F \cdot \hat{T} ds \\
&=
\int_{C_1} F \cdot \hat{T} ds + \int_{C_2}F \cdot \hat{T} ds.
~$$
\end{align*}
```
Reversing $C_2$ to go from $P$ to $Q$, we see the two work integrals are identical, that is the field is conservative.
@ -293,14 +298,14 @@ For example, let $F(x,y) = \langle \sin(xy), \cos(xy) \rangle$. Is this a conser
We can check by taking partial derivatives. Those of interest are:
$$~
```math
\begin{align}
\frac{\partial{F_y}}{\partial{x}} &= \frac{\partial{(\cos(xy))}}{\partial{x}} =
-\sin(xy) y,\\
\frac{\partial{F_x}}{\partial{y}} &= \frac{\partial{(\sin(xy))}}{\partial{y}} =
\cos(xy)x.
\end{align}
~$$
```
It is not the case that $\partial{F_y}/\partial{x} - \partial{F_x}/\partial{y}=0$, so this vector field is *not* conservative.
@ -326,9 +331,9 @@ diff(Fy, x) - diff(Fx, y) |> simplify
As the integrand is ``00``, $\iint_D \left( \partial{F_y}/{\partial{x}}-\partial{F_xy}/{\partial{y}}\right)dA = 0$, as well. But,
$$~
```math
F\cdot\hat{T} = \frac{R}{R\cdot{R}} \cdot \frac{R}{R\cdot{R}} = \frac{R\cdot{R}}{(R\cdot{R})^2} = \frac{1}{R\cdot{R}},
~$$
```
so $\oint_C F\cdot\hat{T}ds = 2\pi$, $C$ being the unit circle so $R\cdot{R}=1$.
@ -357,24 +362,24 @@ p
Let $A$ label the red line, $B$ the green curve, $C$ the blue line, and $D$ the black line. Then the area is given from Green's theorem by considering half of the the line integral of $F(x,y) = \langle -y, x\rangle$ or $\oint_C (xdy - ydx)$. To that matter we have:
$$~
```math
\begin{align}
\int_A (xdy - ydx) &= a f(a)\\
\int_C (xdy - ydx) &= b(-f(b))\\
\int_D (xdy - ydx) &= 0\\
\end{align}
~$$
```
Finally the integral over $B$, using integration by parts:
$$~
```math
\begin{align}
\int_B F(\vec{r}(t))\cdot \frac{d\vec{r}(t)}{dt} dt &=
\int_b^a \langle -f(t),t)\rangle\cdot\langle 1, f'(t)\rangle dt\\
&= \int_a^b f(t)dt - \int_a^b tf'(t)dt\\
&= \int_a^b f(t)dt - \left(tf(t)\mid_a^b - \int_a^b f(t) dt\right).
\end{align}
~$$
```
Combining, we have after cancellation $\oint (xdy - ydx) = 2\int_a^b f(t) dt$, or after dividing by $2$ the signed area under the curve.
@ -403,16 +408,16 @@ The cut leads to a counter-clockwise orientation on the outer ring and a clockw
To see that the area integral of $F(x,y) = (1/2)\langle -y, x\rangle$ produces the area for this orientation we have, using $C_1$ as the outer ring, and $C_2$ as the inner ring:
$$~
```math
\begin{align}
\oint_{C_1} F \cdot \hat{T} ds &=
\int_0^{2\pi} (1/2)(2)\langle -\sin(t), \cos(t)\rangle \cdot (2)\langle-\sin(t), \cos(t)\rangle dt
= (1/2) (2\pi) 4 = 4\pi\\
\int_0^{2\pi} (1/2)(2)\langle -\sin(t), \cos(t)\rangle \cdot (2)\langle-\sin(t), \cos(t)\rangle dt \\
&= (1/2) (2\pi) 4 = 4\pi\\
\oint_{C_2} F \cdot \hat{T} ds &=
\int_{0}^{2\pi} (1/2) \langle \sin(t), \cos(t)\rangle \cdot \langle-\sin(t), -\cos(t)\rangle dt\\
&= -(1/2)(2\pi) = -\pi.
\end{align}
~$$
```
(Using $\vec{r}(t) = 2\langle \cos(t), \sin(t)\rangle$ for the outer ring and $\vec{r}(t) = 1\langle \cos(t), -\sin(t)\rangle$ for the inner ring.)
@ -425,22 +430,22 @@ Green's theorem has a complement in terms of flow across $C$. As $C$ is positive
Let $F = \langle F_x, F_y \rangle$ and $G = \langle F_y, -F_x \rangle$, then $G\cdot\hat{T} = -F\cdot\hat{N}$. The curl formula applied to $G$ becomes
$$~
```math
\frac{\partial{G_y}}{\partial{x}} - \frac{\partial{G_x}}{\partial{y}} =
\frac{\partial{-F_x}}{\partial{x}}-\frac{\partial{(F_y)}}{\partial{y}}
=
-\left(\frac{\partial{F_x}}{\partial{x}} + \frac{\partial{F_y}}{\partial{y}}\right)=
-\nabla\cdot{F}.
~$$
```
Green's theorem applied to $G$ then gives this formula for $F$:
$$~
```math
\oint_C F\cdot\hat{N} ds =
-\oint_C G\cdot\hat{T} ds =
-\iint_D (-\nabla\cdot{F})dA =
\iint_D \nabla\cdot{F}dA.
~$$
```
The right hand side integral is the $2$-dimensional divergence, so this has the interpretation that the flux through $C$ ($\oint_C F\cdot\hat{N} ds$) is the integral of the divergence. (The divergence is defined in terms of a limit of this picture, so this theorem extends the microscopic view to a bigger view.)
@ -522,17 +527,17 @@ Again, the microscopic boundary integrals when added will give a macroscopic bou
But, as seen in the derivation of the divergence, only modified for $2$ dimensions, we have
$\nabla\cdot{F} = \lim \frac{1}{\Delta S} \oint_C F\cdot\hat{N}$, so for each cell
$$~
```math
\oint_{C_i} F\cdot\hat{N} \approx \left(\nabla\cdot{F}\right)\Delta{x}\Delta{y},
~$$
```
an approximating Riemann sum for $\iint_D \nabla\cdot{F} dA$. This yields:
$$~
```math
\oint_C (F \cdot\hat{N}) dA =
\sum_i \oint_{C_i} (F \cdot\hat{N}) dA \approx
\sum \left(\nabla\cdot{F}\right)\Delta{x}\Delta{y} \approx
\iint_S \nabla\cdot{F}dA,
~$$
```
the approximation signs becoming equals signs in the limit.
@ -549,11 +554,11 @@ We have the divergence is simply $a + b$ so $\iint_D (a+b)dA = (a+b)A(D) = 4(a+b
The integral of the flow across $C$ consists of $4$ parts. By symmetry, they all should be similar. We consider the line segment connecting $(1,-1)$ to $(1,1)$ (which has the proper counterclockwise orientation):
$$~
```math
\int_C F \cdot \hat{N} ds=
\int_{-1}^1 \langle F_x, F_y\rangle\cdot\langle 0, 1\rangle ds =
\int_{-1}^1 b dy = 2b.
~$$
```
Integrating across the top will give $2a$, along the bottom $2a$, and along the left side $2b$ totaling $4(a+b)$.
@ -586,10 +591,10 @@ The gradient of $f=\langle v_x, v_y\rangle$ is orthogonal to the contour lines o
As an [example](https://en.wikipedia.org/wiki/Potential_flow#Examples_of_two-dimensional_flows) consider the following in polar coordinates:
$$~
```math
f(r, \theta) = A r^n \cos(n\theta),\quad
g(r, \theta) = A r^n \sin(n\theta).
~$$
```
The constant $A$ just sets the scale, the parameter $n$ has a qualitative effect on the contour lines. Consider $n=2$ visualized below:
@ -607,7 +612,7 @@ f(v) = f(v...); g(v)= g(v...)
xs = ys = range(-2,2, length=50)
p = contour(xs, ys, f∘Φ, color=:red, legend=false, aspect_ratio=:equal)
contour!(p, xs, ys, g∘Φ, color=:blue, linewidth=3)
pyplot()
#pyplot()
p
```
@ -636,29 +641,34 @@ Imagine if instead of the retro labeling, a rectangular grid were drawn on the
Now imagine the popcorn expanding, but rather than worry about burning, focusing instead on what happens to the integral of the curl in the direction of the normal, we have
$$~
```math
\nabla\times{F} \cdot\hat{N} = \lim \frac{1}{\Delta{S}} \oint_C F\cdot\hat{T} ds
\approx \frac{1}{\Delta{S}} F\cdot\hat{T} \Delta{s}.
~$$
```
This gives the series of approximations:
$$~
\oint_C F\cdot\hat{T} ds =
\sum \oint_{C_i} F\cdot\hat{T} ds \approx
\sum F\cdot\hat{T} \Delta s \approx
\sum \nabla\times{F}\cdot\hat{N} \Delta{S} \approx
```math
\begin{align*}
\oint_C F\cdot\hat{T} ds &=
\sum \oint_{C_i} F\cdot\hat{T} ds \\
&\approx
\sum F\cdot\hat{T} \Delta s \\
&\approx
\sum \nabla\times{F}\cdot\hat{N} \Delta{S} \\
&\approx
\iint_S \nabla\times{F}\cdot\hat{N} dS.
~$$
\end{align*}
```
In terms of our expanding popcorn, the boundary integral - after accounting for cancellations, as in Green's theorem - can be seen as a microscopic sum of boundary integrals each of which is approximated by a term
$\nabla\times{F}\cdot\hat{N} \Delta{S}$ which is viewed as a Riemann sum approximation for the the integral of the curl over the surface. The cancellation depends on a proper choice of orientation, but with that we have:
> **Stokes' theorem**: Let $S$ be an orientable smooth surface in $R^3$ with boundary $C$, $C$ oriented so that the chosen normal for $S$ agrees with the right-hand rule for $C$'s orientation. Then *if* $F$ has continuous partial derivatives
> $$~
> ```math
> \oint_C F \cdot\hat{T} ds = \iint_S (\nabla\times{F})\cdot\hat{N} dA.
> ~$$
> ```
Green's theorem is an immediate consequence upon viewing the region in $R^2$ as a surface in $R^3$ with normal $\hat{k}$.
@ -707,51 +717,51 @@ integrate(integrandₛ, (t, 0, 2PI))
Ampere's circuital law relates the line integral of the magnetic field to the induced current through:
$$~
```math
\oint_C B\cdot\hat{T} ds = \mu_0 I.
~$$
```
The goal here is to re-express this integral law to produce a law at each point of the field. Let $S$ be a surface with boundary $C$, Let $J$ be the current density - $J=\rho v$, with $\rho$ the density of the current (not time-varying) and $v$ the velocity. The current can be re-expressed as $I = \iint_S J\cdot\hat{n}dA$. (If the current flows through a wire and $S$ is much bigger than the wire, this is still valid as $\rho=0$ outside of the wire.)
We then have:
$$~
```math
\mu_0 \iint_S J\cdot\hat{N}dA =
\mu_0 I =
\oint_C B\cdot\hat{T} ds =
\iint_S (\nabla\times{B})\cdot\hat{N}dA.
~$$
```
As $S$ and $C$ are arbitrary, this implies the integrands of the surface integrals are equal, or:
$$~
```math
\nabla\times{B} = \mu_0 J.
~$$
```
##### Example: Faraday's law
(Strang) Suppose $C$ is a wire and there is a time-varying magnetic field $B(t)$. Then Faraday's law says the *flux* passing within $C$ through a surface $S$ with boundary $C$ of the magnetic field, $\phi = \iint B\cdot\hat{N}dS$, induces an electric field $E$ that does work:
$$~
```math
\oint_C E\cdot\hat{T}ds = -\frac{\partial{\phi}}{\partial{t}}.
~$$
```
Faraday's law is an empirical statement. Stokes' theorem can be used to produce one of Maxwell's equations. For any surface $S$, as above with its boundary being $C$, we have both:
$$~
```math
-\iint_S \left(\frac{\partial{B}}{\partial{t}}\cdot\hat{N}\right)dS =
-\frac{\partial{\phi}}{\partial{t}} =
\oint_C E\cdot\hat{T}ds =
\iint_S (\nabla\times{E}) dS.
~$$
```
This is true for any capping surface for $C$. Shrinking $C$ to a point means it will hold for each point in $R^3$. That is:
$$~
```math
\nabla\times{E} = -\frac{\partial{B}}{\partial{t}}.
~$$
```
##### Example: Conservative fields
@ -783,20 +793,20 @@ curl(F(x,y,z), [x,y,z])
We need $\phi$ with $\partial{\phi}/\partial{x} = F_x = yz^2$. To that end, we integrate in $x$:
$$~
```math
\phi(x,y,z) = \int yz^2 dx = xyz^2 + g(y,z),
~$$
```
the function $g(y,z)$ is a "constant" of integration (it doesn't depend on $x$). That $\partial{\phi}/\partial{x} = F_x$ is true is easy to verify. Now, consider the partial in $y$:
$$~
```math
\frac{\partial{\phi}}{\partial{y}} = xz^2 + \frac{\partial{g}}{\partial{y}} = F_y = xz^2.
~$$
```
So we have $\frac{\partial{g}}{\partial{y}}=0$ or $g(y,z) = h(z)$, some constant in $y$. Finally, we must have $\partial{\phi}/\partial{z} = F_z$, or
$$~
```math
\frac{\partial{\phi}}{\partial{z}} = 2xyz + h'(z) = F_z = 2xyz,
~$$
```
So $h'(z) = 0$. This value can be any constant, even $0$ which we take, so that $g(y,z) = 0$ and $\phi(x,y,z) = xyz^2$ is a scalar potential for $F$.
@ -847,18 +857,18 @@ However, the function $F(x,y,z) = \langle x, y,z\rangle/\sqrt{x^2+y^2+z^2}$ has
The divergence theorem is a consequence of a simple observation. Consider two adjacent cubic regions that share a common face.
The boundary integral, $\oint_S F\cdot\hat{N} dA$, can be computed for each cube. The surface integral requires a choice of normal, and the convention is to use the outward pointing normal. The common face of the two cubes has *different* outward pointing normals, the difference being a minus sign. As such, the contribution of the surface integral over this face for one cube is *cancelled* out by the contribution of the surface integral over this face for the adjacent cube. As with Green's theorem, this means for a cubic partition, that only the contribution over the boundary is needed to compute the boundary integral. In formulas, if $V$ is a $3$ dimensional cubic region with boundary $S$ and it is partitioned into smaller cubic subregions, $V_i$ with surfaces $S_i$, we have:
$$~
```math
\oint_S F\cdot{N} dA = \sum \oint_{S_i} F\cdot{N} dA.
~$$
```
If the partition provides a microscopic perspective, then the divergence approximation $\nabla\cdot{F} \approx (1/\Delta{V_i}) \oint_{S_i} F\cdot{N} dA$ can be used to say:
$$~
```math
\oint_S F\cdot{N} dA =
\sum \oint_{S_i} F\cdot{N} dA \approx
\sum (\nabla\cdot{F})\Delta{V_i} \approx
\iiint_V \nabla\cdot{F} dV,
~$$
```
the last approximation through a Riemann sum approximation. This heuristic leads to:
@ -965,29 +975,29 @@ The divergence theorem provides two means to compute a value, the point here is
Following Schey, we now consider a continuous analog to the crowd counting problem through a flow with a non-uniform density that may vary in time. Let $\rho(x,y,z;t)$ be the time-varying density and $v(x,y,z;t)$ be a vector field indicating the direction of flow. Consider some three-dimensional volume, $V$, with boundary $S$ (though two-dimensional would also be applicable). Then these integrals have interpretations:
$$~
```math
\begin{align}
\iiint_V \rho dV &&\quad\text{Amount contained within }V\\
\frac{\partial}{\partial{t}} \iiint_V \rho dV &=
\iiint_V \frac{\partial{\rho}}{\partial{t}} dV &\quad\text{Change in time of amount contained within }V
\end{align}
~$$
```
Moving the derivative inside the integral requires an assumption of continuity.
Assume the material is *conserved*, meaning that if the amount in the volume $V$ changes it must flow in and out through the boundary. The flow out through $S$, the boundary of $V$, is
$$~
```math
\oint_S (\rho v)\cdot\hat{N} dS,
~$$
```
using the customary outward pointing normal for the orientation of $S$.
So we have:
$$~
```math
\iiint_V \frac{\partial{\rho}}{\partial{t}} dV =
-\oint_S (\rho v)\cdot\hat{N} dS = - \iiint_V \nabla\cdot\left(\rho v\right)dV.
~$$
```
The last equality by the divergence theorem, the minus sign as a positive change in amount within $V$ means flow *opposite* the outward pointing normal for $S$.
@ -995,9 +1005,9 @@ The volume $V$ was arbitrary. While it isn't the case that two integrals being e
That is, under the *assumptions* that material is conserved and density is continuous a continuity equation can be derived from the divergence theorem:
$$~
```math
\nabla\cdot(\rho v) = - \frac{\partial{\rho}}{dt}.
~$$
```
@ -1018,11 +1028,11 @@ The simplification done by SymPy masks the presence of $R^{-5/2}$ when taking th
*Were* the divergence theorem applicable, then the integral of $F$ over the unit sphere would mean:
$$~
```math
0 = \iiint_V \nabla\cdot{F} dV =
\oint_S F\cdot{N}dS = \oint_S \frac{R}{\|R\|^3} \cdot{R} dS =
\oint_S 1 dS = 4\pi.
~$$
```
Clearly, as $0$ is not equal to $4\pi$, the divergence theorem can not apply.
@ -1045,8 +1055,8 @@ L"We must have $\text{curl}(F) = 1$",
L"We must have $\text{curl}(F) = 0$",
L"We must have $\text{curl}(F) = x$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1074,8 +1084,8 @@ raw" ``(1/2) \int r d\theta``",
raw" ``\int r^2 d\theta``",
raw" ``(1/2) \int r^2d\theta``"
]
ans=4
radioq(choices, ans)
answ=4
radioq(choices, answ)
```
@ -1094,8 +1104,8 @@ raw" ``3\pi/8``",
raw" ``\pi/4``",
raw" ``\pi/2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1110,8 +1120,8 @@ raw" ``0``",
raw" ``1``",
raw" ``2``"
]
ans =1
radioq(choices, ans, keep_order=true)
answ =1
radioq(choices, answ, keep_order=true)
```
As the curl is a constant, say $c$, we have $\iint_S (\nabla\times{F}) dS = c \cdot 1$. This is?
@ -1122,8 +1132,8 @@ raw" ``0``",
raw" ``1``",
raw" ``2``"
]
ans =1
radioq(choices, ans, keep_order=true)
answ =1
radioq(choices, answ, keep_order=true)
```
To integrate around the boundary we have ``4`` terms: the path $A$ connecting $(0,0)$ to $(1,0)$ (on the $x$ axis), the path $B$ connecting $(1,0)$ to $(1,1)$, the path $C$ connecting $(1,1)$ to $(0,1)$, and the path $D$ connecting $(0,1)$ to $(0,0)$ (along the $y$ axis).
@ -1132,8 +1142,8 @@ Which path has tangent $\hat{j}$?
```julia; hold=true; echo=false
choices = ["`` A``","`` B``"," ``C``"," ``D``"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
Along path $C$, $F(x,y) = [1,x]$ and $\hat{T}=-\hat{i}$ so $F\cdot\hat{T} = -1$. The path integral $\int_C (F\cdot\hat{T})ds = -1$. What is the value of the path integral over $A$?
@ -1144,8 +1154,8 @@ raw" ``-1``",
raw" ``0``",
raw" ``1``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
What is the integral over the oriented boundary of $S$?
@ -1156,8 +1166,8 @@ raw" ``0``",
raw" ``1``",
raw" ``2``"
]
ans =1
radioq(choices, ans, keep_order=true)
answ =1
radioq(choices, answ, keep_order=true)
```
@ -1171,8 +1181,8 @@ choices = [
L"They are the same, as Green's theorem applies to the area, $S$, between $C_1$ and $C_2$ so $\iint_S \nabla\cdot{F}dA = 0$."
L"They differ by a minus sign, as Green's theorem applies to the area, $S$, between $C_1$ and $C_2$ so $\iint_S \nabla\cdot{F}dA = 0$."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1185,8 +1195,8 @@ choices = [
L"Also $2\pi$, as Green's theorem applies to the region formed by the square minus the circle and so the overall flow integral around the boundary is $0$, so the two will be the same.",
L"It is $-2\pi$, as Green's theorem applies to the region formed by the square minus the circle and so the overall flow integral around the boundary is $0$, so the two will have opposite signs, but the same magnitude."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1199,8 +1209,8 @@ raw" ``4/3 \pi``",
raw" ``4\pi``",
raw" ``\pi``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1214,8 +1224,8 @@ raw" ``1``",
raw" ``2``",
raw" ``3``"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -1229,8 +1239,8 @@ raw" ``\log(\rho)``",
raw" ``1/\rho``",
raw" ``\rho``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Based on this information, for $S$ a surface not including the origin with boundary $C$, a simple closed curve, what is $\oint_C F\cdot\hat{T}ds$?
@ -1240,8 +1250,8 @@ choices = [
L"It is $0$, as, by Stoke's theorem, it is equivalent to $\iint_S (\nabla\times\nabla{\phi})dS = \iint_S 0 dS = 0$.",
L"It is $2\pi$, as this is the circumference of the unit circle"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1254,8 +1264,8 @@ raw" ``2\pi``",
raw" ``2``",
raw" ``0``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1274,8 +1284,8 @@ choices = [
"the field is *not* conservative.",
"the field *is* conservative"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
###### Question
@ -1311,8 +1321,8 @@ choices = [
"The maximum number in a row",
"The row number plus 1"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1321,10 +1331,10 @@ radioq(choices, ans)
In 1846, Cauchy proved
$$~
```math
\int\left(p\frac{dx}{ds} + q \frac{dy}{ds}\right)ds =
\pm\iint\left(\frac{\partial{p}}{\partial{y}} - \frac{\partial{q}}{\partial{x}}\right)dx dy.
~$$
```
This is a form of:
@ -1334,6 +1344,6 @@ choices = [
"The divergence (Gauss') theorem",
"Stokes' theorem"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```

View File

@ -13,12 +13,12 @@ using Roots
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
title = "Arc length",
description = "Calculus with Julia: Arc length",
tags = ["CalculusWithJulia", "integrals", "arc length"],
frontmatter = (
title = "Arc length",
description = "Calculus with Julia: Arc length",
tags = ["CalculusWithJulia", "integrals", "arc length"],
);
fig_size=(600, 400)
fig_size=(800, 600)
nothing
```
@ -57,20 +57,15 @@ f'(t)^2}$ is Riemann integrable.
> For the special case of the graph of a function $f(x)$ between $a$ and $b$ the formula becomes $L = \int_a^b \sqrt{ 1 + f'(x)^2} dx$ (taking $g(t) = t$).
```julia; echo=false
note(L"""
The form of the integral may seem daunting with the square root and
the derivatives. A more general writing would create a vector out of
the two functions: $\phi(t) = \langle g(t), f(t) \rangle$. It is
natural to then let $\phi'(t) = \langle g'(t), f'(t) \rangle$. With
this, the integrand is just the norm - or length - of the
derivative, or $L=\int \| \phi'(t) \| dt$. This is similar to the
distance traveled being the integral of the speed, or the absolute
value of the derivative of position.
""")
```
!!! note
The form of the integral may seem daunting with the square root and
the derivatives. A more general writing would create a vector out of
the two functions: $\phi(t) = \langle g(t), f(t) \rangle$. It is
natural to then let $\phi'(t) = \langle g'(t), f'(t) \rangle$. With
this, the integrand is just the norm - or length - of the
derivative, or $L=\int \| \phi'(t) \| dt$. This is similar to the
distance traveled being the integral of the speed, or the absolute
value of the derivative of position.
To see why, any partition of the interval $[a,b]$ by $a = t_0 < t_1 < \cdots < t_n =b$ gives rise to $n+1$ points in the plane given by $(g(t_i), f(t_i))$.
@ -154,25 +149,20 @@ L = \int_a^b \sqrt{f'(t)^2 + g'(t)^2} dt.
(This needs a technical adjustment to the Riemann theorem, as we are evaluating our function at two points in the interval. A general proof is [here](https://randomproofs.files.wordpress.com/2010/11/arc_length.pdf).)
```julia; echo=false
note(L"""
!!! note
[Bressoud](http://www.math.harvard.edu/~knill/teaching/math1a_2011/exhibits/bressoud/)
notes that Gregory (1668) proved this formula for arc length of the
graph of a function by showing that the length of the curve $f(x)$ is defined
by the area under $\sqrt{1 + f'(x)^2}$. (It is commented that this was
also known a bit earlier by von Heurat.) Gregory went further though,
as part of the fundamental theorem of calculus was contained in his
work. Gregory then posed this inverse question: given a curve
$y=g(x)$ find a function $u(x)$ so that the area under $g$ is equal to
the length of the second curve. The answer given was $u(x) =
(1/c)\int_a^x \sqrt{g^2(t) - c^2}$, which if $g(t) = \sqrt{1 + f'(t)^2}$
and $c=1$ says $u(x) = \int_a^x f(t)dt$.
[Bressoud](http://www.math.harvard.edu/~knill/teaching/math1a_2011/exhibits/bressoud/)
notes that Gregory (1668) proved this formula for arc length of the
graph of a function by showing that the length of the curve $f(x)$ is defined
by the area under $\sqrt{1 + f'(x)^2}$. (It is commented that this was
also known a bit earlier by von Heurat.) Gregory went further though,
as part of the fundamental theorem of calculus was contained in his
work. Gregory then posed this inverse question: given a curve
$y=g(x)$ find a function $u(x)$ so that the area under $g$ is equal to
the length of the second curve. The answer given was $u(x) =
(1/c)\int_a^x \sqrt{g^2(t) - c^2}$, which if $g(t) = \sqrt{1 + f'(t)^2}$
and $c=1$ says $u(x) = \int_a^x f(t)dt$.
An analogy might be a sausage maker. These take a mass of ground-up sausage material and return a long length of sausage. The material going in would depend on time via an equation like $\int_0^t g(u) du$ and the length coming out would be a constant (accounting for the cross section) times $u(t) = \int_0^t \sqrt{1 + g'(s)} ds$.
""")
```
An analogy might be a sausage maker. These take a mass of ground-up sausage material and return a long length of sausage. The material going in would depend on time via an equation like $\int_0^t g(u) du$ and the length coming out would be a constant (accounting for the cross section) times $u(t) = \int_0^t \sqrt{1 + g'(s)} ds$.
#### Examples
@ -194,13 +184,8 @@ f(x) = x^2
plot(f, 0, 1)
```
```julia; echo=false
note(L"""
The integrand $\sqrt{1 + f'(x)^2}$ may seem odd at first, but it can be interpreted as the length of the hypotenuse of a right triangle with "run" of $1$ and "rise" of $f'(x)$. This triangle is easily formed using the tangent line to the graph of $f(x)$. By multiplying by $dx$, the integral is "summing" up the lengths of infinitesimal pieces of the tangent line approximation.
""")
```
!!! note
The integrand $\sqrt{1 + f'(x)^2}$ may seem odd at first, but it can be interpreted as the length of the hypotenuse of a right triangle with "run" of $1$ and "rise" of $f'(x)$. This triangle is easily formed using the tangent line to the graph of $f(x)$. By multiplying by $dx$, the integral is "summing" up the lengths of infinitesimal pieces of the tangent line approximation.
##### Example
@ -705,8 +690,8 @@ f(x) = \left(\frac{g}{k v_0\cos(\theta)} + \tan(\theta) \right) x + \frac{g}{k^2
This comes from solving the projectile motion equations with a drag force *proportional* to the velocity. This function satisfies:
```julia; hold=true
@syms g::postive, k::postive, v₀::positive, θ::postive, x::postive
ex = (g/(k*v₀*cos(θ)) + tan(θ))*x + g/k^2 * log(1 - k/(v₀*cos(θ))*x)
@syms g::postive, k::postive, v₀::positive, θ::postive, x::postive
ex = (g/(k*v₀*cos(θ)) + tan(θ))*x + g/k^2 * log(1 - k/(v₀*cos(θ))*x)
diff(ex, x, x), diff(ex, x, x, x,)
```
@ -857,16 +842,16 @@ y = a \ln\frac{a + \sqrt{a^2 - x^2}}{x} - \sqrt{a^2 - x^2}
This can be entered into `julia` as:
```julia;
g(x, a) = a * log((a + sqrt(a^2 - x^2))/x) - sqrt(a^2 - x^2)
h(x, a) = a * log((a + sqrt(a^2 - x^2))/x) - sqrt(a^2 - x^2)
```
Let $a=12$, $f(x) = g(x, a)$. Compute the length the bow of the
Let $a=12$, $f(x) = h(x, a)$. Compute the length the bow of the
boat has traveled between $x=1$ and $x=a$ using `quadgk`.
```julia; hold=true; echo=false
a = 12
f(x) = g(x, a);
f(x) = h(x, a);
val = quadgk(x -> sqrt(1 + D(f)(x)^2), 1, a)[1];
numericq(val, 1e-3)
```
@ -874,13 +859,8 @@ numericq(val, 1e-3)
(The most elementary description of this curve is in terms
of the relationship $dy/dx = -\sqrt{a^2-x^2}/x$ which could be used in place of `D(f)` in your work.)
```julia; hold=true; echo=false
note("""
To see an example of how the tractrix can be found in an everyday observation, follow this link on a description of [bicycle](https://simonsfoundation.org/multimedia/mathematical-impressions-bicycle-tracks) tracks.
""")
```
!!! note
To see an example of how the tractrix can be found in an everyday observation, follow this link on a description of [bicycle](https://simonsfoundation.org/multimedia/mathematical-impressions-bicycle-tracks) tracks.
###### Question
@ -905,12 +885,14 @@ radioq(choices, 1)
A curve is parameterized by $g(t) = t + \sin(t)$ and $f(t) = \cos(t)$. Find the arc length of the curve between $t=0$ and $\pi$.
```julia; hold=true; echo=false
g(t) = t + sin(t)
f(t) = cos(t)
a, b = 0, pi
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), a, b)
numericq(val)
```julia; echo=false
let
g(t) = t + sin(t)
f(t) = cos(t)
a, b = 0, pi
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), a, b)
numericq(val)
end
```
###### Question
@ -918,24 +900,28 @@ numericq(val)
The [astroid](http://www-history.mcs.st-and.ac.uk/Curves/Astroid.html) is
a curve parameterized by $g(t) = \cos(t)^3$ and $f(t) = \sin(t)^3$. Find the arc length of the curve between $t=0$ and $2\pi$. (This can be computed by hand or numerically.)
```julia; hold=true; echo=false
g(t) = cos(t)^3
f(t) = sin(t)^3
a, b = 0, 2pi
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), a, b)
numericq(val)
```julia; echo=false
let
g(t) = cos(t)^3
f(t) = sin(t)^3
a, b = 0, 2pi
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), a, b)
numericq(val)
end
```
###### Question
A curve is parameterized by $g(t) = (2t + 3)^{2/3}/3$ and $f(t) = t + t^2/2$, for $0\leq t \leq 3$. Compute the arc-length numerically or by hand:
```julia; hold=true; echo=false
g(t) = (2t+3)^(2/3)/3
f(t) = t + t^2/2
a, b = 0, 3
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), a, b)
numericq(val)
```julia; echo=false
let
g(t) = (2t+3)^(2/3)/3
f(t) = t + t^2/2
a, b = 0, 3
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), a, b)
numericq(val)
end
```
@ -944,12 +930,14 @@ numericq(val)
The cycloid is parameterized by $g(t) = a(t - \sin(t))$ and $f(t) = a(1 - \cos(t))$ for $a > 0$. Taking $a=3$, and $t$ in $[0, 2\pi]$, find the length of the curve traced out. (This was solved by the architect and polymath [Wren](https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/January%202010/3%20Articles/3%20Martin/08-170.pdf) in 1650.)
```julia; hold=true; echo=false
a = 3
g(t) = a*(t - sin(t))
f(t) = a*(1 - cos(t))
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), 0, 2pi)
numericq(val)
```julia; echo=false
let
a = 3
g(t) = a*(t - sin(t))
f(t) = a*(1 - cos(t))
val, _ = quadgk( x -> sqrt(D(g)(x)^2 + D(f)(x)^2), 0, 2pi)
numericq(val)
end
```
A cycloid parameterized this way can be generated by a circle of radius ``a``. Based on this example, what do you think Wren wrote to Pascal about this length:
@ -964,20 +952,16 @@ circle."]
radioq(choices, 3, keep_order=true)
```
```julia; hold=true; echo=false
note("""
In [Martin](https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/January%202010/3%20Articles/3%20Martin/08-170.pdf) we read why Wren was mailing Pascal:
!!! note
In [Martin](https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/January%202010/3%20Articles/3%20Martin/08-170.pdf) we read why Wren was mailing Pascal:
After demonstrating mathematical talent at an early age, Blaise Pascal
turned his attention to theology, denouncing the study of mathematics
as a vainglorious pursuit. Then one night, unable to sleep as the
result of a toothache, he began thinking about the cycloid and to his
surprise, his tooth stopped aching. Taking this as a sign that he had
Gods approval to continue, Pascal spent the next eight days studying
the curve. During this time he discovered nearly all of the geometric
properties of the cycloid. He issued some of his results in ``1658`` in
the form of a contest, offering a prize of forty Spanish gold pieces
and a second prize of twenty pieces.
""")
```
After demonstrating mathematical talent at an early age, Blaise Pascal
turned his attention to theology, denouncing the study of mathematics
as a vainglorious pursuit. Then one night, unable to sleep as the
result of a toothache, he began thinking about the cycloid and to his
surprise, his tooth stopped aching. Taking this as a sign that he had
Gods approval to continue, Pascal spent the next eight days studying
the curve. During this time he discovered nearly all of the geometric
properties of the cycloid. He issued some of his results in ``1658`` in
the form of a contest, offering a prize of forty Spanish gold pieces
and a second prize of twenty pieces.

View File

@ -14,7 +14,7 @@ using Roots
using CalculusWithJulia.WeaveSupport
fig_size = (600, 400)
fig_size = (800, 600)
using Markdown, Mustache
const frontmatter = (
@ -284,17 +284,13 @@ first $n$ natural numbers.
With this expression, it is readily seen that as $n$ gets large this value gets close to $2/6 = 1/3$.
```julia; echo=false
note("""
!!! note
The above approach, like Archimedes', ends with a limit being
taken. The answer comes from using a limit to add a big number of
small values. As with all limit questions, worrying about whether a
limit exists is fundamental. For this problem, we will see that for
the general statement there is a stretching of the formal concept of a limit.
The above approach, like Archimedes', ends with a limit being
taken. The answer comes from using a limit to add a big number of
small values. As with all limit questions, worrying about whether a
limit exists is fundamental. For this problem, we will see that for
the general statement there is a stretching of the formal concept of a limit.
""")
```
----
@ -897,17 +893,12 @@ derivative over $[a,b]$. This is significant, the error in $10$ steps
of Simpson's rule is on the scale of the error of $10,000$ steps of
the Riemann sum for well-behaved functions.
```julia; echo=false
note(L"""
The Wikipedia article mentions that Kepler used a similar formula $100$
years prior to Simpson, or about $200$ years before Riemann published
his work. Again, the value in Riemann's work is not the computation of
the answer, but the framework it provides in determining if a function
is Riemann integrable or not.
""")
```
!!! note
The Wikipedia article mentions that Kepler used a similar formula $100$
years prior to Simpson, or about $200$ years before Riemann published
his work. Again, the value in Riemann's work is not the computation of
the answer, but the framework it provides in determining if a function
is Riemann integrable or not.
## Gauss quadrature
@ -1289,8 +1280,8 @@ choices = [
"``p``",
"``1-p``",
"``p^2``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -1303,8 +1294,8 @@ choices = [
"``2^5/5 - 0^5/5``",
"``2^4/4 - 0^4/4``",
"``3\\cdot 2^3 - 3 \\cdot 0^3``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -1344,8 +1335,8 @@ L"The area between $c$ and $b$ must be positive, so $F(c) < F(b)$.",
"``F(b) - F(c) = F(a).``",
L" $F(x)$ is continuous, so between $a$ and $b$ has an extreme value, which must be at $c$. So $F(c) \geq F(b)$."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1359,8 +1350,8 @@ choices = [
"``10/100``",
"``(10 - 0) \\cdot e^{10} / 100^4``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1440,9 +1431,11 @@ The area under a curve approximated by a Riemann sum.
#CalculusWithJulia.WeaveSupport.JSXGraph(:integrals, url, caption)
# This is just wrong...
url = "https://raw.githubusercontent.com/jverzani/CalculusWithJulia.jl/master/CwJ/integrals/riemann.js"
url = "./riemann.js"
CalculusWithJulia.WeaveSupport.JSXGraph(url, caption)
```
The interactive graphic shows the area of a right-Riemann sum for different partitions. The function is
```math
@ -1502,8 +1495,8 @@ L"around $10^{-2}$",
L"around $10^{-4}$",
L"around $10^{-6}$",
L"around $10^{-8}$"]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
###### Question

View File

@ -317,13 +317,9 @@ g1(y)=exp(y)-1 # y=log(x+1) so e^y = x + 1, x = e^y - 1
quadgk(y -> f1(y) - g1(y), a1, b1)[1]
```
```julia; echo=false
note("""
!!! note
When doing problems by hand this latter style can often reduce the complications, but when approaching the task numerically, the first two styles are generally easier, though computationally more expensive.
When doing problems by hand this latter style can often reduce the complications, but when approaching the task numerically, the first two styles are generally easier, though computationally more expensive.
""")
```
#### Integrating in different directions
@ -427,7 +423,7 @@ Find the area enclosed by the curves $y=2-x^2$ and $y=x^2 - 3$.
```julia; hold=true; echo=false
f(x) = 2 - x^2
g(x) = x^2 - 3
a,b = find_zeros(x -> f(x) - g(x), -10,10)
a,b = find_zeros(x -> f(x) - g(x), -10, 10)
val, _ = quadgk(x -> f(x) - g(x), a, b)
numericq(val)
```
@ -569,16 +565,12 @@ Is the guess that the entire sculpture is more than two tons?
```julia; hold=true; echo=false
choices=["Less than two tons", "More than two tons"]
ans = 2
radioq(choices, ans, keep_order=true)
```
```julia; hold=true; echo=false
note("""
We used area to estimate weight in this example, but Galileo used weight to estimate area. It is [mentioned](https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/January%202010/3%20Articles/3%20Martin/08-170.pdf) by Martin that in order to estimate the area enclosed by one arch of a cycloid, Galileo cut the arch from from some material and compared the weight to the weight of the generating circle. He concluded the area is close to ``3`` times that of the circle, a conjecture proved by Roberval in 1634.
""")
answ = 2
radioq(choices, answ, keep_order=true)
```
!!! note
We used area to estimate weight in this example, but Galileo used weight to estimate area. It is [mentioned](https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/January%202010/3%20Articles/3%20Martin/08-170.pdf) by Martin that in order to estimate the area enclosed by one arch of a cycloid, Galileo cut the arch from from some material and compared the weight to the weight of the generating circle. He concluded the area is close to ``3`` times that of the circle, a conjecture proved by Roberval in 1634.
###### Question

View File

@ -192,13 +192,9 @@ cm = top / bottom
Our guess from the diagram proves correct.
```julia; echo=false
note("""
!!! note
It proves convenient to use the `->` notation for an anonymous function above, as our function `h` is not what is being integrated all the time, but some simple modification. If this isn't palatable, a new function could be defined and passed along to `quadgk`.
It proves convenient to use the `->` notation for an anonymous function above, as our function `h` is not what is being integrated all the time, but some simple modification. If this isn't palatable, a new function could be defined and passed along to `quadgk`.
""")
```
##### Example
@ -220,13 +216,9 @@ For fun, we compare this to the median, which is the value $M$ so that the total
Solving $1/2 = 1 - e^{-M}$ gives $M=\log(2) = 0.69...$, The median is to the left of the mean in this example.
```julia; echo=false
note("""
!!! note
In this example, we used an infinite region, so the idea of "balancing" may be a bit unrealistic, nonetheless, this intuitive interpretation is still a good one to keep this in mind. The point of comparing to the median is that the balancing point is to the right of where the area splits in half. Basically, the center of mass follows in the direction of the area far to the right of the median, as this area is skewed in that direction.
In this example, we used an infinite region, so the idea of "balancing" may be a bit unrealistic, nonetheless, this intuitive interpretation is still a good one to keep this in mind. The point of comparing to the median is that the balancing point is to the right of where the area splits in half. Basically, the center of mass follows in the direction of the area far to the right of the median, as this area is skewed in that direction.
""")
```
##### Example
@ -308,13 +300,9 @@ integrate(x*fx, (x, 0, b)) / integrate(fx, (x, 0, b))
But really, we should have just noted that simply by switching the labels $a$ and $b$ in the diagram we could have discovered this formula.
```julia; echo=false
note(L"""
!!! note
The [centroid](http://en.wikipedia.org/wiki/Centroid) of a region in the plane is just $(\text{cm}_x, \text{cm}_y)$. This last fact says the centroid of the right triangle is just $(b/3, a/3)$. The centroid can be found by other geometric means. The link shows the plumb line method. For triangles, the centroid is also the intersection point of the medians, the lines that connect a vertex with its opposite midpoint.
The [centroid](http://en.wikipedia.org/wiki/Centroid) of a region in the plane is just $(\text{cm}_x, \text{cm}_y)$. This last fact says the centroid of the right triangle is just $(b/3, a/3)$. The centroid can be found by other geometric means. The link shows the plumb line method. For triangles, the centroid is also the intersection point of the medians, the lines that connect a vertex with its opposite midpoint.
""")
```
##### Example

View File

@ -18,7 +18,7 @@ const frontmatter = (
description = "Calculus with Julia: Fundamental Theorem or Calculus",
tags = ["CalculusWithJulia", "integrals", "fundamental theorem or calculus"],
);
fig_size = (600, 400)
fig_size = (800, 600)
nothing
```
@ -107,11 +107,15 @@ definite integral and the derivative we have
```math
\begin{align*}
F'(x) = & \frac{d}{dx} \int_a^x f(u) du \\
& \approx \frac{F(x) - F(x-h)}{h} = \frac{\int_a^x f(u) du - \int_a^{x-h} f(u) du}{h}\\
& \approx \frac{\left(f(a + 1h)h + f(a + 2h)h + \cdots + f(a + (M-1)h)h + f(a + Mh)h\right)}{h} -
& \approx \frac{F(x) - F(x-h)}{h} \\
&= \frac{\int_a^x f(u) du - \int_a^{x-h} f(u) du}{h}\\
& \approx \frac{\left(f(a + 1h)h + f(a + 2h)h + \cdots + f(a + (M-1)h)h + f(a + Mh)h\right)}{h}\\
&- \quad
\frac{\left(f(a + 1h)h + f(a + 2h)h + \cdots + f(a + (M-1)h)h \right)}{h} \\
& = \left(f(a + 1h) + f(a + 2h) + \cdots + f(a + (M-1)h) + f(a + Mh)\right) -
\left(f(a + 1h) + f(a + 2h) + \cdots + f(a + (M-1)h) \right)
& = \left(f(a + 1h) + \quad f(a + 2h) + \cdots + f(a + (M-1)h) + f(a + Mh)\right)\\
&- \quad
\left(f(a + 1h) + f(a + 2h) + \cdots + f(a + (M-1)h) \right) \\
&= f(a + Mh).
\end{align*}
```
@ -152,20 +156,15 @@ With these heuristics, we now have:
```julia; echo=false
note(L"""
In Part 1, the integral $F(x) = \int_a^x f(u) du$ is defined for any
Riemann integrable function, $f$. If the function is not continuous,
then it is true the $F$ will be continuous, but it need not be true
that it is differentiable at all points in $(a,b)$. Forming $F$ from
$f$ is a form of *smoothing*. It makes a continuous function out of an
integrable one, a differentiable function from a continuous one, and a
$k+1$-times differentiable function from a $k$-times differentiable
one.
""")
```
!!! note
In Part 1, the integral $F(x) = \int_a^x f(u) du$ is defined for any
Riemann integrable function, $f$. If the function is not continuous,
then it is true the $F$ will be continuous, but it need not be true
that it is differentiable at all points in $(a,b)$. Forming $F$ from
$f$ is a form of *smoothing*. It makes a continuous function out of an
integrable one, a differentiable function from a continuous one, and a
$k+1$-times differentiable function from a $k$-times differentiable
one.
## Using the fundamental theorem of calculus to evaluate definite integrals
@ -616,7 +615,7 @@ We need to figure out when this is $0$. For that, we use some numeric math.
```julia;
F(x) = exp(-x^2) * quadgk(t -> exp(t^2), 0, x)[1]
Fp(x) = -2x*F(x) + 1
cps = find_zeros(Fp, -4,4)
cps = find_zeros(Fp, -4, 4)
```
We could take a second derivative to characterize. For that we use
@ -714,14 +713,8 @@ dx``, using linearity, as ``\int_0^{x_0} f(x) dx +
\int_{x_{n-1}}^{x_n}f(x)dx``. Then all but the last term could be
stored from the previous steps of Newton's method. The last term presumably being less costly as it would typically involve a small interval.
```julia;echo=false
note("""
The trick using a closure relies on an internal way of accessing elements in a closure. The same trick could be implemented many different ways which aren't reliant on undocumented internals, this approach was just a tad more convenient. It shouldn't be copied for work intended for distribution, as the internals may change without notice or deprecation.
""")
```
!!! note
The trick using a closure relies on an internal way of accessing elements in a closure. The same trick could be implemented many different ways which aren't reliant on undocumented internals, this approach was just a tad more convenient. It shouldn't be copied for work intended for distribution, as the internals may change without notice or deprecation.
##### Example
@ -898,8 +891,8 @@ choices = [
"``-x^2\\cos(x) + 2x\\sin(x)``",
"``-x^2\\cos(x) + 2x\\sin(x) + 2\\cos(x)``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -914,8 +907,8 @@ choices = [
"``-(1+x) e^{-x}``",
"``-(1 + x + x^2) e^{-x}``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -978,8 +971,8 @@ choices = [
L"Between $0$ and $1$",
L"Between $1$ and $5$"
]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
* The position of the particle is $0$ at $t=0$ and:
@ -990,8 +983,8 @@ choices = [
"``t=2``",
"``t=3``",
"``t=4``"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
* The position of the particle at time $t=5$ is?
@ -1010,8 +1003,8 @@ L"The position, $x(t)$, increases with a slope of $1$",
L"The position, $x(t)$, increases quadratically from $-1/2$ to $1$",
L"The position, $x(t)$, increases quadratically from $0$ to $1$"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1024,8 +1017,8 @@ choices = [
"``-f(t-10)``",
"``f(t) - f(t-10)``"
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1037,8 +1030,8 @@ choices = [
"At a critical point",
L"At the endpoint $0$",
L"At the endpoint $1$"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1058,8 +1051,8 @@ choices = [
"The derivative of ``F`` is ``f``, so by the second derivative test, ``x=7``",
"The graph of ``f`` has relative maxima at ``x=2,6,8``"
]
answer = 2
radioq(choices, answer)
answ = 2
radioq(choices, answ)
```
@ -1073,8 +1066,8 @@ L"At a critical point, either $0$ or $1$",
L"At a critical point, $1/2$",
L"At the endpoint $0$",
L"At the endpoint $1$"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1122,8 +1115,8 @@ choices = [
"``A(x) / \\lvert Tx \\rvert = A'(x)``",
"``A(x) \\cdot A'(x) = f(x)``"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
The fact that $\lvert PT \rvert$ is tangent says what in terms of $f(x)$, $A(x)$ and $A'(x)$?
@ -1135,8 +1128,8 @@ choices = [
"``A(x) / \\lvert Tx \\rvert = A'(x)``",
"``A(x) \\cdot A'(x) = f(x)``"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
Solving, we get:
@ -1148,8 +1141,8 @@ choices = [
"``A'(x) = A(x)``",
"``A(x) = f(x)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1160,20 +1153,20 @@ According to [Bressoud](http://www.math.harvard.edu/~knill/teaching/math1a_2011/
choices = [
L"Part 1: $[\int_a^x f(u) du]' = f$",
L"Part 2: $\int_a^b f(u) du = F(b)- F(a)$."]
ans=1
radioq(choices, ans, keep_order=true)
answ=1
radioq(choices, answ, keep_order=true)
```
## More on SymPy's `integrate`
Finding the value of a definite integral through the fundamental theorem of calculus relies on the algebraic identification of an antiderivative. This is difficult to do by hand and by computer, and is complicated by the fact that not every [elementary ](https://en.wikipedia.org/wiki/Elementary_function)function has an elementary antiderivative.
`SymPy`'s documentation on integration indicates that several different means to integrate a function are used internally. As it is of interest here, it is copied with just minor edits below:
`SymPy`'s documentation on integration indicates that several different means to integrate a function are used internally. As it is of interest here, it is copied with just minor edits below (from an older version of SymPy):
#### Simple heuristics (based on pattern matching and integral table):
* most frequently used functions (e.g. polynomials, products of trigonemetric functions)
* most frequently used functions (e.g. polynomials, products of trigonometric functions)
#### Integration of rational functions:
@ -1250,4 +1243,4 @@ Finding the value of a definite integral through the fundamental theorem of calc
is to implement enough of the Risch and Meijer G-function methods
so that this can be deleted.
Setting `heurisch=true` will cause `integrate` to use only this
method. Set `heurisch=false to not use it.
method. Set `heurisch=false` to not use it.

View File

@ -17,7 +17,7 @@ const frontmatter = (
description = "Calculus with Julia: Improper Integrals",
tags = ["CalculusWithJulia", "integrals", "improper integrals"],
);
fig_size=(600, 400)
fig_size=(800, 600)
nothing
```
@ -108,10 +108,8 @@ For the interval $(-\infty, \infty)$ we have need *both* these limits to exist,
\int_{-\infty}^\infty f(x) dx = \lim_{M \rightarrow -\infty} \int_M^a f(x) dx + \lim_{M \rightarrow \infty} \int_a^M f(x) dx.
```
```julia; echo=false
note("""When the integral exists, it is said to *converge*. If it doesn't exist, it is said to *diverge*.
""")
```
!!! note
When the integral exists, it is said to *converge*. If it doesn't exist, it is said to *diverge*.
##### Examples
@ -201,13 +199,8 @@ Suppose $a < c$, we define $\int_a^c f(x) dx = \lim_{M \rightarrow c-} \int_a^c
= \lim_{M \rightarrow 0+} 2(1) - 2\sqrt{M} = 2.
```
```julia; echo=false
note(L"""
The cases $f(x) = x^{-n}$ for $n > 0$ are tricky to keep straight. For $n > 1$, the functions can be integrated over $[1,\infty)$, but not $(0,1]$. For $0 < n < 1$, the functions can be integrated over $(0,1]$ but not $[1, \infty)$.
""")
```
!!! note
The cases $f(x) = x^{-n}$ for $n > 0$ are tricky to keep straight. For $n > 1$, the functions can be integrated over $[1,\infty)$, but not $(0,1]$. For $0 < n < 1$, the functions can be integrated over $(0,1]$ but not $[1, \infty)$.
* Now consider $f(x) = 1/x$. Is this integral $\int_0^1 1/x \cdot dx$ defined? It will be *if* this limit exists:
@ -417,8 +410,8 @@ choices =[
"It is convergent",
"It is divergent",
"Can't say"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -433,8 +426,8 @@ choices =[
"It is convergent",
"It is divergent",
"Can't say"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
----
@ -450,8 +443,8 @@ choices =[
"It is convergent",
"It is divergent",
"Can't say"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
----
@ -465,8 +458,8 @@ choices =[
"It is convergent",
"It is divergent",
"Can't say"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
----
@ -480,8 +473,8 @@ choices =[
"It is convergent",
"It is divergent",
"Can't say"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -496,8 +489,8 @@ choices = [
"``\\int_0^1 u^{2/3} \\cdot du``",
"``\\int_0^\\infty 1/u \\cdot du``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question

View File

@ -13,10 +13,10 @@ using SymPy
using CalculusWithJulia.WeaveSupport
using QuadGK
const frontmatter = (
title = "Integration By Parts",
description = "Calculus with Julia: Integration By Parts",
tags = ["CalculusWithJulia", "integrals", "integration by parts"],
frontmatter = (
title = "Integration By Parts",
description = "Calculus with Julia: Integration By Parts",
tags = ["CalculusWithJulia", "integrals", "integration by parts"],
);
nothing
@ -41,21 +41,23 @@ Now we turn our attention to the implications of the *product rule*: $[uv]' = u'
The following illustrates integration by parts of the integral $(uv)'$ over
$[a,b]$ [original](http://en.wikipedia.org/wiki/Integration_by_parts#Visualization).
```julia; hold=true; echo=false
## parts picture
u(x) = sin(x*pi/2)
v(x) = x
xs = range(0, stop=1, length=50)
a,b = 1/4, 3/4
p = plot(u, v, 0, 1, legend=false)
plot!(p, zero, 0, 1)
scatter!(p, [u(a), u(b)], [v(a), v(b)], color=:orange, markersize=5)
```julia; echo=false
let
## parts picture
u(x) = sin(x*pi/2)
v(x) = x
xs = range(0, stop=1, length=50)
a,b = 1/4, 3/4
p = plot(u, v, 0, 1, legend=false)
plot!(p, zero, 0, 1)
scatter!(p, [u(a), u(b)], [v(a), v(b)], color=:orange, markersize=5)
plot!(p, [u(a),u(a),0, 0, u(b),u(b),u(a)],
[0, v(a), v(a), v(b), v(b), 0, 0],
linetype=:polygon, fillcolor=:orange, alpha=0.25)
annotate!(p, [(0.65, .25, "A"), (0.4, .55, "B")])
annotate!(p, [(u(a),v(a) + .08, "(u(a),v(a))"), (u(b),v(b)+.08, "(u(b),v(b))")])
plot!(p, [u(a),u(a),0, 0, u(b),u(b),u(a)],
[0, v(a), v(a), v(b), v(b), 0, 0],
linetype=:polygon, fillcolor=:orange, alpha=0.25)
annotate!(p, [(0.65, .25, "A"), (0.4, .55, "B")])
annotate!(p, [(u(a),v(a) + .08, "(u(a),v(a))"), (u(b),v(b)+.08, "(u(b),v(b))")])
end
```
The figure is a parametric plot of $(u,v)$ with the points $(u(a),
@ -200,8 +202,8 @@ e^x(x^2 - 2x - 1) \big|_a^b.
In fact, it isn't hard to see that an integral of $x^m e^x$, $m$ a positive integer, can be handled in this manner. For example, when $m=10$, `SymPy` gives:
```julia;
@syms x
integrate(x^10 * exp(x), x)
@syms 𝒙
integrate(𝒙^10 * exp(𝒙), 𝒙)
```
@ -264,7 +266,7 @@ by a double angle formula application, is $x/2 - \sin(2x)/4$.
`SymPy` is quite able to do this repeated bookkeeping. For example with $n=10$:
```julia;
integrate(cos(x)^10, x)
integrate(cos(𝒙)^10, 𝒙)
```
##### Example
@ -403,17 +405,19 @@ When ``u(t)`` is strictly *increasing*, and hence having an inverse function, th
However, the correct answer requires understanding a minus sign. Consider the area enclosed by ``x(t) = \cos(t), y(t) = \sin(t)``:
```julia; hold=true; echo=false
r(t) = [cos(t), sin(t)]
p=plot_parametric(0..2pi, r, aspect_ratio=:equal, legend=false)
for t ∈ (pi/4, 3pi/4, 5pi/4, 7pi/4)
quiver!(unzip([r(t)])..., quiver=Tuple(unzip([0.1*r'(t)])))
```julia; echo=false
let
r(t) = [cos(t), sin(t)]
p=plot_parametric(0..2pi, r, aspect_ratio=:equal, legend=false)
for t ∈ (pi/4, 3pi/4, 5pi/4, 7pi/4)
quiver!(unzip([r(t)])..., quiver=Tuple(unzip([0.1*r'(t)])))
end
ti, tj = pi/3, pi/3+0.1
plot!([cos(tj), cos(ti), cos(ti), cos(tj), cos(tj)], [0,0,sin(tj), sin(tj),0])
quiver!([0],[0], quiver=Tuple(unzip([r(ti)])))
quiver!([0],[0], quiver=Tuple(unzip([r(tj)])))
p
end
ti, tj = pi/3, pi/3+0.1
plot!([cos(tj), cos(ti), cos(ti), cos(tj), cos(tj)], [0,0,sin(tj), sin(tj),0])
quiver!([0],[0], quiver=Tuple(unzip([r(ti)])))
quiver!([0],[0], quiver=Tuple(unzip([r(tj)])))
p
```
@ -441,10 +445,10 @@ This is a case of [Green's Theorem](https://en.wikipedia.org/wiki/Green%27s_theo
Apply the formula to a parameterized circle to ensure, the signed area is properly computed. If we use ``x(t) = r\cos(t)`` and ``y(t) = r\sin(t)`` then we have the motion is counterclockwise:
```julia; hold=true
@syms r t
x(t) = r*cos(t)
y(t) = r*sin(t)
-integrate(y(t) * diff(x(t), t), (t, 0, 2PI))
@syms 𝒓 t
𝒙 = 𝒓 * cos(t)
𝒚 = 𝒓 * sin(t)
-integrate(𝒚 * diff(𝒙, t), (t, 0, 2PI))
```
We see the expected answer for the area of a circle.
@ -458,9 +462,9 @@ Working symbolically, we have one arch given by the following described in a *cl
```julia; hold=true
@syms t
x = t - sin(t)
y = 1 - cos(t)
integrate(y * diff(x, t), (t, 0, 2PI))
𝒙 = t - sin(t)
𝒚 = 1 - cos(t)
integrate(𝒚 * diff(𝒙, t), (t, 0, 2PI))
```
([Galileo](https://mathshistory.st-andrews.ac.uk/Curves/Cycloid/) was thwarted in finding this answer exactly and resorted to constructing one from metal to *estimate* the value.)
@ -469,20 +473,24 @@ integrate(y * diff(x, t), (t, 0, 2PI))
Consider the example ``x(t) = \cos(t) + t\sin(t), y(t) = \sin(t) - t\cos(t)`` for ``0 \leq t \leq 2\pi``.
```julia; hold=true; echo=false
x(t) = cos(t) + t*sin(t)
y(t) = sin(t) - t*cos(t)
ts = range(0,2pi, length=100)
plot(x.(ts), y.(ts))
```julia; echo=false
let
x(t) = cos(t) + t*sin(t)
y(t) = sin(t) - t*cos(t)
ts = range(0,2pi, length=100)
plot(x.(ts), y.(ts))
end
```
How much area is enclosed by this curve and the ``x`` axis? The area is described in a counterclockwise manner, so we have:
```julia; hold=true
x(t) = cos(t) + t*sin(t)
y(t) = sin(t) - t*cos(t)
yx(t) = -y(t) * x'(t) # yx\prime[tab]
quadgk(yx, 0, 2pi)
let
x(t) = cos(t) + t*sin(t)
y(t) = sin(t) - t*cos(t)
yx(t) = -y(t) * x'(t) # yx\prime[tab]
quadgk(yx, 0, 2pi)
end
```
This particular problem could also have been done symbolically, but many curves will need to have a numeric approximation used.
@ -500,8 +508,8 @@ choices = [
"``du=1/x dx \\quad v = x``",
"``du=x\\log(x) dx\\quad v = 1``",
"``du=1/x dx\\quad v = x^2/2``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -514,8 +522,8 @@ choices = [
"``du=\\csc(x) dx \\quad v=\\sec(x)^3 / 3``",
"``du=\\tan(x) dx \\quad v=\\sec(x)\\tan(x)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -530,8 +538,8 @@ choices = [
"``du=-e^{-x} dx \\quad v=-\\sin(x)``",
"``du=\\sin(x)dx \\quad v=-e^{-x}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -581,8 +589,8 @@ choices = [
"``\\int (\\log(x))^{n+1}/(n+1) dx``",
"``x(\\log(x))^n - \\int (\\log(x))^{n-1} dx``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -597,8 +605,8 @@ Consider the integral $\int x \cos(x) dx$. Which letter should be tried first?
```julia; hold=true; echo=false
choices = ["L", "I", "A", "T", "E"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
----
@ -608,8 +616,8 @@ Consider the integral $\int x^2\log(x) dx$. Which letter should be tried first?
```julia; hold=true; echo=false
choices = ["L", "I", "A", "T", "E"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
----
@ -619,8 +627,8 @@ Consider the integral $\int x^2 \sin^{-1}(x) dx$. Which letter should be tried f
```julia; hold=true; echo=false
choices = ["L", "I", "A", "T", "E"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -631,8 +639,8 @@ Consider the integral $\int e^x \sin(x) dx$. Which letter should be tried first?
```julia; hold=true; echo=false
choices = ["L", "I", "A", "T", "E"]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
###### Question
@ -644,6 +652,6 @@ choices = [
"``x\\cos^{-1}(x)-\\sqrt{1 - x^2}``",
"``x^2/2 \\cos^{-1}(x) - x\\sqrt{1-x^2}/4 - \\cos^{-1}(x)/4``",
"``-\\sin^{-1}(x)``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -98,10 +98,12 @@ Though not continuous, $f(x)$ is integrable as it contains only jumps. The integ
What is the average value of the function $e^{-x}$ between $0$ and $\log(2)$?
```math
\text{average} = \frac{1}{\log(2) - 0} \int_0^{\log(2)} e^{-x} dx
= \frac{1}{\log(2)} (-e^{-x}) \big|_0^{\log(2)}
= -\frac{1}{\log(2)} (\frac{1}{2} - 1)
= \frac{1}{2\log(2)}.
\begin{align*}
\text{average} = \frac{1}{\log(2) - 0} \int_0^{\log(2)} e^{-x} dx\\
&= \frac{1}{\log(2)} (-e^{-x}) \big|_0^{\log(2)}\\
&= -\frac{1}{\log(2)} (\frac{1}{2} - 1)\\
&= \frac{1}{2\log(2)}.
\end{align*}
```
Visualizing, we have
@ -214,8 +216,8 @@ choices = [
"``\\int_0^t (v(0) + v(u))/2 du = v(0)/2\\cdot t + x(u)/2\\ \\big|_0^t``",
"``(v(0) + v(t))/2 \\cdot \\int_0^t du = (v(0) + v(t))/2 \\cdot t``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -278,8 +280,8 @@ value of $g(x) = \lvert x \rvert$ over the interval $[0,1]$?
choices = [
L"That of $f(x) = x^{10}$.",
L"That of $g(x) = \lvert x \rvert$."]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -297,8 +299,8 @@ choices = [
]
n1, _ = quadgk(x -> x^2 *(1-x)^3, 0, 1)
n2, _ = quadgk(x -> x^3 *(1-x)^4, 0, 1)
ans = 1 + (n1 < n2)
radioq(choices, ans)
answ = 1 + (n1 < n2)
radioq(choices, answ)
```
###### Question
@ -324,8 +326,8 @@ choices = [
L"Because the mean value theorem says this is $f(c) (x-a)$ for some $c$ and both terms are positive by the assumptions",
"Because the definite integral is only defined for positive area, so it is always positive"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
* Explain why $F(x)$ is increasing.
@ -336,8 +338,8 @@ L"By the extreme value theorem, $F(x)$ must reach its maximum, hence it must inc
L"By the intermediate value theorem, as $F(x) > 0$, it must be true that $F(x)$ is increasing",
L"By the fundamental theorem of calculus, part I, $F'(x) = f(x) > 0$, hence $F(x)$ is increasing"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -354,6 +356,6 @@ choices = [
L"The average of $f$",
L"The exponential of the average of $\log(f)$"
]
ans = val1 > val2 ? 1 : 2
radioq(choices, ans)
answ = val1 > val2 ? 1 : 2
radioq(choices, answ)
```

View File

@ -75,15 +75,10 @@ The value of this decomposition is that the terms $a_{ij}(x)/q_i(x)^j$
each have an antiderivative, and so the sum of them will also have an
antiderivative.
```julia; echo=false
note("""
Many calculus texts will give some examples for finding a partial
fraction decomposition. We push that work off to `SymPy`, as for all
but the easiest cases - a few are in the problems - it can be a bit tedious.
""")
```
!!! note
Many calculus texts will give some examples for finding a partial
fraction decomposition. We push that work off to `SymPy`, as for all
but the easiest cases - a few are in the problems - it can be a bit tedious.
In `SymPy`, the `apart` function will find the partial fraction
decomposition when a factorization is available. For example, here we see $n_i$ terms for each power of
@ -418,8 +413,8 @@ choices = [
L"The value $c$ is a removable singularity, so the integral will be identical.",
L"The resulting function has an identical domain and is equivalent for all $x$."
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -431,8 +426,8 @@ choices = [
L"The value $c$ is a removable singularity, so the integral will be identical.",
L"The resulting function has an identical domain and is equivalent for all $x$."
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -444,8 +439,8 @@ choices = [
L"The value $c$ is a removable singularity, so the integral will be identical.",
L"The resulting function has an identical domain and is equivalent for all $x$."
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```

View File

@ -247,8 +247,12 @@ But $u^3/3 - 4u/3 = (1/3) \cdot u(u-1)(u+2)$, so between $-2$ and $0$
it is positive and between $0$ and $1$ negative, so this integral is:
```math
\int_{-2}^0 (u^3/3 - 4u/3 ) du + \int_{0}^1 -(u^3/3 - 4u/3) du =
(\frac{u^4}{12} - \frac{4}{3}\frac{u^2}{2}) \big|_{-2}^0 - (\frac{u^4}{12} - \frac{4}{3}\frac{u^2}{2}) \big|_{0}^1 = \frac{4}{3} - -\frac{7}{12} = \frac{23}{12}.
\begin{align*}
\int_{-2}^0 (u^3/3 - 4u/3 ) du + \int_{0}^1 -(u^3/3 - 4u/3) du
&= (\frac{u^4}{12} - \frac{4}{3}\frac{u^2}{2}) \big|_{-2}^0 - (\frac{u^4}{12} - \frac{4}{3}\frac{u^2}{2}) \big|_{0}^1\\
&= \frac{4}{3} - -\frac{7}{12}\\
&= \frac{23}{12}.
\end{align*}
```
##### Example
@ -400,13 +404,11 @@ Finally, we put back in the `u(x)` to get an antiderivative.
ex₃(w => u(x))
```
```julia; echo=false
note("""
Lest it be thought this is an issue with `SymPy`, but not other
systems, this example was [borrowed](http://faculty.uml.edu/jpropp/142/Integration.pdf) from an
illustration for helping Mathematica.
""")
```
!!! note
Lest it be thought this is an issue with `SymPy`, but not other
systems, this example was [borrowed](http://faculty.uml.edu/jpropp/142/Integration.pdf) from an
illustration for helping Mathematica.
## Trigonometric substitution
@ -563,8 +565,8 @@ choices = [
"``\\int u (1 - u^2) du``",
"``\\int u \\cos(x) du``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -578,8 +580,8 @@ choices = [
"``u=\\sec(x)``",
"``u=\\sec(x)^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -593,8 +595,8 @@ choices = [
"``u=\\sqrt{x^2 - 1}``",
"``u=x``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -620,8 +622,8 @@ choices = [
"``\\int u du``",
"``\\int u^3/x du``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -633,8 +635,8 @@ choices = [
"``u=\\sin(x)``",
"``u=\\tan(x)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -654,8 +656,8 @@ choices = [
"``a=0,~ b=0``",
"``a=1,~ b=1``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -669,8 +671,8 @@ choices = [
"``\\sec(u) = x``",
"``u = 1 - x^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -684,8 +686,8 @@ choices = [
"``\\tan(u) = x``",
"``\\sec(u) = x``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -699,8 +701,8 @@ choices = [
"``\\sec(u) = x``",
"``u = 1 - x^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -715,8 +717,8 @@ choices = [
"``\\sec(u) = x``",
"``4\\sin(u) = x``",
"``\\sin(u) = x``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -730,8 +732,8 @@ choices = [
"``\\tan(u) = x``",
"``a\\sec(u) = x``",
"``\\sec(u) = x``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -751,8 +753,8 @@ choices =[
"``a=\\pi/3,~ b=\\pi/2``",
"``a=1/2,~ b= 1``"
]
ans =1
radioq(choices, ans)
answ =1
radioq(choices, answ)
```
###### Question
@ -763,6 +765,6 @@ How would we verify that $\log\lvert (\sec(u) + \tan(u))\rvert$ is an antideriva
choices = [
L"We could differentiate $\sec(u)$.",
L"We could differentiate $\log\lvert (\sec(u) + \tan(u))\rvert$ "]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```

View File

@ -17,7 +17,7 @@ const frontmatter = (
description = "Calculus with Julia: Surface Area",
tags = ["CalculusWithJulia", "integrals", "surface area"],
);
fig_size=(600, 400)
fig_size=(800, 600)
nothing
```
@ -174,11 +174,13 @@ formula, even though we just saw how to get this value.
A cone be be envisioned as rotating the function $f(x) = x\tan(\theta)$ between $0$ and $h$ around the $x$ axis. This integral yields the surface area:
```math
\begin{align*}
\int_0^h 2\pi f(x) \sqrt{1 + f'(x)^2}dx
= \int_0^h 2\pi x \tan(\theta) \sqrt{1 + \tan(\theta)^2}dx
= (2\pi\tan(\theta)\sqrt{1 + \tan(\theta)^2} x^2/2 \big|_0^h
= \pi \tan(\theta) \sec(\theta) h^2
= \pi r^2 / \sin(\theta).
&= \int_0^h 2\pi x \tan(\theta) \sqrt{1 + \tan(\theta)^2}dx \\
&= (2\pi\tan(\theta)\sqrt{1 + \tan(\theta)^2} x^2/2 \big|_0^h \\
&= \pi \tan(\theta) \sec(\theta) h^2 \\
&= \pi r^2 / \sin(\theta).
\end{align*}
```
(There are many ways to express this, we used $r$ and $\theta$ to
@ -449,8 +451,8 @@ choices = [
"``-\\int_1^{_1} 2\\pi u \\sqrt{1 + u^2} du``",
"``-\\int_1^{_1} 2\\pi u^2 \\sqrt{1 + u} du``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Though the integral can be computed by hand, give a numeric value.
@ -506,8 +508,8 @@ choices = [
"``\\int_u^{u_h} 2\\pi y dx``",
"``\\int_u^{u_h} 2\\pi x dx``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
##### Questions

View File

@ -105,13 +105,8 @@ area is $\pi r(x)^2$ so the volume is given by:
V = \int_a^b \pi r(x)^2 dx.
```
```julia; echo=false
note(L"""
The formula is for a rotation around the $x$-axis, but can easily be generalized to rotating around any line (say the $y$-axis or $y=x$, ...) just by adjusting what $r(x)$ is taken to be.
""")
```
!!! note
The formula is for a rotation around the $x$-axis, but can easily be generalized to rotating around any line (say the $y$-axis or $y=x$, ...) just by adjusting what $r(x)$ is taken to be.
For a numeric example, we consider the original Red
@ -136,8 +131,8 @@ This is
```julia;
d0, d1, h = 2.5, 3.75, 4.75
r(x) = d0/2 + (d1/2 - d0/2)/h * x
vol, _ = quadgk(x -> pi * r(x)^2, 0, h)
rad(x) = d0/2 + (d1/2 - d0/2)/h * x
vol, _ = quadgk(x -> pi * rad(x)^2, 0, h)
```
So $36.9 \text{in}^3$. How many ounces is that? It is useful to know
@ -178,7 +173,7 @@ So we need to solve $v \cdot (231/128) = \int_0^h\pi r(x)^2 dx$ for $h$ when $v=
Let's express volume as a function of $h$:
```julia;
Vol(h) = quadgk(x -> pi * r(x)^2, 0, h)[1]
Vol(h) = quadgk(x -> pi * rad(x)^2, 0, h)[1]
```
Then to solve we have:
@ -201,12 +196,8 @@ As a percentage of the total height, these are:
h5/h, h12/h
```
```julia;echo=false
note("""
Were performance at issue, Newton's method might also have been considered here, as the derivative is easily computed by the fundamental theorem of calculus.
""")
```
!!! note
Were performance at issue, Newton's method might also have been considered here, as the derivative is easily computed by the fundamental theorem of calculus.
##### Example
@ -239,16 +230,11 @@ quadgk(x -> pi*radius(x)^2, 1, Inf)[1]
That is a value very reminiscent of $\pi$, which it is as $\int_1^\infty 1/x^2 dx = -1/x\big|_1^\infty=1$.
```julia; echo=false
note("""
The interest in this figure is that soon we will be able to show that
it has **infinite** surface area, leading to the
[paradox](http://tinyurl.com/osawwqm) that it seems possible to fill
it with paint, but not paint the outside.
""")
```
!!! note
The interest in this figure is that soon we will be able to show that
it has **infinite** surface area, leading to the
[paradox](http://tinyurl.com/osawwqm) that it seems possible to fill
it with paint, but not paint the outside.
##### Example
@ -668,8 +654,8 @@ choices = [
"``1/3 \\cdot w^2\\cdot h``",
"``l\\cdot w \\cdot h/ 3``"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -696,8 +682,8 @@ choices = [
"``4/3 \\cdot \\pi a^2 b``",
"``\\pi/3 \\cdot a b^2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -752,9 +738,9 @@ Find the volume of rotating the region bounded by the line $y=x$, $x=1$ and the
```julia; hold=true; echo=false
cm=[2/3, 1/3]
c = [1/2, 1/2]
r = norm(cm - c)
rr = norm(cm - c)
A = 1/2 * 1 * 1
val = 2pi*r*A
val = 2pi * rr * A
numericq(val)
```

View File

@ -86,12 +86,10 @@ continuity and *left* continuity at a point, where the limit in the
defintion is replaced by a right or left limit, as appropriate.
```julia; echo=false
alert("""
The limit in the definition of continuity is the basic limit and not an extended sense where
infinities are accounted for.
""")
```
!!! warning
The limit in the definition of continuity is the basic limit and not an extended sense where
infinities are accounted for.
##### Examples of continuity
Most familiar functions are continuous everywhere.
@ -256,8 +254,8 @@ f+g,~ f-g,~ f\cdot g,~ f\circ g,~ f/g
```julia; hold=true; echo=false
choices = ["``f+g``", "``f-g``", "``f\\cdot g``", "``f\\circ g``", "``f/g``"]
ans = length(choices)
radioq(choices, ans)
answ = length(choices)
radioq(choices, answ)
```
###### Question
@ -268,16 +266,16 @@ When will $f\circ g$ be continuous?
```julia; hold=true; echo=false
choices = [L"For all $x$", L"For all $x > 0$", L"For all $x$ where $\sin(x) > 0$"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
When will $g \circ f$ be continuous?
```julia; hold=true; echo=false
choices = [L"For all $x$", L"For all $x > 0$", L"For all $x$ where $\sin(x) > 0$"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -290,8 +288,8 @@ L"The function $g$ is continuous everywhere",
L"The function $f$ is continuous everywhere",
L"The function $g$ is continuous everywhere and $f$ is continuous on the range of $g$",
L"The function $f$ is continuous everywhere and $g$ is continuous on the range of $f$"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -304,8 +302,8 @@ L"When $x > 2$",
L"When $x \geq 2$",
L"When $x \leq 2$",
L"For $x \geq 0$"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -375,8 +373,8 @@ Suppose $f(x)$, $g(x)$, and $h(x)$ are continuous functions on $(a,b)$. If $a <
choices = [L"No, as $g(c)$ may not be in the interval $(a,b)$",
"Yes, composition of continuous functions results in a continuous function, so the limit is just the function value."
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
###### Question
@ -446,6 +444,6 @@ choices = ["Can't tell",
"``-1.0``",
"``0.0``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -7,8 +7,6 @@ using CalculusWithJulia
using Plots
using Roots
using SymPy
import IntervalArithmetic
import IntervalRootFinding
```
```julia; echo=false; results="hidden"
@ -20,7 +18,7 @@ const frontmatter = (
tags = ["CalculusWithJulia", "limits", "implications of continuity"],
);
const fig_size=(400, 400)
fig_size=(800, 600)
nothing
```
@ -237,20 +235,16 @@ sin(c)
### The `find_zero` function.
The `Roots` package has a function `find_zero` that implements the
bisection method when called as `find_zero(f, a..b)` where $[a,b]$
bisection method when called as `find_zero(f, (a,b))` where $[a,b]$
is a bracket. Its use is similar to `simple_bisection` above. This package is loaded when `CalculusWithJulia` is. We illlustrate the usage of `find_zero`
in the following:
```julia;
xstar = find_zero(sin, 3..4)
```
```julia; echo=false
alert("""
Notice, the call `find_zero(sin, 3..4)` again fits the template `action(function, args...)` that we see repeatedly. The `find_zero` function can also be called through `fzero`. The use of `3..4` to specify the interval is not necessary. For example `(3,4)` or `[3,4]` would work equally as well. The `..` is an idiom in `Julia` for intervals, so used here, but is not part of the base language. It is imported from `EllipsisNotation` by the `CalculusWithJulia` package.
""")
xstar = find_zero(sin, (3, 4))
```
!!! warning
Notice, the call `find_zero(sin, (3, 4))` again fits the template `action(function, args...)` that we see repeatedly. The `find_zero` function can also be called through `fzero`. The use of `(3, 4)` to specify the interval is not necessary. For example `[3,4]` would work equally as well. (Anything where `extrema` is defined works.)
This function utilizes some facts about floating point values to
guarantee that the answer will be an *exact* zero or a value where there is a sign change between the next bigger floating point or the next smaller, which means the sign at the next and previous floating point values is different:
@ -265,7 +259,7 @@ The polynomial $p(x) = x^5 - x + 1$ has a zero between $-2$ and $-1$. Find it.
```julia;
p(x) = x^5 - x + 1
c₀ = find_zero(p, -2 .. -1) # avoiding ..-1 which errors
c₀ = find_zero(p, (-2, -1))
(c₀, p(c₀))
```
@ -289,7 +283,7 @@ plot(q, 5, 10)
Find the zero numerically. The plot shows $q(5) < 0 < q(10)$, so $[5,10]$ is a bracket. We thus have:
```julia;
find_zero(q, 5..10)
find_zero(q, (5, 10))
```
@ -310,7 +304,7 @@ plot(x^3 - x + 1, -3, 3)
It appears (and a plot over $[0,1]$ verifies) that there is one zero between $-2$ and $-1$. It is found with:
```julia;
find_zero(x^3 - x + 1, -2 .. -1)
find_zero(x^3 - x + 1, (-2, -1))
```
@ -333,7 +327,7 @@ We see from the graph that it is clearly between $0$ and $2$, so all we need is
```julia;
𝒉(x) = 𝒇(x) - 𝒈(x)
find_zero(𝒉, 0..2)
find_zero(𝒉, (0, 2))
```
#### Using parameterized functions (`f(x,p)`) with `find_zero`
@ -342,7 +336,7 @@ Geometry will tell us that ``\cos(x) = x/p`` for *one* ``x`` in ``[0, \pi/2]`` w
```julia; hold=true;
f(x, p=1) = cos(x) - x/p
I = 0..pi/2
I = (0, pi/2)
find_zero(f, I), find_zero(f, I, p=2)
```
@ -385,7 +379,7 @@ cheaper.
Let's get a numeric value, using a simple bracket and an anonymous function:
```julia;
find_zero(x -> plan1(x) - plan2(x), 10..20)
find_zero(x -> plan1(x) - plan2(x), (10, 20))
```
##### Example, the flight of an arrow
@ -480,7 +474,7 @@ d(b)
From the graph, we can see the zero is around `b`. As `y(b)` is `-Inf` we can use the bracket `(b/2,b)`
```julia;
x1 = find_zero(d, (b/2)..b)
x1 = find_zero(d, (b/2, b))
```
The answer is approximately $140.7$
@ -527,7 +521,7 @@ does the algorithm yield:
```julia;
fᵢ(x) = 1/x
x0 = find_zero(fᵢ, -1..1)
x0 = find_zero(fᵢ, (-1, 1))
```
@ -559,31 +553,25 @@ interval.
Still, with some engineering, this can be a useful approach, save the
caveats. This idea is implemented in the `find_zeros` function of the `Roots` package. The function is
called via `find_zeros(f, a..b)` but here the interval
called via `find_zeros(f, (a, b))` but here the interval
$[a,b]$ is not necessarily a bracketing interval.
To see, we have:
```julia; hold=true;
f(x) = cos(10*pi*x)
find_zeros(f, 0..1)
find_zeros(f, (0, 1))
```
Or for a polynomial:
```julia; hold=true;
f(x) = x^5 - x^4 + x^3 - x^2 + 1
find_zeros(f, -10..10)
find_zeros(f, (-10, 10))
```
(Here $-10$ and $10$ were arbitrarily chosen. Cauchy's method could be used to be more systematic.)
```julia; echo=false
note("""
At the end of this section are details on how to use the `IntervalRootFinding` package to identify all zeros in a specified interval. This package offers a more robust algorithm for this task.
""")
```
##### Example: Solving f(x) = g(x)
Use `find_zeros` to find when $e^x = x^5$ in the interval $[-20, 20]$. Verify the answers.
@ -593,7 +581,7 @@ The zeros are then found with:
```julia;
f₁(x) = exp(x) - x^5
zs = find_zeros(f₁, -20..20)
zs = find_zeros(f₁, (-20,20))
```
@ -760,7 +748,7 @@ $f(x) = e^x - x^4$. Find its value numerically:
```julia; hold=true; echo=false
f(x) = exp(x) - x^4
val = find_zero(f, -10..0);
val = find_zero(f, (-10, 0));
numericq(val, 1e-3)
```
@ -772,7 +760,7 @@ $f(x) = e^x - x^4$. Find its value numerically:
```julia; hold=true; echo=false
f(x) = exp(x) - x^4
val = find_zero(f, 0..5);
val = find_zero(f, (0, 5));
numericq(val, 1e-3)
```
@ -786,7 +774,7 @@ zeros on the positive $x$ axis. You are asked to find the largest
```julia; hold=true; echo=false
b = 10
f(x) = x^2 - b * x * log(x)
val = find_zero(f, 10..500)
val = find_zero(f, (10, 500))
numericq(val, 1e-3)
```
@ -805,7 +793,7 @@ plot(airyai, -10, 10) # `airyai` loaded in `SpecialFunctions` by `CalculusWith
The second largest root is:
```julia; hold=true; echo=false
val = find_zero(airyai, -5 .. -4);
val = find_zero(airyai, (-5, -4));
numericq(val, 1e-8)
```
@ -816,7 +804,7 @@ numericq(val, 1e-8)
Certainly $x^3$ equals $3^x$ at $x=3$. Find the largest value for which $x^3 = 3x$.
```julia; hold=true; echo=false
val = maximum(find_zeros(x -> x^3 - 3^x, 0..20))
val = maximum(find_zeros(x -> x^3 - 3^x, (0, 20)))
numericq(val)
```
@ -824,8 +812,8 @@ Compare $x^2$ and $2^x$. They meet at $2$, where do the meet again?
```julia; hold=true; echo=false
choices = ["Only before 2", "Only after 2", "Before and after 2"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
Just by graphing, find a number in $b$ with $2 < b < 3$ where for
@ -837,8 +825,8 @@ choices=[
"``b \\approx 2.5``",
"``b \\approx 2.7``",
"``b \\approx 2.9``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -882,8 +870,8 @@ Let $v_0= 390$. The three times in question can be found from the zeros of `f` a
choices = ["``(0.0, 12.1875, 24.375)``",
"``(-4.9731, 0.0, 4.9731)``",
"``(0.0, 625.0, 1250.0)``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -915,13 +903,13 @@ ground.
```julia; hold=true; echo=false
t0 = 0.0
tf = find_zero(h, 10..20)
ta = find_zero(D(h), t0..tf)
tf = find_zero(h, (10, 20))
ta = find_zero(D(h), (t0, tf))
choices = ["``(0, 13.187, 30.0)``",
"``(0, 32.0, 390.0)``",
"``(0, 2.579, 13.187)``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -932,7 +920,7 @@ Part of the proof of the intermediate value theorem rests on knowing what the li
choices = [L"It must be that $L > y$ as each $f(x)$ is.",
L"It must be that $L \geq y$",
L"It can happen that $L < y$, $L=y$, or $L>y$"]
ans = 2
answ = 2
radioq(choices, 2, keep_order=true)
```
@ -949,8 +937,8 @@ choices = [
"``f(x) = \\sin(x),~ I=(-\\pi, \\pi)``",
"``f(x) = \\sin(x),~ I=(-\\pi/2, \\pi/2)``",
"None of the above"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -966,8 +954,8 @@ choices = [
"``f(x) = 1/x,~ I=[-2, -1]``",
"``f(x) = 1/x,~ I=[-1, 1]``",
"none of the above"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -984,8 +972,8 @@ choices = [
"``f(x) = 1/x,~ I=[-4, -1]``",
"``f(x) = \\text{floor}(x),~ I=[-1/2, 1/2]``",
"none of the above"]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
@ -1024,8 +1012,8 @@ L"There is no value $c$ for which $f(c)$ is an absolute maximum over $I$.",
L"There is just one value of $c$ for which $f(c)$ is an absolute maximum over $I$.",
L"There are many values of $c$ for which $f(c)$ is an absolute maximum over $I$."
]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
@ -1039,8 +1027,8 @@ L"There is no value $M$ for which $M=f(c)$, $c$ in $I$ for which $M$ is an absol
L"There is just one value $M$ for which $M=f(c)$, $c$ in $I$ for which $M$ is an absolute maximum over $I$.",
L"There are many values $M$ for which $M=f(c)$, $c$ in $I$ for which $M$ is an absolute maximum over $I$."
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -1056,8 +1044,8 @@ choices = [
"``f(x) = \\sin(x),\\quad I=[-\\pi/2, \\pi/2]``",
"``f(x) = \\sin(x),\\quad I=[0, 2\\pi]``",
"``f(x) = \\sin(x),\\quad I=[-2\\pi, 2\\pi]``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
##### Question
@ -1065,7 +1053,7 @@ radioq(choices, ans)
The zeros of the equation $\cos(x) \cdot \cosh(x) = 1$ are related to vibrations of rods. Using `find_zeros`, what is the largest zero in the interval $[0, 6\pi]$?
```julia; hold=true; echo=false
val = maximum(find_zeros(x -> cos(x) * cosh(x) - 1, 0..6pi))
val = maximum(find_zeros(x -> cos(x) * cosh(x) - 1, (0, 6pi)))
numericq(val)
```
@ -1086,98 +1074,3 @@ a,b = 1, 2
k_x, k_y = 3, 4
plot(t -> a * cos(k_x *t), t-> b * sin(k_y * t), 0, 4pi)
```
----
## Using `IntervalRootFinding` to identify zeros
The `IntervalRootFinding` package provides a more *rigorous* alternative to `find_zeros`. This packages leverages the interval arithmetic features of `IntervalArithmetic`.
The `IntervalRootFinding` package provides a function `roots`, with usage similar to `find_zeros`. Intervals are specified with the notation `a..b`. In the following, we *qualify* `roots` to not conflict with the `roots` function from `SymPy`, which has already been loaded:
```julia
u(x) = sin(x) - 0.1*x^2 + 1
𝑱 = IntervalArithmetic.Interval(-10, 10) # cumbersome -10..10; needed here: .. means something in CalculusWithJulia
rts = IntervalRootFinding.roots(u, 𝑱)
```
The "zeros" are returned with an enclosing interval and a flag, which for the above indicates a unique zero in the interval.
The intervals with a unique answer can be filtered and refined with a construct like the following:
```julia
[find_zero(u, (IntervalArithmetic.interval(I).lo, IntervalArithmetic.interval(I).hi)) for I in rts if I.status == :unique]
```
The midpoint of the returned interval can be found by composing the `mid` function with the `interval` function of the package:
```julia
[(IntervalArithmetic.mid ∘ IntervalArithmetic.interval)(I) for I in rts if I.status == :unique]
```
For some problems, `find_zeros` is more direct, as with this one:
```julia
find_zeros(u, -10..10)
```
Which can be useful if there is some prior understanding of the zeros expected to be found.
However, `IntervalRootFinding` is more efficient computationally and *offers a guarantee* on the values found.
For functions where roots are not "unique" a different output may appear:
```julia; hold=true;
f(x) = x*(x-1)^2
rts = IntervalRootFinding.roots(f, 𝑱)
```
The interval labeled `:unknown` contains a `0`, but it can't be proved by `roots`.
Interval arithmetic finds **rigorous** **bounds** on the range of `f` values over a closed interval `a..b` (the range is `f(a..b)`). "Rigorous" means the bounds are truthful and account for possible floating point issues. "Bounds" means the answer lies within, but the bound need not be the answer.
This allows one -- for some functions -- to answer affirmatively questions like:
* Is the function *always* positive on `a..b`? Negative? This can be done by checking if `0` is in the bound given by `f(a..b)`. If it isn't then one of the two characterizations is true.
* Is the function *strictly increasing* on `a..b`? Strictly decreasing? These questions can be answered using the (upcoming) [derivative](../derivatives/derivatives.html). If the derivative is positive on `a..b` then `f` is strictly increasing, if negative on `a..b` then `f` is strictly decreasing. Finding the derivative can be done within the `IntervalArithmetic` framework using [automatic differentiation](../derivatives/numeric_derivatives.html), a blackbox operation denoted `f'` below.
Combined, for some functions and some intervals these two questions can be answered affirmatively:
* the interval does not contain a zero (`0 !in f(a..b)`)
* over the interval, the function crosses the `x` axis *once* (`f(a..a)` and `f(b..b)` are one positive and one negative *and* `f` is strictly monotone, or `0 !in f'(a..b)`)
This allows the following (simplified) bisection-like algorithm to be used:
* consider an interval `a..b`
* if the function is *always* positive or negative, it can be discarded as no zero can be in the interval
* if the function crosses the `x` axis *once* over this interval **then** there is a "unique" zero in the interval and the interval can be marked so and set aside
* if neither of the above *and* `a..b` is not too small already, then *sub-divide* the interval and repeat the above with *both* smaller intervals
* if `a..b` is too small, stop and mark it as "unknown"
When terminated there will be intervals with unique zeros flagged and smaller intervals with an unknown status.
Compared to the *bisection* algorithm -- which only knows for some intervals if that interval has one or more crossings -- this algorithm gives a more rigorous means to get all the zeros in `a..b`.
For a last example of the value of this package, this function, which appeared in our discussion on limits, is *positive* for **every** floating point number, but has two zeros snuck in at values within the floating point neighbors of $15/11$
```julia
t(x) = x^2 + 1 +log(abs( 11*x-15 ))/99
```
The `find_zeros` function will fail on identifying any potential zeros of this function. Even the basic call of `roots` will fail, due to it relying on some smoothness of `f`. However, explicitly asking for `Bisection` shows the *potential* for one or more zeros near $15/11$:
```julia
IntervalRootFinding.roots(t, 𝑱, IntervalRootFinding.Bisection)
```
(The basic algorithm above can be sped up using a variant of [Newton's](../derivatives/newton_method.html) method, this variant assumes some "smoothness" in the function `f`, whereas this `f` is not continuous at the point ``x=15/11``.)

View File

@ -17,7 +17,7 @@ const frontmatter = (
description = "Calculus with Julia: Limits",
tags = ["CalculusWithJulia", "limits", "limits"],
);
const fig_size=(400, 300)
fig_size=(800, 600)
nothing
```
@ -287,8 +287,9 @@ This progression can be seen to be increasing. Cauchy, in his treatise, can see
```math
\begin{align*}
(1 + \frac{1}{m})^n &= 1 + \frac{1}{1} + \frac{1}{1\cdot 2}(1 = \frac{1}{m}) + \\
& \frac{1}{1\cdot 2\cdot 3}(1 - \frac{1}{m})(1 - \frac{2}{m}) + \cdots +
& \frac{1}{1 \cdot 2 \cdot \cdots \cdot m}(1 - \frac{1}{m}) \cdot \cdots \cdot (1 - \frac{m-1}{m}).
& \frac{1}{1\cdot 2\cdot 3}(1 - \frac{1}{m})(1 - \frac{2}{m}) + \cdots \\
&+
\frac{1}{1 \cdot 2 \cdot \cdots \cdot m}(1 - \frac{1}{m}) \cdot \cdots \cdot (1 - \frac{m-1}{m}).
\end{align*}
```
@ -1088,8 +1089,8 @@ plot(f, 0,2)
```julia; hold=true; echo=false
ans = 1/4
numericq(ans, 1e-1)
answ = 1/4
numericq(answ, 1e-1)
```
@ -1158,36 +1159,38 @@ numericq(val, 1e-2)
Select the graph for which there is no limit at ``a``.
```julia; hold=true; echo=false
p1 = plot(;axis=nothing, legend=false)
title!(p1, "(a)")
plot!(p1, x -> x^2, 0, 2, color=:black)
plot!(p1, zero, linestyle=:dash)
annotate!(p1,[(1,0,"a")])
let
p1 = plot(;axis=nothing, legend=false)
title!(p1, "(a)")
plot!(p1, x -> x^2, 0, 2, color=:black)
plot!(p1, zero, linestyle=:dash)
annotate!(p1,[(1,0,"a")])
p2 = plot(;axis=nothing, legend=false)
title!(p2, "(b)")
plot!(p2, x -> 1/(1-x), 0, .95, color=:black)
plot!(p2, x-> -1/(1-x), 1.05, 2, color=:black)
plot!(p2, zero, linestyle=:dash)
annotate!(p2,[(1,0,"a")])
p2 = plot(;axis=nothing, legend=false)
title!(p2, "(b)")
plot!(p2, x -> 1/(1-x), 0, .95, color=:black)
plot!(p2, x-> -1/(1-x), 1.05, 2, color=:black)
plot!(p2, zero, linestyle=:dash)
annotate!(p2,[(1,0,"a")])
p3 = plot(;axis=nothing, legend=false)
title!(p3, "(c)")
plot!(p3, sinpi, 0, 2, color=:black)
plot!(p3, zero, linestyle=:dash)
annotate!(p3,[(1,0,"a")])
p3 = plot(;axis=nothing, legend=false)
title!(p3, "(c)")
plot!(p3, sinpi, 0, 2, color=:black)
plot!(p3, zero, linestyle=:dash)
annotate!(p3,[(1,0,"a")])
p4 = plot(;axis=nothing, legend=false)
title!(p4, "(d)")
plot!(p4, x -> x^x, 0, 2, color=:black)
plot!(p4, zero, linestyle=:dash)
annotate!(p4,[(1,0,"a")])
p4 = plot(;axis=nothing, legend=false)
title!(p4, "(d)")
plot!(p4, x -> x^x, 0, 2, color=:black)
plot!(p4, zero, linestyle=:dash)
annotate!(p4,[(1,0,"a")])
l = @layout[a b; c d]
p = plot(p1, p2, p3, p4, layout=l)
imgfile = tempname() * ".png"
savefig(p, imgfile)
hotspotq(imgfile, (1/2,1), (1/2,1))
l = @layout[a b; c d]
p = plot(p1, p2, p3, p4, layout=l)
imgfile = tempname() * ".png"
savefig(p, imgfile)
hotspotq(imgfile, (1/2,1), (1/2,1))
end
```
###### Question
@ -1209,8 +1212,8 @@ What is $L$?
```julia; hold=true; echo=false
choices = ["``0``", "``1``", "``e^x``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -1237,8 +1240,8 @@ Using the last result, what is the value of $L$?
```julia; hold=true; echo=false
choices = ["``\\cos(x)``", "``\\sin(x)``", "``1``", "``0``", "``\\sin(h)/h``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1309,8 +1312,8 @@ the fact that $x$ is measured in radians. Try to find this limit:
```julia; hold=true; echo=false
choices = [q"0", q"1", q"pi/180", q"180/pi"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -1318,8 +1321,8 @@ What is the limit `limit(sinpi(x)/x, x => 0)`?
```julia; hold=true; echo=false
choices = [q"0", q"1", q"pi", q"1/pi"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question: limit properties
@ -1388,8 +1391,8 @@ choices = [
"Yes, the value is `-11.5123`",
"No, the value heads to negative infinity"
];
ans = 3;
radioq(choices, ans)
answ = 3;
radioq(choices, answ)
```
###### Question
@ -1433,8 +1436,8 @@ What is `limit(ex, x => 0)`?
```julia; hold=true; echo=false
choices = ["``e^{km}``", "``e^{k/m}``", "``k/m``", "``m/k``", "``0``"]
answer = 1
radioq(choices, answer)
answwer = 1
radioq(choices, answwer)
```
###### Question
@ -1511,8 +1514,8 @@ between both $g$ and $h$, so must to have a limit of $0$.
""",
L"The functions $g$ and $h$ squeeze each other as $g(x) > h(x)$",
L"The function $f$ has no limit - it oscillates too much near $0$"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
(The [Wikipedia](https://en.wikipedia.org/wiki/Squeeze_theorem) entry for the squeeze theorem has this unverified, but colorful detail:

View File

@ -149,11 +149,9 @@ limit(f(x), x=>0, dir="+"), limit(f(x), x=>0, dir="-")
```
```julia; echo=false
alert("""
That means the mathematical limit need not exist when `SymPy`'s `limit` returns an answer, as `SymPy` is only carrying out a one sided limit. Explicitly passing `dir="+-"` or checking that both `limit(ex, x=>c)` and `limit(ex, x=>c, dir="-")` are equal would be needed to confirm a limit exists mathematically.
""")
```
!!! warning
That means the mathematical limit need not exist when `SymPy`'s `limit` returns an answer, as `SymPy` is only carrying out a one sided limit. Explicitly passing `dir="+-"` or checking that both `limit(ex, x=>c)` and `limit(ex, x=>c, dir="-")` are equal would be needed to confirm a limit exists mathematically.
The relation between the two concepts is that a function has a limit at $c$ if
an only if the left and right limits exist and are equal. This
@ -623,7 +621,6 @@ The last equality follows, as the function ``x`` dominates the function ``\ln(x)
## Questions
###### Question
Select the graph for which the limit at ``a`` is infinite.
@ -761,8 +758,8 @@ Find $\lim_{x \rightarrow 2+} (x-3)/(x-2)$.
```julia; hold=true; echo=false
choices=["``L=-\\infty``", "``L=-1``", "``L=0``", "``L=\\infty``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Find $\lim_{x \rightarrow -3-} (x-3)/(x+3)$.
@ -771,8 +768,8 @@ Find $\lim_{x \rightarrow -3-} (x-3)/(x+3)$.
```julia; hold=true; echo=false
choices=["``L=-\\infty``", "``L=-1``", "``L=0``", "``L=\\infty``"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
###### Question
@ -861,8 +858,8 @@ choices=["The limit does exist - it is any number from -1 to 1",
"Err, the limit does exists and is 1",
"The function oscillates too much and its y values do not get close to any one value",
"Any function that oscillates does not have a limit."]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -883,8 +880,8 @@ Consider different values of $k$ to see if this limit depends on $k$ or not. Wha
```julia; hold=true; echo=false
choices = ["``1``", "``k``", "``\\log(k)``", "The limit does not exist"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -908,8 +905,8 @@ Consider different values of $k$ to see if the limit depends on $k$ or not. What
```julia; hold=true; echo=false
choices = ["``1``", "``k``", "``\\log(k)``", "The limit does not exist"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -929,8 +926,8 @@ choices=[
"the first, second and third ones",
"the first, second, third, and fourth ones",
"all of them"]
ans = 5
radioq(choices, ans, keep_order=true)
answ = 5
radioq(choices, answ, keep_order=true)
```
@ -947,8 +944,8 @@ L"We can talk about the limit at $\infty$ of $f(x) - mx$ being $b$",
L"We can say $f(x) - (mx+b)$ has a horizontal asymptote $y=0$",
L"We can say $f(x) - mx$ has a horizontal asymptote $y=b$",
"Any of the above"]
ans = 5
radioq(choices, ans, keep_order=true)
answ = 5
radioq(choices, answ, keep_order=true)
```
###### Question
@ -976,6 +973,6 @@ choices = [L" $f(x)$ has a limit of $1$ as $x \rightarrow 0$",
L" $f(x)$ has a limit of $-1$ as $x \rightarrow 0$",
L" $f(x)$ does not have a limit as $x \rightarrow 0$"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```

View File

@ -28,7 +28,6 @@ Clicking the launch link above will open a web page which provides a
blank notebook, save for a package used by these notes. However,
`Binder` is nowhere near as reliable as a local installation.
These notes use `Pluto` notebooks. The "Edit or run this notebook" button allows each notebook to be run through binder. However, it can take several minutes for binder to show any given notebook. (Binder works best when no or few external packages are used.)
## Installing Julia locally
@ -86,14 +85,16 @@ coloring. For example:
2 + 2
```
While many prefer a command line for interacting with `Julia`, when learning a notebook interfaces is suggested. (An IDE like [Julia for Visual Studio Code](https://www.julia-vscode.org/) might be preferred for experienced programmers). In [Julia interfaces](./julia_interfaces.html), we describe two different notebook interfaces that are available through add-on packages. (These notes use `Pluto`, one of the two.)
While many prefer a command line for interacting with `Julia`, when learning a notebook interfaces is suggested. (An IDE like [Julia for Visual Studio Code](https://www.julia-vscode.org/) might be preferred for experienced programmers). In [Julia interfaces](./julia_interfaces.html), we describe two different notebook interfaces that are available through add-on packages.
## Add-on packages
`Julia` has well over a 1000 external, add-on packages that enhance the
offerings of base `Julia`. We refer to one, `CalculusWithJulia`, that is designed to accompany these notes. [Installation notes](./calculus_with_julia.html) are available.
`Julia` is well on its way towards 10,000 external add-on packages
that enhance the offerings of base `Julia`. We refer to one,
`CalculusWithJulia`, that is designed to accompany these
notes. [Installation notes](./calculus_with_julia.html) are available.

View File

@ -11,33 +11,12 @@ Julia can be used through the internet for free using the [mybinder.org](https:/
Just click on the `CalcululsWithJulia.ipynb` file after launching Binder by clicking on the badge. Binder provides the Jupyter interface.
These notes are written as Pluto HTML pages. Pluto is a notebook like alternative to Jupyter which is designed for interactive Julia usage using a *reactive model*. The HTML pages
an be downloaded and run as notebooks within Pluto. (They can also be run through binder, but that will be a disappointing experience due to limitations imposed by binder.)
Pluto will automatically handle the package management for add-on packages, though `Pluto` itself must be installed. In a terminal session, the following commands will install `Pluto`:
```julia; eval=false
import Pkg
Pkg.add("Pluto")
```
Installation happens once. Then each new *session*, `Pluto` must be loaded and run:
```julia; eval=false
using Pluto
Pluto.run()
```
`Pluto` notebooks run in a web browser, the above command will open a landing page in the default browser.
----
Here are some `Julia` usages to create calculus objects.
The `Julia` packages loaded below are all loaded when the `CalculusWithJulia` package is loaded.
@ -84,8 +63,6 @@ f(x) = exp(x) * 2x
```
!!! note
We see in this notebook the use of `let` blocks, which is not typical with `Pluto`. As `Pluto` is reactive -- meaning changes in a variable propagate automatically to variables which reference the changed one -- a variable can only be used *once* per notebook at the top level. The `let` block, like a function body, introduces a separate scope for the binding so `Pluto` doesn't incorporate the binding in its reactive model. This is necessary as we have more than one function named `f`. This is unlike `begin` blocks, which are quite typical in `Pluto`. The `begin` blocks allow one or more commands to occur in a cell, as the design of `Pluto` is one object per cell.
* multi-statement functions are defined with the `function` keyword. The `end` statement ends the definition. The last evaluated command is returned. There is no need for explicit `return` statement, though it can be useful for control flow.

6
CwJ/misc/using-pluto.jmd Normal file
View File

@ -0,0 +1,6 @@
# Using Pluto
!!! note
We see in this notebook the use of `let` blocks, which is not typical with `Pluto`. As `Pluto` is reactive -- meaning changes in a variable propagate automatically to variables which reference the changed one -- a variable can only be used *once* per notebook at the top level. The `let` block, like a function body, introduces a separate scope for the binding so `Pluto` doesn't incorporate the binding in its reactive model. This is necessary as we have more than one function named `f`. This is unlike `begin` blocks, which are quite typical in `Pluto`. The `begin` blocks allow one or more commands to occur in a cell, as the design of `Pluto` is one object per cell.

View File

@ -77,6 +77,7 @@ on how it is being called. Within `Pluto`, a message about
this will be noted.
The basic arithmetic operations on a calculator are "+", "-", "×",
"÷", and "$xʸ$". These have parallels in `Julia` through the *binary*
operators: `+`, `-`, `*`, `/`, and `^`:
@ -320,23 +321,21 @@ To emphasize, this is not the same as the value without the parentheses:
1 + 2 / 3 + 4
```
```julia; echo=false;
alert(L"""
!!! warning
The viniculum also indicates grouping when used with the
square root (the top bar), and complex conjugation. That usage is
often clear enough, but the usage of the viniculum in division
often leads to confusion. The example above is one where the
parentheses are often, erroneously, omitted. However, more
confusion can arise when there is more than one vinicula. An
expression such as $a/b/c$ written inline has no confusion, it is:
$(a/b) / c$ as left association is used; but when written with a
pair of vinicula there is often the typographical convention of a
slightly longer vinicula to indicate which is to be considered
first. In the absence of that, then top to bottom association is
often implied.
The viniculum also indicates grouping when used with the square root
(the top bar), and complex conjugation. That usage is often clear
enough, but the usage of the viniculum in division often leads to
confusion. The example above is one where the parentheses are often,
erroneously, omitted. However, more confusion can arise when there is
more than one vinicula. An expression such as $a/b/c$ written inline
has no confusion, it is: $(a/b) / c$ as left association is used; but
when written with a pair of vinicula there is often the typographical
convention of a slightly longer vinicula to indicate which is to
be considered first. In the absence of that, then top to bottom association is
often implied.
""")
```
### Infix, postfix, and prefix notation
@ -356,13 +355,9 @@ unfamiliar with. These mirror the familiar notation from most math
texts.
```julia; echo=false;
note("""
!!! note
In `Julia` many infix operations can be done using a prefix manner. For example `14 + 2` can also be evaluated by `+(14,2)`. There are very few *postfix* operations, though in these notes we will overload one, the `'` operation, to indicate a derivative.
In `Julia` many infix operations can be done using a prefix manner. For example `14 + 2` can also be evaluated by `+(14,2)`. There are very few *postfix* operations, though in these notes we will overload one, the `'` operation, to indicate a derivative.
""")
```
## Constants
@ -378,11 +373,9 @@ Whereas, `e` is is not simply the character `e`, but *rather* a [Unicode](../uni
```
```julia; echo=false
note("""
However, when the accompanying package, `CalculusWithJulia`, is loaded, the character `e` will refer to a floating point approximation to the Euler constant .
""")
```
!!! note
However, when the accompanying package, `CalculusWithJulia`, is loaded, the character `e` will refer to a floating point approximation to the Euler constant .
In the sequel, we will just use `e` for this constant (though more commonly the `exp` function), with the reminder that base `Julia` alone does not reserve this symbol.
@ -393,10 +386,12 @@ Mathematically these are irrational values with decimal expansions that do not r
```
```julia; echo=false;
alert("""In most cases. There are occasional (basically rare) spots where using `pi` by itself causes an eror where `1*pi` will not. The reason is `1*pi` will create a floating point value from the irrational object, `pi`.
""")
```
!!! warning
In most cases. There are occasional (basically rare) spots
where using `pi` by itself causes an eror where `1*pi` will
not. The reason is `1*pi` will create a floating point value from
the irrational object, `pi`.
### Numeric literals
@ -504,19 +499,14 @@ exp(2), log(10), sqrt(100), 10^(1/2)
```
!!! note
Parentheses have many roles. We've just seen that parentheses may be
used for grouping, and now we see they are used to indicate a function
is being called. These are familiar from their parallel usage in
traditional math notation. In `Julia`, a third usage is common, the
making of a "tuple," or a container of different objects, for example
`(1, sqrt(2), pi)`. In these notes, the output of multiple commands separated by commas is a printed tuple.
```julia; echo=false;
note("""
Parentheses have many roles. We've just seen that parentheses may be
used for grouping, and now we see they are used to indicate a function
is being called. These are familiar from their parallel usage in
traditional math notation. In `Julia`, a third usage is common, the
making of a "tuple," or a container of different objects, for example
`(1, sqrt(2), pi)`. In these notes, the output of multiple commands separated by commas is a printed tuple.
""")
```
@ -621,21 +611,17 @@ exact, can represent much bigger values and are exact for a reasonably
wide range of integer values.)
```julia; echo=false;
alert("""
!!! warning
In a turnaround from a classic blues song, we can think of
`Julia` as built for speed, not for comfort. All of these errors
above could be worked around so that the end user doesn't see
them. However, this would require slowing things down, either
through checking of operations or allowing different types of
outputs for similar type of inputs. These are tradeoffs that are
not made for performance reasons. For the most part, the tradeoffs
don't get in the way, but learning where to be careful takes some
time. Error messages often suggest a proper alternative.
In a turnaround from a classic blues song, we can think of `Julia` as
built for speed, not for comfort. All of these errors above could be
worked around so that the end user doesn't see them. However, this
would require slowing things down, either through checking of
operations or allowing different types of outputs for similar type of
inputs. These are tradeoffs that are not made for performance
reasons. For the most part, the tradeoffs don't get in the way, but
learning where to be careful takes some time. Error messages
often suggest a proper alternative.
""")
```
##### Example
@ -798,8 +784,8 @@ choices = [
q"(3 - 2)/ 4 - 1",
q"3 - 2 / (4 - 1)",
q"(3 - 2) / (4 - 1)"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -818,8 +804,8 @@ choices = [
q"3 * 2 / 4",
q"(3 * 2) / 4"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -838,8 +824,8 @@ choices = [
q"2 ^ 4 - 2",
q"(2 ^ 4) - 2",
q"2 ^ (4 - 2)"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -863,8 +849,8 @@ choices = [
q"1 / (2 / 3 / 4 / 5 / 6)",
q"1 / 2 * 3 / 4 * 5 / 6",
q"1 /(2 * 3 * 4 * 5 * 6)"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -879,8 +865,8 @@ q"2 - 3 - 4",
q"(2 - 3) - 4",
q"2 - (3 - 4)"
];
ans = 3;
radioq(choices, ans)
answ = 3;
radioq(choices, answ)
```
@ -895,8 +881,8 @@ q"2 - 3 * 4",
q"(2 - 3) * 4",
q"2 - (3 * 4)"
];
ans = 2;
radioq(choices, ans)
answ = 2;
radioq(choices, answ)
```
@ -912,8 +898,8 @@ q"-1^2",
q"(-1)^2",
q"-(1^2)"
];
ans = 2;
radioq(choices, ans)
answ = 2;
radioq(choices, answ)
```
@ -989,8 +975,8 @@ choices = [
raw"``e^{\pi}``",
raw"``\pi^{e}``"
];
ans = exp(pi) - pi^exp(1) > 0 ? 1 : 2;
radioq(choices, ans)
answ = exp(pi) - pi^exp(1) > 0 ? 1 : 2;
radioq(choices, answ)
```
###### Question
@ -1002,8 +988,8 @@ What is the value of $\pi - (x - \sin(x)/\cos(x))$ when $x=3$?
```julia; hold=true; echo=false;
x = 3;
ans = x - sin(x)/cos(x);
numericq(pi - ans)
answ = x - sin(x)/cos(x);
numericq(pi - answ)
```
###### Question
@ -1022,8 +1008,8 @@ Will `-2^2` produce `4` (which is a unary `-` evaluated *before* `^`) or `-4` (w
```julia; hold=true; echo=false;
choices = [q"4", q"-4"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -1057,6 +1043,6 @@ choices = [
"The precedence of numeric literal coefficients used for implicit multiplication is higher than other binary operators such as multiplication (`*`), and division (`/`, `\\`, and `//`)",
"Of course it is correct."
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```

View File

@ -165,11 +165,9 @@ That would be an enormous growth. Don't worry: "Exponential growth
cannot continue indefinitely, however, because the medium is soon
depleted of nutrients and enriched with wastes."
```julia; echo=false
note("""
The value of `2^n` and `2.0^n` is different in `Julia`. The former remains an integer and is subject to integer overflow for `n > 62`. As used above, `2^(n/6)` will not overflow for larger `n`, as when the exponent is a floating point value, the base is promoted to a floating point value.
""")
```
!!! note
The value of `2^n` and `2.0^n` is different in `Julia`. The former remains an integer and is subject to integer overflow for `n > 62`. As used above, `2^(n/6)` will not overflow for larger `n`, as when the exponent is a floating point value, the base is promoted to a floating point value.
##### Example
@ -366,11 +364,9 @@ If $1/10$ of the original carbon ``14`` remains, how old is the item? This amoun
-5730 * log2(1/10)
```
```julia; echo=false
note("""
(Historically) Libby and James Arnold proceeded to test the radiocarbon dating theory by analyzing samples with known ages. For example, two samples taken from the tombs of two Egyptian kings, Zoser and Sneferu, independently dated to ``2625`` BC plus or minus ``75`` years, were dated by radiocarbon measurement to an average of ``2800`` BC plus or minus ``250`` years. These results were published in Science in ``1949``. Within ``11`` years of their announcement, more than ``20`` radiocarbon dating laboratories had been set up worldwide. Source: [Wikipedia](http://tinyurl.com/p5msnh6).
""")
```
!!! note
(Historically) Libby and James Arnold proceeded to test the radiocarbon dating theory by analyzing samples with known ages. For example, two samples taken from the tombs of two Egyptian kings, Zoser and Sneferu, independently dated to ``2625`` BC plus or minus ``75`` years, were dated by radiocarbon measurement to an average of ``2800`` BC plus or minus ``250`` years. These results were published in Science in ``1949``. Within ``11`` years of their announcement, more than ``20`` radiocarbon dating laboratories had been set up worldwide. Source: [Wikipedia](http://tinyurl.com/p5msnh6).
### Properties of logarithms
@ -503,8 +499,8 @@ Which is bigger $e^2$ or $2^e$?
```julia; hold=true; echo=false
choices = ["``e^2``", "``2^e``"]
ans = e^2 - 2^e > 0 ? 1 : 2
radioq(choices, ans)
answ = e^2 - 2^e > 0 ? 1 : 2
radioq(choices, answ)
```
@ -514,8 +510,8 @@ Which is bigger $\log_8(9)$ or $\log_9(10)$?
```julia; hold=true; echo=false
choices = [raw"``\log_8(9)``", raw"``\log_9(10)``"]
ans = log(8,9) > log(9,10) ? 1 : 2
radioq(choices, ans)
answ = log(8,9) > log(9,10) ? 1 : 2
radioq(choices, answ)
```
###### Question
@ -529,8 +525,8 @@ raw"``\frac{\log(2)\log(3)}{\log(5)\log(4)}``",
raw"``2/5``",
raw"``\frac{\log(5)\log(4)}{\log(3)\log(2)}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -538,8 +534,8 @@ radioq(choices, ans)
Does $12$ satisfy $\log_2(x) + \log_3(x) = \log_4(x)$?
```julia; hold=true; echo=false
ans = log(2,12) + log(3,12) == log(4, 12)
yesnoq(ans)
answ = log(2,12) + log(3,12) == log(4, 12)
yesnoq(answ)
```
@ -563,8 +559,8 @@ for each?
```julia; hold=true; echo=false
choices = ["``1000`` times", "``100`` times", "``10`` times", "the same"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -600,8 +596,8 @@ choices = [
raw"``x \geq 1 + \log(x)``",
raw"``x \leq 1 + \log(x)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -623,8 +619,8 @@ choices = [
raw"``\log(1-x) \geq -x - x^2/2``",
raw"``\log(1-x) \leq -x - x^2/2``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -634,8 +630,8 @@ reciprocal property of exponents, $a^{-x} = (1/a)^x$, is at play here.)
```julia; hold=true; echo=false
choices = ["``-y``", "``1/y``", "``-1/y``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Based on this, the graph of $\log_{1/a}(x)$ is the graph of
@ -647,8 +643,8 @@ L"Flipped over the $x$ axis",
L"Flipped over the $y$ axis",
L"Flipped over the line $y=x$"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -662,8 +658,8 @@ choices = [
raw"``a^{y-x}``",
raw"``a^{y-x} \cdot (a^x - 1)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Using $a > 1$ we have:
@ -674,8 +670,8 @@ choices = [
L"as $a^x > 1$, $a^y > a^x$",
"``a^{y-x} > 0``"
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
If $a < 1$ then:
@ -686,6 +682,6 @@ L"as $a^{y-x} < 1$ as $y-x > 0$, $a^y < a^x$",
L"as $a^x < 1$, $a^y < a^x$",
"``a^{y-x} < 0``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -54,10 +54,8 @@ possible. The function $h(x)$ would have range
$[0,\infty)$. The $s(x)$ function is either $-1$ or $1$, so only has two possible values in its range. What about $g(x)$? It is a parabola that opens upward, so any $y$ values below the $y$ value of its vertex will not appear in the range. In this case, the symmetry indicates that the vertex will be at $(1/2, -1/4)$, so the range is $[-1/4, \infty)$.
```julia;echo=false;
note("""
**Thanks to Euler (1707-1783):** The formal idea of a function is a relatively modern concept in mathematics. According to [Dunham](http://www.maa.org/sites/default/files/pdf/upload_library/22/Ford/dunham1.pdf),
!!! note
**Thanks to Euler (1707-1783):** The formal idea of a function is a relatively modern concept in mathematics. According to [Dunham](http://www.maa.org/sites/default/files/pdf/upload_library/22/Ford/dunham1.pdf),
Euler defined a function as an "analytic expression composed in any way
whatsoever of the variable quantity and numbers or constant
quantities." He goes on to indicate that as Euler matured, so did
@ -66,8 +64,6 @@ note("""
“analytic expression.” He finishes by saying: "It is fair to say
that we now study functions in analysis because of him."
""")
```
We will see that defining functions within `Julia` can be as simple a concept as Euler started with, but that the more abstract concept has a great advantage that is exploited in the design of the language.
@ -92,28 +88,24 @@ f(pi), g(2), h(4)
For typical cases like the three above, there isn't really much new to learn.
```julia;echo=false;
note("""
!!! note
The equals sign in `Julia` always indicates either an assignment or a
mutation of the object on the left side. The definition of a function
above is an *assignment*, in that a function is added (or modified) in
a table holding the methods associated with the function's name.
The equals sign in `Julia` always indicates either an assignment or a
mutation of the object on the left side. The definition of a function
above is an *assignment*, in that a function is added (or modified) in
a table holding the methods associated with the function's name.
The equals sign restricts the expressions available on the *left*-hand
side to a) a variable name, for assignment; b) mutating an object at an index,
as in `xs[1]`; c) mutating a property of a stuct; or d) a function assignment
following this form `function_name(args...)`.
The equals sign restricts the expressions available on the *left*-hand
side to a) a variable name, for assignment; b) mutating an object at an index,
as in `xs[1]`; c) mutating a property of a stuct; or d) a function assignment
following this form `function_name(args...)`.
Whereas function
definitions and usage in `Julia` mirrors standard math notation;
equations in math are not so mirrored in `Julia`. In mathematical
equations, the left-hand of an equation is typically a complicated
algebraic expression. Not so with `Julia`, where the left hand side of
the equals sign is prescribed and quite limited.
Whereas function
definitions and usage in `Julia` mirrors standard math notation;
equations in math are not so mirrored in `Julia`. In mathematical
equations, the left-hand of an equation is typically a complicated
algebraic expression. Not so with `Julia`, where the left hand side of
the equals sign is prescribed and quite limited.
""")
```
### The domain of a function
@ -244,17 +236,12 @@ Or similarly, a function to represent a cell phone plan where the first ``500``
cellplan(x) = x < 500 ? 20.0 : 20.0 + 0.05 * (x-500)
```
```julia;echo=false;
alert("""
Type stability. These last two definitions used `10.0` and `20.0`
instead of the integers `10` and `20` for the answer. Why the extra
typing? When `Julia` can predict the type of the output from the type
of inputs, it can be more efficient. So when possible, we help out and
ensure the output is always the same type.
""")
```
!!! warning
Type stability. These last two definitions used `10.0` and `20.0`
instead of the integers `10` and `20` for the answer. Why the extra
typing? When `Julia` can predict the type of the output from the type
of inputs, it can be more efficient. So when possible, we help out and
ensure the output is always the same type.
##### Example
@ -303,11 +290,9 @@ end
The line `return x^2`, could have just been `x^2` as it is the last (and) only line evaluated.
```julia;echo=false;
note("""
The `return` keyword is not a function, so is not called with parentheses. An emtpy `return` statement will return a value of `nothing`.
""")
```
!!! note
The `return` keyword is not a function, so is not called with parentheses. An emtpy `return` statement will return a value of `nothing`.
##### Example
@ -602,11 +587,9 @@ just uses the change-of-base formula for logarithms.
But not so fast, on the left side is a function with two arguments and on the right side the functions have one argument - yet they share the same name. How does `Julia` know which to use? `Julia` uses the number, order, and *type* of the positional arguments passed to a function to determine which function definition to use. This is technically known as [multiple dispatch](http://en.wikipedia.org/wiki/Multiple_dispatch) or **polymorphism**. As a feature of the language, it can be used to greatly simplify the number of functions the user must learn. The basic idea is that many functions are "generic" in that they have methods which will work differently in different scenarios.
```julia;echo=false;
alert("""
Multiple dispatch is very common in mathematics. For example, we learn different ways to add: integers (fingers, carrying), real numbers (align the decimal points), rational numbers (common denominators), complex numbers (add components), vectors (add components), polynomials (combine like monomials), ... yet we just use the same `+` notation for each operation. The concepts are related, the details different.
""")
```
!!! warning
Multiple dispatch is very common in mathematics. For example, we learn different ways to add: integers (fingers, carrying), real numbers (align the decimal points), rational numbers (common denominators), complex numbers (add components), vectors (add components), polynomials (combine like monomials), ... yet we just use the same `+` notation for each operation. The concepts are related, the details different.
`Julia` is similarly structured. `Julia` terminology would be to call the operation "`+`" a *generic function* and the different implementations *methods* of "`+`". This allows the user to just need to know a smaller collection of generic concepts yet still have the power of detail-specific implementations. To see how many different methods are defined in the base `Julia` language for the `+` operator, we can use the command `methods(+)`. As there are so many ($\approx 200$) and that number is growing, we illustrate how many different logarithm methods are implemented for "numbers:"
@ -720,17 +703,15 @@ creates a function, this function is returned by `shift_right`.
So we could have done something more complicated like:
```julia;
p(x) = x^2 - 2x
l = shift_right(p, c=3)
f(x) = x^2 - 2x
l = shift_right(f, c=3)
```
Then `l` is a function that is derived from `p`.
Then `l` is a function that is derived from `f`.
!!! note
The value of `c` used when `l` is called is the one passed to `shift_right`. Functions like `l` that are returned by other functions also are called *closures*, as the context they are evaluated within includes the context of the function that constructs them.
```julia;echo=false
note("""
The value of `c` used when `l` is called is the one passed to `shift_right`. Functions like `l` that are returned by other functions also are called *closures*, as the context they are evaluated within includes the context of the function that constructs them.
""")
```
Anonymous functions can be created with the `function` keyword, but we will use the "arrow" notation, `arg->body` to create them, The above, could have been defined as:
@ -741,32 +722,27 @@ shift_right_alt(f; c=0) = x -> f(x-c)
When the `->` is seen a function is being created.
```julia;echo=false;
alert("""
Generic versus anonymous functions. Julia has two types of functions,
generic ones, as defined by `f(x)=x^2` and anonymous ones, as defined
by `x -> x^2`. One gotcha is that `Julia` does not like to use the
same variable name for the two types. In general, Julia is a dynamic
language, meaning variable names can be reused with different types
of variables. But generic functions take more care, as when a new
method is defined it gets added to a method table. So repurposing the
name of a generic function for something else is not allowed (well, in `Pluto` it is.). Similarly,
repurposing an already defined variable name for a generic function is
not allowed. This comes up when we use functions that return functions
as we have different styles that can be used: When we defined `l =
shift_right(f, c=3)` the value of `l` is assigned an anonymous
function. This binding can be reused to define other variables.
However, we could have defined the function `l` through `l(x) =
shift_right(f, c=3)(x)`, being explicit about what happens to the
variable `x`. This would add a method to the generic function `l`. Meaning, we
get an error if we tried to assign a variable to `l`, such as an
expression like `l=3`. We generally employ the latter style, even though
it involves a bit more typing, as we tend to stick to methods of generic
functions for consistency.
""")
```
!!! warning
Generic versus anonymous functions. Julia has two types of functions,
generic ones, as defined by `f(x)=x^2` and anonymous ones, as defined
by `x -> x^2`. One gotcha is that `Julia` does not like to use the
same variable name for the two types. In general, Julia is a dynamic
language, meaning variable names can be reused with different types
of variables. But generic functions take more care, as when a new
method is defined it gets added to a method table. So repurposing the
name of a generic function for something else is not allowed. Similarly,
repurposing an already defined variable name for a generic function is
not allowed. This comes up when we use functions that return functions
as we have different styles that can be used: When we defined `l =
shift_right(f, c=3)` the value of `l` is assigned an anonymous
function. This binding can be reused to define other variables.
However, we could have defined the function `l` through `l(x) =
shift_right(f, c=3)(x)`, being explicit about what happens to the
variable `x`. This would add a method to the generic function `l`. Meaning, we
get an error if we tried to assign a variable to `l`, such as an
expression like `l=3`. We generally employ the latter style, even though
it involves a bit more typing, as we tend to stick to methods of generic
functions for consistency.
##### Example: the secant line
@ -863,8 +839,8 @@ choices = [
"Domain is all non-negative numbers, range is all real numbers",
"Domain is all non-negative numbers, range is all non-negative numbers"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
##### Question
@ -879,8 +855,8 @@ L"Domain is all real numbers except $2$, range is all real numbers except $0$",
L"Domain is all non-negative numbers except $0$, range is all real numbers except $2$",
L"Domain is all non-negative numbers except $-2$, range is all non-negative numbers except $0$"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
##### Question
@ -893,8 +869,8 @@ raw"``f(x) = 2^x``",
raw"``f(x) = 1/x^2``",
raw"``f(x) = |x|``",
raw"``f(x) = \sqrt{x}``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -908,8 +884,8 @@ q"function f(x) = sin(x + pi/3)",
q"f(x) = sin(x + pi/3)",
q"f: x -> sin(x + pi/3)",
q"f x = sin(x + pi/3)"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -923,8 +899,8 @@ q"f(x) := (1 + x^2)^(-1)",
q"f[x] = (1 + x^2)^(-1)",
q"def f(x): (1 + x^2)^(-1)"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1057,8 +1033,8 @@ Will the call `C(1, mu=70)` use a value of `70` for `mu`?
```julia; hold=true;echo=false;
choices = ["Yes, this will work just as it does for keyword arguments",
"No, there will be an error that the function does not accept keyword arguments"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -1077,8 +1053,8 @@ choices = [
"If `x` is in `[a,b]` it returns `x`, otherwise it returns `NaN`",
"`x` is the larger of the minimum of `x` and `a` and the value of `b`, aka `max(min(x,a),b)`"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -1108,8 +1084,8 @@ L"You still get $0.649...$",
"You get a `MethodError`, as `cos(pi/4)` is evaluated as a number and `∘` is not defined for functions and numbers",
"You get a `generic` function, but this won't be callable. If tried, it will give an method error."
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1121,8 +1097,8 @@ choices = [
"It is `0.6663667453928805`, the same as `cos(sin(1))`",
"It is `0.5143952585235492`, the same as `sin(cos(1))`",
"It gives an error"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -1136,8 +1112,8 @@ fn(3)
```julia; hold=true;echo=false;
choices = ["`true`","`false`"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -1160,8 +1136,8 @@ Repeat the secant method two more times to find a better approximation for $\sqr
```julia; hold=true;echo=false;
choices = [q"4//3", q"7//5", q"58//41", q"816//577"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
How small is the value of $f(c)$ for this value?
@ -1175,8 +1151,8 @@ How close is this answer to the true value of $\sqrt{2}$?
```julia; hold=true;echo=false;
choices = [L"about $8$ parts in $100$", L"about $1$ parts in $100$", L"about $4$ parts in $10,000$", L"about $2$ parts in $1,000,000$"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
(Finding a good approximation to $\sqrt{2}$ would be helpful to builders, for example, as it could be used to verify the trueness of a square room, say.)
@ -1190,8 +1166,8 @@ choices = ["Just use `f = h - g`",
"Define `f(x) = h(x) - g(x)`",
"Use `x -> h(x) - g(x)` when the difference is needed"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question

View File

@ -120,10 +120,9 @@ From this, we have the function $g(y) = (y-32) / (9/5)$ is the inverse function
*Usually* we use the name $f^{-1}$ for the inverse function of $f$, so this would be most often [seen](http://tinyurl.com/qypbueb) as $f^{-1}(x) = (x-32)/(9/5)$ or after simplification $f^{-1}(x) = (5/9) \cdot (x-32)$.
```julia; echo=false
note(L"""The use of a negative exponent on the function name is *easily* confused for the notation for a reciprocal when it is used on a mathematical *expression*. An example might be the notation $(1/x)^{-1}$. As this is an expression this would simplify to $x$ and not the inverse of the *function* $f(x)=1/x$ (which is $f^{-1}(x) = 1/x$).
""")
```
!!! note
The use of a negative exponent on the function name is *easily* confused for the notation for a reciprocal when it is used on a mathematical *expression*. An example might be the notation $(1/x)^{-1}$. As this is an expression this would simplify to $x$ and not the inverse of the *function* $f(x)=1/x$ (which is $f^{-1}(x) = 1/x$).
##### Example
@ -277,10 +276,9 @@ same scale, so that this type of line will look perpendicular.)
One consequence of this symmetry, is that if $f$ is strictly increasing, then so is its inverse.
```julia; echo=false
note(L"""In the above we used `cbrt(x)` and not `x^(1/3)`. The latter usage assumes that $x \geq 0$ as it isn't guaranteed that for all real exponents the answer will be a real number. The `cbrt` function knows there will always be a real answer and provides it.
""")
```
!!!note
In the above we used `cbrt(x)` and not `x^(1/3)`. The latter usage assumes that $x \geq 0$ as it isn't guaranteed that for all real exponents the answer will be a real number. The `cbrt` function knows there will always be a real answer and provides it.
### Lines
@ -323,8 +321,8 @@ Is it possible that a function have two different inverses?
```julia; hold=true; echo=false
choices = [L"No, for all $x$ in the domain an an inverse, the value of any inverse will be the same, hence all inverse functions would be identical.",
L"Yes, the function $f(x) = x^2, x \geq 0$ will have a different inverse than the same function $f(x) = x^2, x \leq 0$"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -335,8 +333,8 @@ A function takes a value $x$ adds $1$, divides by $2$, and then subtracts $1$. I
choices = [L"Yes, the function is the linear function $f(x)=(x+1)/2 + 1$ and so is monotonic.",
L"No, the function is $1$ then $2$ then $1$, but not \"one-to-one\""
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -347,8 +345,8 @@ Is the function $f(x) = x^5 - x - 1$ one-to-one?
choices=[L"Yes, a graph over $(-100, 100)$ will show this.",
L"No, a graph over $(-2,2)$ will show this."
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -396,16 +394,16 @@ What is $g(x) = (f(x))^{-1}$?
```julia; hold=true; echo=false
choices = ["``g(x) = x``", "``g(x) = x^{-1}``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
What is $g(x) = f^{-1}(x)$?
```julia; hold=true; echo=false
choices = ["``g(x) = x``", "``g(x) = x^{-1}``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -457,8 +455,8 @@ L"The function that multiplies by $2$, subtracts $1$ and then squares the value.
L"The function that divides by $2$, adds $1$, and then takes the square root of the value.",
L"The function that takes square of the value, then subtracts $1$, and finally multiplies by $2$."
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -509,8 +507,8 @@ choices = [
"``f^{-1}(x) = (5y-4)^3``",
"``f^{-1}(x) = 5/(x^3 + 4)``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -524,8 +522,8 @@ raw"``f^{-1}(x) = (x-e)^{1/\pi}``",
raw"``f^{-1}(x) = (x-\pi)^{e}``",
raw"``f^{-1}(x) = (x-e)^{\pi}``"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -536,8 +534,8 @@ choices = [
raw"``[7, \infty)``",
raw"``(-\infty, \infty)``",
raw"``[0, \infty)``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -550,8 +548,8 @@ choices = [
raw"``[7, \infty)``",
raw"``(-\infty, \infty)``",
raw"``[0, \infty)``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -620,8 +618,8 @@ choices = [
L"As $f_4(f_3(f_2(f_1(x))))=(f_1 \circ f_2 \circ f_3 \circ f_4)(x)$",
"As the latter is more complicated than the former."
]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
@ -631,8 +629,8 @@ What is $g_2(x)=f_2^{-1}(x)$?
```julia; hold=true; echo=false
choices = ["``g_2(x) = x^{-1}``", "``g_2(x) = x``", "``g_2(x) = x -1``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
What is $g_3(x)=f_3^{-1}(x)$?
@ -642,8 +640,8 @@ choices = [
raw"``c^2/(b\cdot c - a\cdot d) \cdot x``",
raw"``(b\cdot c-a\cdot d)/c^2 \cdot x``",
raw"``c^2 x``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Given these, what is the value of $g_4(g_3(g_2(g_1(f_4(f_3(f_2(f_1(10))))))))$?

View File

@ -26,10 +26,6 @@ The [`Julia`](http://www.julialang.org) programming language is well suited as a
## Interacting with `Julia`
The html version of the **Calculus With Julia** notes are formatted as
Pluto notebooks. `Pluto` is one of many different means for a user to
interact with a `Julia` process.
At a basic level, `Julia` provides a means to read commands or instructions, evaluate those commands, and then print or return those commands. At a user level, there are many different ways to interact with the reading and printing. For example:
* The REPL. The `Julia` terminal is the built-in means to interact with `Julia`. A `Julia` Terminal has a command prompt, after which commands are typed and then sent to be evaluated by the `enter` key. The terminal may look something like the following where `2+2` is evaluated:
@ -57,7 +53,7 @@ julia> 2 + 2
* A notebook. The [Project Juptyer](https://jupyter.org/) provides a notebook interface for interacting with `Julia` and a more `IDE` style `jupyterlab` interface. A jupyter notebook has cells where commands are typed and immediately following is the printed output returned by `Julia`. The output of a cell depends on the state of the kernel when the cell is computed, not the order of the cells in the notebook. Cells have a number attached, showing the execution order. The `Juypter` notebook is used by `binder` and can be used locally through the `IJulia` package. This notebook has the ability to display many different types of outputs in addition to plain text, such as images, marked up math text, etc.
* The [Pluto](https://github.com/fonsp/Pluto.jl) package provides a *reactive* notebook interface. Reactive means when one "cell" is modified and executed, the new values cascade to all other dependent cells which in turn are updated. This is very useful for exploring a parameter space, say. These html pages are formatted as `Pluto` notebooks, which makes them able to be easily run on the reader's desktop.
* The [Pluto](https://github.com/fonsp/Pluto.jl) package provides a *reactive* notebook interface. Reactive means when one "cell" is modified and executed, the new values cascade to all other dependent cells which in turn are updated. This is very useful for exploring a parameter space, say. Pluto notebooks can be exported as HTML files which make them easy to read online and -- by clever design -- embed the `.jl` file that can run through `Pluto` if it is downloaded.
The `Pluto` interface has some idiosyncracies that need explanation:
@ -103,11 +99,9 @@ Pkg.add("CalculusWithJulia")
This command instructs `Julia` to look at its *general registry* for the `CalculusWithJulia.jl` package, download it, then install it. Once installed, a package only needs to be brought into play with the `using` or `import` commands.
```julia; echo=false;
note("""
In a terminal setting, there is a package mode, entered by typing `]` as the leading character and exited by entering `<delete>` at a blank line. This mode allows direct access to `Pkg` with a simpler syntax. The command above would be just `add CalculusWithJulia`.)
""")
```
!!! note
In a terminal setting, there is a package mode, entered by typing `]` as the leading character and exited by entering `<delete>` at a blank line. This mode allows direct access to `Pkg` with a simpler syntax. The command above would be just `add CalculusWithJulia`.)
Packages can be updated through the command `Pkg.up()`, and removed with `Pkg.rm(pkgname)`.
@ -129,15 +123,16 @@ Pkg.add("HQuadrature") # for higher-dimensional integration
## `Julia` commands
In `Pluto`, commands are typed into a notebook cell:
In a `Jupyter` notebook or `Pluto` notebook, commands are typed into a
notebook cell:
```julia;
2 + 2 # use shift-enter to evaluate
```
Commands are executed by using `shift-enter` or the run button at the bottom right of a cell.
Commands are executed by using `shift-enter` or a run button near the cell.
Multiple commands per cell are possible if a `begin` or `let` block is used.
In `Jupyter` multiple commands per cell are allowed. In `Pluto`, a `begin` or `let` block is used to collect multiple commmands into a single call.
Commands may be separated by new lines or semicolons.
On a given line, anything **after** a `#` is a *comment* and is not processed.
@ -146,7 +141,10 @@ The results of the last command executed will be displayed in an
output area. Separating values by commas allows more than one value to be
displayed. Plots are displayed when the plot object is returned by the last executed command.
The state of a Pluto notebook is a result of all the cells in the notebook being executed. The cell order does not impact this and can be rearranged by the user.
In `Jupyter`, the state of the notebook is a determined by the cells
executed along with their order. The state of a `Pluto` notebook is a
result of all the cells in the notebook being executed. The cell order
does not impact this and can be rearranged by the user.
## Numbers, variable types
@ -472,11 +470,9 @@ With `Plots` loaded, we can plot a function by passing the function object by na
plot(sin, 0, 2pi) # plot a function - by name - over an interval [a,b]
```
```julia; echo=false
note("""
This is in the form of **the** basic pattern employed: `verb(function_object, arguments...)`. The verb in this example is `plot`, the object `sin`, the arguments `0, 2pi` to specify `[a,b]` domain to plot over.
""")
```
!!1 note
This is in the form of **the** basic pattern employed: `verb(function_object, arguments...)`. The verb in this example is `plot`, the object `sin`, the arguments `0, 2pi` to specify `[a,b]` domain to plot over.
Plotting more than one function over ```[a,b]``` is achieved through the `plot!` function, which modifies the existing plot (`plot` creates a new one) by adding a new layer:

View File

@ -45,9 +45,9 @@ equal can also be represented with the Unicode `≤` (generated by
`\le[tab]`). Similarly, for greater than or equal, there is
`\ge[tab]`.
```julia; echo=false;
alert("The use of `==` is necessary, as `=` is used for assignment and mutation.")
```
!!! warning
The use of `==` is necessary, as `=` is used for assignment and mutation.")
The `!` operator takes a boolean value and negates it. It uses prefix notation:
@ -80,9 +80,9 @@ a < b, a + c < b + c
Trying other choices will show that the two answers are either both `false` or both `true`.
```julia; echo=false;
alert(""" Well, almost... When `Inf` or `NaN` are involved, this may not hold, for example `1 + Inf < 2 + Inf` is actually `false`. As would be `1 + (typemax(1)-1) < 2 + (typemax(1)-1)`.""")
```
!!! warning
Well, almost... When `Inf` or `NaN` are involved, this may not hold, for example `1 + Inf < 2 + Inf` is actually `false`. As would be `1 + (typemax(1)-1) < 2 + (typemax(1)-1)`.
So adding or subtracting most any finite value from an inequality will preserve the inequality, just as it does for equations.
@ -131,7 +131,7 @@ In summary we investigated numerically that the following hold:
- `a < b` if and only if `1/a > 1/b` for all finite, positive `a` and `b`.
#### Examples
### Examples
We now show some inequalities highlighted on this [Wikipedia](http://en.wikipedia.org/wiki/Inequality_%28mathematics%29) page.
@ -337,8 +337,8 @@ choices = [
"`e^pi` is equal to `pi^e`",
"`e^pi` is less than `pi^e`"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -346,8 +346,8 @@ radioq(choices, ans)
Is $\sin(1000)$ positive?
```julia; hold=true; echo=false;
ans = (sin(1000) > 0)
yesnoq(ans)
answ = (sin(1000) > 0)
yesnoq(answ)
```
###### Question
@ -359,8 +359,8 @@ choices = [
"``-1/a < -1/b``",
"``-1/a > -1/b``",
raw"``-1/a \geq -1/b``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -372,8 +372,8 @@ Suppose you know $a < 0 < b$, is it true that $1/a > 1/b$?
choices = ["Yes, it is always true.",
"It can sometimes be true, though not always.",
L"It is never true, as $1/a$ is negative and $1/b$ is positive"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -394,8 +394,8 @@ $x$. Which of these indicates the first negative value : `airyai(-1) <0`,
```julia; hold=true; echo=false;
choices = ["`airyai($i) < 0`" for i in -1:-1:-5]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -406,8 +406,8 @@ By trying three different values of $x > 0$ which of these could possibly be alw
choices = ["`x^x <= (1/e)^(1/e)`",
"`x^x == (1/e)^(1/e)`",
"`x^x >= (1/e)^(1/e)`"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -420,8 +420,8 @@ when $x,y > 0$ and $0 < p < 1$:
choices = ["`(x+y)^p < x^p + y^p`",
"`(x+y)^p == x^p + y^p`",
"`(x+y)^p > x^p + y^p`"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -436,8 +436,8 @@ JSTOR, AMM, Vol.97, No.1, 1990). Which one?
choices = ["`a^a + b^b <= a^b + b^a`",
"`a^a + b^b >= a^b + b^a`",
"`a^b + b^a <= 1`"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -457,8 +457,8 @@ Which of the following is equivalent to $\lvert x - a\rvert > b$:
choices = [raw"``-b < x - a < b``",
raw"`` -b < x-a \text{ and } x - a < b``",
raw"``x - a < -b \text{ or } x - a > b``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -494,8 +494,8 @@ Which of these will show DeMorgan's law holds when both values are `false`:
choices = ["`!(false && false) == (!false && !false)`",
"`!(false && false) == (false || false)`",
"`!(false && false) == (!false || !false)`"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -505,8 +505,8 @@ For floating point numbers there are two special values `Inf` and `NaN`. For whi
```julia; hold=true; echo=false;
choices = ["`Inf < 3.0` and `3.0 <= Inf`",
"`NaN < 3.0` and `3.0 <= NaN`"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -542,8 +542,8 @@ choices = ["""
In the manual we can read that "In the expression `a || b`, the subexpression `b` is only evaluated if `a` evaluates to false." In this case `a` is `true` and so `a` is returned.
""",
"Since the second value is \"`missing`\", only the first is used. So `false || missing` would also be `false`"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
The value for `true && missing` is `missing`, not a boolean value. What happens?
@ -553,6 +553,6 @@ choices = ["""
In the manual we can read that "In the expression `a && b`, the subexpression `b` is only evaluated if `a` evaluates to true." In this case, `a` is `false` so `b` is evaluated and returned. As `b` is just `missing` that is the return value.
""",
"Since the second value is \"`missing`\" all such answers would be missing."]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -57,13 +57,11 @@ types through an easy to understand syntax:
* rationals are constructed from integers using the double division operator, `//`; and
* complex numbers are formed by including a term with the imaginary unit, `im`.
```julia; echo=false;
alert("""
Heads up, the difference between `1` and `1.0` is subtle.
Even more so, as `1.` will parse as `1.0`.
This means some expressions, such as `2.*3`, are ambigous, as the `.` might be part of the `2` (as in `2. * 3`) or the operation `*` (as in `2 .* 3`).
""")
```
!!! warngin
Heads up, the difference between `1` and `1.0` is subtle.
Even more so, as `1.` will parse as `1.0`.
This means some expressions, such as `2.*3`, are ambigous, as the `.` might be part of the `2` (as in `2. * 3`) or the operation `*` (as in `2 .* 3`).
Similarly, each type is printed slightly differently.
@ -197,22 +195,13 @@ as $a\cdot 2^b$ where $a$ is the *significand* and $b$ is the
As per IEEE Standard 754, the `Float64` type gives 52 bits to the precision (with an additional implied one), 11 bits to the exponent and the other bit is used to represent the sign. Positive, finite, floating point numbers have a range approximately between $10^{-308}$ and $10^{308}$, as 308 is about $\log_{10}\cdot 2^{1023}$. The numbers are not evenly spread out over this range, but, rather, are much more concentrated closer to $0$.
```julia; echo=false;
alert("""
You can discover more about the range of floating point values provided by calling a few different functions.
- `typemax(0.0)` gives the largest value for the type (`Inf` in this case).
- `prevfloat(Inf)` gives the largest finite one, in general `prevfloat` is the next smallest floating point value.
- `nextfloat(-Inf)`, similarly, gives the smallest finite floating point value, and in general returns the next largest floating point value.
- `nextfloat(0.0)` gives the closest positive value to 0.
- `eps()` gives the distance to the next floating point number bigger than `1.0`. This is sometimes referred to as machine precision.
""", title="More on floating point", label="More on the range of floating point values")
```
!!! warning "More on floating point numbers"
You can discover more about the range of floating point values provided by calling a few different functions.
* `typemax(0.0)` gives the largest value for the type (`Inf` in this case).
* `prevfloat(Inf)` gives the largest finite one, in general `prevfloat` is the next smallest floating point value.
* `nextfloat(-Inf)`, similarly, gives the smallest finite floating point value, and in general returns the next largest floating point value.
* `nextfloat(0.0)` gives the closest positive value to 0.
* `eps()` gives the distance to the next floating point number bigger than `1.0`. This is sometimes referred to as machine precision.
#### Scientific notation
@ -421,11 +410,9 @@ discr = b^2 - 4a*c
When learning calculus, the only common usage of complex numbers arises when solving polynomial equations for roots, or zeros, though they are very important for subsequent work using the concepts of calculus.
```julia;echo=false
note("""
Though complex numbers are stored as pairs of numbers, the imaginary unit, `im`, is of type `Complex{Bool}`, a type that can be promoted to more specific types when `im` is used with different number types.
""")
```
!!! note
Though complex numbers are stored as pairs of numbers, the imaginary unit, `im`, is of type `Complex{Bool}`, a type that can be promoted to more specific types when `im` is used with different number types.
## Type stability
@ -560,8 +547,8 @@ The number created by `pi/2` is?
```julia; hold=true; echo=false;
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -569,8 +556,8 @@ radioq(choices, ans, keep_order=true)
The number created by `2/2` is?
```julia; hold=true; echo=false;
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -578,8 +565,8 @@ radioq(choices, ans, keep_order=true)
The number created by `2//2` is?
```julia; hold=true; echo=false;
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -587,8 +574,8 @@ radioq(choices, ans, keep_order=true)
The number created by `1 + 1//2 + 1/3` is?
```julia; hold=true; echo=false;
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -597,8 +584,8 @@ radioq(choices, ans, keep_order=true)
The number created by `2^3` is?
```julia; hold=true; echo=false;
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -607,8 +594,8 @@ radioq(choices, ans, keep_order=true)
The number created by `sqrt(im)` is?
```julia; hold=true; echo=false;
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
###### Question
@ -617,8 +604,8 @@ radioq(choices, ans, keep_order=true)
The number created by `2^(-1)` is?
```julia; hold=true; echo=false;
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -628,8 +615,8 @@ radioq(choices, ans, keep_order=true)
The "number" created by `1/0` is?
```julia; hold=true; echo=false;
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question

View File

@ -75,10 +75,8 @@ using Plots
```
```julia;echo=false
note("""
`Plots` is a frontend for one of several backends. `Plots` comes with a backend for web-based graphics (call `plotly()` to specify that); a backend for static graphs (call `gr()` for that). If the `PyPlot` package is installed, calling `pyplot()` will set that as a backend. For terminal usage, if the `UnicodePlots` package is installed, calling `unicodeplots()` will enable that usage. There are still other backends.""")
```
!!! note
`Plots` is a frontend for one of several backends. `Plots` comes with a backend for web-based graphics (call `plotly()` to specify that); a backend for static graphs (call `gr()` for that). If the `PyPlot` package is installed, calling `pyplot()` will set that as a backend. For terminal usage, if the `UnicodePlots` package is installed, calling `unicodeplots()` will enable that usage. There are still other backends.
The `plotly` backend is part of the `Plots` package, as is `gr`. Other backends require installation, such as `PyPlot` and `PlotlyJS`.
We use `gr` in these notes, for the most part. (The `plotly` backend is also quite nice for interactive usage, but doesn't work as well with the static HTML pages.)
@ -112,11 +110,9 @@ Plotting a function is then this simple: `plot(f, xmin, xmax)`.
> style, where the details to execute the action are only exposed as
> needed.
```julia; echo=false
note("""
The time to first plot can feel sluggish, but subsequent plots will be speedy. See the technical note at the end of this section for an explanation.
""")
```
!!! note
The time to first plot can feel sluggish, but subsequent plots will be speedy. See the technical note at the end of this section for an explanation.
Let's see some other graphs.
@ -165,16 +161,12 @@ plot(x -> mxplusb(x, (m=-1, b=1)), -1, 2)
```
```julia;echo=false
note("""
!!! note
The function object in the general pattern `action(function, args...)`
is commonly specified in one of three ways: by a name, as with `f`; as an
anonymous function; or as the return value of some other action
through composition.
The function object in the general pattern `action(function, args...)`
is commonly specified in one of three ways: by a name, as with `f`; as an
anonymous function; or as the return value of some other action
through composition.
""")
```
Anonymous functions are also created by `Julia's` `do` notation, which is useful when the first argument to function (like `plot`) accepts a function:
@ -186,11 +178,9 @@ end
The `do` notation can be a bit confusing to read when unfamiliar, though its convenience makes it appealing.
```julia; echo=false
note("""
Some types we will encounter, such as the one for symbolic values or the special polynomial one, have their own `plot` recipes that allow them to be plotted similarly as above, even though they are not functions.
""")
```
!!! note
Some types we will encounter, such as the one for symbolic values or the special polynomial one, have their own `plot` recipes that allow them to be plotted similarly as above, even though they are not functions.
----
@ -248,22 +238,6 @@ pts_needed(x -> 10x, 0, 10), pts_needed(x -> sin(10x), 0, 10)
(In fact, the `21` is the minimum number of points used for any function; a linear function only needs two.)
##### Example
This demo (which is interactive within a `Pluto` session) shows more points are needed as the function becomes more "curvy." There are the minimum of ``21`` for a straight line, ``37`` for a half period, ``45`` for a full period, etc.
```julia; echo=false
md"""
n = $(@bind 𝐧 Slider(0:20, default=1))
"""
```
```julia; hold=true;
xs,ys = unzip(x -> sin(𝐧*x*pi), 0, 1)
plot(xs, ys, title="n=$(length(xs))")
scatter!(xs, ys)
```
----
For instances where a *specific* set of ``x`` values is desired to be
@ -495,16 +469,12 @@ The ``3`` main functions used in these notes for adding layers are:
* `annotate!((x,y, label))` to add a label at $(x,y)$
```julia;echo=false
alert("""
!!! warning
Julia has a convention to use functions named with a `!` suffix to
indicate that they mutate some object. In this case, the object is the
current graph, though it is implicit. Both `plot!`, `scatter!`, and
`annotate!` (others too) do this by adding a layer.
Julia has a convention to use functions named with a `!` suffix to
indicate that they mutate some object. In this case, the object is the
current graph, though it is implicit. Both `plot!`, `scatter!`, and
`annotate!` (others too) do this by adding a layer.
""")
```
## Additional arguments
@ -709,8 +679,8 @@ choices = ["`(-Inf, -1)` and `(0,1)`",
"`(-Inf, -0.577)` and `(0.577, Inf)`",
"`(-1, 0)` and `(1, Inf)`"
];
ans=3;
radioq(choices, ans)
answ=3;
radioq(choices, answ)
```
@ -737,8 +707,8 @@ choices = ["`(-Inf, -3)` and `(0, 1)`",
"`(-3, 0)` and `(1, Inf)`",
"`(-Inf, -4.1)` and `(1.455, Inf)`"
];
ans=2;
radioq(choices, ans)
answ=2;
radioq(choices, answ)
```
###### Question
@ -787,15 +757,15 @@ choices = [
"`f(x) = x <= 4 ? 35.0 : 35.0 + 10.0 * (x-4)`",
"`f(x) = x <= 10 ? 35.0 : 35.0 + 4.0 * (x-10)`"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
Make a plot of the model. Graphically estimate how many bags of trash will cost 55 dollars.
```julia; hold=true;echo=false
ans = 15
numericq(ans, .5)
answ = 15
numericq(answ, .5)
```
###### Question
@ -829,8 +799,8 @@ What is seen?
choices = [L"It oscillates wildly, as the period is $T=2\pi/(500 \pi)$ so there are 250 oscillations.",
"It should oscillate evenly, but instead doesn't oscillate very much near 0 and 1",
L"Oddly, it looks exactly like the graph of $f(x) = \sin(2\pi x)$."]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
The algorithm to plot a function works to avoid aliasing issues. Does the graph generated by `plot(f, 0, 1)` look the same, as the one above?
@ -840,8 +810,8 @@ choices = ["Yes",
"No, but is still looks pretty bad, as fitting 250 periods into a too small number of pixels is a problem.",
"No, the graph shows clearly all 250 periods."
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -865,8 +835,8 @@ choices = [
"An ellipse",
"A straight line"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -898,8 +868,8 @@ choices = [
"A straight line",
"None of the above"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
@ -917,8 +887,8 @@ choices = [
"A straight line",
"None of the above"
]
ans = 3
radioq(choices, ans,keep_order=true)
answ = 3
radioq(choices, answ,keep_order=true)
```
@ -936,8 +906,8 @@ choices = [
"A straight line",
"None of the above"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
@ -956,8 +926,8 @@ choices = [
"A straight line",
"None of the above"
]
ans = 5
radioq(choices, ans, keep_order=true)
answ = 5
radioq(choices, answ, keep_order=true)
```
----

View File

@ -2,6 +2,7 @@
In this section we use the following add-on packages:
```julia
using SymPy
using Plots
@ -11,6 +12,8 @@ using Plots
using CalculusWithJulia
using CalculusWithJulia.WeaveSupport
fig_size = (800, 600) #400, 300)
const frontmatter = (
title = "Polynomials",
description = "Calculus with Julia: Polynomials",
@ -19,6 +22,7 @@ const frontmatter = (
nothing
```
----
Polynomials are a particular class of expressions that are simple
@ -57,7 +61,7 @@ a_n x^n + a_{n-1}x^{n-1} + \cdots a_1 x + a_0, \quad a_n \neq 0
```julia; hold=true; echo=false; cache=true
##{{{ different_poly_graph }}}
fig_size = (400, 300)
anim = @animate for m in 2:2:10
fn = x -> x^m
plot(fn, -1, 1, size = fig_size, legend=false, title="graph of x^{$m}", xlims=(-1,1), ylims=(-.1,1))
@ -109,11 +113,9 @@ of $m$ can be found from two points through the well-known formula:
m = \frac{y_1 - y_0}{x_1 - x_0} = \frac{\text{rise}}{\text{run}}
```
```julia; hold=true, echo=false; cache=true
```julia; hold=true; echo=false; cache=true
### {{{ lines_m_graph }}}
fig_size = (400, 300)
anim = @animate for m in [-5, -2, -1, 1, 2, 5, 10, 20]
fn = x -> m * x
plot(fn, -1, 1, size = fig_size, legend=false, title="m = $m", xlims=(-1,1), ylims=(-20, 20))
@ -177,21 +179,13 @@ Python session. That is great for `Julia` users, as the `PyCall` and
manner. This allows the `Julia` package `SymPy` to provide
functionality from SymPy within `Julia`.
```julia; echo=false
note("""
!!! note
When `SymPy` is installed through the package manger, the underlying `Python`
libraries will also be installed.
When `SymPy` is installed through the package manger, the underlying `Python`
libraries will also be installed.
""")
```
```julia; echo=false
note("""
The [`Symbolics`](../alternatives/symbolics) package is a rapidly
developing `Julia`-only packge that provides symbolic math options.
""")
```
!!! note
The [`Symbolics`](../alternatives/symbolics) package is a rapidly
developing `Julia`-only packge that provides symbolic math options.
----
@ -212,10 +206,8 @@ that can be made. The `@syms` macro documentation lists them. The
symbols. The *macro* `@syms` does not need assignment, as the
variable(s) are created behind the scenes by the macro.
```julia;echo=false
note("""Macros in `Julia` are just transformations of the syntax into other syntax. The `@` indicates they behave differently than regular function calls.
""")
```
!!! note
Macros in `Julia` are just transformations of the syntax into other syntax. The `@` indicates they behave differently than regular function calls.
The `SymPy` package does three basic things:
@ -440,8 +432,6 @@ larger values of $n$ have greater growth once outside of $[-1,1]$:
```julia; hold=true; echo=false; cache=true
### {{{ poly_growth_graph }}}
fig_size = (400, 300)
anim = @animate for m in 0:2:12
fn = x -> x^m
plot(fn, -1.2, 1.2, size = fig_size, legend=false, xlims=(-1.2, 1.2), ylims=(0, 1.2^12), title="x^{$m} over [-1.2, 1.2]")
@ -482,8 +472,6 @@ of the plot window until the graph appears U-shaped.
```julia;hold=true; echo=false; cache=true
### {{{ leading_term_graph }}}
fig_size = (400, 300)
anim = @animate for n in 1:6
m = [1, .5, -1, -5, -20, -25]
M = [2, 4, 5, 10, 25, 30]
@ -728,8 +716,8 @@ What is the leading term of $p$?
```julia; hold=true; echo=false
choices = ["``3``", "``3x^2``", "``-2x``", "``5``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -761,8 +749,8 @@ The linear polynomial $p = 2x + 3$ is written in which form:
```julia; hold=true; echo=false
choices = ["point-slope form", "slope-intercept form", "general form"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -781,8 +769,8 @@ What command will return the value of the polynomial when $x=2$?
```julia; hold=true; echo=false
choices = [q"p*2", q"p[2]", q"p_2", q"p(x=>2)"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
@ -796,8 +784,8 @@ L"Be $U$-shaped, opening upward",
L"Be $U$-shaped, opening downward",
L"Overall, go upwards from $-\infty$ to $+\infty$",
L"Overall, go downwards from $+\infty$ to $-\infty$"]
ans = 3
radioq(choices, ans, keep_order=true)
answ = 3
radioq(choices, answ, keep_order=true)
```
###### Question
@ -810,8 +798,8 @@ L"Be $U$-shaped, opening upward",
L"Be $U$-shaped, opening downward",
L"Overall, go upwards from $-\infty$ to $+\infty$",
L"Overall, go downwards from $+\infty$ to $-\infty$"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question
@ -824,8 +812,8 @@ L"Be $U$-shaped, opening upward",
L"Be $U$-shaped, opening downward",
L"Overall, go upwards from $-\infty$ to $+\infty$",
L"Overall, go downwards from $+\infty$ to $-\infty$"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -860,7 +848,7 @@ choices = [q"x^3 - 3x^2 + 2x",
q"x^3 - x^2 - 2x",
q"x^3 + x^2 - 2x",
q"x^3 + x^2 + 2x"]
ans = 2
answ = 2
radioq(choices, 2)
```
@ -874,6 +862,6 @@ q"-h^2 + 3hx - 3x^2",
q"h^3 + 3h^2x + 3hx^2 + x^3 -x^3/h",
q"x^3 - x^3/h",
q"0"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -2,7 +2,8 @@
In this section we use the following add on packages:
```juila
```julia
using CalculusWithJulia
using Plots
using SymPy
@ -191,11 +192,9 @@ quotient, remainder = divrem(x^4 + 2x^2 + 5, x - 2)
The answer is a tuple containing the quotient and remainder. The quotient itself could be found with `div` or `÷` and the remainder with `rem`.
```julia; echo=false
note("""
For those who have worked with SymPy within Python, `divrem` is the `div` method renamed, as `Julia`'s `div` method has the generic meaning of returning the quotient.
""")
```
!!! note
For those who have worked with SymPy within Python, `divrem` is the `div` method renamed, as `Julia`'s `div` method has the generic meaning of returning the quotient.
As well, the `apart` function could be used for this task. This function
@ -286,12 +285,11 @@ multiplicity must be accounted for and $x^2 + 1$ to see why complex
values may be necessary.)
```julia; echo=false
alert(raw"""
The special case of the ``0`` polynomial having no degree defined
eliminates needing to exclude it, as it has infinitely many roots. Otherwise, the language would be qualified to have ``n \geq 0``.
""")
```
!!! warning
The special case of the ``0`` polynomial having no degree defined
eliminates needing to exclude it, as it has infinitely many roots.
Otherwise, the language would be qualified to have ``n \geq 0``.
## Finding roots of a polynomial
@ -458,11 +456,9 @@ q = sympy.Poly(p, x) # identify `x` as indeterminate; alternatively p.as_poly(x
roots(q)
```
```julia; echo=false
note("""
The sympy `Poly` function must be found within the underlying `sympy` module, a Python object, hence is qualified as `sympy.Poly`. This is common when using `SymPy`, as only a small handful of the many functions available are turned into `Julia` functions, the rest are used as would be done in Python. (This is similar, but different than qualifying by a `Julia` module when there are two conflicting names. An example will be the use of the name `roots` in both `SymPy` and `Polynomials` to refer to a function that finds the roots of a polynomial. If both functions were loaded, then the last line in the above example would need to be `SymPy.roots(q)` (note the capitalization.)
""")
```
!!! note
The sympy `Poly` function must be found within the underlying `sympy` module, a Python object, hence is qualified as `sympy.Poly`. This is common when using `SymPy`, as only a small handful of the many functions available are turned into `Julia` functions, the rest are used as would be done in Python. (This is similar, but different than qualifying by a `Julia` module when there are two conflicting names. An example will be the use of the name `roots` in both `SymPy` and `Polynomials` to refer to a function that finds the roots of a polynomial. If both functions were loaded, then the last line in the above example would need to be `SymPy.roots(q)` (note the capitalization.)
### Numerically finding roots
The `solve` function can be used to get numeric approximations to the
@ -583,11 +579,9 @@ in fact there are three, two are *very* close together:
N.(solve(h))
```
```julia; echo=false
note("""
The difference of the two roots is around `1e-10`. For the graph over the interval of ``[-5,7]`` there are about ``800`` "pixels" used, so each pixel represents a size of about `1.5e-2`. So the cluster of roots would safely be hidden under a single "pixel."
""")
```
!!! note
The difference of the two roots is around `1e-10`. For the graph over the interval of ``[-5,7]`` there are about ``800`` "pixels" used, so each pixel represents a size of about `1.5e-2`. So the cluster of roots would safely be hidden under a single "pixel."
The point of this is to say, that it is useful to know where to look
for roots, even if graphing calculators or graphing programs make
@ -713,8 +707,8 @@ choices = [
"``6``",
"``0``"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -728,8 +722,8 @@ choices = [
"``x^2 - 2x + 2``",
"``2``"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -744,8 +738,8 @@ choices = [
"``x^3 + x^2 - 1``",
"``-2x + 2``"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -770,8 +764,8 @@ choices = [
"``x^5 + 2x^4 + 4x^3 + 8x^2 + 15x + 31``",
"``x^4 +2x^3 + 4x^2 + 8x + 15``",
"``31``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -784,8 +778,8 @@ choices = [
"``x^5 + 2x^4 + 4x^3 + 8x^2 + 15x + 31``",
"``x^4 +2x^3 + 4x^2 + 8x + 15``",
"``31``"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
What is $r$?
@ -797,8 +791,8 @@ choices = [
"``x^5 + 2x^4 + 4x^3 + 8x^2 + 15x + 31``",
"``x^4 +2x^3 + 4x^2 + 8x + 15``",
"``31``"]
ans = 5
radioq(choices, ans)
answ = 5
radioq(choices, answ)
```
@ -813,8 +807,8 @@ choices = [
L" $2$ and $3$",
L" $(x-2)$ and $(x-3)$",
L" $(x+2)$ and $(x+3)$"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -860,8 +854,8 @@ q"[-0.434235, -0.434235, 0.188049, 0.188049, 0.578696, 4.91368]",
q"[-0.434235, -0.434235, 0.188049, 0.188049]",
q"[0.578696, 4.91368]",
q"[-0.434235+0.613836im, -0.434235-0.613836im]"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -916,8 +910,8 @@ numericq(1)
Let $f(x) = x^5 - 4x^4 + x^3 - 2x^2 + x$. What does Cauchy's bound say is the largest possible magnitude of a root?
```julia; hold=true; echo=false
ans = 1 + 4 + 1 + 2 + 1
numericq(ans)
answ = 1 + 4 + 1 + 2 + 1
numericq(answ)
```
What is the largest magnitude of a real root?
@ -925,8 +919,8 @@ What is the largest magnitude of a real root?
```julia; hold=true; echo=false
f(x) = x^5 - 4x^4 + x^3 - 2x^2 + x
rts = find_zeros(f, -5..5)
ans = maximum(abs.(rts))
numericq(ans)
answ = maximum(abs.(rts))
numericq(answ)
```
@ -970,8 +964,8 @@ choices = [
"``2x^2``",
"``x``",
"``2x``"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
* True or false, the $degree$ of $T_n(x)$ is $n$: (Look at the defining relation and reason this out).
@ -992,8 +986,8 @@ The Chebyshev polynomials have the property that in fact all $n$ roots are real,
@syms x
p = 16x^5 - 20x^3 + 5x
rts = N.(solve(p))
ans = maximum(norm.(rts))
numericq(ans)
answ = maximum(norm.(rts))
numericq(answ)
```
* Plotting `p` over the interval $[-2,2]$ does not help graphically identify the roots:

View File

@ -187,11 +187,8 @@ observed from the output. The lone real root is approximately
irrational root.
```julia;echo=false
note("""
`SymPy` also has a `roots` function. If both `Polynomials` and `SymPy` are used together, calling `roots` must be qualified, as with `Polynomials.roots(...)`. Similarly, `degree` is provided in both, so it too must be qualified.
""")
```
!!! note
`SymPy` also has a `roots` function. If both `Polynomials` and `SymPy` are used together, calling `roots` must be qualified, as with `Polynomials.roots(...)`. Similarly, `degree` is provided in both, so it too must be qualified.
The `roots` function numerically identifies roots. As such, it is susceptible to floating point issues. For example, the following polynomial has one root with multiplicity ``5``, but ``5`` distinct roots are numerically identified:
@ -352,8 +349,8 @@ Mathematically we say the ``0`` polynomial has no degree. What convention does `
```julia; hold=true; echo=false;
choices = ["`nothing`", "`-1`", "`0`", "`Inf`", "`-Inf`"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -511,10 +508,7 @@ It is ``0\cdot T_1(x) + 1\cdot T_1(x) + 2\cdot T_2(x) + 3\cdot T_3(x) = -2 - 8\c
radioq(choices, 3)
```
```julia; hold=true; echo=false
note("""
The `Polynomials` package has an implementation, so you can check your answer through `convert(Polynomial, ChebyshevT([0,1,2,3]))`. Similarly, the `SpecialPolynomials` package has these and many other polynomial bases represented.
!!! note
The `Polynomials` package has an implementation, so you can check your answer through `convert(Polynomial, ChebyshevT([0,1,2,3]))`. Similarly, the `SpecialPolynomials` package has these and many other polynomial bases represented.
The `ApproxFun` package is built on top of polynomials expressed in this basis, as the Chebyshev polynomials have special properties which make them very suitable when approximating functions with polynomials. The `ApproxFun` package uses easier-to-manipulate polynomials to approximate functions very accurately, thereby being useful for investigating properties of non-linear functions leveraging properties for polynomials.
""")
```
The `ApproxFun` package is built on top of polynomials expressed in this basis, as the Chebyshev polynomials have special properties which make them very suitable when approximating functions with polynomials. The `ApproxFun` package uses easier-to-manipulate polynomials to approximate functions very accurately, thereby being useful for investigating properties of non-linear functions leveraging properties for polynomials.

View File

@ -4,7 +4,7 @@
```julia; echo=false; results="hidden"
using CalculusWithJulia
using CalculusWithJulia.WeaveSupport
const frontmatter = (
frontmatter = (
title = "Ranges and Sets",
description = "Calculus with Julia: Ranges and Sets",
tags = ["CalculusWithJulia", "precalc", "ranges and sets"],
@ -155,7 +155,7 @@ collected to realize the values.
The number of points is specified with keyword arguments, as in:
```julia;
xs = range(-1, 1, length=9) # or simply range(-1, 1, 9)
xs = range(-1, 1, length=9) # or simply range(-1, 1, 9) as of v"1.7"
```
and
@ -164,11 +164,9 @@ and
collect(xs)
```
```julia;echo=false
note("""
There is also the `LinRange(a, b, n)` function which can be more performant than `range`, as it doesn't try to correct for floating point errors.
""")
```
!!! note
There is also the `LinRange(a, b, n)` function which can be more performant than `range`, as it doesn't try to correct for floating point errors.
## Modifying sequences
@ -466,8 +464,8 @@ q"1:99",
q"1:3:99",
q"1:2:99"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -477,8 +475,8 @@ Which of these will create the sequence $2, 9, 16, 23, \dots, 72$?
```julia; hold=true;echo=false;
choices = [q"2:7:72", q"2:9:72", q"2:72", q"72:-7:2"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -502,8 +500,8 @@ choices = [
"`1:-1:10`",
"`1:10`"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -538,8 +536,8 @@ choices = ["It is just random",
"Addition happens prior to the use of `:` so this is like `1:(4+2):5`",
"It gives the correct answer, a generator for the vector `[3,5,7,9]`"
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -548,8 +546,8 @@ How is `a:b-1` interpreted:
```julia; hold=true;echo=false;
choices = ["as `a:(b-1)`", "as `(a:b) - 1`, which is `(a-1):(b-1)`"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -558,8 +556,8 @@ Create the sequence $10, 100, 1000, \dots, 1,000,000$ using a list comprehension
```julia; hold=true;echo=false;
choices = [q"[10^i for i in 1:6]", q"[10^i for i in [10, 100, 1000]]", q"[i^10 for i in [1:6]]"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -571,8 +569,8 @@ choices = [
q"[10^-i for i in 1:7]",
q"[(1/10)^i for i in 1:7]",
q"[i^(1/10) for i in 1:7]"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -581,8 +579,8 @@ Evaluate the expression $x^3 - 2x + 3$ for each of the values $-5, -4, \dots, 4,
```julia; hold=true;echo=false;
choices = [q"[x^3 - 2x + 3 for i in -5:5]", q"[x^3 - 2x + 3 for x in -(5:5)]", q"[x^3 - 2x + 3 for x in -5:5]"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question

View File

@ -260,7 +260,7 @@ saying it follows the shape of the leading term of $q(x)$, at the
expense of the work required to find $q(x)$.
##### Examples
### Examples
Consider the rational expression
@ -853,8 +853,8 @@ The rational expression $(x^3 - 2x + 3) / (x^2 - x + 1)$ would have
choices = [L"A horizontal asymptote $y=0$",
L"A horizontal asymptote $y=1$",
L"A slant asymptote with slope $m=1$"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -866,8 +866,8 @@ The rational expression $(x^2 - x + 1)/ (x^3 - 2x + 3)$ would have
choices = [L"A horizontal asymptote $y=0$",
L"A horizontal asymptote $y=1$",
L"A slant asymptote with slope $m=1$"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -881,8 +881,8 @@ The rational expression $(x^2 - x + 1)/ (x^2 - 3x + 3)$ would have
choices = [L"A horizontal asymptote $y=0$",
L"A horizontal asymptote $y=1$",
L"A slant asymptote with slope $m=1$"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -902,8 +902,8 @@ would have
choices = [L"A horizontal asymptote $y=0$",
L"A horizontal asymptote $y=1$",
L"A slant asymptote with slope $m=1$"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -923,8 +923,8 @@ choices = [L"A vertical asymptote $x=1$",
L"A slant asymptote with slope $m=1$",
L"A vertical asymptote $x=5$"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -946,8 +946,8 @@ choices = [
"``y = (1/3)x``",
"``y = (1/3)x - (1/3)``"
]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -971,8 +971,8 @@ Is the following common conception true: "The graph of a function never crosses
```julia; hold=true; echo=false
choices = ["No, the graph clearly crosses the drawn asymptote",
"Yes, this is true"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
(The wikipedia page indicates that the term "asymptote" was introduced
@ -1002,8 +1002,8 @@ choices = ["The horizontal asymptote is not a straight line.",
L"The $y$-axis scale shows that indeed the $y$ values are getting close to $0$.",
L"The graph is always decreasing, hence it will eventually reach $-\infty$."
]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -1040,8 +1040,8 @@ choices = ["between ``0`` and ``8`` hours",
"between ``8`` and ``16`` hours",
"between ``16`` and ``24`` hours",
"after one day"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
This graph has
@ -1051,8 +1051,8 @@ choices = [L"a slant asymptote with slope $50$",
L"a horizontal asymptote $y=20$",
L"a horizontal asymptote $y=0$",
L"a vertical asymptote with $x = 20^{1/3}$"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
@ -1073,6 +1073,6 @@ L"The $\sin(x)$ oscillates, but the rational function eventually follows $7/60 \
L"The $\sin(x)$ oscillates, but the rational function has a slant asymptote",
L"The $\sin(x)$ oscillates, but the rational function has a non-zero horizontal asymptote",
L"The $\sin(x)$ oscillates, but the rational function has a horizontal asymptote of $0$"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```

View File

@ -114,17 +114,13 @@ plot!(gf, label="g∘f")
```
```julia;echo=false
note("""
!!! note
Unlike how the basic arithmetic operations are treated, `Julia` defines the infix
Unicode operator `\\circ[tab]` to represent composition of functions,
mirroring mathematical notation. This infix operations takes in two functions and returns an anonymous function. It
can be useful and will mirror standard mathematical usage up to issues
with precedence rules.
Unlike how the basic arithmetic operations are treated, `Julia` defines the infix
Unicode operator `\\circ[tab]` to represent composition of functions,
mirroring mathematical notation. This infix operations takes in two functions and returns an anonymous function. It
can be useful and will mirror standard mathematical usage up to issues
with precedence rules.
""")
```
Starting with two functions and composing them requires nothing more
than a solid grasp of knowing the rules of function evaluation. If
@ -163,11 +159,9 @@ other compositions could have been given above. For example, the last
function is also $f(x) = e^{-x/2}$ composed with $g(x) = x^2$.
```julia;echo=false
note("""
The real value of composition is to break down more complicated things into a sequence of easier steps. This is good mathematics, but also good practice more generally. For example, when we approach a problem with the computer, we generally use a smallish set of functions and piece them together (that is, compose them) to find a solution.
""")
```
!!! note
The real value of composition is to break down more complicated things into a sequence of easier steps. This is good mathematics, but also good practice more generally. For example, when we approach a problem with the computer, we generally use a smallish set of functions and piece them together (that is, compose them) to find a solution.
### Shifting and scaling graphs
@ -508,8 +502,8 @@ If $f(x) = 1/x$ and $g(x) = x-2$, what is $g(f(x))$?
```julia; hold=true;echo=false
choices=["``1/(x-2)``", "``1/x - 2``", "``x - 2``", "``-2``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -519,8 +513,8 @@ If $f(x) = e^{-x}$ and $g(x) = x^2$ and $h(x) = x-3$, what is $f \circ g \circ h
```julia; hold=true;echo=false
choices=["``e^{-x^2 - 3}``", "``(e^x -3)^2``",
"``e^{-(x-3)^2}``", "``e^x+x^2+x-3``"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -530,8 +524,8 @@ If $h(x) = (f \circ g)(x) = \sin^2(x)$ which is a possibility for $f$ and $g$:
choices = [raw"``f(x)=x^2; \quad g(x) = \sin^2(x)``",
raw"```f(x)=x^2; \quad g(x) = \sin(x)``",
raw"``f(x)=\sin(x); \quad g(x) = x^2``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -544,7 +538,7 @@ choices = [
raw"``h(x) = 6 + \sin(x + 4)``",
raw"``h(x) = 6 + \sin(x-4)``",
raw"``h(x) = 6\sin(x-4)``"]
ans = 3
answ = 3
radioq(choices, 3)
```
@ -555,8 +549,8 @@ Let $h(x) = 4x^2$ and $f(x) = x^2$. Which is **not** true:
choices = [L"The graph of $h(x)$ is the graph of $f(x)$ stretched by a factor of ``4``",
L"The graph of $h(x)$ is the graph of $f(x)$ scaled by a factor of ``2``",
L"The graph of $h(x)$ is the graph of $f(x) shifted up by ``4`` units"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -567,8 +561,8 @@ The transformation $h(x) = (1/a) \cdot f((x-b)/a)$ can be viewed in one sequence
choices = [L"scaling by $1/a$, then shifting by $b$, then stretching by $1/a$",
L"shifting by $a$, then scaling by $b$, and then scaling by $1/a$",
L"shifting by $a$, then scaling by $a$, and then scaling by $b$" ]
ans=1
radioq(choices, ans)
answ=1
radioq(choices, answ)
```
###### Question
@ -603,8 +597,8 @@ raw"``\sin(2x)``",
raw"``\sin(\pi x)``",
raw"``2 \sin(\pi x)``"
]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
@ -626,8 +620,8 @@ choices = [
q"D(S(f))(n) = f(n)",
q"S(D(f))(n) = f(n) - f(0)"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -645,6 +639,6 @@ choices = [
q"D(S(f))(n) = f(n)",
q"S(D(f))(n) = f(n) - f(0)"
]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```

View File

@ -1,5 +1,6 @@
# Trigonometric functions
This section uses the following add-on packages:
```julia
@ -11,6 +12,8 @@ using SymPy
```julia; echo=false; results="hidden"
using CalculusWithJulia.WeaveSupport
fig_size = (800, 600)
const frontmatter = (
title = "Trigonometric functions",
description = "Calculus with Julia: Trigonometric functions",
@ -66,9 +69,8 @@ trigonometric functions are
\end{align*}
```
```julia; echo=false
note("""Many students remember these through [SOH-CAH-TOA](http://mathworld.wolfram.com/SOHCAHTOA.html).""")
```
!!! note
Many students remember these through [SOH-CAH-TOA](http://mathworld.wolfram.com/SOHCAHTOA.html).
Some algebra shows that $\tan(\theta) = \sin(\theta)/\cos(\theta)$. There are also ``3`` reciprocal functions, the cosecant, secant and cotangent.
@ -78,7 +80,6 @@ These definitions in terms of sides only apply for $0 \leq \theta \leq \pi/2$. M
```julia; hold=true; echo=false; cache=true
## {{{radian_to_trig}}}
fig_size = (400, 300)
function plot_angle(m)
r = m*pi
@ -181,15 +182,10 @@ sincos(pi/3)
```
```julia; echo=false
note(L"""
!!! note
For really large values, round off error can play a big role. For example, the *exact* value of $\sin(1000000 \pi)$ is $0$, but the returned value is not quite $0$ `sin(1_000_000 * pi) = -2.231912181360871e-10`. For exact multiples of $\pi$ with large multiples the `sinpi` and `cospi` functions are useful.
For really large values, round off error can play a big role. For example, the *exact* value of $\sin(1000000 \pi)$ is $0$, but the returned value is not quite $0$ `sin(1_000_000 * pi) = -2.231912181360871e-10`. For exact multiples of $\pi$ with large multiples the `sinpi` and `cospi` functions are useful.
(Both functions are computed by first employing periodicity to reduce the problem to a smaller angle. However, for large multiples the floating-point roundoff becomes a problem with the usual functions.)
""")
```
(Both functions are computed by first employing periodicity to reduce the problem to a smaller angle. However, for large multiples the floating-point roundoff becomes a problem with the usual functions.)
##### Example
@ -356,7 +352,6 @@ end
# create animoation
b₁=1/3; n₁=3; b₂=1/4; n₂=4
fig_size = (400, 300)
anim = @animate for t ∈ range(0, 2.5, length=50)
makegraph(t, b₁, n₁, b₂, n₂)
end
@ -618,45 +613,47 @@ the unit *hyperbola* ($x^2 - y^2 = 1$). We define the hyperbolic
sine ($\sinh$) and hyperbolic cosine ($\cosh$) through $(\cosh(\theta),
\sinh(\theta)) = (x,y)$.
```julia; hold=true; echo=false
## inspired by https://en.wikipedia.org/wiki/Hyperbolic_function
# y^2 = x^2 - 1
top(x) = sqrt(x^2 - 1)
```julia; echo=false
let
## inspired by https://en.wikipedia.org/wiki/Hyperbolic_function
# y^2 = x^2 - 1
top(x) = sqrt(x^2 - 1)
p = plot(; legend=false, aspect_ratio=:equal)
p = plot(; legend=false, aspect_ratio=:equal)
x₀ = 2
xs = range(1, x₀, length=100)
ys = top.(xs)
plot!(p, xs, ys, color=:red)
plot!(p, xs, -ys, color=:red)
x₀ = 2
xs = range(1, x₀, length=100)
ys = top.(xs)
plot!(p, xs, ys, color=:red)
plot!(p, xs, -ys, color=:red)
xs = -reverse(xs)
ys = top.(xs)
plot!(p, xs, ys, color=:red)
plot!(p, xs, -ys, color=:red)
xs = -reverse(xs)
ys = top.(xs)
plot!(p, xs, ys, color=:red)
plot!(p, xs, -ys, color=:red)
xs = range(-x₀, x₀, length=3)
plot!(p, xs, xs, linestyle=:dash, color=:blue)
plot!(p, xs, -xs, linestyle=:dash, color=:blue)
xs = range(-x₀, x₀, length=3)
plot!(p, xs, xs, linestyle=:dash, color=:blue)
plot!(p, xs, -xs, linestyle=:dash, color=:blue)
a = 1.2
plot!(p, [0,cosh(a)], [sinh(a), sinh(a)])
annotate!(p, sinh(a)/2, sinh(a)+0.25,"cosh(a)")
plot!(p, [cosh(a),cosh(a)], [sinh(a), 0])
annotate!(p, sinh(a) + 1, cosh(a)/2,"sinh(a)")
scatter!(p, [cosh(a)], [sinh(a)], markersize=5)
a = 1.2
plot!(p, [0,cosh(a)], [sinh(a), sinh(a)])
annotate!(p, [(sinh(a)/2, sinh(a)+0.25,"cosh(a)")])
plot!(p, [cosh(a),cosh(a)], [sinh(a), 0])
annotate!(p, [(sinh(a) + 1, cosh(a)/2,"sinh(a)")])
scatter!(p, [cosh(a)], [sinh(a)], markersize=5)
ts = range(0, a, length=100)
xs = cosh.(ts)
ys = sinh.(ts)
ts = range(0, a, length=100)
xs = cosh.(ts)
ys = sinh.(ts)
xs = [0, 1, xs..., 0]
ys = [0, 0, ys..., 0]
plot!(p, xs, ys, fillcolor=:red, fill=true, alpha=.3)
xs = [0, 1, xs..., 0]
ys = [0, 0, ys..., 0]
plot!(p, xs, ys, fillcolor=:red, fill=true, alpha=.3)
p
p
end
```
These values are more commonly expressed using the exponential function as:
@ -682,8 +679,8 @@ What is bigger $\sin(1.23456)$ or $\cos(6.54321)$?
```julia; hold=true; echo=false
a = sin(1.23456) > cos(6.54321)
choices = [raw"``\sin(1.23456)``", raw"``\cos(6.54321)``"]
ans = a ? 1 : 2
radioq(choices, ans, keep_order=true)
answ = a ? 1 : 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -694,8 +691,8 @@ Let $x=\pi/4$. What is bigger $\cos(x)$ or $x$?
x = pi/4
a = cos(x) > x
choices = [raw"``\cos(x)``", "``x``"]
ans = a ? 1 : 2
radioq(choices, ans, keep_order=true)
answ = a ? 1 : 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -707,8 +704,8 @@ choices = [
raw"``\cos(x) = \sin(x - \pi/2)``",
raw"``\cos(x) = \sin(x + \pi/2)``",
raw"``\cos(x) = \pi/2 \cdot \sin(x)``"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -720,8 +717,8 @@ choices = [
L"The values $k\pi$ for $k$ in $\dots, -2, -1, 0, 1, 2, \dots$",
L"The values $\pi/2 + k\pi$ for $k$ in $\dots, -2, -1, 0, 1, 2, \dots$",
L"The values $2k\pi$ for $k$ in $\dots, -2, -1, 0, 1, 2, \dots$"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -768,24 +765,24 @@ The sine function is an *odd* function.
```julia; hold=true; echo=false
choices = ["odd", "even", "neither"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
* The hyperbolic cosine is:
```julia; hold=true; echo=false
choices = ["odd", "even", "neither"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
* The hyperbolic tangent is:
```julia; hold=true; echo=false
choices = ["odd", "even", "neither"]
ans = 1
radioq(choices, ans, keep_order=true)
answ = 1
radioq(choices, answ, keep_order=true)
```
###### Question

View File

@ -64,11 +64,9 @@ Variable names can be reused, as here, where we redefine `x`:
x = 2
```
```julia; echo=false
note("""
The `Pluto` interface for `Julia` is idiosyncratic, as variables are *reactive*. This interface allows changes to a variable `x` to propogate to all other cells referring to `x`. Consequently, the variable name can only be assigned *once* per notebook **unless** the name is in some other namespace, which can be arranged by including the assignment inside a function or a `let` block.
""")
```
!!! note
The `Pluto` interface for `Julia` is idiosyncratic, as variables are *reactive*. This interface allows changes to a variable `x` to propogate to all other cells referring to `x`. Consequently, the variable name can only be assigned *once* per notebook **unless** the name is in some other namespace, which can be arranged by including the assignment inside a function or a `let` block.
`Julia` is referred to as a "dynamic language" which means (in most
@ -95,7 +93,7 @@ bottom = 5 - 6/7
top/bottom
```
#### Examples
### Examples
##### Example
@ -197,27 +195,22 @@ the `Main` module. `Julia` looks for variables in this module when it
encounters an expression and the value is substituted. Other uses, such as when variables are defined within a function, involve different contexts which may not be
visible within the `Main` module.
```julia; echo=false;
note("""
The `varinfo` function will list the variables currently defined in the
main workspace. There is no mechanism to delete a single variable.
""")
```
!!! note
The `varinfo` function will list the variables currently defined in the
main workspace. There is no mechanism to delete a single variable.
```julia; echo=false;
alert("""
**Shooting oneselves in the foot.** `Julia` allows us to locally
redefine variables that are built in, such as the value for `pi` or
the function object assigned to `sin`. For example, this is a
perfectly valid command `sin=3`. However, it will overwrite the
typical value of `sin` so that `sin(3)` will be an error. At the terminal, the
binding to `sin` occurs in the `Main` module. This shadows that
value of `sin` bound in the `Base` module. Even if redefined in
`Main`, the value in base can be used by fully qualifying the name,
as in `Base.sin(pi)`. This uses the notation
`module_name.variable_name` to look up a binding in a module.
""")
```
!!! warning
**Shooting oneselves in the foot.** `Julia` allows us to
locally redefine variables that are built in, such as the value
for `pi` or the function object assigned to `sin`. For example,
this is a perfectly valid command `sin=3`. However, it will
overwrite the typical value of `sin` so that `sin(3)` will be an
error. At the terminal, the binding to `sin` occurs in the `Main`
module. This shadows that value of `sin` bound in the `Base`
module. Even if redefined in `Main`, the value in base can be used
by fully qualifying the name, as in `Base.sin(pi)`. This uses the
notation `module_name.variable_name` to look up a binding in a
module.
## Variable names
@ -268,17 +261,12 @@ For example, we could have defined `theta` (`\theta[tab]`) and `v0` (`v\_0[tab]`
θ = 45; v₀ = 200
```
These notes often use Unicode alternatives to avoid the `Pluto` requirement of a single use of assigning to a variable name in a notebook without placing the assignment in a `let` block or a function body.
!!! note "Unicode"
These notes can be presented as HTML files *or* as `Pluto` notebooks. They often use Unicode alternatives to avoid the `Pluto` requirement of a single use of assigning to a variable name in a notebook without placing the assignment in a `let` block or a function body.
```julia; echo=false;
alert("""
There is even support for tab-completion of
[emojis](https://github.com/JuliaLang/julia/blob/master/stdlib/REPL/src/emoji_symbols.jl)
such as `\\:snowman:[tab]` or `\\:koala:[tab]`
""")
```
!!! note "Emojis"
There is even support for tab-completion of [emojis](https://github.com/JuliaLang/julia/blob/master/stdlib/REPL/src/emoji_symbols.jl) such as `\\:snowman:[tab]` or `\\:koala:[tab]`
##### Example
@ -404,8 +392,8 @@ What is the result of the above?
p, q = 0.25, 0.2;
top = p - q;
bottom = sqrt(p*(1-p));
ans = top/bottom;
numericq(ans)
answ = top/bottom;
numericq(answ)
```
###### Question
@ -433,8 +421,8 @@ q"some_really_long_name_that_is_no_fun_to_type",
q"aMiXeDcAsEnAmE",
q"fahrenheit451"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -445,8 +433,8 @@ Which of these symbols is one of `Julia`'s built-in math constants?
```julia; hold=true; echo=false;
choices = [q"pi", q"oo", q"E", q"I"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -464,8 +452,8 @@ choices=[
q"\delta[tab] = 1/10",
q"delta[tab] = 1/10",
q"$\\delta$ = 1/10"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -478,8 +466,8 @@ choices = [
q"a=1, b=2, c=3",
q"a,b,c = 1,2,3",
q"a=1; b=2; c=3"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -497,6 +485,6 @@ choices = ["Assign all three variables at once to a value of `3`",
"Create ``3`` linked values that will stay synced when any value changes",
"Throw an error"
]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```

View File

@ -8,7 +8,8 @@ using Plots
using Measures
using LaTeXStrings
fig_size = (400, 300)
#fig_size = (400, 300)
fig_size = (800, 600)
const frontmatter = (
title = "Vectors",
@ -463,23 +464,13 @@ component. However, the special keyword `end` will do so as well, when
put into the context of indexing. So `v[end]` is more idiomatic. (Similarly, there is a `begin` keyword that is useful when the vector is not ``1``-based, as is typical but not mandatory.)
```julia; echo=false;
note("""
There is [much more](http://julia.readthedocs.org/en/latest/manual/arrays/#indexing)
to indexing than just indexing by a single integer value. For example, the following can be used for indexing:
* a scalar integer (as seen)
* a range
* a vector of integers
* a boolean vector
Some add-on packages extend this further.
""",
title="More on indexing", label="More on indexing")
```
!!! note "More on indexing"
There is [much more](http://julia.readthedocs.org/en/latest/manual/arrays/#indexing) to indexing than just indexing by a single integer value. For example, the following can be used for indexing:
* a scalar integer (as seen)
* a range
* a vector of integers
* a boolean vector
Some add-on packages extend this further.
### Assignment and indexing
@ -668,10 +659,9 @@ performant `abs2` function which, in general, efficiently finds $|x|^2$
for various number types. The `.-` uses broadcasting to subtract a scalar (`mean(xs)`) from a vector (`xs`). Without the `.`, this would error.
```julia; echo=false;
note("""The `map` function is very much related to broadcasting and similarly named functions are found in many different programming languages. (The "dot" broadcast is mostly limited to `Julia` and mirrors on a similar usage of a dot in `MATLAB`.) For those familiar with other programming languages, using `map` may seem more natural. Its syntax is `map(f, xs)`.
""")
```
!!! note
The `map` function is very much related to broadcasting and similarly named functions are found in many different programming languages. (The "dot" broadcast is mostly limited to `Julia` and mirrors on a similar usage of a dot in `MATLAB`.) For those familiar with other programming languages, using `map` may seem more natural. Its syntax is `map(f, xs)`.
### Comprehensions
@ -763,15 +753,9 @@ In the sequel, we will typically use broadcasting for this task using two
steps: one to define a function the second to broadcast it.
```julia; echo=false;
note(L"""
!!! note
The style generally employed here is to use plural variable names for a collection of values, such as the vector of $y$ values and singular names when a single value is being referred to, leading to expressions like "`x in xs`".
The style generally employed here is to use plural variable names for a collection
of values, such as the vector of $y$ values and singular names when a
single value is being referred to, leading to expressions like "`x in xs`".
""")
```
## Other container types
@ -805,8 +789,8 @@ q"v = {4, 3}",
q"v = '4, 3'",
q"v = (4,3)",
q"v = <4,3>"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
###### Question
@ -815,8 +799,8 @@ Which command will create the vector with components "4,3,2,1"?
```julia; hold=true; echo=false;
choices = [q"v = [4,3,2,1]", q"v = (4,3,2,1)", q"v = {4,3,2,1}", q"v = '4, 3, 2, 1'", q"v = <4,3,2,1>"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
@ -840,8 +824,8 @@ Which of the following is the unit vector in the direction of $\vec{v} = \langle
```julia; hold=true; echo=false;
choices = [q"[3, 4]", q"[0.6, 0.8]", q"[1.0, 1.33333]", q"[1, 1]"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
@ -851,8 +835,8 @@ What vector is in the same direction as $\vec{v} = \langle 3,~ 4 \rangle$ but is
```julia; hold=true; echo=false;
choices = [q"[3, 4]", q"[30, 40]", q"[9.48683, 12.6491 ]", q"[10, 10]"]
ans = 2
radioq(choices, ans)
answ = 2
radioq(choices, answ)
```
###### Question
@ -861,8 +845,8 @@ If $\vec{v} = \langle 3,~ 4 \rangle$ and $\vec{w} = \langle 1,~ 2 \rangle$ find
```julia; hold=true; echo=false;
choices = [q"[4, 6]", q"[6, 8]", q"[11, 18]", q"[5, 10]"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
###### Question
@ -939,24 +923,24 @@ Express vector **c** in terms of **a** and **b**:
```julia; hold=true; echo=false;
choices = ["3a", "3b", "a + b", "a - b", "b-a"]
ans = 1
radioq(choices, ans)
answ = 1
radioq(choices, answ)
```
Express vector **d** in terms of **a** and **b**:
```julia; hold=true; echo=false;
choices = ["3a", "3b", "a + b", "a - b", "b-a"]
ans = 3
radioq(choices, ans)
answ = 3
radioq(choices, answ)
```
Express vector **e** in terms of **a** and **b**:
```julia; hold=true; echo=false;
choices = ["3a", "3b", "a + b", "a - b", "b-a"]
ans = 4
radioq(choices, ans)
answ = 4
radioq(choices, answ)
```
@ -966,8 +950,8 @@ If `xs=[1, 2, 3, 4]` and `f(x) = x^2` which of these will not produce the vector
```julia; hold=true; echo=false;
choices = [q"f.(xs)", q"map(f, xs)", q"[f(x) for x in xs]", "All three of them work"]
ans = 4
radioq(choices, ans, keep_order=true)
answ = 4
radioq(choices, answ, keep_order=true)
```
###### Question
@ -982,8 +966,8 @@ What construct will give the function values of $f$ at the zeros of $g$?
```julia;hold=true; echo=false;
choices = [q"sin(zs)", q"sin.(zs)", q"sin(.zs)", q".sin(zs)"]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```
###### Question
@ -997,6 +981,6 @@ q"sqrt.(zs)",
q"zs^(1/2)",
q"zs^(1./2)"
]
ans = 2
radioq(choices, ans, keep_order=true)
answ = 2
radioq(choices, answ, keep_order=true)
```

3
quarto/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/.quarto/
/_site/
/_book/

10
quarto/ODEs/Project.toml Normal file
View File

@ -0,0 +1,10 @@
[deps]
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca"
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6"

View File

@ -0,0 +1,458 @@
# The `DifferentialEquations` suite
```{julia}
#| echo: false
import Logging
Logging.disable_logging(Logging.Info) # or e.g. Logging.Info
Logging.disable_logging(Logging.Warn)
import SymPy
function Base.show(io::IO, ::MIME"text/html", x::T) where {T <: SymPy.SymbolicObject}
println(io, "<span class=\"math-left-align\" style=\"padding-left: 4px; width:0; float:left;\"> ")
println(io, "\\[")
println(io, sympy.latex(x))
println(io, "\\]")
println(io, "</span>")
end
# hack to work around issue
import Markdown
import CalculusWithJulia
function CalculusWithJulia.WeaveSupport.ImageFile(d::Symbol, f::AbstractString, caption; kwargs...)
nm = joinpath("..", string(d), f)
u = "![$caption]($nm)"
Markdown.parse(u)
end
nothing
```
This section uses these add-on packages:
```{julia}
using OrdinaryDiffEq
using Plots
using ModelingToolkit
```
```{julia}
#| echo: false
#| results: "hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
title = "The `DifferentialEquations` suite",
description = "Calculus with Julia: The `DifferentialEquations` suite",
tags = ["CalculusWithJulia", "odes", "the `differentialequations` suite"],
);
fig_size = (800, 600)
nothing
```
---
The [`DifferentialEquations`](https://github.com/SciML/DifferentialEquations.jl) suite of packages contains solvers for a wide range of various differential equations. This section just briefly touches touch on ordinary differential equations (ODEs), and so relies only on `OrdinaryDiffEq` part of the suite. For more detail on this type and many others covered by the suite of packages, there are many other resources, including the [documentation](https://diffeq.sciml.ai/stable/) and accompanying [tutorials](https://github.com/SciML/SciMLTutorials.jl).
## SIR Model
We follow along with an introduction to the SIR model for the spread of disease by [Smith and Moore](https://www.maa.org/press/periodicals/loci/joma/the-sir-model-for-spread-of-disease-introduction). This model received a workout due to the COVID-19 pandemic.
The basic model breaks a population into three cohorts: The **susceptible** individuals, the **infected** individuals, and the **recovered** individuals. These add to the population size, $N$, which is fixed, but the cohort sizes vary in time. We name these cohort sizes $S(t)$, $I(t)$, and $R(t)$ and define $s(t)=S(t)/N$, $i(t) = I(t)/N$ and $r(t) = R(t)/N$ to be the respective proportions.
The following *assumptions* are made about these cohorts by Smith and Moore:
> No one is added to the susceptible group, since we are ignoring births and immigration. The only way an individual leaves the susceptible group is by becoming infected.
This implies the rate of change in time of $S(t)$ depends on the current number of susceptibles, and the amount of interaction with the infected cohorts. The model *assumes* each infected person has $b$ contacts per day that are sufficient to spread the disease. Not all contacts will be with susceptible people, but if people are assumed to mix within the cohorts, then there will be on average $b \cdot S(t)/N$ contacts with susceptible people per infected person. As each infected person is modeled identically, the time rate of change of $S(t)$ is:
$$
\frac{dS}{dt} = - b \cdot \frac{S(t)}{N} \cdot I(t) = -b \cdot s(t) \cdot I(t)
$$
It is negative, as no one is added, only taken off. After dividing by $N$, this can also be expressed as $s'(t) = -b s(t) i(t)$.
> assume that a fixed fraction $k$ of the infected group will recover during any given day.
This means the change in time of the recovered depends on $k$ and the number infected, giving rise to the equation
$$
\frac{dR}{dt} = k \cdot I(t)
$$
which can also be expressed in proportions as $r'(t) = k \cdot i(t)$.
Finally, from $S(t) + I(T) + R(t) = N$ we have $S'(T) + I'(t) + R'(t) = 0$ or $s'(t) + i'(t) + r'(t) = 0$.
Combining, it is possible to express the rate of change of the infected population through:
$$
\frac{di}{dt} = b \cdot s(t) \cdot i(t) - k \cdot i(t)
$$
The author's apply this model to flu statistics from Hong Kong where:
$$
\begin{align*}
S(0) &= 7,900,000\\
I(0) &= 10\\
R(0) &= 0\\
\end{align*}
$$
In `Julia` we define these, `N` to model the total population, and `u0` to be the proportions.
```{julia}
S0, I0, R0 = 7_900_000, 10, 0
N = S0 + I0 + R0
u0 = [S0, I0, R0]/N # initial proportions
```
An *estimated* set of values for $k$ and $b$ are $k=1/3$, coming from the average period of infectiousness being estimated at three days and $b=1/2$, which seems low in normal times, but not for an infected person who may be feeling quite ill and staying at home. (The model for COVID would certainly have a larger $b$ value).
Okay, the mathematical modeling is done; now we try to solve for the unknown functions using `DifferentialEquations`.
To warm up, if $b=0$ then $i'(t) = -k \cdot i(t)$ describes the infected. (There is no circulation of people in this case.) The solution would be achieved through:
```{julia}
#| hold: true
k = 1/3
f(u,p,t) = -k * u # solving u(t) = - k u(t)
time_span = (0.0, 20.0)
prob = ODEProblem(f, I0/N, time_span)
sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8)
plot(sol)
```
The `sol` object is a set of numbers with a convenient `plot` method. As may have been expected, this graph shows exponential decay.
A few comments are in order. The problem we want to solve is
$$
\frac{di}{dt} = -k \cdot i(t) = F(i(t), k, t)
$$
where $F$ depends on the current value ($i$), a parameter ($k$), and the time ($t$). We did not utilize $p$ above for the parameter, as it was easy not to, but could have, and will in the following. The time variable $t$ does not appear by itself in our equation, so only `f(u, p, t) = -k * u` was used, `u` the generic name for a solution which in this case is $i$.
The problem we set up needs an initial value (the $u0$) and a time span to solve over. Here we want time to model real time, so use floating point values.
The plot shows steady decay, as there is no mixing of infected with others.
Adding in the interaction requires a bit more work. We now have what is known as a *system* of equations:
$$
\begin{align*}
\frac{ds}{dt} &= -b \cdot s(t) \cdot i(t)\\
\frac{di}{dt} &= b \cdot s(t) \cdot i(t) - k \cdot i(t)\\
\frac{dr}{dt} &= k \cdot i(t)\\
\end{align*}
$$
Systems of equations can be solved in a similar manner as a single ordinary differential equation, though adjustments are made to accommodate the multiple functions.
We use a style that updates values in place, and note that `u` now holds $3$ different functions at once:
```{julia}
function sir!(du, u, p, t)
k, b = p
s, i, r = u[1], u[2], u[3]
ds = -b * s * i
di = b * s * i - k * i
dr = k * i
du[1], du[2], du[3] = ds, di, dr
end
```
The notation `du` is suggestive of both the derivative and a small increment. The mathematical formulation follows the derivative, the numeric solution uses a time step and increments the solution over this time step. The `Tsit5()` solver, used here, adaptively chooses a time step, `dt`; were the `Euler` method used, this time step would need to be explicit.
:::{.callout-note}
## Mutation not re-binding
The `sir!` function has the trailing `!` indicating by convention it *mutates* its first value, `du`. In this case, through an assignment, as in `du[1]=ds`. This could use some explanation. The *binding* `du` refers to the *container* holding the $3$ values, whereas `du[1]` refers to the first value in that container. So `du[1]=ds` changes the first value, but not the *binding* of `du` to the container. That is, `du` mutates. This would be quite different were the call `du = [ds,di,dr]` which would create a new *binding* to a new container and not mutate the values in the original container.
:::
With the update function defined, the problem is setup and a solution found with in the same manner:
```{julia}
p = (k=1/3, b=1/2) # parameters
time_span = (0.0, 150.0) # time span to solve over, 5 months
prob = ODEProblem(sir!, u0, time_span, p)
sol = solve(prob, Tsit5())
plot(sol)
plot!(x -> 0.5, linewidth=2) # mark 50% line
```
The lower graph shows the number of infected at each day over the five-month period displayed. The peak is around 6-7% of the population at any one time. However, over time the recovered part of the population reaches over 50%, meaning more than half the population is modeled as getting sick.
Now we change the parameter $b$ and observe the difference. We passed in a value `p` holding our two parameters, so we just need to change that and run the model again:
```{julia}
#| hold: true
p = (k=1/2, b=2) # change b from 1/2 to 2 -- more daily contact
prob = ODEProblem(sir!, u0, time_span, p)
sol = solve(prob, Tsit5())
plot(sol)
```
The graphs are somewhat similar, but the steady state is reached much more quickly and nearly everyone became infected.
What about if $k$ were bigger?
```{julia}
#| hold: true
p = (k=2/3, b=1/2)
prob = ODEProblem(sir!, u0, time_span, p)
sol = solve(prob, Tsit5())
plot(sol)
```
The graphs show that under these conditions the infections never take off; we have $i' = (b\cdot s-k)i = k\cdot((b/k) s - 1) i$ which is always negative, since `(b/k)s < 1`, so infections will only decay.
The solution object is indexed by time, then has the `s`, `i`, `r` estimates. We use this structure below to return the estimated proportion of recovered individuals at the end of the time span.
```{julia}
function recovered(k,b)
prob = ODEProblem(sir!, u0, time_span, (k,b));
sol = solve(prob, Tsit5());
s,i,r = last(sol)
r
end
```
This function makes it easy to see the impact of changing the parameters. For example, fixing $k=1/3$ we have:
```{julia}
f(b) = recovered(1/3, b)
plot(f, 0, 2)
```
This very clearly shows the sharp dependence on the value of $b$; below some level, the proportion of people who are ever infected (the recovered cohort) remains near $0$; above that level it can climb quickly towards $1$.
The function `recovered` is of two variables returning a single value. In subsequent sections we will see a few $3$-dimensional plots that are common for such functions, here we skip ahead and show how to visualize multiple function plots at once using "`z`" values in a graph.
```{julia}
#| hold: true
k, ks = 0.1, 0.2:0.1:0.9 # first `k` and then the rest
bs = range(0, 2, length=100)
zs = recovered.(k, bs) # find values for fixed k, each of bs
p = plot(bs, k*one.(bs), zs, legend=false) # k*one.(ks) is [k,k,...,k]
for k in ks
plot!(p, bs, k*one.(bs), recovered.(k, bs))
end
p
```
The 3-dimensional graph with `plotly` can have its viewing angle adjusted with the mouse. When looking down on the $x-y$ plane, which code `b` and `k`, we can see the rapid growth along a line related to $b/k$.
Smith and Moore point out that $k$ is roughly the reciprocal of the number of days an individual is sick enough to infect others. This can be estimated during a breakout. However, they go on to note that there is no direct way to observe $b$, but there is an indirect way.
The ratio $c = b/k$ is the number of close contacts per day times the number of days infected which is the number of close contacts per infected individual.
This can be estimated from the curves once steady state has been reached (at the end of the pandemic).
$$
\frac{di}{ds} = \frac{di/dt}{ds/dt} = \frac{b \cdot s(t) \cdot i(t) - k \cdot i(t)}{-b \cdot s(t) \cdot i(t)} = -1 + \frac{1}{c \cdot s}
$$
This equation does not depend on $t$; $s$ is the dependent variable. It could be solved numerically, but in this case affords an algebraic solution: $i = -s + (1/c) \log(s) + q$, where $q$ is some constant. The quantity $q = i + s - (1/c) \log(s)$ does not depend on time, so is the same at time $t=0$ as it is as $t \rightarrow \infty$. At $t=0$ we have $s(0) \approx 1$ and $i(0) \approx 0$, whereas $t \rightarrow \infty$, $i(t) \rightarrow 0$ and $s(t)$ goes to the steady state value, which can be estimated. Solving with $t=0$, we see $q=0 + 1 - (1/c)\log(1) = 1$. In the limit them $1 = 0 + s_{\infty} - (1/c)\log(s_\infty)$ or $c = \log(s_\infty)/(1-s_\infty)$.
## Trajectory with drag
We now solve numerically the problem of a trajectory with a drag force from air resistance.
The general model is:
$$
\begin{align*}
x''(t) &= - W(t,x(t), x'(t), y(t), y'(t)) \cdot x'(t)\\
y''(t) &= -g - W(t,x(t), x'(t), y(t), y'(t)) \cdot y'(t)\\
\end{align*}
$$
with initial conditions: $x(0) = y(0) = 0$ and $x'(0) = v_0 \cos(\theta), y'(0) = v_0 \sin(\theta)$.
This into an ODE by a standard trick. Here we define our function for updating a step. As can be seen the vector `u` contains both $\langle x,y \rangle$ and $\langle x',y' \rangle$
```{julia}
function xy!(du, u, p, t)
g, γ = p.g, p.k
x, y = u[1], u[2]
x, y = u[3], u[4] # unicode \prime[tab]
W = γ
du[1] = x
du[2] = y
du[3] = 0 - W * x
du[4] = -g - W * y
end
```
This function $W$ is just a constant above, but can be easily modified as desired.
:::{.callout-note}
## A second-order ODE is a coupled first-order ODE
The "standard" trick is to take a second order ODE like $u''(t)=u$ and turn this into two coupled ODEs by using a new name: $v=u'(t)$ and then $v'(t) = u(t)$. In this application, there are $4$ equations, as we have *both* $x''$ and $y''$ being so converted. The first and second components of $du$ are new variables, the third and fourth show the original equation.
:::
The initial conditions are specified through:
```{julia}
θ = pi/4
v₀ = 200
xy₀ = [0.0, 0.0]
vxy₀ = v₀ * [cos(θ), sin(θ)]
INITIAL = vcat(xy₀, vxy₀)
```
The time span can be computed using an *upper* bound of no drag, for which the classic physics formulas give (when $y_0=0$) $(0, 2v_{y0}/g)$
```{julia}
g = 9.8
TSPAN = (0, 2*vxy₀[2] / g)
```
This allows us to define an `ODEProblem`:
```{julia}
trajectory_problem = ODEProblem(xy!, INITIAL, TSPAN)
```
When $\gamma = 0$ there should be no drag and we expect to see a parabola:
```{julia}
#| hold: true
ps = (g=9.8, k=0)
SOL = solve(trajectory_problem, Tsit5(); p = ps)
plot(t -> SOL(t)[1], t -> SOL(t)[2], TSPAN...; legend=false)
```
The plot is a parametric plot of the $x$ and $y$ parts of the solution over the time span. We can see the expected parabolic shape.
On a *windy* day, the value of $k$ would be positive. Repeating the above with $k=1/4$ gives:
```{julia}
#| hold: true
ps = (g=9.8, k=1/4)
SOL = solve(trajectory_problem, Tsit5(); p = ps)
plot(t -> SOL(t)[1], t -> SOL(t)[2], TSPAN...; legend=false)
```
We see that the $y$ values have gone negative. The `DifferentialEquations` package can adjust for that with a *callback* which terminates the problem once $y$ has gone negative. This can be implemented as follows:
```{julia}
#| hold: true
condition(u,t,integrator) = u[2] # called when `u[2]` is negative
affect!(integrator) = terminate!(integrator) # stop the process
cb = ContinuousCallback(condition, affect!)
ps = (g=9.8, k = 1/4)
SOL = solve(trajectory_problem, Tsit5(); p = ps, callback=cb)
plot(t -> SOL(t)[1], t -> SOL(t)[2], TSPAN...; legend=false)
```
Finally, we note that the `ModelingToolkit` package provides symbolic-numeric computing. This allows the equations to be set up symbolically, as in `SymPy` before being passed off to `DifferentialEquations` to solve numerically. The above example with no wind resistance could be translated into the following:
```{julia}
#| hold: true
@parameters t γ g
@variables x(t) y(t)
D = Differential(t)
eqs = [D(D(x)) ~ -γ * D(x),
D(D(y)) ~ -g - γ * D(y)]
@named sys = ODESystem(eqs)
sys = ode_order_lowering(sys) # turn 2nd order into 1st
u0 = [D(x) => vxy₀[1],
D(y) => vxy₀[2],
x => 0.0,
y => 0.0]
p = [γ => 0.0,
g => 9.8]
prob = ODEProblem(sys, u0, TSPAN, p, jac=true)
sol = solve(prob,Tsit5())
plot(t -> sol(t)[3], t -> sol(t)[4], TSPAN..., legend=false)
```
The toolkit will automatically generate fast functions and can perform transformations (such as is done by `ode_order_lowering`) before passing along to the numeric solves.

845
quarto/ODEs/euler.qmd Normal file
View File

@ -0,0 +1,845 @@
# Euler's method
```{julia}
#| echo: false
import Logging
Logging.disable_logging(Logging.Info) # or e.g. Logging.Info
Logging.disable_logging(Logging.Warn)
import SymPy
function Base.show(io::IO, ::MIME"text/html", x::T) where {T <: SymPy.SymbolicObject}
println(io, "<span class=\"math-left-align\" style=\"padding-left: 4px; width:0; float:left;\"> ")
println(io, "\\[")
println(io, sympy.latex(x))
println(io, "\\]")
println(io, "</span>")
end
# hack to work around issue
import Markdown
import CalculusWithJulia
function CalculusWithJulia.WeaveSupport.ImageFile(d::Symbol, f::AbstractString, caption; kwargs...)
nm = joinpath("..", string(d), f)
u = "![$caption]($nm)"
Markdown.parse(u)
end
nothing
```
This section uses these add-on packages:
```{julia}
using CalculusWithJulia
using Plots
using SymPy
using Roots
```
```{julia}
#| echo: false
#| results: "hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
title = "Euler's method",
description = "Calculus with Julia: Euler's method",
tags = ["CalculusWithJulia", "odes", "euler's method"],
);
fig_size = (800, 600)
nothing
```
---
The following section takes up the task of numerically approximating solutions to differential equations. `Julia` has a huge set of state-of-the-art tools for this task starting with the [DifferentialEquations](https://github.com/SciML/DifferentialEquations.jl) package. We don't use that package in this section, focusing on simpler methods and implementations for pedagogical purposes, but any further exploration should utilize the tools provided therein. A brief introduction to the package follows in an upcoming [section](./differential_equations.html).
---
Consider the differential equation:
$$
y'(x) = y(x) \cdot x, \quad y(1)=1,
$$
which can be solved with `SymPy`:
```{julia}
@syms x, y, u()
D = Differential(x)
x0, y0 = 1, 1
F(y,x) = y*x
dsolve(D(u)(x) - F(u(x), x))
```
With the given initial condition, the solution becomes:
```{julia}
out = dsolve(D(u)(x) - F(u(x),x), u(x), ics=Dict(u(x0) => y0))
```
Plotting this solution over the slope field
```{julia}
p = plot(legend=false)
vectorfieldplot!((x,y) -> [1, F(x,y)], xlims=(0, 2.5), ylims=(0, 10))
plot!(rhs(out), linewidth=5)
```
we see that the vectors that are drawn seem to be tangent to the graph of the solution. This is no coincidence, the tangent lines to integral curves are in the direction of the slope field.
What if the graph of the solution were not there, could we use this fact to *approximately* reconstruct the solution?
That is, if we stitched together pieces of the slope field, would we get a curve that was close to the actual answer?
```{julia}
#| hold: true
#| echo: false
#| cache: true
## {{{euler_graph}}}
function make_euler_graph(n)
x, y = symbols("x, y")
F(y,x) = y*x
x0, y0 = 1, 1
h = (2-1)/5
xs = zeros(n+1)
ys = zeros(n+1)
xs[1] = x0 # index is off by 1
ys[1] = y0
for i in 1:n
xs[i + 1] = xs[i] + h
ys[i + 1] = ys[i] + h * F(ys[i], xs[i])
end
p = plot(legend=false)
vectorfieldplot!((x,y) -> [1, F(y,x)], xlims=(1,2), ylims=(0,6))
## Add Euler soln
plot!(p, xs, ys, linewidth=5)
scatter!(p, xs, ys)
## add function
out = dsolve(u'(x) - F(u(x), x), u(x), ics=(u, x0, y0))
plot!(p, rhs(out), x0, xs[end], linewidth=5)
p
end
n = 5
anim = @animate for i=1:n
make_euler_graph(i)
end
imgfile = tempname() * ".gif"
gif(anim, imgfile, fps = 1)
caption = """
Illustration of a function stitching together slope field lines to
approximate the answer to an initial-value problem. The other function drawn is the actual solution.
"""
ImageFile(imgfile, caption)
```
The illustration suggests the answer is yes, let's see. The solution is drawn over $x$ values $1$ to $2$. Let's try piecing together $5$ pieces between $1$ and $2$ and see what we have.
The slope-field vectors are *scaled* versions of the vector `[1, F(y,x)]`. The `1` is the part in the direction of the $x$ axis, so here we would like that to be $0.2$ (which is $(2-1)/5$. So our vectors would be `0.2 * [1, F(y,x)]`. To allow for generality, we use `h` in place of the specific value $0.2$.
Then our first pieces would be the line connecting $(x_0,y_0)$ to
$$
\langle x_0, y_0 \rangle + h \cdot \langle 1, F(y_0, x_0) \rangle.
$$
The above uses vector notation to add the piece scaled by $h$ to the starting point. Rather than continue with that notation, we will use subscripts. Let $x_1$, $y_1$ be the postion of the tip of the vector. Then we have:
$$
x_1 = x_0 + h, \quad y_1 = y_0 + h F(y_0, x_0).
$$
With this notation, it is easy to see what comes next:
$$
x_2 = x_1 + h, \quad y_2 = y_1 + h F(y_1, x_1).
$$
We just shifted the indices forward by $1$. But graphically what is this? It takes the tip of the first part of our "stitched" together solution, finds the slope filed there (`[1, F(y,x)]`) and then uses this direction to stitch together one more piece.
Clearly, we can repeat. The $n$th piece will end at:
$$
x_{n+1} = x_n + h, \quad y_{n+1} = y_n + h F(y_n, x_n).
$$
For our example, we can do some numerics. We want $h=0.2$ and $5$ pieces, so values of $y$ at $x_0=1, x_1=1.2, x_2=1.4, x_3=1.6, x_4=1.8,$ and $x_5=2$.
Below we do this in a loop. We have to be a bit careful, as in `Julia` the vector of zeros we create to store our answers begins indexing at $1$, and not $0$.
```{julia}
n=5
h = (2-1)/n
xs = zeros(n+1)
ys = zeros(n+1)
xs[1] = x0 # index is off by 1
ys[1] = y0
for i in 1:n
xs[i + 1] = xs[i] + h
ys[i + 1] = ys[i] + h * F(ys[i], xs[i])
end
```
So how did we do? Let's look graphically:
```{julia}
plot(exp(-1/2)*exp(x^2/2), x0, 2)
plot!(xs, ys)
```
Not bad. We wouldn't expect this to be exact - due to the concavity of the solution, each step is an underestimate. However, we see it is an okay approximation and would likely be better with a smaller $h$. A topic we pursue in just a bit.
Rather than type in the above command each time, we wrap it all up in a function. The inputs are $n$, $a=x_0$, $b=x_n$, $y_0$, and, most importantly, $F$. The output is massaged into a function through a call to `linterp`, rather than two vectors. The `linterp` function we define below just finds a function that linearly interpolates between the points and is `NaN` outside of the range of the $x$ values:
```{julia}
function linterp(xs, ys)
function(x)
((x < xs[1]) || (x > xs[end])) && return NaN
for i in 1:(length(xs) - 1)
if xs[i] <= x < xs[i+1]
l = (x-xs[i]) / (xs[i+1] - xs[i])
return (1-l) * ys[i] + l * ys[i+1]
end
end
ys[end]
end
end
```
With that, here is our function to find an approximate solution to $y'=F(y,x)$ with initial condition:
```{julia}
function euler(F, x0, xn, y0, n)
h = (xn - x0)/n
xs = zeros(n+1)
ys = zeros(n+1)
xs[1] = x0
ys[1] = y0
for i in 1:n
xs[i + 1] = xs[i] + h
ys[i + 1] = ys[i] + h * F(ys[i], xs[i])
end
linterp(xs, ys)
end
```
With `euler`, it becomes easy to explore different values.
For example, we thought the solution would look better with a smaller $h$ (or larger $n$). Instead of $n=5$, let's try $n=50$:
```{julia}
u₁₂ = euler(F, 1, 2, 1, 50)
plot(exp(-1/2)*exp(x^2/2), x0, 2)
plot!(u₁₂, x0, 2)
```
It is more work for the computer, but not for us, and clearly a much better approximation to the actual answer is found.
## The Euler method
```{julia}
#| hold: true
#| echo: false
imgfile ="figures/euler.png"
caption = """
Figure from first publication of Euler's method. From [Gander and Wanner](http://www.unige.ch/~gander/Preprints/Ritz.pdf).
"""
ImageFile(:ODEs, imgfile, caption)
```
The name of our function reflects the [mathematician](https://en.wikipedia.org/wiki/Leonhard_Euler) associated with the iteration:
$$
x_{n+1} = x_n + h, \quad y_{n+1} = y_n + h \cdot F(y_n, x_n),
$$
to approximate a solution to the first-order, ordinary differential equation with initial values: $y'(x) = F(y,x)$.
[The Euler method](https://en.wikipedia.org/wiki/Euler_method) uses linearization. Each "step" is just an approximation of the function value $y(x_{n+1})$ with the value from the tangent line tangent to the point $(x_n, y_n)$.
Each step introduces an error. The error in one step is known as the *local truncation error* and can be shown to be about equal to $1/2 \cdot h^2 \cdot f''(x_{n})$ assuming $y$ has $3$ or more derivatives.
The total error, or more commonly, *global truncation error*, is the error between the actual answer and the approximate answer at the end of the process. It reflects an accumulation of these local errors. This error is *bounded* by a constant times $h$. Since it gets smaller as $h$ gets smaller in direct proportion, the Euler method is called *first order*.
Other, somewhat more complicated, methods have global truncation errors that involve higher powers of $h$ - that is for the same size $h$, the error is smaller. In analogy is the fact that Riemann sums have error that depends on $h$, whereas other methods of approximating the integral have smaller errors. For example, Simpson's rule had error related to $h^4$. So, the Euler method may not be employed if there is concern about total resources (time, computer, ...), it is important for theoretical purposes in a manner similar to the role of the Riemann integral.
In the examples, we will see that for many problems the simple Euler method is satisfactory, but not always so. The task of numerically solving differential equations is not a one-size-fits-all one. In the following, a few different modifications are presented to the basic Euler method, but this just scratches the surface of the topic.
#### Examples
##### Example
Consider the initial value problem $y'(x) = x + y(x)$ with initial condition $y(0)=1$. This problem can be solved exactly. Here we approximate over $[0,2]$ using Euler's method.
```{julia}
𝑭(y,x) = x + y
𝒙0, 𝒙n, 𝒚0 = 0, 2, 1
𝒇 = euler(𝑭, 𝒙0, 𝒙n, 𝒚0, 25)
𝒇(𝒙n)
```
We graphically compare our approximate answer with the exact one:
```{julia}
plot(𝒇, 𝒙0, 𝒙n)
𝒐ut = dsolve(D(u)(x) - 𝑭(u(x),x), u(x), ics = Dict(u(𝒙0) => 𝒚0))
plot(rhs(𝒐ut), 𝒙0, 𝒙n)
plot!(𝒇, 𝒙0, 𝒙n)
```
From the graph it appears our value for `f(xn)` will underestimate the actual value of the solution slightly.
##### Example
The equation $y'(x) = \sin(x \cdot y)$ is not separable, so need not have an easy solution. The default method will fail. Looking at the available methods with `sympy.classify_ode(𝐞qn, u(x))` shows a power series method which can return a power series *approximation* (a Taylor polynomial). Let's look at comparing an approximate answer given by the Euler method to that one returned by `SymPy`.
First, the `SymPy` solution:
```{julia}
𝐅(y,x) = sin(x*y)
𝐞qn = D(u)(x) - 𝐅(u(x), x)
𝐨ut = dsolve(𝐞qn, hint="1st_power_series")
```
If we assume $y(0) = 1$, we can continue:
```{julia}
𝐨ut1 = dsolve(𝐞qn, u(x), ics=Dict(u(0) => 1), hint="1st_power_series")
```
The approximate value given by the Euler method is
```{julia}
𝐱0, 𝐱n, 𝐲0 = 0, 2, 1
plot(legend=false)
vectorfieldplot!((x,y) -> [1, 𝐅(y,x)], xlims=(𝐱0, 𝐱n), ylims=(0,5))
plot!(rhs(𝐨ut1).removeO(), linewidth=5)
𝐮 = euler(𝐅, 𝐱0, 𝐱n, 𝐲0, 10)
plot!(𝐮, linewidth=5)
```
We see that the answer found from using a polynomial series matches that of Euler's method for a bit, but as time evolves, the approximate solution given by Euler's method more closely tracks the slope field.
##### Example
The [Brachistochrone problem](http://www.unige.ch/~gander/Preprints/Ritz.pdf) was posed by Johann Bernoulli in 1696. It asked for the curve between two points for which an object will fall faster along that curve than any other. For an example, a bead sliding on a wire will take a certain amount of time to get from point $A$ to point $B$, the time depending on the shape of the wire. Which shape will take the least amount of time?
```{julia}
#| hold: true
#| echo: false
imgfile = "figures/bead-game.jpg"
caption = """
A child's bead game. What shape wire will produce the shortest time for a bed to slide from a top to the bottom?
"""
ImageFile(:ODEs, imgfile, caption)
```
Restrict our attention to the $x$-$y$ plane, and consider a path, between the point $(0,A)$ and $(B,0)$. Let $y(x)$ be the distance from $A$, so $y(0)=0$ and at the end $y$ will be $A$.
[Galileo](http://www-history.mcs.st-and.ac.uk/HistTopics/Brachistochrone.html) knew the straight line was not the curve, but incorrectly thought the answer was a part of a circle.
```{julia}
#| hold: true
#| echo: false
imgfile = "figures/galileo.gif"
caption = """
As early as 1638, Galileo showed that an object falling along `AC` and then `CB` will fall faster than one traveling along `AB`, where `C` is on the arc of a circle.
From the [History of Math Archive](http://www-history.mcs.st-and.ac.uk/HistTopics/Brachistochrone.html).
"""
ImageFile(:ODEs, imgfile, caption)
```
This simulation also suggests that a curved path is better than the shorter straight one:
```{julia}
#| hold: true
#| echo: false
#| cache: true
##{{{brach_graph}}}
function brach(f, x0, vx0, y0, vy0, dt, n)
m = 1
g = 9.8
axs = Float64[0]
ays = Float64[-g]
vxs = Float64[vx0]
vys = Float64[vy0]
xs = Float64[x0]
ys = Float64[y0]
for i in 1:n
x = xs[end]
vx = vxs[end]
ax = -f'(x) * (f''(x) * vx^2 + g) / (1 + f'(x)^2)
ay = f''(x) * vx^2 + f'(x) * ax
push!(axs, ax)
push!(ays, ay)
push!(vxs, vx + ax * dt)
push!(vys, vys[end] + ay * dt)
push!(xs, x + vxs[end] * dt)# + (1/2) * ax * dt^2)
push!(ys, ys[end] + vys[end] * dt)# + (1/2) * ay * dt^2)
end
[xs ys vxs vys axs ays]
end
fs = [x -> 1 - x,
x -> (x-1)^2,
x -> 1 - sqrt(1 - (x-1)^2),
x -> - (x-1)*(x+1),
x -> 3*(x-1)*(x-1/3)
]
MS = [brach(f, 1/100, 0, 1, 0, 1/100, 100) for f in fs]
function make_brach_graph(n)
p = plot(xlim=(0,1), ylim=(-1/3, 1), legend=false)
for (i,f) in enumerate(fs)
plot!(f, 0, 1)
U = MS[i]
x = min(1.0, U[n,1])
scatter!(p, [x], [f(x)])
end
p
end
n = 4
anim = @animate for i=[1,5,10,15,20,25,30,35,40,45,50,55,60]
make_brach_graph(i)
end
imgfile = tempname() * ".gif"
gif(anim, imgfile, fps = 1)
caption = """
The race is on. An illustration of beads falling along a path, as can be seen, some paths are faster than others. The fastest path would follow a cycloid. See [Bensky and Moelter](https://pdfs.semanticscholar.org/66c1/4d8da6f2f5f2b93faf4deb77aafc7febb43a.pdf) for details on simulating a bead on a wire.
"""
ImageFile(imgfile, caption)
```
Now, the natural question is which path is best? The solution can be [reduced](http://mathworld.wolfram.com/BrachistochroneProblem.html) to solving this equation for a positive $c$:
$$
1 + (y'(x))^2 = \frac{c}{y}, \quad c > 0.
$$
Reexpressing, this becomes:
$$
\frac{dy}{dx} = \sqrt{\frac{C-y}{y}}.
$$
This is a separable equation and can be solved, but even `SymPy` has trouble with this integral. However, the result has been known to be a piece of a cycloid since the insightful Jacob Bernoulli used an analogy from light bending to approach the problem. The answer is best described parametrically through:
$$
x(u) = c\cdot u - \frac{c}{2}\sin(2u), \quad y(u) = \frac{c}{2}( 1- \cos(2u)), \quad 0 \leq u \leq U.
$$
The values of $U$ and $c$ must satisfy $(x(U), y(U)) = (B, A)$.
Rather than pursue this, we will solve it numerically for a fixed value of $C$ over a fixed interval to see the shape.
The equation can be written in terms of $y'=F(y,x)$, where
$$
F(y,x) = \sqrt{\frac{c-y}{y}}.
$$
But as $y_0 = 0$, we immediately would have a problem with the first step, as there would be division by $0$.
This says that for the optimal solution, the bead picks up speed by first sliding straight down before heading off towards $B$. That's great for the physics, but runs roughshod over our Euler method, as the first step has an infinity.
For this, we can try the *backwards Euler* method which uses the slope at $(x_{n+1}, y_{n+1})$, rather than $(x_n, y_n)$. The update step becomes:
$$
y_{n+1} = y_n + h \cdot F(y_{n+1}, x_{n+1}).
$$
Seems innocuous, but the value we are trying to find, $y_{n+1}$, is now on both sides of the equation, so is only *implicitly* defined. In this code, we use the `find_zero` function from the `Roots` package. The caveat is, this function needs a good initial guess, and the one we use below need not be widely applicable.
```{julia}
function back_euler(F, x0, xn, y0, n)
h = (xn - x0)/n
xs = zeros(n+1)
ys = zeros(n+1)
xs[1] = x0
ys[1] = y0
for i in 1:n
xs[i + 1] = xs[i] + h
## solve y[i+1] = y[i] + h * F(y[i+1], x[i+1])
ys[i + 1] = find_zero(y -> ys[i] + h * F(y, xs[i + 1]) - y, ys[i]+h)
end
linterp(xs, ys)
end
```
We then have with $C=1$ over the interval $[0,1.2]$ the following:
```{julia}
𝐹(y, x; C=1) = sqrt(C/y - 1)
𝑥0, 𝑥n, 𝑦0 = 0, 1.2, 0
cyc = back_euler(𝐹, 𝑥0, 𝑥n, 𝑦0, 50)
plot(x -> 1 - cyc(x), 𝑥0, 𝑥n)
```
Remember, $y$ is the displacement from the top, so it is non-negative. Above we flipped the graph to make it look more like expectation. In general, the trajectory may actually dip below the ending point and come back up. The above won't see this, for as written $dy/dx \geq 0$, which need not be the case, as the defining equation is in terms of $(dy/dx)^2$, so the derivative could have any sign.
##### Example: stiff equations
The Euler method is *convergent*, in that as $h$ goes to $0$, the approximate solution will converge to the actual answer. However, this does not say that for a fixed size $h$, the approximate value will be good. For example, consider the differential equation $y'(x) = -5y$. This has solution $y(x)=y_0 e^{-5x}$. However, if we try the Euler method to get an answer over $[0,2]$ with $h=0.5$ we don't see this:
```{julia}
(y,x) = -5y
𝓍0, 𝓍n, 𝓎0 = 0, 2, 1
𝓊 = euler(, 𝓍0, 𝓍n, 𝓎0, 4) # n =4 => h = 2/4
vectorfieldplot((x,y) -> [1, (y,x)], xlims=(0, 2), ylims=(-5, 5))
plot!(x -> y0 * exp(-5x), 0, 2, linewidth=5)
plot!(𝓊, 0, 2, linewidth=5)
```
What we see is that the value of $h$ is too big to capture the decay scale of the solution. A smaller $h$, can do much better:
```{julia}
𝓊₁ = euler(, 𝓍0, 𝓍n, 𝓎0, 50) # n=50 => h = 2/50
plot(x -> y0 * exp(-5x), 0, 2)
plot!(𝓊₁, 0, 2)
```
This is an example of a [stiff equation](https://en.wikipedia.org/wiki/Stiff_equation). Such equations cause explicit methods like the Euler one problems, as small $h$s are needed to good results.
The implicit, backward Euler method does not have this issue, as we can see here:
```{julia}
𝓊₂ = back_euler(, 𝓍0, 𝓍n, 𝓎0, 4) # n =4 => h = 2/4
vectorfieldplot((x,y) -> [1, (y,x)], xlims=(0, 2), ylims=(-1, 1))
plot!(x -> y0 * exp(-5x), 0, 2, linewidth=5)
plot!(𝓊₂, 0, 2, linewidth=5)
```
##### Example: The pendulum
The differential equation describing the simple pendulum is
$$
\theta''(t) = - \frac{g}{l}\sin(\theta(t)).
$$
The typical approach to solving for $\theta(t)$ is to use the small-angle approximation that $\sin(x) \approx x$, and then the differential equation simplifies to: $\theta''(t) = -g/l \cdot \theta(t)$, which is easily solved.
Here we try to get an answer numerically. However, the problem, as stated, is not a first order equation due to the $\theta''(t)$ term. If we let $u(t) = \theta(t)$ and $v(t) = \theta'(t)$, then we get *two* coupled first order equations:
$$
v'(t) = -g/l \cdot \sin(u(t)), \quad u'(t) = v(t).
$$
We can try the Euler method here. A simple approach might be this iteration scheme:
$$
\begin{align*}
x_{n+1} &= x_n + h,\\
u_{n+1} &= u_n + h v_n,\\
v_{n+1} &= v_n - h \cdot g/l \cdot \sin(u_n).
\end{align*}
$$
Here we need *two* initial conditions: one for the initial value $u(t_0)$ and the initial value of $u'(t_0)$. We have seen if we start at an angle $a$ and release the bob from rest, so $u'(0)=0$ we get a sinusoidal answer to the linearized model. What happens here? We let $a=1$, $L=5$ and $g=9.8$:
We write a function to solve this starting from $(x_0, y_0)$ and ending at $x_n$:
```{julia}
function euler2(x0, xn, y0, yp0, n; g=9.8, l = 5)
xs, us, vs = zeros(n+1), zeros(n+1), zeros(n+1)
xs[1], us[1], vs[1] = x0, y0, yp0
h = (xn - x0)/n
for i = 1:n
xs[i+1] = xs[i] + h
us[i+1] = us[i] + h * vs[i]
vs[i+1] = vs[i] + h * (-g / l) * sin(us[i])
end
linterp(xs, us)
end
```
Let's take $a = \pi/4$ as the initial angle, then the approximate solution should be $\pi/4\cos(\sqrt{g/l}x)$ with period $T = 2\pi\sqrt{l/g}$. We try first to plot then over 4 periods:
```{julia}
𝗅, 𝗀 = 5, 9.8
𝖳 = 2pi * sqrt(𝗅/𝗀)
𝗑0, 𝗑n, 𝗒0, 𝗒p0 = 0, 4𝖳, pi/4, 0
plot(euler2(𝗑0, 𝗑n, 𝗒0, 𝗒p0, 20), 0, 4𝖳)
```
Something looks terribly amiss. The issue is the step size, $h$, is too large to capture the oscillations. There are basically only $5$ steps to capture a full up and down motion. Instead, we try to get $20$ steps per period so $n$ must be not $20$, but $4 \cdot 20 \cdot T \approx 360$. To this graph, we add the approximate one:
```{julia}
plot(euler2(𝗑0, 𝗑n, 𝗒0, 𝗒p0, 360), 0, 4𝖳)
plot!(x -> pi/4*cos(sqrt(𝗀/𝗅)*x), 0, 4𝖳)
```
Even now, we still see that something seems amiss, though the issue is not as dramatic as before. The oscillatory nature of the pendulum is seen, but in the Euler solution, the amplitude grows, which would necessarily mean energy is being put into the system. A familiar instance of a pendulum would be a child on a swing. Without pumping the legs - putting energy in the system - the height of the swing's arc will not grow. Though we now have oscillatory motion, this growth indicates the solution is still not quite right. The issue is likely due to each step mildly overcorrecting and resulting in an overall growth. One of the questions pursues this a bit further.
## Questions
##### Question
Use Euler's method with $n=5$ to approximate $u(1)$ where
$$
u'(x) = x - u(x), \quad u(0) = 1
$$
```{julia}
#| hold: true
#| echo: false
F(y,x) = x - y
x0, xn, y0 = 0, 1, 1
val = euler(F, x0, xn, y0, 5)(1)
numericq(val)
```
##### Question
Consider the equation
$$
y' = x \cdot \sin(y), \quad y(0) = 1.
$$
Use Euler's method with $n=50$ to find the value of $y(5)$.
```{julia}
#| hold: true
#| echo: false
F(y, x) = x * sin(y)
x0, xn, y0 = 0, 5, 1
n = 50
u = euler(F, x0, xn, y0, n)
numericq(u(xn))
```
##### Question
Consider the ordinary differential equation
$$
\frac{dy}{dx} = 1 - 2\frac{y}{x}, \quad y(1) = 0.
$$
Use Euler's method to solve for $y(2)$ when $n=50$.
```{julia}
#| hold: true
#| echo: false
F(y, x) = 1 - 2y/x
x0, xn, y0 = 1, 2, 0
n = 50
u = euler(F, x0, xn, y0, n)
numericq(u(xn))
```
##### Question
Consider the ordinary differential equation
$$
\frac{dy}{dx} = \frac{y \cdot \log(y)}{x}, \quad y(2) = e.
$$
Use Euler's method to solve for $y(3)$ when $n=25$.
```{julia}
#| hold: true
#| echo: false
F(y, x) = y*log(y)/x
x0, xn, y0 = 2, 3, exp(1)
n = 25
u = euler(F, x0, xn, y0, n)
numericq(u(xn))
```
##### Question
Consider the first-order non-linear ODE
$$
y' = y \cdot (1-2x), \quad y(0) = 1.
$$
Use Euler's method with $n=50$ to approximate the solution $y$ over $[0,2]$.
What is the value at $x=1/2$?
```{julia}
#| hold: true
#| echo: false
F(y, x) = y * (1-2x)
x0, xn, y0 = 0, 2, 1
n = 50
u = euler(F, x0, xn, y0, n)
numericq(u(1/2))
```
What is the value at $x=3/2$?
```{julia}
#| hold: true
#| echo: false
F(y, x) = y * (1-2x)
x0, xn, y0 = 0, 2, 1
n = 50
u = euler(F, x0, xn, y0, n)
numericq(u(3/2))
```
##### Question: The pendulum revisited.
The issue with the pendulum's solution growing in amplitude can be addressed using a modification to the Euler method attributed to [Cromer](http://astro.physics.ncsu.edu/urca/course_files/Lesson14/index.html). The fix is to replace the term `sin(us[i])` in the line `vs[i+1] = vs[i] + h * (-g / l) * sin(us[i])` of the `euler2` function with `sin(us[i+1])`, which uses the updated angular velocity in the $2$nd step in place of the value before the step.
Modify the `euler2` function to implement the Euler-Cromer method. What do you see?
```{julia}
#| hold: true
#| echo: false
choices = [
"The same as before - the amplitude grows",
"The solution is identical to that of the approximation found by linearization of the sine term",
"The solution has a constant amplitude, but its period is slightly *shorter* than that of the approximate solution found by linearization",
"The solution has a constant amplitude, but its period is slightly *longer* than that of the approximate solution found by linearization"]
answ = 4
radioq(choices, answ, keep_order=true)
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

1011
quarto/ODEs/odes.qmd Normal file

File diff suppressed because it is too large Load Diff

27
quarto/ODEs/process.jl Normal file
View File

@ -0,0 +1,27 @@
using WeavePynb
using Mustache
mmd(fname) = mmd_to_html(fname, BRAND_HREF="../toc.html", BRAND_NAME="Calculus with Julia")
## uncomment to generate just .md files
mmd(fname) = mmd_to_md(fname, BRAND_HREF="../toc.html", BRAND_NAME="Calculus with Julia")
fnames = [
"odes",
"euler"
]
function process_file(nm, twice=false)
include("$nm.jl")
mmd_to_md("$nm.mmd")
markdownToHTML("$nm.md")
twice && markdownToHTML("$nm.md")
end
process_files(twice=false) = [process_file(nm, twice) for nm in fnames]
"""
## TODO ODEs
"""

295
quarto/ODEs/solve.qmd Normal file
View File

@ -0,0 +1,295 @@
# The problem-algorithm-solve interface
```{julia}
#| echo: false
import Logging
Logging.disable_logging(Logging.Info) # or e.g. Logging.Info
Logging.disable_logging(Logging.Warn)
import SymPy
function Base.show(io::IO, ::MIME"text/html", x::T) where {T <: SymPy.SymbolicObject}
println(io, "<span class=\"math-left-align\" style=\"padding-left: 4px; width:0; float:left;\"> ")
println(io, "\\[")
println(io, sympy.latex(x))
println(io, "\\]")
println(io, "</span>")
end
# hack to work around issue
import Markdown
import CalculusWithJulia
function CalculusWithJulia.WeaveSupport.ImageFile(d::Symbol, f::AbstractString, caption; kwargs...)
nm = joinpath("..", string(d), f)
u = "![$caption]($nm)"
Markdown.parse(u)
end
nothing
```
This section uses these add-on packages:
```{julia}
using Plots
using MonteCarloMeasurements
```
```{julia}
#| echo: false
#| results: "hidden"
using CalculusWithJulia.WeaveSupport
const frontmatter = (
title = "The problem-algorithm-solve interface",
description = "Calculus with Julia: The problem-algorithm-solve interface",
tags = ["CalculusWithJulia", "odes", "the problem-algorithm-solve interface"],
);
fig_size = (800, 600)
nothing
```
---
The [DifferentialEquations.jl](https://github.com/SciML) package is an entry point to a suite of `Julia` packages for numerically solving differential equations in `Julia` and other languages. A common interface is implemented that flexibly adjusts to the many different problems and algorithms covered by this suite of packages. In this section, we review a very informative [post](https://discourse.julialang.org/t/function-depending-on-the-global-variable-inside-module/64322/10) by discourse user `@genkuroki` which very nicely demonstrates the usefulness of the problem-algorithm-solve approach used with `DifferentialEquations.jl`. We slightly modify the presentation below for our needs, but suggest a perusal of the original post.
##### Example: FreeFall
The motion of an object under a uniform gravitational field is of interest.
The parameters that govern the equation of motions are the gravitational constant, `g`; the initial height, `y0`; and the initial velocity, `v0`. The time span for which a solution is sought is `tspan`.
A problem consists of these parameters. Typical `Julia` usage would be to create a structure to hold the parameters, which may be done as follows:
```{julia}
struct Problem{G, Y0, V0, TS}
g::G
y0::Y0
v0::V0
tspan::TS
end
Problem(;g=9.80665, y0=0.0, v0=30.0, tspan=(0.0,8.0)) = Problem(g, y0, v0, tspan)
```
The above creates a type, `Problem`, *and* a default constructor with default values. (The original uses a more sophisticated setup that allows the two things above to be combined.)
Just calling `Problem()` will create a problem suitable for the earth, passing different values for `g` would be possible for other planets.
To solve differential equations there are many different possible algorithms. Here is the construction of two types to indicate two algorithms:
```{julia}
struct EulerMethod{T}
dt::T
end
EulerMethod(; dt=0.1) = EulerMethod(dt)
struct ExactFormula{T}
dt::T
end
ExactFormula(; dt=0.1) = ExactFormula(dt)
```
The above just specifies a type for dispatch - the directions indicating what code to use to solve the problem. As seen, each specifies a size for a time step with default of `0.1`.
A type for solutions is useful for different `show` methods or other methods. One can be created through:
```{julia}
struct Solution{Y, V, T, P<:Problem, A}
y::Y
v::V
t::T
prob::P
alg::A
end
```
The different algorithms then can be implemented as part of a generic `solve` function. Following the post we have:
```{julia}
solve(prob::Problem) = solve(prob, default_algorithm(prob))
default_algorithm(prob::Problem) = EulerMethod()
function solve(prob::Problem, alg::ExactFormula)
g, y0, v0, tspan = prob.g, prob.y0, prob.v0, prob.tspan
dt = alg.dt
t0, t1 = tspan
t = range(t0, t1 + dt/2; step = dt)
y(t) = y0 + v0*(t - t0) - g*(t - t0)^2/2
v(t) = v0 - g*(t - t0)
Solution(y.(t), v.(t), t, prob, alg)
end
function solve(prob::Problem, alg::EulerMethod)
g, y0, v0, tspan = prob.g, prob.y0, prob.v0, prob.tspan
dt = alg.dt
t0, t1 = tspan
t = range(t0, t1 + dt/2; step = dt)
n = length(t)
y = Vector{typeof(y0)}(undef, n)
v = Vector{typeof(v0)}(undef, n)
y[1] = y0
v[1] = v0
for i in 1:n-1
v[i+1] = v[i] - g*dt # F*h step of Euler
y[i+1] = y[i] + v[i]*dt # F*h step of Euler
end
Solution(y, v, t, prob, alg)
end
```
The post has a more elegant means to unpack the parameters from the structures, but for each of the above, the parameters are unpacked, and then the corresponding algorithm employed. As of version `v1.7` of `Julia`, the syntax `(;g,y0,v0,tspan) = prob` could also be employed.
The exact formulas, `y(t) = y0 + v0*(t - t0) - g*(t - t0)^2/2` and `v(t) = v0 - g*(t - t0)`, follow from well-known physics formulas. Each answer is wrapped in a `Solution` type so that the answers found can be easily extracted in a uniform manner.
For example, plots of each can be obtained through:
```{julia}
earth = Problem()
sol_euler = solve(earth)
sol_exact = solve(earth, ExactFormula())
plot(sol_euler.t, sol_euler.y;
label="Euler's method (dt = $(sol_euler.alg.dt))", ls=:auto)
plot!(sol_exact.t, sol_exact.y; label="exact solution", ls=:auto)
title!("On the Earth"; xlabel="t", legend=:bottomleft)
```
Following the post, since the time step `dt = 0.1` is not small enough, the error of the Euler method is rather large. Next we change the algorithm parameter, `dt`, to be smaller:
```{julia}
earth₂ = Problem()
sol_euler₂ = solve(earth₂, EulerMethod(dt = 0.01))
sol_exact₂ = solve(earth₂, ExactFormula())
plot(sol_euler₂.t, sol_euler₂.y;
label="Euler's method (dt = $(sol_euler₂.alg.dt))", ls=:auto)
plot!(sol_exact₂.t, sol_exact₂.y; label="exact solution", ls=:auto)
title!("On the Earth"; xlabel="t", legend=:bottomleft)
```
It is worth noting that only the first line is modified, and only the method requires modification.
Were the moon to be considered, the gravitational constant would need adjustment. This parameter is part of the problem, not the solution algorithm.
Such adjustments are made by passing different values to the `Problem` constructor:
```{julia}
moon = Problem(g = 1.62, tspan = (0.0, 40.0))
sol_eulerₘ = solve(moon)
sol_exactₘ = solve(moon, ExactFormula(dt = sol_euler.alg.dt))
plot(sol_eulerₘ.t, sol_eulerₘ.y;
label="Euler's method (dt = $(sol_eulerₘ.alg.dt))", ls=:auto)
plot!(sol_exactₘ.t, sol_exactₘ.y; label="exact solution", ls=:auto)
title!("On the Moon"; xlabel="t", legend=:bottomleft)
```
The code above also adjusts the time span in addition to the graviational constant. The algorithm for exact formula is set to use the `dt` value used in the `euler` formula, for easier comparison. Otherwise, outside of the labels, the patterns are the same. Only those things that need changing are changed, the rest comes from defaults.
The above shows the benefits of using a common interface. Next, the post illustrates how *other* authors could extend this code, simply by adding a *new* `solve` method. For example,
```{julia}
struct Symplectic2ndOrder{T}
dt::T
end
Symplectic2ndOrder(;dt=0.1) = Symplectic2ndOrder(dt)
function solve(prob::Problem, alg::Symplectic2ndOrder)
g, y0, v0, tspan = prob.g, prob.y0, prob.v0, prob.tspan
dt = alg.dt
t0, t1 = tspan
t = range(t0, t1 + dt/2; step = dt)
n = length(t)
y = Vector{typeof(y0)}(undef, n)
v = Vector{typeof(v0)}(undef, n)
y[1] = y0
v[1] = v0
for i in 1:n-1
ytmp = y[i] + v[i]*dt/2
v[i+1] = v[i] - g*dt
y[i+1] = ytmp + v[i+1]*dt/2
end
Solution(y, v, t, prob, alg)
end
```
Had the two prior methods been in a package, the other user could still extend the interface, as above, with just a slight standard modification.
The same approach works for this new type:
```{julia}
earth₃ = Problem()
sol_sympl₃ = solve(earth₃, Symplectic2ndOrder(dt = 2.0))
sol_exact₃ = solve(earth₃, ExactFormula())
plot(sol_sympl₃.t, sol_sympl₃.y; label="2nd order symplectic (dt = $(sol_sympl₃.alg.dt))", ls=:auto)
plot!(sol_exact₃.t, sol_exact₃.y; label="exact solution", ls=:auto)
title!("On the Earth"; xlabel="t", legend=:bottomleft)
```
Finally, the author of the post shows how the interface can compose with other packages in the `Julia` package ecosystem. This example uses the external package `MonteCarloMeasurements` which plots the behavior of the system for perturbations of the initial value:
```{julia}
earth₄ = Problem(y0 = 0.0 ± 0.0, v0 = 30.0 ± 1.0)
sol_euler₄ = solve(earth₄)
sol_sympl₄ = solve(earth₄, Symplectic2ndOrder(dt = 2.0))
sol_exact₄ = solve(earth₄, ExactFormula())
ylim = (-100, 60)
P = plot(sol_euler₄.t, sol_euler₄.y;
label="Euler's method (dt = $(sol_euler₄.alg.dt))", ls=:auto)
title!("On the Earth"; xlabel="t", legend=:bottomleft, ylim)
Q = plot(sol_sympl₄.t, sol_sympl₄.y;
label="2nd order symplectic (dt = $(sol_sympl₄.alg.dt))", ls=:auto)
title!("On the Earth"; xlabel="t", legend=:bottomleft, ylim)
R = plot(sol_exact₄.t, sol_exact₄.y; label="exact solution", ls=:auto)
title!("On the Earth"; xlabel="t", legend=:bottomleft, ylim)
plot(P, Q, R; size=(720, 600))
```
The only change was in the problem, `Problem(y0 = 0.0 ± 0.0, v0 = 30.0 ± 1.0)`, where a different number type is used which accounts for uncertainty. The rest follows the same pattern.
This example, shows the flexibility of the problem-algorithm-solver pattern while maintaining a consistent pattern for execution.

11
quarto/README.md Normal file
View File

@ -0,0 +1,11 @@
# CalculusWithJulia via quarto
To compile the pages through quarto
* author in `.jmd` files (to be run through pluto)
* run `julia make_qmd.jl` to convert to `.qmd` files
* compile with `quarto`
The files in subdirectories are generated, they should not be edited
The files in this main directory are quarto specific.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 76 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 48 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 78 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 76 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

Some files were not shown because too many files have changed in this diff Show More