您的位置:首页 > 编程语言 > C语言/C++

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

2015-11-12 16:46 309 查看
 

要求:

编程实现: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;
}


 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息