成功—失败法和0.618法结合求出局部极小值的C语言实现

 

要求:

编程实现:1.成功失败法找到存在局部极小值的区间[a,b]             

                  2.在该区间内用0.618法找到局部极小值点,精确度为0.01

                 测试函数为:函数f(x)=x^4+x^3-x^2+1;

 

成功失败法找到区间[a,b]:

     1.取x,步长l>0,令k=0,若f(x+l)<=f(x),转3.否则,令l=-l,转2;

      首先选取点x,和步长l,判断f(x+l)是否小于等于f(x),若是,则证明现在朝着函数值下降的方向移动,若不是,证明现在朝着函数值上升的方向移动,这样不能找到局部极小值,所以改变移动方向,令l=-l;

     2.若f(x+l)<=f(x),转3,否则,转4.

     判断f(x+l)是否小于等于f(x),若是,则证明现在朝着函数值下降的方向移动,转3继续沿此方向移动,否则,证明已经找到一个区间,在该区间内存在局部极小值,转4,找到该区间。

     3.更新x,l和k的值,令x=x+l,l=l*2,k=k+1,转2.

     若现在朝着函数值下降的方向移动,则继续向此方向移动,更新x的值,令x=x+1,步长变为原来的2倍,l=l*2,转2继续判断。

     4.若k=0,则令a=x+l,b=x-l。若k>0,则令a = x-l/2,b = x+l;

     若k=0,则说明x已经在含极小值点的区间内了,即在第一步确定过x之后,不管朝着l方向走还是-l方向走,得到的函数值都比x点处的函数值大,此时便找到存在局部极小值的区间[x+l,x-l].若k>0,说明找到该区间时,至少朝着同一个方向走了两次,及l至少更新了一次,所以此时找到的区间为[x-l/2,x+l](或者{[x+l,x-l/2])

    找到存在一个局部极小值的区间之后,在该区间内用0.618黄金分割法求出该区间内的局部极小值

0.618法找到局部极小值:

    1.取n=a+0.618*(b-a),m=a+(b-n)。令r=f(m),g=f(n)。

     第一步从区间[a,b]内找出符合0.618比例的两个点m,n,求出其函数值。

    2.若r>g,转3,否则,转4.

    判断m和n两点处的函数值大小。

    3.令a=m,m=n,r=g,n=b-(m-a),g=f(n) 转5

    如果m点的函数值大于n点的函数值,则在区间[a,m]不可能存在极小值点,故丢掉[a,m]部分,令原来的m点为新的a点,原来的n点为新的m点,根据0.618的比例找出新的n点,同时函数值r和g的值也相应的更新。

    4.令b=n,n=m,g=r,m=a+(b-n),r=f(m),转5

    如果m点的函数值小于n点的函数值,则在区间[n,b]内不可能存在极小值点,故丢掉[n,b]部分,令原来的n点为新的b点,原来的m点为新的n点,根据0.618的比例找出新的m点,同时相应的更新r和g的函数值。

    5.若|b-a|<0.01,则找到局部极小值点(a+b)/2。否则,转2,进行继续循环直到满足所需的精度值,找到局部极小值点。

程序实现:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double f(double x){
	double y;
	y = pow(x,4)+pow(x,3)-pow(x,2)+1;
	return y;
}

int main () {
	
	double x=0,l=0.5;
	double a,b,c;
	double m,n,r,g;
	int k = 0;
	if(f(x+l)<=f(x)){
		    x=x+l;
		    l=l*2;
	        k=k+1;
			
		}
    else
		l=-l;
	while(1){
		if(f(x+l)<=f(x)){
			x=x+l;
			l=l*2;
			k=k+1;
		}
		else{
			break;
		}
	}
	if(k == 0){
		a = x+l;
	    b = x-l;
	}
	else{
		a = x-l/2;
		b = x+l;
	}
	if(a>b){
		c=a;
		a=b;
		b=c;
	}//成功失败法完成,找到区间[a,b],[a,b]区间内存在局部极小值
	//0.618法
	
	n = a+0.618*(b-a);
	m = a+(b-n);
	r=f(m);
	g=f(n);
	do{
	if(r>g){
		a=m;
		m=n;
		r=g;
		n=b-(m-a);
		g=f(n);
	}
	else{
		b=n;
		n=m;
		g=r;
		m=a+(b-n);
		r=f(m);
	}
	}while(abs(b-a)>=0.01);
	printf("局部极小值为:%f\n",(a+b)/2);
	system("pause");
	return 0;
}


 

 

 

你可能感兴趣的:(C语言,工程优化,0.618法,成功失败法)