diff --git a/quarto/README-quarto.md b/quarto/README-quarto.md index c2db764..27a0248 100644 --- a/quarto/README-quarto.md +++ b/quarto/README-quarto.md @@ -1,15 +1,3 @@ -## TODO - - -* mermaid, ojs? - -CAN'T DO * set up quarto to generate on CI. (Tried, but can't get through to the finish before a CI timeout...; Must use quarto publish command locally...) -DONE * PlotlyLight -DONE * clean up edit link -DONE * remove pinned header -DONE * clean up directory -DONE (?) * JSXGraph files -WON'T DO * download links to Pluto .jl files (if we have .jmd, but we might deprecate...) For *now* .jmd is derprecated; though we keep the files around .... # CalculusWithJulia via quarto @@ -44,6 +32,12 @@ This can be done with this commandline call: julia adjust_plotly.jl was solved with (https://waylonwalker.com/til/git-checkout-worktree/) > git worktree remove f5611730 +``` +quarto render; julia adjust_plotly.jl +quarto publish gh-pages --no-render +``` + + # ------ @@ -86,3 +80,18 @@ DONE? * do something with JSXGraph DONE * figure out why PlotlyLight doesn't work XXX hacky! DONE * use an include file not the "hack" in jmd2qmd DONE * modify sympy's show method + + +## TODO + + +* use pandoc references(?) +* mermaid, ojs? + +CAN'T DO * set up quarto to generate on CI. (Tried, but can't get through to the finish before a CI timeout...; Must use quarto publish command locally...) +DONE * PlotlyLight +DONE * clean up edit link +DONE * remove pinned header +DONE * clean up directory +DONE (?) * JSXGraph files +WON'T DO * download links to Pluto .jl files (if we have .jmd, but we might deprecate...) For *now* .jmd is derprecated; though we keep the files around .... diff --git a/quarto/_quarto.yml b/quarto/_quarto.yml index 04685fc..d794c0a 100644 --- a/quarto/_quarto.yml +++ b/quarto/_quarto.yml @@ -1,4 +1,4 @@ -version: "0.11" +version: "0.12" project: type: book diff --git a/quarto/differentiable_vector_calculus/scalar_functions_applications.qmd b/quarto/differentiable_vector_calculus/scalar_functions_applications.qmd index 5989a57..bebc462 100644 --- a/quarto/differentiable_vector_calculus/scalar_functions_applications.qmd +++ b/quarto/differentiable_vector_calculus/scalar_functions_applications.qmd @@ -597,6 +597,60 @@ To find $\partial{z}/\partial{x}$ and $\partial{z}/\partial{y}$ we have: ∂x, ∂y ``` +##### Example + +The `find_zero` function has been used to solve for $f(x, p) = 0$ where $p$ is a parameter. Mathematically, this equation defines $x^*(p)$ satisfying $f(x^*(p), p)=0,$ that is $x^*$ is implicitly a function of $p$. What is the derivative (gradient) of $x^*$? + +Assume for now that $p$ is a scalar quantity, so $f(x,p)$ is a scalar function of two variables. Then we can differentiate in $p$ to see: + +$$ +\frac{d}{dp}f(x^*(p), p) = +\frac{\partial}{\partial x}f(x^*(p),p) \frac{d}{dp}x^*(p) + +\frac{\partial}{\partial p}f(x^*(p),p) \frac{d}{dp}p = 0 +$$ + +As the partial in $x$ of $f$ is a scalar quantity, we can divide to get: + +$$ +\frac{d}{dp}x^*(p) = -\frac{\frac{\partial}{\partial p}f(x^*(p),p)}{\frac{\partial}{\partial x}f(x^*(p),p)} +$$ + +For example, consider the equation $f(x, p) = \cos(x) - px$ for $p > 0$. This will always have a unique solution in $(0, \pi/2)$ which can be found, as follows with $p=2$: + +```{julia} +f(x, p) = cos(x) - p*x +p = 2 +xᵅ = find_zero(f, (0, pi/2), p) +``` + +The derivative could be found directly through automatic differentiation by `ForwardDiff.derivative`, though it takes a bit of an adjustment to our function call to get the types to flow through. Rather than make that adjustment, we use the above to find the derivative for a given $p$, for example, again with $p=2$: + +```{julia} +p = 2 +xᵅ = find_zero(f, (0, pi/2), p) +fₓ = ForwardDiff.derivative(x -> f(x,p), xᵅ) +fₚ = ForwardDiff.derivative(p -> f(xᵅ, p), p) +- fₚ / fₓ +``` + +The negative sign makes sense: as $p$ gets bigger, the line $y=px$ gets steeper and intersects the cosine graph earlier, hence $x^*$ is decreasing. + +A plot can easily be made by wrapping the above in a function: + +```{julia} +function find_zero_derivative(f, x₀, p) + xᵅ = find_zero(f, x₀, p) + fₓ = ForwardDiff.derivative(x -> f(x,p), xᵅ) + fₚ = ForwardDiff.derivative(p -> f(xᵅ, p), p) + - fₚ / fₓ +end +F(p) = find_zero_derivative(f, (0, pi/2), p) +plot(F, 0.01, 5) # p > 0 +``` + +This problem does not have a readily expressed value for $x^*$, but when $p \approx 0$ we should get similar behavior to the intersection of $y=px$ and $y=\pi/2 - x$ for $x^*$, or $x^* \approx \pi/(2(1-p))$ which has derivative of $-\pi/2$ at $p=0$, matching the above graph. For *large* $p$, the problem looks like the intersection of the line $y=1$ with $y=px$ or $x^* \approx 1/p$ which has derivative that goes to $0$ as $p$ goes to infinity, again matching this graph. + + ## Optimization diff --git a/quarto/integrals/arc_length.qmd b/quarto/integrals/arc_length.qmd index 1e78f85..88af745 100644 --- a/quarto/integrals/arc_length.qmd +++ b/quarto/integrals/arc_length.qmd @@ -416,6 +416,18 @@ $$ ##### Example +The following link shows how the perimeter of a complex figure relates to the perimeter of a circle: + +```{julia} +#| echo: false +tweet = """ +
+""" +HTMLoutput(tweet) +``` + +##### Example + A teacher of small children assigns his students the task of computing the length of a jump rope by counting the number of $1$-inch segments it is made of. He knows that if a student is accurate, no matter how fast or slow they count the answer will be the same. (That is, unless the student starts counting in the wrong direction by mistake). The teacher knows this, as he is certain that the length of curve is independent of its parameterization, as it is a property intrinsic to the curve. diff --git a/quarto/limits/intermediate_value_theorem.qmd b/quarto/limits/intermediate_value_theorem.qmd index 72215e3..19270e8 100644 --- a/quarto/limits/intermediate_value_theorem.qmd +++ b/quarto/limits/intermediate_value_theorem.qmd @@ -317,20 +317,34 @@ We see from the graph that it is clearly between $0$ and $2$, so all we need is find_zero(𝒉, (0, 2)) ``` -#### Using parameterized functions (`f(x,p)`) with `find_zero` +##### Example: Inverse functions +If $f(x)$ is *monotonic* and *continuous* over an interval $[a,b]$ then it has an *inverse function*. That is for any $y$ between $f(a)$ and $f(b)$ we can find an $x$ satisfying $y = f(x)$ with $a \leq x \leq b$. This is due, of course, to both the intermediate value theorem (which guarantees an $x$) and monotonicity (which guarantees just one $x$). -Geometry will tell us that $\cos(x) = x/p$ for *one* $x$ in $[0, \pi/2]$ whenever $p>0$. We could set up finding this value for a given $p$ by making $p$ part of the function definition, but as an illustration of passing parameters, we leave `p` as a parameter (in this case, as a second value with default of $1$): - +To see how we can *numerically* find an inverse function using `find_zero`, we have this function: ```{julia} -#| hold: true -f(x, p=1) = cos(x) - x/p -I = (0, pi/2) -find_zero(f, I), find_zero(f, I, p=2) +function inverse_function(f, a, b, args...; kwargs...) + fa, fb = f(a), f(b) + m, M = fa < fb ? (fa, fb) : (fb, fa) + y -> begin + @assert m ≤ y ≤ M + find_zero(x ->f(x) - y, (a,b), args...; kwargs...) + end +end ``` -The second number is the solution when `p=2`. +The check on `fa < fb` is due to the possibility that $f$ is increasing (in which case `fa < fb`) or decreasing (in which case `fa > fb`). + +To see this used, we consider the monotonic function $f(x) = x - \sin(x)$ over $[0, 5\pi]$. To graph, we have: + +```{julia} +f(x) = x - sin(x) +a, b = 0, 5pi +plot(inverse_function(f, a, b), f(a), f(b); aspect_ratio=:equal) +``` + +(We plot over the range $[f(a), f(b)]$ here, as we can guess $f(x)$ is *increasing*.) ##### Example @@ -515,6 +529,29 @@ sign(fᵢ(prevfloat(x0))), sign(fᵢ(nextfloat(x0))) So, the "bisection method" applied here finds a point where the function crosses $0$, either by continuity or by jumping over the $0$. (A `jump` discontinuity at $x=c$ is defined by the left and right limits of $f$ at $c$ existing but being unequal. The algorithm can find $c$ when this type of function jumps over $0$.) +#### Using parameterized functions (`f(x,p)`) with `find_zero` + + +Geometry will tell us that $\cos(x) = x/p$ for *one* $x$ in $[0, \pi/2]$ whenever $p>0$. We could set up finding this value for a given $p$ by making $p$ part of the function definition, but as an illustration of passing parameters, we leave `p` as a parameter (in this case, as a second value with default of $1$): + + +```{julia} +#| hold: true +f(x, p=1) = cos(x) - x/p +I = (0, pi/2) +find_zero(f, I), find_zero(f, I, p=2) +``` + +The second number is the solution when `p=2`. + +The above used a *keyword* argument, but a positional argument allows for broadcasting: + +```{julia} +find_zero.(f, Ref(I), 1:5) # solutions for p=1,2,3,4,5 +``` + +(The use of `Ref` above prevents broadcasting over the specified bracketing interval.) + ### The `find_zeros` function diff --git a/quarto/misc/calculus_with_julia.qmd b/quarto/misc/calculus_with_julia.qmd index aa66f74..9ab0fc9 100644 --- a/quarto/misc/calculus_with_julia.qmd +++ b/quarto/misc/calculus_with_julia.qmd @@ -39,12 +39,6 @@ However, for each new `Julia` session, the package must be *loaded*, as with the using CalculusWithJulia ``` -```{julia} -#| echo: false -#| results: "hidden" -using CalculusWithJulia.WeaveSupport -``` - That is all. The rest of this page just provides some details for the interested reader. @@ -140,5 +134,3 @@ This design works great when the "generic" usage matches the needs of the packag * The extension of a generic is for a type defined outside the author's package. This is known as "type piracy" and is frowned on, as it can lead to subtle errors. The `CalculusWithJulia` package practices this for one case: using `'` to indicate derivatives for `Function` objects. * The generic function concept is not part of base `Julia`. An example might be the `solve` function. This name has a well-defined mathematical usage (e.g., "solve for $x$."), but the generic concept is not part of base `Julia`. As it is used by `SymPy` and `DifferentialEquations`, among others, the ecosystem has a stub package `CommonSolve` allowing the sharing of this "verb." - - diff --git a/quarto/misc/getting_started_with_julia.qmd b/quarto/misc/getting_started_with_julia.qmd index 5b88f52..922733d 100644 --- a/quarto/misc/getting_started_with_julia.qmd +++ b/quarto/misc/getting_started_with_julia.qmd @@ -7,7 +7,6 @@ #| echo: false #| results: "hidden" using CalculusWithJulia -using CalculusWithJulia.WeaveSupport nothing ``` @@ -103,4 +102,3 @@ With that in hand, to make a graph of a function over a range, we follow this pa ```{julia} plot(sin, 0, 2pi) ``` - diff --git a/quarto/misc/julia_interfaces.qmd b/quarto/misc/julia_interfaces.qmd index ecb43fc..54afb17 100644 --- a/quarto/misc/julia_interfaces.qmd +++ b/quarto/misc/julia_interfaces.qmd @@ -7,7 +7,6 @@ #| echo: false #| results: "hidden" using CalculusWithJulia -using CalculusWithJulia.WeaveSupport using Plots nothing ``` @@ -146,5 +145,3 @@ JupyterLab, a variant, has more features, commonly associated with an integrated [Julia for Visual Studio Code](https://www.julia-vscode.org/) provides support for the julia programming language for [VS Code](https://code.visualstudio.com/). VS Code is an open-sourced code editor supported by Microsoft. VS Code provides a cross-platform interface to `Julia` geared towards programming within the language. - - diff --git a/quarto/precalc/calculator.qmd b/quarto/precalc/calculator.qmd index 085ef88..4e06db2 100644 --- a/quarto/precalc/calculator.qmd +++ b/quarto/precalc/calculator.qmd @@ -184,6 +184,27 @@ A right triangle has sides $a=11$ and $b=12$. Find the length of the hypotenus 11^2 + 12^2 ``` +##### Example + +An article in the [Washington Post](https://www.washingtonpost.com/climate-environment/2022/09/19/ants-population-20-quadrillion/) describes estimates for the number of ants on earth. + + +They describe the number of ants two ways: + +* There are $20$ *trillion* ants. +* There are $12$ megatons of ants + +With this how many ants make up a pound? + +Below we use the underscore as a separator, which is parsed as commas are to separate groups of numbers. The calculation is the number of ants divided by the number of pounds of ants (one megaton is $1$ million pounds): + +```{julia} +20_000_000_000_000_000 / (1_000_000 * 12 * 2000) +``` + +Or not quite a million per pound. + + ## Order of operations diff --git a/quarto/precalc/inversefunctions.qmd b/quarto/precalc/inversefunctions.qmd index 346ec99..076f0a6 100644 --- a/quarto/precalc/inversefunctions.qmd +++ b/quarto/precalc/inversefunctions.qmd @@ -139,12 +139,19 @@ $$ We see that $f^{-1}(x) = 1 + (x - 2)^{1/5}$. The fact that the power $5$ is an odd power is important, as this ensures a unique (real) solution to the fifth root of a value, in the above $y-2$. +In the section on [polynomial roots](../precalc/polynomial_roots.html) we introduce the `solve` function of `SymPy`, which can algebraically solve for inverse functions in easier cases. + + + ##### Example The function $f(x) = x^x, x \geq 1/e$ is strictly increasing. However, trying to algebraically solve for an inverse function will quickly run into problems (without using specially defined functions). The existence of an inverse does not imply there will always be luck in trying to find a mathematical rule defining the inverse. +In the section on the [intermediate value theorem](../limits/intermediate_value_theorem.html#the-find_zero-function) we will see how to *numerically* solve for an inverse function. + + ## Functions which are not always invertibleHow cookie cutters are made pic.twitter.com/eumfwH4Ixl
— How Things Are Manufactured (@fastworkers6) August 7, 2022