这里我提供了我的问题的最小完全可验证示例:
考虑尺寸为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在这里不应该可用于分配,或者矩阵中相应的模式相关成本应该更新到太高的值,所以那些不再考虑下一行的人应该像这样继续下去。
最终意味着如果可以分配,相应的模式本质上应该是互斥的。
有人可以建议如何解决这个问题吗?
答案 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),