Home CPSC 220

Simulation

 

Introduction

One particular type of program that lends itself well to using objects is simulation programs. A simulation is a program that models some kind of process or system over time. Simulation programs are very important to many other disciplines.

Some examples of areas that use computer simulation:

Simulations are done by keeping track of several objects, and how they change over time. The objects can possibly interact with each other or outside influences.


 

Example: Disease Simulation

As an example of how we could do a simulation on multiple objects, consider the problem of studying a disease outbreak. The general idea is we can keep track of a large number of virtual people, as they move about. Some people will start out sick, and can pass the disease to those they are near.

Below is a simple program which does just such a simulation. There are a number of parameters which control the simulation as it runs. They are grouped in a class so they can be changed in one place:


// a class which just contains some numbers grouped together
class SimulationParameters {

    static final int POPULATION = 200;
    static final int MOVE_AMOUNT = 2;
    static final int HEAL_DAYS = 10;
    static final int INITIAL_SICK = 10;
    static final double INFECT_DISTANCE = 2.5;
}

To keep track of whether someone is sick or not, we can use an enumeration:


// represents whether a given person is healthy or sick
enum State {
    HEALTHY,
    INFECTED
};

We then can make a Person class for modeling one person in this simulation. They have variables which store their sate and position, and functions which modify them:


class Person {

    // variables used in simulating the person

    private State state;
    private int days_til_healed;
    private double x, y;

    // construct a healthy person, randomly positioned in space
    Person() {
        state = State.HEALTHY;
        Random generator = new Random();
        x = generator.nextInt(100);
        y = generator.nextInt(100);
    }

    // move the person randomly
    void move() {
        Random generator = new Random();

        // getr a random number between 0 and 1
        double val = generator.nextDouble();

        // multiply by twice the move amount - this gets us a value between
        // negative move amount, and positive move amount
        val = val * 2.0 * SimulationParameters.MOVE_AMOUNT;
        val = val - SimulationParameters.MOVE_AMOUNT;

        // move in the x direction by this much
        x += val;

        // do the same thing for y
        double val2 = generator.nextDouble();
        val2 = val2 * 2.0 * SimulationParameters.MOVE_AMOUNT;
        val2 = val2 - SimulationParameters.MOVE_AMOUNT;
        y += val2;

        // don't let them go off the edges
        if (x > 100) {
            x = 100;
        }
        if (y > 100) {
            y = 100;
        }
        if (x < 0) {
            x = 0;
        }
        if (y < 0) {
            y = 0;
        }
    }

    // called after each step in the simulation, if this person is sick,
    // is it time for them to get better yet?
    void checkHeal() {
        if (days_til_healed == 0) {
            state = State.HEALTHY;
        } else {
            days_til_healed--;
        }
    }

    // set this person as infected
    void setInfected() {
        state = State.INFECTED;
        days_til_healed = SimulationParameters.HEAL_DAYS;
    }

    // return the state of this person
    boolean isInfected() {
        return state == State.INFECTED;
    }

    // check if this person has been infected by another person
    void checkInfected(Person others[]) {
        // loop through each other person
        for (int i = 0; i < SimulationParameters.POPULATION; i++) {
            // find the euclidean distance between them
            double distance = Math.sqrt((x - others[i].x) * (x - others[i].x)
                    + (y - others[i].y) * (y - others[i].y));

            // if they are too close
            if (distance < SimulationParameters.INFECT_DISTANCE) {
                // if they're sick and we are not, we are now sick too :(
                if (state == State.HEALTHY && others[i].state == State.INFECTED) {
                    setInfected();
                }
            }
        }
    }
}

Once we have a class to keep track of an individual person, we can create an array of people, and loop through it, performing the simulation over time:


// the main class which runs the simulation
class DiseaseSimulation {

    public static void main(String args[]) {
        // make an array of people
        Person people[] = new Person[SimulationParameters.POPULATION];
        
        // actually create the people
        for (int i = 0; i < SimulationParameters.POPULATION; i++) {
            people[i] = new Person();
        }
        
        // set the first so many to be sick
        for (int i = 0; i < SimulationParameters.INITIAL_SICK; i++) {
            people[i].setInfected();
        }
        
        Scanner in = new Scanner(System.in);
        
        // keep going until the user says no
        boolean cont;
        int day = 1;
        do {
            // go through each person
            for (Person p : people) {
                // move them
                p.move();
                
                // check if they are all better
                p.checkHeal();
                
                // check if they are sick
                p.checkInfected(people);
            }
            
            // count how many people are sick
            int sick = 0;
            for (Person p : people) {
                if (p.isInfected()) {
                    sick++;
                }
            }
            
            // print stats
            System.out.printf("After %d days, %d people are sick and %d people are well\n",
                    day, sick, SimulationParameters.POPULATION - sick);
            
            // move to the next day
            day++;
            
            // check if we want to continue
            System.out.print("Continut (y/n): ");
            cont = in.next().charAt(0) == 'y';
        } while (cont);
    }
}

Some questions we could ask of this simulation:

Copyright © 2024 Ian Finlayson | Licensed under a Creative Commons BY-NC-SA 4.0 License.