我正在尝试实现Kargers最小切割算法。该算法是一种随机算法,您应该运行(n(logn))^2
次,以确信您找到了最小切割。我做了一个新手的工作,在Ruby中实现了这个算法:
def karger(graph)
#graph will be an array
#each element of graph is an array
#these subarrays are of the form [[4], 43, 23, 1, 67]
#where the zeroth element is the vertex label
#the other elements represent edges to other vertices.
while graph.length > 2
#u & v are the indices of two random vertices that will be merged together
u = rand(0...graph.length)
v = rand(0...graph.length)
#while loop ensures u != v
while v == u
u = rand(0...graph.length)
v = rand(0...graph.length)
end
#merge u & v into a single vertex,
graph[u] += graph[v][1...graph[v].length]
graph[u][0].concat(graph[v][0])
graph.delete_at(v)
end
#this nested block eliminates self loops on the two remaining superveticies
graph.each do |z|
z.each do |x|
unless x.class == Array
if z[0].include?(x)
z.delete(x)
end
end
end
end
return (graph[0].length)-1 #-1 since the first element of both subarrays is the vertex label
end
我的问题是,当我试图创建一个块或循环来运行算法必要的(nlog(n))^2
次时,每个切割都是相同的值。因此,如果karger()
的第一个调用产生2的切割,那么此后的每个调用也将返回2。然而,如果我手动调用karger()
,只需在textmate中按cntrl R,我的结果就会发生变化。第一次在某个输入上运行它时,我得到了5的分数,下一次是2。因此,我尝试生成karger()
调用的大量样本并找到最小结果是不可行的,因为我只会有2或5的大量样本或其他什么。如果我运行调用karger()
(nlog(n))^2
次的块,我会得到不同的答案,这取决于karger()
的第一次调用返回的结果,因为每隔一次调用都返回相同的结果。
希望这是清楚的。
这是一个示例图:
testgraph1 = [[[1],2,2,3], [[2],1,1,3,4,5], [[3],1,2,4], [[4],2,3], [[5],2]]
编辑:
我想如果我添加了我用来迭代调用函数的方法,可能会有所帮助:
def kargeriterate(graph)
n = graph.flatten.length
min = graph.flatten.length
((n)*(Math.log(n)))**2.to_i.times do |z|
a = karger(graph)
puts a #this puts is here just to see each output
if a < min
min = a
end
end
return min
end
像delete
和delete_at
这样的方法就地修改它们的参数。由于ruby中的所有内容都是按值传递的,这意味着第二次(以及第三次、第四次、第五次等)调用karger
时,您正在对已处理的图进行调用,因此该方法不会执行任何操作。
看起来您修改了嵌套在graph
内部的数组以及graph
本身,因此在karger
方法开始时执行graph=graph.dup
是不够的。ruby没有内置标准的深度复制,但实现这一点的一个简单方法是转储和反序列化您的对象:
def karger(graph)
graph = Marshal.load(Marshal.dump(graph))
...
end