简体   繁体   English

在Python 2.7中实现Karger Min Cut时出错

[英]An error when implementing Karger Min Cut in Python 2.7

I ran into a deadlock when implementing Karger Min Cut algorithm in Python. 在Python中实现Karger Min Cut算法时,我陷入了僵局。 I broke my head but still can't figure out why my implementation does not work, while it works fine with pencil and paper... 我伤了脑袋,但仍然无法弄清楚为什么我的实现无法正常工作,尽管可以用铅笔和纸正常工作...

Consider a graph with four nodes 1, 2, 3, 4 and five edges 考虑具有四个节点1、2、3、4和5个边的图

[1, 2], [1, 3], [2, 3], [2, 4], [3, 4] . [1, 2], [1, 3], [2, 3], [2, 4], [3, 4]

In python, I represented them by two lists: 在python中,我用两个列表表示它们:

nodes = [1, 2, 3, 4]
edges = [[1, 2], [1, 3], [2, 3], [2, 4], [3, 4]]

My idea is: randomly choose an edge, say [1, 3] , collapse it, remove node = 3 from nodes list as if 3 is merged into 1 and, remove edge [1, 3] from edges list. 我的想法是:随机选择一条边,说[1, 3] ,将其折叠,从节点列表中删除node = 3 ,就好像将3合并为1一样,然后从边列表中删除边[1, 3]

Now the two lists look like: 现在,两个列表看起来像:

nodes = [1, 2, 4]
edges = [[1, 2], [2, 3], [2, 4], [3, 4]]

As 3 is merged into 1, the edges list is further updated to 当3合并为1时,边列表进一步更新为

edges = [[1, 2], [2, 1], [2, 4], [1, 4]] 

by changing all 3 in the resulting edges list to 1. 通过将结果边列表中的所有3更改为1。

This completes the first loop. 这样就完成了第一个循环。

In the second loop, suppose edge [1, 2] is randomly chosen from the edges list, then repeat the above steps I got so that 在第二个循环中,假设从边列表中随机选择了边[1, 2] ,然后重复我得到的上述步骤,以便

nodes = [1, 4]
edges = [[2, 1], [2, 4], [1, 4]] 

which is further changed to [[1, 1], [1, 4], [1, 4]] . 进一步更改为[[1, 1], [1, 4], [1, 4]] As [1, 1] indicates a self loop, it is removed and the resulting edges list for this round is [[1, 4], [1, 4]] 由于[1, 1]表示自循环,因此将其删除,并且此回合的最终边列表为[[1, 4], [1, 4]]

As the number of nodes is two, the process ends and the number of min cuts is 2, the length of the final edges list. 当节点数为2时,过程结束,最小切割数为2,即最终边列表的长度。

So my implementation in Python is as follows: 所以我在Python中的实现如下:

import numpy as np


nodes = []
edges = []


f = open("kargerMinCut.txt", "r")
# The txt file has the form of an adjacency list
# The link to the txt file is at the very end          

for l in f:
    v = l.split()
    # The first element of each line is a (distinct)
    # vertex and is appended to nodes list.    
    nodes.append(int(v[0]))
    for u in v[1:]:
        # Edges list has the form as described in my 4 nodes example
        # above, which is unlike what in an typical adjacency list for
        # an undirected graph is. Here, if node 1 and node 2 share 
        # an edge, then edge [1, 2] only appears once in the "edges"
        # list, edge [2, 1] is not, which is why I used "set" below.
        edge = [int(v[0])]
        edge.append(int(u))
        count = 0
        for edg in edges:
            if (set(edg) == set(edge)):
                count += 1
        if (count == 0):
            edges.append(edge)

f.close()


while (len(nodes) > 2):
    # Number of current edges
    m = len(edges)
    # Choose a random edge uniformly 
    idx = np.random.randint(m)
    edgeChosen = edges[idx]
    # Two corresponding nodes of the chosen edge
    i = edgeChosen[0]
    j = edgeChosen[1]

    # Remove the second one from nodes list
    nodes.remove(j)
    # Remove the chosen edge from edges list
    del edges[idx]

    # Change all "j"s to "i"
    for ed in edges:
        for e in ed:
            if e == j:
                e = i

    # Remove those [i, i] edges (self loop)
    for ed in edges[:]:
        if len(set(ed)) == 1:
            edges.remove(ed)


print len(edges)

This is just one run of the Karger Min Cut algorithm. 这只是Karger Min Cut算法的一次运行。 Although those for loops in the while loop is inefficient, I just wanna have a try on this idea. 尽管while循环中的for循环效率不高,但我只是想尝试一下这个想法。 I experimented the above code on an input with 200 nodes and 2000+ edges. 我在具有200个节点和2000多个边的输入上试验了上面的代码。

But no matter what I did, Python gives the following error after successfully removing a couple of nodes and edges : 但是,不管我做什么,Python在成功删除几个节点和边后都会给出以下错误:

nodes.remove(j)
ValueError: list.remove(x): x not in list

which is kind of funny. 这很有趣。 If x is not in nodes list, it means x is one of the "j"s previously included in a chosen edge and was either removed or changed to the corresponding "i". 如果x不在节点列表中,则表示x是先前包含在所选边中的“ j”之一,并且已被删除或更改为相应的“ i”。

However, I cannot find what is wrong with my code. 但是,我找不到我的代码有什么问题。 Am I missing something? 我想念什么吗? Any ideas on it? 有什么想法吗? Thanks a lot. 非常感谢。

Link to the data file (great thanks to nischayn22 on GitHub): https://github.com/nischayn22/PythonScripts/blob/master/kargerMinCut.txt 链接到数据文件(感谢GitHub上的nischayn22): https : //github.com/nischayn22/PythonScripts/blob/master/kargerMinCut.txt

Here's a pretty rudimentary working version. 这是一个非常基本的工作版本。 This code can be improved in a lot of ways but it works and should point you in the direction of how to do things right. 可以通过很多方式来改进此代码,但是它可以工作,并且应该为您指明正确做事的方向。

from random import randint

nodes = [1,2,3,4]
edges = [[1, 2], [1, 3], [2, 3], [2, 4], [3, 4]]


while (len(nodes) > 2):
    target_edge = edges[randint(0, len(edges) - 1)]
    replace_with = target_edge[0]
    num_to_replace = target_edge[1]
    for edge in edges:
        if(edge[0] == num_to_replace):
            edge[0] = replace_with
        if(edge[1] == num_to_replace):
            edge[1] = replace_with
    edges.remove(target_edge)
    nodes.remove(num_to_replace)
    #remove self loops
    for edge in edges:
        if(edge[0] == edge[1]):
            edges.remove(edge)
    print(edges)

print(nodes)
print(edges)

The actual part of the code making the error is 导致错误的代码的实际部分是

edgeChosen = edges[idx]
i = edgeChosen[0]
j = edgeChosen[1]

j is not in nodes. j不在节点中。

If you post your full code we could help more. 如果您发布完整的代码,我们可以提供更多帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM