NetworkX / Python_igraph:两个节点之间的所有路径,受节点列表限制

时间:2015-06-29 12:57:49

标签: python graph igraph networkx network-analysis

我正在使用here中的函数:

def find_all_paths(graph, start, end, mode = 'OUT', maxlen = None):
def find_all_paths_aux(adjlist, start, end, path, maxlen = None):
    path = path + [start]
    if start == end:
        return [path]
    paths = []
    if maxlen is None or len(path) <= maxlen:
        for node in adjlist[start] - set(path):
            paths.extend(find_all_paths_aux(adjlist, node, end, path, maxlen))
    return paths
adjlist = [set(graph.neighbors(node, mode = mode)) \
    for node in xrange(graph.vcount())]
all_paths = []
start = start if type(start) is list else [start]
end = end if type(end) is list else [end]
for s in start:
    for e in end:
        all_paths.extend(find_all_paths_aux(adjlist, s, e, [], maxlen))
return all_paths

找到两个节点之间的所有路径。

另一个功能是here

def find_all_paths(graph, start, end):
path  = []
paths = []
queue = [(start, end, path)]
while queue:
    start, end, path = queue.pop()
    print 'PATH', path

    path = path + [start]
    if start == end:
        paths.append(path)
    for node in set(graph[start]).difference(path):
        queue.append((node, end, path))
return paths

我想扩展其中一个函数以获取另一个参数,该参数将是“via_nodes”的列表。

如果一个路径在其end和start节点之间有一个via_node,则不应该返回它。

首先使用现在的函数计算所有路径并且之后排除满足上述条件的路径会很容易,但为了使其更高性能,我希望它在遇到a时停止路径搜索via_node在早期阶段。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

您可以创建一个仅包含您希望在路径中看到的节点的子图 在 Networkx 2.5 中:

sub_graph = nx.subgraph_view(graph, filter_node:lambda n: n in [start, end] or n not in vn)
return all_simple_paths(sub_graph, start, end)

这将找到所有简单路径并排除 vn 中的任何节点,因为它们不在子图中

答案 1 :(得分:0)

好的,我会回答自己,但会对测试和评论感到高兴:从上面的第二个功能(适用于python-igraph和networkx),我添加了vn参数,所以如果一个路径搜索停止到达vn节点:

import igraph as ig

def find_all_paths2(graph, start, end, vn = []):
        """ 
        Finds all paths between nodes start and end in graph.
        If any node on such a path is within vn, the path is not         
        returned.
        !! start and end node can't be in the vn list !!

        Params:
        --------

        G : igraph graph

        start: start node index

        end : end node index

        vn : list of via- or stop-nodes indices

        Returns:
        --------

        A list of paths (node index lists) between start and end node
        """

    vn = vn if type(vn) is list else [vn]
    path  = []
    paths = []
    queue = [(start, end, path)]
    while queue:
        start, end, path = queue.pop()
        #print 'PATH', path
        path = path + [start]
        #print 'PATH after adding start ', path

        if start in vn:
            print start,' is in vianodes ',str(vn)
            pass#paths.append(path)

        if start == end:
            print 'end'
            paths.append(path)
        #print graph.neighbors(start)
        if start not in vn:
            print start,' not in vianodes ',str(vn)
            for node in set(graph.neighbors(start)).difference(path):
                queue.append((node, end, path))
    return paths

G = ig.Graph()
G.add_vertices(14)
G.add_edges([(13,10),(12,13),(11,12),(10,11),(9,10),(2,9),(0,1), (1,2),(2,3),(3,0),(0,4),(4,5),(5,6),(6,7),(7,8),(8,6)])#,(0,0)])
#G = G.as_directed()


for p in find_all_paths2(G,0,12,[]):
    print 'path: ',p

path:  [0, 3, 2, 9, 10, 13, 12]
path:  [0, 3, 2, 9, 10, 11, 12]
path:  [0, 1, 2, 9, 10, 13, 12]
path:  [0, 1, 2, 9, 10, 11, 12]

for p in find_all_paths2(G,0,12,[13]):
        print 'path: ',p


path:  [0, 3, 2, 9, 10, 11, 12]
path:  [0, 1, 2, 9, 10, 11, 12]

答案 2 :(得分:0)

在递归长路径之前,从图表中删除节点。

完成后将它们放回去。

这在高度连接的图形中占用的内存较少。

import networkx
G = networkx.Graph()
G.add_node(14)
G.add_edges_from([(13,10),(12,13),(11,12),(10,11),(9,10),(2,9),(0,1),(1,2),(2,3),(3,0),(0,4),(4,5),(5,6),(6,7),(7,8),(8,6)])


def simple_paths_with_node_exclusion(G, source, target, exclude_nodes):
        edge_list = []
        edge_list.extend(G.edges_iter(exclude_nodes))
        G.remove_nodes_from(exclude_nodes)
        value = networkx.all_simple_paths(G, source, target)
        G.add_nodes_from(edge_list)
        return value

print(list(simple_paths_with_node_exclusion(G,0,12,[13])))
  • 如果您正在进行时间或记忆测试,我会很乐意在下面的评论中听到有关实际数据的结果。