web-dev-qa-db-ja.com

Python)で二分法を実行する方法

次のルートを決定するために二分法を実行するPythonプログラムを作成したいと思います。

f(x) = -26 + 85x - 91x2 +44x3 -8x4 + x5

二分法は、多項式f(x)の根を推定するための数値的方法です。

答えを教えてくれる利用可能な擬似コード、アルゴリズム、またはライブラリはありますか?

7
Scrubatpython

基本的なテクニックを示すコードは次のとおりです。

>>> def samesign(a, b):
        return a * b > 0

>>> def bisect(func, low, high):
    'Find root of continuous function where f(low) and f(high) have opposite signs'

    assert not samesign(func(low), func(high))

    for i in range(54):
        midpoint = (low + high) / 2.0
        if samesign(func(low), func(midpoint)):
            low = midpoint
        else:
            high = midpoint

    return midpoint

>>> def f(x):
        return -26 + 85*x - 91*x**2 +44*x**3 -8*x**4 + x**5

>>> x = bisect(f, 0, 1)
>>> print x, f(x)
0.557025516287 3.74700270811e-16
8

以前のStackOverflowの質問 here で解決策を見ることができます scipy.optimize.bisect を使用します。または、目的が学習である場合は、 二分法に関するウィキペディアのエントリ の擬似コードは、前の質問のコメント投稿者が示唆しているように、Pythonで独自の実装を行うための優れたガイドです。

4
Simon

私の実装は他のソリューションよりも一般的でありながらシンプルです:(およびパブリックドメイン)

def solve(func, x = 0.0, step = 1e3, prec = 1e-10):
    """Find a root of func(x) using the bisection method.

    The function may be rising or falling, or a boolean expression, as long as
    the end points have differing signs or boolean values.

    Examples:
        solve(lambda x: x**3 > 1000) to calculate the cubic root of 1000.
        solve(math.sin, x=6, step=1) to solve sin(x)=0 with x=[6,7).
    """
    test = lambda x: func(x) > 0  # Convert into bool function
    begin, end = test(x), test(x + step)
    assert begin is not end  # func(x) and func(x+step) must be on opposite sides
    while abs(step) > prec:
        step *= 0.5
        if test(x + step) is not end: x += step
    return x
1

許容範囲あり:

# there is only one root
def fn(x):
 return x**3 + 5*x - 9
 # define bisection method
def bisection( eq, segment, app = 0.3 ):
 a, b = segment['a'], segment['b']
 Fa, Fb = eq(a), eq(b)
 if Fa * Fb > 0:
  raise Exception('No change of sign - bisection not possible')   
 while( b - a > app ): 
  x = ( a + b ) / 2.0
  f = eq(x)
  if f * Fa > 0: a = x
  else: b = x  
 return x
 #test it
print bisection(fn,{'a':0,'b':5}, 0.00003) # => 1.32974624634

ライブ: http://repl.it/k6q

0
Roman Zhak