Readings
- Prim: 5.1.5
- Kruskal: 5.1.1,5.1.3
- Disjoint Sets: 5.1.3
- Floyd-Wrshall: 6.6 pages 172-173
Description
This assignment is part of the sequence on Graphs and Graph algorithms. A
Graph
is a collection of
Vertices
connected by
Edges
. It is a generalization of the
Tree
data structure from the previous assignments.
The focus is on the following algorithms and data structures:
- Prim's Algorithm for Minimum-Spanning Trees
- Disjoint-Sets Data Structure
- Kruskal's Algorithm for Minimum-Spanning Trees
- Floyd-Warshall's Algorithm for All-Pairs Shortest Path
The work should be done in the project
Graph.
Visualization resources
Here is pseudocode for the various algorithms:
Graph Algorithms
Here is a useful visualization resource:
Test files are available here:
JUnit
Put the test cases in class
GraphAlgosTest. The JUnit testing will be different, since the methods will only print to the screen.
This means that there won't be
assertEquals
. Instead each
@Test
method will look like a mini-
main
method and you will inspect the console to see if the output is correct.
[ To test individual components you can comment
//@Test
]
Here is an example:
@Test
public void test_prim()
{
Graph graph = new Graph("undirected.txt");
String[] labelsList = { "a", ... };
for ( ... ) {
System.out.println("Prim Source: ?");
GraphAlgos.prim(graph, ?); // compare total weight with Kruskal
System.out.println();
}
}
|
@Test
public void test_kruskal()
{
Graph graph = new Graph("undirected.txt");
System.out.println("Kruskal:");
GraphAlgos.kruskal(graph);
// compare total weight with Prim
}
|
@Test
public void test_floydWarshall()
{
Graph graph = new Graph("directed.txt");
System.out.println("Floyd-Warshall:");
GraphAlgos.floydWarshall(graph);
}
|
Edge Update
Add the following method to class
Edge
:
toString()
- returns a string representation of this edge in the following format:
SourceLabel--EdgeWeight--TargetLabel i.e. Hanover--15--NewOxford
Prim's Minimum-Spanning Tree
Implement
Prim's algorithm (
pseudocode) for computing a
Minimum Spanning Tree.
Add the following method to class
GraphAlgos
:
Disjoint-Sets Data Structure
Read Section 5.1.3. Create
generic class DisjointSets
that implements a
Disjoint-Sets data structure with the methods listed below.
There should be internal class
Node
that represents the elements in the disjoint sets with the following fields and constructor:
item
- the item represented by this node
rank
- the length of the longest path from this node to one of its leaves
parent
- the parent of this node; root/top nodes loop onto self
Node(E theItem)
- creates a single node with the given item
Internally,
DisjointSets
maintains
HashMap
that associates an
item
(key) with the
Node
(value) that contains the item.
This map is needed in order to connect
item
(what user knows) with
Node
(what Disjoint Sets works with). Ths is similar to the
Graph
which had a map form
label
(what user knows) to
Vertex
(what Graph Algorithms work with).
DisjointSets(Iterable<E> items)
Creates a Disjoint-Sets data structure with the given items as individual sets.
Makes a single node/set for each of the given items and associates each pair in the internal Hash Map.
[ Since the parameter is of type Iterable , it will accept any collection type that can be traversed with enhanced for-loop. ]
|
Node findRep(Node curr)
Returns the representative of the set that contains the given node, i.e. the root of the tree in which the given node belongs.
Initially, may use a loop to complete this method and ignore path compression.
The final version should use recursion and should perform path compression.
|
boolean sameSet(E a, E b)
Determines if the given elements a and b are in the same set, i.e. if their corresponding nodes are in the same tree (have same representative).
|
void union(E a, E b)
Merges the sets that contain the given elements a and b , i.e. points one of the representatives to the other.
|
Kruskal's Minimum-Spanning Tree
Implement
Kruskal's algorithm (
pseudocode) for computing a
Minimum Spanning Tree
Add the following methods to
GraphAlgos
and
Graph
, respectively, and create a new
Comparator
class:
List<Edge> getEdges()
[ Graph method ] Returns a list of all edges of the graph.
Simply traverse the adjacency lists of the graph. Minimize number of loops by using relevant methods.
|
static Graph kruskal(Graph graph)
[ GraphAlgos method ] Returns the graph representation of the MST for the given graph . Prints a summary for the MST.
Compare with the result from Prim's Algorithm.
Kruskal results on undirected.txt (no source vertex in Kruskal)
|
EdgeComparator
[ new class ] Comparator used for sorting edges in Kruskal's algorithm.
|
Floyd-Warshall All-Pairs Shortest Paths
Implement the
Floyd-Warshall algorithm for computing
All-Pairs Shortest Paths.
Add/update the following methods to
GraphAlgos
and
Graph
, respectively.
Vertex getVertex(String label)
[ Graph method ] Update this method, so that it tags the created vertex with its index:
- in class
Vertex add a new member for the index and modify the constructor Vertex(String theLabel, int theIndex)
- modify method
getVertex so that the index of a newly created vertex is just the number of vertices currently in the graph
|
String[] getLabels()
[ Graph method ] Returns an array representing the labels of the vertices in the graph.
Each vertex label should be placed in the cell that corresponds to the index field of the Vertex .
[ These labels will correspond to the rows/columns of the adjacency matrix. ]
|
double[][] getMatrix()
[ Graph method ] Returns the adjacency matrix of the graph.
First initialize the matrix as shown in the initialization step in the pseudocode.
Then, traverse the adjacency lists and for each edge put its weight in cell [i][j] where i, j are the indices of the vertices of the edge.
This method should run in O(n^2) .
|
static int[][] initPredecessor(double[][] D)
[ GraphAlgos method ] Builds the predecessor matrix from the given adjacency matrix D as shown in the initialization step for Floyd-Warshall in the pseudocode.
|
static void floydWarshall(double[][] D, int[][] P)
[GraphAlgos method ] Implements Floyd-Warshall's algorithm (pseudocode) for computing All-Pairs Shortest Paths for the graph with the given adjacency matrix D and the given predecessor matrix P .
The distance and predecessor matrices D and P are modified to contain the final all-pairs shortest distances and predecessors, respectively.
|
static void floydWarshall(Graph G)
[ GraphAlgos method ] A convenience method that runs Floyd-Warshall's algorithm and prints all paths.
This method simply calls the relevant methods in the correct order.
|
static void printAllPaths(double[][] D, int[][] P, String[] labels)
[ GraphAlgos method ] Displays the shortest paths between all pairs of vertices based on the given distance matrix, D , and predecessor matrix, P , in the following format:
A --4--> H --6--> E --3--> B
A --2--> C
A --8--> F --5--> D
...
Floyd-Warshall results on directed.txt
This method simply calls methods printPathLoop and printPath for each pair (i,j) pair of vertex indices, i.e. each pair of rows/columns in the distance matrix.
|
static void printPathLoop(int i, int j, double[][] D, int[][] P, String[] labels)
[ GraphAlgos method ] Uses a loop to print the path (in reverse) from the given destination vertex j to the given start vertex i .
F <--5-- D <--2-- G <--6-- C <--4-- A (total length 17)
Note: A is the start vertex i and F is the destination vertex j , and the path is printed in reverse. This makes the problem simpler.
Note: The individual numbers are edge lengths, not cumulative distances.
Hint: Follow the parent indices.
This method will be tested indirectly by testing Floyd-Warshall algorithm.
|
static void printPath(int i, int j, double[][] D, int[][] P, String[] labels)
[ GraphAlgos method ] Same as method printPathLoop
but uses recursion (does not include the total length). Unlike the previous
method, this one shows the path from the start vertex i to
the destination vertex j , i.e. not in reverse:
A --4--> C --6--> G --2--> D --5--> F
Note: A is the start vertex i and F is the destination vertex j , and the path is printed correctly. This makes the problem harder (but total distance is not printed).
This method will be tested indirectly by testing Floyd-Warshall algorithm.
|
Executable JAR
Update the
main
method of
GraphExplorer
and rebuild the
.jar file, so that the new algorithms can be run from the command line:
cd path/to/project/Graph (go to correct project folder)
THE_FULL_PATH_TO_JAVA -jar gbcsmaps.jar -prim undirected.txt c (runs Prim starting at c)
THE_FULL_PATH_TO_JAVA -jar gbcsmaps.jar -kruskal undirected.txt (runs Kruskal)
THE_FULL_PATH_TO_JAVA -jar gbcsmaps.jar -fw undirected.txt (runs Floyd-Warshall)
THE_FULL_PATH_TO_JAVA -jar gbcsmaps.jar -fw directed.txt (runs Floyd-Warshall)