{ "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": "f9d8e3c6-23a9-4673-8a52-d23b332a98d7" }, { "cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": [ "using MTH229\n", "using Plots\n", "plotly()" ], "id": "2" }, { "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 quotient* takes a small value of $h$ and uses the\n", "value $(f(x+h) - f(x))/h$ as an approximation.\n", "\n", "For example, to estimate the derivative of $x^{\\ln(x)}$ at $c=2$ with\n", "`h=1e-6` we could have" ], "id": "19cf00e9-b25a-48fc-bde5-2a3f4ec6efbb" }, { "cell_type": "code", "execution_count": 1, "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": "6" }, { "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, and much\n", "easier and more accurate than using an *approximate 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": "041eba96-5cdd-4877-b86e-d3f29a959af7" }, { "cell_type": "code", "execution_count": 1, "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": "8" }, { "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": "a00939f3-0512-4b67-8020-4b6d775fadc4" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ " ⎛ 2⎞ \n", " ⎛ 2⎞ ⎝x ⎠ \n", " ⎝x ⎠ ℯ ⋅cos(√x)\n", "2⋅x⋅ℯ ⋅sin(√x) + ─────────────\n", " 2⋅√x " ] } } ], "source": [ "f(x) = exp(x^2) * sin(sqrt(x))\n", "@syms x\n", "diff(f(x), x)" ], "id": "10" }, { "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": "30c55399-f344-4851-b44c-a64e53c82a96" }, { "cell_type": "code", "execution_count": 1, "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": "12" }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we see how to use it and the related `secant(f,a,b)` function:" ], "id": "6906a012-286d-4669-8309-f9af79059c05" }, { "cell_type": "code", "execution_count": 1, "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": "14" }, { "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": "2647b0ea-50e7-47c5-a45a-7c63d68a004e" }, { "cell_type": "code", "execution_count": 1, "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": "16" }, { "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": "3714eee2-9c55-4c5a-9dc7-57cf791f4a01" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "-39.769061688293974" ] } } ], "source": [ "f(x) = exp(x) * sin(x)\n", "f''(3)" ], "id": "18" }, { "cell_type": "markdown", "metadata": {}, "source": [ "As compared to the symbolic answer:" ], "id": "d2548eac-d9aa-42a3-b9c5-0c0e90d61a8d" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ " x \n", "2⋅ℯ ⋅cos(x)" ] } } ], "source": [ "@syms x\n", "fpp = diff(f(x), x, 2) # or diff(f(x), x, x)" ], "id": "20" }, { "cell_type": "markdown", "metadata": {}, "source": [ "and its numeric value at `3`:" ], "id": "b61947e4-b89c-4722-acca-ff4f5e3d6c30" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "output_type": "display_data", "metadata": {}, "data": { "text/plain": [ "-39.76906168829398" ] } } ], "source": [ "float(fpp(3)) # make numeric" ], "id": "22" }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------" ], "id": "4ced8350-dc28-492b-bd09-d3116b164094" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Your commands go here\n" ], "id": "24" } ], "nbformat": 4, "nbformat_minor": 5, "metadata": { "kernel_info": { "name": "julia" }, "kernelspec": { "name": "julia", "display_name": "Julia", "language": "julia" }, "language_info": { "name": "julia", "codemirror_mode": "julia", "version": "1.10.0" } } }