Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortest Path Doesn't Support Negative Edge Weights Properly #145

Open
jonathanrainer opened this issue Jul 14, 2023 · 6 comments · May be fixed by #155
Open

Shortest Path Doesn't Support Negative Edge Weights Properly #145

jonathanrainer opened this issue Jul 14, 2023 · 6 comments · May be fixed by #155
Labels
enhancement New feature or request

Comments

@jonathanrainer
Copy link

Hi,

First off, thank you so much for implementing this graph library, it's made some of my recent projects so much easier not having to implement all my own algorithms!

However I've found something that I'd be interested in the maintainer's views on. From looking at the code it appears as though the shortestPath function is using a variant of Djikstra's algorithm to find the shortest path, now this is fine, but in my particular use case I was using negative edge weights (because I wanted to find the longest path through a DAG) and I was getting different answers each time I ran the code. Eventually after some searching I realised that Djikstra's doesn't support negative edge weights: https://stackoverflow.com/questions/6799172/negative-weights-using-dijkstras-algorithm, but this wasn't clear from the function documentation. Now I realise my use case is slightly novel but I wondered if it would be possible to at least add a health warning/error case to the function so that people don't fall down the same hole that I did?

In the end I implemented shortest path via repeated DFS and TopologicalSorting so this isn't a huge blocker for me, but I wanted to add to the library in any way I could and thought this would be a good start.

Again huge thanks for this library

@dominikbraun dominikbraun added the enhancement New feature or request label Jul 14, 2023
@dominikbraun
Copy link
Owner

Hi,

I'm happy to hear you like this library! You're right – Dijkstra's algorithm doesn't support negative edge weights, and this should indeed be documented to avoid confusion. For very generic functions such as ShortestPath, this library usually prefers the more general, less performant solution over a less general, more performant solution, so it really would make sense to support negative edge weights even if the algorithm would be slightly slower. There would still be place for faster solutions tailored to a specific use case.

So I'm open to replace the implementation of ShortestPath with an algorithm that can deal with negative edge weights, such as Bellman-Ford or Johnson's algorithm, which modifies Dijkstra's algorithm to use Bellman-Ford. But I will admit that I'm not deep into these algorithms and can't make an informed decision yet, so any suggestions are welcome.

@jonathanrainer
Copy link
Author

Hi,

I'm happy to hear you like this library! You're right – Dijkstra's algorithm doesn't support negative edge weights, and this should indeed be documented to avoid confusion. For very generic functions such as ShortestPath, this library usually prefers the more general, less performant solution over a less general, more performant solution, so it really would make sense to support negative edge weights even if the algorithm would be slightly slower. There would still be place for faster solutions tailored to a specific use case.

So I'm open to replace the implementation of ShortestPath with an algorithm that can deal with negative edge weights, such as Bellman-Ford or Johnson's algorithm, which modifies Dijkstra's algorithm to use Bellman-Ford. But I will admit that I'm not deep into these algorithms and can't make an informed decision yet, so any suggestions are welcome.

My recollection is that Johnson's algorithm is more performant so if that's the choice I'd probably say go with that. However I also wonder if there's a case for including a version based on DFS and TopologicalSorting just for DAGs? As this is one of the fastest solutions I've found, and in fact was what I ended up using. But 100% yes a health warning would be great, even if it only saves one other person falling down a StackOverflow rabbit hole!

@dominikbraun
Copy link
Owner

However I also wonder if there's a case for including a version based on DFS and TopologicalSorting just for DAGs?

If that's the more performant choice for DAGs, then absolutely. This wouldn't even need to be in a dedicated function, a quick if g.Traits().IsDirected (followed by a in-algorithm cycle check, or a g.Traits().IsAcyclic) branch to run that algorithm would suffice.

@dominikbraun
Copy link
Owner

By the way, do you think it would be an option to directly return an error on negative weights and document that negative weights aren't supported, at least for the time being? This usually is the library's approach of handling invalid input.

@jonathanrainer
Copy link
Author

Both of those sound great to me :)

@jhsinger-klotho
Copy link

Hi,

We have also needed this functionality, so i put up a pr #155. When taking in a single source and destination like the ShortestPath signature does, BellmanFord should be more performant, so i decided to implement it going that route.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants