I implemented a C# Dijkstra with Fibonacci Heap using based on SO question and this version in Java, which is very clean, concise and well documented.
I modified the DirectedGraph to make it an undirected graph.
However, I have 2 questions regarding the search algorithm itself:
The current method has 2 parameters (graph & source). If I add a third parameter (target), what are the changes necessary in the search algorithm itself so that it only searches from source to target instead of all-pairs shortest paths?
The function returns a list of distances. What do I need to change to make it return the shortest path?
Related
I do have a question related to checking if the shortest path is strictly monotonic using Dijkstra.
Edges connected to each node are sorted and stored inside a LinkedList<Edge> edges;
The shortestPathMap is a utility to store the entire path from starting node to the end node.
Thanks!
Finding a strictly monotonic shortest path can be done by relaxing edges in order based on their weight.
Say we want to find the shortest ascending path. We would order the edges in ascending order, then relax them in that order. "Relax" just means update the weight of the node at the endpoint of an edge to be the weight of the edge plus the weight of its start point node if that sum is less than the current value. This is the same as relaxing an edge in Dijkstra's. This will always yield the shortest ascending path (and it can be made strictly ascending if we update the node weights at the same time for all equally valued edges).
We can also find the shortest descending path by ordering edges in descending order. One of those two paths will be the shortest monotonic path.
I think you will have more luck using this approach of looping over the sorted edges (in n logn time) than trying to loop over the nodes as in the above method -- if you need to solve the problem by only updating the method you have shown us, it becomes a much harder problem.
I know this is exponential. I already implemented a method to find the shortest path using Dijkstra's algorithm. Is it possible to modify the method to find the longest path instead? If I make all the weights negative, shouldn't this work. All the weights on my current graph are positive. Also there should be no repeating paths.
I know the Bellman Ford algorithm works with negative weights, but im hoping I can just modify my existing shortest path method.
If the graph is undirected, then the longest path has infinite length, because you can visit an edge forward and backward as many times as you want. Therefore you should put some more conditions, like : a node can only be visited once, or the graph must be directed.
Making all weights negative and running Dijkstra will make infinite loop. It is in fact equivalent to what I just explained above.
For more information, I invite you to read about these :
http://en.wikipedia.org/wiki/Topological_sorting
http://en.wikipedia.org/wiki/Travelling_salesman_problem
Good luck !
The A star algorithm is known to be complete. However, all the implementations that I have found searching the web seem to only return only the first (optimal) solution.
For example, this implementation:
A star algoritthm implementation
Since the algorithm always expands the node with the minimum f value, and the implementations seem to stop when the first node is a solution, how would one adapt the aforementioned code so as to output all (or the first n) paths that lead to a goal, without taking into account duplicate actions (that is, paths that contain the same action over and over again)?
For all paths, it probably makes a lot more sense to use breath first search. Alternatively, you can try Dijkstra's algorithm if you want to find the top n shortest paths.
It's complete which means it will find a solution if one exists, but the algorithm specifically only returns one path. A breadth-first search will find all non-cyclical paths between two nodes, however: http://en.wikipedia.org/wiki/Breadth-first_search
Update - Here is the k-shortest paths algorithm which will return a list of n (or in this case, k) shortest paths in order of shortest to longest. http://code.google.com/p/k-shortest-paths/
I need to find a shortest path through an undirected graph whose nodes are real (positive and negative) weighted. These weights are like resources which you can gain or loose by entering the node.
The total cost (resource sum) of the path isn't very important, but it must be more than 0, and length has to be the shortest possible.
For example consider a graph like so:
A-start node; D-end node
A(+10)--B( 0 )--C(-5 )
\ | /
\ | /
D(-5 )--E(-5 )--F(+10)
The shortest path would be A-E-F-E-D
Dijkstra's algorithm alone doesn't do the trick, because it can't handle negative values. So, I thought about a few solutions:
First one uses Dijkstra's algorithm to calculate the length of a shortest path from each node to the exit node, not considering the weights. This can be used like some sort of heuristics value like in A*. I'm not sure if this solution could work, and also it's very costly. I also thought about implement Floyd–Warshall's algorithm, but I'm not sure how.
Another solution was to calculate the shortest path with Dijkstra's algorithm not considering the weights, and if after calculating the path's resource sum it's less than zero, go through each node to find a neighbouring node which could quickly increase the resource sum, and add it to the path(several times if needed). This solution won't work if there is a node that could be enough to increase the resource sum, but farther away from the calculated shortest path.
For example:
A- start node; E- end node
A(+10)--B(-5 )--C(+40)
\
D(-5 )--E(-5 )
Could You help me solve this problem?
EDIT: If when calculating the shortest path, you reach a point where the sum of the resources is equal to zero, that path is not valid, since you can't go on if there's no more petrol.
Edit: I didn't read the question well enough; the problem is more advanced than a regular single-source shortest path problem. I'm leaving this post up for now just to give you another algorithm that you might find useful.
The Bellman-Ford algorithm solves the single-source shortest-path problem, even in the presence of edges with negative weight. However, it does not handle negative cycles (a circular path in the graph whose weight sum is negative). If your graph contains negative cycles, you are probably in trouble, because I believe that that makes the problem NP-complete (because it corresponds to the longest simple path problem).
This doesn't seem like an elegant solution, but given the ability to create cyclic paths I don't see a way around it. But I would just solve it iteratively. Using the second example - Start with a point at A, give it A's value. Move one 'turn' - now I have two points, one at B with a value of 5, and one at D also with a value of 5. Move again - now I have 4 points to track. C: 45, A: 15, A: 15, and E: 0. It might be that the one at E can oscillate and become valid so we can't toss it out yet. Move and accumulate, etc. The first time you reach the end node with a positive value you are done (though there may be additional equivalent paths that come in on the same turn)
Obviously problematic in that the number of points to track will rise pretty quickly, and I assume your actual graph is much more complex than the example.
I would do it similarly to what Mikeb suggested: do a breadth-first search over the graph of possible states, i.e. (position, fuel-left)-pairs.
Using your example graph:
Octagons: Ran out of fuel
Boxes: Child nodes omitted for space reasons
Searching this graph breadth-first is guaranteed to give you the shortest route that actually reaches the goal if such a route exists. If it does not, you will have to give up after a while (after x nodes searched, or maybe when you reach a node with a score greater than the absolute value of all negative scores combined), as the graph can contain infinite loops.
You have to make sure not to abort immediately on finding the goal if you want to find the cheapest path (fuel wise) too, because you might find more than one path of the same length, but with different costs.
Try adding the absolute value of the minimun weight (in this case 5) to all weights. That will avoid negative ciclic paths
Current shortest path algorithms requires calculate shortest path to every node because it goes combinating solutions on some nodes that will help adjusting shortest path in other nodes. No way to make it only for one node.
Good luck
I've a list of proteins in a text file like the format below:
ATF-1 MET4
ATF-1 NFE2L1
ATF-2 ATF-7
ATF-2 B-ATF
ARR1 ARR1
ARR1 CHOP
I want to read from the text file and implement them in undirected graph using adjacency lists either in Java or in Perl. I want to calculate the minimum and maximum number of edges, the shortest and longest path between nodes, and other similar functions.
In perl, you can represent the graph using hash like this:
use warnings;
use strict;
my %graph;
sub add_edge {
my ($n1, $n2) = #_;
$graph{$n1}{$n2} = 1;
$graph{$n2}{$n1} = 1;
}
sub show_edges {
foreach my $n1 (keys %graph) {
foreach my $n2 (keys %{$graph{$n1}}) {
print "$n1 <-> $n2\n";
}
}
}
while (<>) {
my ($n1, $n2) = split /\s+/;
add_edge($n1, $n2);
}
show_edges();
Run it like this:
perl script.pl input.txt
For the shortest path you'll have to decide the start and end node that you want to search the shortest path for.
For this you can use Dijkstra's algorithm. In a nutshell this is how the algorithm works:
Let's call the start node A and the end node B.
Assume that we already know the shortest path for going from A to B. If we are at B, then backtracking our steps using the cheapest path should bring us back to point A. Dijkstra's algorithm starts at A and records the cost of path for going to all of A's adjacent nodes, and repeats the process for each of the adjacent nodes. Once done, then we can print the shortest path from A to B by backtracking from B to A.
To get the number of nodes: print keys %graph;
To get the number of edges you'll have to count (uniquely) the number of entries in each of the hash elements, for example to count the number of edges for one node: print keys %{$graph{'ATF-1'}};
Take a look at Open source libraries to design directed graphs. Their suggestion was to use JGraphT. The javadoc shows that they have implemented a wide range of graph operations, including shortest path.