I am investigating the A* search algorithm, and came across this example:
The description of the algorithm is as follows:
Visiting node 0 with currently lowest priority of 8.0
Updating distance of node 1 to 3 and priority to 9.32455532033676
Updating distance of node 2 to 4 and priority to 10.32455532033676
Visiting node 1 with currently lowest priority of 9.32455532033676
Updating distance of node 3 to 9 and priority to 11.82842712474619
Updating distance of node 4 to 13 and priority to 15.82842712474619
Visiting node 2 with currently lowest priority of 10.32455532033676
Visiting node 3 with currently lowest priority of 11.82842712474619
Updating distance of node 5 to 12 and priority to 12.0
Goal node found!
I am wondering how the priority numbers have been derived. Here's the website, where this information was taken from:
https://www.algorithms-and-technologies.com/a_star/r
Euclidean distance is used as heuristic. The actual costs are the labels.
For example at node 1, the G cost is 3 (the edge from node 0) and the H cost is sqrt(2² + 6²), making the F cost 9.32455532033676.
Related
Apart from the graph having non-negative weights, does Dijkstra algorithm require connectedness? E.g. Would dijkstra algorithm work for a graph that is disconnected, where 3 vertices are connected in a component and 2 other vertices are in another component?
Here is Dijkstra's algorithm from Wikipedia:
Mark all nodes unvisited. Create a set of all the unvisited nodes called the unvisited set.
Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. During the run of the algorithm, the tentative distance of a node v is the length of the shortest path discovered so far between the node v and the starting node. Since initially no path is known to any other vertex than the source itself (which is a path of length zero), all other tentative distances are initially set to infinity. Set the initial node as current.[15]
For the current node, consider all of its unvisited neighbors and calculate their tentative distances through the current node. Compare the newly calculated tentative distance to the one currently assigned to the neighbor and assign it the smaller one. For example, if the current node A is marked with a distance of 6, and the edge connecting it with a neighbor B has length 2, then the distance to B through A will be 6 + 2 = 8. If B was previously marked with a distance greater than 8 then change it to 8. Otherwise, the current value will be kept.
When we are done considering all of the unvisited neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again (this is valid and optimal in connection with the behavior in step 6.: that the next nodes to visit will always be in the order of 'smallest distance from initial node first' so any visits after would have a greater distance).
If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is infinity (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished.
Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new current node, and go back to step 3.
Note the part I emphasized. Laid out this way, if there is no path between the initial node and the destination node, the algorithm still stops once all nodes in the component of the initial node are visited.
So no, the graph being connected is not a requirement. The algorithm will tell you whether the path exists.
According to the Djikstra's algorithm given in psuedocode on Wikipedia (copied below for convenience), the disconnected vertices distance from the source would remain as INFINITY. The answer to your question is no, Dijkstra's algorithm still returns a correct result even if the graph is disconnected.
1 function Dijkstra(Graph, source):
2
3 for each vertex v in Graph.Vertices:
4 dist[v] ← INFINITY
5 prev[v] ← UNDEFINED
6 add v to Q
7 dist[source] ← 0
8
9 while Q is not empty:
10 u ← vertex in Q with min dist[u]
11 remove u from Q
12
13 for each neighbor v of u still in Q:
14 alt ← dist[u] + Graph.Edges(u, v)
15 if alt < dist[v]:
16 dist[v] ← alt
17 prev[v] ← u
18
19 return dist[], prev[]
Typically, in Dijkstra's algorithm, for each encountered node, we check whether that node was processed before attempting to update the distances of its neighbors and adding them to the queue. This method is under the assumption that if a distance to a node is set once then the distance to that node cannot improve for the rest of the algorithm, and so if the node was processed once already, then the distances to its neighbors cannot improve. However, this is not true for graphs with negative edges.
If there are no negatives cycles then if we remove that "processed" check, then will the algorithm always work for graphs with negative edges?
Edit: an example of a graph where the algorithm would fail would be nice
Edit 2: Java code https://pastebin.com/LSnfzBW4
Example usage:
3 3 1 <-- 3 nodes, 3 edges, starting point at node 1
1 2 5 <-- edge of node 1 and node 2 with a weight of 5 (unidirectional)
2 3 -20 <-- more edges
1 3 2
The algorithm will produce the correct answer, but since nodes can now be visited multiple times the time complexity will be exponential.
Here's an example demonstrating the exponential complexity:
w(1, 3) = 4
w(1, 2) = 100
w(2, 3) = -100
w(3, 5) = 2
w(3, 4) = 50
w(4, 5) = -50
w(5, 7) = 1
w(5, 6) = 25
w(6, 7) = -25
If the algorithm is trying to find the shortest path from node 1 to node 7, it will first reach node 3 via the edge with weight 4 and then explore the rest of the graph. Then, it will find a shorter path to node 3 by going to node 2 first, and then it will explore the rest of the graph again.
Every time the algorithm reaches one of the odd indexed nodes, it will first go to the next odd indexed node via the direct edge and explore the rest of the graph. Then it will find a shorter path to the next odd indexed node via the even indexed node and explore the rest of the graph again. This means that every time one of the odd indexed nodes is reached, the rest of the graph will be explored twice, leading to a complexity of at least O(2^(|V|/2)).
If I understand your question correctly, I don't think its possible. Without the processed check the algorithm would fall into infinite loop. For example, for a bidirected graph having two nodes i.e. a and b with one edge from "a" to "b" or "b" to "a", it will first insert node "a" inside the priority queue, then as there have an edge between "a" to "b", it will insert node "b" and pop node "a". And then as node "a" is not marked processed for node "b" it will again insert node "a" inside the priority queue and so on. Which leads to an infinite loop.
For finding shortest path in the graphs with negative edges Bellmen-ford algorithm would be the right way.
If negative edges release from start node, dijkstra's algorithm works. But in the other situation Usually it dosen't works for negative edges.
Given a weighted undirected graph, I need to find the shortest path between two nodes, a classical shortest path problem actually. But there is one more constraint : Each node contains a "reduction" value that can be used to reduce the cost of the following edges for one traversal(not only adjacent, and reduction are not cumulative). So you can reduce the cost of an edge using the "Reduction" that was in one of the node you went throught before (the final cost for each edge can't be less than 0).
Note that once we went throught a node with a reduction, we can use it again for all the following edges (not just adjacent, and it is available an unlimited amount of time). Reduction doesn't accumulate.
Let's consider this graph :
in this graph the shortest path from node 1 to 5 is :
1 -> 4 for a cost of 13 (15-2)
4 -> 3 for a cost of 0 (12-12)
3 -> 5 for a cost of 0 (10-12) In this case, we reuse the reduction of node 4 because it is bigger than the reduction of node 3 (We went throught the node n°4 then we have an unlimited amount of reduction of cost 12). It is 0 and not -2 because the weight of an edge can't be negative.
Then the total cost from node 1 to node 5 is 13 + 0 + 0 = 13
To solve this problem, I've tried to use the classical Dijkstra/Bellman-Ford but it didn't work, can you help me with this ?
It seems to be this can be solved with a variation of Bellman-Ford.
Every path up to a given node can be summarised as a pair (C, D) where C is the cost of that path (after discounts) and D is the best discount factor available on that path. Since a discount can be reused an unlimited number of times once that node has been visited, it makes sense to always use the biggest discount seen so far on that path. For example, the path (1 -> 4 -> 3) has cost C = 13 and discount D = 12.
The complication over the undiscounted problem is that we cannot tell from the cost what the "best" path is to nodes in between the source and destination. In your example the path (1 -> 2 -> 3) has lower cost than (1 -> 4 -> 3), but the latter has a better discount which is why the best path from 1 to 5 is (1 -> 4 -> 3 -> 5).
Rather than recording the lowest cost path to each node (in Bellman-Ford algorithm), we need to record all "feasible" paths from the source to that node found so far. A path can be said to be feasible if there is no other known path that has both a lower cost and a better discount. After the algorithm terminates we can take from all feasible paths from source to destination the one with the smallest cost, ignoring the discount.
(Edit: I originally suggested Djikstra could be used but I think that not be so straightforward. I'm not sure we can choose "the closest" unvisited node in any meaningful way such that we are guaranteed to find the minimal path. Someone else might see how to make it work though...)
I think you can use a Dijkstra-type algorithm. Dijkstra's algorithm can be thought of computing the minimum spanning tree that contains the shortest paths from a source vertex to all other vertices. Let's call this the "Dijkstra tree" that contains all the shortest paths from a given source vertex.
Dijkstra keeps adding new vertices to the current tree. For the next vertex he chooses the one that is closest to the current tree. See this animation from wikipedia:
So when Dijkstra adds a new vertex v to an already inserted vertex u (of the current tree), the edge weight of {u, v} has to be considered. In your case, the costs are not just the edge weight of {u, v}, but the weight reduced by the sum of vertex-reductions along the shortest path to u in the current tree. So you have to remember the sum of the vertex reductions along the paths of this "Dijkstra" tree in the vertices.
Rooted Graph is given. Here, nodes is "home" that contains some valuable item. Entry node is given, i.e., root of the graph.
Cost is also given to move from one node to other, i.e., Egde weight.
Question -
You have to collect maximum valuable item, and total cost should not exceed with given cost.
Contraint -
1. There is no cycle.
2. We can use adjancency matrix also.(Total number of vertices is upto 1000).
Example
Edges given with their weight and values present in destination node.
0 1 10 1
0 2 10 15
1 3 50 10
1 4 30 30
Given Cost = 70.
Solution - You will collect node 1, 2, 4's items in a maximum way. [1+15+30 = 46]
My efforts
I think, this problem will solve by DP, by maintaining some state at every node. But I am not able to make some algorithm. Please help.
Edit 1
I think this question may be solved by making special graph by using original graph by ading some state into each node.
Second approach is, Dynamic programming.
I don't think you're going to find an easy solution for this problem.
Consider a graph made by just a root node connected to N leaves. Each leaf has a value of 1 and the edges have cost c1, c2, ... cN.
As you can see this graph problem has the knapsack problem as a special case.
Suppose you have a set of jobs which can possibly be done in parallel. Each job has a time requirement ( time requirement for the i th job is t_i ). There are also some dependencies, the i th of them saying that you have to do job u_i before job v_i. You have to minimize the total time required.
This is easily done by converting these relations into a directed acyclic graph and then using it to determine which ones to do in parallel.
In case I'm not clear, here is an example. Suppose you have 5 jobs with time requirements 2, 9, 3, 12, 5, and you have to do 3 before 5, 4 before 5, 3 before 1 and 1 before 2. Then the best you can do is 17. This is your dag:
+---> 1 (2) ---> 2(9)
|
3 (3)
|
+----> 5 (5)
^
|
4 (12)-+
You can do 3 and 4 in parallel, so that you spend MAX(3,12)=12 units of time before doing 5, which takes 5 units of time. So 5 is completed after 17 units of time. On the other hand 2 is completed after 14 units. So the answer is 17.
The question is, if exactly one time requirement in updated in each query (where everytime you start with the original graph, not the graph resulting after the previous modifications)
how can you efficiently find the new minimum time requirement?
For those who want constraints, number of jobs <= 10^5. number of dependencies <= 10^6, number of queries <= 10^6.
The time requirement is the maximum weight of a path in the acyclic directed graph. Two linear-time traversals yield, for each node, the maximum weight of a path ending with that node and the maximum weight of a path starting with that node. Now we can find the maximum length of a path including a specified node. If a node's weight increases, then we take the maximum of the previous maximum and the new maximum involving that node, which we can compute in constant time.
Decreases are trickier, since we need, for each node in the maximum weight path, the maximum weight of a path not including that node. The first way (maybe not the best) that I can think of to do this is the following. Add to the acyclic directed graph a source and a sink, both with weight zero and connections to (source) or from (sink) each of the other nodes. Number the nodes in topological order, where the source is 0 and the sink is n + 1, and initialize a segment tree mapping nodes to path weights, where the initial values are -infinity. This segment tree has the following logarithmic-time operations.
Weight(i) - returns the value for node i
Update(i, j, w) - updates the value for nodes i..j to
the maximum of the current value and w
For each arc from i to j, call Update(i + 1, j - 1, w), where w is the maximum weight of a path that includes the arc from i to j. At the end, each weight in the segment tree is the maximum weight of a path excluding the corresponding node.
(Note on the running time: by treating nodes without dependencies separately, the running time of this approach can be made to be O(m log n + n + q), where n is the number of nodes, m is the number of dependencies, and q is the number of queries. My segment tree sort of is computing 3D maxima, a problem well studied by computational geometers. With presorted input (at least in two dimensions), the fastest known algorithm for n points is O(n log log n), via van Emde Boas trees. There also exist algorithms with output-sensitive time bounds better in some cases than that worst-case bound.)