Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Python库在线性规划中执行相等配给_Python_Linear Programming - Fatal编程技术网

如何使用Python库在线性规划中执行相等配给

如何使用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] 这只是一个简单的例子,数组的实际大小大于此

我将用下面的例子来解释我的问题

在这个问题中,我有4个玩家,数量以数量表示,价格以价格表示。我也有估计数量作为估计。目标是使用四名玩家的可用数量完成估计数量。选择政策是这样的,价格较低的玩家将优先考虑供应数量

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
      斗争(例如
      N=150
      的10秒解算时间;取决于bigM)
  • 需要重新表述绝对值()
    • 需要在纸浆中手动完成
SOCP 在目标中引入加权惩罚分量,即供给变量的欧几里德范数

优点:

  • 变量/约束没有指数增长
缺点:

  • 此惩罚的权重取决于问题,需要调整
  • 不再是线性的:需要SOCP解算器(鲁棒性较差)
  • 需要一个规范公式(但如果可以使用SOCP解算器,这是非常自然的)
我没有使用太多的纸浆,并将在概念上展示这两种方法(bigM未调整;缓慢的公式),这会自动为我们提供abs和norm函数(重新公式)

代码 备注:SOCP通过内点法求解,内点法近似于该解(理论上:根据需要精确)。因此,值并不完全是100。

有两个想法:

LP 在目标中引入加权惩罚分量,即供应变量的所有成对差异(绝对值!)之和

优点:

  • 可表示为LP
缺点:

  • 此惩罚的权重取决于问题,需要调整
  • 成对数量的指数增长(关于#供给)
    • 辅助变量和约束的结果
    • 给定快速公式,解算器将开始与
      N>>100
      斗争(例如
      N=150
      的10秒解算时间;取决于bigM)
  • 需要重新表述绝对值()
    • 需要在纸浆中手动完成
SOCP 在目标中引入加权惩罚分量,即供给变量的欧几里德范数

优点:

  • 变量/约束没有指数增长
缺点:

  • 此惩罚的权重取决于问题,需要调整
  • 不再是线性的:需要SOCP解算器(鲁棒性较差)
  • 需要一个规范公式(但如果可以使用SOCP解算器,这是非常自然的)
我没有使用太多的纸浆,并将在概念上展示这两种方法(bigM未调整;缓慢的公式),这会自动为我们提供abs和norm函数(重新公式)

代码
备注: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]]