用docplex和遗传算法解决0-1规划问题

一、什么是0-1规划问题

0-1规划问题是决策变量仅取值0或1的一类特殊的整数规划。0-1变量可以数量化地描述诸如开与关、取与弃、有与无等现象所反映的离散变量间的逻辑关系、顺序关系以及互斥的约束条件,因此0-1规划问题非常适合描述和解决如线路设计、工厂选址、生产计划安排、旅行购物、背包问题、人员安排等问题。

二、经典0-1规划问题

某公司拟在市东、西、南区建立门市部。备选有7个位 A i A_{i} Ai( i = 1 , 2 , . . . , 7 {i}=1,2,...,7 i=1,2,...,7)可供选择。规定 A 1 A_{1} A1 A 2 A_{2} A2 A 3 A_{3} A3三个点中至多选两个, A 4 A_{4} A4 A 5 A_{5} A5两个点中至少选一个, A 6 A_{6} A6 A 7 A_{7} A7两个点中至少选一个。如选用 A i A_{i} Ai点,设备投资为 b i b_{i} bi万元,每年可获利润为 c i c_{i} ci万元,但投资总额不能超过60万元,具体数值如下表,问选择哪几个点可使年利润最大?

地点 A 1 A_{1} A1 A 2 A_{2} A2 A 3 A_{3} A3 A 4 A_{4} A4 A 5 A_{5} A5 A 6 A_{6} A6 A 7 A_{7} A7
b i b_{i} bi(万元)108205132210
c i c_{i} ci(万元)119299213122

首先对该问题进行建模,引入0-1变量 x i x_{i} xi( i = 1 , 2 , . . . , 7 {i}=1,2,...,7 i=1,2,...,7), x i = 1 x_{i}=1 xi=1,表示该点被选中, x i = 0 x_{i}=0 xi=0,表示该点未被选中。模型如下:
Alt

三、Docplex求解0-1规划问题

docplex ( IBM Decision Optimization CPLEX Modeling for Python ) 是IBM为建模和求解优化问题而开发的Python API,其能使用本地的Cplex求解器,也可用账号登录使用云端求解。

from docplex.mp.model import Model  #导出库,只用这一个就够了
model = Model() #创建模型
var_list = [i for i in range(0, 7)] #创建列表
X = model.binary_var_list(var_list, lb=0, name='X') #创建变量列表
#设定目标函数
model.maximize(11* X[0] + 9 * X[1] + 29 * X[2]+9* X[3]+21*X[4]+31*X[5]+22*X[6])  
#添加约束条件
model.add_constraint(X[0]+X[1]+X[2] <= 2)
model.add_constraint(X[3] + X[4] >=1)
model.add_constraint(X[5] + X[6] >=1)
model.add_constraint(10* X[0] + 8* X[1] + 20 * X[2]+5* X[3]+13*X[4]+22*X[5]+10*X[6] <=60)
sol = model.solve() #求解模型
print(sol)  #打印结果

求解结果如下:
Alt

四、用遗传算法求解0-1规划问题

遗传算法(Genetic Algorithm, GA)是模拟生物在自然环境中的遗传和进化的过程而形成的自适应全局优化搜索算法。它借用了生物遗传学的观点,通过自然选择、遗传和变异等作用机制,实现各个个体适应性的提高。遗传算法因能有效求解NP-hard问题及非线性、多峰函数优化和多目标优化问题,得到了众多学者的高度重视。遗传算法借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种并行、高效、全局搜索的方法,它能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最优解。同传统的优化算法相比,遗传算法具有对参数的编码进行操作、不需要推导和附加信息、寻优规则非确定性、自组织、自适应和自学习等特点。

Geatpy 是一个Python 进化算法库,由华南理工大学、华南农业大学、德州奥斯汀公立大学学生联合团队开发。它提供了许多已实现的遗传算法各项操作的函数,如初始化种群、选择、交叉、变异、重插入、多种群迁移等。你可以清晰地看到其基本结构及相关算法的实现,并利用Geatpy 函数方便地进行自由组合,实现多种改进的遗传算法、多目标优化、并行遗传算法等,解决传统优化算法难以解决的问题。

编写目标函数如下:

"""函数接口aimfuc.py"""
import numpy as np
def aimfuc(Phen, LegV):
	x1 = Phen[:, [0]]
	x2 = Phen[:, [1]]
	x3 = Phen[:, [2]]
	x4 = Phen[:, [3]]
	x5 = Phen[:, [4]]
	x6 = Phen[:, [5]]
	x7 = Phen[:, [6]]
	f =11*x1+9*x2 +29*x3+9*x4+21*x5+31*x6+22*x7
	# 约束条件
	idx1 = np.where(10*x1+8*x2+20*x3+5*x4+13*x5+22*x6+10*x7 > 60)[0]
	idx2 = np.where(x1 + x2+ x3 > 2)[0]
	idx3 = np.where(-x4 -x5 > -1)[0]
	idx4 = np.where(-x6 -x7 > -1)[0]
	# 采用惩罚方法1
	f[idx1] = -1
	f[idx2] = -1
	f[idx3] = -1
	f[idx4] = -1
	return [f, LegV]

编写执行脚本如下:

"""执行脚本main.py"""
import numpy as np
import geatpy as ga
from aimfuc import aimfuc
# 获取函数接口地址
AIM_M = __import__('aimfuc')
# ================变量设置==================
# 生成自变量的范围矩阵
ranges = np.vstack([np.zeros((1, 7)), np.ones((1, 7))])
# 生成自变量的边界矩阵
borders = np.vstack([np.ones((1, 7)), np.ones((1, 7))])
FieldDR = ga.crtfld(ranges, borders) # 生成区域描述器
# ==============调用编程模板================
[pop_trace, var_trace, times] = ga.sga_real_templet(AIM_M, 'aimfuc',
None, None, FieldDR, problem = 'I', maxormin = -1, MAXGEN = 300,
NIND = 10, SUBPOP = 1, GGAP = 0.9, selectStyle = 'sus',
recombinStyle = 'xovdp', recopt = 0.9, pm = 0.1, distribute =True, drawing = 1)

求解结果与种群水平图像如下:
求解结果
求解结果
得出的结果与用docplex求解结果一致,即选择第1、4、5、6、7个点。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值