参考:fmincon的官方文档
Syntax
x = fmincon(fun,x0,A,b)
x = fmincon(fun,x0,A,b,Aeq,beq)
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub)
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon)
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)
x = fmincon(problem)
[x,fval] = fmincon(___)
[x,fval,exitflag,output] = fmincon(___)
[x,fval,exitflag,output,lambda,grad,hessian] = fmincon(___)
Description
求解带约束的非线性优化问题。 求解
f
(
x
)
f(x)
f ( x ) 满足约束的最小值,表达式如下:
min
x
f
(
x
)
满
足
{
c
(
x
)
≤
0
c
e
q
(
x
)
=
0
A
⋅
x
≤
b
A
e
q
⋅
x
=
b
e
q
l
b
≤
x
≤
u
b
\min_{x} f(x) \quad 满足 \quad \left\{ \begin{array}{lr} c(x) \leq 0 & \\ ceq(x) = 0 & \\ A \cdot x \leq b & \\ Aeq \cdot x = beq & \\ lb \leq x \leq ub \end{array} \right.
x min f ( x ) 满 足 ⎩ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎧ c ( x ) ≤ 0 c e q ( x ) = 0 A ⋅ x ≤ b A e q ⋅ x = b e q l b ≤ x ≤ u b
c
(
x
)
≤
0
c(x) \leq 0
c ( x ) ≤ 0 是非线性不等式约束;
c
e
q
(
x
)
=
0
ceq(x) = 0
c e q ( x ) = 0 是非线性等式约束;
A
⋅
x
≤
b
A \cdot x \leq b
A ⋅ x ≤ b 是线性不等式约束;
A
e
q
⋅
x
=
b
e
q
Aeq \cdot x = beq
A e q ⋅ x = b e q 是线性等式约束;
l
b
≤
x
≤
u
b
lb \leq x \leq ub
l b ≤ x ≤ u b 是
x
x
x 的上下界约束。 "
⋅
\cdot
⋅ "是点乘,
b
b
b 和
b
e
q
beq
b e q 是向量,
A
A
A 和
A
e
q
Aeq
A e q 是矩阵,
c
(
x
)
c(x)
c ( x ) 和
c
e
q
(
x
)
ceq(x)
c e q ( x ) 是返回一个向量,而
f
(
x
)
f(x)
f ( x ) 是返回一个标量。
f
(
x
)
f(x)
f ( x ) ,
c
(
x
)
c(x)
c ( x ) 和
c
e
q
(
x
)
ceq(x)
c e q ( x ) 可以是非线性函数。x ,lb 和 ub 可以是向量或矩阵;参见:Matrix Arguments 。
x
=
f
m
i
n
c
o
n
(
f
u
n
,
x
0
,
A
,
b
)
x = fmincon(fun,x0,A,b)
x = f m i n c o n ( f u n , x 0 , A , b ) 从
x
0
x0
x 0 开始,寻找一个
x
x
x , 满足
f
(
x
)
f(x)
f ( x ) 最小且满足约束
A
⋅
x
≤
b
A \cdot x ≤ b
A ⋅ x ≤ b 。
x
0
x0
x 0 可以是标量,向量或矩阵。
传递额外参数 说明了如何将额外参数传递给目标函数和非线性约束函数。
x
=
f
m
i
n
c
o
n
(
f
u
n
,
x
0
,
A
,
b
,
A
e
q
,
b
e
q
)
x = fmincon(fun,x0,A,b,Aeq,beq)
x = f m i n c o n ( f u n , x 0 , A , b , A e q , b e q ) 从
x
0
x0
x 0 开始,寻找一个
x
x
x ,满足
f
u
n
fun
f u n 最小且满足
A
e
q
⋅
x
=
b
e
q
Aeq \cdot x = beq
A e q ⋅ x = b e q 和
A
⋅
x
≤
b
A \cdot x ≤ b
A ⋅ x ≤ b . 如果没有不等式约束, 置
A
=
[
]
A = []
A = [ ] 、
b
=
[
]
b = []
b = [ ] .
x
=
f
m
i
n
c
o
n
(
f
u
n
,
x
0
,
A
,
b
,
A
e
q
,
b
e
q
,
l
b
,
u
b
)
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub)
x = f m i n c o n ( f u n , x 0 , A , b , A e q , b e q , l b , u b ) 从
x
0
x0
x 0 开始,寻找一个
x
x
x ,满足
f
u
n
fun
f u n 最小且满足
A
e
q
⋅
x
=
b
e
q
Aeq \cdot x = beq
A e q ⋅ x = b e q 、
A
⋅
x
≤
b
A \cdot x ≤ b
A ⋅ x ≤ b 且
l
b
≤
x
≤
u
b
lb ≤ x ≤ ub
l b ≤ x ≤ u b . 如果不存在等式约束, 设置
A
e
q
=
[
]
Aeq = []
A e q = [ ] 、
b
e
q
=
[
]
beq = []
b e q = [ ] . 如果
x
(
i
)
x(i)
x ( i ) 没有下界, 设置
l
b
(
i
)
=
−
I
n
f
lb(i) = -Inf
l b ( i ) = − I n f , 如果
x
(
i
)
x(i)
x ( i ) 没有上界, 置
u
b
(
i
)
=
I
n
f
ub(i) = Inf
u b ( i ) = I n f .
如果问题的输入范围(
l
b
lb
l b 和
u
b
ub
u b )不一致(原文是inconsistent),则
f
m
i
n
c
o
n
fmincon
f m i n c o n 会抛出错误。 在这种情况下,输出
x
x
x 为
x
0
x0
x 0 ,
f
v
a
l
fval
f v a l 为
[
]
[]
[ ] 。 对于默认的“interior-point”算法,
f
m
i
n
c
o
n
fmincon
f m i n c o n 将
x
x
x 中超出边界(
l
b
≤
x
≤
u
b
lb ≤ x ≤ ub
l b ≤ x ≤ u b )的分量设置为边界值。 对于“trust-region-reflective”算法,
f
m
i
n
c
o
n
fmincon
f m i n c o n 将
x
x
x 中超出边界的分量设置到边界内部。 对于其他算法,
f
m
i
n
c
o
n
fmincon
f m i n c o n 将
x
x
x 中超出边界的分量设置为最小的边界值。
x
x
x 中满足边界调节的分量不会更改。 请参阅迭代可以违反约束 。
x
=
f
m
i
n
c
o
n
(
f
u
n
,
x
0
,
A
,
b
,
A
e
q
,
b
e
q
,
l
b
,
u
b
,
n
o
n
l
c
o
n
)
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon)
x = f m i n c o n ( f u n , x 0 , A , b , A e q , b e q , l b , u b , n o n l c o n ) 从
x
0
x0
x 0 开始, 寻找一个
x
x
x , 满足线性约束
A
e
q
⋅
x
=
b
e
q
Aeq \cdot x = beq
A e q ⋅ x = b e q 、
A
⋅
x
≤
b
A \cdot x ≤ b
A ⋅ x ≤ b 、
l
b
≤
x
≤
u
b
lb ≤ x ≤ ub
l b ≤ x ≤ u b 以及非线性约束
c
(
x
)
≤
0
c(x) ≤ 0
c ( x ) ≤ 0 和
c
e
q
(
x
)
=
0
ceq(x) = 0
c e q ( x ) = 0 ,
c
(
x
)
c(x)
c ( x ) 和
c
e
q
(
x
)
ceq(x)
c e q ( x ) 定义在
n
o
n
l
c
o
n
nonlcon
n o n l c o n (一个函数) 中. 如果不存在下界, 置
l
b
=
[
]
lb = []
l b = [ ] ;如果不存在下界,置
u
b
=
[
]
ub = []
u b = [ ] .
x
=
f
m
i
n
c
o
n
(
f
u
n
,
x
0
,
A
,
b
,
A
e
q
,
b
e
q
,
l
b
,
u
b
,
n
o
n
l
c
o
n
,
o
p
t
i
o
n
s
)
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)
x = f m i n c o n ( f u n , x 0 , A , b , A e q , b e q , l b , u b , n o n l c o n , o p t i o n s ) 使用指定的选项
o
p
t
i
o
n
s
options
o p t i o n s 来优化问题. 使用 optimoptions 来设置这些选项. 如果没有非线性约束,置
n
o
n
l
c
o
n
=
[
]
nonlcon = []
n o n l c o n = [ ] .
x
=
f
m
i
n
c
o
n
(
p
r
o
b
l
e
m
)
x = fmincon(problem)
x = f m i n c o n ( p r o b l e m ) 寻找
p
r
o
b
l
e
m
problem
p r o b l e m 的最小值,
p
r
o
b
l
e
m
problem
p r o b l e m 是一种Input Arguments 中描述的结构(structure). 可以通过从Optimization app导出一个
p
r
o
b
l
e
m
problem
p r o b l e m , 参见Exporting Your Work .
[
x
,
f
v
a
l
]
=
f
m
i
n
c
o
n
(
_
_
_
)
[x,fval] = fmincon(\_\_\_)
[ x , f v a l ] = f m i n c o n ( _ _ _ ) , 对于任何调用形式,返回解
x
x
x 和在解
x
x
x 处目标函数
f
u
n
fun
f u n 的值。
[
x
,
f
v
a
l
,
e
x
i
t
f
l
a
g
,
o
u
t
p
u
t
]
=
f
m
i
n
c
o
n
(
_
_
_
)
[x,fval,exitflag,output] = fmincon(\_\_\_)
[ x , f v a l , e x i t f l a g , o u t p u t ] = f m i n c o n ( _ _ _ ) ,
e
x
i
t
f
l
a
g
exitflag
e x i t f l a g 表示
f
m
i
n
c
o
n
fmincon
f m i n c o n 退出的条件(退出的原因);output是一个结构(structure),描述了一些优化过程的信息。
[
x
,
f
v
a
l
,
e
x
i
t
f
l
a
g
,
o
u
t
p
u
t
,
l
a
m
b
d
a
,
g
r
a
d
,
h
e
s
s
i
a
n
]
=
f
m
i
n
c
o
n
(
_
_
_
)
[x,fval,exitflag,output,lambda,grad,hessian] = fmincon(\_\_\_)
[ x , f v a l , e x i t f l a g , o u t p u t , l a m b d a , g r a d , h e s s i a n ] = f m i n c o n ( _ _ _ ) 额外返回:
l
a
m
b
d
a
lambda
l a m b d a — Structure with fields containing the Lagrange multipliers at the solution x.
g
r
a
d
grad
g r a d —
f
u
n
fun
f u n 在解
x
x
x 处的梯度.
hessian —
f
u
n
fun
f u n 在解
x
x
x 处的Hessian矩阵. 参见 fmincon Hessian .
Examples
Linear Inequality Constraint
求Rosenbrock函数:
f
(
x
)
=
100
(
x
2
2
−
x
1
2
)
2
+
(
1
−
x
1
)
2
(1)
f(x) = 100(x_2^2 - x_1^2 )^2 + (1 - x_1)^2 \tag{1}
f ( x ) = 1 0 0 ( x 2 2 − x 1 2 ) 2 + ( 1 − x 1 ) 2 ( 1 ) 满足约束:
x
1
+
2
x
2
≤
1
(2)
x_1+ 2x_2 \leq 1 \tag{2}
x 1 + 2 x 2 ≤ 1 ( 2 ) 取得最小值时的
x
x
x 。Rosenbrock在无约束的情况下,最优解是
x
1
=
1
,
x
2
=
1
x_1=1, x_2=1
x 1 = 1 , x 2 = 1 ;但有约束2时,
1
+
2
∗
1
=
3
>
1
1 + 2*1 = 3 > 1
1 + 2 ∗ 1 = 3 > 1 ,所以(1, 1)不是有约束2的情况下最优解。
求解步骤如下:
目标函数 编写一个目标函数 fun (就是
f
(
x
)
f(x)
f ( x ) ,可以像下面一样写成一个匿名函数,也可以单独新建一个函数文件fun.m,在fun.m里编写目标函数的代码,并返回一个值):
fun = @(x)100*(x(2)-x(1)^2)^2 + (1-x(1))^2;
约束 约束2是一个线性不等式,需要表达成
A
⋅
x
≤
b
A \cdot x \leq b
A ⋅ x ≤ b 的形式。对于约束2,
A
=
[
1
,
2
]
,
b
=
1
A=[1, 2], b=1
A = [ 1 , 2 ] , b = 1 。对于
x
0
x_0
x 0 的初值,这里取
x
0
=
[
−
1
,
2
]
x_0 = [-1, 2]
x 0 = [ − 1 , 2 ] ;给
x
0
x_0
x 0 取初值时,如果知道
x
x
x 的解所在范围,可以去一个附近的值,如果不知道,随机取非零值 就行。
完整代码(复制到Matlab中,即可运行)
fun = @(x)100*(x(2)-x(1)^2)^2 + (1-x(1))^2;
x0 = [-1,2];
A = [1,2];
b = 1;
x = fmincon(fun,x0,A,b)
运行结果如下:
Local minimum found that satisfies the constraints.
Optimization completed because the objective function is non-decreasing in
feasible directions, to within the default value of the optimality tolerance,
and constraints are satisfied to within the default value of the constraint tolerance.
<stopping criteria details>
x =
0.5022 0.2489
两段英文是调用 fmincon 的结束原因(非常重要!一定要仔细看,有时候优化次数不够,就会在英文中体现出来 )。x 之后的就是优化的结果,
x
1
=
0.5022
,
x
2
=
0.2489
x_1 = 0.5022, x_2 = 0.2489
x 1 = 0 . 5 0 2 2 , x 2 = 0 . 2 4 8 9 。
Linear Inequality and Equality Constraint
求Rosenbrock函数:
f
(
x
)
=
100
(
x
2
2
−
x
1
2
)
2
+
(
1
−
x
1
)
2
(3)
f(x) = 100(x_2^2 - x_1^2 )^2 + (1 - x_1)^2 \tag{3}
f ( x ) = 1 0 0 ( x 2 2 − x 1 2 ) 2 + ( 1 − x 1 ) 2 ( 3 ) 满足约束:
{
x
1
+
2
x
2
≤
1
2
x
1
+
x
2
=
1
(4)
\left\{ \begin{array}{lr} x_1+ 2x_2 \leq 1 & \\ 2x_1 + x_2 = 1 \end{array} \right.\tag{4}
{ x 1 + 2 x 2 ≤ 1 2 x 1 + x 2 = 1 ( 4 ) 取得最小值时的
x
x
x 。
目标函数 目标函数和上面的一致:
fun = @(x)100*(x(2)-x(1)^2)^2 + (1-x(1))^2;
约束
x
1
+
2
x
2
≤
1
x_1+ 2x_2 \leq 1
x 1 + 2 x 2 ≤ 1 是线性不等式约束,需要改写成
A
⋅
x
≤
b
A \cdot x \leq b
A ⋅ x ≤ b 的形式,故
A
=
[
1
,
2
]
,
b
=
1
A=[1, 2], b=1
A = [ 1 , 2 ] , b = 1 。
2
x
1
+
x
2
=
1
2x_1 + x_2 = 1
2 x 1 + x 2 = 1 是线性等式约束,需要改写成
A
e
q
⋅
x
=
b
e
q
Aeq \cdot x = beq
A e q ⋅ x = b e q 的形式,故
A
e
q
=
[
2
,
1
]
,
b
e
q
=
1
Aeq=[2, 1], beq=1
A e q = [ 2 , 1 ] , b e q = 1 。
取
x
0
=
[
0.5
,
0
]
x_0=[0.5, 0]
x 0 = [ 0 . 5 , 0 ] 。
完整代码
fun = @(x)100*(x(2)-x(1)^2)^2 + (1-x(1))^2;
x0 = [0.5,0];
A = [1,2];
b = 1;
Aeq = [2,1];
beq = 1;
x = fmincon(fun,x0,A,b,Aeq,beq)
运行结果:
此处省略那两段英文
x =
0.4149 0.1701
Bound Constraints
求Rosenbrock函数:
f
(
x
)
=
100
(
x
2
2
−
x
1
2
)
2
+
(
1
−
x
1
)
2
(5)
f(x) = 100(x_2^2 - x_1^2 )^2 + (1 - x_1)^2 \tag{5}
f ( x ) = 1 0 0 ( x 2 2 − x 1 2 ) 2 + ( 1 − x 1 ) 2 ( 5 ) 满足约束:
{
0
≤
x
1
≤
1
0
≤
x
2
≤
2
(6)
\left\{ \begin{array}{lr} 0 \leq x_1 \leq 1 & \\ 0\leq x_2 \leq 2 \end{array} \right.\tag{6}
{ 0 ≤ x 1 ≤ 1 0 ≤ x 2 ≤ 2 ( 6 ) 取得最小值时的
x
x
x 。
约束 约束只有对
x
1
x_1
x 1 和
x
2
x_2
x 2 的取值范围有约束,这叫边界约束。边界约束可以分别为每一个元素指定上界和下界。对于本例的边界约束,写成代码是:
lb = [0,0]; % lb是下界
ub = [1,2]; % ub是上界
由于没有其他线性约束,故:
A = [];
b = [];
Aeq = [];
beq = [];
完整代码 取
x
0
=
[
0.5
,
1
]
x_0=[0.5 ,1]
x 0 = [ 0 . 5 , 1 ]
fun = @(x)1+x(1)/(1+x(2)) - 3*x(1)*x(2) + x(2)*(1+x(1));
lb = [0,0];
ub = [1,2];
A = [];
b = [];
Aeq = [];
beq = [];
x0 = [0.5,1];
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub)
运行结果:
x =
1.0000 2.0000
另外,当初值
x
0
x_0
x 0 的取值不同时,得到的优化结果可能也不同。 参见: Obtain the Objective Function Value 。
补充:如果
x
x
x 中某个元素的上界或者下界是无穷大? 假如边界约束如下:
{
1
≤
x
1
x
2
≤
4
(7)
\left\{ \begin{array}{lr} 1 \leq x_1 & \\ x_2 \leq 4 \end{array} \right. \tag{7}
{ 1 ≤ x 1 x 2 ≤ 4 ( 7 ) 改写成有上下界的形式就是:
{
1
≤
x
1
≤
+
∞
−
∞
≤
x
2
≤
4
(8)
\left\{ \begin{array}{lr} 1 \leq x_1 \leq +\infty & \\ -\infty \leq x_2 \leq 4 \end{array} \right. \tag{8}
{ 1 ≤ x 1 ≤ + ∞ − ∞ ≤ x 2 ≤ 4 ( 8 ) 那么有:
lb = [1, -Inf]; % lb是下界
ub = [Inf, 4]; % ub是上界
如果没有上界,那么上界就是Inf;如果没有下界,下界就是-Inf。
Nonlinear Constraints
求Rosenbrock函数:
f
(
x
)
=
100
(
x
2
2
−
x
1
2
)
2
+
(
1
−
x
1
)
2
(9)
f(x) = 100(x_2^2 - x_1^2 )^2 + (1 - x_1)^2 \tag{9}
f ( x ) = 1 0 0 ( x 2 2 − x 1 2 ) 2 + ( 1 − x 1 ) 2 ( 9 ) 满足约束:
{
0
≤
x
1
≤
0.5
0
≤
x
2
≤
0.8
(
x
1
−
1
3
)
2
+
(
x
2
−
1
3
)
2
≤
1.
5
2
(10)
\left\{ \begin{array}{lr} 0 \leq x_1 \leq 0.5 & \\ 0\leq x_2 \leq 0.8 & \\ (x_1 - \frac{1}{3})^2 + (x_2 - \frac{1}{3})^2 \leq 1.5^2 \end{array} \right. \tag{10}
⎩ ⎨ ⎧ 0 ≤ x 1 ≤ 0 . 5 0 ≤ x 2 ≤ 0 . 8 ( x 1 − 3 1 ) 2 + ( x 2 − 3 1 ) 2 ≤ 1 . 5 2 ( 1 0 ) 取得最小值时的
x
x
x 。
约束 除了
x
1
x_1
x 1 和
x
2
x_2
x 2 的边界有约束之外,还多了第三个非线性约束;含义是
x
1
x_1
x 1 和
x
2
x_2
x 2 组成的点,在圆心为
(
1
3
,
1
3
)
(\frac{1}{3}, \frac{1}{3})
( 3 1 , 3 1 ) 半径为1.5的圆内。 对于非线性约束,需要自己实现一个函数nonlcon ,来计算
c
(
x
)
c(x)
c ( x ) 和
c
e
q
(
x
)
ceq(x)
c e q ( x ) 。对于约束
(
x
1
−
1
3
)
2
+
(
x
2
−
1
3
)
2
≤
1.
5
2
(x_1 - \frac{1}{3})^2 + (x_2 - \frac{1}{3})^2 \leq 1.5^2
( x 1 − 3 1 ) 2 + ( x 2 − 3 1 ) 2 ≤ 1 . 5 2 ,需要转换为
c
(
x
)
≤
0
c(x) \leq 0
c ( x ) ≤ 0 的形式,所以需要把
1.
5
2
1.5^2
1 . 5 2 移动到表达式的左边,即:
(
x
1
−
1
3
)
2
+
(
x
2
−
1
3
)
2
−
1.
5
2
≤
0
(x_1 - \frac{1}{3})^2 + (x_2 - \frac{1}{3})^2 - 1.5^2 \leq 0
( x 1 − 3 1 ) 2 + ( x 2 − 3 1 ) 2 − 1 . 5 2 ≤ 0 ,故
c
(
x
)
=
(
x
1
−
1
3
)
2
+
(
x
2
−
1
3
)
2
−
1.
5
2
c(x) = (x_1 - \frac{1}{3})^2 + (x_2 - \frac{1}{3})^2 - 1.5^2
c ( x ) = ( x 1 − 3 1 ) 2 + ( x 2 − 3 1 ) 2 − 1 . 5 2 。
新建一个函数nonlcon.m,输入以下代码:
% nonlcon.m
function [c,ceq] = nonlcon(x)
c = (x(1)-1/3)^2 + (x(2)-1/3)^2 - (1.5)^2;
ceq = [];
c 就是
c
(
x
)
c(x)
c ( x ) (非线性不等式约束)的值;ceq就是
c
e
q
(
x
)
ceq(x)
c e q ( x ) (非线性等式约束)的值,因为本例中没有非线性等式约束,所以置为
[
]
[]
[ ]
完整代码
% example4.m
fun = @(x)1+x(1)/(1+x(2)) - 3*x(1)*x(2) + x(2)*(1+x(1));
lb = [0,0.2];
ub = [0.5,0.8];
A = [];
b = [];
Aeq = [];
beq = [];
x0 = [1/4,1/4];
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,@nonlcon)
运行结果:
x =
0.0000 0.2000
补充: 如果有多个非线性不等式约束或者多个非线性等式约束? 假如函数的约束如下:
{
c
1
(
x
)
≤
0
c
2
(
x
)
≤
0
c
e
q
1
(
x
)
=
0
c
e
q
2
(
x
)
=
0
(11)
\left \{ \begin{array}{lr} c_1(x) \leq 0 & \\ c_2(x) \leq 0 & \\ ceq_1(x) = 0 & \\ ceq_2(x) = 0 \end{array} \right. \tag{11}
⎩ ⎪ ⎪ ⎨ ⎪ ⎪ ⎧ c 1 ( x ) ≤ 0 c 2 ( x ) ≤ 0 c e q 1 ( x ) = 0 c e q 2 ( x ) = 0 ( 1 1 ) 那么,nonlcon.m的代码应是:
% nonlcon.m
function [c,ceq] = nonlcon(x)
c1 = ...
c2 = ...
ceq1 = ...
ceq2 = ...
c = [c1; c2];
ceq = [ceq1; ceq2];
其中:
c
1
=
c
1
(
x
)
,
c
2
=
c
2
(
x
)
,
c
e
q
1
=
c
e
q
1
(
x
)
,
c
e
q
2
=
c
e
q
2
(
x
)
c1 = c_1(x), c2 = c_2(x), ceq1=ceq_1(x), ceq2=ceq_2(x)
c 1 = c 1 ( x ) , c 2 = c 2 ( x ) , c e q 1 = c e q 1 ( x ) , c e q 2 = c e q 2 ( x ) 。就是说,有几个非线性不等式约束,
c
c
c 中就应该有几个元素,
c
e
q
ceq
c e q 同理。