我有一个大的无向图,有数十万个节点和数万个边。我有两个不同的问题:
1)对于一组节点N =(节点[1],节点[2],节点[3],节点[4],节点[5]),例如,M =(节点[1001],节点[1002],节点[1003],节点[1004],节点[1005])在N中的任何节点与M中的任何节点之间是否存在路径?
我知道存在nx.path.bidirectional_dijkstra()函数,但要使用它我必须测试所有N * M组合是多余的(因为许多节点会被多次查询),并且因为在实践中N / M的长度可能是数千,这是不实际的。
2)一个稍微独立的问题,但有没有办法获得从N到M的所有路径列表?
我对如何“推出自己的”解决方案有一个粗略的想法,但我想它会比有人已经这样做慢很多倍,但没有图论的背景我不知道甚至知道我需要搜索什么!感谢。
答案 0 :(得分:2)
这样的事情应该有效:
def is_there_a_path(_from, _to):
visited = set() # remember what you visited
while _from:
from_node = _from.pop(0) # get a new unvisited node
if from_node in _to:
# went the path
return True
# you need to implement get_nodes_referenced_by(node)
for neighbor_node in get_nodes_referenced_by(from_node):
# iterate over all the nodes the from_node points to
if neighbor_node not in visited:
# expand only unvisited nodes to avoid circles
visited.add(neighbor_node)
_from.append(neighbor_node)
return False
您可以通过附加路径而不是neighbor_node从1.
中的函数构建此函数,但需要花费更多时间并且可能出现圆圈。在执行yield
return
代替for path in is_there_a_path(_from, _to):
获取无穷无尽的路径
醇>
这是上面的算法,它遍历ruby中的对象图,并找到从self到另一个对象的路径,返回路径:
class Object
#
# breadth first search for references from the given object to self
#
def reference_path_to(to_object, length, trace = false)
paths = [[to_object]]
traversed = IdentitySet.new
traversed.add(to_object)
start_size = 1 if trace
while not paths.empty? and paths.first.size <= length
references = paths[0][0].find_references_in_memory
# if we print here a SecurityError mey occur
references.each{ |reference|
return [reference] + paths[0] if reference.equal?(self)
unless traversed.include?(reference) or paths.any?{ |path| reference.equal?(path)}
paths.push([reference] + paths[0])
traversed.add(reference)
end
}
if trace and start_size != paths[0].size
puts "reference_path_length: #{paths[0].size}"
start_size = paths[0].size
end
paths.delete_at(0)
end
return nil
end
end # from https://github.com/knub/maglevrecord/blob/60082fd8c16fa7974166b96e5243fc0a176d172e/lib/maglev_record/tools/object_reference.rb
Python算法应该与我认为的ruby算法大致相同。
答案 1 :(得分:0)
1)将一个带有边缘的节点x
添加到N
中的每个节点,将一个节点y
添加到M
中的每个节点。然后检查是否有x
- y
路径。注意 - 确保x
和y
不是节点。
G.add_edges_from([('x',node) for node in N])
G.add_edges_from([(node,'y') for node in M])
nx.has_path(N,M) #true if there was an M to N path
2)
augmented_paths = nx.all_simple_paths(G,source=x,target=y)
(这会产生一个发电机)。
for augmentedpath in nx.all_simple_paths(G, source=x, target=y):
path = augmentedpath[1:-1] #don't want the x and y included
print path