矩形矩阵munkres模式基于列的互斥分配

时间:2015-06-08 11:44:36

标签: python-2.7 hungarian-algorithm

这里我提供了我的问题的最小完全可验证示例:

考虑尺寸为3 X 17的矩形矩阵: 行= [10,6,9]考虑。 其中列是模式,每个模式都与值

相关联
example file: "patterns_list"  <pattern <space> associated value>
['2','3'] 12  
['2','1'] 11  
['2','5'] 11  
['3','4'] 10  
['3','5'] 9  
['4','1'] 9  
['4','5'] 9  
['3','6'] 8  
['4','6'] 8  
['1','5'] 8  
['2'] 7  
['1','6'] 7  
['3'] 5  
['4'] 5  
['1'] 4  
['5'] 4  
['6'] 3  

现在,列值和行值之间的差异被视为矩阵3 X 17中的成本,如果成本结果为负,则将其替换为所有列值的总和(没有具体但确保一些巨大的值)。现在需要进行最低成本分配。我使用 sudo apt-get install python-munkres 安装了库 munkres 并运行以下代码:

from munkres import Munkres, print_matrix
import linecache

rows=[10,6,9]
v=[]
diff=[]
value=[]
f = open("patterns_list","r")
for line in f:
        line=line.strip()
        line=line.split(' ')
        v.append(int(line[1]))
total=sum(v)
for i in range(0,len(rows)):
        for j in range(0,len(v)):
                x=v[j]-rows[i]
                if x<0:
                        value.append(total)
                else:
                        value.append(v[j]-rows[i])
        diff.append(value)
        value=[]

matrix=diff

m = Munkres()
indexes = m.compute(matrix)
print_matrix(matrix, msg='Lowest cost through this matrix:\n')
total = 0
patterns=[]
print "Allocation indices:"
for row, column in indexes:
    value = matrix[row][column]
    total += value
    print '(%d, %d) -> %d' % (row, column, value)
    patterns.append(int(column))

print 'total cost: %d' % total
print "Corresponding allocated patterns:\n"
for i in range(0,len(patterns)):
    line = linecache.getline("patterns_list",patterns[i])
    print line

生成以下输出:

Lowest cost through this matrix:

[  2,   1,   1,   0, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130]
[  6,   5,   5,   4,   3,   3,   3,   2,   2,   2,   1,   1, 130, 130, 130, 130, 130]
[  3,   2,   2,   1,   0,   0,   0, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130]
Allocation indices:
(0, 3) -> 0
(1, 10) -> 1
(2, 4) -> 0
total cost: 1
Corresponding allocated patterns:

['2','5'] 11

['1','5'] 8

['3','4'] 10

问题是[2,5],[1,5],[3,4]是最终分配的模式,它们对应于最低成本。这里的模式[2,5],[1,5]并不相互排斥。 '5'有共同之处。一旦r1得到[2,5]分配,那么包含任何分配元素的其余模式,即2,5在这里不应该可用于分配,或者矩阵中相应的模式相关成本应该更新到太高的值,所以那些不再考虑下一行的人应该像这样继续下去。

最终意味着如果可以分配,相应的模式本质上应该是互斥的。

有人可以建议如何解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

好消息:有办法解决这个问题 坏消息:没有简单方法来解决此问题。

有什么问题?
在进行一些初步计算之后,您将拥有2D成本矩阵和集合列表 - 成本矩阵中的每列一个。目标是在成本矩阵中尽可能多地选择指数

  • 没有两个选定的索引(作业)位于同一行或列中,
  • 与作业列相关联的集合是不相交的,
  • 最小化分配总和。

解决方案是什么?
可以将此问题视为N维分配问题的实例。问题的前两个维度(成本矩阵的两个维度)非常明显。其余的维度可能不那么明显。

首先,我们要创建一个包含其他集合中所有值的超集。这个超集的大小 - 加上成本矩阵的两个维度 - 是这个N维分配问题中N的值。在您的示例中,我们的超集为[1, 2, 3, 4, 5, 6],因此我们的N为8。

在我们的二维成本矩阵中,矩阵中的每个成本可以通过其行号和列号来定位。例如,(1,3)的成本是4.对于8维成本矩阵,每个成本将使用8个位置编号来定位。幸运的是,我们可以迭代地计算这些位置数。

rows = [10,6,9]

import ast
from munkres import print_matrix

listOfSets = []
v = []
with open("patterns_list","r") as file:
    for line in file:
        listOfSets.append(ast.literal_eval(line.strip().replace("'","").split(" ")[0]))
        v.append(int(line.strip().split(" ")[1]))

total = sum(v)
matrix = []
for row in rows:
    values = []
    for num in v:
        x = num-row
        values.append(total if x<0 else x)
    matrix.append(values)

superset = list(set().union(*listOfSets))
counter = [1] * len(superset)
newMatrix = []
for row in range(0, len(rows)):
    for column in range(0, len(v)):
        if matrix[row][column] == total:
            break
        temp = [matrix[row][column], row, column]
        for n in range(0, len(superset)):
            if superset[n] in listOfSets[column]:
                temp.append(0)
            else:
                temp.append(counter[n])
                counter[n] += 1
        newMatrix.append(temp)

print_matrix(newMatrix, msg="New Matrix = [ value, row, column, dimension1position, dimension2position...]")

现在我们有一个列表,其中包含2D成本矩阵中的每个值(不是虚拟值)及其在新N维矩阵中的相关位置。我选择这样做而不是实际制作完整的N维矩阵,因为完整的N维矩阵将非常大并且大部分填充虚拟值。但是,如果需要,可以非常容易地从该列表中创建完整的N维矩阵。在此N维数组上运行多维分配问题解算器将为您提供所需的答案。但是,据我所知,多维分配问题求解器的代码不存在。你必须自己编写代码。

ps:我稍微清理了原始代码。

rows=[10,6,9]

from munkres import Munkres, print_matrix
import linecache

v=[]
with open("patterns_list","r") as file:
    for line in file:
        v.append(int(line.strip().split(" ")[1]))

total=sum(v)
matrix=[]
for row in rows:
    values=[]
    for num in v:
        x=num-row
        values.append(total if x<0 else x)
    matrix.append(values)

print_matrix(matrix, msg="Cost Matrix:")

indices = Munkres().compute(matrix)
total = 0
patterns=[]
print "\nAllocated Indices:"
for row, column in indices:
    value = matrix[row][column]
    total += value
    print "(%d, %d) -> %d" % (row, column, value)
    patterns.append(column)

print "Total Cost: %d" % total

print "\nCorresponding Allocated Patterns:"
for pattern in patterns:
    print linecache.getline("patterns_list",pattern),