CS 222   Winter 1999,  Instructor:  Jeffrey Horn

HOMEWORK 3:  BINARY SEARCH
 
Handed out/Assigned: Friday, February 19, 1999
Due: Tuesday, March 9, 1999

OVERALL:  The problem setting is as described in class:  you are to maintain a history of all binary chromosomes seen so far.  For this assignment, you don't have to worry about inserting into the array, or sorting it, or deleting from it.  You just have to implement the "member" methods, using binary search.

WHAT TO HAND IN:  Hand-in the code (email me the subdirectory in your Unix account, to jhorn@nmu.edu).  And DO comment!  (I always find it easier to go back and add comments later, but whatever works for you.  See my style of commenting.  At the very least, comment modules such as classes, methods, and functions, that you write or modify.)

PURPOSE:  Learn binary search algorithm, and more C++ experience!

 SPECIFICS:  I have written most pieces for you.  In particular, I have written the classes Individual and SortedArray, and also a main that will read in a group of chromosomes and then prompt the console user to test the array of chromosomes.  The code below works; that is, it compiles under the gnu C++ compiler on ga and on Euclid, and runs.  Use "g++ main.cc".  If no compiler errors are generated (warnings should not stop the compilation, and you might get some of those!), the compiler will leave the executable in a file called "a.out" in the same directory in which you ran g++.  You should then be able to run your executable with "a.out", or if you have a different shell setting than I have, you might have to type "./a.out" to force your Unix shell to look in the current directory for a.out!

The code is split up among five files:  main.cc, individual.cc, sortedarray.cc, individual.h, and sortedarray.h.  Also, you will need the file "input", which if you edit with Pico you will see contains the 37 or so bit strings to be input as chromosomes (this is done for you).  You may edit the input file.  Just be careful to keep 8 bits per line, no spaces, and a carriage return at the end of every line but the last.

Let's limit ourselves to 8-bit chromosomes for now.  Furthermore, let's assume an ordering on the 256 possible strings by interpreting them as binary coded integers, with the most significant bit on the left hand side.  Thus 00000000 -> 0 (base 10), 00000011 -> 3 (base 10), 11000000 -> 192 (base 10) etc.  (You can view this a lexicographic sort also.)

THE CODE:  (you can go directly to the files by clicking here)

 Here is the definition for an individual, in "individual.h":
 

class Individual{

      private:

      protected:

      public:

         Individual() {};                     // Constructor.  nothing here for now.
         boolean chromosome[CHROMLENGTH];     // Chrom is a string of true, false.
         int generation_first_seen;           // useful field for later use.
         float fitness;                       // Each chromosome has a fitness.
         boolean equal(Individual other);     // Compare other chromosome to oneself.
         boolean greater(Individual other);   // Compare other chromosome to oneself.
         void printchrom();                   // Print chromosome to console.

};

Note how an individual contains not only the chromosome (boolean array) but also methods to print the chromosome, and methods to compare itself to other individuals ("equal" and "greater").  The file "individual.cc"  contains the implementations for those methods.

Similary, the file "sortedarray.h"  contains the interface for the class sortedarray (of individuals), while "sortedarray.cc contains implementations for those methods.

The file "main.cc" creates an object (Pool) of class sortedarray, while "input" contains the actual chromosomes to be loaded into the sortedarray upon creation.
 

WHAT TO DO:

(0)  Download all six of these files into your own directory.

(I)  Rewrite the "member" and "IndexOf" methods of the SortedArray class so that they implement a binary search of the array of individuals, rather than the linear search they use now.  You can assume the array is sorted!  Test your code  (I will!)  I suggest you leave member and IndexOf intact, and write two new methods with slightly different names.  You might be able to use the old methods in your testing.

(II)  Implement a new method for SortedArray, called "printFirst()"  which simply prints the chromosome of the first individual in the array, assuming there is one.

(III)  Add code to count the number of chromosome comparisons made during a "member" check or "where" check.  In other words, count the number of times "individual.greater" or "individual.equal" are called (i.e., both count as comparisons).   Make methods that print this count (e.g., maybe a different version of "member", like "count_member", that does the member check and also prints the count.  There are many ways to do this.  Think about where is the most logical place to put the counter code.  Which object should track this?  After you get this working, find an example to show that your binary search is faster than the linear search (i.e., give me a chromosome to search for, then the counts from both binary search and linear search).  EXTRA CREDIT:  find an example where the linear search is faster!  (and give the counts, so we can see how MUCH faster it is)

(IV)  What is the run-time complexity of the method "sortedarray::printall()"?  Just give Big Oh notation, and assume two measures of input size:  N (the number of chromosomes in the array) and L, the length of the chromosomes in bits.  In our example input file, N=37 and L=8.  As a basic computer operation, count each iteration through any loop.