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.
Related
How do we perform depth first search on a directed graph using an adjacency matrix in which it explores all of the vertices starting from a random vertex? I attempted to implement dfs, but its only exploring the vertices that are reachable from the starting vertex.
public static void dfs(int [] [] adjMatrix, int startingV,int n)
{
boolean [] visited = new boolean[n];
Stack<Integer> s = new Stack<Integer>();
s.push(startingV);
while(!s.isEmpty())
{
int vertex = s.pop();
if(visited[vertex]==false)
{
System.out.print("\n"+(v));
visited[vertex]=true;
}
for ( int i = 0; i < n; i++)
{
if((adjMatrix[vertex][i] == true) && (visited[i] == false))
{
s.push(vertex);
visited[I]=true;
System.out.print(" " + i);
vertex = i;
}
}
}
}
}
In a directed graph there might be no node from which you can reach all other nodes. So what do you expect in this case?
If there is at least one node from which you can reach all other nodes you only do now know which one it is, you can select a random one, go against the direction of an incoming edge to find a root node from which you can reach all other nodes.
Your code has a couple of issues, one of which is that you do a int vertex = s.pop(); and later an s.push(vertex); with the same vertex. The latter should probably be s.push(i); instead.
The easiest way to implement DF traversal is to just use recursion. Then the code decays to
function dfs(v) {
if v not visited before {
mark v as visited;
for every adjacent vertex a of v do {
dfs(a);
}
do something with v; // this is *after* all descendants have been visited.
}
}
Of course, every recursive implementation can be equivalently implemented using a stack and iteration instead, but in your case that'd be somewhat more complicated because you'd not only have to store the current vertex on the stack but also the state of iteration over its descendants (loop variable i in your case).
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.
I have an undirected graph with positive edge weights. I am given a start point and the maximum amount of distance I can travel, and in the end, I must return to the start point. What sort of algorithm can do this for me, and give me the path that results?
I understand java well, so if you can, please make code samples look similar to java.
Like I said a DFS should do the trick, this sample code gives the idea. But beware, this sample code don't handle cyclic reference, you will have to do that
public class Answer {
private static final int MAX_WEIGHT = 11;
public static void main(String[] args) {
Node node1 = new Node("node 1");
Node node1_1 = new Node("node 1-1");
Node node1_1_1 = new Node("node 1-1-1");
Node node1_2 = new Node("node 1-2");
Node node1_2_1 = new Node("node 1-2-1");
Node node1_2_1_1 = new Node("node 1-2-1-1");
node1.addNeighbour(node1_1, 1);
node1_1.addNeighbour(node1_1_1, 2);
node1.addNeighbour(node1_2, 1);
node1_2.addNeighbour(node1_2_1, 2);
node1_2_1.addNeighbour(node1_2_1_1, 3);
System.out.println("max of nodes = " + travel(node1, 0));
}
private static int travel(Node node, int totalWeight) {
int maxNodes = 1;
for (Map.Entry<Node, Integer> entry : node.neighbours.entrySet()) {
Integer weight = entry.getValue();
int nodes = 1;
if ((totalWeight + weight) * 2 <= MAX_WEIGHT) {
nodes += travel(entry.getKey(), totalWeight + weight);
}
if (nodes > maxNodes) {
maxNodes = nodes;
}
}
return maxNodes;
}
}
class Node {
String id;
Map<Node, Integer> neighbours;
public Node(String id) {
this.id = id;
neighbours = new HashMap<Node, Integer>();
}
public void addNeighbour(Node node, int weight) {
neighbours.put(node, weight);
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("Node{");
sb.append("id='").append(id).append('\'');
sb.append(", neighbours=").append(neighbours);
sb.append('}');
return sb.toString();
}
}
I now realise this is still NP-hard, even if vertices can be visited more than once: Hamiltonian Path is NP-hard even on unweighted graphs, so we are free to create an instance of your problem using arbitrarily chosen weights. Specifically, given an instance (G = (V, E), k) of Hamiltonian Path, we can create an instance (G' = (V', E'), w, s, d) of your problem in which:
V' = V, plus a new vertex, s
E' = E, plus the edge (s, u) for every vertex u in V
The weight w(e) of every edge e in E' is 1
The starting point is s
The maximum total travel distance is |V|+1.
If the solution to this instance is |V|+1 distinct vertices, then clearly it contains every vertex in G' exactly once, so removing the vertex s from the cycle will leave a path through all the remaining vertices, i.e., a Hamiltonian path in the original graph G. If the solution to this instance is less than |V|+1, then no Hamiltonian path exists in G -- since if one did, we would indeed have gotten a solution of |V|+1.
So, if your problem could be solved in polynomial time, then so could an NP-complete problem. That means that it's very unlikely that your problem can be solved in polynomial time.
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...
I need an algorithm to find shortest path between two points in a map
where road distance is indicated by a number.
what is given:
Start City A
Destination City Z
List of Distances between Cities:
A - B : 10
F - K : 23
R - M : 8
K - O : 40
Z - P : 18
J - K : 25
D - B : 11
M - A : 8
P - R : 15
I thought I could use Dijkstra's algorithm , however it finds shortest distance to all destinations. not just one.
Any suggestion is appreciated.
Like SplinterReality said: There's no reason not to use Dijkstra's algorithm here.
The code below I nicked from here and modified it to solve the example in the question.
import java.util.PriorityQueue;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
class Vertex implements Comparable<Vertex>
{
public final String name;
public Edge[] adjacencies;
public double minDistance = Double.POSITIVE_INFINITY;
public Vertex previous;
public Vertex(String argName) { name = argName; }
public String toString() { return name; }
public int compareTo(Vertex other)
{
return Double.compare(minDistance, other.minDistance);
}
}
class Edge
{
public final Vertex target;
public final double weight;
public Edge(Vertex argTarget, double argWeight)
{ target = argTarget; weight = argWeight; }
}
public class Dijkstra
{
public static void computePaths(Vertex source)
{
source.minDistance = 0.;
PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
Vertex u = vertexQueue.poll();
// Visit each edge exiting u
for (Edge e : u.adjacencies)
{
Vertex v = e.target;
double weight = e.weight;
double distanceThroughU = u.minDistance + weight;
if (distanceThroughU < v.minDistance) {
vertexQueue.remove(v);
v.minDistance = distanceThroughU ;
v.previous = u;
vertexQueue.add(v);
}
}
}
}
public static List<Vertex> getShortestPathTo(Vertex target)
{
List<Vertex> path = new ArrayList<Vertex>();
for (Vertex vertex = target; vertex != null; vertex = vertex.previous)
path.add(vertex);
Collections.reverse(path);
return path;
}
public static void main(String[] args)
{
// mark all the vertices
Vertex A = new Vertex("A");
Vertex B = new Vertex("B");
Vertex D = new Vertex("D");
Vertex F = new Vertex("F");
Vertex K = new Vertex("K");
Vertex J = new Vertex("J");
Vertex M = new Vertex("M");
Vertex O = new Vertex("O");
Vertex P = new Vertex("P");
Vertex R = new Vertex("R");
Vertex Z = new Vertex("Z");
// set the edges and weight
A.adjacencies = new Edge[]{ new Edge(M, 8) };
B.adjacencies = new Edge[]{ new Edge(D, 11) };
D.adjacencies = new Edge[]{ new Edge(B, 11) };
F.adjacencies = new Edge[]{ new Edge(K, 23) };
K.adjacencies = new Edge[]{ new Edge(O, 40) };
J.adjacencies = new Edge[]{ new Edge(K, 25) };
M.adjacencies = new Edge[]{ new Edge(R, 8) };
O.adjacencies = new Edge[]{ new Edge(K, 40) };
P.adjacencies = new Edge[]{ new Edge(Z, 18) };
R.adjacencies = new Edge[]{ new Edge(P, 15) };
Z.adjacencies = new Edge[]{ new Edge(P, 18) };
computePaths(A); // run Dijkstra
System.out.println("Distance to " + Z + ": " + Z.minDistance);
List<Vertex> path = getShortestPathTo(Z);
System.out.println("Path: " + path);
}
}
The code above produces:
Distance to Z: 49.0
Path: [A, M, R, P, Z]
Estimated sanjan:
The idea behind Dijkstra's Algorithm is to explore all the nodes of the graph in an ordered way. The algorithm stores a priority queue where the nodes are ordered according to the cost from the start, and in each iteration of the algorithm the following operations are performed:
Extract from the queue the node with the lowest cost from the start, N
Obtain its neighbors (N') and their associated cost, which is cost(N) + cost(N, N')
Insert in queue the neighbor nodes N', with the priority given by their cost
It's true that the algorithm calculates the cost of the path between the start (A in your case) and all the rest of the nodes, but you can stop the exploration of the algorithm when it reaches the goal (Z in your example). At this point you know the cost between A and Z, and the path connecting them.
I recommend you to use a library which implements this algorithm instead of coding your own. In Java, you might take a look to the Hipster library, which has a very friendly way to generate the graph and start using the search algorithms.
Here you have an example of how to define the graph and start using Dijstra with Hipster.
// Create a simple weighted directed graph with Hipster where
// vertices are Strings and edge values are just doubles
HipsterDirectedGraph<String,Double> graph = GraphBuilder.create()
.connect("A").to("B").withEdge(4d)
.connect("A").to("C").withEdge(2d)
.connect("B").to("C").withEdge(5d)
.connect("B").to("D").withEdge(10d)
.connect("C").to("E").withEdge(3d)
.connect("D").to("F").withEdge(11d)
.connect("E").to("D").withEdge(4d)
.buildDirectedGraph();
// Create the search problem. For graph problems, just use
// the GraphSearchProblem util class to generate the problem with ease.
SearchProblem p = GraphSearchProblem
.startingFrom("A")
.in(graph)
.takeCostsFromEdges()
.build();
// Search the shortest path from "A" to "F"
System.out.println(Hipster.createDijkstra(p).search("F"));
You only have to substitute the definition of the graph for your own, and then instantiate the algorithm as in the example.
I hope this helps!
Maintain a list of nodes you can travel to, sorted by the distance from your start node. In the beginning only your start node will be in the list.
While you haven't reached your destination: Visit the node closest to the start node, this will be the first node in your sorted list. When you visit a node, add all its neighboring nodes to your list except the ones you have already visited. Repeat!
This maybe too late but No one provided a clear explanation of how the algorithm works
The idea of Dijkstra is simple, let me show this with the following pseudocode.
Dijkstra partitions all nodes into two distinct sets. Unsettled and settled. Initially all nodes are in the unsettled set, e.g. they must be still evaluated.
At first only the source node is put in the set of settledNodes. A specific node will be moved to the settled set if the shortest path from the source to a particular node has been found.
The algorithm runs until the unsettledNodes set is empty. In each iteration it selects the node with the lowest distance to the source node out of the unsettledNodes set. E.g. It reads all edges which are outgoing from the source and evaluates each destination node from these edges which are not yet settled.
If the known distance from the source to this node can be reduced when the selected edge is used, the distance is updated and the node is added to the nodes which need evaluation.
Please note that Dijkstra also determines the pre-successor of each node on its way to the source. I left that out of the pseudo code to simplify it.
Credits to Lars Vogel
You can see a complete example using java 8, recursion and streams -> Dijkstra algorithm with java