Python 纸浆:最小化一组向量的最大值

Python 纸浆:最小化一组向量的最大值,python,mathematical-optimization,linear-programming,pulp,Python,Mathematical Optimization,Linear Programming,Pulp,我想解决一个线性规划问题,它的所有数据都来自一个表 该表的大小(m*n)如下所示: | c0 c1 c2 c3 ... cn sum --- + ------ + ------ + ------ + ------ + ------ + ------ +++ ----- + r0 | ||| Σ r0 r1

我想解决一个线性规划问题,它的所有数据都来自一个表

该表的大小(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)
pulp.LpVariable("Max___{}".format(s),
                lowBound=max([v.value() for v in column]),
                upBound=max([v.value() for v in column]),
                cat=pulp.LpContinuous
               )
当问题得到优化时,此表中的所有箱子都将保留一个浮点值

我试图最小化每列的最大值之和(∑max(c0…n))

我创建了一个
LpProblem

problem = pulp.LpProblem("problem",pulp.LpMinimize)
我已经创建了表示表中每个箱子的
LpVariables

variables = pulp.LpVariable.dicts("bin",
                                  ((r,c) for r in rows for c in columns),
                                  lowBound=0,
                                  cat='Continuous')
我事先知道每行的和(∑rx),约束条件是一行x的值必须和∑rx。作为这些数据的一个特征,一行中只有一个子集的索引可以产生这个∑rx值。例如,只有第0行中的存储箱(0,1)和(0,3)可能具有非零值。这些贡献箱的索引因行而异;某些行可能只有一个贡献箱,而其他行可能有多个(或全部)贡献箱。我通过为每一行创建约束来说明这一点

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
添加到列表中,然后在此列表上执行
max()
,并将
LpVariable
设置为该值,但这仅获取
LpVariable
s的初始值,当解算器在
solve()
过程中更改数据时,这些最大值将不会动态更新

我还尝试过创建单独的
LpVariable
s来表示每列的最大值,设置如下:

    |    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)
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()
,返回一个
不可行的解决方案


有什么建议吗?

A高层描述

  • m行,n列
  • 引入
    n
    新的连续变量
    m_0,m_1,…,m_(n-1)
  • 添加
    m*n
    表单的新约束:
    • m\u 0>=条目(r\u 0,c\u 0)
    • m\u 0>=条目(r\u 1,c\u 0)
    • m\u 0>=条目(r\u(m-1),c\u 0)
    • m\u 1>=条目(r\u 0,c\u 1)
    • m\u 1>=条目(r\u 1,c\u 1)
    • m\u 1>=条目(r\u(m-1),c\u 1)
  • 目标:
    • 最小化(m_0+m_1+…+m_(n-1))
备注

  • 仅当解算器以某种方式向下推动每个m时,此操作才有效!
    • 这里:最小化总和->确定
  • 它独立于条目的类型(二进制、整数、连续)

通过定义一组2成员元组(表中可能的非零项的行-列索引),您可以更轻松地处理此问题的稀疏性

要处理每个列中的max条目,请引入@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)
“”“
示例,其中表为2x2,除(2,1)项外,任何项都可以为非零
"""
进口纸浆
#为非零的条目定义行-列索引的稀疏集
rowCols=set([(1,1),
(1, 2),
(2, 2)])
#定义行和
行和={1:1.1,
2: 3.4}
#检测表的行和列
行=设置([行中的(行,))行])
cols=set([col for(u,col)在rowCols中])
#定义纸浆模型
问题=纸浆.LpProblem(“问题”,纸浆.LpProblem)
#定义变量
variables=pill.LpVariable.dicts(“bin”,rowCols,lowBound=0,
cat=纸浆(连续)
colMaxes=pill.LpVariable.dicts(“列中的最大条目”),cols,
下限=0,类别=纸浆。LPC(连续)
#定义约束条件
#行和
对于行中的行:
问题+=(
lpSum([变量[行,列]
为col的col
如果(行,列)在rowCols中])
==
行和[行]
)
#列中最大值
对于rowCols中的(行,列):
问题+=(
lpSum([变量[row1,col1]
对于rowCols中的(第1行,第1列)
如果col1==col])