use quarto, not Pluto to render pages

This commit is contained in:
jverzani committed 2022-07-24 16:38:24 -04:00
1 parent 93c993206a
commit 7b37ca828c
879 files changed
+793311 -2678

No files matched your search

@@ -0,0 +1,15 @@
{
"hash": "38ffb9b2d101f324d1a228d65a84d38f",
"result": {
"markdown": "# Derivative-free alternatives to Newton's method\n\n\n\nThis section uses these add-on packages:\n\n``` {.julia .cell-code}\nusing CalculusWithJulia\nusing Plots\nusing ImplicitEquations\nusing Roots\nusing SymPy\n```\n\n\n\n\n---\n\n\nNewton's method is not the only algorithm of its kind for identifying zeros of a function. In this section we discuss some alternatives.\n\n\n## The `find_zero(f, x0)` function\n\n\nThe function `find_zero` from the `Roots` packages provides several different algorithms for finding a zero of a function, including some a derivative-free algorithms for finding zeros when started with an initial guess. The default method is similar to Newton's method in that only a good initial guess is needed. However, the algorithm, while possibly slower in terms of function evaluations and steps, is engineered to be a bit more robust to the choice of initial estimate than Newton's method. (If it finds a bracket, it will use a bisection algorithm which is guaranteed to converge, but can be slower to do so.) Here we see how to call the function:\n\n::: {.cell execution_count=4}\n``` {.julia .cell-code}\nf(x) = cos(x) - x\nx₀ = 1\nfind_zero(f, x₀)\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n0.7390851332151607\n```\n:::\n:::\n\n\nCompare to this related call which uses the bisection method:\n\n::: {.cell execution_count=5}\n``` {.julia .cell-code}\nfind_zero(f, (0, 1)) ## [0,1] must be a bracketing interval\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n0.7390851332151607\n```\n:::\n:::\n\n\nFor this example both give the same answer, but the bisection method is a bit less convenient as a bracketing interval must be pre-specified.\n\n\n## The secant method\n\n\nThe default `find_zero` method above uses a secant-like method unless a bracketing method is found. The secant method is historic, dating back over $3000$ years. Here we discuss the secant method in a more general framework.\n\n\nOne way to view Newton's method is through the inverse of $f$ (assuming it exists): if $f(\\alpha) = 0$ then $\\alpha = f^{-1}(0)$.\n\n\nIf $f$ has a simple zero at $\\alpha$ and is locally invertible (that is some $f^{-1}$ exists) then the update step for Newton's method can be identified with:\n\n\n * fitting a polynomial to the local inverse function of $f$ going through through the point $(f(x_0),x_0)$,\n * and matching the slope of $f$ at the same point.\n\n\nThat is, we can write $g(y) = h_0 + h_1 (y-f(x_0))$. Then $g(f(x_0)) = x_0 = h_0$, so $h_0 = x_0$. From $g'(f(x_0)) = 1/f'(x_0)$, we get $h_1 = 1/f'(x_0)$. That is, $g(y) = x_0 + (y-f(x_0))/f'(x_0)$. At $y=0,$ we get the update step $x_1 = g(0) = x_0 - f(x_0)/f'(x_0)$.\n\n\nA similar viewpoint can be used to create derivative-free methods.\n\n\nFor example, the [secant method](https://en.wikipedia.org/wiki/Secant_method) can be seen as the result of fitting a degree-$1$ polynomial approximation for $f^{-1}$ through two points $(f(x_0),x_0)$ and $(f(x_1), x_1)$.\n\n\nAgain, expressing this approximation as $g(y) = h_0 + h_1(y-f(x_1))$ leads to $g(f(x_1)) = x_1 = h_0$. Substituting $f(x_0)$ gives $g(f(x_0)) = x_0 = x_1 + h_1(f(x_0)-f(x_1))$. Solving for $h_1$ leads to $h_1=(x_1-x_0)/(f(x_1)-f(x_0))$. Then $x_2 = g(0) = x_1 + (x_1-x_0)/(f(x_1)-f(x_0)) \\cdot f(x_1)$. This is the first step of the secant method:\n\n\n\n$$\nx_{n+1} = x_n - f(x_n) \\frac{x_n - x_{n-1}}{f(x_n) - f(x_{n-1})}.\n$$\n\n\nThat is, where the next step of Newton's method comes from the intersection of the tangent line at $x_n$ with the $x$-axis, the next step of the secant method comes from the intersection of the secant line defined by $x_n$ and $x_{n-1}$ with the $x$ axis. That is, the secant method simply replaces $f'(x_n)$ with the slope of the secant line between $x_n$ and $x_{n-1}$.\n\n\nWe code the update step as `λ2`:\n\n::: {.cell execution_count=6}\n``` {.julia .cell-code}\nλ2(f0,f1,x0,x1) = x1 - f1 * (x1-x0) / (f1-f0)\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```\nλ2 (generic function with 1 method)\n```\n:::\n:::\n\n\nThen we can run a few steps to identify the zero of sine starting at $3$ and $4$\n\n::: {.cell hold='true' term='true' execution_count=7}\n``` {.julia .cell-code}\nx0,x1 = 4,3\nf0,f1 = sin.((x0,x1))\n@show x1,f1\n\nx0,x1 = x1, λ2(f0,f1,x0,x1)\nf0,f1 = f1, sin(x1)\n@show x1,f1\n\nx0,x1 = x1, λ2(f0,f1,x0,x1)\nf0,f1 = f1, sin(x1)\n@show x1,f1\n\nx0,x1 = x1, λ2(f0,f1,x0,x1)\nf0,f1 = f1, sin(x1)\n@show x1,f1\n\nx0,x1 = x1, λ2(f0,f1,x0,x1)\nf0,f1 = f1, sin(x1)\nx1,f1\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n(x1, f1) = (3, 0.1411200080598672)\n(x1, f1) = (3.157162792479947, -0.015569509788328599)\n(x1, f1) = (3.14154625558915, 4.639800062679684e-5)\n(x1, f1) = (3.1415926554589646, -1.8691713617942337e-9)\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\n(3.141592653589793, 1.2246467991473532e-16)\n```Line truncated
"supporting": [
"more_zeros_files/figure-html"
],
"filters": [],
"includes": {
"include-in-header": [
"<script src=\"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\" integrity=\"sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg==\" crossorigin=\"anonymous\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js\" integrity=\"sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==\" crossorigin=\"anonymous\"></script>\n<script type=\"application/javascript\">define('jquery', [],function() {return window.jQuery;})</script>\n"
]
}
}
}