线性规划矩阵优化

huangapple go评论61阅读模式
英文:

linear programming optimization for matrix

问题

我有一个包含每个元素成本的n x n矩阵。每行和每列都应满足要求,同时可以最小化激活元素的总和。在这种情况下,激活意味着其系数为1。

具有成本$a_{ij}$的4x4矩阵可以如下所示:

|100  -20  30  40 | = 2     
|10   20   10  20 | = 1     
|50   -40  20  10 | = 2     
|-10  -30  10  50 | = 1    
 1     2   1    2   = 6

因此,第一行只能有两个系数为1的元素,第一列也只能有一个元素。目标基本上是所有非零元素的总和。

结果可以是:

|0  1  0  1 | = 2
|0  0  0  1 | = 1
|1  0  1  0 | = 2
|0  1  0  0 | = 1
 1  2  1  2   = 6

然后目标是:1 * -20 + 1 * 40 + 1 * 20 + 1 * 50 + 1 * 20 + 1 * -30 = 80

在SAS中,有netflow包,但在R中没有类似的包。我尝试过在Python中使用pulp,但似乎不起作用。看起来我们可能需要硬编码每个变量。对于如何以其他方式构建这个问题,任何建议将不胜感激!非常感谢!

英文:

I have a n x n matrix that contains cost for each element.

Each row and each column should satisfy the requirement while it can minimize the sum of activated elements. In this case, activated means its coefficient is 1.

A 4x4 matrix with costs $a_ij$ can look like this:

|100  -20  30  40 | = 2     
|10   20   10  20 | = 1     
|50   -40  20  10 | = 2     
|-10  -30  10  50 | = 1    
 1     2   1    2   = 6

So the first row can only have two elements to have coefficient of 1 and the first column can only have one element to. The objective is basically the summation of all elements that are non-zero.

The results can be:

|0  1  0  1 | = 2
|0  0  0  1 | = 1
|1  0  1  0 | = 2
|0  1  0  0 | = 1
 1  2  1  2   = 6

The objective is then: 1 * -20 + 1 * 40 + 1 * 20 + 1 * 50 + 1 * 20 + 1 * - 30 = 80

In SAS, there is netflow package but there is no similar packages R. I have tried to use pulp in python but it did not seem working. It also seems like we need to hard code each variable. Any suggestions on how else I might formulate the problem would be much appreciated! Thanks a lot!

答案1

得分: 1

以下是 pulp 的一些开始。如果展示你迄今为止的工作,你可能会得到更好的答案...

一些建议:

  • pulp 中,你可以使用几个嵌套循环并逐个声明变量(有许多示例),或者使用 .dicts 方法并传递一个索引集。我喜欢这样做,因为然后你可以使用元组索引 [i, j]
  • 如果你想在索引上保持一致,可以将成本展开为相同类型的索引,或者只是在嵌套循环中声明变量,并始终进行嵌套索引 [i][j]

尝试你的约束条件... 通过按需循环遍历行/列,它们应该很容易。在制定每个约束条件后打印模型,以确保数学是正确的。

如果卡住,请回复评论。

import pulp

costs = [
    [100, -20, 30, 40],
    [10, 20, 10, 20],
    [50, -40, 20, 10],
    [-10, -30, 10, 50],
]

rows, cols = 4, 4
index_set = [(i, j) for i in range(rows) for j in range(cols)]

# 设置问题
prob = pulp.LpProblem('matrix_picker', sense=pulp.LpMaximize)

# 变量
select = pulp.LpVariable.dicts('select', index_set, cat=pulp.LpBinary)

# 目标
prob += sum(select[i, j] * costs[i][j] for i, j in index_set)

print(prob)
英文:

Here's a start in pulp. You'll likely get better answers if you show what you have worked on so far...

A couple of notes:

  • in pulp you can either make a couple of nested loops and declare the variables individually (many examples) or use the .dicts method and pass an index set. I like that because then you can use tuple indexing [i, j]
  • if you want to be consistent in your indexing, you could flatten out costs to the same type of index or just declare variable within nested loop and do nested indexing throughout [i][j]

Try your constraints.... they should be a snap by looping over rows/cols as needed. Print the model after you make each one to make sure the math is correct.

Comment back if you are stuck.

import pulp

costs = [
	[100 , -20 , 30 , 40 ],     
	[10  , 20  , 10 , 20 ],     
	[50  , -40 , 20 , 10 ],     
	[-10 , -30 , 10 , 50 ],    
]

rows, cols = 4, 4
index_set = [(i, j) for i in range(rows) for j in range(cols)]

# set up the problem
prob = pulp.LpProblem('matrix_picker', sense=pulp.LpMaximize)

# variables
select = pulp.LpVariable.dicts('select', index_set, cat=pulp.LpBinary )

# objective
prob += sum(select[i, j] * costs[i][j] for i, j in index_set)

print(prob)

huangapple
  • 本文由 发表于 2023年4月4日 12:33:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75925538.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定