matlab求單峯函數最小值

測試函數是-x*sin(x),求其在0~4.5上的最小值。

首先繪圖觀察一下:

fplot(@(x) -x*sin(x),[0,4.5]);
hold on;
fplot(@(x) -sin(x)-x*cos(x),[0,4.5]);
hold off;
legend('f(x)',"f'(x)");
xlabel('x');

[x,fval] = fmincon(@(x) -x*sin(x),2)

x =
2.028757520194786
fval =
-1.819705741159516

可以看到x在2附近f(x)取到最小值。

三點二次插值

下面構建三點二次插值函數:

function [p1,fval]=int2p3(f,xinterval)
p0=xinterval(1);
p2=xinterval(2);
p1=(p0+p2)/2;
while true
    x=[p0,p1,p2];
    y=[f(p0),f(p1),f(p2)];
    c=polyfit(x,y,2);
    p1_=-c(2)/2/c(1);
    if f(p1)<f(p1_)
        if p1<p1_
            p2=p1_;
        else
            p0=p1_;
        end
    else
        if p1<p1_
            p0=p1;
            p1=p1_;
        else
            p2=p1;
            p1=p1_;
        end
    end
    if p2-p0<0.001
        fval=f(p1);
        break
    end
end
end

測試:

>> [x,fval]=int2p3(@(x) -x*sin(x),[0,4.5])
x =
2.028757824672632
fval =
-1.819705741159653

點x的迭代過程如下圖:

最後收斂到2.029。

牛頓法

function [p1,fval]=newton(f,xinterval)
p0=xinterval(1);
p2=xinterval(2);
p1=(p0+p2)/2;
d=0.001;
while true
    p1_=(f(p1+d)-f(p1))/d;%一階導數
    p1_2=(f(p1)-f(p1-d))/d;
    p1__=(p1_-p1_2)/d;%二階導數
    p1next=p1-p1_/p1__;
    if abs(p1next-p1)<d
        fval=f(p1);
        break
    else
        p1=p1next;
    end
end
end

>> [x,fval]=newton(@(x) -x*sin(x),[0,4.5])
x =
2.028286879504392
fval =
-1.819705441320462

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章