声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 7586|回复: 9

[C/C++] 拟牛顿法(变尺度法)DFP算法的c/c++源码

[复制链接]
发表于 2006-11-12 06:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
  1. #include "iostream.h"
  2. #include "math.h"

  3. void comput_grad(double (*pf)(double *x),  int n,  double *point,  double *grad);                        //计算梯度
  4. double line_search1(double (*pf)(double *x),  int n,  double *start,  double *direction);        //0.618法线搜索
  5. double line_search(double (*pf)(double *x),   int n,  double *start,  double *direction);        //解析法线搜索
  6. double DFP(double (*pf)(double *x),   int n,   double *min_point);                //无约束变尺度法



  7. //梯度计算模块
  8. //参数:指向目标函数的指针,变量个数,求梯度的点,结果
  9. void comput_grad(double (*pf)(double *x),
  10.                                   int n,
  11.                                   double *point,
  12.                                   double *grad)
  13. {
  14.         double h=1E-3;
  15.         int i;
  16.         double *temp;
  17.         temp = new double[n];
  18.         for(i=1;i<=n;i++)
  19.         {
  20.                 temp[i-1]=point[i-1];
  21.         }
  22.         for(i=1;i<=n;i++)
  23.         {
  24.                 temp[i-1]+=0.5*h;
  25.                 grad[i-1]=4*pf(temp)/(3*h);
  26.                 temp[i-1]-=h;
  27.                 grad[i-1]-=4*pf(temp)/(3*h);
  28.                 temp[i-1]+=(3*h/2);
  29.                 grad[i-1]-=(pf(temp)/(6*h));
  30.                 temp[i-1]-=(2*h);
  31.                 grad[i-1]+=(pf(temp)/(6*h));
  32.                 temp[i-1]=point[i-1];
  33.         }
  34.         delete[] temp;
  35. }

  36. //一维搜索模块
  37. //参数:指向目标函数的指针,变量个数,出发点,搜索方向
  38. //返回:最优步长
  39. double line_search(
  40.                                    double (*pf)(double *x),
  41.                                    int n,
  42.                                    double *start,
  43.                                    double *direction)
  44. {
  45.         int i;
  46.         double step=0.001;
  47.         double a=0,value_a,diver_a;
  48.         double b,value_b,diver_b;
  49.         double t,value_t,diver_t;
  50.         double s,z,w;
  51.         double *grad,*temp_point;

  52.         grad=new double[n];
  53.         temp_point=new double[n];
  54.         comput_grad(pf,n,start,grad);
  55.         diver_a=0;
  56.         for(i=1;i<=n;i++)
  57.                 diver_a=diver_a+grad[i-1]*direction[i-1];
  58.         do
  59.         {
  60.                 b=a+step;
  61.                 for(i=1;i<=n;i++)
  62.                         temp_point[i-1]=start[i-1]+b*direction[i-1];
  63.                 comput_grad(pf,n,temp_point,grad);
  64.                 diver_b=0;
  65.                 for(i=1;i<=n;i++)
  66.                         diver_b=diver_b+grad[i-1]*direction[i-1];
  67.                 if( fabs(diver_b)<1E-10 )
  68.                 {
  69.                         delete[] grad;
  70.                         delete[] temp_point;
  71.                         return(b);
  72.                 }
  73.                 if( diver_b<-1E-15 )
  74.                 {
  75.                         a=b;
  76.                         diver_a=diver_b;
  77.                         step=2*step;
  78.                 }
  79.         }while( diver_b<=1E-15 );

  80.         for(i=1;i<=n;i++)
  81.                 temp_point[i-1]=start[i-1]+a*direction[i-1];
  82.         value_a=(*pf)(temp_point);
  83.         for(i=1;i<=n;i++)
  84.                 temp_point[i-1]=start[i-1]+b*direction[i-1];
  85.         value_b=(*pf)(temp_point);

  86.         do
  87.         {
  88.                 s=3*(value_b-value_a)/(b-a);
  89.                 z=s-diver_a-diver_b;
  90.                 w=sqrt( fabs(z*z-diver_a*diver_b) );        //////////////////!!!!!!!!!!!!!!!!!!!!!!
  91.                 t=a+(w-z-diver_a)*(b-a)/(diver_b-diver_a+2*w);
  92.                 value_b=(*pf)(temp_point);
  93.                 for(i=1;i<=n;i++)
  94.                         temp_point[i-1]=start[i-1]+t*direction[i-1];
  95.                 value_t=(*pf)(temp_point);
  96.                 comput_grad(pf,n,temp_point,grad);
  97.                 diver_t=0;
  98.                 for(i=1;i<=n;i++)
  99.                         diver_t=diver_t+grad[i-1]*direction[i-1];
  100.                 if(diver_t>1E-6)
  101.                 {
  102.                         b=t;
  103.                         value_b=value_t;
  104.                         diver_b=diver_t;
  105.                 }
  106.                 else if(diver_t<-1E-6)
  107.                 {
  108.                         a=t;
  109.                         value_a=value_t;
  110.                         diver_a=diver_t;
  111.                 }
  112.                 else break;
  113.         }while( (fabs(diver_t)>=1E-6) && (fabs(b-a)>1E-6) );

  114.         delete[] grad;
  115.         delete[] temp_point;
  116.         return(t);

  117. }

  118. //无约束变尺度法DFP函数声明
  119. //
  120. //参数:pf指向目标函数的指针,n变量个数,min_point接受初始点、存放结果
  121. //返回:极小点处函数值
  122. //
  123. double DFP(
  124.                    double (*pf)(double *x),
  125.                    int n,
  126.                    double *min_point
  127.                    )
  128. {
  129.         int i,j;
  130.         int k=0;
  131.         double e=1E-5;
  132.         double g_norm;
  133.                
  134.         double *g0=new double[n];                //梯度
  135.         double *g1=new double[n];
  136.         double *dg=new double[n];

  137.         double *p=new double[n];                //搜索方向 =-g
  138.         double t;                                                //一维搜索步长

  139.         double *x0=new double[n];
  140.         double *x1=new double[n];
  141.         double *dx=new double[n];

  142.         double **H=new double*[n];
  143.         for (i=0; i<n; i++)                H[i] = new double[n];

  144.         double **tempH=new double*[n];
  145.         for (i=0; i<n; i++)                tempH[i] = new double[n];

  146.         double *gH=new double[n];
  147.         double *Hg=new double[n];
  148.         double num1;
  149.         double num2;



  150.         for(i=0;i<n;i++)
  151.                 for(j=0;j<n;j++)
  152.                 {
  153.                         if(i==j)        H[i][j]=1.0;        // H0=I
  154.                         else        H[i][j]=0.0;
  155.                         tempH[i][j]=0.0;
  156.                 }


  157.         for(i=0;i<n;i++)
  158.                 x0[i]=min_point[i];       

  159.         comput_grad(pf,n,x0,g0);

  160.         g_norm=0.0;
  161.         for(i=0;i<n;i++)        g_norm=g_norm+g0[i]*g0[i];       
  162.         g_norm=sqrt(g_norm);
  163.         if (g_norm<e)
  164.         {
  165.                 for(i=0;i<n;i++)        min_point[i]=x0[i];

  166.                 delete[] g0;               
  167.                 delete[] g1;
  168.                 delete[] dg;
  169.                 delete[] p;
  170.                 delete[] x0;
  171.                 delete[] x1;
  172.                 delete[] dx;
  173.                 for (i=0; i<n; i++)                delete[] H[i];
  174.                 delete []H;
  175.                 for (i=0; i<n; i++)                delete[] tempH[i];
  176.                 delete []tempH;
  177.                 delete[] gH;
  178.                 delete[] Hg;

  179.                 return pf(min_point);
  180.         }

  181.         for(i=0;i<n;i++)        p[i]=-g0[i];       

  182.         do
  183.         {
  184.                 t=line_search(pf,n,x0,p);                               
  185.                 for(i=0;i<n;i++)        x1[i]=x0[i]+t*p[i];
  186.                 comput_grad(pf,n,x1,g1);
  187.                 g_norm=0.0;
  188.                 for(i=0;i<n;i++)        g_norm=g_norm+g1[i]*g1[i];
  189.                 g_norm=sqrt(g_norm);
  190.                 //cout<<k<<"    "<<x0[0]<<"       "<<x0[1]<<"       "<<g_norm<<"\n";
  191.                 if (g_norm<e)
  192.                 {
  193.                         for(i=0;i<n;i++)        min_point[i]=x1[i];

  194.                         delete[] g0;               
  195.                         delete[] g1;
  196.                         delete[] dg;
  197.                         delete[] p;
  198.                         delete[] x0;
  199.                         delete[] x1;
  200.                         delete[] dx;
  201.                         for (i=0; i<n; i++)                delete[] H[i];
  202.                         delete []H;
  203.                         for (i=0; i<n; i++)                delete[] tempH[i];
  204.                         delete []tempH;
  205.                         delete[] gH;
  206.                         delete[] Hg;
  207.                        
  208.                         return pf(min_point);
  209.                 }
  210.                 for(i=0;i<n;i++)
  211.                 {
  212.                         dx[i]=x1[i]-x0[i];
  213.                         dg[i]=g1[i]-g0[i];
  214.                 }

  215.                 //////////////////求Hk+1的矩阵运算

  216.                 //g*H,H*g
  217.                 for(i=0;i<n;i++)
  218.                 {
  219.                         gH[i]=0.0;
  220.                         Hg[i]=0.0;
  221.                 }
  222.                 for(i=0;i<n;i++)
  223.                 {
  224.                         for(j=0;j<n;j++)
  225.                         {
  226.                                 gH[i]=gH[i]+dg[j]*H[j][i];
  227.                                 //Hg[i]=Hg[i]+H[i][j]*dg[j];
  228.                                 Hg[i]=gH[i];
  229.                         }                       
  230.                 }

  231.                 //num1,num2
  232.                 num1=0.0;
  233.                 num2=0.0;
  234.                 for(i=0;i<n;i++)
  235.                 {
  236.                         num1=num1+dx[i]*dg[i];
  237.                         num2=num2+gH[i]*dg[i];
  238.                 }

  239.                 //tempH[i][j]
  240.                 for(i=0;i<n;i++)
  241.                         for(j=0;j<n;j++)
  242.                                 tempH[i][j]=0.0;
  243.                 for(i=0;i<n;i++)
  244.                 {
  245.                         for(j=0;j<n;j++)
  246.                         {
  247.                                 tempH[i][j]=tempH[i][j]+H[i][j];
  248.                                 tempH[i][j]=tempH[i][j]+dx[i]*dx[j]/num1;
  249.                                 tempH[i][j]=tempH[i][j]-Hg[i]*gH[j]/num2;
  250.                         }
  251.                 }

  252.                 for(i=0;i<n;i++)
  253.                 {
  254.                         for(j=0;j<n;j++)
  255.                         {
  256.                                 H[i][j]=tempH[i][j];
  257.                         }
  258.                 }
  259.                 /////////////////////////////

  260.                 //P
  261.                 for(i=0;i<n;i++)        p[i]=0.0;
  262.                 for(i=0;i<n;i++)
  263.                 {
  264.                         for(j=0;j<n;j++)
  265.                         {
  266.                                 p[i]=p[i]-H[i][j]*g1[j];
  267.                         }                       
  268.                 }

  269.                 for(i=0;i<n;i++)
  270.                 {
  271.                         g0[i]=g1[i];
  272.                         x0[i]=x1[i];
  273.                 }
  274.                 k=k+1;
  275.         }while(g_norm>e);

  276.         for(i=0;i<n;i++)        min_point[i]=x1[i];

  277.         delete[] g0;               
  278.         delete[] g1;
  279.         delete[] dg;
  280.         delete[] p;
  281.         delete[] x0;
  282.         delete[] x1;
  283.         delete[] dx;
  284.         for (i=0; i<n; i++)                delete[] H[i];
  285.         delete []H;
  286.         for (i=0; i<n; i++)                delete[] tempH[i];
  287.         delete []tempH;
  288.         delete[] gH;
  289.         delete[] Hg;

  290.         return pf(min_point);
  291. }

  292. /////////////
  293. double fun(double *x)
  294. {
  295.         return 100*( x[1]-x[0]*x[0] )*( x[1]-x[0]*x[0] ) + (1-x[0])*(1-x[0]);
  296. }

  297. void main()
  298. {
  299.         int n=2;
  300.         double min_point[2]={-5,10};
  301.         double min_value=DFP(fun,n,min_point);
  302.         cout<<min_point[0]<<" and "<<min_point[1]<<"   "<<min_value;

  303. }

  304. //0.618法线搜索
  305. //
  306. //参数:指向目标函数的指针,变量个数,出发点,搜索方向
  307. //返回:最优步长
  308. //
  309. double line_search1(
  310.                                    double (*pf)(double *x),
  311.                                    int n,
  312.                                    double *start,
  313.                                    double *direction)
  314. {
  315.         int i;
  316.         int k;

  317.         double l,a,b,c,u,lamda,t,e;

  318.         double *xa=new double[n];
  319.         double *xb=new double[n];
  320.         double *xc=new double[n];
  321.         double *xl=new double[n];
  322.         double *xu=new double[n];

  323.        
  324.         //确定初始搜索区间
  325.         l=0.001;
  326.         a=0;

  327.         k=0;
  328.         do
  329.         {
  330.                 k++;
  331.                 c=a+l;
  332.                 for(i=0;i<n;i++)
  333.                 {
  334.                         xc[i]=start[i]+c*direction[i];
  335.                         xa[i]=start[i]+a*direction[i];
  336.                 }
  337.                 l=l/3;
  338.         }while( pf(xc) >= pf(xa) );                        // ???

  339.         k=0;
  340.         do
  341.         {
  342.                 k++;
  343.                 l=2*l;
  344.                 b=c+l;
  345.                 for(i=0;i<n;i++)
  346.                 {
  347.                         xc[i]=start[i]+c*direction[i];
  348.                         xb[i]=start[i]+b*direction[i];
  349.                 }
  350.                 a=c;
  351.                 c=b;
  352.         }while( pf(xb) <= pf(xc) );


  353.         a=0;
  354.         b=0.1;

  355.         //寻优
  356.         t=0.618;
  357.         e=0.000001;

  358.         lamda=b-t*(b-a);
  359.         u=a+t*(b-a);
  360.        
  361.         for(i=0;i<n;i++)
  362.         {
  363.                 xl[i]=start[i]+lamda*direction[i];
  364.                 xu[i]=start[i]+u*direction[i];
  365.         }

  366.         k=0;
  367.         do
  368.         {
  369.                 k++;
  370.                 if( pf(xl)<pf(xu) )
  371.                 {
  372.                         b=u;
  373.                         u=lamda;
  374.                         lamda=b-t*(b-a);
  375.                 }
  376.                 else
  377.                 {
  378.                         a=lamda;
  379.                         lamda=u;
  380.                         u=t*(b-a);
  381.                 }
  382.         }while( b-a>=e );

  383.         lamda=(a+b)/2;

  384.         delete[] xa;
  385.         delete[] xb;
  386.         delete[] xc;
  387.         delete[] xl;
  388.         delete[] xu;
  389.        
  390.         return lamda ;

  391. }
复制代码

评分

1

查看全部评分

回复
分享到:

使用道具 举报

发表于 2007-5-26 21:41 | 显示全部楼层

回复 #1 风花雪月 的帖子

好贴,帮了我大忙,程序很好懂阿:lol :lol
发表于 2007-11-26 23:51 | 显示全部楼层
非常感谢,可以参考的资料
发表于 2008-7-8 10:04 | 显示全部楼层
非常感谢,看这个就是舒服啊!谢谢
发表于 2008-12-14 17:50 | 显示全部楼层
非常感谢,看这个就是舒服啊:@P
发表于 2009-8-26 11:03 | 显示全部楼层

不错 ,受用了!

不错 ,受用了!不错 ,受用了!
发表于 2012-5-7 17:36 | 显示全部楼层
参考~~谢谢
发表于 2012-6-17 10:07 | 显示全部楼层
谢谢学习了。
发表于 2012-7-18 22:57 | 显示全部楼层
拟牛顿法主要是什么思想呀,可否有个简介呀
发表于 2012-7-21 15:55 | 显示全部楼层
新人来学习一下先
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-12-28 12:34 , Processed in 0.104617 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表