1b bisection ported

This commit is contained in:
lda committed 2025-02-04 03:23:13 +07:00
1 parent 6e35861154
commit 90e0d7638b
3 files changed
+127 -42

No files matched your search

+1
View File
@@ -0,0 +1 @@
__pycache__
+119
View File
@@ -0,0 +1,119 @@
"bisection tailored to fit lab 1b"
from typing import Callable
from numbers import Real
from math import isclose, fabs
# this is the already existing bis, see git blame
def bis(
f: Callable[[Real], Real],
low: Real,
high: Real,
*,
rel_tol: Real = 1e-9,
abs_tol: Real = 0.0,
max_loop: int = 100,
) -> tuple[Real, int]:
"""real
rel_tol and abs_tol passes to `math.isclose`
"""
def ldaprx(a, b):
return isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)
steps = 0
fl = f(low)
fh = f(high)
# raise ValueError(f"at {low =} f(x) is {fl}, at {high =} f(x) is {fh} which has the same sign")
if ldaprx(0, fl):
return (low, 0)
if ldaprx(0, fh):
return (high, 0)
mid = (low + high) / 2
while (steps := steps + 1) and (max_loop := max_loop - 1) + 1 > 0:
match f(mid):
case x if ldaprx(0, x):
return (mid, steps)
case x if x < 0:
low = mid
case x if x > 0:
high = mid
mid = (low + high) / 2
return (mid, steps)
def bis1b(
f: Callable[..., Real],
bounds: tuple[Real, Real],
rel_tol: Real = 1e-6,
maxit: int = 50,
fa: tuple = None,
fkw: dict = None,
) -> tuple[Real, Real, Real, int]:
"""bisect: root location zeroes
uses bisection method to find the root of func
input:
func: name of function
bounds: lower and upper guesses
rel_tol: desired relative error (default = 0.0001%)
maxit: maximum allowable iterations (default = 50)
fa, fkw: additional parameters used by func
output:
root: real root
fx: function value at root
ea: approximate relative error. not in percent because that is bullshit
iter: number of iterations
function should take one real variable x (Real) + farg and fkwarg like so:
`f(x, *fa, **fkw)`
"""
if fa is None:
fa = ()
if fkw is None:
fkw = {}
def fi(x):
return f(x, *fa, **fkw)
if len(bounds) != 2:
raise ValueError("bounds should have two values?")
xl, xu = bounds
# shit naming competition
if fi(xl) * fi(xu) > 0: # maybe incorrect
raise ValueError("no sign change")
it = 0
xr = xl
ea = 1
while True:
xr_old = xr
xr = (xl + xu) / 2
it += 1
if xr != 0:
ea = fabs((xr - xr_old) / xr) # approx
cur_iter = fi(xl) * fi(xu)
match cur_iter:
case x if x > 0:
xu = xr
case x if x < 0:
xl = xr
case 0:
ea = 0
if ea <= rel_tol or it >= maxit:
break
root = xr
fx = fi(xr)
return (root, fx, ea, it)
+7 -42
View File
@@ -192,7 +192,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -208,7 +208,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 4,
"metadata": {},
"outputs": [
{
@@ -217,7 +217,7 @@
"np.float64(1.5213797068045676)"
]
},
"execution_count": 19,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -258,51 +258,16 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from typing import Callable\n",
"from numbers import Real\n",
"from math import isclose\n",
"\n",
"\n",
"def bis(\n",
" f: Callable[[Real], Real],\n",
" low: Real,\n",
" high: Real,\n",
" *,\n",
" rel_tol: Real = 1e-9,\n",
" abs_tol: Real = 0,\n",
" max_loop: int = 100,\n",
") -> tuple[Real, int]:\n",
" ldaprx = lambda a, b: isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)\n",
" steps = 0\n",
" fl = f(low)\n",
" fh = f(high)\n",
" # raise ValueError(f\"at {low =} f(x) is {fl}, at {high =} f(x) is {fh} which has the same sign\")\n",
"\n",
" if ldaprx(0, fl):\n",
" return (low, 0)\n",
" elif ldaprx(0, fh):\n",
" return (high, 0)\n",
" else:\n",
" mid = (low + high) / 2\n",
" while (steps := steps + 1) and (max_loop := max_loop - 1) + 1 > 0:\n",
" match f(mid):\n",
" case x if ldaprx(0, x):\n",
" return (mid, steps)\n",
" case x if x < 0:\n",
" low = mid\n",
" case x if x > 0:\n",
" high = mid\n",
" mid = (low + high) / 2\n",
" return (mid, steps)"
"from bis import bis # to new file"
]
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 5,
"metadata": {},
"outputs": [
{
@@ -311,7 +276,7 @@
"(1.5213797068045676, 52)"
]
},
"execution_count": 21,
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}