Locating a minimum 求極小值

1.Intro

求函數的極值是科學計算中的基本問題。在介紹求函數極值的方法之前,我們先介紹一種求方程解的方法。

對於方程f(x)=0,滿足如下條件的a,b稱之爲root,

a<b and f(a)>0,f(b)<0

我們可以用如下算法求方程的解:

1.令x=(a+b)/2,計算f(x),如果
    a). f(x)>0,則令a=x
    b). else,令b=x
2.重複1,直到b-a小於指定的精度,最後的x即爲函數的一個根

類似的,求函數極值時我們可以找出滿足如下條件的a,b,c三個值,稱之爲一個bracket

   a < b < c and f (a) > f (b) and f (c) > f (b) 
我們按照如下算法來確定函數的解。
1.給定初始的(a,b,c)
2.沒有聚合(converge)之前:
     a). 在a,b或b,c之前找一點x,計算f(x)
     b). 根據f(x)和f(b)的關係,在a,b,c,x四點中找三點以滿足上面的特性。

2.Note

  1. 不能只在a,b或b,c之間求x,否則可能陷入死循環,無法收斂。我們可以在比較大的區間上求x,以儘早收斂。
  2. 求x的方法有多種,比較直觀的是取中點,黃金分割會稍微快一點。
  3. 這個算法只能算出一個極小值,不能算出最小值。

3.Code

下面是Python實現的黃金分割求極小值的代碼,用sinx做測試。

#-*- coding:utf-8 -*-
import math

def minimise(func,a,b,c,tol):
        GOLD=(3-math.sqrt(5))/2
        if(a<b and b<c and func(a)>func(b) and func(b)<func(c)): #check wether it's valid bracket or not
                while c-a>tol:
                        if b-a>c-b:
                                x=(1-GOLD)*a+GOLD*b # evalute x
                                if(func(x)>func(b)):
                                        a=x
                                else:
                                        c=b
                                        b=x
                        else:
                                x=GOLD*b+(1-GOLD)*c # evalute x
                                if(func(x)>func(b)):
                                        c=x
                                else:
                                        a=b
                                        b=x
                return b,func(b) #return the value of x that minimises func(x) and minimum of func(x)
        else:
                raise Exception,'Invalid bracket.'

def func(x):
        return math.sin(x)

if __name__=="__main__":
        print minimise(func,0,math.pi+1,math.pi*2,0.1**10)

函數的輸出爲:
lonfee:~/tmp$ python minimise.py
(4.712388981257224, -1.0)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章