Project P12

This is a 75-point project that must be submitted to the Moodle submission page for Project P12 by 11:00 PM on Tuesday, 29 November.

The assignment

Sparse matrices are frequently used in scientific and engineering applications. In the assignment you are to use a linked list to read and print a sparse matrix, which will contain only integers.

The input

There are five types of input commands for this assignment. The first declares the array. It is of the form:
    dcl X[#rows,#cols]
This creates an array with #rows rows and #cols columns. The array is always “named” X. Initially all the values of the array are zero. This command should only appear as the first line of input.

The second command increments a value of the array. It is of the form:
    inc X[row,col]
This causes one to be added to element X[row,col].

The third command prints a value from the array.
    prt X[row,col]
Your program should print something like the following, where val is the value of X[row,col], in response to this command.
    X[row,col] = val

The final two commands print all the non-zero values of a row or column. These values should be printed in the same format used for output of the prt command. The command for printing a row is
    row X[row,*]
and for printing a column is
    col X[*,col]

Getting started

You will be provided with five files to get you on your way for completing this assignment. For you convenience, all five have have been packaged into a single ZIP file.

The first file, main.c, contains the main routine. This code is responsible for parsing the commands and calling the sparse matrix routines. You should not modify this file.

The second file, parsecommand.c, is an ugly little C program that performs the grunt work of parsing the commands used for this program. It has an associated prototype header file, parsecommand.h, which is the third file for this project.

The fourth file, sparcematrix.h, defines the data structures used to represent the sparse matrix along with prototypes for the sparse matrix routines called by main. You must not modify this file.

The sparse matrix is implemented with linked lists for the elements of each row and column. The “control” structure for the sparse matrix is struct sparceMatrix. This structure has fields numRows and numCols that store the dimensions of the matrix. The structure also has fields rows and cols that point to linked lists used to implement the rows and columns.

Each element of these linked lists is a struct sparceElementRect. These structures record the row, column, and value of each non-zero element and contains the threads of the row and column links.

The fifth file, sparcematrix.c, is a framework for completing the five routines needed to implement the assignments.

The first routine, createSparceMatrix, will allocate the struct sparceMatrix and its associated row and column arrays for the linked lists. Initially all the pointers of these arrays will be NULL to indicate that all of the linked lists are “empty.” My createSparceMatrix routine is about 25 lines of code.

The second routine, incrementSparceMatrix, adds one to an element of the matrix. It starts by searching for the element in the appropriate row or column list. Usually, the element hasn’t be created, so it will be necessary to allocate and initialize a struct sparceElementRect. Be sure to place the newly allocated structure in the linked lists for both its row and column. If the element already exists, just add one to its value field. My implementation of incrementSparceMatrix is also about 25 lines of code. Searching for the element uses only 4 lines of code, so most of the work is in allocating the new element.

The third routine printValueSparceMatrix will search for an element that matches its row and column parameter. If a matching element is found, its value field is printed. Otherwise, 0 is printed as the value of the “element”. This one is about 20 lines long.

The remaining two routines printRowSparceMatrix and printColSparceMatrix print all the non-zero elements within a column. As you can imagine, they are very similar. Also, since they don’t have to do any matching, they are relatively simple. Only about a dozen lines of code are required for each.

Getting it done

Learning how to use the debugger would be the best skill for completing this assignment.

If that investment isn’t for you, you will probably need to instrument your code by writing lots of debugging printf’s into your code. Here's an example of one you could use to look at the row array and print which row isn’t empty.

for (i=0; i<M->numRows; ++i) {
  if (M->rows[i] != NULL) {
    printf("Row %d is not empty\n"; i) ;
  }
}

If you are more ambitious, you could print the first element of these non-empty rows.

for (i=0; i<M->numRows; ++i) {
  sparceElementPtr firstOnRow = M->rows[i] ;
  if (firstElementPtr != NULL) {
    printf("Row %d starts with %d\n", i, firstElementPtr->col) ;
  }
}

An alternate tester

If you don’t want to enter those commands and just want a program that calls your routines, you can try using a more automated driver for your main program. This file autotest.c will replace the main.c and parsecommand.c files described above. The problem with using this driver is that you won’t have control over the commands being sent to your program.

If you want to start your programming task with training wheels, you can try use a testing routine that provides a hard-crafted sparse matrix for your main program. This file trainingwheels.c also replaces the main.c and parsecommand.c. However, it is even creates an initial matrix for you.