查找使用列表表示的所有组合

时间:2019-05-05 10:31:55

标签: python

我们有几个完整的二部图表示为列表。

enter image description here

例如,在图中有3个二部图,第一个由节点0和1组成,称为第1层,第二个由节点2和3组成,称为第2层,第三个由节点4组成,称为第3层。第i层和第i + 1层之间的节点都相互连接。另外,可能会有一些权重分配给这种边缘。权重为30的权重边在0和2之间,权重为10的权重边在2和4之间。这表示为字典{(0, 2): 30, (2, 4): 10}。图层表示为列表,如以下代码所示:

    l=[
        [
            [[0], [30]], [[1], [20]] #first set of bipartite nodes
        ], 

        [   
            [[2], [10]], [[3], [20]] #second set of bipartite nodes
        ], 

        [   
            [[4], [20]] #third set of bipartite nodes
        ]
    ]

我们想计算所有可能的组合,从每一层中选择一个节点。对于每个组合,总值将是各个节点的值之和,并且在该组合中,如果存在任何加权边缘,则将减去那些边缘权重。例如,对于组合0、2、4,节点的总和为30 + 10 + 20,我们在0和2与2和4之间设置了加权边,因此将这些边权重相减得出总权重为30 + 10 + 20-30-10。对于组合1,3,4,由于它们之间没有加权边,因此值将仅为20 + 20 +20。因此,以上所有可能的组合都是

 0,2,4 value = 30 + 10 + 20 - 30 - 10
 0,3,4 value = 30 + 20 + 20
 1,2,4 value = 20 + 10 + 20 - 10
 1,3,4 value = 20 + 20 + 20

如何使用如上所述的列表数据结构计算所有可能的组合及其值?

我尝试过的代码:

for element in itertools.product(*l):
    print(element)

这给了我笛卡尔积和所有可能的组合。但是如何考虑边缘的减法部分。有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

因此,以您的l表示法,这是我想出的(这将提供预期的结果):

edge_weights = {(0, 2): 30, (2, 4): 10}
combinations = dict()
for element in itertools.product(*l):
    combination = tuple([node_id[0] for node_id, node_value in element])
    value = sum([node_value[0] for node_id, node_value in element])
    combinations[combination] = value
print(combinations)  # first print without considering the edge weights
for combination in combinations.keys():
    for edge in zip(combination[:-1], combination[1:]):
        combinations[combination] -= edge_weights.get(edge, 0)
print(combinations)

请注意,这假设至少有2个完整的二部图。

您绝对可以按照this comment中的说明更改变量名l。我不知道这个二部图列表的灵活性如何,但是我不会在列表中包含节点ID或它的值,这会使问题变得更加复杂且难以理解。