Assignment 8, due Mar 15

Solutions

Part of the homework for CS:2820, Spring 2019
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

  1. Background: Consider this bit of code that uses class Simulation distributed with the notes for Lecture 22:
    static void tortise( float time, float delay ) {
        Simulation.schedule( time + delay, (float t) -> tortise( t, delay/2 ) );
    }
    

    Assume that the simulation is started with this code:

    Simulation.schedule( 0.0F, (float t) -> tortise( t, 1.0F ) );
    Simulation.run();
    

    a) The code for tortise includes code to call tortise. Explain why, nonetheless, tortise is not recursive. (0.5 points)

    Because tortise does not call tortise, but it does pass a lambda expression containing a call to tortise to Simulation.schedule(). This lambda expression is then used later, by Simulation.run(), to call tortise. The result is that Simulation.run() ends up repeatedly (that is, iteratively) calling tortise.

    b) The simulation program will never terminate, but How long will the simulation run, in simulated time? (0.5 points)

    The simulated time never quite reaches 2. With each step, it advances by half the previous step, with the first step being of length 1, so the series of times is 1 + 1/2 + 1/4 + 1/8 + 1/16...

    The code is easy to test. Combine the following code with the code for class Simulation and run it:

    public class T {
        static void tortise( float time, float delay ) {
            System.out.println( "Time = " + time );
            Simulation.schedule( time + delay, (float t) -> tortise( t, delay/2 ) );
        }
        public static void main( String[] args ) {
            Simulation.schedule( 0.0F, (float t) -> tortise( t, 1.0F ) );
            Simulation.run();
        }
    }
    

    Here are the first few lines of output it produces:

    Time = 0.0
    Time = 1.0
    Time = 1.5
    Time = 1.75
    Time = 1.875
    Time = 1.9375
    Time = 1.96875
    Time = 1.984375
    

  2. Background: In lecture Monday, two alternative were given for the call to enter a road at the current time within the body of the method that creates a new vehicle in a Source intersection.

    One of these schedules a new event at the current time using our simulation framework, the other just does the job, ignoring the simulation framework. This line of code (either version) was followed by code that could schedule other events and change some of the state variables of the simulation, depending on the values of those variables.

    a) What is the difference between these, in terms of the order in which different bits of code are executed. (0.5 points)

    In the first case, this.pickOutgoing()... will be executed before the code schedules other events or changes any state variables.

    In the second case, the code will schedule other events and change state variables before returning to simulation.run() which will then call this.pickOutgoing()...

    b) Why is is that (in the example given) either version of the code will work? (Hint: Think about how pickOutgoing() or enter() could interact with other code, and explain why they are unlikely to do so.) (0.5 points)

    Because the state variables changed or tested will be variables of this intersection, and pickOutgoing() has no side effects on this intersection, and enter() will inspect and possibly modify the state of some road. In summary, if two pieces of code inspect and possibly modify non-overlapping sets of variables, the order in which they are done does not matter.

    Note that both entering a road and leaving an intersection could schedule other events. If these events are scheduled at the same future times, the order in which they are simulated could change, and this could change the output of the simulation. Because we have declared that simultaneous events can be simulated in either order, those two simulation results are both legal even though they differ.

  3. Background: Consider this bit of code, using class java.util.Random:
    Random r = new Random();
    while (true) {
        int a = new Random().nextInt();
        int b = new Random(1).nextInt();
        int c = r.nextInt();
        System.out.println( "" + a +"\t"+ b +"\t"+ c );
    }
    

    a) Which sequence of values (a, b or c) is actually a correct use of Random (only one is). (0.5 points)

    The sequence of values for c is a correct use of class Random.

    b) Explain why one sequence is completely and obviously non-random. (0.5 points)

    The sequence of values for b will all be equal because each of the new Random objects was given the same seed, 1, used exactly once, and then discarded.