bisection method is a bracketing method that uses intermediate value theorem to bracket an interval that contains local minimum
Given a differentiable function
, if we can fine a closed interval that is defined on, such that and , then exists a value where ( is a critical point).
Once we’re able to find such an interval, we shrink it until we reach a desired level of precision.
Algorithm
Summary
(Forum Notebook Q4) Inputs: a function
, endpoints of an initial interval , a level of precision
- Calculate:
- Cases:
- If
, then TERMINATE since we find the bracket - If
, then set (shrink from right side) - If
, then set (shrink from left side) - If
TERMINATE, else LOOP Output:
Number of steps: (similar to binary search)
Note that this bisection method requires an interval expand_interval
does.
def bisection_method(f, a, b, eps=1e-5):
"""Bisection method to find the minimum of function f within the interval [a, b].
Inputs:
- f: The function to minimize.
- a: Left endpoint of the interval.
- b: Right endpoint of the interval.
- eps: The precision level for termination (default is 1e-5).
Output:
- The bracketed interval [a, b] containing the local minimum.
"""
if a >= b:
a, b = b, a
# If either f'(a) or f'(b) doesn't meet conditions, expand the interval
f_prime_a = central_difference(f, a, h=eps)
f_prime_b = central_difference(f, b, h=eps)
if f_prime_a >= 0 or f_prime_b <= 0:
a, b = expand_interval(f, a, b, h=eps)
while abs(b - a) > eps:
m = (a + b) / 2
f_prime_m = central_difference(f, m, eps)
if f_prime_m > 0:
b = m
else:
a = m
return float(a), float(b)
def expand_interval(f, a, b, w_factor=1.0, h=1e-5):
"""Expands the interval [a, b] until f'(a) < 0 and f'(b) > 0 are satisfied.
Inputs:
- f: The function to minimize.
- a: Left endpoint of the interval.
- b: Right endpoint of the interval.
- w_factor: Factor for expanding the interval (default is 1.0).
Output:
- The new interval [a, b].
"""
while True:
w = abs((b - a) / 2)
f_prime_a = central_difference(f, a, h)
f_prime_b = central_difference(f, b, h)
if f_prime_a < 0 and f_prime_b > 0:
return a, b
a = a - w_factor * w
b = b + w_factor * w
def central_difference(f, x, h=1e-5):
"""Calculate the derivative of f at point x using the central difference method.
Inputs:
- f: function whose derivative is to be calculated
- x: point at which to calculate the derivative
- h: step size for central difference method (default is 1e-5)
Output:
- Approximation of f'(x)
"""
if isinstance(f, sage.symbolic.expression.Expression):
return (f(x = x + h) - f(x = x - h)) / (2 * h)
else:
return (f(x + h) - f(x - h)) / (2 * h)
bisection_method((x-3)^2 + 2, a=0, b=2)