修正牛顿法最优化C++程序
常用无约束最优化方法(一)
项目三 常用无约束最优化方法(一)[实验目的]编写最速下降法、Newton 法(修正Newton 法)的程序。
[实验学时]2学时[实验准备]1.掌握最速下降法的思想及迭代步骤。
2.掌握Newton 法的思想及迭代步骤;3.掌握修正Newton 法的思想及迭代步骤。
[实验内容及步骤]编程解决以下问题:【选作一个】1.用最速下降法求22120min ()25[22]0.01T f X x x X ε=+==,,,.2.用Newton 法求22121212min ()60104f X x x x x x x =--++-,初始点0[00]0.01T X ε==,,.最速下降法Matlab 程序:clc;clear;syms x1 x2;X=[x1,x2];fx=X(1)^2+X(2)^2-4*X(1)-6*X(2)+17;fxd1=[diff(fx,x1) diff(fx,x2)];x=[2 3];g=0;e=0.0005;a=1;fan=subs(fxd1,[x1 x2],[x(1) x(2)]);g=0;for i=1:length(fan)g=g+fan(i)^2;endg=sqrt(g);step=0;while g>estep=step+1;dk=-fan;%点x(k)处的搜索步长ak=((2*x(1)-4)*dk(1)+(2*x(2)-6)*dk(2))/(dk(1)*dk(2)-2*dk(1)^2-2*dk(2)^2);xu=x+ak*dk;x=xu;%输出结果optim_fx=subs(fx,[x1 x2],[x(1) x(2)]);fprintf(' x=[ %d %d ] optim_fx=%d\n',x(1),x(2),optim_fx);%计算目标函数点x(k+1)处一阶导数值fan=subs(fxd1,[x1 x2],[x(1) x(2)]);g=0;for i=1:length(fan)g=g+fan(i)^2;endg=sqrt(g);end%输出结果optim_fx=subs(fx,[x1 x2],[x(1) x(2)]);fprintf('\n最速下降法\n结果:\n x=[ %d %d ] optim_fx=%d\n',x(1),x(2),optim_fx); c++程序#include<stdio.h>#include<iostream.h>#include<iomanip.h>#include<math.h>float goldena(float x[2],float p[2]){float a;a=-1*(x[0]*p[0]+4*x[1]*p[1])/(p[0]*p[0]+4*p[1]*p[1]);return a;}void main(){float a=0,x[2],p[2],g[2]={0,0},e=0.001,t;int i=0;x[0]=1.0;x[1]=1.0;p[0]=2*x[0];p[1]=8*x[1];g[0]=-p[0];g[1]=-p[1];printf("\n\n");while(sqrt(g[0]*g[0]+g[1]*g[1])>e&&i<=100){i=i+1;a=goldena(x,g);x[0]=x[0]+a*g[0];x[1]=x[1]+a*g[1];p[0]=2*x[0];p[1]=8*x[1];g[0]=-p[0];g[1]=-p[1];t=float(sqrt(g[0]*g[0]+g[1]*g[1]));printf("第%d次t=%f x1=%f\tx2=%f\ta=%f\n",i,sqrt(g[0]*g[0]+g[1]*g[1]),x[0],x[1],a);}printf("\n最优解为:x1=%f,x2=%f\n最优值为y=%f\n",x[0],x[1],x[0]*x[0]+4*x[1]*x[1]); }。
修正牛顿法
《数值优化》实验报告实验[2] [修正牛顿法]专业学号姓名日期1 实验目的练习matlab程序设计,深刻理解修正牛顿法,通过计算机计算迭代计算近似解2 实验内容利用程序求解无约束优化问题f(x)=100(x1^2-x2^2)^2+(x1-1)^2在R^2上的最小值3 算法设计Function[x,val,k]=revisenm(fun,gfun,hess,x0)功能:用牛顿修正法求解无约束问题:min f()输入:x0是初始点,fun gfun hess分别是求目标函数值梯度hesse矩阵函数输入:x val 分别是近似最优点和最优值,k是迭代次数4 程序代码(fun,x0)+sigma*rho^m*g'*d)mk=m;break;end;m=m+1;end;x0=x0+rho^mk*d;val=feval (fun,x0);g0=g; d0=d;k=k+1;end;x=x0;val=feval (fun,x)function f=fun(x)f=100*(x(1)*x(1)-x(2)*x(2))^2+(x(1)-1)^2;end;function g=gfun(x)g=[400*x(1)*(x(1)^2-x(2))+2*(x(1)-1),-200*(x(1)^2-x(2))]'; end;5 运行结果有未知错误,暂时没有运行出正确结果6 结果分析选初始值x0=[-1.2 1]没有运行出正确结果。
程序可以运行,但是没有正确结果,程序存在bug 修正牛顿法避免了牛顿法的缺陷,使得在每一个迭代点处都保证f下降。
c语言编写的牛顿拉夫逊法解潮流程序
c语言编写的牛顿拉夫逊法解潮流程序闲来无事,最近把牛拉法用c语言重写一遍,和matlab相比,c语言编写潮流程序最大的难点在于矩阵求逆,我使用的求逆方法是初等行变换法,程序段如下:#include<stdio.h>#define N 3void main(){int i,j,k;float t;float Jacob[N][N]={{1,2,2},{1,3,4},{2,3,4}};//欲进行求逆的矩阵float inv_J[N][N];//逆矩阵存储于此//初始化inv_J[N][N]for(i=0;i<N;i++)for(j=0;j<N;j++){if(i!=j)inv_J[i][j]=0;elseinv_J[i][j]=1;}//将原矩阵化简为对角阵for(i=0;i<N;i++){for(j=0;j<N;j++){if(i!=j){t=Jacob[j][i]/Jacob[i][i];for(k=0;k<N;k++){Jacob[j][k]-=Jacob[i][k]*t;inv_J[j][k]-=inv_J[i][k]*t;}}}}//原矩阵各对角元素化为1,画出逆矩阵for(i=0;i<N;i++)if(Jacob[i][i]!=1){t=Jacob[i][i];for(j=0;j<N;j++)inv_J[i][j]=inv_J[i][j]/t;}//输出逆矩阵for(i=0;i<N;i++){for(j=0;j<N;j++)printf("%9.4f",inv_J[i][j]);printf("\n");}}整个程序为://牛拉法解潮流程序#include<stdio.h>#include<math.h>#define N 4 //节点数#define n_PQ 2 //PQ节点数#define n_PV 1 //PV节点数#define n_br 5 //串联支路数void main(){void disp_matrix(float *disp_p,int disp_m,int disp_n); //矩阵显示函数float Us[2*N]={1.0,0,1.0,0,1.05,0,1.05,0}; //电压初值float Ps[N]={0,-0.5,0.2}; //有功初值float Qs[N]={0,-0.3}; //无功初值float G[N][N],B[N][N]; //各几点电导电纳struct //阻抗参数{int nl; //左节点int nr; //右节点float R; //串联电阻值float X; //串联电抗值float Bl; //左节点并联电导float Br; //右节点并联电纳}ydata[n_br]={{1,2,0,0.1880,-0.6815,0.6040},{1,3,0.1302,0.2479,0.0129,0.0129},{1,4,0.1736,0.3306,0.0172,0.0172},{3,4,0.2603,0.4959,0.0259,0.0259},{2,2,0,0.05,0,0}};float Z2; //Z^2=R^2+X^2 各串联阻抗值的平方float e[N],f[N],dfe[2*(N-1)]; //e,f存储电压的x轴分量和y轴分量,dfe存储电压修正值float mid1[N],mid2[N],dS[2*(N-1)]; //mid1、mid2存储计算雅克比行列式对角线元素的中间值,dS存储PQU的不平衡量float Jacob[2*(N-1)][2*(N-1)],inv_J[2*(N-1)][2*(N-1)]; //雅克比行列式float dPQU=1.0; //PQU不平衡量最大值int kk=0; //迭代次数int i,j,k;float t;float Pij[n_br]; //存储线路i->j的有功float Qij[n_br]; //存储线路i->j的无功float Pji[n_br]; //存储线路j->i的有功float Qji[n_br]; //存储线路j->i的无功float dPij[n_br]; //存储线路i->j的有功损耗float dQij[n_br]; //存储线路i->j的无功损耗float AA,BB,CC,DD; //存储线路潮流计算时的中间值//形成导纳矩阵--------------------------------------------------------------------------------------------------for(i=0;i<N;i++)for(j=0;j<N;j++){G[i][j]=0;B[i][j]=0;}for(i=0;i<n_br;i++){if(ydata[i].nl!=ydata[i].nr){Z2=(ydata[i].R)*(ydata[i].R)+(ydata[i].X)*(ydata[i].X);//串联阻抗等效导纳值//非对角元素G[ydata[i].nl-1][ydata[i].nr-1]=(-ydata[i].R)/Z2;B[ydata[i].nl-1][ydata[i].nr-1]=ydata[i].X/Z2;G[ydata[i].nr-1][ydata[i].nl-1]=(-ydata[i].R)/Z2;B[ydata[i].nr-1][ydata[i].nl-1]=ydata[i].X/Z2;//对角元素G[ydata[i].nl-1][ydata[i].nl-1]+=ydata[i].R/Z2;G[ydata[i].nr-1][ydata[i].nr-1]+=ydata[i].R/Z2;B[ydata[i].nl-1][ydata[i].nl-1]+=(-ydata[i].X/Z2);B[ydata[i].nr-1][ydata[i].nr-1]+=(-ydata[i].X/Z2);//并联导纳等效导纳值B[ydata[i].nl-1][ydata[i].nl-1]+=ydata[i].Bl;B[ydata[i].nr-1][ydata[i].nr-1]+=ydata[i].Br;}else{G[ydata[i].nl-1][ydata[i].nr-1]+=ydata[i].R;B[ydata[i].nl-1][ydata[i].nr-1]+=ydata[i].X;}}printf("G=\n");disp_matrix(*G,N,N);printf("B=\n");disp_matrix(*B,N,N);//分离e,ffor(i=0;i<N;i++){e[i]=Us[2*i];f[i]=Us[2*i+1];}//主程序=============================================================================== ======================while(dPQU>0.00001){//计算功率不平衡量for(i=0;i<N-1;i++){mid1[i]=0;mid2[i]=0;for(j=0;j<N;j++){mid1[i]=mid1[i]+G[i][j]*e[j]-B[i][j]*f[j];mid2[i]=mid2[i]+G[i][j]*f[j]+B[i][j]*e[j];}dS[2*i]=Ps[i]-(e[i]*mid1[i]+f[i]*mid2[i]);if(i<n_PQ)dS[2*i+1]=Qs[i]-(f[i]*mid1[i]-e[i]*mid2[i]);elsedS[2*i+1]=Us[2*i]*Us[2*i]-(e[i]*e[i]+f[i]*f[i]);}dPQU=0;for(i=0;i<2*(N-1);i++){if(dS[i]<0&&dPQU<-dS[i])dPQU=-dS[i];else if(dS[i]>0&&dPQU<dS[i])dPQU=dS[i];}if(dPQU>0.00001){kk++;//形成雅克比行列式-------------------------------------------------------------------------------------------------for(i=0;i<2*(N-1);i++)for(j=0;j<2*(N-1);j++)Jacob[i][j]=0;for(j=0;j<N-1;j++){//求H,Nfor(i=0;i<N-1;i++){if(i!=j){Jacob[2*i][2*j]=B[i][j]*e[i]-G[i][j]*f[i];Jacob[2*i][2*j+1]=-G[i][j]*e[i]-B[i][j]*f[i];}else{Jacob[2*i][2*i]=B[i][i]*e[i]-G[i][i]*f[i]-mid2[i];Jacob[2*i][2*i+1]=-G[i][j]*e[i]-B[i][j]*f[i]-mid1[i];}}//求J,Lfor(i=0;i<n_PQ;i++){if(i!=j){Jacob[2*i+1][2*j]=G[i][j]*e[i]+B[i][j]*f[i];Jacob[2*i+1][2*j+1]=B[i][j]*e[i]-G[i][j]*f[i];}else{Jacob[2*i+1][2*i]=G[i][j]*e[i]+B[i][j]*f[i]-mid1[i];Jacob[2*i+1][2*i+1]=B[i][j]*e[i]-G[i][j]*f[i]+mid2[i];}}//求R,Sfor(i=n_PQ;i<N-1;i++){if(i==j){Jacob[2*i+1][2*i]=-2*f[i];Jacob[2*i+1][2*i+1]=-2*e[i];}}}//雅克比行列式求逆-----------------------------------------------------------------------------------for(i=0;i<2*(N-1);i++)for(j=0;j<2*(N-1);j++){if(i!=j)inv_J[i][j]=0;elseinv_J[i][j]=1;}for(i=0;i<2*(N-1);i++){for(j=0;j<2*(N-1);j++){if(i!=j){t=Jacob[j][i]/Jacob[i][i];for(k=0;k<2*(N-1);k++){Jacob[j][k]-=Jacob[i][k]*t;inv_J[j][k]-=inv_J[i][k]*t;}}}}for(i=0;i<2*(N-1);i++)if(Jacob[i][i]!=1){t=Jacob[i][i];for(j=0;j<2*(N-1);j++)inv_J[i][j]=inv_J[i][j]/t;}//求电压修正值--------------------------------------------------------------------------------------------for(i=0;i<2*(N-1);i++){dfe[i]=0;for(j=0;j<2*(N-1);j++)dfe[i]-=inv_J[i][j]*dS[j];}for(i=0;i<N-1;i++){e[i]+=dfe[2*i+1];f[i]+=dfe[2*i];}}elsebreak;}//循环结束---------------------------------------------------------------------------------------------------------------//求平衡节点功率---------------------------------------------------------------------------------------------------mid1[N-1]=0;mid2[N-1]=0;for(j=0;j<N;j++){mid1[N-1]=mid1[N-1]+G[N-1][j]*e[j]-B[N-1][j]*f[j];mid2[N-1]=mid2[N-1]+G[N-1][j]*f[j]+B[N-1][j]*e[j];}Ps[N-1]=e[N-1]*mid1[N-1]+f[N-1]*mid2[N-1];Qs[N-1]=f[N-1]*mid1[N-1]-e[N-1]*mid2[N-1];for(i=n_PQ;i<N-1;i++)Qs[i]=f[i]*mid1[i]-e[i]*mid2[i];//---------------------------------------------------------------------------------------------------------------------------// 显示输出结果printf("kk=%d\n",kk);printf("P=");for(i=0;i<N;i++)printf("%9.4f",Ps[i]);printf("\nQ=");for(i=0;i<N;i++)printf("%9.4f",Qs[i]);printf("\ne=");for(i=0;i<N;i++)printf("%9.4f",e[i]);printf("\nf=");for(i=0;i<N;i++)printf("%9.4f",f[i]);printf("\n");//求线路上的潮流//计算S[i][j]for(i=0;i<n_br;i++){if(ydata[i].nl!=ydata[i].nr){Z2=(ydata[i].R)*(ydata[i].R)+(ydata[i].X)*(ydata[i].X);AA=-f[ydata[i].nl-1]*ydata[i].Bl+(e[ydata[i].nl-1]-e[ydata[i].nr-1])*ydata[i].R/Z2+(f[ydata[i].nl-1]-f[ydata[i].nr-1])*ydata[i].X/Z2;BB=-e[ydata[i].nl-1]*ydata[i].Bl-(f[ydata[i].nl-1]-f[ydata[i].nr-1])*ydata[i].R/Z2+(e[ydata[i].nl-1]-e[ydata[i].nr-1])*ydata[i].X/Z2;Pij[i]=e[ydata[i].nl-1]*AA-f[ydata[i].nl-1]*BB;Qij[i]=e[ydata[i].nl-1]*BB+f[ydata[i].nl-1]*AA;printf("S[%d][%d]=%9.4f+j%9.4f\n",ydata[i].nl,ydata[i].nr,Pij[i],Qij[i]);dPij[i]=Pij[i]+Pji[i];dQij[i]=Qij[i]+Qji[i];}}printf("\n");//计算S[j][i]for(i=0;i<n_br;i++){if(ydata[i].nl!=ydata[i].nr){Z2=(ydata[i].R)*(ydata[i].R)+(ydata[i].X)*(ydata[i].X);CC=-f[ydata[i].nr-1]*ydata[i].Br+(e[ydata[i].nr-1]-e[ydata[i].nl-1])*ydata[i].R/Z2+(f[ydata[i].nr-1]-f[ydata[i].nl-1])*ydata[i].X/Z2;DD=-e[ydata[i].nr-1]*ydata[i].Br-(f[ydata[i].nr-1]-f[ydata[i].nl-1])*ydata[i].R/Z2+(e[ydata[i].nr-1]-e[ydata[i].nl-1])*ydata[i].X/Z2;Pji[i]=e[ydata[i].nr-1]*CC-f[ydata[i].nr-1]*DD;Qji[i]=e[ydata[i].nr-1]*DD+f[ydata[i].nr-1]*CC;printf("S[%d][%d]=%9.4f+j%9.4f\n",ydata[i].nr,ydata[i].nl,Pji[i],Qji[i]);}}printf("\n");//计算dS[i][j]for(i=0;i<n_br;i++){if(ydata[i].nl!=ydata[i].nr){dPij[i]=Pij[i]+Pji[i];dQij[i]=Qij[i]+Qji[i];printf("dS[%d][%d]=%9.4f+j%9.4f\n",ydata[i].nl,ydata[i].nr,dPij[i],dQij[i]);}}printf("\n");}//主程序结束//矩阵显示函数=============================================================================== =========================void disp_matrix(float *disp_p,int disp_m,int disp_n){int i,j;for(i=0;i<disp_m;i++){for(j=0;j<disp_n;j++)printf("%9.4f",*(disp_p+i*disp_m+j));printf("\n");}printf("\n");}。
最优化方法之修正牛顿法matlab源码(含黄金分割法寻找步长)
revisenewton.msyms x1 x2 x3 xx;% f = x1*x1 +x2*x2 -x1*x2 -10*x1 -4*x2 + 60 ; % f = x1^2 + 2*x2^2 - 2*x1 *x2 -4*x1 ;f = 100 * (x1^2 - x2^2) + (x1 -1 )^2 ;hessen = jacobian(jacobian(f , [x1,x2]),[x1,x2]) ; gradd = jacobian(f , [x1,x2]) ;X0 = [0,0]' ;B = gradd' ;x1 = X0(1);x2 = X0(2);A = eval(gradd) ;% while sqrt( A(1)^2 + A(2)^2) >0.1i=0;while norm(A) >0.1i = i+1 ;fprintf('the number of iterations is: %d\n', i)if i>10break;endB1 = inv(hessen)* B ;B2= eval(B1);% X1 = X0 - B2% X0 = X1 ;f1= x1 + xx * B2(1);f2= x2 + xx* B2(2);% ff = norm(BB) ?syms x1 x2 ;fT=[subs(gradd(1),x1,f1),subs(gradd(2),x2,f2)];ff = sqrt((fT(1))^2+(fT(2))^2);MinData = GoldData(ff,0,1,0.01);x1 = X0(1);x2 = X0(2);x1 = x1 + MinData * B2(1)x2 = x2 + MinData * B2(2)A = eval(gradd)EndGoldData.mfunction MiniData = GoldData( f,x0,h0,eps) syms xx;if nargin==3eps=1.0e-6;end[minx,maxx]=minJT(f,x0,h0,eps);MiniData = Gold(f,minx,maxx,0.001 ) ;minJT.mfunction [minx,maxx]=minJT(f,x0,h0,eps)%目标函数:f;%初始点:x0;%初始步长:h0;%精度:eps;%目标函数取包含极值的区间左端点:minx; %目标函数取包含极值的区间又端点:maxx; syms xx;format long;if nargin==3eps=1.0e-6;endx1=x0;k=0;h=h0;while 1x4=x1+h; %试探步k=k+1;% f4=subs(f,findsym(f),x4);% f1=subs(f,findsym(f),x1);xx =x4;f4 = eval(f);xx=x1;f1 = eval(f);if f4<f1x2=x1;x1=x4;f2=f1;f1=f4;h=2*h; %加大步长elseif k==1h=-h; %反向搜索x2=x4;f2=f4;elsex3=x2;x2=x1;x1=x4;break;endendendminx=min(x1,x3);maxx=x1+x3-minx;format short;Gold.mfunction Mini=Gold(f,a0,b0,eps) syms x;format long;syms xx;u=a0+0.382*(b0-a0);v=a0+0.618*(b0-a0);k=0;a=a0;b=b0;array(k+1,1)=a;array(k+1,2)=b; while((b-a)/(b0-a0)>=eps)Fu=subs(f,xx,u);Fv=subs(f,xx,v);if(Fu<=Fv)b=v;v=u;u=a+0.382*(b-a);k=k+1;elseif(Fu>Fv)a=u;u=v;v=a+0.618*(b-a);k=k+1;endarray(k+1,1)=a;array(k+1,2)=b; endxxMini=(a+b)/2;。
最优化牛顿法
Step 1. 给定初始点x0 ,正定矩阵H0 ,精度 0,k : 0
Step 2. 计算搜索方向d k H kf ( x k );
step 3. 令 x k1 x k tk d k , 其中 tk : f ( x k tk d k ) min f ( x k t d k )。
(sk Hk yk
Hk )T yk
yk
)T
SR1校正:H k1
Hk
(sk
H k yk )(sk H k (sk H k yk )T yk
yk )T
SR1校正具有二次终止性, 即对于二次函数,它不 需要线搜索,
而具有n步终止性质 H n G 1 .
定理
设s0 , s1 ,
,
s
n
线性无关,那么对二次
满足上述方程的解很多 ,我们可以如下确定一 组解:
k uk ukT yk sk kvkvkT yk Hk yk
这样,我们可以取:
uk sk ,
k ukT y k 1,
vk H k y k , k vkT y k 1。
即:
uk sk , vk Hk yk ,
k
1 skT y k
x k1 x k t k H k f ( x k )
xk1 xk tk Hkf ( xk )
H k I时 梯度法 最速下降方向 d k f ( x k ) , 度量为 x xT I x
H k Gk1时 Newton法 Newton方向 d k Gk1f (xk ), 度量为 x xT Gk x
当Gk 0 时,有 f ( xk )T d k f ( xk )T Gk1gk gkT Gk1gk 0 ,
Newton法
实验名称 Newton 法及修正Newton 法一、 实验目的:Newton 法及修正Newton 法二、 实验要求:理解Newton 法及修正Newton 法算法的思想,利用计算机编写出此算法的程序。
三、 实验学时数:2学时四、 实验类别:基础实验五、 实验内容:1)、 用Newton 法求解2122212141060)(min x x x x x x x f -++--=,初始点[]01.0,0,00==εT X2)、 用Newton 法求解10)1(2)1(4)(min 212221+++-++=x x x x x f ,初始点[]01.0,0,00==εT X六、 实验报告a) 实验程序流程图b)主要模块代码#include<math.h>#include<stdio.h># define eps 0.01double f (double coe[], double x[]) //返回待求函数的函数值{returncoe[0]*pow(x[0],2)+coe[1]*pow(x[1],2)+coe[2]*x[0]*x[1]+coe[3]*x[0]+coe[4]*x[1]+coe[5] ;}void grads (double coe[], double x[],double grads_x[]) //求解函数的梯度{grads_x[0] = 2*coe[0]*x[0]+coe[2]*x[1]+coe[3];grads_x[1] = 2*coe[1]*x[1]+coe[2]*x[0]+coe[4];}void H (double coe[], double h[])//求解海赛矩阵{h[0] = 2.0*coe[0];h[1] = coe[2];h[2] = coe[2];h[3] = 2.0*coe[1];}void inverseH (double h[], double inverseh[])//求解海赛矩阵的逆矩阵{double deter;deter = h[0]*h[3]-h[1]*h[2];inverseh[0] = h[3]/deter;inverseh[1] = -h[1]/deter;inverseh[2] = -h[2]/deter;inverseh[3] = h[0]/deter;}void main()//主函数{double coe[6] = {1,1,-1,-10,-4,60},x[2] = {0 , 0},grads_x[2],h[4],inverseh[4],fx = 0;grads(coe, x, grads_x);//求梯度while(sqrt(pow(grads_x[0],2)+pow(grads_x[1],2))-eps>0){H(coe, h);//求海赛矩阵inverseH(h, inverseh);//海赛矩阵求逆x[0] = x[0]-(inverseh[0]*grads_x[0]+inverseh[1]*grads_x[1]);x[1] = x[1]-(inverseh[2]*grads_x[0]+inverseh[3]*grads_x[1]);grads(coe, x, grads_x);}fx = f(coe, x);printf("最优解为:");for(int i=0;i<2;i++){printf("\n%f\n",x[i]);}printf("\n最优值为:");printf("\nfx=%f \n",fx);}c)实例计算结果d)收获体会用Newton法求解,只经一轮迭代就得到最优解。
修正牛顿法求解非约束问题C程序编程
修正牛顿法求解非约束问题C程序编程————————————————————————————————作者:————————————————————————————————日期:一 题目利用修正牛顿法求函数f(x1,x2)=4(x1+1)^2+2(x2-1)^2+x1+x2+10的极小值点。
二 修正牛顿法基本思想:1) 给定初始点0x ,收敛精度ε,置0k ←。
2) 计算()k f x ∇、 2()k f x ∇、21(())k f x -∇和21(())()k k k d f x f x -=-∇∇3) 求1k k k k x x d α+=+,其中k α为沿k d 进行一维搜索的最佳步长。
4) 检查收敛精度。
若1k k n x x ε+-<,则*1k x x +=,停机;否则置1k k ←+,返回步骤2,继续进行进行搜索。
改进后的修正牛顿法程序框图如下: 开始0,x ε给定0k ←1?k k n x x ε+-<*1k x x +=1k k =+是否结束12()()k k k f x f x d -←-∇∇1:()kk k k k k k d x x minf d x αααα++←+三用修正牛顿法求函数程序如下:#include<stdio.h>#include<math.h>#include<conio.h>#include <iostream>double fun1(double q1,double q2){return(pow((q1+1),2)*4+2*pow((q2-1),2)+q1+q2+10);}double fun2(double g,double x,double y,double r1,double r2){return (pow((x+g*y+1),2)*4+pow(((r1+g*r2)-1),2)*2+(x+g*y)+(r1+g*r2)+10); }void main(){double A[2][1],B[2][2],C[2][1],D[2][1],X[2][1];double E[2][1]={0,0};//¡ä¨²¦Ì?3?¨º?¦Ì?x0int t=0,i=0,j=0;double E0,x1,x2,x3,h(0.1);double y1,y2,y3,m;double a,b,k=0.618,a1,a2,f1,f2;printf("输入收敛度");std::cin>>E0;do{D[0][0]=E[0][0];D[1][0]=E[1][0];A[0][0]=8*D[0][0]+0*D[1][0]+9;A[1][0]=0*(D[0][0]+4*D[1][0])-3;B[0][0]=0*D[0][0]+0*D[1][0]+0.125;B[0][1]=0*D[0][0]+0*D[1][0]+0;B[1][0]=0*D[0][0]+0*D[1][0]+0;B[1][1]=0*D[0][0]+0*D[1][0]+0.25;//B[0][0],B[0][1],B[1][0],B[1][1]为海森矩阵的逆C[0][0]=-(B[0][0]*A[0][0]+B[0][1]*A[1][0]);C[1][0]=-(B[1][0]*A[0][0]+B[1][1]*A[1][0]);x1=0;x2=x1+h;y1=fun2(x1,D[0][0],C[0][0],D[1][0],C[1][0]);y2=fun2(x2,D[0][0],C[0][0],D[1][0],C[1][0]);if(y2>y1){h=-h;x3=x1,y3=y1;x1=x2,y1=y2;x2=x3,y2=y3;}x3=x2+h;y3=fun2(x3,D[0][0],C[0][0],D[1][0],C[1][0]); while(y3<y2){h=2*h;x1=x2,y1=y2;x2=x3,y2=y3;x3=x2+h;y3=fun2(x3,D[0][0],C[0][0],D[1][0],C[1][0]); i++;}a=x1;b=x3;a1=b-k*(b-a);a2=a+k*(b-a);f1=fun2(a1,D[0][0],C[0][0],D[1][0],C[1][0]); f2=fun2(a2,D[0][0],C[0][0],D[1][0],C[1][0]); do{if(f1>=f2){a=a1;a1=a2;f1=f2;a2=a+k*(b-a);f2=fun2(a2,D[0][0],C[0][0],D[1][0],C[1][0]);}else{b=a2;a2=a1;f2=f1;a1=b-k*(b-a);f1=fun2(a1,D[0][0],C[0][0],D[1][0],C[1][0]);}j++;}while(fabs((b-a)/b)>=E0&&fabs((f2-f1)/f2)>=E0);m=0.5*(a+b);//m?aE[0][0]=D[0][0]+m*C[0][0];E[1][0]=D[1][0]+m*C[1][0];printf("%d%15f10%15f10\n",t,E[0][0],E[1][0],fun1(E[0][0],E[1][0])); t++;}while(fabs(E[0][0]-D[0][0])>=E0&&fabs(E[1][0]-D[1][0])>=E0);X[0][0]=E[0][0];X[1][0]=E[1][0];printf("迭代了%d次n",t);printf("极小点x1,x2)=(%f10,%f10)\n",X[0][0],X[1][0]);printf(""极小值f(x1,x2)=%f10\n",fun1(X[0][0],X[1][0]));getchar();}程序运行结果:四结论由该程序的运行结果可知,要求迭代两次后函数的极小值点在(-1.125,0.6624)处,与精确结果(应为(-1.125,0.75))有误差。
一种修正牛顿算法
南京航空航天大学硕士学位论文
绪 论
在化学,生物,医学等领域常常要求处理一些不定矩阵,而处理这些不定矩
阵通常是改进方法的 Cholesky 分解算法,这也为解优化问题的牛顿方法提供了行 之有效的实现手段,成为优化领域应用十分广泛的基础内容之一。
Cholesky 分解算法是数值计算的基本方法。自 1974 年, Gill 和 Murray 在优 化中应用这一方法以来,它就得到了迅速发展,并不断完善,广泛应用于各学科 领域中。在 Hesse 矩阵的 Cholesky 分解过程中,调整对角元使得修正后的 Hesse 矩阵充分正定,即在矩阵的 LDLT 分解中,D 中的对角元不小于某一个给定的正常 数,这种修正的 Cholesky 分解算法使得任意的对称矩阵均有三角分解,而且每一 分解因子相对原矩阵的差有界。如果 Hesse 阵 A 是对称正定的,则 A 有三角分解
θ ≤ π / 2 − µ ,对某个 µ >0, 结合起来,给出
d
k
=
dkn
,
若
cos
d
n k
,
−gk
−
g
k
≥ η, (1.6)
其中η > 0 是预先给定的正常数。这样,搜索方向 dk 总满足
第二是即使这种分解存在,其计算过程一般也是不稳定的,因为其矩阵分解因子
的元素可能是无界的。进一步,当 Gk 仅是稍微不定的,用这样的方法产生的 Gk 也 可能和 Gk 相差很大,例如:
1 1 Gk = 1 1 +10−10
2 3
2 3 , (1.8) 1
一个新的修正cholesky分解算法本章考虑对称不定矩阵修正的cholesky分解算法分解形式是papldl其中p是排列阵i是一个单位阵l这个修正的cholesky算法是在ashcraftgrimes和lewis的一个选主元方法bbk基础上提出的而有约束的选主元策略是来自于bunchkaufman选主元方法bunchkaufman算法中a的分解为papldl其中l是下三角矩阵d是包含1块的块对角阵
最优化理论与方法——牛顿法
最优化理论与⽅法——⽜顿法⽜顿法简介摘要:⽜顿法作为求解⾮线性⽅程的⼀种经典的迭代⽅法,它的收敛速度快,有内在函数可以直接使⽤。
结合着matlab 可以对其进⾏应⽤,求解⽅程。
关键词:⽜顿法,Goldfeld 等⼈修正⽜顿法,matlab 实现1介绍:迭代法也称辗转法,是⼀种不断⽤变量的旧值递推新值的过程,跟迭代法相对应的是直接法,即⼀次性解决问题。
但多数⽅程不存在求根公式,因此求解根⾮常困难,甚⾄不可能,从⽽寻找⽅程的近似根就显得特别重要。
迭代算法是⽤计算机解决问题的⼀种基本⽅法。
它利⽤计算机运算速度快、适合做重复性操作的特点,让计算机对⼀组指令(或⼀定步骤)进⾏重复执⾏,在每次执⾏这组指令(或这些步骤)时,都从变量的原值推出它的⼀个新值。
利⽤迭代算法解决问题,需要做好以下3个⽅⾯的⼯作:1,确定迭代变量。
在可以⽤迭代算法解决的问题中,⾄少存在⼀个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。
2,建⽴迭代关系式。
所谓迭代关系式,是指如何从变量的前⼀个值推出下⼀个值的公式(或关系)。
迭代关系式的建⽴是解决迭代问题的关键,通常可以使⽤递推或倒推的⽅法来完成。
3,对迭代过程进⾏控制。
在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。
不能让迭代过程⽆休⽌地重复下去。
迭代过程的控制通常可分为两种情况:⼀种是所需的迭代次数是个确定的值,可以计算出来;另⼀种是所需的迭代次数⽆法确定。
对于前⼀种情况,可以构建⼀个固定次数的循环来实现对迭代过程的控制;对于后⼀种情况,需要进⼀步分析出⽤来结束迭代过程的条件。
⽜顿迭代法(Newton’s method )⼜称为⽜顿-拉夫逊⽅法(Newton-Raphson method ),它是⽜顿在17世纪提出的⼀种在实数域和复数域上近似求解⽅程的⽅法,其基本思想是利⽤⽬标函数的⼆次Taylor 展开,并将其极⼩化。
⽜顿法使⽤函数()f x 的泰勒级数的前⾯⼏项来寻找⽅程()0f x =的根。
最优化理论与算法------牛顿法(附Matlab实现):
最优化理论与算法------⽜顿法(附Matlab 实现):1、写在最前:在此只是简单在应⽤层⾯说明⼀下相关算法,严谨的数学知识,请⼤家参考最下⾯参考书⽬,后期有精⼒会进⾏细化,先占个坑。
2、基本知识::f (x )=10!f x 0+11!x −x 0f ′x 0+12!x −x 02f ′′x 0+⋯+1n !x −x 0n f (n )x 0+R n⽜顿法的基本思想是,在极⼩点附件⽤⼆阶 Taylor 多项式:f (x )=10!f x 0+11!x −x 0f ′x 0+12!x −x 02f ′′x 0近似⽬标函数f (x ),进⽽求出极⼩点的估计值。
⽜顿法实现的动图如下所⽰:为了便于以下讨论时符号的统⼀,重写公式(2)如下所⽰:φ(x )=f x (k )+f ′x (k )x −x (k )+12f ′′x (k )x −x (k )2对(3)式求导:φ′(x )=f ′x (k )+f ′′x (k )x −x (k )=0令(4)式为0,既可以得到切线与x 轴交点:x (k +1)=x (k )−f ′x (k )f ′′x (k )由此可以得到⼀系类的x (k ),逐渐逼近真实最⼩值。
3、程序框图:4、算例:求 min f (x )=4x 21+x 22−x 21x 2初始点:x A =(1,1)T ,精度要求:ε=10−3f (x )=4x 21+x 22−x 21x 2∇f (x )=8x 1−2x 1x 2,2x 2−x 21T∇2f (x )=8−2x 2−2x 1−2x 12进⾏迭代计算:5、Matlab 求解(调试环境2016a ):如算例4要求所⽰:求得:x =[−0.1586×e −4,−0.1631×e −4]T result =1.2719e −6结果与⼿算的吻合。
全套下载链接:包含⽂档、PPT 、Matlab 源代码等等:6、优缺点:优点:•Newton 法产⽣的点列x k 若收敛,则收敛速度快,具有⾄少⼆阶收敛速率•Newton 法具有⼆次终⽌性缺点:•可能会出现在某步迭代时,⽬标函数值上升()()()()()()()()()()()()()()()()()()()()()()()()Processing math: 100%•当初始点远离极⼩点时,⽜顿法产⽣的点列可能不收敛,或者收敛到鞍点,或者Hesse矩阵不可逆,⽆法计算•需要计算Hesse矩阵的逆矩阵,计算量⼤7、参考:最优化理论与算法(第⼆版)陈宝林编著最优化理论Matlab。
改进的Newton法解决二次优化问题
最优化理论与算法实验报告(三)实验名称 改进的Newton 法解决二次优化问题 实验时间姓名专业班级学号成绩一、实验目的和内容实验目的:通过实验, 让学生掌握改进的Newton 法解决优化问题的具体实现, 同时对于具体的问题设计, 让学生根据在实验中出现的数值计算结果,. 理解改进的Newton 法的基本思想. 实验内容:(问题同实验二) 请采用改进的Newton 法求解2221212min ()33n x f x x x x x ∈=+-终止的准则610k g -≤, 分别用如下不同的初时结点进行迭代. 1. ()0 1.5,1.5Tx =, 2. ()02,4Tx =-, 3. ()00,3Tx =二、相关背景知识介绍一、Goldstein —Price (1967) 修正方案:当k G 非正定时, 采用最速下降方向k g -替代牛顿方向. 若进一步将搜索方向与负梯度方向的角度准则结合起来, 则有if cos , elseN Nk k k k k d d g d g η⎧-≥⎪=⎨-⎪⎩其中: 1N k k k d G g -=-,二、Goldfeld (1966) 修正方案若k G 非不正定, 则用k k k G G v I =+来修正k G . 通过适当选取0k v >, 可以使k G 正定. 三、代码牛顿改进算法代码:function re=New(x,Gk,var,n) e=10^n; xk=x;gk=fgk(@f,xk,1); t=[1;0]; k=0;while(norm(gk)>e)mGk=subs(Gk,var,xk);if((t'*mGk*t)>0)[L U]=lu(mGk);dk=U\(L\-gk);xk=xk+dk;gk=fgk(@f,xk,1);k=k+1;elsee=diag(mGk);f1=min(diag(mGk));f1=0.01-f1;E=eye(length(e));mGk=mGk+f1.*E;[L U]=lu(mGk);dk=U\(L\-gk);xk=xk+dk;gk=fgk(@f,xk,1);k=k+1;endend计算梯度的函数:function gk=fgk(f,xk,h)if(h==1)t=f(xk);xk(1)=xk(1)+1;gk(1,1)=f(xk)-txk(1)=xk(1)-1;xk(2)=xk(2)+1;gk(2,1)=f(xk)-t;end初始化函数:syms x1 x2var=[x1,x2];f=3*x1^2+3*x2^2-x1^2*x2;A=jacobian(f,var);e=jacobian(A,var);Gk=e;n=-12;x=[0;0];目标函数:function r=f(x)r=3*x(1)^2+3*x(2)^2-x(1)^2*x(2)四、数值结果X=[-2;4] K=2 Xk=[-4.8087;3.0196]X=[1.5;1.5] K=12 Xk=[-0.5;-0.4583]五、计算结果的分析与New法相互比较,在X=[1.5;1.5]处的迭代次数并未下降,反倒是在鞍点X=[-2;4]处的迭代次数减少了不少,可视为将鞍面做了一个稍稍的倾斜,加快了下降速度。
改进牛顿法程序设计
改进牛顿法程序设计
要改进牛顿法程序设计,可以考虑以下几个方面:
1. 初始值选择:通过合理选择初始值,可以避免收敛到局部极小值点的情况。
可以考虑使用其他优化方法来预估一个较好的初始值,然后再使用牛顿法进行迭代。
2. 迭代终止条件:可以设置更加精确的终止条件,例如达到一定的迭代次数或者目标函数值的变化足够小。
这样可以避免无限循环的情况出现。
3. 步长选择:可以使用线搜索方法或者拟牛顿方法来确定每次迭代的步长,以保证迭代过程更快地收敛。
4. 收敛性检验:在每一次迭代过程中,可以对牛顿法的收敛性进行检测,如果发现不收敛,则可以进行一些修正,例如使用梯度下降法进行下一次迭代。
5. 并行计算:可以将迭代过程进行并行计算,加快求解速度。
例如,可以使用多线程或者GPU等技术来并行处理。
6. 多元函数的求解:将牛顿法扩展到多元函数的求解。
可以通过计算Hessian矩阵的逆来求解多元函数的极小值。
通过以上改进,可以提高牛顿法的求解效率和收敛性,使其更适用于实际问题的求解。
最优化方法三分法+黄金分割法+牛顿法
最优化⽅法三分法+黄⾦分割法+⽜顿法最优化_三等分法+黄⾦分割法+⽜顿法⼀、实验⽬的1. 掌握⼀维优化⽅法的集中算法;2. 编写三分法算法3. 编写黄⾦分割法算法4. 编写⽜顿法算法⼆、系统设计三分法1.编程思路:三分法⽤于求解单峰函数的最值。
对于单峰函数,在区间内⽤两个mid将区间分成三份,这样的查找算法称为三分查找,也就是三分法。
在区间[a,b]内部取n=2个内等分点,区间被分为n+1=3等分,区间长度缩短率=1 3 .各分点的坐标为x k=a+b−an+1⋅k (k=1,2) ,然后计算出x1,x2,⋯;y1,y2,⋯;找出y min=min{y k,k=1,2} ,新区间(a,b)⇐(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; %将区间三等分,每⼩段长度=marginm1=left+margin; %left-m1-m2-right,三等分需要两个点m2=m1+margin; %m2=left+margin+marginif(f(m1)<=f(m2))right=m2; %离极值点越近,函数值越⼩(也有可能越⼤,视函数⽽定)。
else %当f(m1)>f(m2),m2离极值点更近。
缩⼩区间范围,逼近极值点left=m1; %所以令left=m1.endend %这是matlab的.m⽂件,不⽤写return.黄⾦分割法1.编程思路三分法进化版,区间长度缩短率≈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)]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法的改进形式:每次缩⼩区间时,同时⽐较两内点和两端点处的函数值。
改进的Newton法解决二次优化问题
t=f(xk);
xk(1)=xk(1)+1;
gk(1,1)=f(xk)-t
xk(1)=xk(1)-1;
xk(2)=xk(2)+1;
gk(2,1)=f(xk)-t;
end
初始化函数:
syms x1 x2
var=[x1,x2];f=3*x1^2+3*x2^2-x1^2*x2;
A=jacobian(f,var);e=jacobian(A,var);
当 非正定时, 采用最速下降方向 替代牛顿方向. 若进一步将搜索方向与负梯度方向的角度准则结合起来, 则有
其中: ,
二、Goldfeld (1966) 修正方案
若 非不正定, 则用 来修正 . 通过适当选取 , 可以使 正定.
3、代码
牛顿改进算法代码:
function re=New(x,Gk,var,n)
Gk=e;
n=-12;
x=[0;0];
目标函数:
function r=f(x)
r=3*x(1)^2+3*x(2)^2-2
Xk=[-4.8087;3.0196]
X=[1.5;1.5]
K=12
Xk=[-0.5;-0.4583]
5、计算结果的分析
与New法相互比较,在X=[1.5;1.5]处的迭代次数并未下降,反倒是在鞍点X=[-2;4]处的迭代次数减少了不少,可视为将鞍面做了一个稍稍的倾斜,加快了下降速度。在算法本身上做了不少改进,曾将使用过mGk=mGk+(f1+E);但效果却不及mGk=mGk+f1.*E;好。
else
e=diag(mGk);
f1=min(diag(mGk));
c语言简化牛顿迭代法
c语言简化牛顿迭代法牛顿迭代法是一种求解方程近似解的数值方法,它的原理是通过不断逼近方程的根来得到方程的解。
牛顿迭代法的思想非常简单,即通过不断迭代计算来逼近方程的解,直到满足预设的精度要求为止。
牛顿迭代法的基本思路是,假设我们要求解的方程是f(x)=0,我们可以通过对方程进行泰勒展开,然后取展开式的一阶导数来逼近方程的解。
具体来说,我们可以取方程在某一点x0处的切线来逼近方程的解,切线与x轴的交点就是方程的近似解,然后我们再以这个交点为起点,再进行下一次迭代,直到满足预设的精度要求。
牛顿迭代法的迭代公式可以表示为:x[n+1] = x[n] - f(x[n])/f'(x[n]),其中x[n]表示第n次迭代的近似解,f(x)表示方程,f'(x)表示方程的导数。
下面我们通过一个简单的例子来说明牛顿迭代法的具体步骤。
假设我们要求解方程x^2 - 2 = 0的近似解,我们可以将方程转化为f(x) = x^2 - 2的形式,然后我们需要求解f(x) = 0的根。
我们选择一个初始值作为迭代的起点,假设我们选择x0 = 1作为初始值。
然后,我们计算初始值x0处的函数值f(x0)和导数值f'(x0)。
对于方程f(x) = x^2 - 2,我们可以得到f(1) = -1和f'(1) = 2。
接下来,我们可以使用迭代公式x[n+1] = x[n] - f(x[n])/f'(x[n])来计算下一次迭代的近似解。
根据我们之前计算的值,可以得到x[1] = 1 - (-1)/2 = 1.5。
然后,我们继续计算x[1]处的函数值f(x[1])和导数值f'(x[1]),然后再使用迭代公式计算下一次迭代的近似解。
以此类推,直到满足预设的精度要求。
需要注意的是,牛顿迭代法并不是一定能够收敛到方程的解,有时候可能会出现迭代发散的情况。
因此,在使用牛顿迭代法时,我们需要对迭代的收敛性进行分析,并选择合适的初始值。
牛顿法求解约束优化算法流程
牛顿法求解约束优化算法流程一、什么是牛顿法。
牛顿法原本就是一种很厉害的迭代算法啦。
它的基本思想是利用函数的泰勒级数展开式,取到二阶导数项,然后找到一个近似的函数,通过这个近似函数来求函数的极值点。
就好像我们在一个很复杂的迷宫里找出口,牛顿法给了我们一个比较聪明的找路方法呢。
对于无约束的优化问题,它就像一个小机灵鬼,能比较快地找到最优解。
比如说,我们有一个函数f(x),牛顿法就会根据这个函数在某一点的一阶导数和二阶导数,不断地调整下一个迭代点的位置,每次都想着离那个最优解更近一点。
二、约束优化问题的难点。
可是呢,约束优化问题就不像无约束那么自由自在啦。
约束条件就像是给我们的优化过程加上了一道道小围栏。
比如说,我们可能有不等式约束g(x) <= 0,或者等式约束h(x)=0。
这些约束条件会让我们不能像在无约束情况下那样随心所欲地找最优解。
我们得小心翼翼地在这些约束的范围内寻找那个最好的点。
这就好比我们要在一个有很多规则的游戏里获胜,既要遵守规则,又要达到最好的成绩。
三、牛顿法求解约束优化的准备工作。
1. 我们得先把目标函数和约束条件都明确地表示出来。
目标函数就是我们想要优化的那个函数,比如让它最小化或者最大化。
约束条件呢,就得按照不等式和等式的形式写得清清楚楚。
这就像是我们要参加一场比赛,得先知道比赛的目标和规则一样。
2. 然后呢,我们要把这些函数进行一些处理。
对于等式约束,我们可以通过拉格朗日乘数法把它和目标函数结合起来。
这就像是给目标函数找了个小伙伴,这个小伙伴就是等式约束条件,它们俩要一起被考虑。
对于不等式约束,我们也有一些特殊的处理方法,像把不等式约束转化为障碍函数之类的,这样就能让牛顿法也能处理这些不等式约束啦。
四、牛顿法求解约束优化的迭代过程。
1. 在每一次迭代的时候,我们要根据已经结合了约束条件的函数(比如拉格朗日函数)来计算它的梯度和海森矩阵。
这个梯度就像是函数在这个点的一个“小向导”,告诉我们函数值在哪个方向上变化得最快。
修正牛顿(newton)法求解无约束问题
修正牛顿(newton)法求解无约束问题------------------基于成都理工大学最优化教材#include <iostream.h>#include "Matrix.h"#include<LIMITS.H>#define MAX_M 2048#include<math.h>#define beta (sqrt(5)-1)/2#define eclipse 0.01CMatrixhesse(){CMatrixtemp(2,2);temp.A[0][0] = 8;temp.A[0][1] = 0;temp.A[1][0] = 0;temp.A[1][1] =4;return temp;}double fun(double t,CMatrix&X1,CMatrix &X2){double x1 = X1.A[0][0] + t*X2.A[0][0];double x2 = X1.A[1][0] + t*X2.A[1][0];return 4*(x1+1)*(x1+1) + 2*(x2-1)*(x2-1) + x2 + x1 +10;}doubleMax_Num(double a,double b){if(a>b){return a;}else{return b;}}doubleMin_Num(double a,double b){if(a<b){return a;}else{return b;}}voidStepAdding_Search(double &a,double&b,CMatrix&mt1,CMatrix &mt2) {double t[MAX_M]={0};double h[MAX_M]={0};double f[MAX_M]={0};double result=0;double p=2.1;t[0]=0;h[0]=1;f[0]=fun(t[0],mt1,mt2);for(int k=0;k<MAX_M-1;k++){t[k+1]=t[k]+h[k];f[k+1]=fun(t[k+1],mt1,mt2);if(f[k+1]<f[k]){h[k+1]=p*h[k];result=t[k];t[k]=t[k+1];f[k]=f[k+1];}else if(k == 0){h[k]=-h[k];result=t[k+1];}else{a=Min_Num(result,t[k+1]);b=Max_Num(result,t[k+1]);}}}double Fibonacci(double &a,double&b,CMatrix mt1,CMatrix mt2){double t2,t1,result_1,result_2;t2 = a + beta*(b-a);result_2 = fun(t2,mt1,mt1);while(true){t1 = a+b-t2;result_1 = fun(t1,mt1,mt2);if(fabs(t1-t2)<eclipse){return (t1+t2)/2;}else if(result_1 < result_2){b = t1;t1 = t2;result_1 = result_2;t2 = a+beta*(b-a);result_2 = fun(t2,mt1,mt2);}else if(result_1 == result_2){a = t1;b = t2;result_2 = fun(a,mt1,mt2);}else{a = t2;t2 = t1;result_2 = result_1;}}}double distance(CMatrix&X1,CMatrix &X2) {double x1 = X1.A[0][0] - X2.A[0][0];double x2 = X1.A[1][0] - X2.A[1][0];return x1*x1 + x2*x2;}CMatrixdiff_fun(CMatrix&mt){CMatrixtemp(2,1);temp.A[0][0] = 8*(mt.A[0][0] +1) +1;temp.A[1][0] = 4*(mt.A[1][0] -1) +1;return temp;}void main(){CMatrix X1(2,1);X1.A[0][0] = 0;X1.A[1][0] = 0;CMatrixm_temp = hesse();CMatrixn_temp = diff_fun(X1);CMatrix X2 = (m_temp.Inverse()* n_temp).Matrix_Multiply(-1);doublea,b;StepAdding_Search(a,b,X1,X2);double m = Fibonacci(a,b,X1,X2);CMatrix X3 = X1 + X2.Matrix_Multiply(m);while(distance(X1,X3) > eclipse){X1 = X3;X2 = m_temp.Inverse()* diff_fun(X1);StepAdding_Search(a,b,X1,X2);m = Fibonacci(a,b,X1,X2);X3 = X1 + X2.Matrix_Multiply(m);}cout<<"求解的结果是:"<<endl;cout<<"("<<X1.A[0][0]<<","<<X1.A[1][0]<<")"<<endl;cout<<"最优解是:"<<endl;cout<<fun(m,X1,X2)<<endl;}。
最优化算法最速下降法、牛顿法、拟牛顿法Python实现
最优化算法最速下降法、⽜顿法、拟⽜顿法Python实现---------------------------------------2020.9.23更新---------------------------------把 BFGS(x)改写了⼀下,变简洁了def BFGS(x): #拟⽜顿法epsilon, h, maxiter = 10**-5, 10**-5, 10**4Bk = np.eye(x.size)for iter1 in range(maxiter):grad = num_grad(x, h)if np.linalg.norm(grad) < epsilon:return xdk = -np.dot((np.linalg.inv(Bk)), grad)ak = linesearch(x, dk)x = x + dk*akyk = num_grad(x, h) -gradsk = ak*dkif np.dot(yk, sk) > 0:Bs = np.dot(Bk,sk)ys = np.dot(yk,sk)sBs = np.dot(np.dot(sk,Bk),sk)Bk = Bk - 1.0*Bs.reshape((n,1))*Bs/sBs + 1.0*yk.reshape((n,1))*yk/ysreturn x---------------------------------------2020.9.23更新---------------------------------只⽤到了numpy这⼀个库,只要安装有这个库应该都可以直接运⾏import numpy as npdef f(x): #⽬标函数x1 = x[0]x2 = x[1]y = 100*((x2 - x1**2)**2) + (x1-1)**2return ydef num_grad(x, h): #求梯度df = np.zeros(x.size)for i in range(x.size):x1, x2 = x.copy(), x.copy() #这⾥需要⽤到复制,⽽不能⽤赋值号(=),原因是Python⾥⾯=号只是取别名,不是复制(c/c++⾥⾯是)x1[i] = x[i] - hx2[i] = x[i] + hy1, y2 = f(x1), f(x2)df[i] = (y2-y1)/(2*h)return dfdef num_hess(x, h): #求hess矩阵hess = np.zeros((x.size, x.size))for i in range(x.size):x1 = x.copy()x1[i] = x[i] - hdf1 = num_grad(x1, h)x2 = x.copy()x2[i] = x[i] + hdf2 = num_grad(x2, h)d2f = (df2 - df1) / (2 * h)hess[i] = d2freturn hessdef linesearch(x, dk): #求步长ak = 1for i in range(20):newf, oldf = f(x + ak * dk), f(x)if newf < oldf:return akelse:ak = ak / 4 #迭代更新步长,步长可随意变换,保证newf⽐oldf⼩就可以了(如改为: ak=ak/2 也是可以的)return akdef steepest(x): #最速下降法epsilon, h, maxiter = 10**-5, 10**-5, 10**4for iter1 in range(maxiter):grad = num_grad(x, h)if np.linalg.norm(grad) < epsilon:return xdk = -gradak = linesearch(x, dk)x = x + ak * dkreturn xdef newTonFuction(x): #⽜顿法epsilon, h1, h2, maxiter = 10**-5, 10**-5, 10**-5, 10**4for iter1 in range(maxiter):grad = num_grad(x, h1)if np.linalg.norm(grad) < epsilon:return xhess = num_hess(x, h2)dk = -np.dot((np.linalg.inv(hess)), grad)x = x + dkreturn xdef BFGS(x): #拟⽜顿法epsilon, h, maxiter = 10**-5, 10**-5, 10**4Bk = np.eye(x.size)for iter1 in range(maxiter):grad = num_grad(x, h)if np.linalg.norm(grad) < epsilon:return xdk = -np.dot((np.linalg.inv(Bk)), grad)ak = linesearch(x, dk)x = x + dk*akyk = num_grad(x, h) -gradsk = ak*dkif np.dot(yk.reshape(1, grad.shape[0]), sk) > 0:'''第⼀种分步计算实现t0 = np.dot(Bk, sk)t1 = np.dot(t0.reshape(sk.shape[0], 1), sk.reshape(1, sk.shape[0]))temp0 = np.dot(t1, Bk)temp1 = np.dot(np.dot(sk.reshape(1, sk.shape[0]), Bk), sk)tmp0 = np.dot(yk.reshape(yk.shape[0], 1), yk.reshape(1, yk.shape[0]))tmp1 = np.dot(yk.reshape(1, yk.shape[0]), sk)Bk = Bk - temp0 / temp1 + tmp0 / tmp1'''#第⼆种直接写公式实现Bk = Bk - np.dot(np.dot(np.dot(Bk, sk).reshape(sk.shape[0], 1), sk.reshape(1, sk.shape[0])), Bk)/np.dot(np.dot(sk.reshape(1, sk.shape[0]), Bk), sk) + np.dot(yk.reshape(yk.shape[0], 1), yk.reshape(1, yk.shape[0])) / np.dot(yk.reshape(1, yreturn x#x0 = np.array([0.999960983973235, 0.999921911551354]) #初始解x0 = np.array([0.7, 0.9]) #初始解x = steepest(x0) #调⽤最速下降法print("最速下降法最后的解向量:",x)print("最速下降法最后的解:",f(x))print('')x = newTonFuction(x0) #调⽤⽜顿法print("⽜顿法最后的解向量:", x)print("⽜顿法最后的解:", f(x))print('')x = BFGS(x0) #调⽤拟⽜顿法print("拟⽜顿法最后的解向量:", x)print("拟⽜顿法最后的解:", f(x))print('')结果如下拟⽜顿法感觉弄⿇烦了,暂时也没想法改,先就这样吧。
实验四 改进欧拉法,二分法,牛顿法
实验四改进欧拉法,二分法,牛顿法实验报告学院:计算机科学与软件学院班级:116班姓名:薛捷星学号:112547一、 目的与要求:熟悉求解常微分方程初值问题的有关方法和理论,主要是改进欧拉法会编制上述方法的计算程序针对实习题编制程序,并上机计算其所需要的结果;二、 实验内容:熟悉求解常微分方程初值问题的有关方法和理论,主要是改进欧拉法,体会其解法的功能。
程序与实例改进欧拉方法算法概要解一阶常微分方程初值问题⎩⎨⎧=='00)(),(y x y y x f y b x a ≤≤将区间[a,b]作n 等分,取步长na b h -=。
欧拉公式为),(1i i i i y x hf y y +=+梯形公式为 []),(),(2111+++++=i i i i i i y x f y x f h y y改进欧拉法,采用公式()()[]⎪⎩⎪⎨⎧++=+=++++1111,,2),(i i i i i i i i i i y x f y x f h y y y x hf y y 或表为⎪⎪⎪⎩⎪⎪⎪⎨⎧+=+=+=++)(21),(),(11c p i p i i c i i i p y y y y x hf y y y x hf y y实验题:30≤≤x程序如下:#include<stdio.h>double fac(double x,double y){double f;f=-x*y*y;return(f);}main(){int n,i;double a=0,b=3.0,c1,d1,c2,d2,h,x[30],y[30],r[30];printf("输入n:");scanf("%d",&n);h=(b-a)/n;y[0]=2;printf("y[0]=2\n");for(i=0;i<=n-1;i++){x[i]=a+i*h;c1=x[i];d1=y[i];c2=x[i]+h;r[i+1]=y[i]+h*fac(c1,d1);d2=r[i+1];y[i+1]=y[i]+h/2*(fac(c1,d1)+fac(c2,d2));printf("y[%d]=%f\n",i+1,y[i+1]);}}()⎩⎨⎧=-='202y xy y一、目的与要求:通过对二分法和牛顿迭代法作编程练习和上机运算,进一步体会它们在方程求根中的不同特点;比较二者的计算速度和计算精度二、实验内容:通过对二分法和牛顿迭代法作编程练习和上机运算,进一步体会它们在方程求根中的不同特点三、程序与实例二分法算法:给定区间[a,b],并设与符号相反,取为根的容许误差,为的容许误差。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for(;i<2*n;i++)
{
t[1]+=f_xs[i]*p[i%n];
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
t[1]+=f_xs[(n+1)+n*(i+1)-i*(i+1)/2+j-i-1]*(x[i]*p[j]+x[j]*p[i]);
{
for(int j=0;j<n;j++)
{
cout<<setw(10)<<c[i][j]<<" ";
}
cout<<endl;
}
}
void xiang_cheng(double a[n][n],double b[n],double c[n])//n*n矩阵乘以n*1矩阵
int tap1=0,tap2=0;//最大列主元下标
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j)
{
c[i][j]=1;
}
else
{
c[i][j]=0;
}
for(j=0;j<n;j++)
{
Hesse[i][j]=Q[i][j];
}
}
cout<<"Hesse 矩阵:"<<endl;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
cout<<setw(10)<<Hesse[i][j]<<" ";
}
}
if(t==0)
{cout<<"列主元为零,失败!"<<endl;break;}
if(tap1!=tap2)//换行
{
for(int i=0;i<n;i++)//s
{
T=a[tap1][i];
a[tap1][i]=a[s][i];
p[i]*=(-1);
abc(x,p,f_xs,t);//开始计算minf(Xk+tPk)时的步长t的值,
t_bc=t_c(t);//求一阶导来计算t
for(i=0;i<n;i++)
{
x[i]=x[i]+t_bc*p[i];
}
tap++;
}
}
}
void D_fun(double x[n],double Q[n][n+1],double g0[n])//自变量初值,正定二次函数的各项系数,返回梯度的初值
{
int i,j;
for(i=0;i<n;i++)
{
g0[i]=0;//清零
for(j=0;j<n;j++)
{
int i,j,k;
if(n==n)
{
cout<<"两矩阵阶数相符可以相乘!"<<endl;
for(i=0;i<n;i++)
{
c[i]=0;
}
for(k=0;k<n;k++)//c矩阵的第k行
{
for(j=0;j<n;j++)
{
double inv_Hesse[n][n];//Hesse矩阵的逆
double t[3];//返回求minf()时t的二次函数的a,b,c的系数值
double t_bc;//步长
double p[n];//保存矩阵相乘结果_加负号后变成下降方向
int i,tap=0;//迭代次数
{
int i,j;
double f=0;
for(i=0;i<n;i++)//计算X^2部分
{
f+=pow(x[i],2)*f_xs[i];
}
for(;i<2*n;i++)//计算X部分
{
f+=x[i%n]*f_xs[i];
}
f+=f_xs[i];//计算常数项部分
for(i=0;i<n;i++)//计算XiXj部分
{
for(j=i+1;j<n;j++)
{
f+=f_xs[(n+1)+n*(i+1)-i*(i+1)/2+j-i-1]*x[i]*x[j];
}
}
return f;
}
void Q_fun(double f_xs[n+n+1+(n-1)*n/2],double Q[n][n+1])
}
}
t[2]=fun(x,f_xs);
cout<<endl<<"二次函数minf(Xk)的二次项系数:"<<t[0]<<" 一次项系数:"<<t[1]<<" 常数项系数:"<<t[2]<<endl<<endl;
}
//二次函数一阶导为零计算t的值,t>0
double t_c(double t[3])
}
cout<<endl;
}
}
int H(double g0[n],double c)//判别准则:返回1结束,返回0继续迭代
{
double s=0;
for(int i=0;i<n;i++)
{
s+=pow(g0[i],2);
}
if(sqrt(s)<c)
{
int i,j;
t[0]=t[1]=t[2]=0;
t[0]=fun(p,f_xs)-f_xs[2*n];
for(i=n;i<2*n;i++)
{
t[0]-=f_xs[i]*p[i%n];
}
for(i=0;i<n;i++)
{
t[1]+=2*f_xs[i]*x[i]*p[i];
#include<iostream.h>
#include<math.h>
#include<iomanip.h>
#define n 2//正定二次函数的自变量个数
double fun(double x[n],double f_xs[n+n+1+(n-1)*n/2])//输入变量为函数自变量初值
{
if(i==j)
g0[i]+=Q[i][j]*x[j];
else
g0[i]+=Q[i][j]*x[j];
}
}
for(i=0;i<n;i++)
{
g0[i]+=Q[i][n];
}
cout<<endl<<"梯度g0的值="<<endl;
a[s][i]=T;
T=c[tap1][i];//逆矩阵换行
c[tap1][i]=c[s][i];
c[s][i]=T;
}
}
tap1=tap2=0;//置零
for(int j=0;j<n;j++)//单位化,(注意:逆矩阵每列都单位化,而原矩阵则不受影响)
Q_fun(f_xs,Q);//计算正定二次函数对应的实对称矩阵ok!
f0=fun(x,f_xs);//求函数初值ok!
D_fun(x,Q,g0);//返回梯度的初值
while(H(g0,c)==0)
{
//x_k_1(x,g0,Q);//求出下一个迭代点,更新了x[n]的值
for(i=0;i<n;i++)
cout<<setw(10)<<g0[i]<<endl;
cout<<endl;
}
void Hesse_fun(double Q[n][n+1],double Hesse[n][n])
{
int i,j;
for(i=0;i<n;i++)
{
for(i=0;i<n;i++)
{
cout<<"x"<<i+1<<"="<<x[i]<<endl;
}
cout<<"迭代次数为:"<<tap<<endl;
//n元的系数存放类推
double x[n]={0,0};//函数自变量初值
double f0;//函数值