def bisect(f, min, max, tol, max_its): """Bisection method The quadratic y(x) = x^2 + 2x -1 has roots -1 - sqrt(2) = -2.4142135623730950488016887242097 and -1 + sqrt(2) = 0.4142135623730950488016887242097. >>> bisect(lambda x: x*x + 2*x - 1, -3, -2, lambda x, y: math.fabs(x-y) < 0.000001, 10) (-2.4142141342163086, -2.4142131805419922, 3) >>> bisect(lambda x: x*x + 2*x - 1, 0, 1, lambda x, y: math.fabs(x-y) < 0.000001, 10) (0.41421318054199219, 0.41421413421630859, 3) """ fmin, fmax = f(min), f(max) if fmin == 0: return (min, min, 0) if fmax == 0: return (max, max, 0) if min >= max: raise RuntimeError, "Arguments in wrong order" if fmin * fmax >= 0: raise RuntimeError, "Root not bracketed" count = max_its if count < 3: count = 0 else: count -= 3 while count and tol(min, max) == 0: mid = (min + max) / 2. fmid = f(mid) if mid == max or mid == min: break if fmid == 0: min = max = mid break elif sign(fmid) * sign(fmin) < 0: max, fmax = mid, fmid else: min, fmin = mid, fmid --count max_its -= count return (min, max, max_its)
def bisect(f, min, max, tol, max_its): """Bisection method The quadratic y(x) = x^2 + 2x -1 has roots -1 - sqrt(2) = -2.4142135623730950488016887242097 and -1 + sqrt(2) = 0.4142135623730950488016887242097. >>> bisect(lambda x: x*x + 2*x - 1, -3, -2, lambda x, y: math.fabs(x-y) < 0.000001, 10) (-2.4142141342163086, -2.4142131805419922, 3) >>> bisect(lambda x: x*x + 2*x - 1, 0, 1, lambda x, y: math.fabs(x-y) < 0.000001, 10) (0.41421318054199219, 0.41421413421630859, 3) """ fmin, fmax = f(min), f(max) if fmin == 0: return (min, min, 0) if fmax == 0: return (max, max, 0) if min >= max: raise RuntimeError, "Arguments in wrong order" if fmin*fmax >= 0: raise RuntimeError, "Root not bracketed" count = max_its if count < 3: count = 0 else: count -= 3 while count and tol(min, max) == 0: mid = (min + max)/2. fmid = f(mid) if mid == max or mid ==min: break if fmid == 0: min = max = mid break elif sign(fmid)*sign(fmin) < 0: max, fmax = mid, fmid else: min, fmin = mid, fmid --count max_its -= count return (min, max, max_its)
def _handle_zero_derivative(f, last_f0, f0, delta, result, guess, min, max): if last_f0 == 0: # must be first iteration if result == min: guess = max else: guess = min last_f0, _ = f(guess) delta = guess - result if sign(last_f0)*sign(f0) < 0: # we've crossed over so move in opposite # direction to last step if delta < 0: delta = (result - min)/2.0 else: delta = (result - max)/2.0 else: # move in same direction of last step if delta < 0: delta = (result - max)/2.0 else: delta = (result - min)/2.0 return (last_f0, delta, result, guess)
def _handle_zero_derivative(f, last_f0, f0, delta, result, guess, min, max): if last_f0 == 0: # must be first iteration if result == min: guess = max else: guess = min last_f0, _ = f(guess) delta = guess - result if sign(last_f0) * sign(f0) < 0: # we've crossed over so move in opposite # direction to last step if delta < 0: delta = (result - min) / 2.0 else: delta = (result - max) / 2.0 else: # move in same direction of last step if delta < 0: delta = (result - max) / 2.0 else: delta = (result - min) / 2.0 return (last_f0, delta, result, guess)