![]() |
Algorithms and Data Structures | ||||
|
Graphs
(and single source shortest path algorithm)
Basic definition of a graph = (V,E), where the graph G is composed of a set of vertices V (also known as nodes) and a set of undirected edges E. Edges may be "labelled" with something, such as a cost, where cost may be a distance between vertices, time between vertices, cost in going between vertices, etc. Therefore, we may have a "labelled graph". Alternatively, edges maybe labelled with relations, such as before/after, < or >, and so on. Representation
With the adjacency list we associate with each vertex a list, containing the vertices adjacent to that vertex. In the scheme implementation we will use a more general representation. We will have an object called a graph G, where the graph may be directed or undirected. The (directed) graph object can be created using the function call: (define G (make-random-digraph n p)) where n is the size of the graph (number of vertices) and p is the probability that an edge exists between vertices i and j, for all i and all j, where i is not equal to j. The object will have a number of attributes, most notably: (n G) number of vertices in G. Think of n of G as the size of G (V G) the vertices of G, as a set of the first n integers (1 to n inclusive) (E G) the edges of G, as a list of pairs (p G) the probability that an edge (i j) exists. This can also be thought of as the density of G. if (= 1 (p G)) then G is a clique (fully connected) and if (= 0 (p G)) then G is the null graph (x-vect G) A vector, where (vector-ref (x-vect G) i) gives the x coordinate of vertex i. (y-vect G) A vector, where (vector-ref (y-vect G) i) gives the y coordinate of vertex i. Consequently x-vect and y-vect give the position of the vertices in the x-y plane (C G) Is the cost matrix for the graph G. (array-ref (C G) (list i j)) gives the cost from i to j in G, and is computed as the Euclidean distance using x-vect and y-vect. If the edge (i j) does not exist then then (array-ref (C G) (list i j)) is *max*. Therefore, the diagonal (for the non-existent edges (i i)) will have all elements set to *max*Making an undirected graph we use the function (define G (make-random-graph n p)) There are functions to save graphs to disc (ie. (save-graph G fname)) and to load graphs from disc (ie. (load-graph fname)). There are also function for drawing a graph (ie. (draw-graph G)), drawing a vertex (ie. ((draw-vertex G) i)), drawing an edge (ie. ((draw-edge G) edge) where edge is a pair, such as (list i j)). It should be noted that the functions draw-vertex and draw-edge are "partially applicable" and can therefore be "curried" thus allowing us to use the primitive ``for-each''. For example, given graph G we can draw all of the edges of G as follows: (for-each (draw-edge G) (E G)) and we can draw all the vertices of G as follows: (for-each (draw-vertex) (V G)) There are also functions (as you could expect) to determine if G is a graph (graph? G), test if vertex i is adjacent to vertex j in G (adjacent? i j G), and get the set of vertices that are adjacent to i in G (adjacent-to i G). Single Source Shortest Paths (SSSP)
An algorithm that does this is Dijkstra's algorithmdijkstra.scm and is describe informally below. A demo of the algorithm can be run by loading the above file and making the function call (demo 10 0.3) This will produce a random graph with 10 vertices, edge probability of 0.3, and will display all of the shortest paths with their costs. The algorithm uses the following variable S, the set of ``special'' vertices, such that all vertices in S are already on shortest paths V-S (read it as V minus S) the set of vertices not in S D a vector, such that D[i] is the distance from Source to i (and initially D is a copy of the Source'th row in (C G)) P a vector, such that P[i] is the vertex immediately before vertex i on the path from Source The algorithm goes like this: 1. let u be the closest vertex to Source in V-S 2. add u to the set S, and remove u from the set V-S 3. For all vertices w in V-S If the cost from Source -> u -> w is less than the cost from Source -> w (that is, it is less costly via u) Then set D[w] to be cost(Source -> u) + cost(u -> w) and set P[w] to be u 4. If there are still vertices remaining in the set V-S Then go back to step 1 above For example, if we have the following cost matrix ------------------------------- | | | | | | | - | 10 | - | 30 | 100 | | | | | | | ------------------------------- | | | | | | | 10 | - | 50 | - | - | | | | | | | ------------------------------- | | | | | | | - | 50 | - | 20 | 10 | | | | | | | ------------------------------- | | | | | | | 30 | - | 20 | - | 60 | | | | | | | ------------------------------- | | | | | | | 100 | - | 10 | 60 | - | | | | | | | ------------------------------- and Source = 1, the algorithm proceeds as follows S V-S u D1 D2 D3 D4 D5 P1 P2 P3 P4 P5 {1} {2,3,4,5} - 10 - 30 100 1 1 1 1 1 {1,2} {3,4,5} 2 - 10 60 30 100 1 1 2 1 1 {1,2,4} {3,5} 4 - 10 50 30 90 1 1 4 1 4 {1,2,4,3} {5} 3 - 10 50 30 60 1 1 4 1 3 {1,2,4,3,5} {}We then get the costs of the shortest paths in the vector D, and we can trace back the path from some vertex i to the Source using vector P. For example the path from vertex 1 to vertex 5 goes 5 <- 3 <- 4 <- 1 and has a cost of 60 (note that the function that does this is called (get-path-from i k P) NOTE: Dijkstra's algorithm is of complexity O(n*n) and you might care to convince yourself of that. Furthermore, the algorithm only holds so long as all labels are positive, that is there is no negative costs to be found in the graph. We have an informal proof below. We know that in step 1 (choosing the vertex u in V-S, such that u is closest to the source) that the vertex u MUST be special. If it were not special, then we should be able to find some other vertex w such that there is a path Source -> w -> u that has lower cost than Source -> u. But we know that u is the vertex closest to Source in V-S therefore for a shorter path to exist to u we must have a path from Source -> w that is greater than Source -> u and a path from w -> u that is negative ... and this is not allowed. So we can show that it would be absurd for this to exist, so u must be special |