many edits

This commit is contained in:
jverzani
2024-04-26 18:26:12 -04:00
parent 6e807edb46
commit 4f924557ad
45 changed files with 326 additions and 296 deletions

View File

@@ -179,8 +179,8 @@ Not much to do here if you are satisfied with a graph that only gives insight in
```{julia}
𝒇(x) = ( (x-1)*(x-3)^2 ) / (x * (x-2) )
plot(𝒇, -50, 50)
f(x) = ( (x-1)*(x-3)^2 ) / (x * (x-2) )
plot(f, -50, 50)
```
We can see the slant asymptote and hints of vertical asymptotes, but, we'd like to see more of the basic features of the graph.
@@ -193,9 +193,9 @@ To identify how wide a viewing window should be, for the rational function the a
```{julia}
𝒇cps = find_zeros(𝒇', -10, 10)
poss_ips = find_zero(𝒇'', (-10, 10))
extrema(union(𝒇cps, poss_ips))
cps = find_zeros(f', -10, 10)
poss_ips = find_zero(f'', (-10, 10))
extrema(union(cps, poss_ips))
```
So a range over $[-5,5]$ should display the key features including the slant asymptote.
@@ -205,7 +205,7 @@ Previously we used the `rangeclamp` function defined in `CalculusWithJulia` to a
```{julia}
plot(rangeclamp(𝒇), -5, 5)
plot(rangeclamp(f), -5, 5)
```
With this graphic, we can now clearly see in the graph the two zeros at $x=1$ and $x=3$, the vertical asymptotes at $x=0$ and $x=2$, and the slant asymptote.
@@ -219,7 +219,7 @@ Again, this sort of analysis can be systematized. The rational function type in
```{julia}
xᵣ = variable(RationalFunction)
plot(𝒇(xᵣ)) # f(x) of RationalFunction type
plot(f(xᵣ)) # f(x) of RationalFunction type
```
##### Example

View File

@@ -454,7 +454,7 @@ The notation - $\big|$ - on the right-hand side separates the tasks of finding t
* Euler used `D` for the operator `D(f)`. This was initially used by [Argobast](http://jeff560.tripod.com/calculus.html). The notation `D(f)(c)` would be needed to evaluate the derivative at a point.
* Newton used a "dot" above the variable, $\dot{x}(t)$, which is still widely used in physics to indicate a derivative in time. This inidicates take the derivative and then plug in $t$.
* Newton used a "dot" above the variable, $\dot{x}(t)$, which is still widely used in physics to indicate a derivative in time. This indicates first taking the derivative and then plugging in $t$.
* The notation $[expr]'(c)$ or $[expr]'\big|_{x=c}$would similarly mean, take the derivative of the expression and **then** evaluate at $c$.
@@ -493,8 +493,10 @@ We can rearrange $(k(x+h) - k(x))$ as follows:
$$
(a\cdot f(x+h) + b\cdot g(x+h)) - (a\cdot f(x) + b \cdot g(x)) =
a\cdot (f(x+h) - f(x)) + b \cdot (g(x+h) - g(x)).
\begin{align*}
(a\cdot f(x+h) + b\cdot g(x+h)) - (a\cdot f(x) + b \cdot g(x)) &=\\
\quada\cdot (f(x+h) - f(x)) + b \cdot (g(x+h) - g(x)). &
\end{align*}
$$
Dividing by $h$, we see that this becomes
@@ -645,8 +647,12 @@ Let's first treat the case of $3$ products:
$$
[u\cdot v\cdot w]' =[ u \cdot (vw)]' = u' (vw) + u [vw]' = u'(vw) + u[v' w + v w'] =
u' vw + u v' w + uvw'.
\begin{align*}
[u\cdot v\cdot w]' &=[ u \cdot (vw)]'\\
&= u' (vw) + u [vw]'\\
&= u'(vw) + u[v' w + v w'] \\
&=u' vw + u v' w + uvw'.
\end{align*}
$$
This pattern generalizes, clearly, to:

View File

@@ -180,8 +180,8 @@ Consider the function $f(x) = e^{-\lvert x\rvert} \cos(\pi x)$ over $[-3,3]$:
```{julia}
𝐟(x) = exp(-abs(x)) * cos(pi * x)
plotif(𝐟, 𝐟', -3, 3)
f(x) = exp(-abs(x)) * cos(pi * x)
plotif(f, f', -3, 3)
```
We can see the first derivative test in action: at the peaks and valleys the relative extrema the color changes. This is because $f'$ is changing sign as the function changes from increasing to decreasing or vice versa.
@@ -191,7 +191,7 @@ This function has a critical point at $0$, as can be seen. It corresponds to a p
```{julia}
find_zeros(𝐟', -3, 3)
find_zeros(f', -3, 3)
```
##### Example
@@ -204,17 +204,17 @@ We will do so numerically. For this task we first need to gather the critical po
```{julia}
𝒇(x) = sin(pi*x) * (x^3 - 4x^2 + 2)
𝒇cps = find_zeros(𝒇', -2, 2)
f(x) = sin(pi*x) * (x^3 - 4x^2 + 2)
cps = find_zeros(f', -2, 2)
```
We should be careful though, as `find_zeros` may miss zeros that are not simple or too close together. A critical point will correspond to a relative maximum if the function crosses the axis, so these can not be "pauses." As this is exactly the case we are screening for, we double check that all the critical points are accounted for by graphing the derivative:
```{julia}
plot(𝒇', -2, 2, legend=false)
plot(f', -2, 2, legend=false)
plot!(zero)
scatter!(𝒇cps, 0*𝒇cps)
scatter!(cps, 0*cps)
```
We see the six zeros as stored in `cps` and note that at each the function clearly crosses the $x$ axis.
@@ -234,7 +234,7 @@ We will apply the same approach, but need to get a handle on how large the value
```{julia}
g(x) = sqrt(abs(x^2 - 1))
gcps = find_zeros(g', -2, 2)
cps = find_zeros(g', -2, 2)
```
We see the three values $-1$, $0$, $1$ that correspond to the two zeros and the relative minimum of $x^2 - 1$. We could graph things, but instead we characterize these values using a sign chart. A piecewise continuous function can only change sign when it crosses $0$ or jumps over $0$. The derivative will be continuous, except possibly at the three values above, so is piecewise continuous.
@@ -244,7 +244,7 @@ A sign chart picks convenient values between crossing points to test if the func
```{julia}
pts = sort(union(-2, gcps, 2)) # this includes the endpoints (a, b) and the critical points
pts = sort(union(-2, cps, 2)) # this includes the endpoints (a, b) and the critical points
test_pts = pts[1:end-1] + diff(pts)/2 # midpoints of intervals between pts
[test_pts sign.(g'.(test_pts))]
```
@@ -512,14 +512,14 @@ Use the second derivative test to characterize the critical points of $j(x) = x^
```{julia}
j(x) = x^5 - 2x^4 + x^3
jcps = find_zeros(j', -3, 3)
cps = find_zeros(j', -3, 3)
```
We can check the sign of the second derivative for each critical point:
```{julia}
[jcps j''.(jcps)]
[cps j''.(cps)]
```
That $j''(0.6) < 0$ implies that at $0.6$, $j(x)$ will have a relative maximum. As $j''(1) > 0$, the second derivative test says at $x=1$ there will be a relative minimum. That $j''(0) = 0$ says that only that there **may** be a relative maximum or minimum at $x=0$, as the second derivative test does not speak to this situation. (This last check, requiring a function evaluation to be `0`, is susceptible to floating point errors, so isn't very robust as a general tool.)

View File

@@ -268,8 +268,8 @@ Setting $a=1$ we have the graph:
```{julia}
𝒂 = 1
G(x,y) = x^3 + y^3 - 3*𝒂*x*y
a = 1
G(x,y) = x^3 + y^3 - 3*a*x*y
implicit_plot(G)
```
@@ -573,15 +573,15 @@ To illustrate, we need specific values of $a$, $b$, and $L$:
```{julia}
𝐚, 𝐛, 𝐋 = 3, 3, 10 # L > sqrt{a^2 + b^2}
F₀(x, y) = F₀(x, y, 𝐚, 𝐛)
a, b, L = 3, 3, 10 # L > sqrt{a^2 + b^2}
F₀(x, y) = F₀(x, y, a, b)
```
Our values $(x,y)$ must satisfy $f(x,y) = L$. Let's graph:
```{julia}
implicit_plot((x,y) -> F₀(x,y) - 𝐋, xlims=(-5, 7), ylims=(-5, 7))
implicit_plot((x,y) -> F₀(x,y) - L, xlims=(-5, 7), ylims=(-5, 7))
```
The graph is an ellipse, though slightly tilted.

View File

@@ -229,7 +229,7 @@ Of course, we could have just relied on `limit`, which knows about L'Hospital's
```{julia}
limit(f(x)/g(x), x, a)
limit(f(x)/g(x), x => a)
```
## Idea behind L'Hospital's rule
@@ -272,13 +272,13 @@ function lhopitals_picture_graph(n)
plt
end
caption = L"""
Geometric interpretation of ``L=\lim_{x \rightarrow 0} x^2 / (\sqrt{1 +
x} - 1 - x^2)``. At ``0`` this limit is indeterminate of the form
caption = raw"""
Geometric interpretation of
``L=\lim_{x \rightarrow 0} x^2 / (\sqrt{1 + x} - 1 - x^2)``.
At ``0`` this limit is indeterminate of the form
``0/0``. The value for a fixed ``x`` can be seen as the slope of a secant
line of a parametric plot of the two functions, plotted as ``(g,
f)``. In this figure, the limiting "tangent" line has ``0`` slope,
line of a parametric plot of the two functions, plotted as
``(g, f)``. In this figure, the limiting "tangent" line has ``0`` slope,
corresponding to the limit ``L``. In general, L'Hospital's rule is
nothing more than a statement about slopes of tangent lines.
@@ -437,38 +437,38 @@ $$
\lim_{x \rightarrow 1} \frac{x\log(x)-(x-1)}{(x-1)\log(x)}
$$
In `SymPy` we have:
In `SymPy` we have (using italic variable names to avoid a problem with the earlier use of `f` as a function):
```{julia}
𝒇 = x*log(x) - (x-1)
𝒈 = (x-1)*log(x)
𝒇(1), 𝒈(1)
𝑓 = x * log(x) - (x-1)
𝑔 = (x-1) * log(x)
𝑓(1), 𝑔(1)
```
L'Hospital's rule applies to the form $0/0$, so we try:
```{julia}
𝒇 = diff(𝒇, x)
𝒈 = diff(𝒈, x)
𝒇(1), 𝒈(1)
𝑓 = diff(𝑓, x)
𝑔 = diff(𝑔, x)
𝑓(1), 𝑔(1)
```
Again, we get the indeterminate form $0/0$, so we try again with second derivatives:
```{julia}
𝒇 = diff(𝒇, x, x)
𝒈 = diff(𝒈, x, x)
𝒇(1), 𝒈(1)
𝑓 = diff(𝑓, x, x)
𝑔 = diff(𝑔, x, x)
𝑓(1), 𝑔(1)
```
From this we see the limit is $1/2$, as could have been done directly:
```{julia}
limit(𝒇/𝒈, x=>1)
limit(𝑓/𝑔, x=>1)
```
## The assumptions are necessary
@@ -524,7 +524,7 @@ This ratio has no limit, as it oscillates, as confirmed by `SymPy`:
```{julia}
limit(u(x)/v(x), x=> oo)
limit(u(x)/v(x), x => oo)
```
## Questions
@@ -645,8 +645,8 @@ What is $L$?
#| hold: true
#| echo: false
f(x) = (4x - sin(x))/x
L = float(N(limit(f, 0)))
numericq(L)
L = limit(f(x), x=>0)
numericq(float(L))
```
###### Question
@@ -666,8 +666,8 @@ What is $L$?
#| hold: true
#| echo: false
f(x) = (sqrt(1+x) - 1)/x
L = float(N(limit(f, 0)))
numericq(L)
L = limit(f(x), x => 0)
numericq(float(L))
```
###### Question
@@ -687,8 +687,8 @@ What is $L$?
#| hold: true
#| echo: false
f(x) = (x - sin(x))/x^3
L = float(N(limit(f, 0)))
numericq(L)
L = limit(f(x), x=>0)
numericq(float(L))
```
###### Question
@@ -708,8 +708,8 @@ What is $L$?
#| hold: true
#| echo: false
f(x) = (1 - x^2/2 - cos(x))/x^3
L = float(N(limit(f, 0)))
numericq(L)
L = limit(f(x), x=>0)
numericq(float(L))
```
###### Question
@@ -729,8 +729,8 @@ What is $L$?
#| hold: true
#| echo: false
f(x) = log(log(x))/log(x)
L = N(limit(f(x), x=> oo))
numericq(L)
L = limit(f(x), x=> oo)
numericq(float(L))
```
###### Question
@@ -750,8 +750,8 @@ What is $L$?
#| hold: true
#| echo: false
f(x) = 1/x - 1/sin(x)
L = float(N(limit(f, 0)))
numericq(L)
L = limit(f(x), x => 0)
numericq(float(L))
```
###### Question
@@ -770,8 +770,8 @@ What is $L$?
```{julia}
#| hold: true
#| echo: false
L = float(N(limit(log(x)/x, x=>oo)))
numericq(L)
L = limit(log(x)/x, x=>oo)
numericq(float(L))
```
###### Question

View File

@@ -355,6 +355,7 @@ There can be problems when the stopping criteria is `abs(b-a) <= 2eps(m))` and t
```{julia}
#| hold: true
#| error: true
fu(x) = -40*x*exp(-x)
chandrapatla(fu, -9, 1, λ3)
```

View File

@@ -403,8 +403,8 @@ A plot shows us roughly where the value lies:
#| hold: true
f(x) = exp(x)
g(x) = x^6
plot(f, 0, 25, label="f")
plot!(g, label="g")
plot(f, 0, 25; label="f")
plot!(g; label="g")
```
Clearly by $20$ the two paths diverge. We know exponentials eventually grow faster than powers, and this is seen in the graph.
@@ -858,8 +858,10 @@ The calculation that produces the quadratic convergence now becomes:
$$
x_{i+1} - \alpha = (x_i - \alpha) - \frac{1}{k}(x_i-\alpha - \frac{f''(\xi)}{2f'(x_i)}(x_i-\alpha)^2) =
\frac{k-1}{k} (x_i-\alpha) + \frac{f''(\xi)}{2kf'(x_i)}(x_i-\alpha)^2.
\begin{align*}
x_{i+1} - \alpha &= (x_i - \alpha) - \frac{1}{k}(x_i-\alpha - \frac{f''(\xi)}{2f'(x_i)}(x_i-\alpha)^2)
&= \frac{k-1}{k} (x_i-\alpha) + \frac{f''(\xi)}{2kf'(x_i)}(x_i-\alpha)^2.
\end{align*}
$$
As $k > 1$, the $(x_i - \alpha)$ term dominates, and we see the convergence is linear with $\lvert e_{i+1}\rvert \approx (k-1)/k \lvert e_i\rvert$.

View File

@@ -1475,8 +1475,10 @@ Numerically find the value of $a$ that minimizes the length of the line seqment
```{julia}
#| hold: true
#| echo: false
x(a) = -a - 1/(2a)
d(a) = (a-x(a))^2 + (a^2 - x(a)^2)^2
a = find_zero(d', 1)
numericq(a)
let
x(a) = -a - 1/(2a)
d(a) = (a-x(a))^2 + (a^2 - x(a)^2)^2
a = find_zero(d', 1)
numericq(a)
end
```

View File

@@ -34,7 +34,7 @@ The `Symbolics` package provides native symbolic manipulation abilities for `Jul
An expression is an unevaluated portion of code that for our purposes below contains other expressions, symbols, and numeric literals. They are held in the `Expr` type. A symbol, such as `:x`, is distinct from a string (e.g. `"x"`) and is useful to the programmer to distinguish between the contents a variable points to from the name of the variable. Symbols are fundamental to metaprogramming in `Julia`. An expression is a specification of some set of statements to execute. A numeric literal is just a number.
The three main functions from `TermInterface` we leverage are `istree`, `operation`, and `arguments`. The `operation` function returns the "outside" function of an expression. For example:
The three main functions from `TermInterface` we leverage are `isexpr`, `operation`, and `arguments`. The `operation` function returns the "outside" function of an expression. For example:
```{julia}
@@ -65,7 +65,7 @@ function arity(ex)
end
```
Differentiation must distinguish between expressions, variables, and numbers. Mathematically expressions have an "outer" function, whereas variables and numbers can be directly differentiated. The `istree` function in `TermInterface` returns `true` when passed an expression, and `false` when passed a symbol or numeric literal. The latter two may be distinguished by `isa(..., Symbol)`.
Differentiation must distinguish between expressions, variables, and numbers. Mathematically expressions have an "outer" function, whereas variables and numbers can be directly differentiated. The `isexpr` function in `TermInterface` returns `true` when passed an expression, and `false` when passed a symbol or numeric literal. The latter two may be distinguished by `isa(..., Symbol)`.
Here we create a function, `D`, that when it encounters an expression it *dispatches* to a specific method of `D` based on the outer operation and arity, otherwise if it encounters a symbol or a numeric literal it does the differentiation:
@@ -73,7 +73,7 @@ Here we create a function, `D`, that when it encounters an expression it *dispat
```{julia}
function D(ex, var=:x)
if istree(ex)
if isexpr(ex)
op, args = operation(ex), arguments(ex)
D(Val(op), arity(ex), args, var)
elseif isa(ex, Symbol) && ex == :x

View File

@@ -592,12 +592,12 @@ To see a plot, we have
```{julia}
𝒇(x) = sin(x)
𝒄, 𝒉, 𝒏 = 0, 1/4, 4
int_poly = newton_form(𝒇, [𝒄 + i*𝒉 for i in 0:𝒏])
tp = taylor_poly(𝒇, 𝒄, 𝒏)
𝒂, 𝒃 = -pi, pi
plot(𝒇, 𝒂, 𝒃; linewidth=5, label="f")
f(x) = sin(x)
c, h, n = 0, 1/4, 4
int_poly = newton_form(f, [c + i*h for i in 0:n])
tp = taylor_poly(f, c, n)
a, b = -pi, pi
plot(f, a, b; linewidth=5, label="f")
plot!(int_poly; color=:green, label="interpolating")
plot!(tp; color=:red, label="Taylor")
```
@@ -606,10 +606,10 @@ To get a better sense, we plot the residual differences here:
```{julia}
d1(x) = 𝒇(x) - int_poly(x)
d2(x) = 𝒇(x) - tp(x)
plot(d1, 𝒂, 𝒃; color=:blue, label="interpolating")
plot!(d2; color=:green, label="Taylor")
d1(x) = f(x) - int_poly(x)
d2(x) = f(x) - tp(x)
plot(d1, a, b; linecolor=:blue, label="interpolating")
plot!(d2; linecolor=:green, label="Taylor")
```
The graph should be $0$ at each of the points in `xs`, which we can verify in the graph above. Plotting over a wider region shows a common phenomenon that these polynomials approximate the function near the values, but quickly deviate away:
@@ -825,10 +825,10 @@ To try this out to compute $\log(5)$. We have $5 = 2^2(1+0.25)$, so $k=2$ and $m
```{julia}
k, m = 2, 0.25
𝒔 = m / (2+m)
pₗ = 2 * sum(𝒔^(2i)/(2i+1) for i in 1:8) # where the polynomial approximates the logarithm...
s = m / (2+m)
pₗ = 2 * sum(s^(2i)/(2i+1) for i in 1:8) # where the polynomial approximates the logarithm...
log(1 + m), m - 𝒔*(m-pₗ), log(1 + m) - ( m - 𝒔*(m-pₗ))
log(1 + m), m - s*(m-pₗ), log(1 + m) - ( m - s*(m-pₗ))
```
@@ -836,7 +836,7 @@ The two values differ by less than $10^{-16}$, as advertised. Re-assembling then
```{julia}
Δ = k * log(2) + (m - 𝒔*(m-pₗ)) - log(5)
Δ = k * log(2) + (m - s*(m-pₗ)) - log(5)
```
The actual code is different, as the Taylor polynomial isn't used. The Taylor polynomial is a great approximation near a point, but there might be better polynomial approximations for all values in an interval. In this case there is, and that polynomial is used in the production setting. This makes things a bit more efficient, but the basic idea remains - for a prescribed accuracy, a polynomial approximation can be found over a given interval, which can be cleverly utilized to solve for all applicable values.
@@ -1166,7 +1166,7 @@ Here is one way to get all the values bigger than 1:
ex = (1 - x + x^2)*exp(x)
Tn = series(ex, x, 0, 100).removeO()
ps = sympy.Poly(Tn, x).coeffs()
qs = numer.(ps)
qs = numerator.(ps)
qs[qs .> 1] |> Tuple # format better for output
```