lots of cleanup
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
# Polynomials
|
||||
|
||||
|
||||
Now that basic properties of functions have been discussed, we move to various types of related functions beginning with polynomial functions.
|
||||
With the basic properties of functions have been discussed, we move to various types of related functions beginning with polynomial functions.
|
||||
|
||||
|
||||
{{< include ../_common_code.qmd >}}
|
||||
@@ -12,7 +11,7 @@ In this section we use the following add-on packages:
|
||||
```{julia}
|
||||
using SymPy
|
||||
using Plots
|
||||
plotly()
|
||||
plotly();
|
||||
```
|
||||
|
||||
```{julia}
|
||||
@@ -26,13 +25,13 @@ nothing
|
||||
|
||||
|
||||
|
||||
Polynomials are a particular class of expressions that are simple enough to have many properties that can be analyzed. In particular, the key concepts of calculus: limits, continuity, derivatives, and integrals are all relatively trivial for polynomial functions. However, polynomials are flexible enough that they can be used to approximate a wide variety of functions. Indeed, though we don't pursue this, we mention that `Julia`'s `ApproxFun` package exploits this to great advantage.
|
||||
Polynomials are a particular class of expressions that are simple enough to have many properties that can be analyzed. In particular, the key concepts of calculus: limits, continuity, derivatives, and integrals are all relatively straightforward for polynomial functions. However, polynomials are flexible enough that they can be used to approximate a wide variety of functions. Indeed, though we don't pursue this, we mention that `Julia`'s `ApproxFun` package exploits this to great advantage.
|
||||
|
||||
|
||||
Here we discuss some vocabulary and basic facts related to polynomials and show how the add-on `SymPy` package can be used to model polynomial expressions within `SymPy`. `SymPy` provides a Computer Algebra System (CAS) for `Julia`. In this case, by leveraging a mature `Python` package [SymPy](https://www.sympy.org/). Later we will discuss the `Polynomials` package for polynomials.
|
||||
Here we discuss some vocabulary and basic facts related to polynomials and show how the add-on `SymPy` package can be used to model polynomial expressions within `SymPy`. `SymPy` provides a Computer Algebra System (CAS) for `Julia`. In this case, by leveraging a mature `Python` package [SymPy](https://www.sympy.org/). In the next section we will discuss the `Polynomials` package for representing polynomials.
|
||||
|
||||
|
||||
For our purposes, a *monomial* is simply a non-negative integer power of $x$ (or some other indeterminate symbol) possibly multiplied by a scalar constant. For example, $5x^4$ is a monomial, as are constants, such as $-2$ (it being $-2x^0$) and the symbol $x$ itself (it begin $x^1$. In general, one may consider restrictions on where the constants can come from, and consider more than one symbol, but we won't pursue this here, restricting ourselves to the case of a single variable and real coefficients.
|
||||
For our purposes, a *monomial* is simply a non-negative integer power of $x$ (or some other indeterminate symbol) possibly multiplied by a scalar constant. For example, $5x^4$ is a monomial, as are constants, such as $-2$ (it being $-2x^0$) and the symbol $x$ itself (it being $x^1$). In general, one may consider restrictions on where the constants can come from, and consider more than one symbol, but we won't pursue this here, restricting ourselves to the case of a single variable and real coefficients.
|
||||
|
||||
|
||||
A *polynomial* is a sum of monomials. After combining terms with same powers, a non-zero polynomial may be written uniquely as:
|
||||
@@ -42,6 +41,9 @@ $$
|
||||
a_n x^n + a_{n-1}x^{n-1} + \cdots + a_1 x + a_0, \quad a_n \neq 0
|
||||
$$
|
||||
|
||||
The zero polynomial is just $0$.
|
||||
|
||||
::: {#fig-various-even-degree-monic-monomials}
|
||||
```{julia}
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
@@ -61,13 +63,16 @@ end
|
||||
|
||||
imgfile = tempname() * ".gif"
|
||||
gif(anim, imgfile, fps = 1)
|
||||
caption = "Polynomials of varying even degrees over ``[-1,1]``."
|
||||
caption = ""
|
||||
|
||||
plotly()
|
||||
ImageFile(imgfile, caption)
|
||||
```
|
||||
|
||||
The numbers $a_0, a_1, \dots, a_n$ are the **coefficients** of the polynomial in the standard basis. With the identifications that $x=x^1$ and $1 = x^0$, the monomials above have their power match their coefficient's index, e.g., $a_ix^i$. Outside of the coefficient $a_n$, the other coefficients may be negative, positive, *or* $0$. Except for the zero polynomial, the largest power $n$ is called the [degree](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). The degree of the [zero](http://tinyurl.com/he6eg6s) polynomial is typically not defined or defined to be $-1$, so as to make certain statements easier to express. The term $a_n$ is called the **leading coefficient**. When the leading coefficient is $1$, the polynomial is called a **monic polynomial**. The monomial $a_n x^n$ is the **leading term**.
|
||||
Polynomials of varying even degrees over $[-1,1]$
|
||||
:::
|
||||
|
||||
The numbers $a_0, a_1, \dots, a_n$ are the *coefficients* of the polynomial in the standard basis. With the identifications that $x=x^1$ and $1 = x^0$, the monomials above have their power match their coefficient's index, e.g., $a_ix^i$. Outside of the coefficient $a_n$, the other coefficients may be negative, positive, *or* $0$. Except for the zero polynomial, the largest power $n$ is called the [degree](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). The degree of the [zero](http://tinyurl.com/he6eg6s) polynomial is typically not defined or defined to be $-1$, so as to make certain statements easier to express. The term $a_n$ is called the *leading coefficient*. When the leading coefficient is $1$, the polynomial is called a *monic polynomial*. The monomial $a_n x^n$ is the *leading term*.
|
||||
|
||||
|
||||
For example, the polynomial $-16x^2 - 32x + 100$ has degree $2$, leading coefficient $-16$ and leading term $-16x^2$. It is not monic, as the leading coefficient is not $1$.
|
||||
@@ -86,13 +91,14 @@ $$
|
||||
a_1 x + a_0, \quad a_1 \neq 0,
|
||||
$$
|
||||
|
||||
is often written as $mx + b$, which is the **slope-intercept** form. The slope of a line determines how steeply it rises. The value of $m$ can be found from two points through the well-known formula:
|
||||
is often written as $mx + b$, which is the *slope-intercept* form. The slope of a line determines how steeply it rises. The value 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}}
|
||||
$$
|
||||
|
||||
::: {#fig-graph-linear-polynomial-different-m}
|
||||
```{julia}
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
@@ -111,15 +117,17 @@ end
|
||||
|
||||
imgfile = tempname() * ".gif"
|
||||
gif(anim, imgfile, fps = 1)
|
||||
caption = "Graphs of y = mx for different values of m"
|
||||
caption = ""
|
||||
plotly()
|
||||
ImageFile(imgfile, caption)
|
||||
```
|
||||
Graphs of y = mx for different values of m
|
||||
:::
|
||||
|
||||
The intercept, $b$, comes from the fact that when $x=0$ the expression is $b$. That is the graph of the function $f(x) = mx + b$ will have $(0,b)$ as a point on it.
|
||||
The intercept, $b$, comes from the fact that when $x=0$ the expression is $b$. That is, the graph of the function $f(x) = mx + b$ will have $(0,b)$ as a point on it.
|
||||
|
||||
|
||||
More generally, we have the **point-slope** form of a line, written as a polynomial through
|
||||
More generally, we have the *point-slope* form of a line, written as a polynomial through
|
||||
|
||||
|
||||
$$
|
||||
@@ -138,11 +146,11 @@ Thinking in terms of transformations, this looks like the function $f(x) = x$ (w
|
||||
The indeterminate value `x` (or some other symbol) in a polynomial, is like a variable in a function and unlike a variable in `Julia`. Variables in `Julia` are identifiers, just a means to look up a specific, already determined, value. Rather, the symbol `x` is not yet determined, it is essentially a place holder for a future value. Although we have seen that `Julia` makes it very easy to work with mathematical functions, it is not the case that base `Julia` makes working with expressions of algebraic symbols easy. This makes sense, `Julia` is primarily designed for technical computing, where numeric approaches rule the day. However, symbolic math can be used from within `Julia` through add-on packages.
|
||||
|
||||
|
||||
Symbolic math programs include well-known ones like the commercial programs Mathematica and Maple. Mathematica powers the popular [WolframAlpha](www.wolframalpha.com) website, which turns "natural" language into the specifics of a programming language. The open-source [Sage](https://www.sagemath.org/) project is an alternative to these two commercial giants. It includes a wide-range of open-source math projects available within its umbrella framework. (`Julia` can even be run from within the free service [cloud.sagemath.com](https://cloud.sagemath.com/projects).) A more focused project for symbolic math, is the [SymPy](www.sympy.org) Python library. SymPy is also used within Sage. However, SymPy provides a self-contained library that can be used standalone within a Python session.
|
||||
Symbolic math programs include well-known ones like the commercial programs Mathematica and Maple. Mathematica powers the popular [WolframAlpha](www.wolframalpha.com) website, which turns "natural" language into the specifics of a programming language. The open-source [Sage](https://www.sagemath.org/) project is an alternative to these two commercial giants. It includes a wide-range of open-source math projects available within its umbrella framework. A more focused project for symbolic math, is the [SymPy](www.sympy.org) Python library. SymPy is also used within Sage. However, SymPy provides a self-contained library that can be used standalone within a Python session.
|
||||
|
||||
The [Symbolics](https://github.com/JuliaSymbolics/Symbolics.jl) package for `Julia` provides a "fast and modern CAS for fast and modern language." It is described further in [Symbolics.jl](../alternatives/symbolics.qmd).
|
||||
The [Symbolics](https://github.com/JuliaSymbolics/Symbolics.jl) package for `Julia` provides a "fast and modern CAS for fast and modern language." It is described further in [Symbolics.jl](../alternatives/symbolics.qmd). The [Giac.jl](https://github.com/s-celles/Giac.jl/) package is another alternative.
|
||||
|
||||
As `SymPy` has some features not yet implemented in `Symbolics`, we use `SymPy` in these notes. The `PyCall` and `PythonCall` packages are available to glue `Julia` to Python in a seamless manner. These allow the `Julia` package `SymPy` (or `SymPyPythonCall`) to provide functionality from SymPy within `Julia`.
|
||||
As `SymPy` has some features not yet implemented in `Symbolics`, we use `SymPy` in these notes. The `PyCall` and `PythonCall` packages are available to glue `Julia` to Python in a seamless manner. These allow the `Julia` package `SymPy` (or `SymPyPythonCall`) to provide functionality from SymPy within `Julia`. (`Giac` calls a `C++` library and is an alternative that may not be easier to install.)
|
||||
|
||||
|
||||
:::{.callout-note}
|
||||
@@ -152,9 +160,8 @@ When `SymPy` is installed through the package manager, the underlying `Python` l
|
||||
:::
|
||||
|
||||
:::{.callout-note}
|
||||
## Note
|
||||
The [`Symbolics`](../alternatives/symbolics) package is a rapidly developing `Julia`-only package that provides symbolic math options.
|
||||
|
||||
## Alternative
|
||||
The [Symbolics](../alternatives/symbolics) package is a rapidly developing `Julia`-only package that provides symbolic math options. The [Giac package](https://github.com/s-celles/Giac.jl/) is another good alternative to `SymPy`. Both packages are described further when alternative packages are discussed.
|
||||
:::
|
||||
|
||||
---
|
||||
@@ -167,7 +174,7 @@ To use `SymPy`, we create symbolic objects to be our indeterminate symbols. The
|
||||
@syms a, b, c, x::real, zs[1:10]
|
||||
```
|
||||
|
||||
The above shows that multiple symbols can be defined at once. The annotation `x::real` instructs `SymPy` to assume the `x` is real, as otherwise it assumes it is possibly complex. There are many other [assumptions](http://docs.sympy.org/dev/modules/core.html#module-sympy.core.assumptions) that can be made. The `@syms` macro documentation lists them. The `zs[1:10]` tensor notation creates a container with $10$ different symbols. The *macro* `@syms` does not need assignment, as the variable(s) are created behind the scenes by the macro.
|
||||
The above shows that multiple symbols can be defined at once. The annotation `x::real` instructs `SymPy` to assume the `x` is real, as otherwise it assumes it is possibly complex. There are many other [assumptions](http://docs.sympy.org/dev/modules/core.html#module-sympy.core.assumptions) that can be made. The `@syms` macro documentation lists them. The `zs[1:10]` "tensor notation" creates a container with $10$ different symbols. The *macro* `@syms` does not need assignment, as the variable(s) are created behind the scenes by the macro.
|
||||
|
||||
|
||||
:::{.callout-note}
|
||||
@@ -179,9 +186,11 @@ Macros in `Julia` are just transformations of the syntax into other syntax. The
|
||||
The `SymPy` package does three basic things:
|
||||
|
||||
|
||||
* It imports some of the functionality provided by `SymPy`, including the ability to create symbolic variables.
|
||||
* It overloads many `Julia` functions to work seamlessly with symbolic expressions. This makes working with polynomials quite natural.
|
||||
* It gives access to a wide range of SymPy's functionality through the `sympy` object.
|
||||
* It imports some of the functionality provided by `SymPy`, including the ability to create symbolic variables.
|
||||
|
||||
* It add methods for many `Julia` functions to work seamlessly with symbolic expressions. This makes working with polynomials quite natural.
|
||||
|
||||
* It gives access to a wide range of SymPy's functionality through the `sympy` object.
|
||||
|
||||
|
||||
To illustrate, using the just defined `x`, here is how we can create the polynomial $-16x^2 + 100$:
|
||||
@@ -263,13 +272,6 @@ The result will always be of a symbolic type, even if the answer is just a numbe
|
||||
typeof(y)
|
||||
```
|
||||
|
||||
If there is just one free variable in an expression, the pair notation can be dropped:
|
||||
|
||||
|
||||
```{julia}
|
||||
p(4) # substitutes x=>4
|
||||
```
|
||||
|
||||
##### Example
|
||||
|
||||
|
||||
@@ -298,28 +300,25 @@ In the above, we substituted `2` in for `x` to get `y`:
|
||||
```{julia}
|
||||
#| hold: true
|
||||
p = -16x^2 + 100
|
||||
y = p(2)
|
||||
y = p(x => 2)
|
||||
```
|
||||
|
||||
The value, $36$ is still symbolic, but clearly an integer. If we are just looking at the output, we can easily translate from the symbolic value to an integer, as they print similarly. However the conversion to an integer, or another type of number, does not happen automatically. If a number is needed to pass along to another `Julia` function, it may need to be converted. In general, conversions between different types are handled through various methods of `convert`.
|
||||
|
||||
For real numbers, an easy to call conversion is available through the `float` method:
|
||||
For real numbers, an easy to call conversion is available through the generic `float` method, which converts a value to a floating point type::
|
||||
|
||||
```{julia}
|
||||
float(y)
|
||||
```
|
||||
|
||||
|
||||
|
||||
The use of the generic `float` method returns a floating point number. (The `.evalf()` method of `SymPy` objects uses `SymPy` to produce floating point versions of symbolic values.
|
||||
|
||||
`SymPy` objects have their own internal types. To preserve these on conversion to a related `Julia` value, the `N` function from `SymPy` is useful:
|
||||
|
||||
|
||||
```{julia}
|
||||
#| hold: true
|
||||
p = -16x^2 + 100
|
||||
N(p(2))
|
||||
N(p(x=>2))
|
||||
```
|
||||
|
||||
Where `convert(T, x)` requires a specification of the type to convert `x` to, `N` attempts to match the data type used by SymPy to store the number. As such, the output type of `N` may vary (rational, a BigFloat, a float, etc.) Conversion by `N` will fail if the value to be converted contains free symbols, as would be expected.
|
||||
@@ -333,7 +332,7 @@ Evaluating a symbolic expression and returning a numeric value can be done by co
|
||||
|
||||
```{julia}
|
||||
p = 200 - 16x^2
|
||||
N(p(2))
|
||||
N(p(x=>2))
|
||||
```
|
||||
|
||||
This approach is direct, but can be slow *if* many such evaluations were needed (such as with a plot). An alternative is to turn the symbolic expression into a `Julia` function and then evaluate that as usual.
|
||||
@@ -358,26 +357,26 @@ pp = lambdify(p)
|
||||
pp(1,2,3)
|
||||
```
|
||||
|
||||
This evaluation matches `a` with `1`, `b` with`2`, and `x` with `3` as that is the order returned by the function call `free_symbols(p)`. To adjust that, a second `vars` argument can be given:
|
||||
This evaluation matches `a` with `1`, `b` with`2`, and `x` with `3` as that is the order returned by the function call `free_symbols(p)`. Leaving the order to an underlying function is not a great idea, rather, explicitly passing the variables is recommended:
|
||||
|
||||
|
||||
```{julia}
|
||||
#| hold: true
|
||||
pp = lambdify(p, (x,a,b))
|
||||
pp = lambdify(p, (x,a,b)) # specify the variables
|
||||
pp(1,2,3) # computes 2*1^2 + 3
|
||||
```
|
||||
|
||||
(We suggest using the pair notation when there is more than one variable.)
|
||||
|
||||
## Graphical properties of polynomials
|
||||
|
||||
|
||||
Consider the graph of the polynomial `x^5 - x + 1`:
|
||||
|
||||
Consider the graph of the polynomial `x^5 - x + 1` in @fig-plot-polynomial-using-sympy-plot-recipe:
|
||||
|
||||
::: {#fig-plot-polynomial-using-sympy-plot-recipe}
|
||||
```{julia}
|
||||
plot(x^5 - x + 1, -3/2, 3/2)
|
||||
```
|
||||
Plot of $f(x) = x^5 - x + 1$ using the recipe for `SymPy` expression
|
||||
:::
|
||||
|
||||
(Plotting symbolic expressions with `Plots` is similar to plotting a function, in that the expression is passed in as the first argument. The expression must have only one free variable, as above, or an error will occur. This happens, as there is a `Plots` "recipe" for `SymPy` defined.)
|
||||
|
||||
@@ -385,14 +384,16 @@ plot(x^5 - x + 1, -3/2, 3/2)
|
||||
This graph illustrates the key features of polynomial graphs:
|
||||
|
||||
|
||||
* there may be values for `x` where the graph crosses the $x$ axis (real roots of the polynomial);
|
||||
* there may be peaks and valleys (local maxima and local minima);
|
||||
* except for constant polynomials, the ultimate behaviour for large values of $|x|$ is either both sides of the graph going to positive infinity, or negative infinity, or as in this graph one to the positive infinity and one to negative infinity. In particular, there is no *horizontal asymptote*.
|
||||
* there may be values for `x` where the graph crosses the $x$ axis (real roots of the polynomial);
|
||||
|
||||
* there may be peaks and valleys (local maxima and local minima);
|
||||
|
||||
* except for constant polynomials, the ultimate behaviour for large values of $|x|$ is either both sides of the graph going to positive infinity, or negative infinity, or as in this graph one to the positive infinity and one to negative infinity. In particular, there is no *horizontal asymptote*.
|
||||
|
||||
|
||||
To investigate this last point, let's consider the case of the monomial $x^n$. When $n$ is even, the following animation shows that larger values of $n$ have greater growth once outside of $[-1,1]$:
|
||||
|
||||
To investigate this last point, let's consider the case of the monomial $x^n$. When $n$ is even, the animation in @fig-faster-growing-monomials-animation shows that larger values of $n$ have greater growth once outside of $[-1,1]$:
|
||||
|
||||
::: {#fig-faster-growing-monomials-animation}
|
||||
```{julia}
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
@@ -411,30 +412,36 @@ end
|
||||
|
||||
imgfile = tempname() * ".gif"
|
||||
gif(anim, imgfile, fps = 1)
|
||||
caption = L"Demonstration that $x^{10}$ grows faster than $x^8$, ... and $x^2$ grows faster than $x^0$ (which is constant)."
|
||||
caption = L""
|
||||
plotly()
|
||||
ImageFile(imgfile, caption)
|
||||
```
|
||||
Demonstration that $x^{10}$ grows faster than $x^8$, $\dots$, and $x^2$ grows faster than $x^0$ (which is constant)
|
||||
:::
|
||||
|
||||
Of course, this is expected, as, for example, $2^2 < 2^4 < 2^6 < \cdots$. The general shape of these terms is similar - $U$ shaped, and larger powers dominate the smaller powers as $|x|$ gets big.
|
||||
Of course, this is expected, as, for example, $2^2 < 2^4 < 2^6 < \cdots$. The general shape of these terms is similar---$U$ shaped, and larger powers dominate the smaller powers as $|x|$ gets big.
|
||||
|
||||
|
||||
For odd powers of $n$, the graph of the monomial $x^n$ is no longer $U$ shaped, but rather constantly increasing. This graph of $x^5$ is typical:
|
||||
|
||||
For odd powers of $n$, the graph of the monomial $x^n$ is no longer $U$ shaped, but rather constantly increasing. This graph of $x^5$ is typical; for larger powers the shape is similar, but the growth is faster.
|
||||
|
||||
::: {#fig-show-odd-power-shape}
|
||||
```{julia}
|
||||
plot(x^5, -2, 2)
|
||||
```
|
||||
|
||||
Again, for larger powers the shape is similar, but the growth is faster.
|
||||
Plot of odd degree monomial showing the general shape for large $x$.
|
||||
:::
|
||||
|
||||
|
||||
|
||||
### Leading term dominates
|
||||
|
||||
|
||||
To see the roots and/or the peaks and valleys of a polynomial requires a judicious choice of viewing window, as ultimately the leading term will dominate the graph. The following animation of the graph of $(x-5)(x-3)(x-2)(x-1)$ illustrates. Subsequent images show a widening of the plot window until the graph appears U-shaped.
|
||||
To see the roots and/or the peaks and valleys of a polynomial requires a judicious choice of viewing window, as ultimately the leading term will dominate the graph. @fig-leading-term-dominates shows the graph of the fourth-degree polynomial $(x-5)(x-3)(x-2)(x-1)$ over different domains. Subsequent images show a widening of the plot window until the graph appears U-shaped. The leading term in the animation is $x^4$, of even degree, so the graphic is U-shaped, were the leading term of odd degree the left and right sides would each head off to different signs of infinity.
|
||||
|
||||
|
||||
::: {#fig-leading-term-dominates}
|
||||
|
||||
```{julia}
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
@@ -457,14 +464,14 @@ anim = @animate for n in 1:6
|
||||
end
|
||||
end
|
||||
|
||||
caption = "The previous graph is highlighted in red. Ultimately the leading term (\$x^4\$ here) dominates the graph."
|
||||
imgfile = tempname() * ".gif"
|
||||
gif(anim, imgfile, fps=1)
|
||||
plotly()
|
||||
ImageFile(imgfile, caption)
|
||||
ImageFile(imgfile, "")
|
||||
```
|
||||
|
||||
The leading term in the animation is $x^4$, of even degree, so the graphic is U-shaped, were the leading term of odd degree the left and right sides would each head off to different signs of infinity.
|
||||
The previous graph is highlighted in red. Ultimately the leading term ($x^4$ here) dominates the graph.
|
||||
:::
|
||||
|
||||
|
||||
To illustrate analytically why the leading term dominates, consider the polynomial $2x^5 - x + 1$ and then factor out the largest power, $x^5$, leaving a product:
|
||||
@@ -474,15 +481,15 @@ $$
|
||||
x^5 \cdot (2 - \frac{1}{x^4} + \frac{1}{x^5}).
|
||||
$$
|
||||
|
||||
For large $|x|$, the last two terms in the product on the right get close to $0$, so this expression is *basically* just $2x^5$ - the leading term.
|
||||
For large $|x|$, the last two terms in the product on the right get close to $0$, so this expression is *basically* just $2x^5$---the leading term.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
The following graphic illustrates the $4$ basic *overall* shapes that can result when plotting a polynomials as $x$ grows without bound:
|
||||
|
||||
@fig-four-basic-polynomial-shapes illustrates the $4$ basic *overall* shapes that can result when plotting a polynomials as $x$ grows without bound:
|
||||
|
||||
::: {#fig-four-basic-polynomial-shapes}
|
||||
```{julia}
|
||||
#| echo: false
|
||||
let
|
||||
@@ -501,12 +508,8 @@ plotly()
|
||||
nothing
|
||||
```
|
||||
|
||||
##### Example
|
||||
|
||||
This graphic shows some of the above:
|
||||
|
||||
[](https://m.youtube.com/watch?v=OFzqDatEvCo)
|
||||
|
||||
Figure illustrating the four basic shapes a polynomial may take for large values of $x$ or $-x$.
|
||||
:::
|
||||
|
||||
##### Example
|
||||
|
||||
@@ -536,7 +539,7 @@ This observation is the start of Descartes' rule of [signs](http://sepwww.stanfo
|
||||
## Factoring polynomials
|
||||
|
||||
|
||||
Among numerous others, there are two common ways of representing a non-zero polynomial:
|
||||
Among others, there are two common ways of representing a non-zero polynomial:
|
||||
|
||||
|
||||
* expanded form, as in $a_n x^n + a_{n-1}x^{n-1} + \cdots + a_1 x + a_0,\quad a_n \neq 0$; or
|
||||
@@ -547,7 +550,7 @@ The former uses the *standard basis* to represent the polynomial $p$.
|
||||
The latter writes $p$ as a product of linear factors, though this is only possible in general if we consider complex roots. With real roots only, then the factors are either linear or quadratic, as will be discussed later.
|
||||
|
||||
|
||||
There are values to each representation. One value of the expanded form is that polynomial addition and scalar multiplication is much easier than in factored form. For example, adding polynomials just requires matching up the monomials of similar powers. (These can be realized easily as vector operations.) For the factored form, polynomial multiplication is much easier than expanded form. For the factored form it is easy to read off *roots* of the polynomial (values of $x$ where $p$ is $0$), as a product is $0$ only if a term is $0$, so any zero must be a zero of a factor. Factored form has other technical advantages. For example, the polynomial $(x-1)^{1000}$ can be compactly represented using the factored form, but would require $1001$ coefficients to store in expanded form. (As well, due to floating point differences, the two would evaluate quite differently as one would require over a $1000$ operations to compute, the other just two.)
|
||||
There are values to each representation. One value of the expanded form is that polynomial addition and scalar multiplication is much easier than in factored form. For example, adding polynomials just requires matching up the monomials of similar powers. For the factored form, polynomial multiplication is much easier than expanded form. For the factored form it is easy to read off *roots* of the polynomial (values of $x$ where $p$ is $0$), as a product is $0$ only if a term is $0$, so any zero must be a zero of a factor. Factored form has other technical advantages. For example, the polynomial $(x-1)^{1000}$ can be compactly represented using the factored form, but would require $1001$ coefficients to store in expanded form. (As well, due to floating point differences, the two would evaluate quite differently as one would require over a $1000$ operations to compute, the other just two.)
|
||||
|
||||
|
||||
Translating from factored form to expanded form can be done by carefully following the distributive law of multiplication. For example, with some care it can be shown that:
|
||||
@@ -594,10 +597,7 @@ The factoring $(x-\sqrt{2})\cdot(x + \sqrt{2})$ is not found, as $\sqrt{2}$ is n
|
||||
### Polynomial functions and polynomials.
|
||||
|
||||
|
||||
Our definition of a polynomial is in terms of algebraic expressions which are easily represented by `SymPy` objects, but not objects from base `Julia`. (Later we discuss the `Polynomials` package for representing polynomials. There is also the `AbstractAlbegra` package for a more algebraic treatment of polynomials.)
|
||||
|
||||
|
||||
However, *polynomial functions* are easily represented by `Julia`, for example,
|
||||
Our definition of a polynomial is in terms of algebraic expressions which are easily represented by `SymPy` objects, but not objects from base `Julia`. However, *polynomial functions* are easily represented by `Julia`, for example:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -607,22 +607,16 @@ f(x) = -16x^2 + 100
|
||||
The distinction is subtle, the expression is turned into a function just by adding the "`f(x) =`" preface. But to `Julia` there is a big distinction. The function form never does any computation until after a value of $x$ is passed to it. Whereas symbolic expressions can be manipulated quite freely before any numeric values are specified.
|
||||
|
||||
|
||||
It is easy to create a symbolic expression from a function - just evaluate the function on a symbolic value:
|
||||
It is easy to create a symbolic expression from a function---just evaluate the function on a symbolic value:
|
||||
|
||||
|
||||
```{julia}
|
||||
f(x)
|
||||
```
|
||||
|
||||
This is easy---but can also be confusing. The function object is `f`, the expression is `f(x)`---the function evaluated on a symbolic object. Moreover, as seen, the symbolic expression can be evaluated using the same syntax as a function call:
|
||||
This is easy---but can also be confusing. The function object is `f`, the expression is `f(x)`---the function evaluated on a symbolic object.
|
||||
|
||||
|
||||
```{julia}
|
||||
p = f(x)
|
||||
p(2)
|
||||
```
|
||||
|
||||
For many uses, the distinction is unnecessary to make, as the many functions will work with any callable expression. For `Plots` there is a recipe – either `plot(f, a, b)` or `plot(f(x), a, b)` will produce the same plot using the `Plots` package.
|
||||
For many uses, the distinction is unnecessary to make, as the many functions will work with any callable expression. For `Plots` there is a recipe---either `plot(f, a, b)` or `plot(f(x), a, b)` will produce the same plot using the `Plots` package.
|
||||
|
||||
|
||||
## Questions
|
||||
@@ -690,8 +684,8 @@ What is the leading term of $p$?
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
choices = ["``3``", "``3x^2``", "``-2x``", "``5``"]
|
||||
answ = 2
|
||||
radioq(choices, answ)
|
||||
answer = 2
|
||||
buttonq(choices, answer)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -734,8 +728,8 @@ The linear polynomial $p = 2x + 3$ is written in which form:
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
choices = ["point-slope form", "slope-intercept form", "general form"]
|
||||
answ = 2
|
||||
radioq(choices, answ)
|
||||
answer = 2
|
||||
buttonq(choices, answer)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -758,8 +752,8 @@ What command will return the value of the polynomial when $x=2$?
|
||||
#| hold: true
|
||||
#| echo: false
|
||||
choices = [q"p*2", q"p[2]", q"p_2", q"p(x=>2)"]
|
||||
answ = 4
|
||||
radioq(choices, answ)
|
||||
answer = 4
|
||||
buttonq(choices, answer)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -776,8 +770,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$"]
|
||||
answ = 3
|
||||
radioq(choices, answ, keep_order=true)
|
||||
answer = 3
|
||||
radioq(choices, answer, keep_order=true)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -794,8 +788,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$"]
|
||||
answ = 1
|
||||
radioq(choices, answ, keep_order=true)
|
||||
answer = 1
|
||||
radioq(choices, answer, keep_order=true)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -812,8 +806,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$"]
|
||||
answ = 2
|
||||
radioq(choices, answ, keep_order=true)
|
||||
answer = 2
|
||||
radioq(choices, answer, keep_order=true)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -859,8 +853,8 @@ 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"]
|
||||
answ = 2
|
||||
radioq(choices, 2)
|
||||
answer = 2
|
||||
buttonq(choices, answer)
|
||||
```
|
||||
|
||||
###### Question
|
||||
@@ -877,6 +871,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"]
|
||||
answ = 1
|
||||
radioq(choices, answ)
|
||||
answer = 1
|
||||
buttonq(choices, answer)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user