Gettysburg College

CS 216
Data Structures

Spring 2024

Assignment 11

Due: Mon, Apr 29, by 11:59pm
  • method stubs: Vertex|Edge|Graph|GraphAlgos.java
  • junit tests: GraphAlgosTest.java
  • coverage-Graph.pdf
  • coverage-GraphAlgos.pdf
  • api-Graph.pdf (ony for Graph.java)
Due: Thu, May 2, by 11:59pm
  • Vertex|Edge|Graph|GraphAlgos.java
  • VertexComparator|EdgeComparator.java
  • GraphAlgosTest.java
  • run-jar.png (screenshot of terminal)
  • coverage-Graph.pdf
  • coverage-GraphAlgos.pdf

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:

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:
London Tube Map

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:

Graph Update

Add a default constructor to class Graph: Add the following method to class Graph:

Prim's Minimum-Spanning Tree

Implement Prim's algorithm (pseudocode) for computing a Minimum Spanning Tree.

Add the following method to class GraphAlgos:

static Graph prim(Graph graph, String source)

Returns the graph representation of the MST for the given graph from the given source. Prints a summary for the MST.

Prim results on undirected.txt for a couple of vertices as source

Note: Simply changing the distance field of a vertex will not automatically reconfigure the PQ.

Disjoint-Sets Data Structure

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:

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)

Sort the collection of edges with the relevant method in Collections API.

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 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)


What to turn in

Turn in:

Turn in: