c语言编程用进退法求搜索区间代码,用c对函数进行优化的问题
//多維無約束優化軟件設計#include
#include
#include
double det=1e-5; //計算精度double det1=1e-3; //梯度判斷精度double ak=3e-3; //搜索步長double dx=1e-4; //梯度計算步長
/*目標函數(n維)
入口參數:
x :n維數組,自變量
返回值 :函數值*/
double f(double *x)
{
double y;
y=(x[0]-2)*(x[0]-2)*(x[0]-2)*(x[0]-2)+(x[0]-2*x[1])*(x[0]-2*x[1]);
//y=(x[0]-2)^4+(x[0]-2*x[1])^2; return y;
}
/*計算X(k+1)=X(k)+a*S(k)
入口參數:
x_k : n維數組,自變量
s_k : n維數組,方向向量
a : 方向步長
n : 維數
出口參數:
x_k1 : 轉換后的n維數組*/
void fun(double *x_k1,double *x_k,double *s_k,double a,int n)
{
int i;
for(i=0;i
x_k1[i]=x_k[i]+a*s_k[i];
}
/*進退法求谷區間
入口參數:
n :優化模型維數
x_k :n維數組,初始點坐標
s_k :n維數組,搜索方向向量
出口參數:
a1 :搜索區間步長下限
a3 :搜索區間步長上限*/
void Get_Search_area(int n,double *x_k,double *s_k,double *a1,double *a3)
{
double a=ak,s,f0,a2=0;
double f1=0,f2=0,f3=0;
double *x_k1;
x_k1=(double*)malloc(sizeof(double)*n);
f2=f(x_k);
while(1)
{
*a1=a2+a;
fun(x_k1,x_k,s_k,*a1,n);
f1=f(x_k1);
if(f1>f2)
{
if(a==ak)
{
*a3=*a1;
f3=f1;
a=-a;
continue;
}
else if(*a1>*a3)
{
s=*a1;
*a1=*a3;
*a3=s;
f0=f1;
f1=f3;
f3=f0;
break;
}
else break;
}
else
{
*a3=a2;
a2=*a1;
f3=f2;
f2=f1;
a=2*a;
continue;
}
}
free(x_k1);
}
/*黃金分割法求極小值*/
/*入口參數:
n :優化模型維數
a1 :搜索區間步長下限
a4 :索區間步長上限
s_k :n維數組,搜索方向向量*/
/*出口參數:
x_k :n維數組,極小點坐標*/
void Gold_division(int n,double a1,double a4,double *x_k,double *s_k)
{
double a2,a3,f2,f3,a_star;
double *x_k2,*x_k3; int i;
x_k2=(double*)malloc(sizeof(double)*n);
x_k3=(double*)malloc(sizeof(double)*n);
for(i=0;i
{
x_k2[i]=0;
x_k3[i]=0;
}
a2=a1+0.382*(a4-a1);
fun(x_k2,x_k,s_k,a2,n);
f2=f(x_k2);
a3=a1+0.618*(a4-a1);
fun(x_k3,x_k,s_k,a3,n);
f3=f(x_k3);
do
{
if(f2<=f3)
{
a4=a3;
a3=a2;
f3=f2;
a2=a1+0.382*(a4-a1);
fun(x_k2,x_k,s_k,a2,n);
f2=f(x_k2);
}
else
{
a1=a2;
a2=a3;
f2=f3;
a3=a1+0.618*(a4-a1);
fun(x_k3,x_k,s_k,a3,n);
f3=f(x_k3);
}
} while(fabs(a4-a1)>det);
a_star=(a1+a4)*0.5;
fun(x_k,x_k,s_k,a_star,n);
free(x_k2);
free(x_k3);
}
/*計算函數梯度
入口參數:
n :優化模型維數
dx :梯度步長
x_k :n維數組,初始點坐標
出口參數:
s_k :梯度的負方向向量*/
void tidu(int n,double dx,double x[],double s_k[])
{
int i;
double *x0;
x0=(double*)malloc(sizeof(double)*n);
for(i=0;i
x0[i]=x[i];
for(i=0;i
{
x0[i]=x[i]+dx;
s_k[i]=(f(x0)-f(x))/dx*(-1);
x0[i]=x0[i]-dx;
}
free(x0);
}
/*計算梯度范數
入口參數:
n :優化模型維數
s_k :梯度的負方向向量
返回值:梯度范數*/
double f_fanshu(int n,double s_k[])
{
int i;
double sum=0;
for(i=0;i
sum+=s_k[i]*s_k[i];
return (sqrt(sum));
}
/*梯度法求最優函數值
/*入口參數:
n :優化模型維數
x_k :n維數組,極小點坐標*/
/*出口參數:
f0 :函數極小值*/
void fun_tidu(int n,double *x_k,double *f0)
{
double *s_k;
double a1=0,a3=0;
double *a_1,*a_3;
a_1=&a1;
a_3=&a3;
s_k=(double*)malloc(sizeof(double)*n);
while(1)
{ tidu(n,dx,x_k,s_k);
if(f_fanshu(n,s_k)>det1)
{
Get_Search_area(n,x_k,s_k,a_1,a_3);
Gold_division(n,*a_1,*a_3,x_k,s_k);
}
else
break;
}
*f0=f(x_k);
free(s_k);
}
/*主函數*/
int main()
{
int n,i;
double *x_k,*f;
double f0=0;
f=&f0;
puts("原函數為f=(x[0]-2)*(x[0]-2)*(x[0]-2)*(x[0]-2)+(x[0]-2*x[1])*(x[0]-2*x[1]);\n");
puts("請輸入變量維數n:\n");
scanf("%d",&n);
x_k=(double*)malloc(sizeof(double)*n);
printf("輸入起始坐標x_k:\n");
for(i=0;i
{
scanf("%lf",&x_k[i]);
fun_tidu(n,x_k,f);
}
puts("函數極小點坐標:\n");
for(i=0;i
printf("%lf;",x_k[i]);
printf("\n");
puts("函數最優值:\n");
printf("%lf\n",*f);
free(x_k);
return 0;
}
總結
以上是生活随笔為你收集整理的c语言编程用进退法求搜索区间代码,用c对函数进行优化的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何取消信用卡的消费备用金
- 下一篇: c语言将字母的acsaii,C语言上机实