SlowFish

The second type of fish that the biologists were interested in adding to their simulation moved very slowly or infrequently, so we dubbed it "SlowFish." A slow fish moves so slowly that it only has a 1 in 5 chance of moving out of its current cell into an adjacent cell in any given timestep in the simulation. When it does move, though, it moves like a normal fish; it is equally likely to move forward or to either side, and virtually never turns completely around to swim backwards.

Design Issues

To test whether the fish should move, I knew I would randomly pick a number and compare it to the probability of moving. The first design decision I had to make, though, was whether to put that test in the move method or in the nextLocation method. If I put it in the move method, then 4 out of 5 times it would do nothing. If I put it in the nextLocation method, then 4 out of 5 times it would return the current location. Since it seemed like the test could go in either place, I decided to put it in the lower-level, more specific method, nextLocation.

Having just decided to redefine the nextLocation method, I realized that when the slow fish do move, they choose their next location just as any other fish would. I was thinking that I would have to duplicate that code from Fish in my redefined method in SlowFish (since a redefined method overrides the original from the superclass), when I remembered that it is possible to call the superclass method from within the subclass method. I just needed to call super.nextLocation() within my nextLocation method in SlowFish. This gave me my updated pseudo-code.

  SlowFish Next Location method:
        Get random number
        If random number represents 1 in 5 chance of moving
            Get next location as any normal fish would (super.nextLocation())
        Otherwise,
            Return the current location.

My final design decision was how to determine whether a given slow fish should move. In mathematics, probabilities are represented as real numbers from 0.0 to 1.0, where 0.0 means there is no probability that something will happen and 1.0 means that it will always happen. The probability corresponding to a 1 in 5 chance is the mathematical value 1/5 (or 0.2). Therefore, the test for whether the fish should move or not could be implemented by randomly picking a real number (a double) in the range of 0.0 to 1.0 (using the nextDouble() method from the java.util.Random or edu.kzoo.util.RandNumGenerator classes). I could then compare the random double to the mathematical value 1/5. There is a 1 in 5 chance that the randomly chosen value would be less than 1/5. (Similarly, there would be a 3 in 5 chance that the randomly chosen value would be less than 3/5, or 0.6.)

As I thought about it, I realized I could also represent the probability using integers. I could get a random integer using nextInt(5) and compare the random number to 0 (or any other number between 0 and 4). There would be a 1 in 5 chance of the random number being whichever integer I chose. (Or a 3 in 5 chance of it being less than 3, if that were what I needed.)

Programming Exercise: SlowFish

Testing Random Behavior

Programs with random behavior can be difficult to test. Every time you run the program, you get different results, which makes it difficult to come up with expected results for comparing against actual results. If the program includes probabilistic behavior, like slow fish movement, it is difficult to verify that the probabilities of different behaviors are correct. Just because a slow fish has a 1 in 5 chance of moving doesn't mean that they move exactly 20% of the time.

One technique I tried was to run the program for many steps with a small number of fish, so I could better keep track of the behavior for each one. Each step yielded different results, but the accumulation of results demonstrated that the slow fish were moving approximately as often as expected.

Another technique I tried was to put many slow fish in the grid, and keep track of all of their movements for a smaller number of steps. In this case, approximately 20% of the fish moved in any given time step, which was again what I expected.

Later in the summer I learned to seed the random number generator. This causes the generator to create the same sequence of pseudo-random numbers every time the program is run, leading to predictable results. For example, the fish.dat configuration file specifies the initial location and direction of each fish, but not its color. Once I learned to seed the random number generator, then the initial colors of the fish and their behavior in each timestep were consistent every time I ran the simulation. The benefit of this was that after recording the behavior of one run of the simulation, I could use that as a prediction of expected results for future tests, unless I made code changes that changed the behavior.

Programming Exercise: Testing SlowFish



Alyce Brady, Kalamazoo College