2

Stack Overflow!

I have a directed graph and need to find all paths between a source and target vertex. Between several vertices, there are multiple edges. Using graph-tool, one may suggest using graph_tool.topology.all_paths(g, source, target), however, the lists contained in this vertex iterator are for vertices only; see some of the output below. Due to there being multiple edges between vertices, there are multiple occurrences of paths such as [ 0 4 8 13] and [0 4 13] and I am not able to distinguish between these paths.

iterator, paths:  [ 0  4  8 13]
iterator, paths:  [ 0  4 13]
iterator, paths:  [ 0  4  8 13]
iterator, paths:  [ 0  4 13]
iterator, paths:  [ 0  4  8 13]
iterator, paths:  [ 0  4 13]

I need the paths in the form of edges, to be able to iterate over edge properties along each path. To solve this issue, I can only think of one method (apart from rewriting large amounts of code): creation of intermediary vertices to avoid occurrences of multiple edges between any two vertices. For any parallel edges between two vertices, they would be connected to each their own, unique intermediary vertex as to uniquely define the paths returned from graph_tool.topology.all_paths(g, source, target).

Is there a way to return all paths in the form of edges between a source and destination vertex?

Espenol
  • 21
  • 3

2 Answers2

3

This has been added to graph-tool recently: https://git.skewed.de/count0/graph-tool/commit/5457d04f5f37c7a49e87b67c666c1a865e206b9a

You just need to pass the edges=True parameter:

for p in all_paths(g, u, v, edges=True):
    for e in p:
        print(e)  # e is an edge descriptor
Tiago Peixoto
  • 5,149
  • 2
  • 28
  • 28
  • Is it possible to get e.edge_index which was set for edge before? – D. Make Nov 28 '18 at 12:34
  • @D.Make I don't understand your question. – Tiago Peixoto Nov 28 '18 at 17:39
  • @TiagoPeixoto I can set vertex_index using v.vertex_index = index. And when I calculate all_paths I use two indexes (from and to) I've set before. I tried the same with e.edge_index = index, but when I got edges from all_path and tried to get edge_index from edge descriptor I got different index from I've set before (as I understand all_path reindexed every edge from 0). So the way I use to clarify edge is to add edge property. But I supposed to set edge_index, because every edge in my case have a unique id from my db. That just details. Thank you for your great package! It works really cool. – D. Make Nov 29 '18 at 05:29
-1

Finding all paths is pretty computationally expensive (O(N+E), IIRC) already. If you are ultimately interested in the combinations of data attributes of your edges then I would find the path on a reduced graph (without multi-edges), and then look up the possible data attributes of each edge (can be done in constant time) and compute the possible combinations of data attributes. Step-by-step:

Find the paths. Convert the list of nodes to a list of edges.

path_edges = zip(path_nodes[:-1], path_nodes[1:])

Create a dictionary (dict) mapping each edge (source, target) to a list of data attributes, e.g. [0.2, 0.7, 42]. Each data attribute corresponds to one multi-edge (presumably, many of these will be lists of length 1 in your case as multi-edges seem rare from the data sample you gave).

Compute all combinations of data attributes for all edges in the path.

 data = [edge_to_data[edge] for edge in path_edges]
 cartesian_product = itertools.product(*data) # returns an iterator!
 print(list(cartesian_product))

Finally, apply your cost function or whatever to the list of values.

Paul Brodersen
  • 11,221
  • 21
  • 38