目录
1.demo1--带约束的多目标背包问题的求解
2. demo2--带约束的多目标背包问题--扩展
3. demo3--一个离散决策变量的最小化目标的双目标优化问题的求解
4. demo4--如何通过先验知识来帮助进化
5. demo5--离散决策变量的最小化目标的双目标优化问题
# -*- coding: utf-8 -*-
"""一个带约束的多目标背包问题.
假设有5类物品,每类物品中包含着四个具体的物品,要求从这五种类别的物品中分别选择一个物品放进背包,
使背包内的物品总价最高,总体积最小,且背包的总质量不能超过92kg。用矩阵P代表背包中物品的价值;
矩阵R代表背包中物品的体积;矩阵C代表物品的质量。P,R,C的取值如下:
P=[[3,4,9,15,2], R=[[0.2, 0.3, 0.4, 0.6, 0.1], C=[[10,13,24,32,4],
[4,6,8,10,2.5], [0.25,0.35,0.38,0.45,0.15], [12,15,22,26,5.2],
[5,7,10,12,3], [0.3, 0.37,0.5, 0.5, 0.2], [14,18,25,28,6.8],
[3,5,10,10,2]] [0.3, 0.32,0.45,0.6, 0.2]] [14,14,28,32,6.8]]
分析:
这是一个0-1背包问题,但如果用一个元素为0或1的矩阵来表示哪些物品被选中,则不利于后面采用进
化算法进行求解。可以从另一种角度对背包问题进行编码:由于问题要求在每类物品均要选出一件,这里我
们可以用0, 1, 2, 3来表示具体选择哪件物品。因此染色体可以编码为一个元素属于{0, 1, 2, 3}的1x5Numpy ndarray一维数组,
比如:[0,0,0,0,0]表示从这五类物品中各选取第一个物品。
"""
import numpy as np
import geatpy as ea
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self, M=2):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
maxormins = [-1, 1] # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
Dim = 5 # 初始化Dim(决策变量维数)
varTypes = [1] * Dim # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
lb = [0] * Dim # 决策变量下界
ub = [3] * Dim # 决策变量上界
lbin = [1] * Dim # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1] * Dim # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
# 调用父类构造方法完成实例化
ea.Problem.__init__(self,
name,
M,
maxormins,
Dim,
varTypes,
lb,
ub,
lbin,
ubin)
# 添加几个属性来存储P、R、C
self.P = np.array([[3, 4, 9, 15, 2], [4, 6, 8, 10, 2.5],
[5, 7, 10, 12, 3], [3, 5, 10, 10, 2]])
self.R = np.array([[0.2, 0.3, 0.4, 0.6,
0.1], [0.25, 0.35, 0.38, 0.45,
0.15], [0.3, 0.37, 0.5, 0.5, 0.2],
[0.3, 0.32, 0.45, 0.6, 0.2]])
self.C = np.array([[10, 13, 24, 32, 4], [12, 15, 22, 26, 5.2],
[14, 18, 25, 28, 6.8], [14, 14, 28, 32, 6.8]])
def evalVars(self, Vars): # 目标函数
x = Vars.astype(int)
f1 = np.sum(self.P[x, [0, 1, 2, 3, 4]], 1)
f2 = np.sum(self.R[x, [0, 1, 2, 3, 4]], 1)
# 采用可行性法则处理约束
CV = np.array([np.sum(self.C[x, [0, 1, 2, 3, 4]], 1)]).T - 92
ObjV = np.vstack([f1, f2]).T
return ObjV, CV
# -*- coding: utf-8 -*-
"""该案例展示了一个带约束的多目标背包问题的求解。详见MyProblem.py."""
# from MyProblem import MyProblem # 导入自定义问题接口
import geatpy as ea # import geatpy
if __name__ == '__main__':
# 实例化问题对象
problem = MyProblem()
# 构建算法
algorithm = ea.moea_NSGA2_templet(
problem,
ea.Population(Encoding='BG', NIND=30),
MAXGEN=300, # 最大进化代数
logTras=0) # 表示每隔多少代记录一次日志信息,0表示不记录。
# 求解
res = ea.optimize(algorithm,
verbose=False,
drawing=1,
outputMsg=True,
drawLog=False,
saveFlag=False)
print(res)
# -*- coding: utf-8 -*-
"""一个带约束的多目标背包问题.
假设有5类物品,每类物品中包含着四个具体的物品(序号记作0,1,2,3),现要求从这五种类别的物品
中分别选择一个物品放进背包,要求使背包内的物品总价最高,总体积最小,且背包的总质量不能超过92kg。
不同于moea_demo3的案例的是:这里额外要求选出的五个物品的序号最多只能有2个重复。
若用矩阵P代表背包中物品的价值;矩阵R代表背包中物品的体积;矩阵C代表物品的质量,则P,R,C的取值如下:
P=[[3,4,9,15,2], R=[[0.2, 0.3, 0.4, 0.6, 0.1], C=[[10,13,24,32,4],
[4,6,8,10,2.5], [0.25,0.35,0.38,0.45,0.15], [12,15,22,26,5.2],
[5,7,10,12,3], [0.3, 0.37,0.5, 0.5, 0.2], [14,18,25,28,6.8],
[3,5,10,10,2]] [0.3, 0.32,0.45,0.6, 0.2]] [14,14,28,32,6.8]]
分析:
这是一个0-1背包问题,但如果用一个元素为0或1的矩阵来表示哪些物品被选中,则不利于后面采用进
化算法进行求解。可以从另一种角度对背包问题进行编码:由于问题要求在每类物品均要选出一件,这里我
们可以用每类物品的序号0, 1, 2, 3来表示从每类物品中具体选择哪件物品。因此染色体可以编码为一个
元素属于{0, 1, 2, 3}的1x5Numpy ndarray一维数组,比如:[0,1,2,3,0]。
该问题可以像demo1那样单纯用实整数编码'RI'来实现,但由于有一个”要求选出的五个物品的
序号最多只能有2个重复“的约束,因此把后面四个决策变量用排列编码'P',第一个决策变量采用实整数编码'RI'来求解会更好。
MyProblem是问题类,本质上是不需要管具体使用什么编码的,因此混合编码的设置在执行脚本main.py中进行而不是在此处。
"""
import numpy as np
import geatpy as ea
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self, M=2):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
maxormins = [-1, 1] # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
Dim = 5 # 初始化Dim(决策变量维数)
varTypes = [1] * Dim # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
lb = [0] * Dim # 决策变量下界
ub = [3] * Dim # 决策变量上界
lbin = [1] * Dim # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1] * Dim # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
# 调用父类构造方法完成实例化
ea.Problem.__init__(self,
name,
M,
maxormins,
Dim,
varTypes,
lb,
ub,
lbin,
ubin)
# 添加几个属性来存储P、R、C
self.P = np.array([[3, 4, 9, 15, 2], [4, 6, 8, 10, 2.5],
[5, 7, 10, 12, 3], [3, 5, 10, 10, 2]])
self.R = np.array([[0.2, 0.3, 0.4, 0.6,
0.1], [0.25, 0.35, 0.38, 0.45,
0.15], [0.3, 0.37, 0.5, 0.5, 0.2],
[0.3, 0.32, 0.45, 0.6, 0.2]])
self.C = np.array([[10, 13, 24, 32, 4], [12, 15, 22, 26, 5.2],
[14, 18, 25, 28, 6.8], [14, 14, 28, 32, 6.8]])
def evalVars(self, Vars): # 目标函数
x = Vars.astype(int) # 得到决策变量矩阵
f1 = np.sum(self.P[x, [0, 1, 2, 3, 4]], 1)
f2 = np.sum(self.R[x, [0, 1, 2, 3, 4]], 1)
# 采用可行性法则处理约束
CV = np.array([np.sum(self.C[x, [0, 1, 2, 3, 4]], 1)]).T - 92
ObjV = np.vstack([f1, f2]).T
return ObjV, CV
# -*- coding: utf-8 -*-
# from MyProblem import MyProblem # 导入自定义问题接口
import geatpy as ea # import geatpy
if __name__ == '__main__':
# 实例化问题对象
problem = MyProblem()
# 构建算法
algorithm = ea.moea_psy_NSGA2_templet(
problem,
ea.PsyPopulation(Encodings=['RI', 'P'],
NIND=30,
EncoIdxs=[[0], [1, 2, 3, 4]]),
MAXGEN=200, # 最大进化代数
logTras=0) # 表示每隔多少代记录一次日志信息,0表示不记录。
# 求解
res = ea.optimize(algorithm,
verbose=False,
drawing=1,
outputMsg=True,
drawLog=False,
saveFlag=True)
print(res)
# -*- coding: utf-8 -*-
"""该案例是moea_demo1的拓展,在main.py中通过两次运行算法类来展示如何通过先验知识来帮助进化.
待优化模型如下:
min f1 = -25 * (x1 - 2)**2 - (x2 - 2)**2 - (x3 - 1)**2 - (x4 - 4)**2 - (x5 - 1)**2
min f2 = (x1 - 1)**2 + (x2 - 1)**2 + (x3 - 1)**2 + (x4 - 1)**2 + (x5 - 1)**2
s.t.
x1 + x2 >= 2
x1 + x2 <= 6
x1 - x2 >= -2
x1 - 3*x2 <= 2
4 - (x3 - 3)**2 - x4 >= 0
(x5 - 3)**2 + x4 - 4 >= 0
x1,x2,x3,x4,x5 ∈ {0,1,2,3,4,5,6,7,8,9,10}
"""
import numpy as np
import geatpy as ea
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self, M=2):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
Dim = 5 # 初始化Dim(决策变量维数)
maxormins = [1] * M # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
varTypes = [1] * Dim # 初始化varTypes(决策变量的类型,0:实数;1:整数)
lb = [0] * Dim # 决策变量下界
ub = [10] * Dim # 决策变量上界
lbin = [1] * Dim # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1] * Dim # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
# 调用父类构造方法完成实例化
ea.Problem.__init__(self,
name,
M,
maxormins,
Dim,
varTypes,
lb,
ub,
lbin,
ubin)
def evalVars(self, Vars): # 目标函数
x1 = Vars[:, [0]]
x2 = Vars[:, [1]]
x3 = Vars[:, [2]]
x4 = Vars[:, [3]]
x5 = Vars[:, [4]]
f1 = -25 * (x1 - 2)**2 - (x2 - 2)**2 - (x3 - 1)**2 - (x4 - 4)**2 - (
x5 - 1)**2
f2 = (x1 - 1)**2 + (x2 - 1)**2 + (x3 - 1)**2 + (x4 - 1)**2 + (x5
- 1)**2
# # 利用罚函数法处理约束条件
# idx1 = np.where(x1 + x2 < 2)[0]
# idx2 = np.where(x1 + x2 > 6)[0]
# idx3 = np.where(x1 - x2 < -2)[0]
# idx4 = np.where(x1 - 3*x2 > 2)[0]
# idx5 = np.where(4 - (x3 - 3)**2 - x4 < 0)[0]
# idx6 = np.where((x5 - 3)**2 + x4 - 4 < 0)[0]
# exIdx = np.unique(np.hstack([idx1, idx2, idx3, idx4, idx5, idx6])) # 得到非可行解的下标
# f1[exIdx] = f1[exIdx] + np.max(f1) - np.min(f1)
# f2[exIdx] = f2[exIdx] + np.max(f2) - np.min(f2)
# 利用可行性法则处理约束条件
CV = np.hstack([
2 - x1 - x2,
x1 + x2 - 6,
-2 - x1 + x2,
x1 - 3 * x2 - 2, (x3 - 3)**2 + x4 - 4,
4 - (x5 - 3)**2 - x4
])
ObjV = np.hstack([f1, f2])
return ObjV, CV
# -*- coding: utf-8 -*-
"""该案例展示了一个离散决策变量的最小化目标的双目标优化问题的求解。问题的定义详见MyProblem.py."""
from MyProblem import MyProblem # 导入自定义问题接口
import geatpy as ea # import geatpy
if __name__ == '__main__':
# 实例化问题对象
problem = MyProblem()
# 构建算法
algorithm = ea.moea_NSGA2_templet(
problem,
ea.Population(Encoding='BG', NIND=50),
MAXGEN=200, # 最大进化代数
logTras=0) # 表示每隔多少代记录一次日志信息,0表示不记录。
algorithm.mutOper.Pm = 0.2 # 修改变异算子的变异概率
algorithm.recOper.XOVR = 0.9 # 修改交叉算子的交叉概率
# 求解
res = ea.optimize(algorithm,
verbose=False,
drawing=1,
outputMsg=True,
drawLog=False,
saveFlag=False)
print(res)
# -*- coding: utf-8 -*-
"""该案例是moea_demo1的拓展,在main.py中通过两次运行算法类来展示如何通过先验知识来帮助进化.
待优化模型如下:
min f1 = -25 * (x1 - 2)**2 - (x2 - 2)**2 - (x3 - 1)**2 - (x4 - 4)**2 - (x5 - 1)**2
min f2 = (x1 - 1)**2 + (x2 - 1)**2 + (x3 - 1)**2 + (x4 - 1)**2 + (x5 - 1)**2
s.t.
x1 + x2 >= 2
x1 + x2 <= 6
x1 - x2 >= -2
x1 - 3*x2 <= 2
4 - (x3 - 3)**2 - x4 >= 0
(x5 - 3)**2 + x4 - 4 >= 0
x1,x2,x3,x4,x5 ∈ {0,1,2,3,4,5,6,7,8,9,10}
"""
import numpy as np
import geatpy as ea
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self, M=2):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
Dim = 5 # 初始化Dim(决策变量维数)
maxormins = [1] * M # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
varTypes = [1] * Dim # 初始化varTypes(决策变量的类型,0:实数;1:整数)
lb = [0] * Dim # 决策变量下界
ub = [10] * Dim # 决策变量上界
lbin = [1] * Dim # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1] * Dim # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
# 调用父类构造方法完成实例化
ea.Problem.__init__(self,
name,
M,
maxormins,
Dim,
varTypes,
lb,
ub,
lbin,
ubin)
def evalVars(self, Vars): # 目标函数
x1 = Vars[:, [0]]
x2 = Vars[:, [1]]
x3 = Vars[:, [2]]
x4 = Vars[:, [3]]
x5 = Vars[:, [4]]
f1 = -25 * (x1 - 2)**2 - (x2 - 2)**2 - (x3 - 1)**2 - (x4 - 4)**2 - (
x5 - 1)**2
f2 = (x1 - 1)**2 + (x2 - 1)**2 + (x3 - 1)**2 + (x4 - 1)**2 + (x5
- 1)**2
# # 利用罚函数法处理约束条件
# idx1 = np.where(x1 + x2 < 2)[0]
# idx2 = np.where(x1 + x2 > 6)[0]
# idx3 = np.where(x1 - x2 < -2)[0]
# idx4 = np.where(x1 - 3*x2 > 2)[0]
# idx5 = np.where(4 - (x3 - 3)**2 - x4 < 0)[0]
# idx6 = np.where((x5 - 3)**2 + x4 - 4 < 0)[0]
# exIdx = np.unique(np.hstack([idx1, idx2, idx3, idx4, idx5, idx6])) # 得到非可行解的下标
# f1[exIdx] = f1[exIdx] + np.max(f1) - np.min(f1)
# f2[exIdx] = f2[exIdx] + np.max(f2) - np.min(f2)
# 利用可行性法则处理约束条件
CV = np.hstack([
2 - x1 - x2,
x1 + x2 - 6,
-2 - x1 + x2,
x1 - 3 * x2 - 2, (x3 - 3)**2 + x4 - 4,
4 - (x5 - 3)**2 - x4
])
ObjV = np.hstack([f1, f2])
return ObjV, CV
# -*- coding: utf-8 -*-
# from MyProblem import MyProblem # 导入自定义问题接口
import geatpy as ea # import geatpy
if __name__ == '__main__':
# 实例化问题对象
problem = MyProblem()
# 构建算法
algorithm = ea.moea_awGA_templet(
problem,
ea.Population(Encoding='RI', NIND=50),
MAXGEN=20, # 最大进化代数
logTras=0) # 表示每隔多少代记录一次日志信息
# 求解
res = ea.optimize(algorithm,
verbose=False,
drawing=0,
outputMsg=False,
drawLog=False,
saveFlag=False)
prophetPop = res['optPop']
algorithm = ea.moea_NSGA2_templet(
problem,
ea.Population(Encoding='RI', NIND=50),
prophetPop=prophetPop, # 传入先验知识
MAXGEN=50, # 最大进化代数
logTras=0) # 表示每隔多少代记录一次日志信息,0表示不记录。
# 求解
res = ea.optimize(algorithm,
verbose=False,
drawing=1,
outputMsg=True,
drawLog=False,
saveFlag=True)
print(res)
# -*- coding: utf-8 -*-
"""这是一个离散决策变量的最小化目标的双目标优化问题.
min f1 = -25 * (x1 - 2)**2 - (x2 - 2)**2 - (x3 - 1)**2 - (x4 - 4)**2 - (x5 - 1)**2
min f2 = (x1 - 1)**2 + (x2 - 1)**2 + (x3 - 1)**2 + (x4 - 1)**2 + (x5 - 1)**2
s.t.
x1 + x2 >= 2
x1 + x2 <= 6
x1 - x2 >= -2
x1 - 3*x2 <= 2
4 - (x3 - 3)**2 - x4 >= 0
(x5 - 3)**2 + x4 - 4 >= 0
x1,x2,x3,x4,x5 ∈ {0,1,2,3,4,5,6,7,8,9,10}
"""
import numpy as np
import geatpy as ea
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self, M=2):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
Dim = 5 # 初始化Dim(决策变量维数)
maxormins = [1] * M # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
varTypes = [1] * Dim # 初始化varTypes(决策变量的类型,0:实数;1:整数)
lb = [0] * Dim # 决策变量下界
ub = [10] * Dim # 决策变量上界
lbin = [1] * Dim # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1] * Dim # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
# 调用父类构造方法完成实例化
ea.Problem.__init__(self,
name,
M,
maxormins,
Dim,
varTypes,
lb,
ub,
lbin,
ubin)
def aimFunc(self, pop): # 目标函数
Vars = pop.Phen # 得到决策变量矩阵
x1 = Vars[:, [0]]
x2 = Vars[:, [1]]
x3 = Vars[:, [2]]
x4 = Vars[:, [3]]
x5 = Vars[:, [4]]
f1 = -25 * (x1 - 2)**2 - (x2 - 2)**2 - (x3 - 1)**2 - (x4 - 4)**2 - (
x5 - 1)**2
f2 = (x1 - 1)**2 + (x2 - 1)**2 + (x3 - 1)**2 + (x4 - 1)**2 + (x5
- 1)**2
# 利用可行性法则处理约束条件
pop.CV = np.hstack([
2 - x1 - x2,
x1 + x2 - 6,
-2 - x1 + x2,
x1 - 3 * x2 - 2, (x3 - 3)**2 + x4 - 4,
4 - (x5 - 3)**2 - x4
])
pop.ObjV = np.hstack([f1, f2]) # 把求得的目标函数值赋值给种群pop的ObjV
# -*- coding: utf-8 -*-
"""描述.
该案例是moea_demo1的另一个版本,展示了如何定义aimFunc()而不是evalVars()来计算目标函数和违反约束程度值。【见MyProblem.py】
同时展示如何定义outFunc(),用于让算法在每一次进化时调用该outFunc()函数。
"""
# from MyProblem import MyProblem # 导入自定义问题接口
import geatpy as ea # import geatpy
if __name__ == '__main__':
# 实例化问题对象
problem = MyProblem()
# 定义outFunc()函数
def outFunc(alg, pop): # alg 和 pop为outFunc的固定输入参数,分别为算法对象和每次迭代的种群对象。
print('第 %d 代' % alg.currentGen)
# 构建算法
algorithm = ea.moea_NSGA2_templet(
problem,
ea.Population(Encoding='RI', NIND=50),
MAXGEN=200, # 最大进化代数
logTras=1, # 表示每隔多少代记录一次日志信息,0表示不记录。
outFunc=outFunc)
# 求解
res = ea.optimize(algorithm,
verbose=False,
drawing=1,
outputMsg=True,
drawLog=True,
saveFlag=False)
print(res)