 |
Birdflu Simulator in Java
Short introduction to inheritige, generics and epidemics
The world is crazy about bird flu. The birds are approaching Europe, and
Bush want to bring in the Army.
However, apparently all you have to do,
to protect yourself, is wash your hands,
but what does it all have to do with Java?
|
While reading the latest about the avian influenza craze, it occurred to me that
this could provide a half decent Java example on how to solve some common object oriented
programming issues. More specifically, I had a simulator in mind, which
would play out a more or less realistic scenario of a spreading epidemic (probably less realistic).
To grasp the concepts, it is perhaps easiest to look at the basic entities
in the small application of this example. They include the classes
Bird, Human, Virus and Location. The
Viruses can infect the hosts of type Birds and Humans, and these hosts are
at a certain Location. Now the details are down to some design decisions.
|
|
Given that the classes Bird and Human will have at least some common features
related to the infecting Virus, should we have a common super class, or
let them just implement an interface?
If a common super class is chosen, it will have to be an abstract entity,
since traversing the complete hieracry of animals from birds to humans will
probably not be useful for the application. On the other hand, an interface
defining the basic actions of a virus host can be more straight forward, and
also hopefully more general for any future implementations. However, the
interface gives no common implementation, which could be useful in some
cases. The compromise: an interface, Host, with an abstract implementation,
AbstractHost, which is sub-classed by Bird and Human.
The other main classes include Virus and Location. Since we might want
to have different implementation of Viruses spreading, it could be
beneficial to create this as an interface, which is implemented by a class,
say Flu. As for Location, it should only include some simple functions:
spreading the Virus amongst the Hosts it holds, and possibly moving
Hosts between the Locations.
|
|
The algorithm for the simulation is kept fairly simple in this example: In
a turn based fashion the hosts, Birds and Humans, may move between the
Locations and then the virus has the potential to spread amongst the hosts
at each Location.
private void moveHosts(Location location) {
//how many move attempts do we get
double noHosts = location.hosts.size();
int moveAttempts = (int)(noHosts*MOVE_RATIO);
//Loops the given number of attempts, and for each turn
//select a random Host. With the given probability of
//migration, move to a random Location
for (int i = 0; i < moveAttempts; i++) {
//get random host to move
Host host = (Host)Location.getRandomObject(location.hosts);
//see if we'll move this host
if(Math.random() < MIGRATION_PROBABILITY) {
//get a random destination
Location dest = getRandomLocation(locations, location);
//move the host
location.remove(host);
dest.addHost(host);
}
}
}
Since there seems to be different probabilities for the virus so spread from bird to bird,
bird to a human and human to human, each type of host class implements the method transmitProbability
which return the probability of the given instance being infected. The method take source host, from which the
virus will spread, and check for its type, which in turn decides with what probability the virus will spread.
In this example, only static numbers are returned.
The probability of infection is compared to a random number, and infection is successful if the random number is
lower than the return probability from the host. The remaining bit of code clones the virus and injects it into
the new host. (The native Java method clone() turns out to be very appropriate here...)
double probability = host.transmitProbability(this.host);
if (Math.random() < probability) {
// clone this virus
Flu clone = null;
clone = (Flu) this.clone();
// infect the given host
host.addVirus(clone);
clone.host = host;
}
|
|
Now, all that remains is the actual code. The eight classes included in the project can be downloaded below.
To run the simulation, just start the main class FluSimulator. You might also want to play around with the
variables at the top of this class, which controls initial population, number of iterations to run, and
probability of moving one entity to a new location.
|
|
|
 |