Related
My job is to generate a random undirected, unweighted graph with a given diameter d. What I did already is to generate a random distance matrix D where each element Dij represents the distance between the i-th and j-th vertices of the graph. So, basically I am doing this:
if (i == j) {
D[i][j] = 0;
} else {
D[i][j] = D[j][i] = random.nextInt(d + 1);
}
The diagonal is zero because it always needs zero effort to reach the same vertex, am I right?
Also, Dij = Dji because it is undirected. Are my assumptions right?
I want to use java, but I tagged the question as language-agnostic because I need an algorithm and not a code.
My next step is to use Dijkstra's algorithm to generate a random graph by generating an adjacency matrix. I think that Dijkstra's algorithm is to find the shortest path, but can I use it for my case?
EDIT #1:
As you can see in the figure above, the diameter is 4 because the most distanced vertices are 2 and 7 have a distance of 4. For that reason, we have D[2][7] = D[7][2] = 4. Another example is D[3][6] = D[6][3] = 2, because if we want to go from 3 to 6, we can go 3 -> 5 -> 6, or 3 -> 1 -> 6 and vice versa for going from 6 to 3.
What I am looking for is to generate a random graph by knowing the diameter which is the maximum distance between two vertices in the graph. I know there are a lot of possibilities of the graph, but I need any of them.
I have an idea which is assuming that the number of vertices is d + 1, then connecting each vertex to the following vertex. In this case we will have a linear graph.
Example (diameter = 2, number of vertices = 3):
v
1
2
3
1
0
1
2
2
1
0
1
3
2
1
0
The diagonal = zero
D1,2 = D2,1 = D2,3 = D3,2 = 1, because to go from 1 to 2, or 2 to 3, there is a direct link
D1,3 = D3,1 = 2, because to go from 1 to 3, the shortest path is 1
-> 2 -> 3
Here is the graph associated to the above distance matrix:
I am looking for a better approach.
I'm having a trouble finding a contradicting example of the next variation of the TSP problem.
Input: G=(V,E) undirected complete graph which holds the triangle inequality, w:E->R+ weight function, and a source vertex s.
Output: Simple Hamilton cycle that starts and ends at s, with a minimum weight.
Algorithm:
1. S=Empty-Set
2. B=Sort E by weights.
3. Initialized array M of size |V|,
where each cell in the array holds a counter (Initialized to 0)
and a list of pointers to all the edges of that vertex (In B).
4. While |S|!=|V|-1
a. e(u,v)=removeHead(B).
b. If e does not close a cycle in S then
i. s=s union {e}
ii. Increase degree counter for u,v.
iii. If M[u].deg=2 then remove all e' from B s.t e'=(u,x).
iv. If M[v].deg=2 then remove all e' from B s.t e'=(v,x).
5. S=S union removeHead(B).
This will be done similar to the Kruskal Algorithm (Using union-find DS).
Steps 4.b.iii and 4.b.iv will be done using the List of pointers.
I highly doubt that this algorithm is true so I instantly turned into finding why it is wrong. Any help would be appreciated.
Lets say we have a graph with 4 vertices (a, b, c, d) with edge weights as follows:
w_ab = 5
w_bc = 6
w_bd = 7
w_ac = 8
w_da = 11
w_dc = 12
7
|--------------|
5 | 6 12 |
a ---- b ---- c ----- d
|______________| |
| 8 |
|_____________________|
11
The triangle inequality holds for each triangle in this graph.
Your algorithm will choose the cycle a-b-c-d-a (cost 34), when a better cycle is a-b-d-c-a (cost 32).
Your procedure may not terminate. Consider a graph with nodes { 1, 2, 3, 4 } and edges { (1,2), (1,3), (2,3), (2,4), (3,4) }. The only Hamiltonian cycle in this graph is { (1,2), (1,3), (2,4), (3,4) }. Suppose the lowest weighted edge is (2,3). Then your procedure will pick (2,3), pick one of { (1,2), (1,3) } and eliminate the other, pick one of { (2,4), (3,4) } and eliminate the other, then loop forever.
Nuances like this are what makes the Travelling Salesman problem so difficult.
Consider the complete graph on 4 vertices, where {a,b,c,d} are the nodes, imagined as the clockwise arranged corners of a square. Let the edge weights be as follows.
w({a,b}) := 2, // "edges"
w({b,c}) := 2,
w({c,d}) := 2,
w({d,a}) := 2,
w({a,c}) := 1, // "diagnoals"
w({b,d}) := M
where M is an integer larger than 2. On one hand, the hamiltonian cycle consisting of the "edges" has weight 8. On the other hand, the hamiltonian cycle containing {a,c} , which is the lightest edge, must contain {b,d} and has total weight
1 + M + 2 + 2 = 5 + M > 8
which is larger than the minimum possible weight. In total, this means that in general a hamitonian cycle of minimum weight does not necessarily contain the lightst edge, which is chosen by the algorithm in the original question. Furthermore, as M tends to infinity, the algorithm performs arbitrarily badly in terms of the approximation ratio, as
(5 + M) / 8
grows arbitrarily large.
I've been studying the three and I'm stating my inferences from them below. Could someone tell me if I have understood them accurately enough or not? Thank you.
Dijkstra's algorithm is used only when you have a single source and you want to know the smallest path from one node to another, but fails in cases like this
Floyd-Warshall's algorithm is used when any of all the nodes can be a source, so you want the shortest distance to reach any destination node from any source node. This only fails when there are negative cycles
(this is the most important one. I mean, this is the one I'm least sure about:)
3.Bellman-Ford is used like Dijkstra's, when there is only one source. This can handle negative weights and its working is the same as Floyd-Warshall's except for one source, right?
If you need to have a look, the corresponding algorithms are (courtesy Wikipedia):
Bellman-Ford:
procedure BellmanFord(list vertices, list edges, vertex source)
// This implementation takes in a graph, represented as lists of vertices
// and edges, and modifies the vertices so that their distance and
// predecessor attributes store the shortest paths.
// Step 1: initialize graph
for each vertex v in vertices:
if v is source then v.distance := 0
else v.distance := infinity
v.predecessor := null
// Step 2: relax edges repeatedly
for i from 1 to size(vertices)-1:
for each edge uv in edges: // uv is the edge from u to v
u := uv.source
v := uv.destination
if u.distance + uv.weight < v.distance:
v.distance := u.distance + uv.weight
v.predecessor := u
// Step 3: check for negative-weight cycles
for each edge uv in edges:
u := uv.source
v := uv.destination
if u.distance + uv.weight < v.distance:
error "Graph contains a negative-weight cycle"
Dijkstra:
1 function Dijkstra(Graph, source):
2 for each vertex v in Graph: // Initializations
3 dist[v] := infinity ; // Unknown distance function from
4 // source to v
5 previous[v] := undefined ; // Previous node in optimal path
6 // from source
7
8 dist[source] := 0 ; // Distance from source to source
9 Q := the set of all nodes in Graph ; // All nodes in the graph are
10 // unoptimized - thus are in Q
11 while Q is not empty: // The main loop
12 u := vertex in Q with smallest distance in dist[] ; // Start node in first case
13 if dist[u] = infinity:
14 break ; // all remaining vertices are
15 // inaccessible from source
16
17 remove u from Q ;
18 for each neighbor v of u: // where v has not yet been
19 removed from Q.
20 alt := dist[u] + dist_between(u, v) ;
21 if alt < dist[v]: // Relax (u,v,a)
22 dist[v] := alt ;
23 previous[v] := u ;
24 decrease-key v in Q; // Reorder v in the Queue
25 return dist;
Floyd-Warshall:
1 /* Assume a function edgeCost(i,j) which returns the cost of the edge from i to j
2 (infinity if there is none).
3 Also assume that n is the number of vertices and edgeCost(i,i) = 0
4 */
5
6 int path[][];
7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
8 from i to j using intermediate vertices (1..kâ1). Each path[i][j] is initialized to
9 edgeCost(i,j).
10 */
11
12 procedure FloydWarshall ()
13 for k := 1 to n
14 for i := 1 to n
15 for j := 1 to n
16 path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );
You are correct about the first two questions, and about the goal of Floyd-Warshall (finding the shortest paths between all pairs), but not about the relationship between Bellman-Ford and Floyd-Warshall: Both algorithms use dynamic programming to find the shortest path, but FW isn't the same as running BF from each starting node to every other node.
In BF, the question is: What is the shortest path from the source to the target using at most k steps, and the running time is O(EV). If we were to run it to each other node, the running time would be O(EV^2).
In FW, the question is: what is the shortest path from i to j through k, for all nodes i,j,k. This leads to O(V^3) running time - better than BF for each starting node (by a factor of up to |V| for dense graphs).
One more note about negative cycles / weights: Dijkstra may simply fail to give the correct results. BF and FW won't fail - they will correctly state that there is no minimum weight path, since the negative weight is unbounded.
Single source shortest paths:
Dijkstra Algorithm - No negative weight allowed - O(E+Vlg(V))
Bellman ford Algorithm - Negative weight is allowed. But if a negative cycle is present Bellman ford will detect the -ve cycle - O(VE)
Directed Acyclic Graph - as name suggests it works only for DAG - O(V+E)
All pairs shortest paths:
Dijkstra Algorithm - No negative weight allowed - O(VE + V^2lg(V))
Bellman ford Algorithm - O(V^2E)
Matrix chain multiplication method -complexity same as Bellman ford algorithm
Floyd Warshall algorithm -uses dynamic programming method - Complexity is O(V^3)
Concerning
floyds(int a[][100],int n).
What does 'a' and represent and what does each of the two dimensions of a represent?
What does 'n' represent?
I have a list of locations, with a list of connections between those locations and have computed the distance between those connections that are connect to each other. Now I need to find shortest path between any given two locations (floyd's) - but need to understand how to apply floyds(int a[][100],int n) to my locations array, city dictionaries, and connection arrays.
FYI - Using objective C - iOS.
n is the number of nodes in the graph.
a is an distance matrix of the graph. a[i][j] is the cost (or distance) of the edge from node i to node j.
(Also read the definition of adjacency matrix if you need more help with the concept.)
/* Assume a function edgeCost(i,j) which returns the cost of the edge from i to j
2 (infinity if there is none).
3 Also assume that n is the number of vertices and edgeCost(i,i) = 0
4 */
5
6 int path[][];
7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
8 from i to j using intermediate vertices (1..kâ1). Each path[i][j] is initialized to
9 edgeCost(i,j).
10 */
12 procedure FloydWarshall ()
13 for k := 1 to n
14 for i := 1 to n
15 for j := 1 to n
16 path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );
http://en.wikipedia.org/wiki/Floyd-Warshall
wiki is very good~~~
floyd-warshall(W) // W is the adjacent matrix representation of graph..
n=W.rows;
for k=1 to n
for i=1 to n
for j=1 to n
w[i][j]=min(W[i][j],W[i][k]+W[k][j]);
return W;
It's a dp-algorithm.At the k-th iteration here W[i][j] is the shortest path between i and j and the vertices of the shortest path(excluding i and j) are from the set {1,2,3...,k-1,k}.In min(W[i][j],W[i][k]+W[k][j]), W[i][j] is the computed shortest path between i and j at k-1-th iteration and here since the intermediate vertices are from the set {1,2...k-1},so this path does not include vertex k. In W[i][k]+W[k][j],we include vertex k in the path.whichever between the two is minimum is the shortest path at k-th iteration.
Basically we check that whether we should include vertex k in the path or not.
I understand what Dijkstra's algorithm is, but I don't understand why it works.
When selecting the next vertex to examine, why does Dijkstra's algorithm select the one with the smallest weight? Why not just select a vertex arbitrarily, since the algorithm visits all vertices anyway?
You can think of Djikstra's algorithm as a water-filling algorithm (i.e. a pruned breadth-first search). At each stage, the goal is to cover more of the whole graph with the lowest-cost path possible. Suppose you have vertices at the edge of the area you've filled in, and you list them in terms of distance:
v0 <= v1 <= v2 <= v3 ...
Could there possibly be a cheaper way to get to vertex v1? If so, the path must go through v0, since no untested vertex could be closer. So you examine vertex v0 to see where you can get to, checking if any path through v0 is cheaper (to any other vertex one step away).
If you peel away the problem this way, you're guaranteed that your distances are all minimums, because you always check exactly that vertex that could lead to a shortest path. Either you find that shortest path, or you rule it out, and move on to the next vertex. Thus, you're guaranteed to consume one vertex per step.
And you stop without doing any more work than you need to, because you stop when your destination vertex occupies the "I am smallest" v0 slot.
Let's look at a brief example. Suppose we're trying to get from 1 to 12 by multiplication, and the cost between nodes is the number you have to multiply by. (We'll restrict the vertices to the numbers from 1 to 12.)
We start with 1, and we can get to any other node by multiplying by that value. So node 2 has cost 2, 3 has cost 3, ... 12 has cost 12 if you go in one step.
Now, a path through 2 could (without knowing about the structure) get to 12 fastest if there was a free link from 2 to 12. There isn't, but if there was, it would be fastest. So we check 2. And we find that we can get to 4 for cost 2, to 6 for 3, and so on. We thus have a table of costs like so:
3 4 5 6 7 8 9 10 11 12 // Vertex
3 4 5 5 7 6 9 7 11 8 // Best cost to get there so far.
Okay, now maybe we can get to 12 from 3 for free! Better check. And we find that 3*2==6 so the cost to 6 is the cost to 3 plus 2, and to 9 is plus 3, and 12 is plus 4.
4 5 6 7 8 9 10 11 12
4 5 5 7 6 6 7 11 7
Fair enough. Now we test 4, and we see we can get to 8 for an extra 2, and to 12 for an extra 3. Again, the cost to get to 12 is thus no more than 4+3 = 7:
5 6 7 8 9 10 11 12
5 5 7 6 8 7 11 7
Now we try 5 and 6--no improvements so far. This leaves us with
7 8 9 10 11 12
7 6 8 7 11 7
Now, for the first time, we see that the cost of getting to 8 is less than the cost of getting to 7, so we had better check that there isn't some free way to get to 12 from 8. There isn't--there's no way to get there at all with integers--so we throw it away.
7 9 10 11 12
7 8 7 11 7
And now we see that 12 is as cheap as any path left, so the cost to reach 12 must be 7. If we'd kept track of the cheapest path so far (only replacing the path when it's strictly better), we'd find that 3*4 is the first cheapest way to hit 12.
Dijkstra's algorithm picks the vertex with the least path cost thus far, because a path through any other vertex is at least as costly as a path through the vertex with the least path cost.
Visiting any other vertex, therefore, if it is more costly (which is quite possible) would necessitate visiting not only that other vertex, but also the one with the least path cost thus far, so you would have to visit more vertices before finding the shortest path. In fact, you would end up with the Bellman-Ford algorithm if you did that.
I should also add that the vertex doesn't have a weight, it is the edge that has a weight. The key for a given vertex is the cost of the shortest path found thus far to that vertex from the source vertex.
The reason why Dijsktra's algorithm works the way it does is in part because it exploits the fact that the shortest path between node u and w that includes point v also contains the shortest path from u to v and from v to w. If there existed something shorter between u to v, then it wouldn't be the shortest path.
To really understand why Dijkstra's algorithm works, look into the basics of dynamic programming, sounds hard but it's really pretty easy to understand the principles.
It likes greedy strategy.My English is not good.It translates by google.If you don't understand,I am very sorry.
Dijkstra algorithm, a G from S to all vertices of the shortest path length.
We assume that each vertex of G in V have been given a flag L (V), it is either a number, either â. Suppose P is the set of vertices of G, P contains S, to satisfy:
A) If V is P, then L (V) from V S to the length of the shortest path, and the existence of such V from S to the shortest path: path on the vertices in P in
B) If V does not belong to P, then L (V) from S to V satisfy the following restrictions on the length of the shortest path: V is the only path P does not belong to the vertex.
We can use induction to prove P Dijkstra algorithm in line with the above definition of the collection:
1) When the number of elements in P = 1, P corresponds to the first step in the algorithm, P = (S), is clearly satisfied.
2) Suppose P is k, the number of elements, P satisfy the above definition, see the algorithm below the third step
3) P in and the first to find out is not marked with the minimum vertex U, marked as L (U), can be proved from S to U of U outside the shortest path, in addition to P does not contain the elements do not belong.
Because if there is outside the other vertices except U, then the shortest path to S, P1, P2 ... Pn, Q1, Q2 ... Qn, U (P1, P2 ... Pn is P; Q1, Q2, ... Qn does not belong to P), from the nature of B) the shortest path length L (Q1) + PATH (Q1, U)> L (U).
Which is greater than S, P1, P2 ... Pn, U of the channel length L (U), is not the shortest path. Therefore, from the S to the U of U outside the shortest path, in addition to P does not contain the elements do not belong to U from S to the length of the shortest path from the L (U) is given.
U is added to P in the form P ', clearly P' to meet the nature of the A).
Take V does not belong to P ', obviously does not belong to V P, then from S to V except the shortest path and meet all the vertices outside V in P' in the path there are two possibilities, i) contains U, ii) does not contain U.
On i) S, P1, P2 ... Pn, U, V = L (U) + W (U, V)
ii) S, P1, P2 ... Pn, V = L (V)
Obviously the two are given in the smallest V from S to meet the minimum access and outside addition to all the vertices are V P 'in length.
The third step to algorithm given in P 'with k +1 elements and meet the A), B).
By the induction proposition may permit.
Here is the source.
It checks the path with the lowest weight first because this is most likely (without additional information) to reduce the number of paths checked. For example:
a->b->c cost is 20
a->b->d cost is 10
a->b->d->e cost is 12
If goal is to get from a to e, we don't need to even check the cost of:
a->b->c->e
Because we know it's at least 20 so we know it's not optimal because there is already another path with a cost of 12. You can maximize this effect by checking the lowest weights first. This is similar (same?) to how minimax works in chess and other games to reduce the branching factor of the game tree.
Dijsktra's algorithm is a greedy algorithm which follows the problem solving heuristic of making the locally optimal choice at each stage with the hope of finding a global optimum.
For understand the basic concept of this algorithm, I wrote this code for you. There is an explanation of how it works.
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["finish"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["finish"] = 5
graph["finish"] = {}
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["finish"] = infinity
print "The weight of each node is: ", costs
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["finish"] = None
processed = []
def find_lowest_cost_node(costs):
lowest_cost = float("inf")
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs)
print "Start: the lowest cost node is", node, "with weight",\
graph["start"]["{}".format(node)]
while node is not None:
cost = costs[node]
print "Continue execution ..."
print "The weight of node {} is".format(node), cost
neighbors = graph[node]
if neighbors != {}:
print "The node {} has neighbors:".format(node), neighbors
else:
print "It is finish, we have the answer: {}".format(cost)
for neighbor in neighbors.keys():
new_cost = cost + neighbors[neighbor]
if costs[neighbor] > new_cost:
costs[neighbor] = new_cost
parents[neighbor] = node
processed.append(node)
print "This nodes we researched:", processed
node = find_lowest_cost_node(costs)
if node is not None:
print "Look at the neighbor:", node
# to draw graph
import networkx
G = networkx.Graph()
G.add_nodes_from(graph)
G.add_edge("start", "a", weight=6)
G.add_edge("b", "a", weight=3)
G.add_edge("start", "b", weight=2)
G.add_edge("a", "finish", weight=1)
G.add_edge("b", "finish", weight=5)
import matplotlib.pyplot as plt
networkx.draw(G, with_labels=True)
plt.show()