《数值计算方法》系列总目录
第一章 误差序列实验
第二章 非线性方程f(x)=0求根的数值方法
第三章 CAD模型旋转和AX=B的数值方法
第四章 插值与多项式逼近的数值计算方法
第五章 曲线拟合的数值方法
第六章 数值微分计算方法
第七章 数值积分计算方法
第八章 数值优化方法
第八章——内德-米德方法
一、算法原理
1、黄金分割搜索法
对于多元函数极值点的求解显然不能继续沿用第一节的方法,因为多元函数涉及到每个变量的偏导数,情况更加复杂。对于多元函数,内德-米德方法可以很好的利用迭代解决多元函数极小值点的问题。内德和米德提出了单纯形法,可用于求解多变量函数的局部极小值。对于双变量函数,单纯形即为三角形。通俗来讲,二元函数的单纯性就是由三个二元向量组成的集合,该方法通过模式搜索过程最终求解函数极小值点。比较三角形3个顶点处的函数值, 值最大的顶点为最差顶点
W
W
W,用一个新的顶点代替最差顶点,形成新的三角形式,然后继续这一过程。这一过程生成一系列三角形,函数在其顶点处的值越来越小,随着三角形的减小就可以找到极小值点的坐标。因此就需要确定以怎样的原则和搜索方向选取每次迭代的新增迭代点。通过推导,以如下原则进行迭代:
A. 初始三角形
B
G
W
BGW
BGW
设要求函数
f
(
x
,
y
)
f(x,y)
f(x,y)的极小值。首先,给定三角形的3个顶点 ,
k
=
1
,
2
,
3
k=1,2,3
k=1,2,3。在这3个点上对函数
f
(
x
,
y
)
f(x,y)
f(x,y)求值
z
k
=
f
(
x
k
,
y
k
)
{z_k} = f({x_k},{y_k})
zk=f(xk,yk),
k
=
1
,
2
,
3
k=1,2,3
k=1,2,3。下标编号满足
z
1
≤
z
2
≤
z
3
z_1≤z_2≤z_3
z1≤z2≤z3。用
B
=
(
x
1
,
y
1
)
,
G
=
(
x
2
,
y
2
)
,
W
=
(
x
3
,
y
3
)
B = ({x_1},{y_1}),G = ({x_2},{y_2}),W = ({x_3},{y_3}){\rm{ }}
B=(x1,y1),G=(x2,y2),W=(x3,y3)来帮助记忆。
B
B
B是最佳顶点,
G
G
G是次最佳顶点,而
W
W
W是最差顶点。
B. 良边的中点
构造过程使用了连接
B
B
B和
G
G
G的线段的中点。它可由平均坐标得到
M
=
B
+
G
2
=
(
x
1
+
x
2
2
,
y
1
+
y
2
2
)
M = \frac{{B + G}}{2} = \left( {\frac{{{x_1} + {x_2}}}{2},\frac{{{y_1} + {y_2}}}{2}} \right){\rm{ }}
M=2B+G=(2x1+x2,2y1+y2)C. 反射点
R
R
R
沿着三角形的边由
W
W
W向
B
B
B方向和由
W
W
W向
G
G
G方向,函数的值递减,因此以点
B
B
B和
G
G
G连线为分界线,与
W
W
W相对的点的函数值
f
(
x
,
y
)
f(x,y)
f(x,y)会较小。选择测试点R为关于边
B
G
BG
BG对三角形进行的"反射"。要确定点R,首先找到边
B
G
BG
BG的中点
M
M
M,然后从点
W
W
W到
M
M
M画线段,称其长度为
d
d
d。从
M
M
M点做该线段的延长线,长度为
d
d
d,得到点
R
R
R。
R
R
R的向量公式为
R
=
M
+
(
M
−
W
)
=
2
M
−
W
R = M + (M - W) = 2M - W
R=M+(M−W)=2M−W
D. 开拓点
E
E
E
如果
R
R
R处的函数值比
W
W
W处的函数值小,则求解的方向是正确的。可能极小值点的位置只比点
R
R
R略远一点。因此,将过
M
M
M和
R
R
R的线段延长到点
E
E
E,构成一个新的开拓三角形
B
G
E
BGE
BGE。点
E
E
E沿着连结
M
M
M和
R
R
R的线段的方向延长距离
d
d
d。如果
E
E
E处的函数值比
R
R
R处的小,则该顶点比
R
R
R好。点
E
E
E的向量公式为
E
=
R
+
(
R
−
M
)
=
2
R
−
M
E = R + (R - M) = 2R - M
E=R+(R−M)=2R−ME. 收缩点 C
如果点
R
R
R和
W
W
W的函数值相等,则需要测试另一个点。或许点
M
M
M处的函数值较小,但是为了保证构成三角形,不能用点
M
M
M替代
W
W
W。分别考虑两个线段
W
M
WM
WM和
M
R
MR
MR上的点
C
1
C_1
C1和
C
2
C_2
C2。具有较小函数值的点为
C
C
C,并由此构成三角形
B
G
C
BGC
BGC。注意在二维情况下,在点
C
1
C_1
C1和
C
2
C_2
C2之间选择看起来不合适,但在高维情况下这一点非常重要。
F. 向
B
B
B方向收缩
如果点
C
C
C处的函数值不小于
W
W
W处的值,则点
G
G
G和
W
W
W必将向
B
B
B的方向收缩。点
G
G
G置换为M,点W置换为
S
S
S,后者是连接
B
B
B和
W
W
W的线段中点。
到此,所有搜索步骤结束,通过反复的迭代,最终在误差精度范围内停止搜索得到极小值点。综上所述,内德-米德方法的基本流程如下所示:
二、实验内容及核心算法代码
内德-米德方法原理实现
由第一节原理部分可知,对于多元函数,内德-米德方法可以通过迭代的方法实现。对于 N N N元函数,需要 N + 1 N+1 N+1个点组成的单纯性进行迭代,最终找到极小值点。对于多元函数,求解良边的中点、反射点、拓展点和收缩点的方法类似。因此我们仅讨论二元函数的内德-米德方法的步骤。其基本流程如下:
- 对于给定的三个点进行排序,决定 B G W BGW BGW点的顺序。
- 求解良边 B G BG BG的中点并计算反射点,比较反射点的取值与 G G G点的取值。
- 若反射点小于 G G G点,则继续计算拓展点及其取值,若拓展点小于 B B B点,则将 W W W点替换为拓展点,若拓展点大于 B B B点,则将 W W W点替换为反射点;否则,计算收缩点。
- 若收缩点小于 W W W点,则将 W W W替换为收缩点;否则计算向 B B B方向收缩边的中点,并将 W G WG WG替换为 B B B方向收缩点。
- 重复步骤1-4,直到搜索点满足精度要求。
通过以上步骤我们可以发现,计算的过程主要集中在求解各个点及其函数值上,因此我们可以运用面向对象的编程方法,构造二元点类,设置其成员变量的为其横纵坐标,成员函数包括求解与另一二元点中点、拓展点以及该点处函数值,并且重载
+
∗
+*
+∗运算符方便程序使用。
因此通过以下实例对内德-米德方法进行试验。
- 使用内德-米德方法求解以下函数的极小值点。
对于三元、四元函数,需要4、5个点进行搜索迭代,并且求解各个迭代点的方式也有所不同,所构造的类也有所不同,但是核心思想都是基于迭代。
其核心函数算法代码为:
//---------------------------------Golden_section--------------------------------
void CmpExtremumPointbyNelder_Mead(TriPoint_3pt* Pt, TriPoint_3pt** ptset, int& iter, const float eps, const int Max_iter, int sign)
{
Sort_PtRelation(Pt, sign);
ptset[iter][0] = Pt[0];//best
ptset[iter][1] = Pt[1];//good1
ptset[iter][2] = Pt[2];//good2
ptset[iter][3] = Pt[3];//worst
++iter;
TriPoint_3pt B, G1, G2, W;
//the value sort is B<G1<G2<W
B = Pt[0]; G1 = Pt[1]; G2 = Pt[2]; W = Pt[3];
if (abs(W.fun_set(sign) - B.fun_set(sign)) < eps || iter >= Max_iter)
{
return;
}
TriPoint_3pt M, R;
M = B.CmpMeanpoint(G1, G2);
R = W.CmpReflectpoint(M);
R.fun_set(sign);
if (R.fun_set(sign) < G2.fun_set(sign))
{
if (R.fun_set(sign) > B.fun_set(sign))
{
W = R;
}
else
{
TriPoint_3pt E;
E = W.CmpExploitpoint(M);
if (E.fun_set(sign) < B.fun_set(sign))
{
W = E;
}
else
{
W = R;
}
}
}
else
{
if (R.fun_set(sign) < W.fun_set(sign))
{
W = R;
}
else
{
TriPoint_3pt C1, C2;
C1 = W.Cmp_IN_Contractionpoint(M);
C2 = W.Cmp_OUT_Contractionpoint(M);
if (C1.fun_set(sign) < W.fun_set(sign))
{
W = C1;
}
else if (C2.fun_set(sign) < W.fun_set(sign))
{
W = C2;
}
else
{
TriPoint_3pt S, M1, M2;
S = B.CmpMidpoint(W);
M1 = B.CmpMidpoint(G1);
M2 = B.CmpMidpoint(G2);
W = S;
G1 = M1;
G2 = M2;
}
}
}
Pt[0] = B; Pt[1] = G1; Pt[2] = G2; Pt[3] = W;
CmpExtremumPointbyNelder_Mead(Pt, ptset, iter, eps, Max_iter, sign);
}
四、结论
由实验结果可以看出,利用内德-米德方法求解多元函数极小值点的迭代次数较多,其收敛速度较慢,其原因是因为内德-米德方法搜索极小值点的方法完全是依靠判断两个方向的函数值进行盲目搜索,每次迭代过程中并没有准确的搜索方向,因此会导致搜索过程完全基于迭代比较,其原理与分类搜索法类似,因此参考分类搜索方法的实验结果可以知道内德-米德方法的搜索速度会很慢。然而如果初始值点选取好并且函数性质良好,有可能会减少搜索次数。
声明:本系列《数值计算方法》所有章节源代码均为作者编写,大家可以自行下载,仅供学习交流使用,欢迎大家评论留言或者私信交流,请勿用于任何商业行为。其中,各章实验数据结果也在资源链接中,大家可以自行实验对照,欢迎大家批评指正!文件中每个算法均由作者进行初步测试,部分算法可直接用于工程开发作为模块参考。