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