{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bisection method"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"%config InlineBackend.figure_format = 'svg'\n",
"from numpy import exp,sin,linspace,sign,abs\n",
"from matplotlib.pyplot import figure,plot,grid,xlabel,ylabel"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us define three different functions for which we will find the root."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def f1(x):\n",
" f = exp(x) - sin(x)\n",
" return f"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"def f2(x):\n",
" f = x**2 - 4.0*x*sin(x) + (2.0*sin(x))**2\n",
" return f"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def f3(x):\n",
" f = x**2 - 4.0*x*sin(x) + (2.0*sin(x))**2 - 0.5\n",
" return f"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following function implements the bisection method. Note that it takes some default arguments."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"def bisect(fun,a,b,N=100,eps=1.0e-4,delta=1.0e-4,debug=False):\n",
" fa, fb = fun(a), fun(b)\n",
" sa, sb = sign(fa), sign(fb)\n",
" \n",
" if abs(fa) < delta:\n",
" return (a,0)\n",
"\n",
" if abs(fb) < delta:\n",
" return (b,0)\n",
"\n",
" # check if interval is admissible\n",
" if fa*fb > 0.0:\n",
" if debug:\n",
" print(\"Interval is not admissible\\n\")\n",
" return (0,1)\n",
"\n",
" for i in range(N):\n",
" e = b-a\n",
" c = a + 0.5*e\n",
" if abs(e) < eps*abs(c):\n",
" if debug:\n",
" print(\"Interval size is below tolerance\\n\")\n",
" return (c,0)\n",
" fc = fun(c)\n",
" if abs(fc) < delta:\n",
" if debug:\n",
" print(\"Function value is below tolerance\\n\")\n",
" return (c,0)\n",
" sc = sign(fc)\n",
" if sa != sc:\n",
" b = c\n",
" fb= fc\n",
" sb= sc\n",
" else:\n",
" a = c\n",
" fa= fc\n",
" sa= sc\n",
" if debug:\n",
" print(\"%5d %16.8e %16.8e %16.8e\"%(i+1,c,abs(b-a),abs(fc)))\n",
" \n",
" # If we reached here, then there is no convergence\n",
" print(\"No convergence in %d iterations !!!\" % N)\n",
" return (0,2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## First function"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 1 -3.00000000e+00 1.00000000e+00 1.90907076e-01\n",
" 2 -3.50000000e+00 5.00000000e-01 3.20585844e-01\n",
" 3 -3.25000000e+00 2.50000000e-01 6.94209267e-02\n",
" 4 -3.12500000e+00 1.25000000e-01 6.05288259e-02\n",
" 5 -3.18750000e+00 6.25000000e-02 4.61629389e-03\n",
" 6 -3.15625000e+00 3.12500000e-02 2.79283147e-02\n",
" 7 -3.17187500e+00 1.56250000e-02 1.16471966e-02\n",
" 8 -3.17968750e+00 7.81250000e-03 3.51301957e-03\n",
" 9 -3.18359375e+00 3.90625000e-03 5.52273640e-04\n",
" 10 -3.18164062e+00 1.95312500e-03 1.48021741e-03\n",
" 11 -3.18261719e+00 9.76562500e-04 4.63932552e-04\n",
"Function value is below tolerance\n",
"\n"
]
}
],
"source": [
"M = 100 # Maximum number of iterations\n",
"eps = 1.0e-4 # Tolerance on the interval\n",
"delta = 1.0e-4 # Tolerance on the function\n",
"a, b = -4.0, -2.0\n",
"r,status = bisect(f1,a,b,M,eps,delta,True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Second function"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Interval is not admissible\n",
"\n"
]
}
],
"source": [
"M = 100 # Maximum number of iterations\n",
"eps = 1.0e-4 # Tolerance on the interval\n",
"delta = 1.0e-4 # Tolerance on the function\n",
"a, b = -4.0, -2.0\n",
"r,status = bisect(f2,a,b,M,eps,delta,True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets visualize this function."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n"
],
"text/plain": [
"