1 优化目标
多目标优化的标准形式如下:
min
f
m
(
x
)
m
=
1
,
…
,
M
s.t.
g
j
(
x
)
≤
0
j
=
1
,
…
,
J
h
k
(
x
)
=
0
k
=
1
,
…
,
K
x
i
L
≤
x
i
≤
x
i
U
i
=
1
,
…
,
N
x
∈
Ω
\begin{array}{lll} \min & f_{m}(x) & m=1, \ldots, M \\ \text { s.t. } & g_{j}(x) \leq 0 & j=1, \ldots, J \\ & h_{k}(x)=0 & k=1, \ldots, K \\ & x_{i}^{L} \leq x_{i} \leq x_{i}^{U} & i=1, \ldots, N \\ & x \in \Omega & \end{array}
min s.t. fm(x)gj(x)≤0hk(x)=0xiL≤xi≤xiUx∈Ωm=1,…,Mj=1,…,Jk=1,…,Ki=1,…,N
一个示意如下:
min
f
1
(
x
)
=
100
(
x
1
2
+
x
2
2
)
max
f
2
(
x
)
=
−
(
x
1
−
1
)
2
−
x
2
2
s.t.
g
1
(
x
)
=
2
(
x
1
−
0.1
)
(
x
1
−
0.9
)
≤
0
g
2
(
x
)
=
20
(
x
1
−
0.4
)
(
x
1
−
0.6
)
≥
0
−
2
≤
x
1
≤
2
−
2
≤
x
2
≤
2
x
∈
R
\begin{aligned} \min & f_{1}(x)=100\left(x_{1}^{2}+x_{2}^{2}\right) \\ \max & f_{2}(x)=-\left(x_{1}-1\right)^{2}-x_{2}^{2} \\ \text { s.t. } & g_{1}(x)=2\left(x_{1}-0.1\right)\left(x_{1}-0.9\right) \leq 0 \\ & g_{2}(x)=20\left(x_{1}-0.4\right)\left(x_{1}-0.6\right) \geq 0 \\ &-2 \leq x_{1} \leq 2 \\ &-2 \leq x_{2} \leq 2 \\ & x \in \mathbb{R} \end{aligned}
minmax s.t. f1(x)=100(x12+x22)f2(x)=−(x1−1)2−x22g1(x)=2(x1−0.1)(x1−0.9)≤0g2(x)=20(x1−0.4)(x1−0.6)≥0−2≤x1≤2−2≤x2≤2x∈R 该优化问题包含两个目标,其中
f
1
(
x
)
f_1(x)
f1(x)为最小化,
f
2
(
x
)
f_2(x)
f2(x)反之;两个不等式约束,以及两个变量。
注:该优化并不满足pymoo的输入要求,因为它不满足优化问题的标准形式。当然,该示意仅仅出于验证目的,并用于理解优化问题的设计过程与优化空间的映射。
2 Pareto最优解
f
1
f_1
f1的最小值取于
(
0
,
0
)
(0,0)
(0,0),
f
2
f_2
f2取于
(
1
,
0
)
(1,0)
(1,0)。由于这两个函数均为二次,最优解则由两个最优值之间的直线确定。在意味着忽略约束时,所有的Pareto最优解满足:
x
1
∈
(
1
,
0
)
,
x
2
=
0
x_1\in(1,0), x_2=0
x1∈(1,0),x2=0 进一步,需要满足
g
1
g_1
g1时,有
x
1
∈
(
0.1
,
0.9
)
x_1\in(0.1,0.9)
x1∈(0.1,0.9);满足
g
2
g_2
g2时,有
x
1
∈
(
0.4
,
0.6
)
x_1\in(0.4,0.6)
x1∈(0.4,0.6)。这表明Pareto最优集合被给定为:
P
S
=
{
(
x
1
,
x
2
)
∣
(
0.1
≤
x
1
≤
0.4
)
∨
(
0.6
≤
x
1
≤
0.9
)
∧
x
2
=
0
}
PS=\{(x_1,x_2)|(0.1\leq x_1\leq0.4)\vee(0.6\leq x_1\leq0.9)\wedge x^2=0\}
PS={(x1,x2)∣(0.1≤x1≤0.4)∨(0.6≤x1≤0.9)∧x2=0}
T
n
=
⋃
B
i
∈
T
∖
T
+
T_n = \bigcup B_i \in \mathcal{T}\setminus\mathcal{T}^+
Tn=⋃Bi∈T∖T+
接下来可视化
P
S
PS
PS,即图中橙色线条:
代码如下:
import numpy as np
import matplotlib.pyplot as plt
# 变量的搜索空间
X1, X2 = np.meshgrid(np.linspace(-2, 2, 500),
np.linspace(-2, 2, 500))
# 目标函数
F1 = X1 ** 2 + X2 ** 2
F2 = (X1 - 1) ** 2 + X2 ** 2
# 约束条件所在直线
G1 = 2 * (X1[0] - 0.1) * (X1[0] - 0.9)
G2 = 20 * (X1[0] - 0.4) * (X1[0] - 0.6)
# 图像大小
plt.figure(figsize=(7, 5))
# 确定等高线的数量和位置
levels = [0.02, 0.1, 0.25, 0.5, 0.8]
# 绘制
CS = plt.contour(X1, X2, F1, levels, colors='black', alpha=0.5)
# 添加当前等高线的标签
CS.collections[0].set_label("$f_1(x)$")
CS = plt.contour(X1, X2, F2, levels, linestyles="dashed", colors='black', alpha=0.5)
CS.collections[0].set_label("$f_2(x)$")
# 约束条件G1
plt.plot(X1[0], G1, linewidth=2.0, color="green", linestyle='dotted')
plt.plot(X1[0][G1 < 0], G1[G1 < 0], label="$g_1(x)$", linewidth=2.0, color="green")
# 约束条件G2
plt.plot(X1[0], G2, linewidth=2.0, color="blue", linestyle='dotted')
plt.plot(X1[0][X1[0] > 0.6], G2[X1[0] > 0.6], label="$g_2(x)$", linewidth=2.0, color="blue")
plt.plot(X1[0][X1[0] < 0.4], G2[X1[0] < 0.4], linewidth=2.0, color="blue")
# 绘制解
plt.plot(np.linspace(0.1, 0.4, 100), np.zeros(100), linewidth=3.0, color="orange")
plt.plot(np.linspace(0.6, 0.9, 100), np.zeros(100), linewidth=3.0, color="orange")
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1)
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
# 添加标签
plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.12), ncol=4, fancybox=True, shadow=False)
# 减少图片边缘空白
plt.tight_layout()
plt.show()
3 Pareto前沿
Pareto前沿反应了多个最优解 (Pareto最优) 下优化目标的变化情况。由于
x
2
=
0
x_2=0
x2=0,则
f
1
(
x
)
=
100
x
1
2
f_1(x)=100x_1^2
f1(x)=100x12且
f
2
(
x
)
=
−
(
x
1
−
1
)
2
f_2(x)=-(x_1-1)^2
f2(x)=−(x1−1)2,最终
f
1
f_1
f1与
f
2
f_2
f2的关系为:
f
2
=
(
f
1
100
−
1
)
2
f_2 = \left(\sqrt{\frac{f_1}{100}}-1\right)^2
f2=(100f1−1)2 通过计算,有
f
1
∈
[
1..16
]
f_1\in[1..16]
f1∈[1..16]、
f
2
∈
[
36..81
]
f_2\in[36..81]
f2∈[36..81],则该公式的可视化如下:
代码如下:
import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(7, 5))
# 两个目标函数的关系函数
f2 = lambda f1: - ((f1 / 100) ** 0.5 - 1) ** 2
F1_a, F1_b = np.linspace(1, 16, 300), np.linspace(36, 81, 300)
F2_a, F2_b = f2(F1_a), f2(F1_b)
plt.plot(F1_a, F2_a, linewidth=2.0, color="green", label="Pareto-front")
plt.plot(F1_b, F2_b, linewidth=2.0, color="green")
plt.xlabel("$f_1$")
plt.ylabel("$f_2$")
plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=False)
plt.tight_layout()
plt.show()