Project 2: Who wants to be a course coordinator?

Due: Tuesday, March 5, before 9:00 pm


Addenda


Objectives

The objective of this programming assignment is for you to become familiar with some of the templated data structures in the C++ Standard Template Library (STL).


Introduction

In this project, you will complete a program to grade an implementation of the Graph class from Project 1. In order to test whether an implementation is correct, we need some way to know how a correct implementation would function. For example, suppose we construct a Graph object with the implementation we are testing and want to determine whether the m_nz, m_ci, and m_re arrays have been populated correctly. It would be nice if we had an implementation of Graph that we knew to be correct; then we could construct the same graph in our correct implementation and just compare the arrays in the the two objects.

We aren't allowed to have two different classes with exactly the same name. So how can we possibly run two versions of the class and compare them? Well, we could give one of them a different name. Or we can just put one of them in a different namespace. Our correct implementation will just be a re-working of the Graph class, contained in a namespace called Baseline:

namespace Baseline { class Graph { public: friend Grader; // Allows Grader class to access private variables // Graph constructor; must give number of vertices Graph(int n); ... remainder of class declarations ... }; }

In addition to being contained in a namespace, there are some other important differences between Baseline::Graph and the original Graph class:

  1. It uses STL vectors instead of C-style arrays and, therefore, does not directly use dynamic memory allocation.
  2. Since it does not use dynamic memory allocation, it does not need a destructor, copy constructor, or assignment operator.
  3. Since vectors automatically resize themselves, you do not need to explicitly expand them in addEdge().
  4. Since the vector container provides an insert() method, you will not have to shift elements of m_nz and m_ci when inserting a new edge.

Once you have implemented Baseline::Graph, you will be able to use it and a test implementation of Graph in the same program. For example:

Graph G(numVert); Baseline::Graph GG(numVert); G.addEdge(1,2,3); GG.addEdge(1,2,3); // etc.

Once you've got Baseline::Graph working and have a version of Graph to test, you're ready to start writing the required tests in the Grader class.


Assignment

For this project, we will start you off with several source files:

First, you need to complete the implementation of Baseline::Graph. The requirements for the methods in Baseline::Graph are the same as in Project 1 and will not be repeated here. You can use test1bg.cpp for basic testing of the class. There is no test2bg.cpp because the main purpose of test2.cpp in Project 1 was to to test the copy constructor and assignment operator, which are not needed for this implementation.

Next, implement the methods of Grader. Most of the work is in implementing the required test functions:

Method Description of tests
testCSRExact() Tests exact correctness of the m_re, m_nz, and m_ci arrays. Since m_nz and m_ci should be ordered by increasing column index, there is a single correct configuration of the arrays. The test should check correctness of the arrays after any edge is inserted.
testCSRUnordered() Tests correctness of the m_re, m_nz, and m_ci arrays, without regard to ordering within each row. That is, if the values for each row are correct but are not ordered by increasing column index, this test should pass.
testNbIterator() Tests that the NbIterator produces the correct set of neighbors for every vertex in the graph.
testEgIterator() Tests that the EgIterator produces a valid listing of the edges of the graph. All edges must be included and none may be repeated.
testExceptions() Tests that an out_of_range exception is thrown for every operations specified to do so in the Project 1 description. Must check if some other exception is thrown, or no exception at all.

Each of these test functions can generate Error objects, defined in Grader.h. Each Error object consists of a point deduction, error id, and error description. Whenever an Error is produced, it is pushed onto a queue, a private variable of the Grader class. Somewhat counter-intuitively, there are error types that correspond to passing a test (i.e. “no error”); this allows success messages to be pushed into the error queue and printed at the end of the test program. The complete list of errors that the test functions can produce is described in errors.txt.

Grader has three methods in addition to the test functions:

Method Description of method
Grader(string name="") The Grader constructor; accepts an optional descriptive name for the object.
printAllErrors() Print all the errors in the error queue and the total point deductions; leaves the queue empty.
resetErrorQueue() Removes all entries from the error queue.

To test your implementation of Grader, you'll need a version of Graph.cpp from Project 1. Your own submission should be sufficient to get started. It is not difficult to modify your Project 1 code to produce specific errors. However, you will be provided with some sample Graph implementations with which to test your code after the final submission deadline for Project 1.


Specifications

Requirement: You may not modify Graph.h or BaselineGraph.h. You may add private helper functions to the Grader class, but you may not change anything else in Grader.h.

Requirement: Your Baseline::Graph class must satisfy all the requirements of Project 1 except those specifically excluded due to the use of vectors rather than C arrays (e.g. no destructor, copy constructor, or assignment operator).

Requirement: You must use at least one STL container class in addition to vector and queue, and the the third container must be used within one of the test methods of Grader. Good candidates for the third container are set or multiset.

Requirement: The testCSRExact() and testCSRUnordered() functions shall test the correctness of the arrays whenever an edge is added to the graph. If at any point, one of the arrays is incorrect, then the implementation fails the test and the appropriate Error shall be pushed onto the queue.

Requirement: No error (identified by the unique error id) shall be pushed into the error queue more than once. Suppose testCSRExact() checks the correctness of m_nz after each call to addEdge() and finds that the array is incorrect after each insertion; the error with id 102 should still only be pushed onto the queue once.

Requirement: Contradictory errors shall not be pushed onto the Error queue. For example, only one of errors 510, 511 and 512 can occur; only one should appear in the queue.

Requirement: “No error” errors (e.g. 100, 200, 300, etc.) shall be pushed onto the queue whenever appropriate.

Requirement: You must use the provided operator<< to output Error objects.


Test Programs

The following programs may be used to test your implementations. These are only basic test programs; it is your responsibility to thoroughly test your programs.

These and all the provided project files are available on GL:

/afs/umbc.edu/users/c/m/cmarron/pub/www/cs341.s19/projects/proj2files/


Implementation Notes


What to Submit

You must submit the following files to the proj2 directory.

If you followed the instructions in the Project Submission page to set up your directories, you can submit your code using this Unix command command:

cp Grader.h Grader.cpp BaselineGraph.cpp ~/cs341proj/proj2/