Dijkstra's Algorithm Java implementation with Priority Queue - java

Hi I am trying to find an minimum possible route in my weighted graph using Dijkstra'a algorithm. I am trying to implement the algorithm below from geeksforgeeks.com :
1) Initialize distances of all vertices as infinite.
2) Create an empty priority_queue pq. Every item
of pq is a pair (weight, vertex). Weight (or
distance) is used used as first item of pair
as first item is by default used to compare
two pairs
3) Insert source vertex into pq and make its
distance as 0.
4) While either pq doesn't become empty
a) Extract minimum distance vertex from pq.
Let the extracted vertex be u.
b) Loop through all adjacent of u and do
following for every vertex v.
// If there is a shorter path to v
// through u.
If dist[v] > dist[u] + weight(u, v)
(i) Update distance of v, i.e., do
dist[v] = dist[u] + weight(u, v)
(ii) Insert v into the pq (Even if v is
already there)
5) Print distance array dist[] to print all shortest
paths.
My main Data Structures are:
// HashMap of Intersections
private static HashMap<String, Intersection> intersections;
// Edge/Rail List
private static ArrayList<Rail> railList;
My function below called route and it first gets source and destination
vertexes from the commands as String and then i try to implement algorithm above. However i do not know how to store them in final Arraylist so that i can return the path.Additionally, it is problematic i think:
public void route(String wholeLine){
String[] temp = wholeLine.split(" |\\>");
int vel = Integer.parseInt(temp[3]);
double totalpath = 0;
int numOfSwitches = 0;
// My Source and Destination Nodes
Intersection src = intersections.get(temp[1]);
Intersection dest = intersections.get(temp[2]);
// Start the operation
PriorityQueue<Intersection> pq = new PriorityQueue<RailNetwork.Intersection>();
// Setting Distance to 0 for Source Node
src.setDistanceFromSource(0);
pq.add(src);
// While Priority Queue not empty
while(pq.size() != 0){
// Extract the vertex with minimum distance value node from Min Heap. Let the extracted vertex be u.
Intersection u = pq.remove();
// For every adjacent vertex v of u, check if v is in Min Heap.
for(Intersection v : u.getNeigbours()){
double weight = 0;
// Find edgeweight of u and v from rail/edge list
for(int i = 0;i<railList.size();i++){
if(railList.get(i).getSrc().getLabel().equals(u.label) && railList.get(i).getDest().getLabel().equals(v.label)){
weight = railList.get(i).getDistance();
}
else if(railList.get(i).getSrc().getLabel().equals(v.label) && railList.get(i).getDest().getLabel().equals(u.label)){
weight = railList.get(i).getDistance();
}
}
//If v is in Min Heap and distance value is more than weight of u-v plus distance value of u, then update the distance value of v.
if(u.getDistanceFromSource() > v.getDistanceFromSource() + weight){
//Update distance of v, i.e., do dist[v] = dist[u] + weight(u, v)
v.setDistanceFromSource(u.getDistanceFromSource() + weight);
System.out.println(v.label + "\t" + v.distanceFromSource);
pq.add(v);
}
}
}
}
**Could someone please help me to find my mistakes in order to implement it correctly?**Any help or hint is appreciated. Thanks in advance stackoverflow family.

Related

How can I determine the shortest distance from a certain type of vertex for all vertices?

I have a grid that represents a map. I have nodes that are ocean, and I have nodes that are land. I would like to assign a distance to every one of them using a recursive function. (So I guess one function call/island).
I have a code currently, which is this:
public int searchOcean(int x, int y, boolean[] visited) {
if (x < 0 || x >= width || y < 0 || y >= height) {
return 1000;
}
Node current = this.get(x, y);
int index = current.getIndex(this);
if (visited[index]) {
return current.oceanDist;
}
visited[index] = true;
if (current.ocean) {
current.oceanDist=0;
return 0;
}
int r1 = searchOcean(x + 1, y, visited);
int r2 = searchOcean(x - 1, y, visited);
int r3 = searchOcean(x, y + 1, visited);
int r4 = searchOcean(x, y - 1, visited);
int min = Math.min(Math.min(r1, r2), Math.min(r3 , r4))+1;
current.oceanDist = min;
return min;
}
The problem is, that it doesnt really work, I think mainly because I dont know how to handle the nodes that are already visited.
You want the Dijkstra algorithm https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
Loop A over nodes that are land
Apply Dijkstra
Loop B over nodes that are land
add distance ( given by Dijkstra ) from A to B to results.
or better ( remove un-needed calls to Dijkstra )
construct empty D to store distances between every pair of land nodes
loop A over every land node
loop B over every land node
if A-B NOT saved into D
apply Dijkstra with source A
loop C over land nodes
save distance A-C into D
break out of loop B
D is a map of distances keyed by the ordered node pair A,B. That is A->B and B->A give the same distance.

How to calculate the shortest path between two vertices in Graph with given parameters?

We need to compute the minCost(), which has follwing parameters:
gNodes - no of Nodes in graph g.
an array of int's, gFrom, where each gfrom[i] denotes a node connected by ith edge in graph g.
an array of int's, gTo, where each gTo[i] denotes a node connected by ith edge in graph g.
an array of int's, gWeight, denoting the respective weights of each edge in graph g.
an int, start, denoting the start node index.
an int, end, denoting the end node index.
an integer, wExtra, denoting the weight of optional extra edge.
We need to find the path from start to end having minimum possible weight. We can add at most one extra edge(ie. zero or one) having wExtra weight between any two distinct nodes that are not already connected by an edge. The function must return an int denoting the minimum path weight from start to end.
I was able to come up with following code (Dijkstra algorithm) but it doesn't give the expected output.
public static int minCost(int gNodes, int[] gFrom, int[] gTo, int[] gWeights, int start, int end) {
//making a array to store shortest length and filling it with infinity except the first one
int[] shortest = new int[gNodes];
for (int i = 0; i < gNodes; i++) {
shortest[i] = Integer.MAX_VALUE;
}
shortest[start]=0;
//filling the Queue with all vertices
Queue<Integer> theQ = new PriorityQueue<>();
for (int i = 0; i < gNodes; i++) {
theQ.add(i + 1);
}
//following the algorithm
while (!theQ.isEmpty()) {
int u = theQ.poll();
//making a list of adjacent vertices
List<Integer> adjacent = new ArrayList<>();
for (int i = 0; i < gFrom.length; i++) {
if (gFrom[i] == u) {
adjacent.add(gTo[i]);
} else if (gTo[i] == u) {
adjacent.add(gFrom[i]);
}
}
for (int v: adjacent) {
int weight=0;
for (int i = 0; i < gFrom.length; i++) {
if ((gFrom[i] == u && gTo[i] == v) || (gFrom[i] == v && gTo[i] == u)) {
weight = gWeights[i];
}
}
//relaxing the verices
if (shortest[v] > shortest[u] + weight) {
shortest[v] = shortest[u] + weight;
}
if (v == end) {
return shortest[v];
}
theQ.add(v);
}
}
return -1;
}
public static void main(String[] args) {
int gNodes = 4;
int[] gFrom = {1, 2, 2, 3};
int[] gTo = {2, 3, 4, 4};
int[] gWeights = {2, 1, 2, 3};
int start =1;
int end = 4;
System.out.println(shortestDistance(gNodes, gFrom, gTo, gWeights, start, end));
}
}
It's not giving the expected output which I think is because I can't think of how to use that wExtra. Also, the code is quite messy. Please let me know what's wrong or feel free to provide any robust code that does it well. Thanks.
A possible idea to integrate wExtra is the following:
Duplicate the graph, such that you have two nodes for every input node. The original graph represents the state before introducing the new edge. The copy represents the state after the introduction. For every node n in the original graph, you should then introduce directed edges with weight wExtra to all nodes m in the copy, where the original of m is not adjacent to n. This basically represents the fact that you can introduce a new edge between any two non-adjacent edges. But once you have done this, you cannot go back. Then, run usual Dijkstra on the modified graph between start and either the original end or the copy of end and you should get the correct result.
The best way to visualize this is probably to interpret the two sub graphs as layers. You start at the original layer and want to get to one of the two end nodes (whichever is closer). But you may switch layers only once.

BFS Find Shortest Path of 2d matrix using 2 queues

What I'm trying to do:
Using a graph found in a text file, find and print the shortest path (minimum amount of vertices) from vertex A to vertex B.
Current implementation:
public String findPath(int v, int w) {
Queue<Integer> q = new LinkedList<Integer>();
boolean[] visited = new boolean[g.numVertices()];
String[] pathTo = new String[g.numVertices()];
q.add(v);
pathTo[v] = v+" ";
while(q.peek() != null) {
if(runBFS(q.poll(),w,visited,q,pathTo))
break;
}
return pathTo[w];
}
private boolean runBFS(int v, int w, boolean[] visited, Queue<Integer> q, String[] pathTo) {
if(visited[v]) {
}
else if(v == w)
return true;
}
else {
visited[v] = true;
VertexIterator vi = g.adjacentVertices(v);
while(vi.hasNext()) {
int nextVertex = vi.next();
pathTo[nextVertex] = pathTo[v] + nextVertex + " ";
q.add(nextVertex);
}
}
return false;
}
v = vertex of origin
w = target vertex
g = graph
vi = a normal iterator that iterates over the neighbours of v
Right now , it is using String[] to trace the paths but I was suggested that there is a solution to do this with Queue<ArrayList<Integer>> rather than String[] when saving paths by running this queue in parallel with the q queue.
Could someone guide me through this ?
You can use a second queue Queue<ArrayList<Integer>> q2 to store the shortest path (as an ArrayList<Integer>) from v to each node currently in q in the same order. Whenever you poll q, you also poll q2, and whenever you add a node to q, you calculate the shortest path to that node by copying the shortest path to the previous node and appending the current node, and add it to q2.
Note, however, that copying the shortest path may take time linear in the number of vertices, which will increase the overall complexity. For this reason I wouldn't recommend this approach. Instead, for each node n you can store the previous node you came from when you visited n. As soon as you reach the target node w, you can then backtrack through these previous nodes to find the shortest path from the start node.

How to test if a weighted graph has a negative cycle

I need to create a test that returns true if the graph (directed graph) as a parameter has a cycle of negative weight, false otherwise.
For now I created this. Theoretically should check if there are "generic" cycles, not if there are negative cycles. How can I change the method?
There's an easier or efficient?
//if there is a negative cycle, get out and return
public void bellmanFord(Graph<V, E> graph, V source, V dest) {
ArrayList<V> vertices = (ArrayList<V>) graph.getVertices();
HashMap<V, Boolean> visited = new HashMap<V, Boolean>(vertices.size());
for(V v : vertices) {
visited.put(v, false);
}
boolean cycle = hasNegativeCycle(graph, source, visited, vertices);
if(cycle == true)
return;
else {
...
}
}
public boolean hasNegativeCycle(Graph<V, E> graph, V source, HashMap<V, Boolean> visited, ArrayList<V> vertices) {
visited.put(source, true);
for(V u : vertices) {
ArrayList<V> neigh_u = (ArrayList<V>) graph.getNeighbors(u);
for(V v : neigh_u) {
if(visited.get(v) == true || hasNegativeCycle(graph, v, visited, vertices)) {
return true;
}
}
}
return false;
}
Thanks
EDIT: As you can see from the method name written on it, I'm trying to implement the algorithm of Bellman-Ford and I'm following this pseudocode:
BellmanFord(Graph G, Vertex start) {
foreach(Vertex u of G) {
dist[u] = ∞;
prev[u] = -1;
}
prev[start] = s;
dist[start] = 0;
repeat n times {
foreach(Vertex u of G) {
foreach(Vertex v near u) {
if(dist[u] + weigth_uv < dist[v]) {
prev[v] = u;
dist[v] = dist[u] + weigth_uv;
}
}
}
}
}
You have to apply Bellman-Ford Algorithm.Wikipedia has proper pseudocode. If you apply this properly your problem will be solved.
function BellmanFord(list vertices, list edges, vertex source)
::distance[],predecessor[]
// This implementation takes in a graph, represented as
// lists of vertices and edges, and fills two arrays
// (distance and predecessor) with shortest-path
// (less cost/distance/metric) information
// Step 1: initialize graph
for each vertex v in vertices:
if v is source then distance[v] := 0
else distance[v] := inf
predecessor[v] := null
// Step 2: relax edges repeatedly
for i from 1 to size(vertices)-1:
for each edge (u, v) in Graph with weight w in edges:
if distance[u] + w < distance[v]:
distance[v] := distance[u] + w
predecessor[v] := u
// Step 3: check for negative-weight cycles
for each edge (u, v) in Graph with weight w in edges:
if distance[u] + w < distance[v]:
error "Graph contains a negative-weight cycle"
return distance[], predecessor[]
You may want to do a BFS traversal of the graph. At each node visit, record the node's unique id (.hashCode() for example, if implemented) into a HashSet. Whenever you are trying to insert an already present element into the hashset, you found a circle.
If you found a circle in say node F, you can count the circle's sum weight by traversing the tree upwards, until you find F again, and summing the weights.
Of course after determining the circle size, and it was positive, you must continue the BFS traversal, but without traversing F's children. If it was negative, return from the function, as you found a negative circle.
Edit: you can also keep track of the current sum weight during the BFS traversal steps, this way you don't have to traverse the tree upwards to calculate the total weight...As your graph is Directed, this method would fit also better...

Get neighbouring vertices only using depth first search

How to get neighbouring vertices only using depth first search?
I am using depth first search algorithm to search a Directed Graph, my problem is that I want to make it only return the neighbors of my start vertex, instead it keeps carrying on until it reaches a dead end.
So lets say I have vertices (A, B, C, D)
And edges ((A -> B), (A -> C), (C -> D))
And I want all neighbors of Vertex A, instead of getting B and C it is also including D even though D is not Adjacent to A?
public void dfs(int x) // depth-first search
{ // begin at vertex 0
vertexList[x].wasVisited = true; // mark it
displayVertex(x); // display it
theStack.push(x); // push it
while( !theStack.isEmpty() ) // until stack empty,
{
// get an unvisited vertex adjacent to stack top
int v = getAdjUnvisitedVertex( theStack.peek() );
if(v == -1) // if no such vertex,
theStack.pop();
else // if it exists,
{
vertexList[v].wasVisited = true; // mark it
displayVertex(v); // display it
theStack.push(v); // push it
}
} // end while
// stack is empty, so we're done
for(int j=0; j<nVerts; j++) // reset flags
vertexList[j].wasVisited = false;
} // end dfs
// ------------------------------------------------------------
// returns an unvisited vertex adj to v
public int getAdjUnvisitedVertex(int v)
{
for(int j=0; j<nVerts; j++)
if(adjMat[v][j]==1 && vertexList[j].wasVisited==false)
return j;
System.out.println("Found unvisited vertex");
return -1;
} // end getAdjUnvisitedVertex()
I understand I could just store the neighbors of a Vertex when creating it but then that means I will have to make a lot of changes if I had to make changes in the future, if anyone has any ideas on how to guide me in the right direction I would be very grateful!!
If you represent your graph as the adjecency matrix then you should just can just take all entries that are non zero from the row corresponding to vertex A.
for(int j=0; j<nVerts; j++)
if(adjMat[v][j]==1) System.out.println("vertex " + j);
so you do not need dfs for that.

Categories

Resources