{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# \n", "\n", "# Approximate derivatives with Julia\n", "\n", "To get started, we load the `MTH229` package and a plotting package:" ], "id": "17866994-7e6e-49a0-8e8d-df5470fd9a69" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "using MTH229\n", "using Plots\n", "plotly()" ], "id": "e149e887" }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "### Quick background\n", "\n", "Read about this material here: [Approximate derivatives in\n", "julia](http://mth229.github.io/derivatives.html).\n", "\n", "For the impatient, A secant line connecting points on the graph of\n", "$f(x)$ between $x=c$ and $x = c+h$ has slope:\n", "\n", "$$\n", "\\frac{f(c+h) - f(c)}{h}.\n", "$$\n", "\n", "The slope of the tangent line to the graph of $f(x)$ at the point\n", "$(c,f(c))$ is given by taking the limit as $h$ goes to $0$:\n", "\n", "$$\n", "\\lim_{h \\rightarrow 0} \\frac{f(c + h) - f(c)}{h}.\n", "$$\n", "\n", "The notation for this - when the limit exists - is $f'(c)$.\n", "\n", "In general the derivative of a function $f(x)$ is the function $f'(x)$,\n", "which returns the slope of the tangent line for each $x$ where it is\n", "defined. Though finding derivatives of mathematical functions is a skill\n", "that can be mastered, there are scenarios where approximating the value\n", "is desirable.\n", "\n", "#### Approximate derivatives\n", "\n", "We can approximate the slope of the tangent line several ways. The\n", "*forward [difference\n", "quotient](https://en.wikipedia.org/wiki/Difference_quotient)* takes a\n", "small value of $h$ and uses the value $(f(x+h) - f(x))/h$ as an\n", "approximation to $f'(x)$.\n", "\n", "For example, to estimate the derivative of $x^{\\ln(x)}$ at $c=2$ with\n", "`h=1e-6` we could have" ], "id": "bea8d265-d167-4164-b165-0c9d2c67281f" }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "1.120685498845475" ] } } ], "source": [ "f(x) = x^log(x)\n", "c, h = 2, 1e-6\n", "(f(c+h) - f(c)) / h" ], "id": "f2232867" }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above pattern finds the approximate derivative at the point $c$.\n", "Though this can be pushed to return a function giving the derivative at\n", "any point, we will use the more convenient solution described next for\n", "finding the derivative as a function, when applicable.\n", "\n", "#### Automatic derivatives\n", "\n", "In mathematics we use the notation $f'(x)$ to refer to the function that\n", "computes the derivative of $f(x)$ at a given $x$. The `MTH229` package\n", "provides the same notation in `Julia`. In the background, this uses\n", "*automatic differentiation*, as provided by the `ForwardDiff` package,\n", "to compute the derivative. Automatic differentiation is a tad slower\n", "than using a \\* \\[ \\] hand-computed derivative, but as accurate as that,\n", "and much easier and more accurate than using an *approximate\n", "derivative*.\n", "\n", "The `MTH229` package, using `ForwardDiff.derivative`, overloads the\n", "default meaning of `'` allowing the usual notation for a derivative to\n", "be used:" ], "id": "fdd7a2c8-224a-4033-9359-00e52ef3713b" }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "(-1.0, -1.2246467991473532e-16)" ] } } ], "source": [ "f(x) = sin(x)\n", "f'(pi), f''(pi)" ], "id": "8227dcc7" }, { "cell_type": "markdown", "metadata": {}, "source": [ "(The math notation is followed by `Julia`, in that `f'` itself returns a\n", "function which evaluates the derivative, and `f'(pi)` first computes the\n", "derivative and then evaluates that function at `pi`.)\n", "\n", "#### Symbolic derivatives\n", "\n", "Automatic differentiation gives accurate numeric values for first,\n", "second, and even higher-order derivatives. It does not however, return\n", "the expression one would get were these computed by hand. The `diff`\n", "function from `SymPy` will find symbolic derivatives, similar to what is\n", "achieved when differentiating “by hand,” though for many problems the\n", "effort will be much less.\n", "\n", "The `diff` function can be called with a symbolic expression and a\n", "variable to differentiate in:" ], "id": "78e559dd-19db-45f7-b255-44419e557b39" }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "f(x) = exp(x^2) * sin(sqrt(x))\n", "@syms x\n", "diff(f(x), x)" ], "id": "6ff9f3a5" }, { "cell_type": "markdown", "metadata": {}, "source": [ "Symbolic expressions can be generated by passing `x` into the function,\n", "as illustrated, or written directly, as in\n", "`diff(exp(x^2)*sin(sqrt(x)), x)`.\n", "\n", "### Tangent lines\n", "\n", "The tangent line to the graph of $f(x)$ at $x=c$ is given by\n", "$y=f(c)+f'(c)(x-c)$. It is fairly easy to plot both the function and its\n", "tangent line — we just need a function to compute the tangent line. Such\n", "a function, `tangent(f,c)` is found in the `MTH229` package. This\n", "function consumes a function (`f`) and a point (`c`) and returns a\n", "**function** of `x` returning the `y` values of the tangent line." ], "id": "a761b5d7-6576-4d58-a6c4-f8fff86da238" }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "Function of `x` to compute the tangent line of `f` at `c`:\n", " f(c) + f'(c) * (x-c)" ] } } ], "source": [ "f(x) = x^x\n", "a,b = 1/2, 2\n", "c = 1\n", "sl = secant(f, a, b)\n", "tl = tangent(f, c)" ], "id": "118c0db1" }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we see how to use it and the related `secant(f,a,b)` function:" ], "id": "8f68a464-786e-4170-9448-173c53d8b0c0" }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/html": [ "" ] } } ], "source": [ "plot(f, 1/4, 2.5, legend=false)\n", "plot!(sl)\n", "plot!(tl)" ], "id": "263864af" }, { "cell_type": "markdown", "metadata": {}, "source": [ "Suppose the intersection point between the secant and tangent lines\n", "between $0$ and $0.5$ is to be identified. This can be done with:" ], "id": "14a42daa-068d-4d48-8edb-5c2231fd6f7b" }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "0.3267268967722361" ] } } ], "source": [ "eqn(x) = tl(x) - sl(x)\n", "fzero(eqn, 0, 0.5)" ], "id": "3d86cd48" }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Higher-order derivatives\n", "\n", "Higher-order derivatives can be computed as well:\n", "\n", "Automatic derivatives can be computed using the usual notation, e.g.,\n", "`f''` to find $f''(x)$.\n", "\n", "Higher-order symbolic derivatives can be computed by passing the order\n", "to `diff` as a second argument, as in `diff(f(x), x, n)`.\n", "\n", "For example, consider $f(x) = e^x \\sin(x)$. We have:" ], "id": "307c6c55-d8d9-4691-ad06-3ee0a121b643" }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "-39.769061688293974" ] } } ], "source": [ "f(x) = exp(x) * sin(x)\n", "f''(3)" ], "id": "60cab8fa" }, { "cell_type": "markdown", "metadata": {}, "source": [ "As compared to the symbolic answer:" ], "id": "819bd9f5-ec3e-4cb6-aca3-5b8ad7ce8004" }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "@syms x\n", "fpp = diff(f(x), x, 2) # or diff(f(x), x, x)" ], "id": "4beba7c7" }, { "cell_type": "markdown", "metadata": {}, "source": [ "and its numeric value at `3`:" ], "id": "f1c5aefe-1bda-4c55-b25f-85819527a57e" }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "-39.76906168829398" ] } } ], "source": [ "float(fpp(3)) # make numeric" ], "id": "c97970e1" }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------" ], "id": "f0ca6c19-7ebb-4824-8e33-9bafc3c3f464" }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Your commands go here" ], "id": "948293a9" } ], "nbformat": 4, "nbformat_minor": 5, "metadata": { "kernelspec": { "name": "julia-1.11", "display_name": "Julia 1.11.2", "language": "julia", "path": "/Users/jverzani/Library/Jupyter/kernels/julia-1.11" }, "language_info": { "name": "julia", "file_extension": ".jl", "mimetype": "application/julia", "version": "1.11.2" } } }