Skip to content Skip to sidebar Skip to footer

NetworkX / Python_igraph: All Paths Between Two Nodes, Limited By List Of Nodes

I am using the function from here : def find_all_paths(graph, start, end, mode = 'OUT', maxlen = None): def find_all_paths_aux(adjlist, start, end, path, maxlen = None): path =

Solution 1:

You can create a subgraph that only includes the nodes you would like to see in your paths In 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)

This will find all simple paths and exclude any nodes in vn since they are not in the subgraph


Solution 2:

Ok, I will answer myself, but will be happy about testing and comments: Taking the second function from above (adapted to work with both python-igraph and networkx), I added the vn argument, so path search stops if a vn node is reached:

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]

Solution 3:

Delete the nodes from the Graph before you recurse over long paths.

Put them back when you are done.

This takes less memory in highly connected graphs.

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])))
  • if you are doing time or memory tests I would enjoy hearing about the results with real data in the comments below.

Post a Comment for "NetworkX / Python_igraph: All Paths Between Two Nodes, Limited By List Of Nodes"