PULP:最小化一组向量的最大值

时间:2017-10-24 21:35:36

标签: python mathematical-optimization linear-programming pulp

我有一个我想解决的线性编程问题,其所有数据都来自表格。

该表的大小(m * n)看起来像这样:

    |    c0      c1       c2       c3      ...       cn        sum
--- + ------ + ------ + ------ + ------ + ------ + ------ +++ ----- +
r0  |                                                     |||  Σ r0 
r1  |                                                     |||  Σ r1
r2  |                                                     |||  Σ r2
r3  |                                                     |||  Σ r3
r4  |                                                     |||
 .  |                                                     |||
 .  |                                                     |||
 .  |                                                     |||
rm  |                                                     |||  Σ rm
------------------------------------------------------------------- +
max |max(c0)  max(c1)  max(c2)  max(c3)           max(cn) |||  Σ max(c0...n)

当问题得到优化时,此表中的所有容器都将保持浮点值。

我正在尝试最小化每列(Σmax(c0 ... n))最大值之和

我创建了LpProblem

problem = pulp.LpProblem("problem",pulp.LpMinimize)

我创建了表示表格中每个bin的LpVariables

variables = pulp.LpVariable.dicts("bin",
                                  ((r,c) for r in rows for c in columns),
                                  lowBound=0,
                                  cat='Continuous')

我事先知道每行的总和(Σrx),并且约束是 x 的行必须总和为Σrx< / strong>即可。作为这些数据的一个特征,一行中只有一个索引子集可以贡献这个Σrx值。例如,只有第0行中的bin(0,1)和(0,3)可能具有非零值。这些贡献箱的索引因行而异;某些行可能只有1个贡献箱,而其他行有多个(或所有)贡献箱。我通过为每一行创建约束来解释这一点。

for row in rows:
    column_set # a list of bin indexes for this row that make up the sum.
    variable_set = [ variables[(row,c)] for c in column_set ]
    problem += pulp.lpSum(variable_set) == row_sum # the sum of the row.

我的问题在于如何定义我的目标函数。由于python的max()不适用于LpVariable个对象,因此我尝试考虑如何获取任何列的最大值并将其分配给自己的LpVariable对象。

这样做的一种方法可能是循环遍历给定列中表示二进制位的每个LpVariable,执行v = variable.value()之类的操作并将所有v添加到列表中,然后执行{ {1}}在此列表中设置max()等于{1}},但这只会得到LpVariable的初始值,并且当求解器在LpVariable进程中更改数据时,这些最大值不会动态更新。

我也试过单独solve()代表每个列的最大值,将它们设置为:

LpVariable

但是,这似乎只是从每个pulp.LpVariable("Max___{}".format(s), lowBound=max([v.value() for v in column]), upBound=max([v.value() for v in column]), cat=pulp.LpContinuous ) 的初始条件中获取值,并且在此上运行LpVariable会返回solve()解决方案。

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

高级别说明

  • m rows, n cols
  • 介绍n个新连续变量 m_0, m_1, ..., m_(n-1)
  • 添加表单的m*n个新约束
    • m_0 >= entry(r_0,c_0)
    • m_0 >= entry(r_1,c_0)
    • ...
    • m_0 >= entry(r_(m-1),c_0)
    • ...
    • ...
    • m_1 >= entry(r_0,c_1)
    • m_1 >= entry(r_1,c_1)
    • ...
    • m_1 >= entry(r_(m-1),c_1)
    • ...
  • 目标
    • minimize(m_0 + m_1 + ... + m_(n-1))

<强>说明

  • 这只有在每个m被解算器以某种方式推下时才有效!
    • 此处:最小化总和 - &gt; OK!
  • 它独立于条目的类型(二进制,整数,连续)

答案 1 :(得分:0)

您可以通过定义一组2成员元组来更轻​​松地处理此问题的稀疏性,这些元组是表中可能的非零条目的行列索引。

要处理每列中的最大条目,请引入新的决策变量和约束,如@sascha所述。

例如:

"""
Example where the table is 2x2, and any entries can be non-zero except the (2,1) entry
"""

import pulp

# Define the sparse set of row-column indexes for entries that can be non-zero
rowCols = set([(1, 1),
               (1, 2),
               (2, 2)])

# Define row sums
rowSums = {1: 1.1,
           2: 3.4}

# Detect the rows and columns of the table
rows = set([row for (row, _) in rowCols])
cols = set([col for (_, col) in rowCols])

# Define the PuLP model
problem = pulp.LpProblem("problem", pulp.LpMinimize)

# Define the variables
variables = pulp.LpVariable.dicts("bin", rowCols, lowBound=0,
                                  cat=pulp.LpContinuous)
colMaxes = pulp.LpVariable.dicts("maximum entry in the column", cols,
                                 lowBound=0, cat=pulp.LpContinuous)

# Define the constraints
#  row sum
for row in rows:
    problem += (
        pulp.lpSum([variables[row, col]
                    for col in cols
                    if (row, col) in rowCols])
        ==
        rowSums[row]
    )
#  max in column
for (row, col) in rowCols:
    problem += (
        pulp.lpSum([variables[row1, col1]
                    for (row1, col1) in rowCols
                    if col1 == col])
        <=
        colMaxes[col]
    )

# Define objective function
problem += pulp.lpSum([colMaxes[col] for col in cols])

# Solve the problem
problem.solve()

# Print the solution
print('row col value')
for (row, col) in rowCols:
    print(row, col, variables[row, col].varValue)