from random import randint
from collections import defaultdict
######################
def getGraph(filename):
'''
The function takes a txt file as input and returns
the Graph with 1st element of each row as a vertex.
'''
with open(filename, 'r') as f_in:
G = defaultdict(list)
for row in f_in:
row = row.split()
G[row[0]] = row[1 : ]
return G
######################
def getVEPair(range):
'''
The function takes the range as input and returns a
pair of random integers.
'''
v = randint(1, range)
e = randint(1, range)
return v, e
######################
def removeVEPair(G, V, E):
'''
The function takes Graph, Vertex and Edge as input
and removes this pair from the Graph. The function then
returns the resulting Graph.
'''
while E in G[V]:
G[V].remove(E)
return G
######################
def contractNodes(G, V, E):
'''
The function takes a Graph, vertex and edge as the input
and contracts the two nodes which the edge connects. The
function then returns the resulting Graph.
'''
edges = G[E]
for edge in edges:
if edge != V:
G[V].append(edge)
return G
######################
def removeNode(G, V, E):
'''
The function intakes the graph and the node to be deleted.
The function deletes the node and updates all instances of
the deleted node in the Graph.
The function then returns the resulting Graph.
'''
del G[E]
for Vertex in G:
while E in G[Vertex]:
G[Vertex].remove(E)
if V != Vertex:
G[Vertex].append(V)
return G
######################
def kargerMinCut():
'''
The function takes a graph as input and returns the min cut
of the graph.
'''
minCut = []
for i in range(0, 100):
G = getGraph('dataGraph.txt')
while(len(G) > 2):
v, e = getVEPair(8)
V = str(v)
E = str(e)
keys = G.keys()
if V in keys and E != V:
if E in G[V]:
G = removeVEPair(G, V, E)
G = contractNodes(G, V, E)
G = removeNode(G, V, E)
else:
continue
print G
for v in G:
minCut.append(len(G[v]))
break
return minCut
######################
minCut = kargerMinCut()
print '######################'
print minCut
print min(minCut)
我通过将下面的数据保存在dataGraph.txt文件中来执行上面的代码。数字,即最小切割为1,正确的切割为(4,5),但我得到的是(1,7),(3,6),(8,4),(1,5),(3,7 ),(4,5)也作为算法的单独迭代中的最小割对。
所以我的问题是,尽管minCut即1是正确的,但是为什么我将这些其他对作为minCuts?
在下面的数据中,每行的第一个元素表示一个节点,该行的其余元素表示第一个元素连接到的节点。例如1连接到3、4和2。
1 3 4 2
2 1 4 3
3 1 2 4
4 5 3 2 1
5 4 8 6 7
6 8 7 5
7 5 8 6
8 5 7 6
答案 0 :(得分:1)
我认为说“正确的分数是(4,5)”是不正确的。
我认为说“正确的切线是两组{1、2、3、4}和{5、6、7、8}”会更正确。切割是将图的顶点分为两个部分,而切割集(这似乎是您所指的)是连接这两组顶点的一组边。对于您的图形,与最小切割对应的切割集为{(4,5)}。
为什么会出现“(1,5)”这样的“不正确”结果?这是因为当您收缩一条边线并将两个节点合并为一个节点时,无需重新标记合并的节点。合并的节点保留两个节点之一的名称。当您到达最后并且算法碰巧找到大小为1的剪切时,两个尚存节点的标签是最小剪切每一侧的节点的标签,这些标签碰巧一直未删除。如我所说,正确的切割是({1、2、3、4},{5、6、7、8}):值1和5只是切割两侧的代表。
您将需要调整代码,以便在收缩边并将两个节点合并为一个时调整节点标签。最后,您可以从两个尚存节点的标签读取剪切,并从连接两组节点的边缘读取剪切集。