powell.cpp

来自「优化设计中powell法的类」· C++ 代码 · 共 501 行

CPP
501
字号
#include <iostream.h>
#include <math.h>

double fxy1(double *p)
{
	return (10*(*p+*(p+1)-5)*(*p+*(p+1)-5)+(*p-*(p+1))*(*p-*(p+1)));
}


double fxy2(double *p)
{
	return ((*p-2)*(*p-2)+(*(p+1)-3)*(*(p+1)-3)+(*(p+2)-10)*(*(p+2)-10));
}

double fxy(double *p)
{ 
	return ((*p-2)*(*p-2)+(*(p+1)-3)*(*(p+1)-3)+1.0/(*p)+1.0/(*(p+1))); 
}
double fxy4(double *p)
{
	return(*p);
}
class powell
{
private:
	int n;
	double jing;
	double h;

	double kkk[6];



public:
	void tansuo(double *b,double *e1,int ii)
	{
	   int j; 

       double h0;
	   double yy2;
	   double x1,x2,x3,y1,y2,y3,xx,yy;
	 
	   h0 = h;
	 
	 
	   double *pm = new double [n];  //临时存放前一分量
	   double *pt = new double [n];  //临时存放探索分量
	   double *ee = new double [n];  //临时存放方向向量

	   double *p1 = new double [n];  //临时存放区间分量
	   double *p2 = new double [n];  //临时存放区间分量
	   double *p3 = new double [n];  //临时存放区间分量

	   
       double aa,bb,cc;  //用于探索区间
		
	   
	   for(j=0;j<n;j++)
		{
            *(pm+j) = *(b+j*(n+1)+ii-1);  //把初值传给pm  
		}
		aa = fxy(pm);   //把pm的函数值给aa

	
		for(j=0;j<n;j++)
		{
			*(ee+j) = *(e1+j*n+ii-1);  //设置ee为当前方向
		}


		

		for(j=0;j<n;j++)
		{
			*(pt+j) = *(pm+j)+*(ee+j)*h;   //向前一个步长
		}
        bb = fxy(pt);

			
		if(aa>bb)   
		{   
			for(j=0;j<n;j++)
				*(p2+j) = *(pt+j);  //pt当前值给p2
			
			cc = bb-10;  
			while(bb>cc)
			{
				h = h*2;
				for(j=0;j<n;j++)
					*(pt+j) = *(pt+j)+*(ee+j)*h;

				cc = fxy(pt);
			}

			for(j=0;j<n;j++)
			{
				*(p1+j) = *(pm+j);
				*(p3+j) = *(pt+j);
			}
			
			x1 = 0;
			x2 = h0;
			x3 = h0 + h;
			
		}
		else
		{
			cc = aa-10;
			h = -h/16;
			for(j=0;j<n;j++)
			{
				*(p3+j) = *(pt+j);
			}

			for(j=0;j<n;j++)
			{
				*(pt+j) = *(pm+j);
			}
				
			while(cc<aa)
			{
				h = 2*h;
				for(j=0;j<n;j++)
				{
					*(pt+j) = *(pt+j)+*(ee+j)*h;
				}
					
				cc = fxy(pt);
			}

		
			for(j=0;j<n;j++)
			{
				*(p1+j) = *(pt+j);
				*(p2+j) = *(pm+j);
			}

			x1 = h;
			x2 = 0;
			x3 = h0;
		}
       
		

		aa = fxy(p1);
		bb = fxy(p2);
		cc = fxy(p3);

		
            y1 = aa;
			y2 = bb;
			y3 = cc;
		
			double *zx = new double [n];
						
			yy = jing*10+y2+10;
			double xx2;
			xx = 0;
			while((yy-yy2)*(yy-yy2)>jing*100)
			{
				xx2 = xx;
				
				xx = 0.5*(x1+x3-((y3-y1)/(x3-x1)*(x2-x3))/((y2-y1)/(x2-x1)-(y3-y1)/(x3-x1)));  //二次插值公式
				yy2 = y2;
						
				for(j=0;j<n;j++)
				
					*(zx+j) = *(pm+j) + *(ee+j)*xx;
				                 				
               	yy = fxy(zx);

				if(xx<x2)
				{
					x3 = x2;
					x2 = xx;
					y3 = y2;
					y2 = yy;
                	
				}
				else
				{   
				
					x1 = x2;
				    x2 = xx;				
					y1 = y2;
					y2 = yy;
				}

				if(yy>1e+010||yy<-1e+010||yy2>1e+010||yy2<-1e+010)
				{
					xx = xx2;
					break;
				}

				
			}
		

		  delete zx;

		for(j=0;j<n;j++)	
		  *(b+j*(n+1)+ii) = *(pm+j) + *(ee+j)*xx;  //一维探索得到一个新点

		

		delete pt;
		
		delete pm;
		delete ee;

		delete p1;
		delete p2;
		delete p3;	

		

	}

	void action(int nn,double jingdu)
	{
		int i,j;
		double F0,F2,F3;
		double maxfc,aa,bb,cc,h0,yy2;
		int m;
		double x1,x2,x3,y1,y2,y3,xx,yy;


		n = nn;
		jing = jingdu;


		h = 10;  //设定初始步长
		h0 = h;

		double *e = new double [n*n];  //  方向向量
		double *p = new double [n*(n+1)];  // 存储全部点的分量
        
		
		for(i=0;i<n*(n+1);i++)  
			*(p+i) = i+1;

	
       
		for(i=0;i<n*n;i++)  //设置方向向量
		{
			if((i/n)==(i%n))
			       *(e+i) = 1;
			else 
				*(e+i) = 0;
		}
   
		double ass;
		ass = jing*jing+10;

   while(sqrt(ass)>jing)
   {  
	  for(i=1;i<n+1;i++)  //进行一维探索
	  {
		  h = 10;
		  tansuo(p,e,i);
	  }

	  

	  double *px = new double [n];
	  double *p0 = new double [n];
	  double *pn = new double [n];
	  double *pk = new double [n];  //方向

	  
	  

	  for(i=0;i<n;i++)         //设置始点,终点,反射点
	  {
          *(p0+i) = *(p+i*(n+1));
		  *(pn+i) = *(p+i*(n+1)+n);
          *(px+i) = 2**(p+i*(n+1)+n) - *(p+i*(n+1));
	  }	  *(pk+i) = *(p+i*(n+1)+n)-*(p+i*(n+1));

       F0 = fxy(p0);
	   F2 = fxy(pn);
	   F3 = fxy(px);

	   double *fx = new double [n+1];   // 记录各中间点的函数值
	   for(i=0;i<n+1;i++)
	   {
		   double *temp = new double [n];  //临时存储分量
		   for(j=0;j<n;j++)
		   {
			   *(temp+j) = *(p+j*(n+1)+i);
		   }
		   *(fx+i) = fxy(temp);
		   delete temp;
	   }
	   

	   double *fc = new double [n];  //存储n个函数值之差
	   for(i=0;i<n;i++)
	   {
		   *(fc+i) = *(fx+i) - *(fx+i+1);
	   }

	   maxfc = *fc;   //最大函数值差
	   for(i=0;i<n;i++)
	   {
		   if(*(fc+i)>maxfc)
		   {
			   maxfc = *(fc+i);
			   m = i;
		   }
	   }
	   delete fc;
	 
	   delete fx;

	   int some;
	   some = (F3>F0)&&(((F0-2*F2+F3)*(F0-F2-maxfc)*(F0-F2-maxfc))<(0.5*maxfc*(F0-F3)*(F0-F3)));
	   
	   if(0)
	   {
           h = 10;
		   for(i=m;i<n-1;i++)
			   for(j=0;j<n;j++)
				   *(e+j*n+i) = *(e+j*n+i+1);

		   for(j=0;j<n;j++)
		        *(e+j*n+n-1) = *(pk+j);

		   double *k1 = new double [n];
		   double *k2 = new double [n];
		   double *k3 = new double [n];
		   double *kt = new double [n];   //临时存储探索分量

		   aa = fxy(p0);

		   for(i=0;i<n;i++)
			   *(kt+i) = *(p0+i) + *(pk+i)*h;

		   bb = fxy(kt);

		   if(aa>bb)
		   {
			   for(i=0;i<n;i++)
				   *(k2+i) = *(kt+i);
			   cc = bb-10;

			   while(bb>cc)
			   {
				   h = h*2;
				   for(i=0;i<n;i++)
					   *(kt+i) = *(kt+i) + *(pk+i)*h;
				   cc = fxy(kt);
			   }

			   for(i=0;i<n;i++)
			   {
				   *(k1+i) = *(p0+i);
				   *(k3+i) = *(kt+i);
			   }
			 
			   x1 = 0;
			   x2 = h0;
			   x3 = h0 + h;
		   }

		   else
		   {
			   cc = aa-10;
			   h = -h/16;

			   for(i=0;i<n;i++)
				   *(k3+i) = *(kt+i);
			   for(i=0;i<n;i++)
				   *(kt+i) = *(p0+i);

			   while(cc<aa)
			   {
				   h = h*2;
				   for(i=0;i<n;i++)
					   *(kt+i) = *(kt+i) + *(pk+i)*h;
				   cc = fxy(kt);
			   }
			   for(i=0;i<n;i++)
			   {
				 *(k1+i) = *(kt+i);
				 *(k2+i) = *(p0+i);
			   }
			 
			   x1 = h;
			   x2 = 0;
			   x3 = h0;
		   }

		   aa = fxy(k1);
		   bb = fxy(k2);
		   cc = fxy(k3);

		   
            y1 = aa;
			y2 = bb;
			y3 = cc;
	
			double *zx = new double [n];
              			
			yy = jing*10+y2+10;
			double xx2;
			xx = 0;
			while((yy-yy2)*(yy-yy2)>jing*jing)
			{
				xx2 = xx;
				
				xx = 0.5*(x1+x3-((y3-y1)/(x3-x1)*(x2-x3))/((y2-y1)/(x2-x1)-(y3-y1)/(x3-x1)));  //二次插值公式
                yy2 = y2;

			for(j=0;j<n;j++)
				*(zx+j) = *(p0+j) + *(pk+j)*xx;
				
					yy = fxy(zx);

				if(xx<x2)
				{
					x3 = x2;
					x2 = xx;
					y3 = y2;
					y2 = yy;
				}
				else
				{					
					x1 = x2;
					x2 = xx;
					y1 = y2;
					y2 = yy;
				}
				if(yy>1e+010||yy<-1e+010||yy2>1e+010||yy2<-1e+010)
				{
					xx = xx2;
					break;
				}
									
			}
	

		  delete zx;

		   for(i=0;i<n;i++)
			   *(kt+i) = *(p0+i) + *(pk+i)*xx;   // kt是下一轮始点
		   for(i=0;i<n;i++)
			   *(p+i*(n+1)) = *(kt+i);    //输入初始位置

		   delete k1;
		   delete k2;
		   delete k3;
		   delete kt;
		   
	   }
	   else
	   {
		   if(F2>F3)
			   for(i=0;i<n;i++)
				   *(p+i*(n+1)) = *(px+i);
		   else
			   for(i=0;i<n;i++)
				   *(p+i*(n+1)) = *(pn+i);
			   
	   }

	   ass = 0;
       for(i=0;i<n;i++)
		   ass += (*(pn+i)-*(p0+i))*(*(pn+i)-*(p0+i));

	   for(i=0;i<2;i++)
		  kkk[i] = *(pk+i);

	   delete p0;
	   delete pn;
	   delete px;
	  // delete pk;   //??为什么不能delete
	  
      int bbs;
	  bbs = 8;
   }  

   for(i=0;i<n;i++)
	   cout<<endl<<*(p+i*(n+1));
       cout<<endl;
   delete e;
   delete p;
   
   
	}



};

void main()
{
	powell eg;

	eg.action(2,0.00001);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?