bhumi: a simple, extensible, agent-based-modeling...

22
Bhumi: A simple, extensible, agent-based-modeling framework Vivin Suresh Paliath Arizona State University [email protected] Abstract Agent-based models belong to a class of computational models and are used to model dynamic interactions and actions using autonomous agents in an attempt to explore, examine, re-create, or predict the emergence of complex phenomena. Agent-based models can be created using specialized software or through programming-language frameworks. For the Objective-C language, the most- popular framework is Swarm, which was originally written for GNUstep. Unfortunately, the richest Objective-C ecosystem today is on OS X and iOS and Swarm has not been reliably ported to both environments. In this paper, I present a very simple agent-based-modeling framework written in Objective-C, which performs well on the OS X and iOS environments. This provides the possibility of creating agent-based models that can run on OS X, as well as iOS devices like the iPhone and the iPad. 1. Introduction Agent-based modeling has its roots in the desire to predict and explain the emergent and complex behavior that is observed in non-linear and dynamic systems. Agent-based modeling is extensively used to study and predict emergent and complex behavior in such disparate fields as economics, epidemiology, and sociology. The models that are described in this areas are essentially non-linear with a large number of variables and therefore manual calculation is prohibitive. To address these issues, computers are used along with specialized software to simulate these models. While there are numerous agent-based modeling platforms and software, in this paper I will be focusing on an alternative to Swarm, which is an agent-based- modeling framework that is written in the Objective-C programming language. Models created in Swarm are written in the Objective-C programming-language as well. Swarm was created in 1994 at the Santa Fe Institute, and was the first re-usable software tool for agent-based modeling[1]. The framework was specifically designed for artificial-life applications. Swarm was created before Java was viable as a general-purpose programming language, and hence was written in Objective-C. With the rise of Java as a popular general-purpose programming-language, a Swarm clone called Repast was created at the University of Chicago. The use of the Java programming-language made Repast much more attractive due to the language's rich and thriving ecosystem. As a result, the Swarm environment suffered and has not seen that much development over the last decade. Coupled with the relative lack of interest in the GNUstep platform (which Swarm was originally developed for) in comparison to the OS X and iOS platform, development using the Swarm platform has slowed down. 2. Problem Statement The most-viable platforms for Objective-C development today are OS X and iOS, with the latter seeing the most growth. Furthermore, with the increasing usage of mobile devices and the corresponding increase in their processing power, mobile devices also present a viable platform that can be used for agent-based modeling. Swarm does not satisfy these requirements due to its GNUstep heritage and the difficulty in getting it to work acceptably on OS X. Our problem statement therefore involves the creation of a simple agent-based-modeling framework in Objective-C that can be used to create models that can run in both the OS X and iOS environments. 3. Background The first inklings of the agent-based-modeling concept can be seen in such discoveries as Donald Hebb's Cell Assembly, and the Blind Watchmaking in Darwinian Evolution[2]. Both discoveries attempt to explain complex and emergent phenomena based on a few simple rules and assumptions. In the case of Donald Hebb's Cell Assembly, the idea was that individual neurons acting in concert bring about the emergent phenomena of associative learning, whereas

Upload: others

Post on 25-Jun-2020

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

Bhumi: A simple, extensible, agent-based-modeling framework

Vivin Suresh PaliathArizona State [email protected]

Abstract

Agent-based models belong to a class of computational models and are used to model dynamic interactions and actions using autonomous agents in an attempt to explore, examine, re-create, or predict the emergence of complex phenomena. Agent-based models can be created using specialized software or through programming-language frameworks. For the Objective-C language, the most-popular framework is Swarm, which was originally written for GNUstep. Unfortunately, the richest Objective-C ecosystem today is on OS X and iOS and Swarm has not been reliably ported to both environments. In this paper, I present a very simple agent-based-modeling framework written in Objective-C, which performs well on the OS X and iOS environments. This provides the possibility of creating agent-based models that can run on OS X, as well as iOS devices like the iPhone and the iPad.

1. Introduction

Agent-based modeling has its roots in the desire to predict and explain the emergent and complex behavior that is observed in non-linear and dynamic systems. Agent-based modeling is extensively used to study and predict emergent and complex behavior in such disparate fields as economics, epidemiology, and sociology. The models that are described in this areas are essentially non-linear with a large number of variables and therefore manual calculation is prohibitive. To address these issues, computers are used along with specialized software to simulate these models.

While there are numerous agent-based modeling platforms and software, in this paper I will be focusing on an alternative to Swarm, which is an agent-based-modeling framework that is written in the Objective-C programming language. Models created in Swarm are written in the Objective-C programming-language as well. Swarm was created in 1994 at the Santa Fe Institute, and was the first re-usable software tool for agent-based modeling[1]. The framework was

specifically designed for artificial-life applications. Swarm was created before Java was viable as a general-purpose programming language, and hence was written in Objective-C. With the rise of Java as a popular general-purpose programming-language, a Swarm clone called Repast was created at the University of Chicago. The use of the Java programming-language made Repast much more attractive due to the language's rich and thriving ecosystem. As a result, the Swarm environment suffered and has not seen that much development over the last decade. Coupled with the relative lack of interest in the GNUstep platform (which Swarm was originally developed for) in comparison to the OS X and iOS platform, development using the Swarm platform has slowed down.

2. Problem Statement

The most-viable platforms for Objective-C development today are OS X and iOS, with the latter seeing the most growth. Furthermore, with the increasing usage of mobile devices and the corresponding increase in their processing power, mobile devices also present a viable platform that can be used for agent-based modeling. Swarm does not satisfy these requirements due to its GNUstep heritage and the difficulty in getting it to work acceptably on OS X. Our problem statement therefore involves the creation of a simple agent-based-modeling framework in Objective-C that can be used to create models that can run in both the OS X and iOS environments.

3. Background

The first inklings of the agent-based-modeling concept can be seen in such discoveries as Donald Hebb's Cell Assembly, and the Blind Watchmaking in Darwinian Evolution[2]. Both discoveries attempt to explain complex and emergent phenomena based on a few simple rules and assumptions. In the case of Donald Hebb's Cell Assembly, the idea was that individual neurons acting in concert bring about the emergent phenomena of associative learning, whereas

Page 2: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

in the case of Darwinian Evolution, complex and specialized organisms arose via individual variation and natural selection. Although the scientists of the time could observe and theorize about emergent behavior in these systems, they did not have the tools to model these systems, and as a result could not fully study and understand them. This is due to the fact that the described systems were non-linear in nature and the calculations involved were prohibitive; a classic example is the Three Body Problem in classical mechanics, where it is shown that one cannot mathematically determine the future state of three bodies even if one is provided the initial conditions.

The situation changed during the latter half of the 1930's due to certain theoretical advancements. The first advancement was Alan Turing's definition of the Turing Machine, which showed that it was possible to duplicate mathematical processes via machinery. This was a remarkable discovery in of itself, because it showed that machines are capable of representing mathematical systems. The second advancement was the development of the Church-Turing hypothesis by Alan Turing and Alonzo Church in 1939, which showed that a machine could not only duplicate mathematical processes and systems, but it could also duplicate natural systems[2]. Another theoretical advancement was made towards the end of the 1940's when John von Neumann, in lectures delivered in 1948 and 1949, put forward a model of a kinematic, self-reproducing automaton as a thought-experiment[3]. This machine operated with very complicated rules, on a rectangular grid. He later developed an even-more abstract model that was based on self-replicating cellular-automata[4].

Building on von Neumann's idea of a hypothetical self-replicating machine, British mathematician John Horton Conway presented a drastically-simplified model of a cellular automaton, called Conway's Game of Life, that also operated on a rectangular grid. From a theoretical standpoint, his model was interesting because it was essentially a universal Turing machine; anything that can be computed algorithmically, can be computed with Conway's Game of Life[5]. It also demonstrated that starting with a few simple rules, one was able to produce complex and often chaotic output. Conway's idea was also prescient, since he presented it in 1970, when inexpensive minicomputers were just being released into the market, and the rules of Conway's Game of Life were simple enough to be modeled on these microcomputers. This was, perhaps, the first sign that the complex non-linear models described decades ago, could be simulated on computers.

The most important result from Conway's discovery was the opening up of an entirely-new field of mathematical research known as cellular automata. Once it was discovered that cellular automata could

lead to emergent and complex behavior, scientists from various fields such as ecology, economics, and epidemiology started using cellular automata to create models of non-linear systems that were originally too hard to study. Initially, these software models were extremely domain-specific. That is, the software would simulate one type of model only, with perhaps a few variables that could be changed by the user. One example is the Boids artificial-life program, developed by Craig Reynolds in 1986, which simulated the behavior of flocking birds[6]. The problem with this sort of approach is two-fold: it involves a lot of duplication of work and it is also tedious. Anyone who desired to create a new model had to create one from scratch, and this involved implementing basic boiler-plate programming-code that had little to do with the model itself. Scientists would spend an inordinate amount of time setting up the foundation and structure of the environment before they could even create and simulate their model. This was especially difficult for scientists who previously didn't have experience with computer programming and who now had to deal with moderately-difficult programming-concepts such as memory management and concurrency. The net effect was that the focus was shifted from studying the model, into creating the foundation and environment that the model could then be run on. In simple terms, creating an agent-based software-model was difficult unless you knew how to program a computer.

Swarm was created by the Santa Fe Institute in 1994 to address these very concerns[1]. It was the first general-purpose framework, created specifically for agent-based modeling. Swarm's appeal was that it helped the scientists who wished to create agent-based models, focus on the model itself rather than focusing on the environment required to simulate the model. The end result was that Swarm created a new paradigm which focused on the creation of generic frameworks that supported the creation of agent-based models.

4. A Survey of Swarm

Swarm was a tremendous success after it was created, and a very strong and active community formed around the framework. For a time, it was a very popular tool amongst scientists who wished to create agent-based models. While it was still advantageous to know how to program a computer, Swarm alleviated some of the difficulties because scientists only needed to concentrate on programming the model. However, over the last two decades, Swarm has become less viable as an agent-based-modeling framework. This is due to two reasons. The first reason was the emergence of RePast in 2001, which was initially created as a Swarm clone in Java, due to the growing popularity of Java as a general-purpose

Page 3: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

programming-language[7]. Java was relatively easier to program in, compared to Objective-C, especially due to its garbage-collection feature, which freed the programmer from having to perform manual memory-management. Another advantage was that Java was designed to be platform agnostic, and therefore a model that was written in RePast could be executed on any environment, as long as there was a Java Virtual Machine for that environment. Furthermore, the Java ecosystem was growing at a fast place and became extremely rich, providing a large variety of tools, libraries, and frameworks for people who wished to create agent-based models. The second reason is the emergence and adoption of the iOS platform, which is the mobile platform that Apple uses for the iPhone and the iPad. There was not much interest in using Objective-C as a programming-language until the advent of the iOS platform, due to the fact that the only real use for Objective-C was to create software for the Macintosh operating system, which, though it was used by a devoted community, did not have the same reach as its dominant competitor, Windows. However, the release of the iOS platform, which coincided with the release of the iPhone, created a new demand for powerful mobile-software. Compared to its competition, it was far easier to develop software for iOS in Objective-C. Developers had an added incentive to develop for the iOS platform since they could now sell their software in Apple's AppStore and thus earn money.

Foreseeing a resurgence of interest in the Objective-C programming-language, Apple made significant improvements and additions which culminated in Objective-C 2.0, which was released in October 2007. These improvements featured such improvements as garbage collection, and language constructs designed to make concurrent-programming easier. In version 10.8 of OS X, Apple introduced Automatic Reference Counting, which could be used in place of manual reference counting. This shifted the task of performing memory management to the compiler, which lessened the burden on developers.

Unfortunately, some of these modern changes have not made their way into Swarm due to the fact that Swarm was originally developed in GNUstep (a free-software implementation of Cocoa Objective-C libraries). This is because the GNUstep version of Objective-C lags behinds Apple's implementation. Furthermore, the GNUstep ecosystem is sparse, offering very little documentation, few tools, and very limited IDEs. In contrast, the Objective-C environment on OS X is extremely rich, featuring a mature toolset, a powerful IDE (Xcode) and a strong community. Another problem is that Swarm is the only agent-based-modeling framework that is written in the Objective-C language, and as a result there aren't any newer alternatives.

Due to these issues, Swarm is not as attractive a platform as it once was. One obvious solution would be to port Swarm to OS X; this has been done, but the effort is largely experimental and not without issues. It is still difficult to create a working model in OSX and due to the port being experimental, there is not enough documentation surrounding the effort. But even if Swarm was ported to OS X successfully, there are still other issues with the framework. These include a steep learning-curve, out-of-date and incomplete documentation, and sample code that isn't easily built. Furthermore, development on Swarm seems to have slowed, with the last production-version of the framework having been released in 2005.

Another aspect to consider is the rise of mobile platforms. With their increasing processing-power, they present a viable platform for agent-based modeling. Currently there are no agent-based modeling-frameworks that work on mobile platforms like iOS or Android. Swarm, while it has been ported to OS X has not been ported to iOS and there doesn't seem to be an effort to do so.

To address these issues, I will describe a simple framework in this paper, that satisfies these two constraints. The framework (called Bhumi; Sanskrit for “world”) is written in Objective-C using modern features of the language, and can easily be used on OS X as well as iOS. While it is still a preliminary effort (i.e., proof of concept) and doesn't have complete feature-parity with Swarm, I believe that with continued research, more work, and improvements, it could turn into a viable alternative.

5. Introduction to Bhumi

Bhumi has two main components: a world and a bug. The world is represented by one or more toroidal two-dimensional grids. Multiple grids are referred to as layers and the dimensions of all layers are identical. A bug in Bhumi is essentially an agent. It can be placed at specific coordinates in a specific layer. Creating a model usually involves defining one or more bugs with specific behavior. Bugs can query and modify their own state, the state of the world, and other bugs.

When a simulation starts, the world runs for a set number of iterations. During each iteration, each bug is, in random order, given a chance to interact with the world. The world running by itself is not very useful since one needs to query the state of the world so that one can observe the progression of the simulation. We can do is using interceptors. When creating and defining a world, the user can specify an interceptor which can query the state of the world. Typical uses of an interceptor include simple logging to a text file, or rendering the state of the world into a graphical form. This approach ensures that simulation

Page 4: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

and observation is not tightly-coupled. As a result, one only needs to create one model and different interceptors to observe the simulation in different ways.

Using these three simple components, a user can craft different types of models, and then simulate and observe them. A typical Bhumi model consists of one or more bugs and an interceptor which is used to report on the results of the simulations.

6. Design Overview

Bhumi has a very simple design. As mentioned in previously, there are three main components: the world, the bug, and the interceptor. The first two components deal with simulation, whereas the last one deals with observation. The components aren't useful by themselves, however. They simply provide a foundation upon which a user can create their own models:

A. World

The world is represented by a World class, and is where the simulation takes place. When a World instance is created, the user can provide the number of rows and columns for the grid, the number of iterations the simulation is supposed to run, a “snapshot interval” that specified when the interceptor should be called, and an instance of the interceptor itself.

The World class has one primary data-structure that represents layered grids. This data structure is a dictionary that maps a layer name to a sparse two-dimensional array that represents the grid for that layer. The decision to use sparse two-dimensional arrays was made to address memory concerns, especially on mobile devices.

The World class also provides methods for users to add, remove, and move bugs. In addition, it also has state-inspection methods that enable users to check if grid locations are occupied, or to get references to bugs that are in a specific location.

The life-cycle of a simulation is controlled by the start and step methods of the World class. The start method starts the simulation and will advance the simulation by one iteration. To advance through subsequent iterations, the step method needs to be called. This is usually done inside the interceptor. The reason for this decision is to address concurrency issues if the simulation is running in a separate thread. For example, consider the situation where the simulation is being rendered on-screen. Graphical updates usually happen on the main thread. For this reason, it is advisable to run expensive operations on a background thread to stop the user interface from being non-responsive. The expensive operation in this

case would be the simulation itself and the code that renders the simulation on-screen would be the interceptor. Since both the simulation and the interceptor have access to the same resource (the world), we will see concurrency issues if the simulation is proceeding while it is being rendered. The step method addresses this very issue. Once the interceptor is done performing its task, it can call the step method to let the world know that it can proceed to the next iteration of simulation.

B. Bug

A bug is represented by a Bug class and. The Bug by itself is not very useful. It is an abstract class that serves as a template for concrete Bug-implementations; the user will need to subclass Bug for it to be useful. The Bug has a few basic attributes such as an X and a Y coordinate that represents its position on the grid, a layer that represents the layer of the World instance that the bug belongs to, a reference to the World instance that the bug is part of, a name, and a flag that says whether the Bug is alive or not. Concrete implementations of Bug usually will have other attributes. The Bug provides methods that allow users to set its position or change its state (from “alive” to “dead”). The Bug also has an important method called act, and it is in this method where the Bug's behavior is described. As a result, this is more-or-less where the model is described. More complicated models can involve different types of Bugs, which is why one type of bug can sometimes only represent part of the model.

Keeping the Bug separate from the world is a good design-decision overall due to reasons of separation of concern and code-reuse. Since the behavior of the agent is abstracted and encapsulated inside the concrete implementation there are no side-effects or interactions with other parts of the framework. Furthermore, a concrete implementation, once defined, can be used in any other model. Hence, once you create a specific type of Bug, you can easily re-use it in another model, if you so chose.

C. Interceptor

An interceptor object is how a user is able to observe the state of the simulation. There isn't a specific class that represents an interceptor. Rather, there is a protocol with an intercept method which a world instance calls (passing in itself as a reference). This way, a class only needs to implement the interceptor protocol for it to be able to gain access to the state of the world.

Separating the observation of the model from the simulation gives us many advantages. The first advantage is, of course, separation of concern.

Page 5: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

Running the simulation and observing the simulation are separate tasks and performing observation inside the World class would have led to a tight coupling between the two tasks. The second advantage is that observation of the simulation has now been abstracted and encapsulated inside another class. This means that the way you observe and record data from a simulation can easily be swapped out depending on what kind of data you want to record, and how you want to record it. In fact, this is what makes us able to run Bhumi on OS X as well as iOS. Once you create a model, all you have to do is to create different interceptors for it. One interceptor can handle rendering for OS X, whereas the other interceptor can handle rendering for iOS. This way the Bhumi model can work on a mobile or a desktop environment (Figure 11 and Figure 14).

7. Sample models in Bhumi

To adequately display Bhumi's capabilities, I will go over three simple-models that have been created using the framework.

A. Random Bug model

The “Random Bug” model is the perhaps the most-simple and usable model that one can create. It features a bug that randomly “walks” the grid by choosing a random cell to move to, out of the eight cells that surround it. The concrete implementation of the “Random Bug” can be seen in the source-code listings in Figure 1 and Figure 2.

The RandomBug implementation of Bug has one property; an array called possibleDirectionDeltas. This array consists eight coordinate deltas, each of which is a delta into one of the surrounding eight cells. For example, a delta of (-1, 1) represents a cell that is to the bottom left of the current cell. This array is initialized inside the init method of the RandomBug class.

The bulk of the work is done in the act method. First, we shuffle possibleDirectionDeltas. This ensures that we pick a location at random. After that, we start up a do-while loop that runs as long as we have locations to examine, and we haven't found an unoccupied location. Inside the loop, we pick the first delta from our array. We then apply it to the bug's current location, making sure that we wrap the coordinates if needed. After that we check to see if the location is unoccupied. If it is, it means that we have found our new location and we can exit from the loop. Otherwise, we have to go back and pick a new delta to see if the corresponding location is unoccupied. The net effect of this method is that the bug will choose a random cell from the eight surrounding-cells (if one is available) and then move to it.

Of course, this code by itself doesn't provide the complete picture. We need to see how we can use it. This can be seen in the code listing in Figure 3, which shows how the model is constructed and run, and in Figure 4 and Figure 5, which shows the code for the interceptor that observes the simulation. A sample of the output from the model is shown in Figure 6.

Layer: FirstLayer, Bug: RandomBug is at (23, 30)Layer: FirstLayer, Bug: RandomBug is at (22, 30)Layer: FirstLayer, Bug: RandomBug is at (23, 30)Layer: FirstLayer, Bug: RandomBug is at (23, 29)Layer: FirstLayer, Bug: RandomBug is at (24, 29)

Figure 6: Output of Random Bug model

B. Infectable Bug Model

The “Infectable Bug” (Figure 7 and Figure 8) model is a slightly more-complicated model. It features a population of healthy bugs and one infected bug. After a bug is infected, it will infect other bugs within its “infection radius” after the incubation period has elapsed.

The InfectableBug implementation of Bug has a few additional-attributes. The first is a flag that says whether the bug is infected or not, the second is an infection radius which describes the area surrounding an infected bug within which any healthy bug gets infected, and the third is an incubation period which specifies the number of iterations it takes before the bug starts infecting healthy bugs.

Since the InfectableBug does more than the RandomBug, its act method is correspondingly longer and a bit more complicated. The InfectableBug implementation also features an additional method called scan that scans the area within the infection radius for healthy bugs.

When the act method is executed, we first check to see if this bug is infected or not. If it isn't, we simply move the bug to a random location just like the RandomBug implementation. This part is virtually similar to the RandomBug implementation. However, if the bug has been infected, we check to see if we are past the incubation period. If we are, we call the scan method. The scan method examines each cell within the infection radius to see if there are any healthy bugs present. It creates a list of all healthy bugs it has found and returns the list back to the act method. The act method then iterates over that list and calls the infect method on each healthy bug, which has the effect of turning all those bugs into infected bugs. Once we have finished infecting all healthy bugs within our infection radius (if there were any), we move our bug to a random location.

When this model is run, we are able to observe the number of infected bugs progressively increasing,

Page 6: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

until all healthy bugs have turned into infected bugs. However, this isn't a very accurate representation of disease spreading through a population. When an actual disease progresses through the population, we can expect a certain percentage of the population to gain immunity or die. Also, people have a tendency to move away from infections agents. The next model simulates this situation.

C. Infectable Non-Linear Bug Model

The “Infectable Non-Linear Bug” more-accurately models the spread of disease through a population. I created this model to demonstrate that Bhumi is capable of simulating reasonably-complex models.

The InfectableNonLinearBug implementation of Bug (Figure 9 and Figure 10) describes an agent that behaves in specific ways based on its state, which can be one of the following: healthy, infected, infectious, immune, or dead. As before, this behavior is encapsulated inside the act method. The InfectableNonLinearBug has some additional attributes as well, and we are able to tweak the model to represent different scenarios, by adjusting these attributes:

State: The health-state of the bug, which as mentioned before can be one of the following: healthy, infected, infectious, immune, or dead.

Incubation Period: The number of iterations after which the bug turns infectious. The bug is still able to infect other bugs during the incubation period.

Infection Period: The number of iterations after the incubation period, after which the bug either turns immune or dies from the disease. The bug is also able to infect other bugs during this state.

Infection Radius: The radius within which any healthy bugs can be infected by this bug.

Alert Radius: If one or more infectious bugs are detected within this radius, the bug will try to move away from them.

Mortality Rate: The chance that a bug dies after the infectious period is over.

When the act method is executed, the bug will display different behavior depending on its health state:

Healthy Bug: When the bug is in this state, it will scan within its alert radius for any infectious bugs. If it doesn't find any infectious bugs within its alert radius, it simple moves to a random location in a manner

similar to the RandomBug implementation. However, if it finds one or more infectious bugs, it chooses a direction that moves it away from those infectious bugs. The algorithm for this is very naïve. The bug first calculates the current distances between itself and all infectious bugs in its alert radius. It then chooses a candidate location (i.e., one of the surrounding eight cells assuming it is unoccupied) and calculates the distances from that location to the infectious agents. The bug then compares the two sets of distances to see how many distances are greater. The bug then moves to the next candidate-cell and performs the same calculation. If there are more number of greater distances at this new location, then this location is assumed to be the new candidate location. Otherwise, the candidate location remains the same. These calculations are performed for all surrounding cells (assuming they are not occupied) and at the end, the bug will have a location that takes it the farthest from most of the infectious agents within its alert radius. This algorithm is obviously not perfect and has shortcomings, but it is suitable for our purposes.

Infected Bug: When the bug is in this state, it is able to infect other bugs. This state simulates the real-world scenario where individuals do not know that they are infected since they do not show signs of the disease. However, they are still able to spread the disease since they have been infected. An infected bug will thus behave like a healthy bug in the sense that it will try to move away from infectious bugs within its alert radius, but it will be infecting other bugs as it does so. The infection behavior of the bug in this state is similar to the InfectableBug implementation; the bug scans for healthy bugs within its infection radius and infects the ones it finds.

Infectious Bug: When the bug is in this state, it is visible as an infectious agent to other bugs. Healthy and infected bugs will therefore try to move away from an infectious bug. An infectious bug behaves like the InfectableBug implementation. It moves in a random direction and will infect any bugs within its infection radius.

Immune Bug: A bug transitions into the immune state once the incubation and infection periods are over, if it does not die from the infection. The chance of this transition is governed by the mortality-rate attribute. An immune bug cannot be reinfected and moves in a random direction. That is, it does not try to move away from infectious agents.

When we run this model, we can easily see the disease progressing through the population (Figure 11). The “front” of the infection is marked by bugs that are in the “infected” state. Within the front, there

Page 7: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

is a population of infectious and immune bugs. The infectious bugs are closer to the front, whereas the immune bugs are further away and closer to the center.

Viewing a graph of the simulation population over time (Figure 12) gives us additional information. We can see that the curve that represnts the healthy population starts decreasing slowly at first, and then at a much faster rate once the disease spreads through the population. The infected and infectious curves are offset by 25 iterations, since that is how long it takes for a bug to transition between the two states. The curve that represents the number of immune population increases slowly at first and then at a much faster rate once the disease progresses and those bugs that have been infected, become immune. Since a percentage of the population does not survive the disease, the final number of immune bugs is less that the total number of bugs that we started with.

As mentioned before, we can tweak the model to represent different scenarios, by adjusting the attributes on the bugs. For example, suppose we wanted to model the spread of an extremely-virulent pathogen like the Ebola virus. We can do this by tweaking the model in the following manner: increasing the mortality rate to 95%, lowering the incubation period to 2 iterations, and lowering the infection period to 5 iterations.

A characteristic of highly-virulent infections such as Ebola is that they are not easily able to spread through a population due to the fact that they “burn out” quickly. This is because the disease usually ends up killing the host before it can be transmitted to another host[8]. This behavior can be seen in Figure 13. The healthy population of bugs is virtually unchanged. There is a short period during which bugs are infected and turn infectious. However, due to the high mortality-rate and the low transmission-period (the sum of the incubation and infection period, which in this case is seven iterations), the disease rapidly disappears before any other bugs can be infected, due to the majority of the hosts having died.

8. Conclusion and Future Work

As the examples have shown, Bhumi is able to simulate reasonably-complex models without trouble. The models I have described is only a small sample of what is possible with Bhumi. It is possible to simulate even-more complex models by utilizing additional layers. Going back to the epidemiological models from the last section, we can use layers to group different populations. For example, we might wish to see how the very young and very old respond to the same disease. We can put these populations into separate layers and see how they respond over time. Layers can also have more complex behavior. We can add “static”

bugs to a layer so that they can take on the functions of walls or roads, influencing the movement of the population and thus the spread or behavior of the disease. However due to being a preliminary effort, Bhumi is not without its short-comings and there is always room for enhancements and improvements.

The first area of improvement is performance. While the framework itself is not performance-intensive, individual models can be. For example, the algorithm used to scan the surrounding locations of a cell is O(n2). The framework itself is also synchronous, which means that only one bug is executing at a time. This definitely makes the code easier to write and understand since there is no need to guard against shared resources, however the drawback is that performance-intensive Bug implementations will degrade the performance of the simulation as a whole. The solution to this problem would be to convert the framework and bugs to behave concurrently. In contrast to older and more error-prone approaches that uses locks, synchronized blocks, and threads, Objective-C now includes a library called Grand Central Dispatch which makes writing concurrent code much easier, in Objective-C. Converting the framework (specifically the World class) class to support concurrency is sure to provide major performance gains.

The second area of improvement is with regard to scheduling. Frameworks like Swarm and RePast provide the ability to schedule actions to happen at specific times. While this behavior is possible with Bhumi, the resulting code will be somewhat awkward due to there not being an explicit abstraction for scheduling. Supporting scheduling also allows us to incorporate events and notifications which helps us make more-complicated models, easily.

The third area of improvement is with respect to unit tests. Currently Bhumi does not feature any unit tests at all. Unit testing has a significant impact on the quality and robustness of code. Thus, writing unit tests that provide 100% effective-coverage of Bhumi code will ensure that the framework is solid and also provides us with a sense of confidence as to the performance and stability of the framework.

The final area of improvement is somewhat of a long-term goal. Creating models in Bhumi requires a non-trivial knowledge of the Objective-C programming-language (just as it does in Swarm). Ideally, there should be a way to abstract this away so that anyone who wants to create a model doesn't have to write code in Objective-C unless they absolutely have to. One way of doing this would be to create a domain-specific language on top of Bhumi, that abstracts away the underlying details and only provides tools to describe the model (similar to Multi-Agent Modeling language for Swarm[9]). Specific actions, such as scanning, can be implemented in an

Page 8: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

efficient manner in Objective-C and exposed via the domain-specific-language. The language should also be extensible, so that new actions can be implemented in Objective-C and then exposed through the language.

Bhumi has great promise and potential, which I believe has been amply demonstrated by the different models that it is able to simulate. Given enough time and work, I believe that it can be turned into a viable alternative to Swarm, and into an agent-based-modeling framework in its own right.

Page 9: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

9. Figures

#import <Foundation/Foundation.h> #import "../framework/Bug.h"

@interface RandomBug : Bug @property NSMutableArray* possibleDirectionDeltas;

- (id) init; @end

Figure 1: RandomBug.h

#import "RandomBug.h"#import "../framework/World.h"

@implementation RandomBug

- (id) init { if(self = [super init]) { _possibleDirectionDeltas = [[NSMutableArray alloc] init]; for(NSInteger _x = -1; _x <= 1; _x++) { for(NSInteger _y = -1; _y <= 1; _y++) { struct FixedPoint possibleDirectionPoint; possibleDirectionPoint.x = _x; possibleDirectionPoint.y = _y; [_possibleDirectionDeltas addObject: [NSValue valueWithBytes: &possibleDirectionPoint

objCType: @encode(FixedPoint)]]; } } } return self;}

- (void) act { [_possibleDirectionDeltas shuffle]; NSUInteger rows = [self.world rows]; NSUInteger columns = [self.world columns]; NSUInteger i = 0; BOOL found = NO; do { NSInteger _x = self.x; NSInteger _y = self.y; struct FixedPoint point; [[_possibleDirectionDeltas objectAtIndex: i] getValue: &point]; _x += point.x; _y += point.y; _x %= columns; if(_x < 0) _x += columns; _y %= rows; if(_y < 0) _y += rows; found = ([self.world isLocationOccupiedInLayer: self.layer atX: _x atY: _y] == NO); if(found) { self.x = _x; self.y = _y; } i++; } while(!found && i < [_possibleDirectionDeltas count]);}

@end

Figure 2: RandomBug.m

Page 10: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

#import "framework/World.h"#import "domain/RandomBug.h"#import "domain/SimpleLoggingInterceptor.h"

int main(void) { @autoreleasepool { World* world = [[World alloc] initWithName: @"Bhumi" rows: 100 columns: 100 iterations: 10 snapshotInterval: 1 interceptor: [[SimpleLoggingInterceptor alloc] init]];

Bug* randomBug = [[RandomBug alloc] initWithWorld: world name: @"RandomBug" layer: @"FirstLayer"];

[world addBug: randomBug]; [world start]; }

return 0;}

Figure 3: main.m

#import <Foundation/Foundation.h>#import "InterceptorProtocol.h"

@interface SimpleLoggingInterceptor : NSObject <InterceptorProtocol>@end

Figure 4: SimpleLoggingInterceptor.h

#import "SimpleLoggingInterceptor.h"#import "World.h"

@implementation SimpleLoggingInterceptor {}

- (void) intercept: (World *) world { NSUInteger currentIteration = [world currentIteration];

NSMutableString* json = [NSMutableString stringWithString: @""]; NSEnumerator* layerEnumerator = [[world layers] objectEnumerator]; NSString* layer;

while((layer = [layerEnumerator nextObject])) { NSArray* bugs = [world bugs: layer]; NSEnumerator* bugEnumerator = [bugs objectEnumerator]; Bug* bug;

while((bug = [bugEnumerator nextObject])) { printf("%s", [[NSString stringWithFormat:@"Layer: %@, Bug %@ is at (%lu, %lu)\n", layer, [bug

name], [bug x], [bug y]] UTF8String]); } }

[world step];}

@end

Figure 5: SimpleLoggingInterceptor.m

Page 11: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

#import <Foundation/Foundation.h>#import "../framework/Bug.h"

@interface InfectableBug : Bug @property BOOL infected; @property(readonly) NSUInteger infectionStartIteration; @property NSUInteger incubationPeriod; @property NSUInteger infectionRadius; @property NSMutableArray* scanLocationDeltas; @property NSMutableArray* possibleDirectionDeltas;

- (id) initWithWorld: (World*) aWorld name: (NSString*) aName layer: (NSString*) aLayer infected: (BOOL) anInfected infectionRadius: (NSUInteger) anInfectionRadius incubationPeriod: (NSUInteger) anIncubationPeriodinfectionStartIteration: (NSUInteger) anInfectionStartIteration;

- (NSArray*) scan;- (void) infect;

@end

Figure 7: InfectableBug.h

#import "InfectableBug.h"#import "../framework/World.h"#include <stdlib.h>#include <time.h>#include <math.h>

@class World;@class BugToStringSerializer;

@implementation InfectableBug

@synthesize infected;@synthesize infectionRadius;@synthesize incubationPeriod;@synthesize infectionStartIteration;

- (id) initWithWorld: (World*) aWorld name: (NSString*) aName layer: (NSString*) aLayer infected: (BOOL) anInfected infectionRadius: (NSUInteger) anInfectionRadius incubationPeriod: (NSUInteger) anIncubationPeriodinfectionStartIteration: (NSUInteger) anInfectionStartIteration {

if((self = [super initWithWorld: aWorld name: aName layer: aLayer])) { infected = anInfected; infectionRadius = anInfectionRadius; incubationPeriod = anIncubationPeriod; infectionStartIteration = anInfectionStartIteration;

_possibleDirectionDeltas = [[NSMutableArray alloc] init]; for(NSInteger _x = -1; _x <= 1; _x++) { for(NSInteger _y = -1; _y <= 1; _y++) { struct FixedPoint possibleDirectionPoint; possibleDirectionPoint.x = _x; possibleDirectionPoint.y = _y; [_possibleDirectionDeltas addObject: [NSValue valueWithBytes: &possibleDirectionPoint

objCType: @encode(FixedPoint)]]; } }

_scanLocationDeltas = [[NSMutableArray alloc] init]; for(NSInteger _x = (NSInteger) infectionRadius * -1; _x <= (NSInteger) infectionRadius; _x++) { for(NSInteger _y = (NSInteger) infectionRadius * -1; _y <= (NSInteger) infectionRadius; _y++) { struct FixedPoint scanPoint; scanPoint.x = _x;

Page 12: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

scanPoint.y = _y;

[_scanLocationDeltas addObject: [NSValue valueWithBytes: &scanPoint objCType: @encode(FixedPoint)]];

} } }

return self;}

- (void) act {

NSUInteger rows = [self.world rows]; NSUInteger columns = [self.world columns];

NSInteger iterationDelta = [self.world currentIteration] - infectionStartIteration; if(infected && iterationDelta > (NSInteger) incubationPeriod) {

NSArray* uninfectedBugsWithinInfectionRadius = [self scan]; NSEnumerator* bugEnumerator = [uninfectedBugsWithinInfectionRadius objectEnumerator]; InfectableBug* bug; while((bug = [bugEnumerator nextObject])) { [bug infect]; } }

[_possibleDirectionDeltas shuffle]; NSUInteger i = 0; BOOL found = NO; do { NSInteger _x = self.x; NSInteger _y = self.y; struct FixedPoint point; [[_possibleDirectionDeltas objectAtIndex: i] getValue: &point]; _x += point.x; _y += point.y; _x %= columns; if(_x < 0) _x += columns; _y %= rows; if(_y < 0) _y += rows; found = ([self.world isLocationOccupiedInLayer: self.layer atX: _x atY: _y] == NO); if(found) { self.x = _x; self.y = _y; } i++; } while(!found && i < [_possibleDirectionDeltas count]);}

- (NSArray*) scan {

NSMutableArray* uninfectedBugsWithinInfectionRadius = [[NSMutableArray alloc] init];

NSEnumerator* scanLocationDeltaEnumerator = [_scanLocationDeltas objectEnumerator]; NSValue* scanLocationDeltaValue;

while((scanLocationDeltaValue = [scanLocationDeltaEnumerator nextObject])) { struct FixedPoint scanLocationDelta; [scanLocationDeltaValue getValue: &scanLocationDelta];

NSInteger rows = [self.world rows]; NSInteger columns = [self.world columns];

NSInteger scanX = self.x + scanLocationDelta.x; NSInteger scanY = self.y + scanLocationDelta.y;

scanX %= columns; if(scanX < 0) scanX += columns; scanY %= rows; if(scanY < 0) scanY += rows;

Page 13: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

double distance = sqrt((scanLocationDelta.x * scanLocationDelta.x) + (scanLocationDelta.y * scanLocationDelta.y));

if(distance <= infectionRadius && distance > 0) { NSArray* bugs = [self.world getBugsAtX: (NSUInteger) scanX atY: (NSUInteger) scanY];

if([bugs count] > 0) { NSEnumerator* bugEnumerator = [bugs objectEnumerator]; InfectableBug* bug;

while((bug = [bugEnumerator nextObject])) { if([bug infected]) { [uninfectedBugsWithinInfectionRadius addObject: bug]; } } } } }

return uninfectedBugsWithinInfectionRadius;}

- (void) infect { infected = YES; infectionStartIteration = [self.world currentIteration];}

@end

Figure 8: InfectableBug.m

#import <Foundation/Foundation.h>#import "Bug.h"#import "InfectableNonLinearBugState.h"

@class World;

@interface InfectableNonLinearBug : Bug

@property InfectableNonLinearBugState state; @property(readonly) NSUInteger infectionStartIteration; @property(readonly) NSUInteger incubationPeriod; @property(readonly) NSUInteger infectionPeriod; @property(readonly) NSUInteger infectionRadius; @property(readonly) NSUInteger alertRadius; @property(readonly) NSUInteger mortalityRate; @property NSMutableArray* possibleDirectionDeltas; @property NSMutableArray* alertScanLocationDeltas; @property NSMutableArray* infectionScanLocationDeltas;

- (id) initWithWorld: (World *) aWorld name: (NSString *) aName layer: (NSString *) aLayer state: (InfectableNonLinearBugState) aState incubationPeriod: (NSUInteger) anIncubationPeriod infectionPeriod: (NSUInteger) anInfectionPeriod infectionRadius: (NSUInteger) anInfectionRadius alertRadius: (NSUInteger) anAlertRadius mortalityRate: (NSUInteger) aMortalityRate;

+ (id) objectWithWorld: (World *) aWorld name: (NSString *) aName layer: (NSString *) aLayer state: (InfectableNonLinearBugState) aState incubationPeriod: (NSUInteger) anIncubationPeriod infectionPeriod: (NSUInteger) anInfectionPeriod infectionRadius: (NSUInteger) anInfectionRadius alertRadius: (NSUInteger) anAlertRadius mortalityRate: (NSUInteger) aMortalityRate;

- (NSArray *) scanForState: (InfectableNonLinearBugState) bugState withinRadius: (NSUInteger) radius;- (void) infect;

@end

Figure 9: InfectableNonLinearBug.h

Page 14: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

#import "InfectableNonLinearBug.h"#import "World.h"

@implementation InfectableNonLinearBug

@synthesize state;@synthesize infectionStartIteration;@synthesize incubationPeriod;@synthesize infectionPeriod;@synthesize infectionRadius;@synthesize alertRadius;@synthesize mortalityRate;

- (id) initWithWorld: (World *) aWorld name: (NSString *) aName layer: (NSString *) aLayer state: (InfectableNonLinearBugState) aState incubationPeriod: (NSUInteger) anIncubationPeriod infectionPeriod: (NSUInteger) anInfectionPeriod infectionRadius: (NSUInteger) anInfectionRadius alertRadius: (NSUInteger) anAlertRadius mortalityRate: (NSUInteger) aMortalityRate {

if((self = [super initWithWorld: aWorld name: aName layer: aLayer])) { state = aState; incubationPeriod = anIncubationPeriod; infectionPeriod = anInfectionPeriod; infectionRadius = anInfectionRadius; alertRadius = anAlertRadius; mortalityRate = aMortalityRate;

if(state == INFECTED || state == INFECTIOUS) { infectionStartIteration = 1; }

_possibleDirectionDeltas = [[NSMutableArray alloc] init]; _alertScanLocationDeltas = [[NSMutableArray alloc] init]; _infectionScanLocationDeltas = [[NSMutableArray alloc] init];

for(NSInteger _x = -1; _x <= 1; _x++) { for(NSInteger _y = -1; _y <= 1; _y++) { struct FixedPoint possibleDirectionPoint; possibleDirectionPoint.x = _x; possibleDirectionPoint.y = _y;

[_possibleDirectionDeltas addObject: [NSValue valueWithBytes: &possibleDirectionPoint objCType: @encode(FixedPoint)]];

} } for(NSInteger _x = (NSInteger) alertRadius * -1; _x <= (NSInteger) alertRadius; _x++) { for(NSInteger _y = (NSInteger) alertRadius * -1; _y <= (NSInteger) alertRadius; _y++) { struct FixedPoint alertScanPoint; alertScanPoint.x = _x; alertScanPoint.y = _y;

[_alertScanLocationDeltas addObject: [NSValue valueWithBytes: &alertScanPoint objCType: @encode(FixedPoint)]];

} }

for(NSInteger _x = (NSInteger) infectionRadius * -1; _x <= (NSInteger) infectionRadius; _x++) { for(NSInteger _y = (NSInteger) infectionRadius * -1; _y <= (NSInteger) infectionRadius; _y++) { struct FixedPoint infectionScanPoint; infectionScanPoint.x = _x; infectionScanPoint.y = _y;

[_infectionScanLocationDeltas addObject: [NSValue valueWithBytes: &infectionScanPoint objCType: @encode(FixedPoint)]];

} } }

return self;}

Page 15: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

+ (id) objectWithWorld: (World *) aWorld name: (NSString *) aName layer: (NSString *) aLayer state: (InfectableNonLinearBugState) aState incubationPeriod: (NSUInteger) anIncubationPeriod infectionPeriod: (NSUInteger) anInfectionPeriod infectionRadius: (NSUInteger) anInfectionRadius alertRadius: (NSUInteger) anAlertRadius mortalityRate: (NSUInteger) aMortalityRate { return [[InfectableNonLinearBug alloc] initWithWorld: aWorld name: aName layer: aLayer state: aState incubationPeriod: anIncubationPeriod infectionPeriod: anInfectionPeriod infectionRadius: anInfectionRadius alertRadius: anAlertRadius mortalityRate: aMortalityRate];}

- (void) act {

NSInteger iterationDelta = [self.world currentIteration] - infectionStartIteration;

if((state == INFECTED || state == INFECTIOUS) && iterationDelta > (NSInteger) incubationPeriod) { state = INFECTIOUS;

NSArray* bugs = [self scanForState: HEALTHY];

NSEnumerator* bugEnumerator = [bugs objectEnumerator]; InfectableNonLinearBug* bug; while((bug = [bugEnumerator nextObject])) { [bug infect]; } }

if(state == INFECTIOUS && iterationDelta > (NSInteger) (incubationPeriod + infectionPeriod)) { NSUInteger number = arc4random() % 100;

if(number <= mortalityRate) { self.alive = NO; } else { state = IMMUNE; } }

if(self.alive == YES) {

[_possibleDirectionDeltas shuffle];

NSArray* bugs = [self scanForState: INFECTIOUS];

NSUInteger rows = [self.world rows]; NSUInteger columns = [self.world columns];

if([bugs count] > 0 && state != IMMUNE) {

NSMutableArray* distancesFromCurrentPosition = [[NSMutableArray alloc] init]; NSEnumerator* bugEnumerator = [bugs objectEnumerator]; InfectableNonLinearBug* bug;

while((bug = [bugEnumerator nextObject])) { NSInteger dx = self.x - [bug x]; NSInteger dy = self.y - [bug y]; NSNumber* distance = [NSNumber numberWithDouble: sqrt((dx * dx) + (dy * dy))];

[distancesFromCurrentPosition addObject: distance]; }

NSUInteger numberOfFurtherPoints = 0; struct FixedPoint furthest; furthest.x = 0; furthest.y = 0;

NSEnumerator* directionDeltaEnumerator = [_possibleDirectionDeltas objectEnumerator]; NSValue* directionDeltaValue; BOOL furthestPointFound = NO;

Page 16: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

while ((directionDeltaValue = [directionDeltaEnumerator nextObject])) {

struct FixedPoint directionDelta; [directionDeltaValue getValue: &directionDelta];

NSMutableArray* distancesFromDeltaPosition = [[NSMutableArray alloc] init];

NSInteger _x = self.x + directionDelta.x; NSInteger _y = self.y + directionDelta.y;

_x %= columns; if(_x < 0) _x += columns; _y %= rows; if(_y < 0) _y += rows;

if([self.world isLocationOccupiedInLayer: self.layer atX: (NSUInteger) _x atY: (NSUInteger) _y] == NO) {

bugEnumerator = [bugs objectEnumerator]; while((bug = [bugEnumerator nextObject])) { NSInteger dx = _x - [bug x]; NSInteger dy = _y - [bug y]; NSNumber* distance = [NSNumber numberWithDouble: sqrt((dx * dx) + (dy * dy))];

[distancesFromDeltaPosition addObject: distance]; }

NSUInteger numberOfFurtherPointsForDelta = 0; for(NSUInteger i = 0; i < [distancesFromCurrentPosition count]; i++) { if([[distancesFromDeltaPosition objectAtIndex: i] doubleValue] >

[[distancesFromCurrentPosition objectAtIndex: i] doubleValue]) { numberOfFurtherPointsForDelta++; } }

if(numberOfFurtherPointsForDelta > numberOfFurtherPoints) { furthest.x = _x; furthest.y = _y; numberOfFurtherPoints = numberOfFurtherPointsForDelta; furthestPointFound = YES; } } }

if(furthestPointFound == YES) { self.x = (NSUInteger) furthest.x; self.y = (NSUInteger) furthest.y; }

} else {

NSUInteger i = 0; BOOL found = NO;

do {

NSInteger _x = self.x; NSInteger _y = self.y;

struct FixedPoint point; [[_possibleDirectionDeltas objectAtIndex: i] getValue: &point];

_x += point.x; _y += point.y;

_x %= columns; if(_x < 0) _x += columns; _y %= rows; if(_y < 0) _y += rows;

found = ([self.world isLocationOccupiedInLayer: self.layer atX: _x atY: _y] == NO);

if(found) { self.x = _x; self.y = _y; }

i++;

} while(!found && i < [_possibleDirectionDeltas count]); } }}

Page 17: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

- (NSArray *) scanForState: (InfectableNonLinearBugState) bugState { NSMutableArray* bugsWithStateWithinInfectionRadius = [[NSMutableArray alloc] init];

NSMutableArray* scanLocationDeltas;

if(bugState == HEALTHY) { scanLocationDeltas = _alertScanLocationDeltas; } else { scanLocationDeltas = _infectionScanLocationDeltas; }

NSEnumerator* scanLocationDeltaEnumerator = [scanLocationDeltas objectEnumerator]; NSValue* scanLocationDeltaValue;

while((scanLocationDeltaValue = [scanLocationDeltaEnumerator nextObject])) { struct FixedPoint scanLocationDelta; [scanLocationDeltaValue getValue: &scanLocationDelta];

NSInteger rows = [self.world rows]; NSInteger columns = [self.world columns];

NSInteger scanX = self.x + scanLocationDelta.x; NSInteger scanY = self.y + scanLocationDelta.y;

scanX %= columns; if(scanX < 0) scanX += columns; scanY %= rows; if(scanY < 0) scanY += rows;

double distance = sqrt((scanLocationDelta.x * scanLocationDelta.x) + (scanLocationDelta.y * scanLocationDelta.y));

if(distance <= infectionRadius && distance > 0) { NSArray* bugs = [self.world getBugsAtX: (NSUInteger) scanX atY: (NSUInteger) scanY]; if([bugs count] > 0) { NSEnumerator* bugEnumerator = [bugs objectEnumerator]; InfectableNonLinearBug* bug;

while((bug = [bugEnumerator nextObject])) { if([bug state] == bugState) { [bugsWithStateWithinInfectionRadius addObject: bug]; } } } } }

return bugsWithStateWithinInfectionRadius;}

- (void) infect { state = INFECTED; infectionStartIteration = [self.world currentIteration];}

@end

Figure 10: InfectableNonLinearBug.m

Page 18: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

Figure 11: Snapshot of the Infectable Non-Linear-Bug Model at iteration 204 running on OS X. Healthy bugs are blue, infected bugs are yellow, infectious bugs are red, and immune bugs are green.

Page 19: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

Figure 12: Graph of population during the Infectable Non-Linear-Bug simulation

Page 20: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

Figure 13: Graph of population during the Infectable Non-Linear-Bug simulation representing a virulent pathogen

Page 21: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

Figure 14: Infectable Non-Linear-Bug model running on the iPad simulator

Page 22: Bhumi: A simple, extensible, agent-based-modeling frameworkpooh.poly.asu.edu/.../VivanPalliathProjectReport.pdf · agent-based modeling. Swarm's appeal was that it helped the scientists

9. References

[1] N. Minar, R. Burkhart, C. Langton, and M. Askenazi, “The SWARM Simulation System: A Toolkit for Building Multi-Agent Simulations,” Santa Fe, New Mexico, 1996.

[2] B. Heath L., “The History, Philosophy, and Practice of Agent-Based Modeling and the Development of the Conceptual Model for Simulation Diagram,” Wright State University, 2010.

[3] J. von Neumann, Theory of Self-Reproducing Automata. Urbana, Illinois: University of Illinois Press, 1966.

[4] R. A. Freitas and R. Merkle C., Kinematic Self-Replicating Machines. Georgetown, TX: Landes Bioscience, 2004.

[5] E. R. Berlekamp, J. H. Conway, and R. K. Guy, Winning Ways for your Mathematical Plays, 2nd ed. Wellesly, Massachusetts: A. K. Peters Ltd., 2001.

[6] C. Reynolds, “Flocks, herds and schools: A distributed behavioral model,” in Proceedings of the 15th annual conference on Computer graphics and interactive techniques, 1987.

[7] N. Collier, “RePast: An Extensible Framework for Agent Simulation,” University of Chicago, Chicago, IL, 2001.

[8] M. Lipsitch, E. A. Herre, and M. A. Nowak, “Host Population Structure and the Evolution of Virulence: A ‘Law of Diminishing Returns’,” Evolution, vol. 49, no. 4, pp. 743–748, Aug. 1995.

[9] L. Gulyás, T. Kozsik, and S. Fazekas, “The Multi-Agent Modeling Language,” presented at the 4th International Conference on Applied Informatics, Eger-Noszvaj, Hungary, 1999.