{
    "nbformat": 4,
    "nbformat_minor": 5,
    "metadata": {
        "kernelspec": {
            "display_name": "Python",
            "language": "python",
            "name": "python"
        },
        "language_info": {
            "name": "python"
        }
    },
    "cells": [
        {
            "id": "32247f12",
            "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": "a2d08c49",
            "cell_type": "markdown",
            "source": "Suppose we wish to minimize the following function.\n",
            "metadata": {}
        },
        {
            "id": "13668e63",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "def f(x, c=1):\n    return (x - c)**2 + 2",
            "outputs": []
        },
        {
            "id": "bac26ced",
            "cell_type": "markdown",
            "source": "First, we must find a valid bracket. The function is unimodal,\nso `bracket_minium` will easily find a bracket.\n",
            "metadata": {}
        },
        {
            "id": "a0e70024",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "from scipy.optimize import elementwise\nres_bracket = elementwise.bracket_minimum(f, 0)\nres_bracket.success",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "True"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "71dd449b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "res_bracket.bracket",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "(0.0, 0.5, 1.5)"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "73744191",
            "cell_type": "markdown",
            "source": "Indeed, the bracket points are ordered and the function value\nat the middle bracket point is less than at the surrounding\npoints.\n",
            "metadata": {}
        },
        {
            "id": "26681d70",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "xl, xm, xr = res_bracket.bracket\nfl, fm, fr = res_bracket.f_bracket\n(xl < xm < xr) and (fl > fm <= fr)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "True"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "9003a623",
            "cell_type": "markdown",
            "source": "Once we have a valid bracket, `find_minimum` can be used to provide\nan estimate of the minimizer.\n",
            "metadata": {}
        },
        {
            "id": "dfd9a1e7",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "res_minimum = elementwise.find_minimum(f, res_bracket.bracket)\nres_minimum.x",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "1.0000000149011612"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "451ebcfd",
            "cell_type": "markdown",
            "source": "The function value changes by only a few ULPs within the bracket, so\nthe minimizer cannot be determined much more precisely by evaluating\nthe function alone (i.e. we would need its derivative to do better).\n",
            "metadata": {}
        },
        {
            "id": "2224c3c3",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "import numpy as np\nfl, fm, fr = res_minimum.f_bracket\n(fl - fm) / np.spacing(fm), (fr - fm) / np.spacing(fm)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "(0.0, 2.0)"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "0d861081",
            "cell_type": "markdown",
            "source": "Therefore, a precise minimum of the function is given by:\n",
            "metadata": {}
        },
        {
            "id": "9c2b04df",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "res_minimum.f_x",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "2.0"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "84c16ad6",
            "cell_type": "markdown",
            "source": "`bracket_minimum` and `find_minimum` accept arrays for most arguments.\nFor instance, to find the minimizers and minima for a few values of the\nparameter ``c`` at once:\n",
            "metadata": {}
        },
        {
            "id": "427bb99b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "c = np.asarray([1, 1.5, 2])\nres_bracket = elementwise.bracket_minimum(f, 0, args=(c,))\nres_bracket.bracket",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "(array([0. , 0.5, 0.5]), array([0.5, 1.5, 1.5]), array([1.5, 2.5, 2.5]))"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "2d8c5dac",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "res_minimum = elementwise.find_minimum(f, res_bracket.bracket, args=(c,))\nres_minimum.x",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([1.00000001, 1.5       , 2.        ])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "c6db8446",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "res_minimum.f_x",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([2., 2., 2.])"
                    },
                    "execution_count": null
                }
            ]
        }
    ]
}