Programming Assignment

Due:

Please make sure you adhere to the policies on academic honesty.

Please see the general programming webpage for details about the programming environment for this course, and specifically for directions in how to submit your programming assignment electronically.

The files you need for this assignment can be downloaded here.


Contents:

  • Overview
  • The Driver
  • Your Tasks
  • Readme File and Experiments
  • Files you will need
  • Files to Submit
  • Accessing bits of a long
  • Extra Credit
  • Overview

    Our goal in this assignment is to be able to compare the relative efficiency of radix-sort versus quick-sort on a variety of input scenarios involving (long) integer keys in a specified range. We will ask you to run experiments measuring the system time used for these methods. Note that the experimental phase will take significant time, so please plan on developing your code well ahead of the submission deadline.

    For quick-sort, we will use an implementation provided by our text. For radix-sort, we will ask you to write the implementation based on the method outlined in Chapter 10.5 of the text, using an underlying stable bucket-sort.

    Radix-sort is described as a lexicographical sort of keys which are d-tuples, such as (k1, k2, k3, ..., kd). In class, we discussed how such a sort can be used on integral keys by breaking an original integer into digits. An example involved using digits base 10, where we considered separately the ones digit, the tens digits, the hundreds digits, the thousands digits, etc. Though humans are trained very well to work with decimal notation, this technique can be used with bases other than 10. In particular, computers are much more efficient in dealing with numbers represented using powers of two.

    For this assignment, you will write a procedure which implements radix sort by representing numbers using base 2b for some parameter b. That is, each digit is comprised of b bits and thus has value between [0,2b-1]. As an example, the decimal number 2471 would be stored in binary as 100110100111, because

    displaymath83

    Alternatively, we can view the binary number considering four bits at a time as a digit, in which case we get a hexadecimal (base 16) representation,

    displaymath87

    The key parameters for the method are the number of bits to consider per digit, the overall number of bits which make up the full key, and the number of keys which are to be sorted.

    The Driver

    The driver for this program will take all of its input from command line arguments. In particular, you will need to run the program with three command line arguments, specified in this order:

    The driver will prepare an experiment by storing n randomly chosen long's from the range tex2html_wrap_inline103 in an array. Then it will call the routine
    Radix.sort(long A[ ], int n, int m, int b)
    which you are to write in the file Radix.java. Please note that this routine has no return value. Instead, the driver maintains its own reference to array A, and it expects that your routine places the sorted results into this very same array. If you were to place results in a newly constructed array, the driver would not be able to see those results.

    You will want to imagine breaking each key into tex2html_wrap_inline105 digits, where each digit is comprised of b bits and thus has value between tex2html_wrap_inline77 . When comparing to the book's notation, we have that tex2html_wrap_inline111 for each bucket sort, and tex2html_wrap_inline113 is the number of digits used in representing each key and thus the number of passes of bucket sort.

    As we have done in the past, there is an optional fourth argument, which is the seed for the random number generator, allowing you to repeat experiments while debugging.

    Your Task

    Your task is to understand and correctly implement the radix-sort method. Getting a correct implementation is indeed necessary. However there is more to this assignment. We ask that you perform experiments comparing the running time of your method versus quick-sort on a variety of input settings. As the name ``quick-sort'' suggests, that method is a reasonably quick sorting method. You might have to work very hard to get your sorting method to be competitive with quick-sort. You might also work very hard and still end up losing to quick-sort on many settings. Do the best that you can.

    Consider whether there are simple ways to clean-up your code. Consider whether there are major design decisions which effect the overall efficiency. You will want to concern yourself not only with the number of instructions you need, but also with the amount of memory which your program uses. The reason for this is three-fold. Eventually, you may run out of memory on large enough inputs. Even if you do not run out, as you use more and more memory this taxes Java's memory management system and the overall computer system, resulting in an overall slower running time. Finally, if you choose to use data structures which require more memory, this generally means you also will have to execute more operations to initialize and maintain the information stored in that memory. So often reducing the memory to the bare minimum structures helps you reduce unnecessary time spent maintaining the structures.

    Readme File and Experiments

    Your readme file should contain the results of the following experiments, reporting the running times for all settings. Additionally, your readme file should include a paragraph or two in which you interpret the significance of your experimental results.

    For the experiments, there are three parameters which we want you to vary: n, m, b. Please structure your experiments as follows.

    Set m=8 and test your program as follows:

    tabular23

    If you have trouble with time or memory for the largest values of n, so be it; report as many results as possible. Now create a new version of the above table including a column b=16, and report experiment results for values m=16, m=32, m=48.

    As you might notice there are a total of almost 140 different running times you are asked to report. Collecting such data will undoubtedly take a significant amount of your time even after your program is implemented. You should try, as best possible, to run all of the experiments on the same machine, under the same conditions.

    There are two options for gathering this data. One is to sit in front of the computer for an hour or two, running the driver over-and-over by hand with different parameters. The driver relies on a routine
    Experiment.doExperiment(long A[ ], int n, int m, int b, long seed)
    which prepares the array of random values, starts a timer, and then calls your sort. The other option is to write yourself your own driver which has loops to vary the parameters in calling Experiment.doExperiment. Please note that the array sent to this routine must be pre-constructed to have length as long as the maximum value of n you will be using in your tests. (if you instead kept allocating memory for a new array for each such experiment, your own driver will start taxing the memory system and this in turn might adversely effect the timings of the latter experiments).

    Armed with such a driver, you can start it running to gather data and then go do something else. If you do create such a driver, you do not need to submit it - it is purely for your own benefit in gathering results.

    Files you will Need

    The files you need for this assignment can be downloaded here.

    We will provide you with the file Experiment.java which contains the driver. We will also provide you with a simple template file Radix.java which is the file you must modify and resubmit.

    Files to Submit

    You should submit the files: readme and Radix.java. If you choose to define any additional classes, please submit those files too.

    Accessing bits of a long

    One technical key in the implementation will be your ability to pull out a particular ``digit'' from a key when working base tex2html_wrap_inline71 . We will make it easy on you and tell you an efficient way to do this in Java. To be specific, let us assume that you have a long ``value'', and that you are interested in finding the tex2html_wrap_inline159 least-significant digit of that value, where each digit consists of b bits. That is, j=0 will refer to the rightmost digit, j=1 to the second from the right, and so on. This calculation can be accomplished as follows in Java,

    int digit = (int) ((value>>(b*j)) & ((1L<<b) - 1));

    For those interested in understanding why this line does what it does, we will explain below. For those who are not interested, there is no need to read any further. You might first think about how to accomplish this in decimal notation. If you have a value ``x'' and want to know the seventh digit from the right (i.e. the millions digit), how can you calculate this? One way is by using the proper combination of division and modulus operations. You can take the original value x, divide it by 1000000, throwing away the remainder. At this point, the digit you want is the least significant digit of that result. You can calculate that by taking mod 10. We will use the same idea when working in base tex2html_wrap_inline71 . You can get the tex2html_wrap_inline159 least-significant digit of a value by calculating the expression:

    displaymath171

    However, we can take great advantage of the fact that computers offer efficient ways of dealing with numbers represented using powers of two. Although this may be new to many of you, Java offers several operators which allow you to view and modify a number by means of its binary representation. A list of these operators is given on page 21 of Chapter 1.3 of the text, and other Java reference books may contain more information. We will not repeat the information which is there; instead we will give a few of our favorite examples and tips.

    Extra Credit (1 point)

    Really wow me with your efficiency! Get your radix-sort to beat quick-sort for most settings. This will require a great deal of streamlining, but it is possible.

    Hint: Most important will be the time and space efficiency of your choice of the bucket implementation. Think back to Programming Assignment  for some ideas.


    Last modified: 26 November 2002