说明

遗传算法的简单应用到这里就告一段落,原理比较简单,上手也容易。在应用过程中发现几个问题:

  • 1 文档做的太粗糙,我很多参数是靠猜的(比如cv)
  • 2 调用的参数还是比较复杂
  • 3 用matplotlib画图的效果不好(特别是对中文的支持很差,应该改为前端展示)

当然这个包的计算效果(效率)是很不错的,所以这里计划:

  • 1 进行封装,方便日后调用
  • 2 解读源码,参考性的进行重构(例如目前都是基于numpy计算,可以转向pytorch的tensor计算)

在应用上,遗传算法有几个方向:

  • 1 直接的应用问题,例如之前的爬虫优化
  • 2 辅助建模,例如构造海量的变量,然后通过遗传算法选择

当然,在更高层次上,还可以做模型的组合优化。

内容

1 源码

在github上可以找到这个包的源码,整个包大概100M

python运筹学优化代码 python运筹学的包_python运筹学优化代码


未来我会参考源码,重构一套新的遗传算法工具包,特别是使用pytorch替代numpy,这样可以利用CUDA进行更快速的计算。

2 封装示例

一些和问题相关的常量

#服务器起的爬虫数 k1,k2
k1 = 4
k2 = 3

#服务器金额 m1, m2
m1 = 2000
m2 = 600

#两种代理稳定时间 t1, t2
t1 = 2
t2 = 6

#每日使用上限 N1, N2
N1 = 150000
N2 = 580000

#单位时间可维持的最大ip数 n1, n2
n1 = 10
n2 = 10

#代理金额 M1, M2
M1 = 1000
M2 = 1360

#爬虫爬取速度 c1, c2
c1 = 1.2033
c2 = 1.9567

#总预算 M
M = 8000

定义问题

import numpy as np
import geatpy as ea

class MyProblem(ea.Problem):                # 继承Problem父类
    def __init__(self):
        name = 'MyProblem'                  # 初始化name(函数名称,可以随意设置)
        M = 1                               # 初始化M(目标维数)
        maxormins = [-1]                    # 初始化目标最小最大化标记列表,1:min;-1:max
        Dim = 4                             # 初始化Dim(决策变量维数)
        varTypes = [1] * Dim                # 初始化决策变量类型,0:连续;1:离散
        lb = [0,0,0,0]                        # 决策变量下界
        ub = [30,30,30,30]                        # 决策变量上界
        lbin = [1]*Dim                      # 决策变量下边界
        ubin = [1]*Dim                      # 决策变量上边界 # 调用父类构造方法完成实例化
        ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin)

    def aimFunc(self, pop):                 # 目标函数,pop为传入的种群对象
        Vars = pop.Phen                     # 得到决策变量矩阵
        x1 = Vars[:, [0]]                   # 取出第一列得到所有个体的x1组成的列向量
        x2 = Vars[:, [1]]                   # 取出第二列得到所有个体的x2组成的列向量
        x3 = Vars[:, [2]]                   # 取出第三列得到所有个体的x3组成的列向量
        x4 = Vars[:, [3]]
        # 计算目标函数值,赋值给pop种群对象的ObjV属性
        pop.ObjV = c1* x3 + c2 * x4
        # 采用可行性法则处理约束,生成种群个体违反约束程度矩阵
        
        # 约束
        # 约束1:k1x1 + k2x2 - y1 - y2 = 0
        cv1 = np.abs(k1* x1 + k2* x2 - x3 - x4)
        # 约束2: x1m1 + x2m2 + M1 + M2 - M <=0
        cv2 = x1 * m1 + x2 * m2 + M1 + M2 - M
        # 约束3:x3 * 1day/ t1 - N1 
        cv3 = 1440 * x3/t1 - N1
        # 约束4:x4 * 1day/t2 - N2
        cv4 = 1440 * x4 / t2 - N2
        # 约束5:y1 -n1 <=0
        cv5 = x3 - n1
        # 约束6:y2 -n2 <=0
        cv6 = x4 - n2

        
        pop.CV = np.hstack([cv1,cv2,cv3,cv4,cv5,cv6])   # 第1.2.3个约束

执行算法

# -*- coding: utf-8 -*-
"""main.py"""
import geatpy as ea # import geatpy
# from MyProblem import MyProblem # 导入自定义问题接口
"""===============================实例化问题对象================================"""
problem = MyProblem() # 生成问题对象
"""==================================种群设置=================================="""
Encoding = 'RI'       # 编码方式(用BG好像效率更高)
NIND = 1000            # 种群规模
Field = ea.crtfld(Encoding, problem.varTypes, problem.ranges, problem.borders) # 创建区域描述器
population = ea.Population(Encoding, Field, NIND) # 实例化种群对象(此时种群还没被初始化,仅仅是完成种群对象的实例化)
"""================================算法参数设置================================="""
myAlgorithm = ea.soea_EGA_templet(problem, population) # 实例化一个算法模板对象
myAlgorithm.MAXGEN = 200 # 最大进化代数
myAlgorithm.logTras = 1  # 设置每隔多少代记录日志,若设置成0则表示不记录日志
myAlgorithm.verbose = True  # 设置是否打印输出日志信息
myAlgorithm.drawing = 0  # 设置绘图方式(0:不绘图;1:绘制结果图;2:绘制目标空间过程动画;3:绘制决策空间过程动画)
"""===========================调用算法模板进行种群进化==============--==========="""
[BestIndi, population] = myAlgorithm.run()  # 执行算法模板,得到最优个体以及最后一代种群
# BestIndi.save()  # 把最优个体的信息保存到文件中
"""==================================输出结果=================================="""
print('用时:%f 秒' % myAlgorithm.passTime)
print('评价次数:%d 次' % myAlgorithm.evalsNum)
if BestIndi.sizes != 0:
    print('最优的目标函数值为:%s' % BestIndi.ObjV[0][0])
    print('最优的控制变量值为:')
    for i in range(BestIndi.Phen.shape[1]):
        print(BestIndi.Phen[0, i])
else:
    print('没找到可行解。')
---
用时:0.232716 秒
评价次数:199801 次
最优的目标函数值为:30.396700000000003
最优的控制变量值为:
1.0
5.0
9.0
10.0

3 画图

myAlgorithm.trace.keys()
---
dict_keys(['f_best', 'f_avg'])


s1 = myAlgorithm.trace['f_best']
s2 = myAlgorithm.trace['f_avg']

# 看起来被“烧掉”了9次迭代
len(s1)
---
191

画图函数

import pyecharts.options as opts
from pyecharts.charts import Line

def pe_line_pair(x_list, y_list1, y_list2, y_list1_name = '', y_list2_name='',
                is_show_label_number = False, title=''):

    c = (
        Line()
        .add_xaxis(x_list)
        .add_yaxis(y_list1_name, y_list1, is_smooth=True)
        .add_yaxis(y_list2_name, y_list2, is_smooth=True)
        .set_global_opts(title_opts=opts.TitleOpts(title=title))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=is_show_label_number))
        .render_notebook()
    )
    return c

画图

# pe_line_pair(x_list, y_list1, y_list2)
x_list = list(range(len(s1)))
y_list1 = myAlgorithm.trace['f_best']
y_list2 = myAlgorithm.trace['f_avg']
y_list1_name = 'best'
y_list2_name = 'average'
is_show_label_number = False
title = '迭代过程目标值'
pe_line_pair(x_list, y_list1, y_list2,y_list1_name =y_list1_name, y_list2_name=y_list2_name,title=title)

结果

python运筹学优化代码 python运筹学的包_python运筹学优化代码_02

到这里geatpy的使用就告一段落,可以先用,但之后还是要重写。