lots of cleanup

This commit is contained in:
jverzani
2026-08-11 17:17:08 -04:00
parent ae461659e0
commit 253295ff6e
91 changed files with 18284 additions and 7872 deletions

View File

@@ -34,17 +34,21 @@ The rational numbers are simply ratios of integers, of the form $p/q$ for non-ze
We know that polynomials have nice behaviors due to the following facts:
* Behaviors at $-\infty$, $\infty$ are known just from the leading term.
* There are possible wiggles up and down, the exact behavior depends on intermediate terms, but there can be no more than $n-1$ wiggles.
* The number of real zeros is no more than $n$, the degree of the polynomial.
* Behaviors at $-\infty$, $\infty$ are known just from the leading term.
* There are possible wiggles up and down, the exact behavior depends on intermediate terms, but there can be no more than $n-1$ wiggles.
* The number of real zeros is no more than $n$, the degree of the polynomial.
Rational functions are not quite so nice:
* behavior at $-\infty$ and $\infty$ can be like a polynomial of any degree, including constants
* behaviour at any value x can blow up due to division by $0$ - rational functions, unlike polynomials, need not be always defined
* The function may or may not cross zero, even if the range includes every other point, as the graph of $f(x) =1/x$ will show.
* behavior at $-\infty$ and $\infty$ can be like a polynomial of any degree, including constants
* behaviour at any value x can blow up due to division by $0$---rational functions, unlike polynomials, need not be always defined
* The function may or may not cross zero, even if the range includes every other point, as the graph of $f(x) =1/x$ illustrates.
Here, as with our discussion on polynomials, we are interested for now in just a few properties:
@@ -65,28 +69,34 @@ $$
f(x) = \frac{(x-1)^2 \cdot (x-2)}{(x+3) \cdot (x-3)}.
$$
::: {#fig-plot-rational-f-over-minus10-10-bad-choice}
```{julia}
f(x) = (x-1)^2 * (x-2) / ((x+3)*(x-3) )
plot(f, -10, 10)
```
We would be hard pressed to answer any of the three questions above from the graph, though, on inspection, we might think the strange spikes have something to do with $x$ values where $q(x)=0$.
Basic plot of the rational function $f(x)$ over $[-10,10]$. As no extra effort was made to adjust the $y$-viewing window, the graphic is not to useful for identifying basic properties of the function.
:::
We would be hard pressed to answer any of the three questions above from the @fig-plot-rational-f-over-minus10-10-bad-choice, though, on inspection, we might think the strange spikes have something to do with $x$ values where $q(x)=0$.
The question of big or small $x$ is not answered well with this graph, as the spikes dominate the scale of the $y$-axis. Setting a much larger viewing window illuminates this question:
::: {#fig-plot-rational-f-over-minus100-100-can-see-slant-asymptote}
```{julia}
plot(f, -100, 100)
```
Plot of rational function $f(x)$ over $[-100, 100]$ allowing the slant asymptote to be identified
:::
We can see from this, that the function eventually looks like a slanted straight line. The *eventual* shape of the graph is something that can be determined just from the two leading terms.
The spikes haven't vanished completely. It is just that with only a few hundred points to make the graph, there aren't any values near enough to the problem to make a large spike. The spikes happen because the function has a *vertical asymptote* at these values. Though not quite right, it is reasonable to think of the graph being made by selecting a few hundred points in the specified domain, computing the corresponding $y$ values, plotting the pairs, and finally connecting the points with straight line segments. Near a vertical asymptote the function values can be arbitrarily large in absolute values, though at the vertical asymptote the function is undefined. This graph doesn't show such detail.
The spikes will be related to the points where $q(x) = 0$, though not necessarily all of them not all such points will produce a vertical asymptote.
The spikes will be related to the points where $q(x) = 0$, though not necessarily all of them.
Where the function crosses $0$ is very hard to tell from these two graphs. As well, other finer features, such as local peaks or valleys, when present, can be hard to identify as the $y$-scale is set to accommodate the asymptotes. Working around the asymptotes requires some extra effort. Strategies are discussed herein.
@@ -146,12 +156,14 @@ h = g(x) # a symbolic expression
apart(h)
```
This decomposition breaks the rational expression into two pieces: $x-4$ and $40/(3x+9) + 2/(3x-9)$. The first piece would have a graph that is the line with slope $1$ and $y$-intercept $4$. As $x$ goes to $\infty$, the second piece will clearly go towards $0,$ as this simple graph shows:
This decomposition breaks the rational expression into two pieces: $x-4$ and $40/(3x+9) + 2/(3x-9)$. The first piece would have a graph that is the line with slope $1$ and $y$-intercept $4$. As $x$ goes to $\infty$, the second piece will clearly go towards $0,$ as @fig-plot-aparth-minus-x-minus-4-over-10-100 shows.
::: {#fig-plot-aparth-minus-x-minus-4-over-10-100}
```{julia}
plot(apart(h) - (x - 4), 10, 100)
```
Plot of just remainder term of the rational function $g(x)$ after reduction showing the decay towards $0$ as $x$ gets large
:::
Similarly, a plot over $[-100, -10]$ would show decay towards $0$, though in that case from below. Combining these two facts then, it is now no surprise that the graph of the rational function $f(x)$ should approach a straight line, in this case $y=x-4$, as $x \rightarrow \pm \infty$.
@@ -176,16 +188,19 @@ $$
The terms $(1 - 4/x + 5/x^2 - 2/x^3)$ and $(1 - 9/x^2)$ go towards $1$ as $x \rightarrow \pm \infty$, as each term with $x$ goes towards $0$. So the dominant terms comes from the ratio of the leading terms, $x^3$ and $x^2$. This ratio is $x$, so their will be an asymptote around a line with slope $1$. (The fact that the asymptote is $y=x-4$ takes a bit more work, as a division step is needed.)
Just by looking at the ratio of the two leading terms, the behaviour as $x \rightarrow \pm \infty$ can be discerned. If this ratio is of:
Just by looking at the ratio of the two leading terms, the behaviour as $x \rightarrow \pm \infty$ can be discerned. If this ratio is of the form:
* the form $c x^m$ with $m > 1$ then the shape will follow the polynomial growth of the monomial $c x^m$.
* the form $c x^m$ with $m=1$ then there will be a line with slope $c$ as a *slant asymptote*.
* the form $cx^0$ with $m=0$ (or just $c$) then there will be a *horizontal asymptote* $y=c$.
* the form $c/x^{m}$ with $m > 0$ then there will be a horizontal asymptote $y=0$, or the $y$ axis.
* $c x^m$ with $m > 1$ then the shape will follow the polynomial growth of the monomial $c x^m$;
* $c x^m$ with $m=1$ then there will be a line with slope $c$ as a *slant asymptote*;
* $cx^0$ with $m=0$ (or just $c$) then there will be a *horizontal asymptote* $y=c$;
* $c/x^{m}$ with $m > 0$ then there will be a horizontal asymptote $y=0$, or the $y$ axis.
To expand on the first points where the degree of the numerator is greater than that of the denominator, we have from the division algorithm that if $a(x)$ is the numerator and $b(x)$ the denominator, then $a(x)/b(x) = q(x) + r(x)/b(x)$ where the degree of $b(x)$ is greater than the degree of $r(x)$, so the right-most term will have a horizontal asymptote of $0$. This says that the graph will eventually approach the graph of $q(x)$, giving more detail than just saying it follows the shape of the leading term of $q(x)$, at the expense of the work required to find $q(x)$.
To expand on the first point, where the degree of the numerator is greater than that of the denominator, we have from the division algorithm that if $a(x)$ is the numerator and $b(x)$ the denominator, then $a(x)/b(x) = q(x) + r(x)/b(x)$ where the degree of $b(x)$ is greater than the degree of $r(x)$, so the right-most term will have a horizontal asymptote of $0$. This says that the graph will eventually approach the graph of $q(x)$, giving more detail than just saying it follows the shape of the leading term of $q(x)$, at the expense of the work required to find $q(x)$.
### Examples
@@ -217,8 +232,7 @@ Then we can see that the ratio of the leading terms is $x^5 / (5x^4) = (1/5)x$.
```{julia}
#| hold: true
p = (x^5 - 2x^4 + 3x^3 - 4x^2 + 5) / (5x^4 + 4x^3 + 3x^2 + 2x + 1)
quo, rem = divrem(numerator(p), denominator(p)) # or apart(p)
quo
div(numerator(p), denominator(p)) # or apart(p)
```
---
@@ -240,23 +254,23 @@ bottom = x-1
quo, rem = divrem(top, bottom)
```
The graph has nothing in common with the graph of the quotient for small $x$
@fig-asymptote-matches-for-large-x shows that for small $x$ ($\lvert x\rvert \approx 0$) the graph of the rational function and `quo` are not similar, but that they are when $x$ is larger.
::: {#fig-asymptote-matches-for-large-x}
```{julia}
plot(top/bottom, -3, 3)
plot!(quo, -3, 3)
#| echo: false
p1 = plot(top/bottom, -3, 3; title="small x", label="p/q")
plot!(quo, -3, 3; line=(3, :red), label="quo")
p2 = plot(top/bottom, 5, 10; title="larger x", label="p/q")
plot!(quo, 5, 10; label="quo")
plot(p1, p2)
```
But the graphs do match for large $x$:
```{julia}
plot(top/bottom, 5, 10)
plot!(quo, 5, 10)
```
---
The asymptotic nature is similar to the function for larger $x$ values.
:::
Finally, consider this rational expression in factored form:
@@ -272,7 +286,7 @@ By looking at the powers we can see that the leading term of the numerator will
#### Partial fractions
The `apart` function was useful to express a rational function in terms of a polynomial plus additional rational functions whose horizontal asymptotes are $0$. This function computes the partial fraction [decomposition](https://en.wikipedia.org/wiki/Partial_fraction_decomposition) of a rational function. Outside of the initial polynomial, this decomposition is a reexpression of a rational function into a sum of rational functions, where the denominators are *irreducible*, or unable to be further factored (non-trivially) and the numerators have lower degree than the denominator. Hence the horizontal asymptotes of $0$.
The `apart` function is used to express a rational function in terms of a polynomial plus additional rational functions whose horizontal asymptotes are $0$. This function computes the partial fraction [decomposition](https://en.wikipedia.org/wiki/Partial_fraction_decomposition) of a rational function. Outside of the initial polynomial, this decomposition is a reexpression of a rational function into a sum of rational functions, where the denominators are *irreducible*, or unable to be factored further over the set of rational numbers and the numerators have lower degree than the denominator. Hence the horizontal asymptotes of $0$.
To see another example we have:
@@ -291,28 +305,35 @@ The denominator, $q$, has factors $x-3$ and $x^2 - x - 1$, each irreducible. The
### Vertical asymptotes
As just discussed, the graph of $1/x$ will have a horizontal asymptote. However it will also show a spike at $0$:
As just discussed, the graph of $1/x$ will have a horizontal asymptote. However its graph (@fig-plot-1-over-x-over-minus1-1-showing-vertical-asymptote) also shows a spike at $0$.
::: {#fig-plot-1-over-x-over-minus1-1-showing-vertical-asymptote}
```{julia}
plot(1/x, -1, 1)
```
Plot of $f(x) = 1/x$ over $[-1,1]$. The vertical asymptote at $0$ dominates the display, preventing other features to be identified.
:::
Again, this spike is an artifact of the plotting algorithm. The $y$ values for $x$-values just smaller than $0$ are large negative values and the $x$ values just larger than $0$ produce large, positive $y$ values.
The two points with $x$ components closest to $0$ are connected with a line, though that is misleading. Here we deliberately use far fewer points to plot $1/x$ to show how this happens:
The two points with $x$ components closest to $0$ are connected with a line, though that is misleading. @fig-plot-of-1-over-x-few-points we deliberately use far fewer points to plot $1/x$ to show how this happens:
::: {#fig-plot-of-1-over-x-few-points}
```{julia}
#| hold: true
f(x) = 1/x
xs = range(-1, 1, length=12)
ys = f.(xs)
plot(xs, ys)
plot(xs, ys; legend=false)
scatter!(xs, ys)
```
Plot of $f(x) = 1/x$ with few points to illustrate how "spikes" can be artifacts of the plotting algorithm
:::
The line $x = 0$ is a *vertical asymptote* for the graph of $1/x$. As $x$ values get close to $0$ from the right, the $y$ values go towards $\infty$ and as the $x$ values get close to $0$ on the left, the $y$ values go towards $-\infty$.
@@ -328,12 +349,12 @@ $$
where both $r(c)$ and $s(c)$ are non zero. Knowing $m$ and $n$ (the multiplicities of the root $c$) allows the following to be said:
* If $m < n$ then $x=c$ will be a vertical asymptote.
* If $m < n$ then $x=c$ will be a vertical asymptote.
* If $m \geq n$ then $x=c$ will not be vertical asymptote. (The value $c$ will be known as a removable singularity). In this case, the graph of $p(x)/q(x)$ and the graph of $(x-c)^{m-n}r(x)/s(x)$ will differ, though very slightly, as the latter will include a value for $x=c$, whereas $x=c$ is not in the domain of $p(x)/q(x)$.
* If $m \geq n$ then $x=c$ will not be vertical asymptote. (The value $c$ will be known as a removable singularity). In this case, the graph of $p(x)/q(x)$ and the graph of $(x-c)^{m-n}r(x)/s(x)$ will differ, though very slightly, as the latter will include a value for $x=c$, whereas $x=c$ is not in the domain of $p(x)/q(x)$.
Finding the multiplicity may or may not be hard, but there is a very kludgy quick check that is often correct. With `Julia`, if you have a rational function that has `f(c)` evaluate to `Inf` or `-Inf` then there will be a vertical asymptote. If the expression evaluates to `NaN`, more analysis is needed. (The value of `0/0` is `NaN`, where as `1/0` is `Inf`.)
Finding the multiplicity may or may not be hard, but there is a very kludgy quick check that is often correct. With `Julia`, if you have a rational function that has `f(c)` evaluate to `Inf` or `-Inf` then there will be a vertical asymptote. If the expression evaluates to `NaN`, more analysis is needed. (The value of `0/0` is `NaN`, whereas `1/0` is `Inf`.)
For example, the function $f(x) = ((x-1)^2 \cdot (x-2)) / ((x+3) \cdot(x-3))$ has vertical asymptotes at $-3$ and $3$, as its graph illustrated. Without the graph we could see this as well:
@@ -353,45 +374,62 @@ As seen in several graphs, the basic plotting algorithm does a poor job with ver
Consider again the function $f(x) = ((x-1)^2 \cdot (x-2)) / ((x+3) \cdot(x-3))$. Without much work, we can see that $x=3$ and $x=-3$ will be vertical asymptotes and there will be a slant asymptote with slope $1$. How to graph this?
::: {#fig-rational-function-avoiding-spikes}
```{julia}
#| echo: false
f(x) = (x-1)^2 * (x-2) / ((x+3)*(x-3) )
p1 = plot(f, -5, 5; legend=false,
title="no effort", xlabel="(a)")
p2 = plot(f, -2.9, 2.9; legend=false,
title = "restrict domain", xlabel="(b)")
p3 = plot(f, -20, 20; ylims=(-20, 20),
legend=false,
title ="set ylims", xlabel="(c)")
p4 = plot(rangeclamp(f, 30), -20, 20; legend=false,
title="rangeclamp", xlabel="(d)")
We can avoid the vertical asymptotes in our viewing window. For example we could look at the area between the vertical asymptotes, by plotting over $(-2.9, 2.9)$, say:
plot(p1, p2, p3, p4; layout = 4)
```
Four ways to plot the rational function $f(x)$: (a) has no effort, (b) restricts the plot domain, (c) uses `ylims` to restrict the viewing window, (d) calls `rangeclamp` to break lines when there are larger values.
:::
@fig-rational-function-avoiding-spikes shows four graphics, produced along the lines of:
```{julia}
#| eval: false
f(x) = (x-1)^2 * (x-2) / ((x+3)*(x-3))
plot(f, -5, 5)
```
This no effort approach shows the reason extra effort should be taken. This extra effort can come in terms of limiting the $x$ viewing window by backing off from the boundaries $(-3, 3)$:
```{julia}
f(x) = (x-1)^2 * (x-2) / ((x+3)*(x-3) )
#| eval: false
plot(f, -2.9, 2.9)
```
This backs off by $\delta = 0.1$. As we have that $3 - 2.9$ is $\delta$ and $1/\delta$ is 10, the $y$ axis won't get too large, and indeed it doesn't.
This graph doesn't show well the two zeros at $x=1$ and $x=2$, for that a narrower viewing window is needed. By successively panning throughout the interesting part of the graph, we can get a view of the function.
We can also clip the `y` axis. The `plot` function can be passed an argument `ylims=(lo, hi)` to limit which values are plotted. With this, we can have:
Extra effort can come by limiting the $y$ viewing window through `ylims`:
```{julia}
#| hold: true
plot(f, -5, 5, ylims=(-20, 20))
#| eval: false
plot(f, -20, 20, ylims=(-20, 20))
```
This isn't ideal, as the large values are still computed, just the viewing window is clipped. This leaves the vertical asymptotes still effecting the graph.
There is another way, we could ask `Julia` to not plot $y$ values that get too large. This is not a big request. If instead of the value of `f(x)` - when it is large - we use `NaN` instead, then the connect-the-dots algorithm will skip those values.
This was discussed in an earlier section where the `rangeclamp` function was introduced to replace large values of `f(x)` (in absolute values) with `NaN`.
Finally, we show the use of `rangeclamp` from the `CalculusWithJulia` package which replaces the plotted values with `NaN` when they are large (in absolute value). This breaks the lines.
```{julia}
plot(rangeclamp(f, 30), -25, 25) # rangeclamp is in the CalculusWithJulia package
#| eval: false
plot(rangeclamp(f, 30), -20, 20)
```
We can see the general shape of $3$ curves broken up by the vertical asymptotes. The two on the side heading off towards the line $x-4$ and the one in the middle. We still can't see the precise location of the zeros, but that wouldn't be the case with most graphs that show asymptotic behaviors. However, we can clearly tell where to "zoom in" were those of interest.
### Sign charts
@@ -410,7 +448,7 @@ The usual recipe for construction follows these steps:
* Identify "test points" within each implied interval (these are $(-\infty, -1)$, $(-1,0)$, $(0,1)$, and $(1, \infty)$ in the example) and check for the sign of $f(x)$ at these test points. Write in `-`, `+`, `0`, or `*`, as appropriate. The value comes from the fact that "continuous" functions may only change sign when they cross $0$ or are undefined.
With the computer, where it is convenient to draw a graph, it might be better to emphasize the sign on the graph of the function, but at times numeric values are preferred. The `sign_chart` function from `CalculusWithJulia` does this analysis by numerically identifying points where the function is $0$ or $\infty$ and indicating the sign as $x$ crosses over these points.
With the computer, where it is convenient to draw a graph, it might be better to emphasize the sign on the graph of the function, but at times numeric values are preferred. The `sign_chart` function from `CalculusWithJulia` does this analysis by numerically identifying points where the function is $0$ or $\infty$ and indicating any sign change as $x$ crosses over these points.
```{julia}
@@ -419,7 +457,7 @@ f(x) = x^3 - x
sign_chart(f, -3/2, 3/2)
```
This format is a bit different from above, but shows to the left of $-1$ a minussign; between $-1$ and $0$ a plus sign; between $0$ and $1$ a minus sign; and between $1$ and $3/2$ a plus sign.
This format is a bit different from above, but shows from $-3/2$ to the left of $-1$ a minus sign; between $-1$ and $0$ a plus sign; between $0$ and $1$ a minus sign; and between $1$ and $3/2$ a plus sign.
## Pade approximate
@@ -441,20 +479,26 @@ $$
\tan(x) \approx \frac{x - 1/15 \cdot x^3}{1 - 2/5 \cdot x^2}
$$
We can look graphically at these approximations:
@fig-pade-approximations show these approximations through a graph.
::: {#fig-pade-approximations}
```{julia}
#| echo: false
sin_p(x) = (x - (7/60)*x^3) / (1 + (1/20)*x^2)
tan_p(x) = (x - (1/15)*x^3) / (1 - (2/5)*x^2)
plot(sin, -pi, pi)
plot!(sin_p, -pi, pi)
p1 = plot(sin, -pi, pi; label="sin")
plot!(p1, sin_p, -pi, pi; label="pade approx")
Δ = 0.1
p2 = plot(tan, -pi/2 + Δ, pi/2 - Δ; label="tan")
plot!(p2, tan_p, -pi/2 + Δ, pi/2 - Δ; label="pade approx")
plot(p1, p2)
```
```{julia}
plot(tan, -pi/2 + 0.2, pi/2 - 0.2)
plot!(tan_p, -pi/2 + 0.2, pi/2 - 0.2)
```
Small-degree Pade approximations for $\sin(x)$ and $\tan(x)$.
:::
## The `Polynomials` package for rational functions
@@ -530,26 +574,32 @@ One difference is the rational number `3//1` also represents other expressions,
Rational functions also have a plot recipe defined for them that attempts to ensure the basic features are identifiable. As previously discussed, a plot of a rational function can require some effort to avoid the values associated to vertical asymptotes taking up too many of the available vertical pixels in a graph.
For the polynomial `pq` above, we have from observation that $1$ and $2$ will be zeros and $x=3$ a vertical asymptote. We also can identify a slant asymptote with slope $1$. These are hinted at in this graph:
For the polynomial `pq` above, we have from observation that $1$ and $2$ will be zeros and $x=3$ a vertical asymptote. We also can identify a slant asymptote with slope $1$. These are hinted at in @fig-basic-plot-recipe-rational-function
::: {#fig-basic-plot-recipe-rational-function}
```{julia}
plot(pq)
```
Plot of rational function `pq` using the basic plot recipe. The vertical asymptote is clear, but the slant asymptote requires a trained eye.
:::
To better see the zeros, a plot over a narrower interval, say $[0,2.5]$, would be encouraged; to better see the slant asymptote, a plot over a wider interval, say $[-10,10]$, would be encouraged.
For one more example of the default plot recipe, we redo the graphing of the rational expression we earlier plotted with `rangeclamp`:
For one more example of the default plot recipe, we redo the graphing of the rational expression we earlier plotted with `rangeclamp` in @fig-plot-rational-function-with-asymptotes-at-minus3-3-from-pq-recipe.
::: {#fig-plot-rational-function-with-asymptotes-at-minus3-3-from-pq-recipe}
```{julia}
#| hold: true
p,q = fromroots([1,1,2]), fromroots([-3,3])
plot(p//q)
plot(p//q; legend=false)
```
A plot of a rational function with vertical asymptotes at $x= \pm 3$. The plot recipe avoids showing artifacts from the vertical asymptotes.
:::
##### Example: transformations of polynomials; real roots
##### Example: Transformations of polynomials; real roots
We have seen some basic transformations of functions such as shifts and scales. For a polynomial expression we can implement these as follows, taking advantage of polynomial evaluation:
@@ -633,7 +683,18 @@ numerator(lowest_terms( (x + 1)^d * pq((a*x + b)/(x + 1))))
Now, why is this of any interest?
Mobius transforms are used to map regions into other regions. In this special case, the transform $\phi(x) = (ax + b)/(x + 1)$ takes the interval $[0,\infty]$ and sends it to $[a,b]$ ($0$ goes to $(a\cdot 0 + b)/(0+1) = b$, whereas $\infty$ goes to $ax/x \rightarrow a$). Using this, if $p(u) = 0$, with $q(x) = (x+1)^d p(\phi(x))$, then setting $u = \phi(x)$ we have $q(x) = (\phi^{-1}(u)+1)^d p(\phi(\phi^{-1}(u))) = (\phi^{-1}(u)+1)^d \cdot p(u) = (\phi^{-1}(u)+1)^d \cdot 0 = 0$. That is, a zero of $p$ in $[a,b]$ will appear as a zero of $q$ in $[0,\infty)$ at $\phi^{-1}(u)$.
Mobius transforms are used to map regions into other regions. In this special case, the transform $\phi(x) = (ax + b)/(x + 1)$ takes the interval $[0,\infty]$ and sends it to $[a,b]$ ($0$ goes to $(a\cdot 0 + b)/(0+1) = b$, whereas $\infty$ goes to $ax/x \rightarrow a$). Using this, if $p(u) = 0$, with $q(x) = (x+1)^d p(\phi(x))$, then setting $u = \phi(x)$ we have
$$
\begin{align*}
q(x) &= (x+1)^d p(\phi(x))\\
&= (\phi^{-1}(u)+1)^d p(\phi(\phi^{-1}(u))) \\
& = (\phi^{-1}(u)+1)^d \cdot p(u) \\
& = (\phi^{-1}(u)+1)^d \cdot 0 = 0.\\
\end{align*}
$$
That is, a zero of $p$ in $[a,b]$ will appear as a zero of $q$ in $[0,\infty)$ at $x = \phi^{-1}(u)$.
The Descartes rule of signs applied to $q$ then will give a bound on the number of possible roots of $p$ in the interval $[a,b]$. In the example we did, the Mobius transform for $a=4, b=6$ is $15 - x - 11x^2 - 3x^3$ with $1$ sign change, so there must be exactly $1$ real root of $p=(x-1)(x-3)(x-5)$ in the interval $[4,6]$, as we can observe from the factored form of $p$.
@@ -653,12 +714,14 @@ This observation, along with a detailed analysis provided by [Kobel, Rouillier,
The basic algorithm, as presented next, is fairly simple to understand, and hints at the bisection algorithm to come. It is due to Akritas and Collins. Suppose you know the only possible positive real roots are between $0$ and $M$ *and* no roots are repeated. Find the transformed polynomial over $[0,M]$:
* If there are no sign changes, then there are no roots of $p$ in $[0,M]$.
* If there is one sign change, then there is a single root of $p$ in $[0,M]$. The interval $[0,M]$ is said to isolate the root (and the actual root can then be found by other means)
* If there is more than one sign change, divide the interval in two ($[0,M/2]$ and $[M/2,M]$, say) and apply the same consideration to each.
* If there are no sign changes, then there are no roots of $p$ in $[0,M]$.
* If there is one sign change, then there is a single root of $p$ in $[0,M]$. The interval $[0,M]$ is said to isolate the root (and the actual root can then be found by other means)
* If there is more than one sign change, divide the interval in two ($[0,M/2]$ and $[M/2,M]$, say) and apply the same consideration to each.
Eventually, **mathematically** this will find isolating intervals for each positive real root. (The negative ones can be similarly isolated.)
Eventually, *mathematically* this will find isolating intervals for each positive real root. (The negative ones can be similarly isolated.)
Applying these steps to $p$ with an initial interval, say $[0,9]$, we would have:
@@ -686,7 +749,7 @@ The `ANewDsc` function takes a collection of coefficients representing a polynom
```{julia}
p₀ = fromroots([1,3,5])
p₀ = fromroots([1, 3, 5])
st = ANewDsc(coeffs(p₀))
```
@@ -701,7 +764,7 @@ More challenging problems can be readily handled by this package. The following
```{julia}
s = Polynomial([0,1]) # also just variable(Polynomial{Int})
s = variable(:s)
u = -1 + 254*s - 16129*s^2 + s^15
```
@@ -719,6 +782,7 @@ and
refine_roots(st)
```
The `Hecke.jl` package has a `roots` function that handles the task of root isolation more performantly than `ANewDsc`.
The SymPy package (`sympy.real_roots`) can accurately identify the three roots but it can take a **very** long time. The `Polynomials.roots` function from the `Polynomials` package identifies the cluster as complex valued. Though the implementation in `RealPolynomialRoots` doesn't handle such large polynomials, the authors of the algorithm have implementations that can quickly solve polynomials with degrees as high as $10,000$.
@@ -737,8 +801,9 @@ 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$"]
answ = 3
radioq(choices, answ)
answer = 3
explanation = L"The ratio of the two leading terms is $x$"
buttonq(choices, answer; explanation)
```
###### Question
@@ -753,8 +818,9 @@ 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$"]
answ = 1
radioq(choices, answ)
answer = 1
explanation = L"The ratio of the two leading terms is $1/x$"
buttonq(choices, answer; explanation)
```
###### Question
@@ -769,8 +835,9 @@ 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$"]
answ = 2
radioq(choices, answ)
answer = 2
explanation = L"The ratio of the two leading terms can be seen to be $1$"
buttonq(choices, answer; explanation)
```
###### Question
@@ -792,8 +859,9 @@ would have
choices = [L"A horizontal asymptote $y=0$",
L"A horizontal asymptote $y=1$",
L"A slant asymptote with slope $m=1$"]
answ = 2
radioq(choices, answ)
answer = 2
explanation = L"the ratio of the leading terms is $1$"
buttonq(choices, answer; explanation)
```
###### Question
@@ -816,8 +884,9 @@ choices = [L"A vertical asymptote $x=1$",
L"A slant asymptote with slope $m=1$",
L"A vertical asymptote $x=5$"
]
answ = 3
radioq(choices, answ)
answer = 3
explanation = L"the ratio of the leading terms is $1$, not $x$ and there are vertical asymptotes at $x=4,5,6$"
buttonq(choices, answer; explanation)
```
###### Question
@@ -841,8 +910,9 @@ choices = [
"``y = (1/3)x``",
"``y = (1/3)x - (1/3)``"
]
answ = 3
radioq(choices, answ)
answer = 3
explanation = "Try `div(x^3 - 3x^2+ 2x, 3x^2 - 6x +2)`"
buttonq(choices, answer)
```
###### Question
@@ -871,8 +941,8 @@ Is the following common conception true: "The graph of a function never crosses
#| echo: false
choices = ["No, the graph clearly crosses the drawn asymptote",
"Yes, this is true"]
answ = 1
radioq(choices, answ)
answer = 1
buttonq(choices, answer)
```
(The wikipedia page indicates that the term "asymptote" was introduced by Apollonius of Perga in his work on conic sections, but in contrast to its modern meaning, he used it to mean any line that does not intersect the given curve. It can sometimes take a while to change perception.)
@@ -883,18 +953,17 @@ radioq(choices, answ)
Consider the two graphs of $f(x) = 1/x$ over $[10,20]$ and $[100, 200]$:
::: {#fig-plot-1-over-x-10-to-20-100-to-200}
```{julia}
#| hold: true
#| echo: false
plot(x -> 1/x, 10, 20)
p1 = plot(x -> 1/x, 10, 20)
p2 = plot(x -> 1/x, 100, 200)
plot(p1, p2)
```
```{julia}
#| hold: true
#| echo: false
plot(x -> 1/x, 100, 200)
```
The graph of $f(x) = 1/x$ over different viewing windows
:::
The two shapes are basically identical and do not look like straight lines. How does this reconcile with the fact that $f(x)=1/x$ has a horizontal asymptote $y=0$?
@@ -906,8 +975,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$."
]
answ = 2
radioq(choices, answ)
answer = 2
buttonq(choices, answer)
```
###### Question
@@ -955,8 +1024,8 @@ choices = ["between ``0`` and ``8`` hours",
"between ``8`` and ``16`` hours",
"between ``16`` and ``24`` hours",
"after one day"]
answ = 1
radioq(choices, answ)
answer = 1
buttonq(choices, answer)
```
This graph has
@@ -969,8 +1038,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}$"]
answ = 3
radioq(choices, answ)
answer = 3
buttonq(choices, answer)
```
###### Question
@@ -996,6 +1065,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$"]
answ = 2
radioq(choices, answ)
answer = 2
buttonq(choices, answer)
```