我有一个我想解决的线性编程问题,其所有数据都来自表格。
该表的大小(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()
解决方案。
有什么建议吗?
答案 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))
<强>说明强>:
答案 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)