共轭梯度法求函数极小值的方法,利用到了黄金分割和外推法求方向上的极小值。
#include
#include
#define lamda 0.618
//************************
float a,b,c,d,e,g;//目标函数的系数
float x1,x2,arf;//目标函数的变量
float a0[2],b0[2],c0[2];//一维搜索区间的变量定义
float xi1,xi2,xi3,xi4;
float min_gold_x[2];
float directon[2];//搜索方向
float powell_minx[2],xg_min[2];
float _g[2];
//***********************************
void get_num()
{
printf("输入目标函数系数\n");
scanf("%f %f %f %f %f %f",&a,&b,&c,&d,&g,&e);
printf("a=%f b=%f c=%f d=%f e=%f g=%f\n",a,b,c,d,e,g);
printf("\n目标函数为:\n");
printf("y=%f*x1*x1+%f*x2*x2+%f*x1+%f*x2+%f*x1*x2+%f\n",a,b,c,d,g,e);
}
//功能函数***************************
float fun(float x1,float x2)
{
float y;
y=a*x1*x1+b*x2*x2+c*x1+d*x2+g*x1*x2+e;
return y;
}
//*********计算步长***
float change(float h0,float d[2])
{
float m,n;
n=(d[0]*d[0]+d[1]*d[1])/(h0*h0);
m=sqrt(n);
return m;
}
//***区间搜索********************
void search(float x01,float x02,float h0,float d[2])
{
float y0,y1,y2,n,di[2],x1[2],x2[2],x0[2];
int j,k=0;
for(j=0;j<2;j++)//读取搜索方向
{
di[j]=d[j];
}
x0[0]=x01,x0[1]=x02;
n=change(h0,di);
di[0]=di[0]/n;
di[1]=di[1]/n;
x1[0]=x0[0]+di[0];
x1[1]=x0[1]+di[1];
y0=fun(x0[0],x0[1]);
y1=fun(x1[0],x1[1]);
if(y1<=y0)
{
for(j=0;j<2;j++)
{
di[j]=2*di[j];
x2[j]=x1[j]+di[j];
}
}
if(y1>y0)
{
for(j=0;j<2;j++)
{
di[j]=(-2)*di[j];
x2[j]=x1[j]+di[j];
}
}
while(1)
{
y2=fun(x2[0],x2[1]);
if(y2<=y1)
{
y0=y1;y1=y2;
for(j=0;j<2;j++)
{
x0[j]=x1[j];
x1[j]=x2[j];
}
for(j=0;j<2;j++)
{
di[j]=2*di[j];
x2[j]=x1[j]+di[j];
}
}
if(y2>y1)
{
for(j=0;j<2;j++)
{
a0[j]=x0[j];
b0[j]=x1[j];
c0[j]=x2[j];
}
break;
}
}
}
//*********************黄金分割********************
void gold_d(float a[2],float b[2],float dlt)
{
float alf1[2],alf2[2],y1,y2;
float at[2],bt[2],temp1[2],temp2[2];
float m,n,i,k;
int j;
/*dlt=dlt*dlt;*/
for(j=0;j<2;j++)
{
at[j]=a[j];
bt[j]=b[j];
}
for(j=0;j<2;j++)
{
alf1[j]=bt[j]-lamda*(bt[j]-at[j]);
alf2[j]=at[j]+lamda*(bt[j]-at[j]);
}
y1=fun(alf1[0],alf1[1]);
y2=fun(alf2[0],alf2[1]);
while(1)
{
if(y1>=y2)
{
for(j=0;j<2;j++)
{
at[j]=alf1[j];
alf1[j]=alf2[j];
}
y1=y2;
for(j=0;j<2;j++)
{
alf2[j]=at[j]+lamda*(bt[j]-at[j]);
}
y2=fun(alf2[0],alf2[1]);
}
else
{
for(j=0;j<2;j++)
{
bt[j]=alf2[j];
alf2[j]=alf1[j];
}
y2=y1;
for(j=0;j<2;j++)
{
alf1[j]=bt[j]-lamda*(bt[j]-at[j]);
}
y1=fun(alf1[0],alf1[1]);
}
for(j=0;j<2;j++)
{
temp1[j]=bt[j]-at[j];
}
n=(y2-y1)/y2;n=fabs(n);
m=temp1[0]*temp1[0]+temp1[1]*temp1[1];