无约束优化方法——进退法求函数极值(matlab实现)

一、进退法

进退法是一种重要的无约束优化方法,本文以求函数的极小值为例理解进退法的思想,事实上进退法作为一种思想应用相当广泛。
进退法顾名思义,就像人走路一样,以迭代的方式,不断得通过进退来逼近我们想要的答案(不一定是绝对精确的解,但是可以控制误差)

二、代码及讲解

clc
clear                         %清理屏幕
f=@ (x) (x-1).^2+1;           %这里以(x-1)^2+1为例
[x,y]=fminunc(f,rand(1,1))    %试用malab工具箱函数求解

symf=sym(f);
df1=diff(symf);
df1=matlabFunction(df1);      %用于求一阶导数的函数

err=0.001;                    %err表示误差
h=0.02;                       %步长
x0=-1;                        %初始搜索点

x=-200:200;
y=f(x);
plot(x,y);                   %画出函数图像

a=-1;                         %初始搜索区域
b=3;                          
ans=99999;                    %存最后答案,这里初值我们定义为一个很大的数,便于确定其是否曾被修改过,若未被修改则其值仍是99999

while abs((b-a)/2)>err        %我们尽可能地使a和b接近并恰好处于极值点的两端,这时我们可以在一定误差内认为a和b的平均值就是极值点的x坐标
    p=df1(x0);                %这里有两个值x0和x1,可以想象成人走路的过程,x0和x1是两条腿,但是这两条腿有时左腿在前,有时右腿在前
    if p<0                    %因为求极小值,所以当一阶导数小于0时,极值点在这个位置的右侧,于是我们向右走
        x1=x0+h;              %向右跨一步
        q=df1(x1);            %向右走就要用到另外一条腿x1,跨越之后有两种情况,一种是跨过极值点(x1与x0异号)一种是未跨过极值点(同号)
        if q>0                %如果异号,说明“走过了”那就缩短步长往回走(缩短步长是为了提高运算精度)
            b=x1;
            a=x0;
            h=h/2;
        elseif q<0            %如果同号,说明“还没到”那就增大步长往前走(增大步长是为了提高运算速度)
            x0=x1;
            h=h*2;
        else
            ans=x1;           %特殊情况是导数恰好为0,这时我们可以求得精确解
            break;
        end
    elseif p>0                %下面同理
         x1=x0-h;
         q=df1(x1);
         if q>0
             x0=x1;
             h=h*2;
         elseif q<0
             a=x1;
             b=x0;
             h=h/2;
         else
             ans=x1;
             break;
         end
    else 
        ans=x0;
        break;
    end
end    
if ans==99999                  %ans之前赋了一个很大的值,这里起标记作用,如果之前运算中,ans没有被修改过,则我们取(a+b)/2作为答案
    ans=(b+a)/2;
end
x=ans
y=f(ans)

输出样例:
x =

1.0000

y =

 1

x =

 1

y =

 1

上一组x和y是由matlab工具箱函数求出的,下面一组由进退法求出。注意所求结果的精确度与我们规定的步长和误差有关。

所以我们将一些地方做改变,比如将函数改为(x-1.1111).^2+1,这样的话,在初始步长只有0.02的时候,我们就难以求得绝对精确的解,输出样例:
x =

1.1111

y =

1.0000

x =

1.1106

y =

1.0000

例如我们再改变误差值err,在步长h仍为0.02时,将函数变为(x-1.11111111).^2+1,误差err定为0.001,输出样例:
x =

扫描二维码关注公众号,回复: 8625659 查看本文章
1.1111

y =

 1

x =

1.1106

y =

1.0000

但是如果我们将err变小,将err定为0.00001,则输出:
x =

1.1111

y =

1.0000

x =

1.1111

y =

1.0000

读者可以自行更改函数、h值和err值来进行试验,此外本文全部输出默认保留四位小数,读者也可以用vpa函数将输出精度调高来进行试验。

三、作者

Bowen
本文所有代码、注释及讲解均为作者原创,转载请注明出处。作者水平有限,如有纰漏,敬请斧正。欢迎大家一起学习交流。

发布了50 篇原创文章 · 获赞 7 · 访问量 1159

猜你喜欢

转载自blog.csdn.net/numb_ac/article/details/102994521