函數求根:全域收斂的牛頓法

 

基本觀念

牛頓法在前面有介紹,若是用多維度的符號,它的關鍵是是利用斜率找出 dx :

我們前面有看過牛頓法的缺點,也就是它利用猜測點處的函數值除以該處的斜率(外帶一個負號)而預測下一步的這種作法,有時會把下一步帶出有效範圍外(在根的旁邊有一個小坑的時候,就容易發生這個現象),或是恰巧陷入往復不止的無窮迴圈。


這些問題,都跟直接使用斜率資訊(即近似函數為線性)預測下一點的步幅有關。換句話說,牛頓法的預測步有時衝得太快太多,即便是落入小坑洞中,只要能正確偵測到是停在坑底的狀況,也都還可以另外猜測點而重新開始,但牛頓法碰到這種狀限則會射出範圍外太遠。

其實,說牛頓法會有衝得太快這種傾向,真的是很貼切。

在前面的單元談牛頓法,有提到找極小的方法並不能套用用在(牛頓法)求根的問題上 (NR 9.6)。在有補救牛頓法之主要缺點的情況下,找極小的策略就可以幫助牛頓法變成一個可靠有效的演算法)。

斜率方向上保證有最小值,只要 dx 夠小的話,大家可直觀想像或參看課本公式。也就是說,我們不能完全相信牛頓法的步輻大小,但方向則可以。如果用公式來解讀,見下面兩式的定義與推導:

這�堜珛馴X的訊息是,牛頓法的方向的確能夠讓原函數的平方變小,也就挾帶了能夠找到根的潛力。如果斜率的方向是對的,我們把牛頓法的步幅走小一點,則保證能夠把原函數的絕對值變小,如此必然讓原函數更接近根了。這個想法引發線性搜尋的策略,也就是在保有原牛頓法方向的情況下,測試並調節其長度以達到對其平方函數找極小。如果陷入無根的小坑,則會再另找起點重新搜尋。

線性搜尋與倒退追蹤 (Line searching and Backtracking) 是兩個主要的策略,細節的公式推導 (9.7.6) ~ (9.7.14) 可參考課文。

 

 

副程式的使用

需要用到以下的副程式或函式,共六個

newt:全域收斂型牛頓法的主要副程式

lnsrch :線性搜尋,由 newt 叫用

fmin :求函數平方的值,是要被極小化的對象

fdjac : 給函數 fvec 就可以得 Jacobian

ludcmp:LU 分解法程式

lubksb:LU 向後取代求解程式

 

使用 newt 的範例主程式,反而相當簡單,只要給初始猜測的向量,如下例:

program newt_main
implicit none
integer n,i,i_again
parameter (n=2)
real x(n)
logical check

 100 write(*,*) 'Type in the vector x(1:',n,') as initial guess :'

read (*,*) (x(i),i=1,n)

c "n" is used to declare x(n) in subroutine newt, we therefore need
c to make "n" an parameter in the main program.

call newt(x,n,check)

write(*,*) 'The resulting root vector is :'
write(*,*) (x(i),i=1,n)

 102 write(*,*) 'Find root again ? (1=YES; 0=NO)'

read(*,*) i_again
if (i_again.eq.1) goto 100
if (i_again.ne.0) goto 102

end

subroutine funcv(n,x,f)
integer n
real x(n),f(n)
f(1) = x(1)**2 + x(2)**2 - 25
f(2) = x(2)
end