0

Task: I want to compute a shortest path between a source and target node in a DAG (directed acyclic graph) using Python's graph-tool efficiently. My DAG has negative weights.

In theory, this is a computationally "easy" problem (i.e., O(V + E)) by first computing a topological sorting of the graph and then visiting and updating parent nodes and distances (e.g. as discussed here).

How can I implement this efficiently using graph-tool?

My failed attempts so far:

  • manually implementing the theoretically efficient algorithm in Python. Since I have to loop over each vertex in the graph, however, this becomes unacceptably slow
  • using shortest_path function from graph-tool to call the Dijkstra routine from Boost Graph Library would have an acceptable running time, but doesn't fully exploit the DAG structure and doesn't work for negative weights anyways
  • using shortest_path to call Bellman-Ford returns a correct shortest path, but doesn't exploit the DAG structure and is too slow (O(VE)).

The efficient DAG shortest path algorithm is implemented as dag_shortest_paths in the underlying Boost Graph Library. Is there any way of accessing this function through graph-tool or any other way of computing this efficiently with graph-tool?

netword
  • 113
  • 2
  • 13

2 Answers2

0

This functionality has been added to the git version of graph-tool:

https://git.skewed.de/count0/graph-tool/commit/012787ecde818efc2b893ad0d8aff819b8deb6ca

An optional parameter dag=True can now be passed to shortest_path() that achieves what you want.

netword
  • 113
  • 2
  • 13
Tiago Peixoto
  • 5,149
  • 2
  • 28
  • 28
  • Thank you! :) Could you please clarify on the behaviour of the negative_weights flag if `dag=True` is passed? On a trial run, a call to `shortest_path` with `dag=True, negative_weights=False` runs considerably faster than with `dag=True, negative_weights=True` even though for DAGs, negative weights should not affect the running time – netword Jan 28 '19 at 10:37
  • The `negative_weights=True` parameter triggers the Bellman-Ford algorithm. When using `dag=True`, there is no need to pass `negative_weights=True`. – Tiago Peixoto Jan 28 '19 at 21:30
-1

Have you tried to use the Networkx library? Since I know, it's efficient, works for weighted and non-weighted graphs, and it's very simple to use.

https://networkx.github.io/documentation/networkx-1.10/reference/generated/networkx.algorithms.shortest_paths.weighted.all_pairs_dijkstra_path.html#networkx.algorithms.shortest_paths.weighted.all_pairs_dijkstra_path

An example:

    >>> import networkx as nx

    >>> G=nx.path_graph(5)
    >>> path=nx.all_pairs_dijkstra_path(G)
    >>> print(path[0][4])

[0, 1, 2, 3, 4]
Eduardo Soares
  • 992
  • 4
  • 14
  • 1
    Hi Eduardo, thank you for your answer, but I'm explicitly looking for a solution that uses `graph-tool` and that can be used with netagive edge weights. Furthermore, I'd like to be able to exploit the DAG structure. – netword Jan 21 '19 at 16:55