前言
二次插值法是一种数值优化方法,用于求解函数的极小值。其基本思想是通过对函数进行二次插值来逼近极小值点的位置,并通过求解插值函数的极小值点来得到函数的极小值。
具体步骤如下:
- 选择一个起始点,并计算该点处的函数值和一阶导数值;
- 根据起始点和一阶导数值,构造一个二次插值函数,通常采用二次多项式来表示;
- 求解二次插值函数的极小值点,得到新的近似极小值点;
- 判断新的近似极小值点与前一次的近似极小值点之间的误差是否小于预设的精度要求,如果满足则停止迭代,否则返回步骤2,继续迭代。
需要注意的是,二次插值法可能会因为插值函数的形状而导致迭代过程不稳定,因此在实际应用中需要根据具体情况选择合适的起始点和迭代策略,以确保能够得到准确的极小值点。
算法流程图
注:其中的
h
h
h表示区间消去法的步长,具体可以看这篇文章。
算法代码
function Paowuxian_minValue(f_sym,x0,eps,N,h)
% f_sym为所求函数, 符号函数
% x0为初始点,默认为0
% eps为允许误差, 默认为1e-4
% N为最大迭代次数, 默认为500
% h为区间消去法迭代步长, 默认为0.01
if nargin < 2, x0 = 0; end
if nargin < 3, eps = 1e-4; end
if nargin < 4, N = 500; end
if nargin < 5, h = 0.01; end
f = matlabFunction(f_sym);
y = f(x0);
x = x0;
k = 0;
fprintf('函数f=%s迭代开始:\n',f_sym)
while true
k = k + 1;
c1 = (y(3) - y(1))/(x(3)-x(1));
c2 = ( (y(2)-y(1))/(x(2)-x(1)) - c1 ) / (x(2)-x(3));
xp = (1/2)*(x(1) + x(3) - c1/c2 );
yp = f(xp);
fprintf('k=%2.d, x1=%.4f, x2=%.4f, x3=%.4f, xp=%.4f, fp=%.4f\n',k,x(1),x(2),x(3),xp,yp);
if abs((y(2)-yp)/y(2)) < eps
if y(2)<yp
x_star = x(2);
else
x_star = xp;
end
y_star = f(x_star);
fprintf('已收敛!结果如下:\nk=%2.d, x1=%.4f, x2=%.4f, x3=%.4f, x_star=%.4f, f_star=%.4f',...
k,x(1),x(2),x(3),x_star,y_star);
break
end
if (xp - x(2))*h > 0
if y(2) >= yp
x(1) = x(2);
y(1) = y(2);
x(2) = xp;
y(2) = yp;
else
x(3) = xp;
y(3) = yp;
end
else
if y(2) >= yp
x(3) = x(2);
y(3) = y(2);
x(2) = xp;
y(2) = yp;
else
x(1) = xp;
y(1) = yp;
end
end
if k > N
fprintf('已经超出最大迭代次数%d!\n',N)
break
end
end
fprintf('\n\n')
end
测试
测试函数如下:
syms x
f1_sym = (1/4)*x.^4 - (4/3)*x.^3 + (5/2)*x.^2 - 2*x ;
f2_sym = 8*x.^3 - 2*x.^2 - 7*x + 3;
解析解
% 解析解
f1 = diff(f1_sym);
x1_min = double(vpa(solve(f1,x)));
f2 = diff(f2_sym);
x2_min = double(vpa(solve(f2,x)));
x1_min | x2_min |
---|---|
2.0000 | 0.6298 |
注:上表格仅展示了局部解。
算法解
x01 = [1,0,3];
x02 = [0,1,2];
eps1 = 1e-6;
eps2 = 1e-6;
N = 100;
Paowuxian_minValue(f1_sym,x01,eps1,N)
Paowuxian_minValue(f2_sym,x02,eps2,N)
迭代过程如下:
函数f=(5*x^2)/2 - 2*x - (4*x^3)/3 + x^4/4迭代开始:
k= 1, x1=1.0000, x2=0.0000, x3=3.0000, xp=1.2000, fp=-0.5856
k= 2, x1=0.0000, x2=1.2000, x3=3.0000, xp=1.1951, fp=-0.5854
k= 3, x1=1.1951, x2=1.2000, x3=3.0000, xp=1.2341, fp=-0.5869
k= 4, x1=1.2000, x2=1.2341, x3=3.0000, xp=1.2589, fp=-0.5880
k= 5, x1=1.2341, x2=1.2589, x3=3.0000, xp=1.2962, fp=-0.5901
k= 6, x1=1.2589, x2=1.2962, x3=3.0000, xp=1.3351, fp=-0.5927
k= 7, x1=1.2962, x2=1.3351, x3=3.0000, xp=1.3820, fp=-0.5966
k= 8, x1=1.3351, x2=1.3820, x3=3.0000, xp=1.4336, fp=-0.6017
k= 9, x1=1.3820, x2=1.4336, x3=3.0000, xp=1.4907, fp=-0.6082
k=10, x1=1.4336, x2=1.4907, x3=3.0000, xp=1.5507, fp=-0.6160
k=11, x1=1.4907, x2=1.5507, x3=3.0000, xp=1.6120, fp=-0.6247
k=12, x1=1.5507, x2=1.6120, x3=3.0000, xp=1.6718, fp=-0.6335
k=13, x1=1.6120, x2=1.6718, x3=3.0000, xp=1.7279, fp=-0.6417
k=14, x1=1.6718, x2=1.7279, x3=3.0000, xp=1.7784, fp=-0.6488
k=15, x1=1.7279, x2=1.7784, x3=3.0000, xp=1.8223, fp=-0.6544
k=16, x1=1.7784, x2=1.8223, x3=3.0000, xp=1.8594, fp=-0.6585
k=17, x1=1.8223, x2=1.8594, x3=3.0000, xp=1.8900, fp=-0.6615
k=18, x1=1.8594, x2=1.8900, x3=3.0000, xp=1.9146, fp=-0.6634
k=19, x1=1.8900, x2=1.9146, x3=3.0000, xp=1.9342, fp=-0.6647
k=20, x1=1.9146, x2=1.9342, x3=3.0000, xp=1.9496, fp=-0.6655
k=21, x1=1.9342, x2=1.9496, x3=3.0000, xp=1.9615, fp=-0.6660
k=22, x1=1.9496, x2=1.9615, x3=3.0000, xp=1.9707, fp=-0.6663
k=23, x1=1.9615, x2=1.9707, x3=3.0000, xp=1.9778, fp=-0.6664
k=24, x1=1.9707, x2=1.9778, x3=3.0000, xp=1.9832, fp=-0.6665
k=25, x1=1.9778, x2=1.9832, x3=3.0000, xp=1.9873, fp=-0.6666
k=26, x1=1.9832, x2=1.9873, x3=3.0000, xp=1.9904, fp=-0.6666
k=27, x1=1.9873, x2=1.9904, x3=3.0000, xp=1.9927, fp=-0.6666
k=28, x1=1.9904, x2=1.9927, x3=3.0000, xp=1.9945, fp=-0.6667
k=29, x1=1.9927, x2=1.9945, x3=3.0000, xp=1.9959, fp=-0.6667
k=30, x1=1.9945, x2=1.9959, x3=3.0000, xp=1.9969, fp=-0.6667
k=31, x1=1.9959, x2=1.9969, x3=3.0000, xp=1.9977, fp=-0.6667
k=32, x1=1.9969, x2=1.9977, x3=3.0000, xp=1.9982, fp=-0.6667
k=33, x1=1.9977, x2=1.9982, x3=3.0000, xp=1.9987, fp=-0.6667
k=34, x1=1.9982, x2=1.9987, x3=3.0000, xp=1.9990, fp=-0.6667
已收敛!结果如下:
k=34, x1=1.9982, x2=1.9987, x3=3.0000, x_star=1.9990, f_star=-0.6667
函数f=8*x^3 - 2*x^2 - 7*x + 3迭代开始:
k= 1, x1=0.0000, x2=1.0000, x3=2.0000, xp=0.5227, fp=-0.0629
k= 2, x1=0.0000, x2=0.5227, x3=1.0000, xp=0.5491, fp=-0.1223
k= 3, x1=0.5227, x2=0.5491, x3=1.0000, xp=0.6131, fp=-0.1998
k= 4, x1=0.5491, x2=0.6131, x3=1.0000, xp=0.6207, fp=-0.2024
k= 5, x1=0.6131, x2=0.6207, x3=1.0000, xp=0.6274, fp=-0.2034
k= 6, x1=0.6207, x2=0.6274, x3=1.0000, xp=0.6287, fp=-0.2034
k= 7, x1=0.6274, x2=0.6287, x3=1.0000, xp=0.6295, fp=-0.2034
k= 8, x1=0.6287, x2=0.6295, x3=1.0000, xp=0.6297, fp=-0.2034
k= 9, x1=0.6295, x2=0.6297, x3=1.0000, xp=0.6297, fp=-0.2034
已收敛!结果如下:
k= 9, x1=0.6295, x2=0.6297, x3=1.0000, x_star=0.6297, f_star=-0.2034
总代码
clc;clear;close all
%%
syms x
f1_sym = (1/4)*x.^4 - (4/3)*x.^3 + (5/2)*x.^2 - 2*x ;
f2_sym = 8*x.^3 - 2*x.^2 - 7*x + 3;
% 解析解
f1 = diff(f1_sym);
x1_min = double(vpa(solve(f1,x)));
f2 = diff(f2_sym);
x2_min = double(vpa(solve(f2,x)));
x01 = [1,0,3];
x02 = [0,1,2];
eps1 = 1e-6;
eps2 = 1e-6;
N = 100;
Paowuxian_minValue(f1_sym,x01,eps1,N)
Paowuxian_minValue(f2_sym,x02,eps2,N)
%%
function Paowuxian_minValue(f_sym,x0,eps,N,h)
% f_sym为所求函数, 符号函数
% x0为初始点,默认为0
% eps为允许误差, 默认为1e-4
% N为最大迭代次数, 默认为500
% h为区间消去法迭代步长, 默认为0.01
if nargin < 2, x0 = 0; end
if nargin < 3, eps = 1e-4; end
if nargin < 4, N = 500; end
if nargin < 5, h = 0.01; end
f = matlabFunction(f_sym);
y = f(x0);
x = x0;
k = 0;
fprintf('函数f=%s迭代开始:\n',f_sym)
while true
k = k + 1;
c1 = (y(3) - y(1))/(x(3)-x(1));
c2 = ( (y(2)-y(1))/(x(2)-x(1)) - c1 ) / (x(2)-x(3));
xp = (1/2)*(x(1) + x(3) - c1/c2 );
yp = f(xp);
fprintf('k=%2.d, x1=%.4f, x2=%.4f, x3=%.4f, xp=%.4f, fp=%.4f\n',k,x(1),x(2),x(3),xp,yp);
if abs((y(2)-yp)/y(2)) < eps
if y(2)<yp
x_star = x(2);
else
x_star = xp;
end
y_star = f(x_star);
fprintf('已收敛!结果如下:\nk=%2.d, x1=%.4f, x2=%.4f, x3=%.4f, x_star=%.4f, f_star=%.4f',...
k,x(1),x(2),x(3),x_star,y_star);
break
end
if (xp - x(2))*h > 0
if y(2) >= yp
x(1) = x(2);
y(1) = y(2);
x(2) = xp;
y(2) = yp;
else
x(3) = xp;
y(3) = yp;
end
else
if y(2) >= yp
x(3) = x(2);
y(3) = y(2);
x(2) = xp;
y(2) = yp;
else
x(1) = xp;
y(1) = yp;
end
end
if k > N
fprintf('已经超出最大迭代次数%d!\n',N)
break
end
end
fprintf('\n\n')
end
总结
这只是一个基础的示例,实际中还会有更具体的、更细致的要求,这就需要再做额外调整;另外本人也仍在学习中,这只是个人的学习笔记,可能还有一些不足之处,欢迎指正。
参考文献
主编白清顺. 机械优化设计.第6版 [M]. 2017.