CS 1501
Data
Structures and Algorithms
Programming
Project 4
Purpose:
The purpose of this
assignment is to familiarize you with graphs and graph algorithms, and to
demonstrate the differences between the adjacency matrix and adjacency list implementations.
Program
Details:
In this assignment you
will generate "random" graphs of various densities and run 3
algorithms on each: Depth-First Search, Breadth-First Search and Prim's Minimum Spanning Tree. You will run each of these algorithms using
both an adjacency list and an adjacency matrix and compare the times required
for each. You will then summarize your
results in a short paper. More details
are provided below.
The Data:
You will generate
random graphs with V vertices, where you will use the following values for V:
(25),
50, 100, 200, 400, 800, (1600)
First try to use the 5
middle values. If you find your program
is taking too long to run, instead use the first 5 values. If you find your program is running so
quickly that you are not getting good results, try the last 5 values. Assume that the graphs are undirected. We know from lecture that a sparse graph with
V vertices has roughly VlgV or fewer edges and a
dense graph with V vertices has ~V2 edges (within a constant
factor). In this assignment you will
have 3 different graph "densities":
a)
E = V
b)
E = V lgV
c)
E = (V-1)2/2
For each graph size
you will run each algorithm twice for each density and average the
results. Thus, in total you will have:
(3 algorithms) x (2 implementations) x (5 graph sizes) x (3 densities) x (2
runs) = 180 total runs. Naturally you
should automate this process within your main program so that your program can
generate all of your output in a single execution.
Generate your graphs
in the following way: For the current
value of, V, vertices, create an adjacency matrix and an adjacency list array
(without nodes) of the appropriate size (see note
below). Then, for each density,
"add" the correct amount of edges to the graph. You can do this in any reasonable way. Note that your approach for the sparse and
dense graphs may be different, in the interest of efficiency. In the sparse graph, a reasonable approach is
to generate V or VlgV random vertex pairs and
"add" each edge to the adjacency list and adjacency matrix (making
sure the pair has not already been generated – so you may have to try more than
the required number of edges). However,
in the dense graph, an easier and more efficient approach is to generate ((V)(V-1)/2 – ((V-1)2/2)) vertex pairs that will NOT
be in the graph, and put all other pairs into the adjacency matrix and
adjacency list in a systematic way.
Since MST requires a weighted graph, also generate a random positive
weight for each edge that you generate (you can simply ignore the weight for
the DFS and BFS algorithms).
The Algorithms:
Implement the DFS, BFS
and (Prim's) MST algorithms more or less as specified
in the text. Note that the code is
(mostly) provided for these algorithms in the text, but, as always, you will
have to tweak it to get it to work. One
code segment that is not provided in the text is the BFS algorithm for an
adjacency matrix, so you will have to write that one. For the adjacency list MST algorithm a
priority queue is required. For this
priority queue you should use the pq.h code provided on the CS 1501 Web site, adding to
it the update() method as required (think about what update() needs to do – it
is actually not that difficult to add).
The Timing:
Time each of your 180
runs separately. Time each run by
starting the system clock just prior to the algorithm execution and stopping it
just after the algorithm completes. Do NOT
time the setting up of the data in the adjacency matrix or adjacency list. You can time in the same way that you did for
previous assignments. Remember to
average the two runs for each of the 90 different cases.
The Results:
You should produce 90
different results (or data points) in this program. Be sure to print out and label all of your
results in a clear manner. Also graph your results using V for the x-axis and
the run-time for the y-axis in the following way:
a)
Produce a graph for each algorithm (3
graphs total), putting 6 plots (2 implementations x 3 densities) of 5 points
each onto each graph.
b)
Produce a graph for each density (3
graphs total), putting 6 plots (2 implementations x 3 algorithms) of 5 points
each onto each graph.
Write a short (~2
page) paper describing and analyzing your results. Be sure to indicate your
expectations, your actual results and how the results conformed to your
expectations. If some results were not
clear-cut, speculate as to why. Also speculate
as to how much (if any) overhead would be added if the creation of the graphs
were timed as well.
Notes:
·
You will be using a LOT of memory for
this assignment, so allocate it carefully.
Note that for the adjacency matrix with 800 vertices you will need
640000 locations and if you need to use the 1600 vertex graph you will need
2560000 locations. To manage this memory
effectively you should use a dynamic two-d array for the adjacency matrix and a
dynamic array of lists for the adjacency list.
See handout twod.java for
some help with allocating/de-allocating two-dimensional dynamic arrays in Java.
·
Some of the algorithms may run very
quickly (especially for sparse graphs) and may be difficult to get good timing
results for. Don't worry if not all of
your data points are consistent for the sparse graphs. However, the fact that these algorithms run
too quickly to time should in itself tell you a lot about their run-times.
·
Don't forget the Assignment Information
Sheet! You can download it from my Web
Page.
·
The breath-first search (BFS) and
depth-first search (DFS) algorithms are found on the syllabus along with the algorithms
to represent a graph as an adjacency matrix or an adjacency list. Start with
these BFS and DFS first. We will discuss Prim's
algorithm very soon.
·
If you want to try some extra credit, add
some extra algorithms to your simulation.
Some to try are the Shortest Path algorithm and the connected-components
algorithm.