使用Pymoo库实现多目标优化算法优化自定义问题

一、本文的目的:

1、通过Pymoo库实现多目标优化算法,用于优化自定义问题,例如调度问题

二、重要库文件版本:

python 3.6

pymoo 0.6.1.2 

三、通过Pymoo实现多目标优化

3.0过程步骤:

  1. 定义问题
    • 是否启用并行计算
  2. 初始化算法
    • 设置各种算子
  3. 设置终止条件
  4. 组装部件,执行优化

3.1定义问题

定义问题包含变量数量、变量范围、约束数量、适应值计算函数等,下面是定义问题的相关参数。

import numpy as np
from pymoo.core.problem import ElementwiseProblem

class MyProblem(ElementwiseProblem):

    def __init__(self, **kwargs):
        super().__init__(n_var=2,
                         n_obj=2,
                         n_ieq_constr=2,
                         xl=np.array([-2,-2]),
                         xu=np.array([2,2]),
                         **kwargs)  # 在问题定义时可以设置并行计算的参数  
        # https://pymoo.org/problems/parallelization.html

    def _evaluate(self, x, out, *args, **kwargs):
        f1 = 100 * (x[0]**2 + x[1]**2)
        f2 = (x[0]-1)**2 + x[1]**2

        g1 = 2*(x[0]-0.1) * (x[0]-0.9) / 0.18
        g2 = - 20*(x[0]-0.4) * (x[0]-0.6) / 4.8

        out["F"] = [f1, f2]
        out["G"] = [g1, g2]

problem = MyProblem()

3.2初始化算法(设置算子相关参数)

 选择NSGA-II 多目标优化算法,设置各种算子,各种算子操作符open in new window,主要包括采样、选择、变异与交叉。

import numpy as np
from pymoo.core.problem import ElementwiseProblem

class MyProblem(ElementwiseProblem):

    def __init__(self, **kwargs):
        super().__init__(n_var=2,
                         n_obj=2,
                         n_ieq_constr=2,
                         xl=np.array([-2,-2]),
                         xu=np.array([2,2]),
                         **kwargs)  # 在问题定义时可以设置并行计算的参数  
        # https://pymoo.org/problems/parallelization.html

    def _evaluate(self, x, out, *args, **kwargs):
        f1 = 100 * (x[0]**2 + x[1]**2)
        f2 = (x[0]-1)**2 + x[1]**2

        g1 = 2*(x[0]-0.1) * (x[0]-0.9) / 0.18
        g2 = - 20*(x[0]-0.4) * (x[0]-0.6) / 4.8

        out["F"] = [f1, f2]
        out["G"] = [g1, g2]

problem = MyProblem()

3.3设置终止条件(例如,终止迭代次数)

通过设置代数为终止条件:

from pymoo.termination import get_termination
termination = get_termination("n_gen", 40)

3.4组装部件,执行优化

主要是组装前面的三种组件,执行优化:

from pymoo.optimize import minimize

res = minimize(problem,
               algorithm,
               termination,
               seed=1,  # seed 相同就能保证在任何地方执行的结果相同
               save_history=True, # 保存历史
               verbose=True)  # 输出优化过程  

X = res.X  # 结果中的自变量
F = res.F  # 结果中的目标量

3.5可视化

自变量的分布:

import matplotlib.pyplot as plt
xl, xu = problem.bounds()
plt.figure(figsize=(7, 5))
plt.scatter(X[:, 0], X[:, 1], s=30, facecolors='none', edgecolors='r')
plt.xlim(xl[0], xu[0])
plt.ylim(xl[1], xu[1])
plt.title("Design Space")
plt.show()

帕累托前沿:

plt.figure(figsize=(7, 5))
plt.scatter(F[:, 0], F[:, 1], s=30, facecolors='none', edgecolors='blue')
plt.title("Objective Space")
plt.show()

3.6完整可执行代码

import numpy as np
from pymoo.core.problem import ElementwiseProblem
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.operators.crossover.sbx import SBX
from pymoo.operators.mutation.pm import PM
from pymoo.operators.sampling.rnd import FloatRandomSampling
from pymoo.termination import get_termination
from pymoo.optimize import minimize
import matplotlib.pyplot as plt

class MyProblem(ElementwiseProblem):

    def __init__(self, **kwargs):
        super().__init__(n_var=2,
                         n_obj=2,
                         n_ieq_constr=2,
                         xl=np.array([-2,-2]),
                         xu=np.array([2,2]),
                         **kwargs)  # 在问题定义时可以设置并行计算的参数
        # https://pymoo.org/problems/parallelization.html

    def _evaluate(self, x, out, *args, **kwargs):
        f1 = 100 * (x[0]**2 + x[1]**2)
        f2 = (x[0]-1)**2 + x[1]**2

        g1 = 2*(x[0]-0.1) * (x[0]-0.9) / 0.18
        g2 = - 20*(x[0]-0.4) * (x[0]-0.6) / 4.8

        out["F"] = [f1, f2]
        out["G"] = [g1, g2]

problem = MyProblem()

algorithm = NSGA2(
    pop_size=40,     # 种群数量
    n_offsprings=10, # 每一代中从父代个体中产生的新个体的数量
    sampling=FloatRandomSampling(), # 用于生成初始种群的采样算子。
    crossover=SBX(prob=0.9, eta=15), # 交叉算法,模拟二进制
    # 交叉概率,分布指数,变异指数,上下限
    mutation=PM(eta=20),  # 变异算子,默认为多项式变异
    eliminate_duplicates=True, # 剔除重复项
)

termination = get_termination("n_gen", 40)

res = minimize(problem,
               algorithm,
               termination,
               seed=1,  # seed 相同就能保证在任何地方执行的结果相同
               save_history=True, # 保存历史
               verbose=True)  # 输出优化过程

X = res.X  # 结果中的自变量
F = res.F  # 结果中的目标量

xl, xu = problem.bounds()
plt.figure(figsize=(7, 5))
plt.scatter(X[:, 0], X[:, 1], s=30, facecolors='none', edgecolors='r')
plt.xlim(xl[0], xu[0])
plt.ylim(xl[1], xu[1])
plt.title("Design Space")
plt.show()

plt.figure(figsize=(7, 5))
plt.scatter(F[:, 0], F[:, 1], s=30, facecolors='none', edgecolors='blue')
plt.title("Objective Space")
plt.show()

四、自定义问题

自定义问题需要解决的关键问题是,算法变量的定义和目标值的输出。

4.1、定义问题

import numpy as np
from pymoo.core.problem import ElementwiseProblem

class MyProblem(ElementwiseProblem):
    def __init__(self, Job,Machine, PT,Jobs_duetime,Jobs_duetime_slack, MachineStart,
                 Jobs_Windows_penalty_Type,TimeWindows_Penalty,Jobs_Wire_Type,Jobs_Frame_Type,xl,xu,**kwargs):
        super().__init__(n_var=Job,
                         n_obj=3,
                         n_ieq_constr=2,# 非等式约束
                         xl=xl,
                         xu=xu,
                         **kwargs)  # 在问题定义时可以设置并行计算的参数
        # https://pymoo.org/problems/parallelization.html

        # 调度优化过程所需参数
        self.Job = Job
        self.Machine = Machine
        self.PT = PT
        self.Jobs_duetime = Jobs_duetime
        self.Jobs_duetime_slack = Jobs_duetime_slack
        self.MachineStart = MachineStart
        self.Jobs_Windows_penalty_Type = Jobs_Windows_penalty_Type
        self.TimeWindows_Penalty = TimeWindows_Penalty
        self.Jobs_Wire_Type = Jobs_Wire_Type
        self.Jobs_Frame_Type = Jobs_Frame_Type
        self.xl = xl
        self.xu = xu

    def _evaluate(self, x, out, *args, **kwargs):
        f1 = 100 * (x[0]**2 + x[1]**2)
        f2 = (x[0]-1)**2 + x[1]**2

        g1 = 2*(x[0]-0.1) * (x[0]-0.9) / 0.18
        g2 = - 20*(x[0]-0.4) * (x[0]-0.6) / 4.8

        out["F"] = [f1, f2]
        out["G"] = [g1, g2]

problem = MyProblem()

其中,f1、f2是关于目标值的计算;

问题定义中的n_ieq_constr=2代表约束为2;

g1、g2是自变量x的约束范围,保证g1,g2≤0。

4.2、问题调用

problem = MyProblem()

五、展望

可以通过Pymoo官方网站找到关于NSGA-III和MOEA/D算法的调用,下面是关于NSGA-III和MOEA/D算法的使用,求解的问题是官网提供案例。

5.1、NSGA-III

相比于NSGA-II,NSGA-III需要加入一个新的参数定义。

5.1.1、需要添加的参数

# create the reference directions to be used for the optimization
ref_dirs = get_reference_directions("das-dennis", 3, n_partitions=12)

5.1.2、补全算法定义部分

# create the reference directions to be used for the optimization
ref_dirs = get_reference_directions("das-dennis", 3, n_partitions=12)

# create the algorithm object
algorithm = NSGA3(pop_size=92,
                  ref_dirs=ref_dirs)

5.1.3、可运行完整代码

from pymoo.algorithms.moo.nsga3 import NSGA3


from pymoo.optimize import minimize
from pymoo.problems import get_problem
from pymoo.util.ref_dirs import get_reference_directions
from pymoo.visualization.scatter import Scatter

# create the reference directions to be used for the optimization
ref_dirs = get_reference_directions("das-dennis", 3, n_partitions=12)

# create the algorithm object
algorithm = NSGA3(pop_size=92,
                  ref_dirs=ref_dirs)

# execute the optimization
res = minimize(get_problem("dtlz1"),
               algorithm,
               seed=1,
               termination=('n_gen', 600))

Scatter().add(res.F).show()

5.2、MOEA/D

5.2.1、需要添加的参数

ref_dirs = get_reference_directions("das-dennis", 3, n_partitions=12)

5.2.2、补全算法定义部分

ref_dirs = get_reference_directions("uniform", 3, n_partitions=12)

algorithm = MOEAD(
    ref_dirs,
    n_neighbors=15,
    prob_neighbor_mating=0.7,
)

5.2.3、可运行完整代码

from pymoo.algorithms.moo.moead import MOEAD
from pymoo.optimize import minimize
from pymoo.problems import get_problem
from pymoo.util.ref_dirs import get_reference_directions
from pymoo.visualization.scatter import Scatter

problem = get_problem("dtlz2")

ref_dirs = get_reference_directions("uniform", 3, n_partitions=12)

algorithm = MOEAD(
    ref_dirs,
    n_neighbors=15,
    prob_neighbor_mating=0.7,
)

res = minimize(problem,
               algorithm,
               ('n_gen', 200),
               seed=1,
               verbose=False)

Scatter().add(res.F).show()

六、参考文献与网站:

1、 重点参考个人笔记网站:Pymoo 多目标优化笔记 | 12Tall

2、 pymoo库源网站:pymoo - 经济部/D

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值