如何使用Python库在线性规划中执行相等配给
我将用下面的例子来解释我的问题 在这个问题中,我有4个玩家,数量以数量表示,价格以价格表示。我也有估计数量作为估计。目标是使用四名玩家的可用数量完成估计数量。选择政策是这样的,价格较低的玩家将优先考虑供应数量如何使用Python库在线性规划中执行相等配给,python,linear-programming,Python,Linear Programming,我将用下面的例子来解释我的问题 在这个问题中,我有4个玩家,数量以数量表示,价格以价格表示。我也有估计数量作为估计。目标是使用四名玩家的可用数量完成估计数量。选择政策是这样的,价格较低的玩家将优先考虑供应数量 price = [140, 50, 80, 60] quantity = [100, 150, 200, 400] estimate = 400 所以,对于这个问题,每个玩家提供的数量是 supply = [0, 150, 0, 250] 这只是一个简单的例子,数组的实际大小大于此
price = [140, 50, 80, 60]
quantity = [100, 150, 200, 400]
estimate = 400
所以,对于这个问题,每个玩家提供的数量是
supply = [0, 150, 0, 250]
这只是一个简单的例子,数组的实际大小大于此。我正在使用Python的纸浆库来解决这个线性规划问题
但问题是当所有价格相等时,它会根据指数给出答案,这意味着index0的玩家将首先供应,然后index1的玩家,依此类推。但是,我的实际需求是在同等定价的情况下,在所有参与者之间平均分配估计数量。看看这个例子
price = [60, 60, 60, 60]
quantity = [100, 150, 200, 400]
estimate = 400
产出是,
supply = [100 , 150, 150, 0]
我的要求是,
supply = [100, 100, 100, 100]
所以,我的问题是,如何解决平等配给问题?两个想法:
LP
在目标中引入加权惩罚分量,即供应变量的所有成对差异(绝对值!)之和
优点:
- 可表示为LP
- 此惩罚的权重取决于问题,需要调整李>
- 成对数量的指数增长(关于#供给)
- 辅助变量和约束的结果
- 给定快速公式,解算器将开始与
斗争(例如N>>100
的10秒解算时间;取决于bigM)N=150
- 需要重新表述绝对值()
- 需要在纸浆中手动完成
- 变量/约束没有指数增长
- 此惩罚的权重取决于问题,需要调整李>
- 不再是线性的:需要SOCP解算器(鲁棒性较差)
- 需要一个规范公式(但如果可以使用SOCP解算器,这是非常自然的)
- 可表示为LP
- 此惩罚的权重取决于问题,需要调整李>
- 成对数量的指数增长(关于#供给)
- 辅助变量和约束的结果
- 给定快速公式,解算器将开始与
斗争(例如N>>100
的10秒解算时间;取决于bigM)N=150
- 需要重新表述绝对值()
- 需要在纸浆中手动完成
- 变量/约束没有指数增长
- 此惩罚的权重取决于问题,需要调整李>
- 不再是线性的:需要SOCP解算器(鲁棒性较差)
- 需要一个规范公式(但如果可以使用SOCP解算器,这是非常自然的)
备注:SOCP通过内点法求解,内点法近似于该解(理论上:根据需要精确)。因此,数值不完全是100。小心
,但问题是当所有价格相等时,它会根据指数给出答案,这意味着index0的玩家将首先提供,然后index1的玩家,依此类推。
。这取决于解算器设计,虽然这应该是确定性的,但它可能会随着解算器版本的不同而变化!计算相等的变量数需要额外的二进制变量。您将得到一个MIP模型。感谢您的建议并回答@sascha。谢谢@erwin。如果你能分享一些关于MIP模型的资料,我将不胜感激。有很多关于混合整数规划的书。小心,但问题是当所有价格相等时,它会根据指数给出答案,意味着index0的玩家将首先提供,然后index1的玩家,依此类推
。这取决于解算器设计,虽然这应该是确定性的,但它可能会随着解算器版本的不同而变化!计算相等的变量数需要额外的二进制变量。您将得到一个MIP模型。感谢您的建议并回答@sascha。谢谢@erwin。如果你能分享一些关于MIP模型的资料,我将不胜感激。有很多关于混合整数规划的书。
import numpy as np
import cvxpy as cvx
from itertools import combinations
np.set_printoptions(suppress=True, precision=6)
# price = np.array([140, 50, 80, 60])
# quantity = np.array([100, 150, 200, 400])
price = np.array([60, 60, 60, 60])
quantity = np.array([100, 150, 200, 400])
estimate = 400
# LP approach
def solve_lp(penalty=True):
bigM = 1e-3
N = len(price)
pairs = list(combinations(range(N), 2))
x = cvx.Variable(N)
constraints = [x >= 0,
cvx.sum_entries(x) >= estimate,
x <= quantity]
obj_costs = price * x
obj_penalty = sum([cvx.abs(x[a] - x[b]) for (a,b) in pairs])
objective = obj_costs + bigM * float(penalty) * obj_penalty
problem = cvx.Problem(cvx.Minimize(objective), constraints)
problem.solve(solver='CBC') # Warning: solver not shipped by default
# same solver as shipped by pulp
# = Clp/Cbc
print(problem.status)
print(problem.value)
print(x.value.T)
# QP approach
def solve_socp(penalty=True):
bigM = 1e-3
N = len(price)
est_avg = estimate / N
x = cvx.Variable(N)
constraints = [x >= 0,
cvx.sum_entries(x) >= estimate,
x <= quantity]
obj_costs = price * x
obj_penalty = cvx.norm(x - est_avg)
objective = obj_costs + bigM * float(penalty) * obj_penalty
problem = cvx.Problem(cvx.Minimize(objective), constraints)
problem.solve(solver='ECOS')
print(problem.status)
print(problem.value)
print(x.value.T)
print('LP a')
solve_lp(penalty=False)
print('LP b')
solve_lp(penalty=True)
print('SOCP a')
solve_socp(penalty=False)
print('SOCP b')
solve_socp(penalty=True)
LP a
optimal
24000.0
[[100. 100. 200. 0.]]
LP b
optimal
24000.0
[[100. 100. 100. 100.]]
SOCP a
optimal
24000.000032013406
[[ 44.92762 69.401923 93.878797 191.791661]]
SOCP b
optimal
24000.000001071123
[[ 99.999423 99.999973 99.999959 100.000645]]