To do this assignment, you will do the following steps in order.
Dijkstra
.ssspDistances()
.shortestPaths()
.Your work will be evaluated based on the quality of your tests, the correctness and robustness of its implementation (that is, whether it gets the right answer for a variety of inputs, including tricky edge cases), and the organization and style of your code. There is also a small extension that counts for two points (shortestPaths()).
It's likely that you will want to refer to the Javadoc documentation for our class's ADT interfaces and implementation classes.
Download all the ADT and implementation code from the page for the graph traversal activities.
This is a partner assignment. Work with your assigned partner from class and submit only one copy of your work. As always, all partners' names should be in a comment at the top of the source code, and you should work by pair programming. No working remotely! You need to be sitting side by side.
Create a new Java file Dijkstra.java
with the empty class Dijkstra defined within it. Note that only static methods (and static final fields) are allowed: your class should store no mutable state! Here's a sketch of what it should look like once you're done:
// HW4: Dijkstra's Algorithm // By Thelma Dickinson and Louise Sawyer // For Data Structures: Comp 630, 10th period, with Dr. Miles // S'16 at Phillips Academy // // Due 2016-04-26 // ... // ... [ Answers to questions about Dijkstra's algorithm; step 3 above ] // ... public class Dijkstra { /** * ... [ Javadoc comment for ssspDistances() ] */ public static List<Double> ssspDistances(WeightedGraph G, int source) { // ... [ Stub body at first, then implementation filled in later ] } /** * ... [ Javadoc comment for shortestPaths() ] */ public static List<List<Integer>> shortestPaths(WeightedGraph G, int source) { // ... [ Stub body at first, then implementation filled in later ] } // ... [ Helper functions for methods above ] public static void main(String[] args) { // ... [ Tests for ssspDistances() ] // ... [ Tests for shortestPaths() ] } // ... [ Helper functions for your tests ] }
Obviously there should be no notes in square brackets in the code that you submit to me, nor ellipses. Those are simply placeholders for work that you will do throughout the assignment.
In a weighted graph, the “length” of a path in a weighted graph is the sum of the weights of the edges along that path. A “shortest $s–t$ path” is a path from $s$ to $t$ whose length is the minimum out of all $s–t$ paths. The “distance” from $s$ to $t$ is this minimum length, or ∞ if no path exists.
The Single-Source Shortest Paths problem (SSSP problem) is the following task: given a single starting node $s$ in a weighted graph, compute the distance from $s$ to each node in the graph.
There are several variations on this problem. An upgraded version instead asks us to compute a shortest $s–v$ path for all $v$ in the graph, rather than just the length of this path. The algorithm below can be upgraded to solve this problem instead, and in fact that's what you'll do for shortestPaths() at the end of the assignment.
In addition, a more limited version of the problem specifies two vertices, $s$ and $t$, and asks just for a shortest $s–t$ path, or just the length of this path. This is trivial to solve by first solving the entire SSSP problem, and then looking up the answer just for $t$.
Given an unweighted graph (directed or undirected) $G = (V,E)$ with non-negative weighting function $w$, and a vertex $s$ in that graph, the Single-Source Shortest Paths problem is solved by Dijkstra's Algorithm:
Dijkstra's Algorithm
Read and discuss this algorithm with your partner. Take a while to think through why it works, and what each part means. Relate it to the more abstract pseudocode we went over in class. Then answer the following questions in a comment at the top of Dijkstra.java.
You will implement the above algorithm in a method with the following signature:
/** * Computes single-source shortest path distances. Given graph G and vertex * s, computes the length of the shortest path from s to each node in G. G * is a weighted graph, but may be directed or undirected. * * @param G The graph in which to search. * @param source The ID of the node from which distances will be computed. * * @return A List of length G.numVerts(), whose entry at index u is the * distance from source to u. */ public static List<Double> ssspDistances(WeightedGraph G, int source)
Before you write your implementation, design a thorough set of tests on paper.
Keep in mind that a test consists of an input, an expected output, and, when executed, a comparison to the actual output computed by the implementation. Note that you can and should write your tests before you write your implementation.
Working on paper, try to come up with example graphs that will demonstrate the different expected behaviors of the algorithm, and also come up with challenging graphs that might expose bugs. (Remember that big things are challenging for humans, but usually not for computers! Your goal is to come up with devious examples, not necessarily big or complex ones.) Think about edge cases — empty graphs, singletons, fully disconnected graphs, graphs with many connected components, trees, complete graphs, etc. Don't bother testing invalid input; that's not the point.
Implement your tests in code to run from the main method. When run, each test should print out the following three things:
ssspDistances()
Use spacing and indentation in your printed output so that the output is as easy as possible to read, and so that tests are easy to distinguish from each other. A giant pile of hard-to-decipher text is not helpful to your users, and will not earn full credit.
You may write helper functions for your tests; in fact, for graph algorithms this is a particularly good idea, since there's so much verbose code just to create the graph. (Messy code will also not earn full credit.)
When you first run your tests, it's likely that they'll all fail, since you haven't yet implemented the algorithm. That's just fine!
ssspDistances()
, as always using descriptive variable names and comments. Use your tests as a guide to catch bugs.For your final two points on this assignment, test and implement another function, with the following interface:
/** * Computes single-source shortest paths. Given graph G and vertex s, * computes a shortest path from s to each node in G. G is a weighted * graph, but may be directed or undirected. * * @param G The graph in which to search. * @param source The ID of the node from which distances will be computed. * * @return A List of length G.numVerts(), whose entry at index u is a list * of vertices forming a path from source to u. If no such path * exists, the list for u is empty. */ public static List<List<Integer>> shortestPaths(WeightedGraph G, int source)
Submit your Dijkstra.java file on Canvas. (Only one submission per pair!)
Start early, ask lots of questions, and have fun!
This assignment is worth 25 points.
Feature | Points |
---|---|
Answers to questions about Dijkstra's Algorithm. | 4.5 |
Code compiles & runs. | 1 |
Tests for ssspDistances() . | 3 |
Implementation of ssspDistances() . | 7 |
Proportion of my tests that your implementation passes. | 2.5 |
Tests for shortestPaths() . | 1 |
Implementation of shortestPaths() . | 1 |
Comments, style, design, and clear output. | 5 |
Total | 25 |