问题描述
我正在研究一个优化问题,我的目标是当出售两个产品对时最大化利润,但约束是,该对产品中的产品不应重复。
http://www.voidspace.org.uk/python/modules.shtml#pycrypto
我正在使用Pulp优化解决方案,但是代码效率低下,并且会无限循环。
file = pd.read_csv('input_file.csv')
main_product_1 = list(file['Product ID'].unique())
main_product_2 = list(file['Product ID 2'].unique())
file.set_index(['Product ID','Product ID 2'],inplace=True)
file = file['Profit']
# Target Variable
combine = pulp.LpVariable.dicts("combine",((product_1,product_2) for product_1 in main_product_1 for
product_2 in main_product_2 if product_1 != product_2),cat='Binary')
# Initializing the model
model = pulp.LpProblem("prof_max",pulp.LpMaximize)
# Objective Function optimization
model += pulp.lpSum(
[combine[product_1,product_2] * file.loc[(product_1,product_2)] for product_1 in
main_product_1 for product_2 in main_product_2 if product_1 != product_2])
# Constraints for optimization
for area in set_plant:
model += pulp.lpSum([combine[area,other] for other in main_product_1 if area != other]
+ [combine[other,area] for other in main_product_2 if area != other]) == 1
model.solve()
print(pulp.LpStatus[model.status])
# Check
set_index = set(file.index)
set_expected = set(
[(product_1,product_2) for product_1 in main_product_1 for product_2 in main_product_2 if
product_1 != product_2])
len(set_expected - set_index)
问题是代码进入无限循环,但我没有得到任何结果,是否有更优化的方式来运行此方法?
解决方法
问题是您要添加非常大量的整数变量,而整数线性规划是一个极其困难且效率低下的问题。但是,您可能还需要进行其他一些改进。
请考虑以下构造:
- 如果您拥有产品1的
M
个实例和产品2的N
个实例,那么您就有MN
个二进制变量x_mn
; - 如果
P
为1,则每个变量都会对目标函数贡献x_mn
; - 您在约束中说
x_mn + x_nm == 1
,但实际上应该是x_mn + x_nm <= 1
。否则,您说必须在列表中有每个组合。这可能会导致不可行的解决方案; - 如果您考虑的是组合而不是排列(即[1000,1001]和[1001,1000]相同,那么这意味着
M = N
,并且您只能删除大约一半的变量即可还剩M^2 / 2
。(如果您将值空间视为MxM正方形,则您只能接受一个三角形,因为另一个三角形是等效的; - 如果您像上面提到的那样限制变量空间,则实际上不需要任何约束;如果
x_nm
不存在,那么对于二进制变量,x_mn <= 1
很明显。
import pandas as pd
import numpy as np
import pulp
file = pd.read_csv('file.csv')
file = file[file['Product ID'] < file['Product ID 2']]
file.set_index(['Product ID','Product ID 2'],inplace=True)
file = file['Profit']
combinations = file.index
individual_products = set()
for product_1,product_2 in combinations:
individual_products.add(product_1)
individual_products.add(product_2)
# Target Variable
combine = pulp.LpVariable.dicts("combine",combinations,cat='Binary')
# Initializing the model
model = pulp.LpProblem("prof_max",pulp.LpMaximize)
# Objective Function optimization
model += pulp.lpSum([combine[i] for i in file.index] * file)
# All individual products can only be used once
for product in individual_products:
matching_combinations = combinations[(combinations.to_frame() == product).any(axis=1)]
model += pulp.lpSum([combine[i] for i in matching_combinations]) <= 1
model.solve()
print(pulp.LpStatus[model.status])
print([v for v in model.variables() if v.varValue > 0])
通过这些更改,在不改变问题或固有实现的前提下,您基本上消除了75%的约束。