{ "metadata": { "name": "", "signature": "sha256:ebdc09f2bf4edb98a5219f3c142f07a09ffe11eda7f5673574e9160ba49be18c" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": [], "source": [ "> This is one of the 100 recipes of the [IPython Cookbook](http://ipython-books.github.io/), the definitive guide to high-performance scientific computing and data science in Python.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 9.1. Finding the root of a mathematical function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Let's import NumPy, SciPy, scipy.optimize, and matplotlib." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np\n", "import scipy as sp\n", "import scipy.optimize as opt\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. We define the mathematical function $f(x)=\\cos(x)-x$ in Python. We will try to find a root of this function numerically, which corresponds to a fixed point of the cosine function." ] }, { "cell_type": "code", "collapsed": false, "input": [ "f = lambda x: np.cos(x) - x" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Let's plot this function on the interval $[-5, 5]$." ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = np.linspace(-5, 5, 1000)\n", "y = f(x)\n", "plt.figure(figsize=(5,3));\n", "plt.plot(x, y);\n", "plt.axhline(0, color='k');\n", "plt.xlim(-5,5);" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. We see that this function has a unique root on this interval (this is because the function's sign changes on this interval). The scipy.optimize module contains a few root-finding functions that are adapted here. For example, the `bisect` function implements the **bisection method** (also called the **dichotomy method**). It takes as input the function and the interval to find the root in." ] }, { "cell_type": "code", "collapsed": false, "input": [ "opt.bisect(f, -5, 5)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's visualize the root on the plot." ] }, { "cell_type": "code", "collapsed": false, "input": [ "plt.figure(figsize=(5,3));\n", "plt.plot(x, y);\n", "plt.axhline(0, color='k');\n", "plt.scatter([_], [0], c='r', s=100);\n", "plt.xlim(-5,5);" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "5. A faster and more powerful method is `brentq` (Brent's method). This algorithm also requires that $f$ is continuous and that $f(a)$ and $f(b)$ have different signs." ] }, { "cell_type": "code", "collapsed": false, "input": [ "opt.brentq(f, -5, 5)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `brentq` method is faster than `bisect`. If the conditions are satisfied, it is a good idea to try Brent's method first." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%timeit opt.bisect(f, -5, 5)\n", "%timeit opt.brentq(f, -5, 5)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> You'll find all the explanations, figures, references, and much more in the book (to be released later this summer).\n", "\n", "> [IPython Cookbook](http://ipython-books.github.io/), by [Cyrille Rossant](http://cyrille.rossant.net), Packt Publishing, 2014 (500 pages)." ] } ], "metadata": {} } ] }