最優化方法 三分法+黃金分割法+牛頓法


最優化_三等分法+黃金分割法+牛頓法

一、實驗目的

  1. 掌握一維優化方法的集中算法;

  2. 編寫三分法算法

  3. 編寫黃金分割法算法

  4. 編寫牛頓法算法

二、系統設計

三分法

1.編程思路:

三分法用於求解單峰函數的最值。對於單峰函數,在區間內用兩個mid將區間分成三份,這樣的查找算法稱為三分查找,也就是三分法。在區間[a,b]內部取n=2個內等分點,區間被分為n+1=3等分,區間長度縮短率\(=\frac{1}{3}\) .

各分點的坐標為 \(x_k=a+\frac{b-a}{n+1}\cdot k\ \ (k=1,2)\)

然后計算出\(x_1,x_2,\cdots ;y_1,y_2,\cdots;\)
找出\(y_{min}=min\{y_k,k=1,2\}\) ,新區間\((a,b)\Leftarrow (x_{m-1},x_{m+1})\) .

coding中,建立\(left,mid1,mid2,right\) 四個變量用於計算,用新的結果賦值給舊區間即可。

2.算法描述

function [left]=gridpoint(left,right,f)
epsilon=1e-5;				%給定誤差范圍
while((left+epsilon)<right)		 %檢查left,right區間精度
    margin=(right-left)/3;		%將區間三等分,每小段長度=margin
    m1=left+margin;			%left-m1-m2-right,三等分需要兩個點
    m2=m1+margin;			%m2=left+margin+margin
    if(f(m1)<=f(m2))		
        right=m2;			%離極值點越近,函數值越小(也有可能越大,視函數而定)。
    else				%當f(m1)>f(m2),m2離極值點更近。縮小區間范圍,逼近極值點
        left=m1;			%所以令left=m1.
    end
end					%這是matlab的.m文件,不用寫return.

黃金分割法

1.編程思路

三分法進化版,區間長度縮短率\(\approx 0.618\).

在區間\([a,b]\)上取兩個內試探點,\(p_i,q_i\) 要求滿足下面兩個條件:

\(1.[a_i,q_i]與[p_i,b_i]的長度相同,即b_i-p_i=q_i-a_i;\)

\(2.區間長度的縮短率相同,即b_{i+1}-a_{i+1}=t(b_i-a_i)]\)

image

2.算法描述

自己編寫的:
function [s,func_s,E]=my_golds(func,left,right,delta)
tic
%輸入:    func:目標函數,left,right:初始區間兩個端點
%          delta:自變量的容許誤差
%輸出:    s,func_s:近似極小點和函數極小值
%           E=[ds,dfunc] ds,dfunc分別為s和dfunc的誤差限
%0.618法的改進形式:每次縮小區間時,同時比較兩內點和兩端點處的函數值。
%當左邊第一個或第二個點是這四個點中函數值最小的點時,丟棄右端點,構成新的搜索區間
%否則,丟棄左端點。
%left---------|--mu       lambda,mu為了兩個試探點,且lambda<mu
%     lambda--|------right
%根據定理2.1.4 
%若f(lambda_k)<=f(mu_k) 
%   則left_(k+1)=a_k,        right_(k+1)=mu_k
%若f(lambda_k)>f(mu_k)  
%   則left_(k+1)=lambda_k,   right_(k+1)=right_k

t=(sqrt(5)-1)/2;h=right-left; %區間長度縮短率t
lambda=left+(1-t)*h;
mu=left+t*h;
func_left=feval(func,left);
func_right=feval(func,right);
func_lambda=feval(func,lambda);
func_mu=feval(func,mu);
k=1;
G=[func_left,func_lambda,func_mu,func_right];
while(abs(right-left)>delta)
    func_t=min(G);
    if(func_t==func_left|func_t==func_lambda)
        %當func_left,func_lambda較小時,丟棄右端點,即t<3,轉步4
        right=mu;
        func_right=func_mu;
        mu=lambda;
        func_mu=func_lambda;
        h=right-left;%漏行!!!!!!!!!!!!
        lambda=left+(1-t)*h; 
        func_lambda=feval(func,lambda);%漏行!!!!!!!!        
    else %當func_mu,func_right較小時,丟棄左端點,即t不<3,轉步3
        left=lambda;
        func_left=func_lambda;
        lambda=mu;
        func_lambda=func_mu;
        h=right-left;
        mu=left+t*h;
        func_mu=feval(func,mu);
    end
    k=k+1;
    G=[func_left,func_lambda,func_mu,func_right];
end
ds=abs(right-left);dfunc=abs(func_right-func_left);
if(func_lambda<=func_mu)
    s=lambda;func_s=func_lambda;
else
    s=mu;func_s=func_mu;
end
E=[ds,dfunc];toc;  
書上例程:
%黃金分割法(0.618)
function [s,phi_s,k,G,E]=golds(phi,left,right,delta,epsilon)
tic;
%輸入:phi:目標函數;left,right:搜索區間兩個端點
% delta,epsilon:自變量和函數值的容許誤差
%輸出:s,phi_s:近似極小點和極小值,G為n*4矩陣
% 其第k行分別為left,m1,m2,right的第k次迭代值[ak,m1k,m2k,nk]
% E=[ds,dphi] ,分別為s,phis的誤差限
t=(sqrt(5)-1)/2;
h=right-left;
phi_left=feval(phi,left);phi_right=feval(phi,right);		
%[y1,y2,...] = feval(fhandle,x1,x2,...,xn)
m1=left+(1-t)*h;m2=left+t*h;
phi_m1=feval(phi,m1);phi_m2=feval(phi,m2);
k=1;
G(k,:)=[left,m1,m2,right];
while((abs(phi_m2-phi_m1)>epsilon)|(h>delta))
	if(phi_m1<phi_m2)
		right=m2;phi_right=phi_m2;
		m2=m1;phi_m2=phi_m1;
		h=right-left;
		m1=left+(1-t)*h;phi_m1=feval(phi,m1);
	else
		left=m1;phi_left=phi_m1;
		m1=m2;phi_m1=phi_m2;
		h=right-left;
		m2=left+t*h;phi_m2=feval(phi,m2);
	end
	k=k+1;G(k,:)=[left,m1,m2,right];
end
ds=abs(right-left);dphi=abs(phi_right-phi_left);
if(phi_m1<=phi_m2)
	s=m1;phi_s=phi_m1;
else
	s=m2;phi_s=phi_m2;
end
E=[ds,dphi]	;toc;

牛頓法

1.編程思路

牛頓法用於求解無約束優化問題,基本思想是用迭代點\(x_k\)處的一階導數(梯度)和二階導數(Hessian陣)對目標函數進行二次函數近似,然后用二次模型的極小點作為新的迭代點,並不斷重復,直到求得滿足精度要求的近似極小點。

其迭代公式為:\(x_{k+1}=x_k-G^{-1}_kg_k\)
image
image
image
image
image

【書上的推導看得腦殼痛,還是PPT簡單易懂】

image

2.算法描述

DIY:
function [min,k]=NR1(f,x0,epsilon,var)
%x0表示起始點
%f為函數
%epsilon表示誤差范圍
%var表示函數變量名
error=epsilon+1;
k=0;
diff(f)
while((error>epsilon)&(k<1000))
    if(subs(diff(f),var,x0)==0)
        break
    end
    x1=x0-subs(diff(f),var,x0)/subs(diff(f,2),var,x0);
    x1=double(x1);
    error=abs(x1-x0);
    x0=x1;k=k+1;
end
min=x0;

例程:

  • 修正牛頓法

  • 阻尼牛頓法

    function [x,val,k]=dampnm(fun,gfun,Hess,x0)
    %功能:用阻尼牛頓法求解無約束問題:min f(x)
    %輸入:x0是初始點,fun,gfun,Hess分別求目標函數值,梯度,Hessian陣的函數
    %輸出:x,val分別為近似最優點和最優值,k為迭代次數
    maxk=100;		%給出最大迭代次數
    rho=0.55;sigma=0.4;
    k=0;epsilon=1e-5;
    while(k<maxk)
    	gk=feval(gfun,x0);	%計算梯度
    	Gk=feval(Hess,x0);	%計算Hessian陣
    	dk=-Gk/gk;			%解方程組Gk*dk=-gk,計算搜索方向
    	if(norm(gk)<epsilon)%n=norm(A,p),計算矩陣范數
    		break;
    	end
    	m=0;mk0;
    	while(m<20)			%用Armijo搜索求步長
    		if(feval(fun,x0+rho^m*dk)<feval(fun,x0)+sigma*rho^m*gk'*dk)
    			mk=m;
    			break;
    		end
    		m=m+1;
    	end
    	x0=x0+rho^mk*dk;
    	k=k+1;
    end
    x=x0;
    val=feval(fun,x);
    

    舉例:求解無約束優化問題:\(\mathop{min}\limits_{x\in\mathbb{R}^2} f(x)=100(x^2_1-x_2)^2+(x_1-1)^2\)

    minx∈R2⁡f(x)=100(x12−x2)2+(x1−1)2
    \mathop{min}\limits_{x\in\mathbb{R}^2} f(x)=100(x^2_1-x_2)^2+(x_1-1)^2 
    

    先建立兩個分別計算目標函數和梯度的.m文件

    function f=fun(x)
    
    function g=gfun(x)
    

    再建立求\(Hessian\)陣的.m文件

    function He=Hess(x)
    n=length(X);
    He=zeros(n,n);
    He=[1200*x(1)^2-400*x(2)+2,-400*x(1);
    	-400*x(1),				200		];
    

    終止准則取為\(\parallel \nabla f(x_k)\parallel\leqslant10^{-5}\)

    ∥∇f(xk)∥⩽10−5 \parallel \nabla f(x_k)\parallel\leqslant10^{-5}
    

    程序調用方式為:

    \(x0=[-1.2,1]'\)

    \([x,val,k]=dampnm('fun','gfun','Hess',x0)\)

三、測試

三分法

image

黃金分割法

image

牛頓法

image

四、總結

matlab 不用聲明變量,科學計算的時候很方便,不過沒聲明的變量編譯默認為0,可能會帶來奇怪的bug.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM