{
    "nbformat": 4,
    "nbformat_minor": 5,
    "metadata": {
        "kernelspec": {
            "display_name": "Python",
            "language": "python",
            "name": "python"
        },
        "language_info": {
            "name": "python"
        }
    },
    "cells": [
        {
            "id": "aa020df7",
            "cell_type": "markdown",
            "source": "<div class='alert alert-warning'>\n\nSciPy's interactive examples with Jupyterlite are experimental and may not always work as expected. Execution of cells containing imports may result in large downloads (up to 60MB of content for the first import from SciPy). Load times when importing from SciPy may take roughly 10-20 seconds. If you notice any problems, feel free to open an [issue](https://github.com/scipy/scipy/issues/new/choose).\n\n</div>",
            "metadata": {}
        },
        {
            "id": "ccf81ece",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom scipy import optimize",
            "outputs": []
        },
        {
            "id": "09003c0f",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "def f(x):\n    return (x**3 - 1)  # only one real root at x = 1",
            "outputs": []
        },
        {
            "id": "c9214218",
            "cell_type": "markdown",
            "source": "``fprime`` is not provided, use the secant method:\n",
            "metadata": {}
        },
        {
            "id": "65193a54",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "root = optimize.newton(f, 1.5)\nroot",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "1.0000000000000016"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "7802f7ce",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "root = optimize.newton(f, 1.5, fprime2=lambda x: 6 * x)\nroot",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "1.0000000000000016"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "4d6cf87f",
            "cell_type": "markdown",
            "source": "Only ``fprime`` is provided, use the Newton-Raphson method:\n",
            "metadata": {}
        },
        {
            "id": "2b17ea9f",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "root = optimize.newton(f, 1.5, fprime=lambda x: 3 * x**2)\nroot",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "1.0"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "0baaf7f9",
            "cell_type": "markdown",
            "source": "Both ``fprime2`` and ``fprime`` are provided, use Halley's method:\n",
            "metadata": {}
        },
        {
            "id": "f1fb6c1a",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "root = optimize.newton(f, 1.5, fprime=lambda x: 3 * x**2,\n                       fprime2=lambda x: 6 * x)\nroot",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "1.0"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "a5e9f13d",
            "cell_type": "markdown",
            "source": "When we want to find roots for a set of related starting values and/or\nfunction parameters, we can provide both of those as an array of inputs:\n",
            "metadata": {}
        },
        {
            "id": "08c13156",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "f = lambda x, a: x**3 - a\nfder = lambda x, a: 3 * x**2\nrng = np.random.default_rng()\nx = rng.standard_normal(100)\na = np.arange(-50, 50)\nvec_res = optimize.newton(f, x, fprime=fder, args=(a, ), maxiter=200)",
            "outputs": []
        },
        {
            "id": "43bcf423",
            "cell_type": "markdown",
            "source": "The above is the equivalent of solving for each value in ``(x, a)``\nseparately in a for-loop, just faster:\n",
            "metadata": {}
        },
        {
            "id": "2fa6c490",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "loop_res = [optimize.newton(f, x0, fprime=fder, args=(a0,),\n                            maxiter=200)\n            for x0, a0 in zip(x, a)]\nnp.allclose(vec_res, loop_res)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "True"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "44f377e9",
            "cell_type": "markdown",
            "source": "Plot the results found for all values of ``a``:\n",
            "metadata": {}
        },
        {
            "id": "7cc29549",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "analytical_result = np.sign(a) * np.abs(a)**(1/3)\nfig, ax = plt.subplots()\nax.plot(a, analytical_result, 'o')\nax.plot(a, vec_res, '.')\nax.set_xlabel('$a$')\nax.set_ylabel('$x$ where $f(x, a)=0$')\nplt.show()",
            "outputs": []
        }
    ]
}