最近想重新搞一下遗传算法,突然发现python也有一个牛批的包可以吊了,兄弟姐妹们,还等什么,都给我调
自己手动编写遗传算法例程见HELLO,遗传算法!
geatpy
geatpy官方主页
作者大大赛高
官方入门教程
简单来说就是, 我们只需要根据自己的实际问题,写好MyProblem这个类
Problem类定义了与问题相关的一些信息,如问题名称name、优化目标的维数M、决策变量的个数Dim、决策变量的范围ranges、决策变量的边界borders等。maxormins是一个记录着各个目标函数是最小化抑或是最大化的Numpy array行向量,其中元素为1表示对应的目标是最小化目标;为-1表示对应的是最大化目标。例如M=3,maxormins=array([1,-1,1]),此时表示有三个优化目标,其中第一、第三个是最小化目标,第二个是最大化目标。varTypes是一个记录着决策变量类型的行向量,其中的元素为0表示对应的决策变量是连续型变量;为1表示对应的是离散型变量。待求解的目标函数定义在aimFunc()的函数中。calReferObjV()函数则用于计算或读取目标函数参考值(一般用理论上的目标函数的最优值作为参考值),该参考值可以用于后续的指标分析。在实际使用时,不是直接在Problem类的文件中修改相关代码来使用的,而是通过定义一个继承Problem的子类来完成对问题的定义的。这些在后面的章节中会详细讲述。getReferObjV()是Problem父类中已经实现了的一个函数,它先尝试读取特定文件夹中的目标函数值参考数据,如果读取不到,则调用calReferObjV()进行计算。对于Problem类中各属性的详细含义可查看Problem.py源码。
然后选择一个合适的模板算法(这里是模板集合)就可以冲了, 不管什么单目标优化,多目标优化,统统ok
单目标优化实例
"""MyProblem.py"""
import numpy as np
import geatpy as ea
"""
该案例展示了一个带等式约束的连续型决策变量最大化目标的单目标优化问题。
该函数存在多个欺骗性很强的局部最优点。
max f = 4*x1 + 2*x2 + x3
s.t.
2*x1 + x2 - 1 <= 0
x1 + 2*x3 - 2 <= 0
x1 + x2 + x3 - 1 == 0
0 <= x1,x2 <= 1
0 < x3 < 2
"""
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
M = 1 # 初始化M(目标维数)
maxormins = [-1] # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
Dim = 3 # 初始化Dim(决策变量维数)
varTypes = [0] * Dim # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
lb = [0,0,0] # 决策变量下界
ub = [1,1,2] # 决策变量上界
lbin = [1,1,0] # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1,1,0] # 决策变量上边界(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]]
pop.ObjV = 4*x1 + 2*x2 + x3 # 计算目标函数值,赋值给pop种群对象的ObjV属性
# 采用可行性法则处理约束
pop.CV = np.hstack([2*x1 + x2 - 1,
x1 + 2*x3 - 2,
np.abs(x1 + x2 + x3 - 1)])
def calReferObjV(self): # 设定目标数参考值(本问题目标函数参考值设定为理论最优值)
referenceObjV = np.array([[2.5]])
return referenceObjV
if __name__ == '__main__':
"""================================实例化问题对象==========================="""
problem = MyProblem() # 生成问题对象
"""==================================种群设置==============================="""
Encoding = 'RI' # 编码方式
NIND = 100 # 种群规模
Field = ea.crtfld(Encoding, problem.varTypes, problem.ranges, problem.borders) # 创建区域描述器
population = ea.Population(Encoding, Field, NIND) # 实例化种群对象(此时种群还没被初始化,仅仅是完成种群对象的实例化)
"""================================算法参数设置============================="""
myAlgorithm = ea.soea_DE_rand_1_bin_templet(problem, population) # 实例化一个算法模板对象
myAlgorithm.MAXGEN = 500 # 最大进化代数
myAlgorithm.mutOper.F = 0.5 # 差分进化中的参数F
myAlgorithm.recOper.XOVR = 0.7 # 重组概率
"""===========================调用算法模板进行种群进化======================="""
[population, obj_trace, var_trace] = myAlgorithm.run() # 执行算法模板
population.save() # 把最后一代种群的信息保存到文件中
# 输出结果
best_gen = np.argmin(problem.maxormins * obj_trace[:, 1]) # 记录最优种群个体是在哪一代
best_ObjV = obj_trace[best_gen, 1]
print('最优的目标函数值为:%s'%(best_ObjV))
print('最优的决策变量值为:')
for i in range(var_trace.shape[1]):
print(var_trace[best_gen, i])
print('有效进化代数:%s'%(obj_trace.shape[0]))
print('最优的一代是第 %s 代'%(best_gen + 1))
print('评价次数:%s'%(myAlgorithm.evalsNum))
print('时间已过 %s 秒'%(myAlgorithm.passTime))
多目标优化示例
import numpy as np
import geatpy as ea
"""
该案例展示了一个离散决策变量的最小化目标的双目标优化问题。
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}
"""
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
# # 利用罚函数法处理约束条件
# 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)
# 利用可行性法则处理约束条件
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
if __name__ == '__main__':
"""================================实例化问题对象==========================="""
problem = MyProblem() # 生成问题对象
"""==================================种群设置==============================="""
Encoding = 'BG' # 编码方式
NIND = 50 # 种群规模
Field = ea.crtfld(Encoding, problem.varTypes, problem.ranges, problem.borders) # 创建区域描述器
population = ea.Population(Encoding, Field, NIND) # 实例化种群对象(此时种群还没被初始化,仅仅是完成种群对象的实例化)
"""================================算法参数设置============================="""
myAlgorithm = ea.moea_NSGA2_templet(problem, population) # 实例化一个算法模板对象
myAlgorithm.mutOper.Pm = 0.2 # 修改变异算子的变异概率
myAlgorithm.recOper.XOVR = 0.9 # 修改交叉算子的交叉概率
myAlgorithm.MAXGEN = 200 # 最大进化代数
"""==========================调用算法模板进行种群进化========================"""
NDSet = myAlgorithm.run() # 执行算法模板,得到帕累托最优解集NDSet
NDSet.save() # 把结果保存到文件中
# 输出
print('用时:%s 秒'%(myAlgorithm.passTime))
print('非支配个体数:%s 个'%(NDSet.sizes))
print('单位时间找到帕累托前沿点个数:%s 个'%(int(NDSet.sizes // myAlgorithm.passTime)))
注意的是由于是多目标优化,所以并不是跟单目标优化一样得到一个最优解,而是最终得到得是一个最优集合,叫pareto最优解。 1、pareto最优解又称非支配解、非占优解,pareto最优解集又称非劣解、非支配解集、非占优解集 2、下图为最小化的两目标优化问题的最终pareto前沿(pareto front)分布示意图,则f1和f2目标值均为越小越优,实线和虚线组成部分为可行域,实线表示pareto前沿面,也就是所有pareto最优解对应的目标矢量组成的曲面,一个多目标优化问题对应一个pareto前沿面。 3、A、B、C三点位于pareto前沿面上,该三点的解为pareto最优解,他们三者之间不存在支配或是占优关系。D、E、F三点的解为可行解,非pareto最优解。 4、A点的解支配F点的解,或是相比F点的解,A点的解是pareto占优。同样B和C点与D、E、F点之间存在支配关系或是占优关系。