A new implementation of Holland`s Complex Adaptive Systems

jECHO: A new implementation of Holland’s Complex Adaptive
Systems model with the aim of seeking answers to some
fundamental open questions
By
Brian W. McIndoe
A DISSERTATION
Submitted to
The University of Liverpool
in partial fulfillment of the requirements
for the degree of
MASTER OF SCIENCE
17th February 2005
ABSTRACT
jECHO: A new implementation of Holland’s Complex Adaptive
Systems model with the aim of seeking answers to some
fundamental open questions
By
Brian W. McIndoe
ECHO, one of the most celebrated models of a Complex
Adaptive System (CAS), is analyzed and a new implementation designed and
developed using Java and the RePast multi-agent toolkit. The new
implementation, called jECHO, incorporates mechanisms for resource
exchange, resource transformation and sexual reproduction of agent genetic
material through crossover between agent pairs having accumulated sufficient
resources for reproduction. Previous implementations of ECHO have been
incomplete and have not given full consideration of Holland’s mature ideas on
CAS. This effort is an attempt to build an extensible object oriented version of
ECHO that can provide a platform for advanced experimentation in order to
answer some fundamental questions about CAS. This implementation
incorporates the adhesion mechanism and enables the creation of multi-agent
aggregates.
UML diagrams such as use case, domain, sequence and class
diagrams are used to analyze and design jECHO. The capabilities of the
RePast framework are also considered and provide a foundation for the
simulation. jECHO is subjected to a number of test runs to gain an
understanding of the range of evolutionary dynamics that can be obtained.
This work was motivated by the author’s discontent with
previous ECHO implementations, software engineering issues with the state
of the available code, and lack of answers to some fundamental questions
about the efficacy of the ECHO model. Progress on several important
questions still needs to be made as steps toward a theory of CAS.
Recommendations for future work are made based on results obtained.
Brian W. McIndoe
DECLARATION
I hereby certify that this dissertation constitutes my own product, that where
the language of others is set forth, quotation marks so indicate, and that appropriate
credit is given where I have used the language, ideas, expressions or writings of
another.
I declare that the dissertation describes original work that has not previously
been presented for the award of any other degree of any institution.
Signed,
Brian W. McIndoe
ACKNOWLEDGEMENTS
I would like to thank Lalit Garg of Thapar Institute of Engineering and
Technology, and the University of Liverpool/Kit-eLearning for both sponsoring this
project and for acting as my supervisor. His help and guidance has assisted this
effort in many important ways.
I also acknowledge John Holland of the University of Michigan for
starting the ‘ECHO’ ball rolling (amongst many others!), and the many able
researchers who have also worked with these ideas.
I cannot forget my parents who made all of this possible. Thanks Mum
and Dad!
Finally, to my wife Julie, my children Vivien and James, and our cats
Vinnie and Dexi, thank you for putting up with a distracted husband, dad and
playmate over the last few months. Hopefully it has been worth it.
This page left intentionally blank
TABLE OF CONTENTS
Page
CHAPTER 1 INTRODUCTION......................................................................................................1
AIMS AND OBJECTIVES OF THE PROJECT ...........................................................................................1
CAS DEFINITION.............................................................................................................................2
THE CLASSIC ECHO MODEL OF A COMPLEX ADAPTIVE SYSTEM ......................................................3
CHAPTER 2 LITERATURE REVIEW .........................................................................................4
COMPLEX ADAPTIVE SYSTEMS IN THE NATURAL WORLD ...................................................................4
ORIGINS OF THE ECHO CAS MODEL ...............................................................................................5
THE EVOLUTION OF THE ECHO MODEL ......................................................................................... 11
CRITIQUES OF ECHO BY SMITH, BEDAU AND OTHERS .................................................................... 14
THE CURRENT STATE OF ECHO AND OUTSTANDING QUESTIONS ...................................................... 15
CHAPTER 3 PROJECT METHODOLOGY ............................................................................... 16
DEVELOPMENT METHODOLOGY FOR JECHO.................................................................................. 16
TEST METHODOLOGY FOR JECHO ................................................................................................. 17
PROJECT PHASES AND METHODOLOGIES ........................................................................................ 17
CHAPTER 4 ANALYSIS AND DESIGN MODELS .................................................................... 19
JECHO ANALYSIS MODEL ............................................................................................................ 19
HOLLAND’S ECHO MODEL SPECIFICATIONS AND REQUIREMENTS .................................................. 21
Overview .................................................................................................................................. 21
Model 1 .................................................................................................................................... 24
Model 2 .................................................................................................................................... 25
Model 3 .................................................................................................................................... 26
Model 4 .................................................................................................................................... 27
Model 5 .................................................................................................................................... 28
Model 6 .................................................................................................................................... 29
REPAST MULTI-AGENT SIMULATION FRAMEWORK ........................................................................ 29
JECHO DESIGN MODEL ................................................................................................................ 31
JECHO EXECUTION FLOW ............................................................................................................. 33
JECHO DISPLAY OUTPUT .............................................................................................................. 35
JECHO DESIGN CHALLENGES AND SOLUTIONS .............................................................................. 37
CHAPTER 5 RESULTS AND ANALYSIS................................................................................... 39
“CATERPILLAR-ANT-FLY” ECOLOGICAL TRIANGLE TEST ............................................................... 39
SMITH AND BEDAU – MUTATION RATE TESTS ................................................................................ 46
MULTI-SITE TESTS ........................................................................................................................ 51
TEST RESULTS REVIEW.................................................................................................................. 54
CHAPTER 6 CONCLUSIONS AND FURTHER WORK ........................................................... 59
REFERENCES CITED .................................................................................................................. 62
APPENDIX A: GLOSSARY OF TERMS...................................................................................... 65
APPENDIX B: JECHO USE CASE DESCRIPTIONS ................................................................. 67
APPENDIX C: DETAILED LIST OF ECHO TEST PARAMETERS ......................................... 71
APPENDIX D: CODE INSTALLATION DETAILS .................................................................... 77
APPENDIX E: SOURCE CODE LISTINGS................................................................................. 84
vii
List of Tables
Table
Page
Table 1 jECHO Boundary Rules ..................................................................................................... 38
Table 2 Caterpillar-Ant-Fly - Simulation 1 Parameters ..................................................................... 41
Table 3 Caterpillar-Ant-Fly - Simulation 2 Parameters ..................................................................... 43
Table 4 Caterpillar-Ant-Fly - Simulation 3 Parameters ..................................................................... 45
Table 5 Mutation Rate - Simulation 1 Parameters............................................................................. 47
Table 6 Mutation Rate - Simulation 2 Parameters............................................................................. 48
Table 7 Mutation Rate - Simulation 3 Parameters............................................................................. 49
Table 8 Mutation Rate - Simulation 4 Parameters............................................................................. 50
Table 9 Mutation Rate - Simulation 5 Parameters............................................................................. 51
Table 10 Multi-Site – Simulaton Parameters..................................................................................... 52
Table 11 Multi-Site with Aggregation - Parameters .......................................................................... 53
Table 12 Multi-Site - Stable - Parameters ......................................................................................... 54
viii
List of Figures
Figure
Page
Figure 1 Project Phases, Activities and Artifacts............................................................................... 18
Figure 2 jECHO Use Cases.............................................................................................................. 19
Figure 3 Analysis Level Sequence Diagram ..................................................................................... 20
Figure 4 Domain Model................................................................................................................... 21
Figure 5 ECHO Agent ..................................................................................................................... 22
Figure 6 The ECHO Model Geography ............................................................................................ 23
Figure 7 Model 1 Interaction............................................................................................................ 24
Figure 8 Model 2 Interaction............................................................................................................ 26
Figure 9 Model 3 Resource Transformation...................................................................................... 26
Figure 10 Model 4 Adhesion............................................................................................................ 27
Figure 11 Model 5 Selective Mating ................................................................................................ 29
Figure 12 RePast GUI Controller ..................................................................................................... 31
Figure 13 jECHO Class Diagram ..................................................................................................... 32
Figure 14 jECHO Sequence Diagram - buildModel()........................................................................ 33
Figure 15 jECHO Execution Flow.................................................................................................... 34
Figure 16 jECHO Agent Population Graph....................................................................................... 35
Figure 17 jECHO Resource Window................................................................................................ 36
Figure 18 jECHO Agent Window .................................................................................................... 36
Figure 19 Caterpillar-Ant-Fly Ecological Triangle............................................................................ 40
Figure 20 jECHO simulation 1 of Caterpillar-Ant-Fly Ecological Triangle ....................................... 41
Figure 21 jECHO simulation 2 of Caterpillar-Ant-Fly Ecological Triangle ....................................... 43
Figure 22 jECHO simulation 3 of Caterpillar-Ant-Fly Ecological Triangle ....................................... 45
Figure 23 jECHO simulation 1 of Mutation Rate.............................................................................. 46
Figure 24 jECHO simulation 2 of Mutation Rate.............................................................................. 47
Figure 25 jECHO simulation 3 of Mutation Rate.............................................................................. 48
Figure 26 jECHO simulation 4 of Mutation Rate.............................................................................. 49
Figure 27 jECHO simulation 5 of Mutation Rate.............................................................................. 50
Figure 28 jECHO multi-site simulation ............................................................................................ 52
Figure 29 Multi-Site with Aggregation............................................................................................. 53
Figure 30 Multi-Site - Stable............................................................................................................ 54
ix
CHAPTER 1
INTRODUCTION
Aims and Objectives of the project
The main aim of this project was to implement a new version of the classic ECHO
model of a Complex Adaptive System (CAS) described by Holland (1995). A further
aim was for the new implementation, called jECHO, to be used to seek insights into
CAS behavior in an attempt to evaluate ECHO model mechanisms and properties
using published methods such as those of Smith and Bedau (1999) and my own
investigations. In particular, insight was sought into the operation of the Adhesion
mechanism described by Holland (1995, p.115) on which little information can be
found in the available literature. The software developed for this project is to be made
freely available on the Internet as a resource for the CAS research community.
The aims for this project were supported by the following objectives:
•
To perform an analysis of the requirements for the ECHO model, and a design
and implementation of this model using OO techniques. The analysis and design
was performed using the Unified Process and documented using the Unified
Modeling
Language
based
on
the approach
of
Larman
(2001).
The
implementation used Java and incorporated the RePast Multi-agent simulation
toolkit (Collier 2004) as a supporting framework.
•
To investigate the behavior of jECHO using published tests such as those
documented by Holland (1995, p.105), Smith and Bedau (1999) and my own set
of tests to evaluate the mechanisms and properties designed into ECHO, in
particular the adhesion mechanism, and to attempt to determine their contribution
to CAS behavior.
•
To create a web site that contains the jECHO software and instructions for use.
1
This project had both a development component and a research component. The
development component resulted in the jECHO software. The research component
sought to provide some answers to the following closely related research questions.
These were:
•
Do the agent interactions and transformations described in Holland (1995)
actually produce the behavior of a Complex Adaptive System? What behavior do
they produce?
•
How closely do the seven basic elements (four properties and three mechanisms)
of a Complex Adaptive System proposed in Holland (1995) appear to be
determining factors in the behavior of jECHO?
•
Related to this is the question as to whether the tests described by Smith and
Bedau (1999) are a satisfactory way to test for the behavior of a Complex
Adaptive System? What other tests might be used to determine this behavior?
•
Should the jECHO implementation of ECHO not exhibit CAS behavior then what
modifications might be made to the model that may lead to CAS behavior?
•
What are potentially fruitful avenues for future work on the ECHO CAS model?
CAS Definition
A widely accepted definition for a Complex Adaptive System is not available.
However, Dooley (1996) has gone the furthest in attempting to rectify this. For the
purpose of this dissertation, and modifying Dooley’s definition somewhat,
A CAS is a system composed of many interacting semi-autonomous parts
(usually called agents) where each part has a few simple individual behaviors
which when aggregated with other parts can produce systems with emergent
behaviors of high complexity.
2
The Classic ECHO Model of a Complex Adaptive System
Examples of ‘real-world’ CAS given by Holland (1992, p.1 and 2) are economies,
ecologies, immune systems, developing embryos, cities such as New York, and the
mammalian brain. ECHO is an attempt to strip away situation specific detail and to
focus on the essential abstract properties and mechanisms that underlie the
phenomena believed to be common to all Complex Adaptive Systems. The purpose
of developing and experimenting with a model such as ECHO is to develop a deeper
understanding of its behavior as a step to the development of a theory of CAS. The
ECHO model takes place in an artificial World where two dimensional Sites play host
to Agents. An agent can interact with other agents and the site environment to
accumulate resources, which enable the agent to sexually reproduce with partners.
Fitness of an agent is determined by its ability to accumulate resources and hence
propagate its genetic material through future generations. Chapters Two and Four of
this work will provide further detail on the mechanisms, properties and intentions with
the ECHO model.
3
CHAPTER 2
LITERATURE REVIEW
Complex Adaptive Systems in the natural world
Throughout the natural world we see a multitude of examples of systems that appear
to be composed of simple interacting parts yet that exhibit astounding complexities
and emergent properties not possessed by the individual parts alone. Systems of this
type are predominant in the natural world; however, they have only recently become
the subject of study and attempts at understanding.
The reasons for the neglect by science of the complex in favor of the simple are
many. The necessity to simplify complex systems in order to facilitate mathematical
analysis and understanding has been a significant reason, combined with the natural
sciences successful bias in favor of reductionism. Reason (1999) gives a good
account as to why reductionism has been such a productive analytical tool for
science but describes how this approach is not sufficient when dealing with biological
systems, where a holistic view of a system, its components and interactions is often
required.
The development of increasingly powerful computers over the last few decades,
combined with a growing realization of the limitations of traditional mathematical
analysis of complex systems has led to the increasing use of the computer for
simulations of systems that have so far defied mathematical analysis. Bedau (1999)
sees this application of computer simulation to the understanding of complex
systems as inevitable and beneficial. He also attempts to deal with the criticism that
computer models of complex systems are unrealistic and he notes that this is more of
a strength than a weakness, as computer models can abstract away unnecessary
4
details and concentrate on “the minimal set of properties to generate and explain the
phenomena under investigation”.
The field of complex systems divides naturally into two classes. The first being
systems that have large complexity due to the number of component parts, but the
parts do not adapt or learn based on their experience. Gell-Mann (1994, p.235) offers
galaxies, stars, planets and rocks as examples of this type of complexity. The second
category consists of systems that have component parts that can adapt and evolve
based on the history of their interactions with other parts of the system and with the
environment. It is the category of adaptive systems capable of evolutionary behavior
in response to their history of interaction that is the topic of this dissertation.
Systems with many adaptive parts (usually called agents) are commonly known as
Complex Adaptive Systems often abbreviated simply as CAS. As mentioned in
Chapter One, no broadly accepted definition of a CAS currently exists, however, a
number of authors cited by Dooley (1996) have provided insights into the
characteristics they believe important for a CAS and have tried to lay the foundations
for a definition. The most complete description for the elements of a CAS model,
which would allow for implementation and testing is to be found in Holland (1995)
under the name of ECHO. The next section will consider the origins of the ECHO
model and its basic characteristics.
Origins of the ECHO CAS Model
In the late 1980s a number of scientists working in the fields of biology, physics,
computer science and mathematics began to view the computer as a tool for
understanding the dynamics of CAS that prior to then had been largely ignored by
science as too difficult for analysis. Researchers affiliated with the Santa Fe Institute
(SFI), an institution with an interdisciplinary mission to understand complexity and
5
whose founders included three Nobel Prize winners, undertook much of this new
work focusing on nonlinear complex systems. A good account of the founding of SFI,
the key personalities involved and the early work undertaken can be found in
Waldrop (1992).
One researcher well known for utilizing biological metaphors in the development of
computational algorithms was John Holland from the University of Michigan. Holland
who had previously developed Genetic Algorithms (1992) and Classifier Systems
(1986) became associated with the Santa Fe Institute and began work on a general
model of CAS behavior in the early 1990s. In Holland (1992, p.184) he describes his
recent work as one of searching for the core similarities he believed may be exhibited
by all types of CAS as a step on the way to developing a complete theory of CAS.
His list of commonalities shared by CAS which he states (p.184) have blocked
broadly based attempts at comprehension are:
1. CAS incorporate large numbers of parts that are “undergoing a kaleidoscopic
array of simultaneous nonlinear interactions.” Holland (1992, p.184). He
makes the point that because of the nonlinear interactions between the
agents, the behavior of the system is not even close to the sum of its parts.
2. It is the aggregate behavior of the whole system that is of interest. Holland
goes on to note “that the aggregate behavior often feeds back to the
individual parts modifying their behavior.” He uses the examples of
Government economic statistics influencing the plans of individual businesses
in an economy, or the effect of aggregate nutrient retention in a rain forest on
species diversity, to illustrate this point.
3. “Interaction between the parts of the system evolves over time as the parts
adapt in an attempt to survive in the environment provided by the other parts.
As a result, the parts face perpetual novelty, and the system as a whole
typically operates far from a global optimum or equilibrium.”
6
4. “Complex Adaptive Systems anticipate.” Holland sees the parts (agents) as
developing rules that become components of a model that anticipates the
consequences of responses. As an illustration he uses the example of
anticipation of an oil shortage. The act of anticipation by the agents can cause
a sharp run up in oil prices whether or not a shortage actually occurs.
Many examples of Complex Adaptive Systems are described in the literature.
Representative examples of CAS provided by Gell-Mann (1994) are:
•
The origin of life on Earth.
•
Biological Evolution.
•
The behavior of organisms in ecological systems.
•
The operation of the mammalian immune system.
•
Learning and thinking in animals.
•
The evolution of human societies.
•
The behavior of investors in financial markets.
•
Computer software designed to evolve strategies or to make predictions
based on past observations.
In (1995) Holland attempts to lay out what he sees as the fundamental building
blocks from which a theory of CAS could be developed. In his view, working toward a
theory of CAS is essential as without it, all investigations in this area will be “endless
forays into uncharted badlands” (1995, p.5). He goes on to describe the following as
the seven basics common to all CAS:
•
AGGREGATION (Property)
Holland describes this as the most basic of the characteristics typical of CAS
(1995, p.12). It is “the emergence of complex large-scale behaviors from the
aggregate interactions of less complex agents.” This is the property that enables
7
aggregates of agents to become meta-agents and in turn behave as agents at
higher level, and so on, giving the hierarchical organization Holland describes as
typical of CAS.
•
TAGGING (Mechanism)
Tagging is a form of identification and recognition for agents. Holland
describes examples of tagging in real life as such things as banners, flags,
logos, trademarks, etc. He sees the tagging mechanism as a pervasive
feature of CAS as they enable selective interaction between agents and
hence act as a mechanism for aggregation and boundary formation. (p.15)
•
NONLINEARITY (Property)
Holland (1995, p 15) makes the point that most mathematical tools are based on
an assumption of linearity, hence their inadequacy for analyzing CAS behavior.
Examples of nonlinear interactions in the real world are money flows within an
economy, and predator prey interactions such as between foxes and rabbits as
expressed by the Lotka-Volterra model (Lotka, 1956). Non-linearity leads to
increased complexity of behavior.
•
FLOWS (Property)
Flows are information, matter or energy that can recycle within a network of
agents and also become subject to multiplier effects which contribute to nonlineararities. As agents within a system die, the resources within their bodies can
be recycled within the CAS to emerge as the basis for new agents. Holland
(1995, p.26) mentions that the overall effect in a network with many cycles can be
striking.
•
DIVERSITY (Property)
In a population of heterogeneous agents, each type of agent fills a niche in the
ecosystem created by other agents. If one agent type is removed it creates a
‘hole’ which the system will attempt to fill through as Holland (1995, p.27)
8
describes “a cascade of adaptations resulting in a new agent that ‘fills the hole’”.
The new agent typically fills the new niche with similar interactions as the
removed agent had with its environment.
•
INTERNAL MODELS (Mechanism)
The internal model Holland (1995, p.31) describes is interior to each agent. The
agent needs to select patterns in the torrent of information it receives and must
then convert the patterns into changes in its internal structure. Internal models
provide an agent with the ability to anticipate its response to stimulus from other
agents and the environment.
•
BUILDING BLOCKS (Mechanism)
Building blocks are the components that enable an agent to build an internal
model. They are regularities (patterns) in the environment that the agent has
been able to hypothesis. Holland (1995, p.34) draws an analogy with the way
humans use building blocks to parse their environment into understandable
chunks.
The description of an actual CAS model designed to exhibit the above characteristics
was first noted in Holland (1992, p.186). The model was called ECHO and had the
goal of being an abstraction of the key properties and mechanisms exhibited by a
CAS. Holland’s original intention with ECHO was that it become a platform for
performing thought experiments as an aide to building CAS theory, though in time
various researchers tried to model specific CAS such as ecosystems with the model.
Holland developed the ECHO model over a number of years (92, 94, 95) and it is
true to say that ECHO should really be considered a class of models rather than one
specific model. Examples of features that were changed in subsequent versions of
ECHO were tags and conditions comprising the agent chromosome, specifically the
addition of an Adhesion tag in the later model described in Holland (1995). This later
9
version of the model is assumed to be the most complete and mature version
available and is the version that will be implemented by this project.
The details of the ECHO model are covered in the Requirements Analysis section of
this document. At this point it is sufficient to point out that each agent has a set of
genomes (Tags and Conditions) which when combined form the chromosome
(genotype) of the agent. The agent’s genes are divided into two broad categories.
These are “Tags” that serve as an agent’s phenotypic expression, so that other
agents may determine whether or not to interact, and “Conditions” which are internal
to the agent and that cannot be accessed by other agents but which indirectly affect
interaction. Tags are provided for offense, defense and adhesion, conditions are for
resource exchange, mating and resource transformation. The agent chromosome is
subject to crossover during mating with another agent where genetic material is
exchanged and also the possibility of point mutation. Through these operators, an
evolutionary mechanism is introduced into the ECHO model where genetic
inheritance and selection for fitness can occur. The selection force is implicit in the
sense that there is no explicit fitness function as would be the case with a genetic
algorithm. Instead, fitness is gauged by how capable an agent is in collecting the
resources it needs to reproduce and pass on its genetic material. The evolutionary
component in ECHO is based on Genetic Algorithms (GA) which Holland pioneered
in the 1960’s and is described in greater detail in Holland (1992). Mitchell and Forrest
(1993, p.9) describe how ECHO extends the concept of a Genetic Algorithm in
several important ways. These are:
1. ECHO resources are modeled explicitly in the system.
2. Agents have a geographical location, which may play a role in their implicit
fitness.
3. Interactions are built into the system such as trade, combat and mating.
10
4. Fitness is endogenous to ECHO, whereas GA’s have an external fitness imposed
on them,
There is also a clear development in ECHO of Holland’s other notable evolutionary
idea, the Learning Classifier System (1986, p.68). Holland (1992, p.195) notes that
ECHO and Classifier Systems are similar in many ways, particularly between
conditions in the agent chromosome and the condition/action rules in the classifier.
Classifier systems have been used to model cognitive systems and provide a
mechanism for the creation of hierarchies of internal models based on building
blocks.
Other models of CAS have been proposed and implemented with varying degrees of
success. Primary examples are Tierra developed by Ray (1992) and Sugarscape
developed by Epstein and Axtell (1996). Tierra consists of digital organisms
composed of executable machine codes that are subjected to endogenous fitness by
competing for CPU time as the resource. Sugarscape is closer to ECHO in design as
agents roam a 2D landscape in search of sugar and can reproduce sexually. The
field of computational simulation of multi-agent systems has been subjected to
criticism as a valid scientific technique and a good review of criticisms and the
proposed use and benefits of agent simulation can be found in Axtell (2000).
The Evolution of the ECHO model
The early ECHO model described in Holland (1992) was implemented at SFI by
Terry Jones and is documented in Jones and Forrest (1993). This implementation
was subjected to experimental investigation to determine whether it could exhibit
many of the same broad class of behaviors as natural ecosystems. Forrest and
Jones (1994) document findings on the distribution of ECHO species abundance
similar to those observed in natural systems. An assumption made in order to obtain
11
useful results was that each unique ECHO agent (unique genome) corresponds to a
species. This step was taken because ECHO does not have the concept of a species
explicitly built into it. Forest and Jones note an alternative could have been to
somehow define families of related genomes (a group of genomes) to be a species.
In that case the question would be where in the population of agents to draw the line
for each species grouping. Forrest and Jones then created Preston species curves
from data obtained from ECHO runs. They describe the ECHO Preston curves as
showing quite rich species abundance and being not dissimilar to those obtained
from real ecosystems.
The ecological characteristics of ECHO continued to be probed by Schmitz and
Booth (1997) when they configured a modified version of the SFI implementation to
create food webs (such as those occurring between carnivore, herbivore and plants).
The goal of the research was “to discover the biological features leading to stability of
artificial food chains over ecological time and under different conditions of trophic
efficiency”.
In order to study trophic efficiency, ECHO needed to be extensively
modified to enable a more realistic simulation of a real world food web. The
modifications included a simplification of the types of interactions between agents,
the addition of resource transformations, changes to the model timing algorithm and
a restructuring of the chromosome. Schmitz and Booth renamed ECHO to Gecko to
reflect the modifications and very different purpose of their simulator from the original
ECHO conception. They claim that their results show evidence of an emergent result
that modulated the degree of oscillation of a prey through the behavior of individual
agents. This work was followed up by Hraber and Milne (1996) who also created a
modified version of the SFI code they called ‘Simple’ ECHO. Simple ECHO only
allowed 2 letter resource alphabets (unlike standard SFI ECHO which was
implemented for a 4 letter resource alphabet), and placed restrictions on the possible
interactions between agents. The goal of the research undertaken by Hraber and
12
Milne was to investigate the mechanisms of community assembly processes. Their
main interest was to gain insight into whether assembly patterns seen in natural
systems are a result of biotic processes (utilizing specific interactions between
agents) or whether they could be the result of random selection. Hraber and Milne
found that certain processes did in fact have a regulatory impact on community
assembly. These processes were: “evolution of alternative community states by
symmetry breaking, selection for functional guilds given non-random interactions
among agents, and sensitivity to invasion (mutation) rate.” They also drew attention
to the fact that the SFI code from which Simple ECHO was developed, did not
implement one of Holland’s key adhesion mechanisms for the formation of explicit
ensembles of “meta-agents”, as an essential mechanism of adaptive agents.
Efforts to understand the dynamics of the SFI version of ECHO continued with
Hraber et al. (1997) who compared the relative species abundance and the species
area scaling relation between ECHO and a neutral model in which selection was a
random process. The experiments reported were based on a design which
incorporated three different agents configured in a trophic triangle. The results
showed that “qualitatively the pattern of genome abundances in ECHO populations
resembles the general patterns found in biological systems, although there were
some differences”.
All of the above investigations have demonstrated the ECHO class of models to have
robust evolutionary dynamics, which are similar to documented examples of the
dynamics seen in natural ecologies.
13
Critiques of ECHO by Smith, Bedau and others
A major critique of ECHO and its fidelity as a model of CAS is to be found in Smith
and Bedau (1999). They based their experiments on the latest available code
implemented at SFI (Jones and Forrest (1993)). A long-standing interest of the
authors has been to develop statistics for the quantification of evolutionary activity in
natural and artificial systems (Smith and Bedau (1997), Bedau et al. (1998) and
Bedau (1999)).
In their paper, after reviewing their experimental data, they come to the conclusion
that ECHO does not exemplify the features of CAS as described in Holland (1995).
Their main reason for this assertion is “there is no evidence of the emergence of a
diversity of hierarchically organized adaptive aggregates. The only evident
aggregations were simple trading ecologies and transitory combat ecologies.” They
do not see this as a setback necessarily for the ECHO model, just the motivation for
another iteration in the hypothesis-test-revise methodology promoted in Holland
(1995) as an approach for making progress on the development of a theory of CAS.
Smith and Bedau then go on to mention how a few trivial revisions of the current SFI
implementation of ECHO may make a difference to its behavior. Specifically the SFI
implementation does not allow for resources freed up through metabolic taxes and
death to be available to other agents to forage (and hence create additional flows
and nonlinearities). They also mention that it would be of interest to see the result of
allowing mating to coexist with combat and trading. They conclude by reiterating that
the lack of generation of diverse aggregations of hierarchical adaptive structures is
the reason why ECHO is not a CAS.
14
The current state of ECHO and outstanding questions
In reading the work of Smith and Bedau, it is important to keep in mind that they are
critiquing an early version of ECHO as implemented in the SFI code. The model
proposed in Holland (1995) is quite different and has additional tags and processes
included to support the creation of multi-agent aggregates, principally through the
mechanism of adhesion. A review of the literature available on the Internet has been
unable to locate any implementation of the ECHO model that claims to be a full
development of Holland’s mature ideas of a CAS described in Holland (1995). The
most recent implementation was created for Sandia National Laboratories and is
documented in Harris (2001). The Sandia version implements ECHO through model
3 described in Holland (1995), and does not address the mechanisms for adhesion
and multi-agent formation. Another development is reported in Dominiak et al,
(2001), where the authors describe their interest in investigating spatial aspects of a
CAS using a 3D representation of ECHO’s dynamics. They mention modifications
made to ECHO which include adhesion mechanisms but do not provide any details.
A search of the Internet was unable to uncover any further information on this
implementation.
In light of the fact that little information has been published on the mature ECHO as
described in Holland (1995), particularly aspects related to adhesion mechanisms, it
is in my view important to the development of a theory of CAS that ECHO now be
implemented as completely as possible. It is also important in my view that any new
implementations be shared with the community of researchers to further ongoing
research into CAS. The rest of this dissertation documents a project to implement the
ECHO model in Holland (1995) and to subject the model to tests for CAS behavior.
15
CHAPTER 3
PROJECT METHODOLOGY
This chapter describes the methodologies used to analyze, design and test the
jECHO software. The project approach taken and methods selected for analysis and
design are object oriented and fit well with the Java language selected for
implementation. The final section of this chapter ties together the project phases,
methodologies and artifacts.
Development Methodology for jECHO
The development methodology used to create jECHO was based on the Unified
Process (UP) and made use of the Unified Modeling Language (UML). Larman
(2001), Scott (2001) and Fowler & Scott (2000) were the main reference works used
in the development of the Analysis and Design models for this project. Two sets of
requirements were considered. The first set described the requirements of the
simulator that runs the ECHO model, displays model activity and collects data about
the model. The second set defined the requirements of the ECHO model itself.
Analysis Model
The Analysis Model for the project consisted of:
1. An analysis of the requirements for the jECHO simulation using use case
diagrams and templates.
2. An analysis level sequence diagram showing the interactions between jECHO
and its environment.
3. A Domain model for ECHO showing the major entities and their relationships.
4. An analysis of the capabilities of the RePast Multi-Agent Simulation Framework
so that an understanding could be developed of how RePast was to be used as
the foundation of the jECHO implementation.
5. An analysis of the specifications and requirements of Holland’s ECHO model
described in Holland (1995).
16
The analysis of requirements formed the basis of the design model. The design
model consisted of both a static view of the system represented on a class diagram,
and a dynamic behavioral view expressed in sequence diagrams.
Design Model
The Design Model for this project consisted of:
1. Development of a class diagram showing the design level entities that make up
the jECHO application.
2. Creation of three sequence diagrams that show the object interactions for 1)
creating Model objects, 2) scheduling Model objects to run and for 3) updating
the GUI components.
Test Methodology for jECHO
In addition to Unit and Integration tests, the completed jECHO code was subjected to
the following set of tests to investigate its behavior:
1. The “Caterpillar-Ant-Fly” ecological triangle described in Holland (1995, p.105). A
set of agents were created with the tag and condition attributes identifying them
as a caterpillar, an ant or a fly.
2. The set of tests with steadily increasing rates of mutation described in Smith &
Bedau (1999).
3. A series of tests of my own devising intended to attempt to characterize the
behavior of jECHO, specifically the contribution of each mechanism to the overall
observed behavior.
Project Phases and Methodologies
The project commenced with the Inception Phase where initial versions of the
artifacts described above under the heading of Analysis Model were developed. As
my understanding of the ECHO model grew I produced elaborated versions of the
17
Analysis Model artifacts to show greater detail. This elaboration of artifacts for the
purpose of definition is part of the Elaboration phase in the Unified Process [See
Larman (2001)]. As the Elaboration phase proceeded it developed into a design
activity where solutions were sought to the requirements defined in the Analysis
Model. In this design activity, the artifacts described in the Design Model above were
developed. These artifacts then formed the basis for the implementation of the code
which was undertaken in the Construction phase. The development of the code was
an iterative process where basic functionality was created, tested and integrated.
Subsequent iterations added additional functionality to the integrated code base. The
testing of the developed code described under the Test Methodology heading above
was then performed. The following shows the relationship between the project
phases, the project activities and the points in the lifecycle where the artifacts were
developed.
Progress of Project
PHASE
ACTIVITY
Inception
Elaboration
Analysis Model
Use Cases
ARTIFACTS
Domain
Diagram
Sequence
diagram
Construction
Design Model
Coding
Class
Diagram
Transition
Tests
Eco
Triangle
Sequence
Diagrams
Smith &
Bedau
My Own
Tests
Figure 1 Project Phases, Activities and Artifacts
18
CHAPTER 4
ANALYSIS AND DESIGN MODELS
jECHO Analysis Model
As mentioned in Chapter 3, two sets of requirements were considered. The first were
requirements for the jECHO simulation environment in which the ECHO model runs.
The following use case diagram was created to identify and analyze these
requirements.
Figure 2 jECHO Use Cases
The main requirements were 1) The ability to configure model parameters for a run,
2) The ability to run a model and 3) The ability to collect and display data from the
model run. Use case descriptions analyzing the requirements for the use cases
depicted in the above diagram are in Appendix C of this document. A system
19
sequence diagram was also created to show the interaction between a user
(researcher) and the system (jECHO).
Figure 3 Analysis Level Sequence Diagram
Following this a Domain model was developed to identify the major entities in the
jECHO, their attributes and relations.
20
Figure 4 Domain Model
The key points to note on the domain model diagram are that:
1. There are in fact 6 models described in Holland (1995). Each model builds on the
rules (mechanisms) defined in the previous model. For example, model 3 makes
use of the mechanisms defined in models 1 and 2.
2. The ECHO model consists of a World entity that in turn may contain many Site
entities, which may contain many Agent entities. Each type of entity (World, Site
and Agent) has a set of configurable parameters, the modification of which could
be of interest to a user of jECHO.
Holland’s ECHO Model Specifications and Requirements
Overview
All of the following specifications and requirements for ECHO are taken from Holland
(1995, p. 101 to 139). The fundamental unit of the ECHO model is the resource
which is represented by letters from a resource alphabet, usually the four resources
21
symbolized by the letters {a, b, c, d}. These resource letters can be viewed as
building blocks used to construct everything within ECHO by their combination into
strings. These strings of resource letters then represent entities such as agent tags
and conditions. The ECHO model is played out on a two dimensional grid of one or
more interconnected sites. Each site can host a resource fountain which provides the
site with a renewable replenishment of its resource letter(s) at a predetermined rate
every time cycle. The resource distribution and replenishment rate can vary from site
to site. Central to ECHO is the concept of an agent. An agent is made up of tags,
conditions and a resource reservoir, which are themselves strings of resource letters.
The following shows the major components of an agent [adapted from Holland (1995,
p. 103)]:
Tag
Resource Reservoir
aabd
a
a
b
d a c
bdba
c a
Condition
Figure 5 ECHO Agent
A tag is available to other agent’s and is synonymous with an agent’s phenotype.
Conditions on the other hand are only available for internal use by an agent and
cannot be viewed by other agent’s.
22
Agents are located at a site and a portion of them are allowed to interact during any
given simulation cycle. If an agent is unable to accumulate resources then it
becomes eligible for migration to another randomly selected site. The following
diagram [adapted from Holland (1995, p.102)] shows the geographic layout of an
ECHO world.
WORLD
Interaction
Between
Agents
AGENT
SITE
cdac
adbc
aab
cba
Figure 6 The ECHO Model Geography
The ECHO model is in fact a family of models; each model in the series inherits the
mechanisms of the models defined earlier in the series and then adds its own
mechanism. The following is a definition of each model starting with the most basic
case.
23
Model 1
As shown in Figure 6, an agent contains both a chromosome and a resource
reservoir. In order to be able to reproduce (asexually) an agent needs to be able to
acquire, either by interaction with other agent’s or by interaction with the site, enough
resources in its reservoir to create its own genetic code in its child, and also provide
some amount of resource in its reservoir. When an agent meets the resource
requirements for asexual reproduction, its offspring’s chromosome which is a copy of
its parent is subject to possible mutation at a user settable probability. An agent in
model 1 has a simple chromosome that consists of just two tags, an offense tag and
a defense tag, with all interactions being mediated by these tags. Each simulation
cycle, a user settable fraction of the agent population at a site is selected for potential
interaction. When two agent’s meet, the outcome of their interaction is decided by
matching the offense tag of one agent with the defense tag of the other, scoring the
match, and repeating for the other offense/defense tag combination.
Offense Tag
abbd
………...
………..
abbc
Defense Tag
Position Comparison
abbd
abbc
2+2+2-2 = 4
Match characters at each position
and use a scoring matrix to score
the match. Add up all scores to
arrive at an overall match score.
Figure 7 Model 1 Interaction
24
The result of the match scoring is used to determine the result of the interaction. The
outcome can either be:
1. Nothing happens as the two agents are equally matched.
2. One agent has a slightly more powerful score than the other; in this case the
surplus amount in the weaker agent’s resource reservoir is transferred to the
stronger agent. The weaker agent continues to exist.
3. One agent is substantially stronger than the other; in this case the whole
resource reservoir is taken by the victor. The weaker agent continues to exist.
4. One agent overpowers the other with a very large score; in this case all genetic
material in the chromosome and resource reservoir of the loser is claimed by the
victor and the loser is erased.
In addition to the above, there is also a need for a user settable random death rate
and also the ability to have a user settable fraction of the population at a site to be
selected for migrate to a randomly chosen site.
Model 2
An extension to the previous model, this model adds the ability for an agent to either
reject or accept an interaction. This is achieved by segmenting the agent
chromosome into two parts, tags and conditions. An exchange condition is now
defined and is used to check the offense tag in the other agent’s chromosome. The
exchange condition is defined over the same resource alphabet as used for offense
and defense tags, with the one exception being the introduction of a ‘don’t care’
symbol. The symbol suggested by Holland (1995, p.112) is the ‘d’ character. This
means that whenever a ‘d’ is encountered in a condition, the condition will accept any
valid character (e.g., ‘a’, ‘b’ or ‘c’) appearing in a tag at that location. As tags may be
of arbitrary length, the last character in a condition “is treated as if it were followed by
an indefinite number of don’t care symbols”. When two agents are selected for
interaction, the exchange condition of each agent is checked against the other
25
agent’s offense tag. If both agents have their conditions satisfied, then the interaction
proceeds as described in model 1. If neither is satisfied, then the interaction aborts. If
only one is satisfied, then the other agent has the chance to flee with some user
settable probability.
Agent 1 Chromosome
Offense Tag
Defense Tag
Exchange Condition
abbd
cadb
ad
Match
(Model 1)
bcdd
Agent 2 Chromosome
Check
(Model 2)
acbd
cdc
Figure 8 Model 2 Interaction
Model 3
In model 3 Holland (1995, p.113) recognizes the importance of including a
mechanism that enables an agent to transform resources into new forms which are
more beneficial to it. He uses the examples of cells and factories to illustrate the point
of taking a resource in plentiful supply and transforming it into a resource in short
supply. The simplest method suggested by Holland (1995, p.114) is to add a
segment to the chromosome which specifies the resource to be transformed, the
resource produced as a result and the “cost” of the transformation process. For
example:
Resource to be Result of the
transformed
transformation
c
a
Cost of the
transformation
bb
Figure 9 Model 3 Resource Transformation
26
The rate at which the source resource is transformed into the target resource can be
variable and needs to be settable for experimentation.
Model 4
A property of CAS described by Holland (1995, p. 11, 12) is for the ability of agents to
aggregate in the sense that they can create higher level meta-agents which can inturn aggregate into meta-meta-agents, thus building a hierarchical structure. Seeing
the need to incorporate a mechanism which can facilitate this creation of aggregates,
Holland proposed an adhesion tag to be added to the agents chromosome (p. 115).
This adhesion tag would enable agents to selectively adhere and possibly lead to
agents within an aggregate beginning to specialize, for example some agents could
become collectors and providers of a resource, others could make use of the
resource through transformation, mating, etc. In model 4 the chromosome is
extended as follows:
Agent 1 Chromosome
Resource
Transformation
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
abbd
cadb
cad
ad
a d cc
cadb
cdc
c a bd
Match
Agent 2 Chromosome
bcdd
acb
External Tags
Internal Conditions
Figure 10 Model 4 Adhesion
In model 4, adhesion is tested by matching the adhesion tag of each agent with the
offense tag of its pair. If both tag comparisons have a low or zero score then no
adhesion takes place. Otherwise, either both agents will adhere using a common
27
boundary, or in the case of a very high score, one agent will become interior to the
other.
The test for adhesion is made at the point of creation of new agents when a parent
agent reproduces. The child agent’s tags are tested against those of the parent and
vice versa. It is also made in conjunction with the test for interaction and exchange
introduced in models 1 and 2. Agents that form an aggregate are considered to have
created a domain of interaction in that future interactions will give preference to other
agents within the aggregate.
Model 5
This model introduces the ability for agents to selectively mate with other agents to
exchange genetic material via crossover and to create a child agent. As mating is
selective it opens the door for the development of species within ECHO. This
capability is facilitated by including a mating condition in the agent chromosome.
Selective mating is initiated when an agent has accumulated enough resources to
enable reproduction [Holland (1995, p.122)]. A mating condition is matched with the
offense tag in a similar way that the exchange condition was matched with the
offense tag in model 2. Depending upon the specificity of the mating condition an
agent may accept almost any partners, or may evolve to accept only very specific
partners with explicit mating conditions.
28
Agent 1 Chromosome
Offense Tag
Defense Tag
Adhesion Tag
Exchange
Condition
Mating
Condition
Resource
Transformation
abbd
cadb
cad
ad
bd
a d cc
cdc
acd
c a bd
Check
Agent 2 Chromosome
bcdd
acb
cadb
External Tags
Internal Conditions
Figure 11 Model 5 Selective Mating
The crossover between two parent agents is at a randomly chosen point which could
be in any sub part (tag or condition) of the chromosome. The idea behind crossover
is that it is a way to potentially improve the genetic material of a child agent by
combining the genetic building blocks from two fit parents.
Model 6
The ideas and mechanisms introduced by Holland (1995, p.123) address complex
multi-agent processes and will not be addressed by this project. To my knowledge,
none of the ideas in model 6 have been fully implemented to this point.
RePast Multi-Agent Simulation Framework
The RePast framework is essentially a re-implementation in Java of the SWARM
simulation system [See Minar et al. (1996)]. RePast provides a set of basic
functionality helpful to researchers who want to model a Multi-Agent system. jECHO
leverages this functionality using the standard RePast classes and methods [See
RePast (2004)]. The RePast framework imposes certain constraints on the designer
though in return it provides several benefits, such as the ability to schedule events
and draw dynamically updating graphs.
29
RePast provides an abstract class called SimModelImpl from which custom
simulations are expected to extend. Included in the SimModelImpl class are three
methods which can be overridden to provide the structure of the simulation. These
methods are:
1. buildModel(). This method is responsible for creating the simulation objects that
represent what is being modeled, such as agents, sites, resources, etc. This is
one of the first methods executed by RePast.
2. buildSchedule(). This method is responsible for building the simulation schedule
that when it runs alters the state of the model. The RePast schedule object is told
what methods to call on which objects and when.
3. buildDisplay(). This method is where RePast expects the code to be for building
the parts of the application that have to do with displaying the simulation to the
user such as grids and graphs.
RePast provides a Controller which can be used for simulation control and for
the configuration of model parameters. The following is an example of the GUI
obtained by instantiating the RePast SimInit object:
30
Figure 12 RePast GUI Controller
The series of buttons in the top box are similar to the controls found on a VCR in that
they allow you to run, pause and stop the execution of the simulation.
jECHO Design Model
A key feature of ECHO that was important to reflect in jECHO was that each model is
additive in that each builds on the previous models and adds a new mechanism.
Thus, an inheritance hierarchy was chosen to show that each successive model is a
subclass that inherits methods and attributes from its predecessor. The Unified
Process uses the class diagram to show the classes that make up an application and
the relationships between the classes. The following diagram shows the major
classes, attributes and methods created for the jECHO implementation.
31
SimModel
EchoAgent
- IDNumber (static) : int
- ID :int
- generation :double
- parentID :int
- eSite :EchoSite
- resourceAlphabet :char
- x :int
- y :int
- boundaryID :int
- eb :EchoBoundary
- offenseTag :String
- defenseTag :String
- adhesionTag :String
- ExchangeCondition :String
- MatingCondition :String
- resourceTransformCondition :String
- resourceTransformRate :int
- replicationCondition :String
- resourceReservoir :String
- replicationThreshold :int
+ setXY() :void
+ incrementDecrement() :void
+ canAgentReplicate() :boolean
+ mutateAgent() :void
+ mutateTagCondition() :void
+ flipBit() :String
+ crossAgent() :void
+ crossoverChromosome() :void
+ swapTagsAndConds() :void
+ performSwap() :void
+ cullAgent() :void
+ amtResourceReservoir() :int
+ amtGeneticMaterial() :int
+ calculateAgentSurplus() :int
+ acquireAgentSurplus() :void
+ acquireAgentReservoir() :void
+ killOtherAgent() :void
+ transformResources() :void
+ addStringAmtResourceReservoir() :void
+ subtractStringAmtResourceReservoir()
:void
+ addAmtResourceReservoir() :void
+ subtractAmtResourceReservoir() :void
+ draw() :void
EchoModel1
<<Abstract>>
SimModelImpl
- siteAgentList :ArrayList
- interactionFraction :float
- mutateProbability :float
- deathRate :float
RePast Class
+ buildModel()
+ buildDisplay()
+ buildSchedule()
+ step()
+ begin()
+ setup()
+ getInitParam()
+ getName()
builds
executes
builds
executes
+ compareOffenseDefenseTags () :void
+ reallocateResources() :void
+ compareAgentOffenseAgainstSiteDefense() :int
+ compareAgentDefenseAgainstSiteOffense() :int
+ reallocateAgentSiteResources() :void
+ step() :void
EchoModel2
Jecho
+ step() :void
+ checkAgentExchangeConditions() :int
- Schedule
- DisplaySurface
- SiteArrayList
- AgentArrayList
EchoModel3
+ buildModel()
+ buildDisplay()
+ buildSchedule()
+ step() :void
EchoModel4
+ step() :void
+ checkAdhesion() :void
builds
executes
EchoModel5
builds
executes
+ step() :void
+ otherAgentInBoundary() :boolean
+ mateAgents() :boolean
+ checkAdhesion() :void
+ getNumberOfAgentsInABoundary() :int
EchoResource
builds
executes
EchoSite
- siteX :int
- siteY :int
- agentSites :Multi2DTorus
- resourceSites : Object2DTorus
+ addAgent() :void
+ addAgentToSite() :void
+ addResource() :void
+ getResource() :EchoResource
+ getAgentAt() :EchoAgent
+ getCurrentAgentSite() :Multi2DTorus
+ getCurrentResourceSite() :Object2DGrid
+ getObjectsAt() :List
+ removeAgent() :void
+ migrateAgent() :void
+ replenishSites() :void
- resourceIDNumber :String
- resourceId :String
- siteX :int
- siteY :int
- siteResource :String
- resourceOffenseTag :String
- resourceDefenseTag :String
- resourceRate :int
+ addStringAmtResourceReservoir() :void
+ subtractStringAmtResourceReservoir() :void
+ subtractAmtResourceReservoir() :void
EchoBoundary
- boundaryID :int
- generation :int
- parentBoundaryID :int
- agentsInABoundary :ArrayList
+ placeInExistingBoundary() :void
+ createInternalBoundary() :void
+ createExternalBoundary() :void
+ createCommonBoundary() :void
+ create2LevelBoundaries() :void
+ setParentBoundaryID() :void
+ isAgentInABoundary() :boolean
+ getNumberOfAgentsInABoundary() :int
+ removeAgentFromBoundary() :void
Figure 13 jECHO Class Diagram
Each jECHO site is assigned a location on a torus of locations (the ECHO world)
provided by the RePast class Multi2DTorus. No limit is placed by RePast on the
number of agents that can reside at a site.
32
The following sequence diagram shows the creation of objects when the buildModel()
method in the jECHO module runs.
Figure 14 jECHO Sequence Diagram - buildModel()
Once the model objects have been created by the buildModel() method, then the
buildDisplay() method runs to create the display objects and the buildSchedule()
method creates the schedule which updates both the step() method of the model and
the updateDisplay() method to redraw the screen.
jECHO Execution Flow
Holland (1995, p.147) gives some general ideas about the order in which processing
within an ECHO simulation could proceed, though many questions remain for an
actual implementation. In designing an execution flow for jECHO it was important to
33
recognize the parallel nature of the simulation and the need to update both the model
state and the display graph which shows the model state varying by time. The
buildSchedule() method within the RePast toolkit was used to call the step() method
within the echoModel5 object once every clock tick to calculate new model values
which were then updated on a real-time graph using the update() method of the
DisplaySurface object. The following diagram shows the sequence of events within
the step() method.
For Each
Time Step:
For Each
Site:
Replenish Site with Resources
Determine the agents that will
interact in this time step
Perform the Interaction and
reallocate resources
Check for Adhesion and create
Boundaries as necessary
Calculate Resource
Transformations for all agents
Agents interact with site to
gather resources
Determine who can reproduce
and create mating pairs
Cull a fraction of agents
Create child agent with
crossover and mutation
Migrate a fraction of agents
Check for Adhesion and create
Boundaries as necessary
Figure 15 jECHO Execution Flow
34
jECHO Display Output
The main source of output from jECHO is the graph of agent population against time
shown below. The red line shows the plot of the total agent population against time
and the blue line is a plot of the total number of boundaries created through the
adhesion of agents to other agents. Boundaries are a concept developed for jECHO
and will be described in the next section.
Figure 16 jECHO Agent Population Graph
In addition to the graph, other displays include a window showing sites which can be
clicked to obtain information on the resources at each site, and a window that shows
details of each agent at each site. The following are depictions of each:
35
Figure 17 jECHO Resource Window
Figure 18 jECHO Agent Window
There is also an text output window onto which messages can be written to record
particular model events using standard I/O such as System.out.println(“Text
Message”);
Tag Comparison Scoring matrix
A key component of the ECHO model is to compare various tags from two agents
that have been selected for interaction. Within jECHO there are three two
dimensional matrices that have been established for setting tag scoring values.
36
These are modelScore for scoring offense tags against defense tags, siteAgentScore
for scoring agents against sites when determining how much resource an agent
takes from a site, and adhesionScore which determines the strength of the adhesion
between two interacting agents.
jECHO Design Challenges and Solutions
One of the major challenges facing an implementation of ECHO is how to incorporate
a notion of aggregates into the simulation. Holland (1995, p.117) proposes a concept
called boundaries into which agents can be placed. Multiple levels of boundaries can
exist within an aggregate. Creating a boundary creates what Holland calls a ‘Domain
of Interaction’. This Domain of Interaction has an impact on the mechanisms within
ECHO in that an agent may only interact with agents belonging to the same or an
adjacent boundary. One also has to consider the impact of agent death such as what
should happen to an aggregate if the root (seed) agent is killed. In the jECHO
implementation the following rules were developed for the creation of boundaries
based on the outcome of adhesion scoring and whether the selected agents were
already members of existing boundaries.
In the following, Agent1 and Agent2 are the two agents that are selected for the
adhesion test, and the adhesion scoring has indicated that they should adhere.
Agent1 is the primary agent in that it had the highest adhesion score and the decision
on what to do with Agent2 is made relative to Agent1. There is also a flag called
Common that is set depending upon the intensity of adhesion from the match score
and if true, then agents will be placed into a common boundary and if false, the two
agents will be placed into separate boundaries where one is subservient to the other.
37
CONDITION
IF (Agent1 and Agent2 are already in the
same boundary)
IF (Agent1 and Agent2 are already in a
different boundary)
IF (Agent1 is in a boundary, Agent2 is
not in a boundary, and Common is True)
IF (Agent1 is in a boundary, Agent2 is
not in a boundary, and Common is False)
ACTION
THEN (do nothing)
THEN (do nothing)
THEN (place Agent2 in the same
boundary as Agent1)
THEN (place Agent2 in an internal sub
boundary to the boundary occupied by
Agent1)
THEN (place Agent1 in the same
boundary as Agent2)
THEN (place Agent1 in a unique
boundary)
THEN (place Agent1 and Agent2 in a
new common boundary)
IF (Agent1 is not in a boundary, Agent2
is in a boundary, and Common is True)
IF (Agent1 is not in a boundary, Agent2
is in a boundary, and Common is False)
IF (Agent1 is not in a boundary, Agent2
is not in a boundary, and Common is
True)
IF (Agent1 is not in a boundary, Agent2 THEN (place Agent1 in a root boundary,
is not in a boundary, and Common is and Agent2 in an internal sub boundary)
False)
Table 1 jECHO Boundary Rules
Because each new agent within jECHO is created as a new object, available memory
becomes a limiting resource for the simulation. Efforts were made to attempt to
minimize object creation and to set obsolete agent references to null, even so, a
successful simulation run often produces several thousand objects which may lead to
serious performance degradation. Additional work needs to be done to see if object
creation can be minimized and to see whether further optimizations can be made to
alleviate performance problems due to excessive object creation. Additionally,
because of the large number of string operations performed by jECHO, StringBuffer
methods were used in preference to regular string operations.
38
CHAPTER 5
RESULTS AND ANALYSIS
This chapter presents the results from the tests applied to the jECHO software
system. These tests were i) The “Caterpillar-Ant-Fly” Ecological Triangle Test, ii)
Smith and Bedau – Mutation Rate Tests and iii) a series of Multi-Site Tests. Appendix
C contains the detailed parameter and code settings that were used to conduct each
set of tests. The tests addressed multiple objectives. The main one being to ensure
that the mechanisms programmed into jECHO worked as expected. An additional
general testing objective was to observe the range and nature of the evolutionary
dynamics capable of being produced by jECHO. These example dynamics are
captured in the screen shots included in this chapter and the related analysis. The
intent of the Smith and Bedau tests was to gauge the impact of varying the mutation
rate on the growth of the population. The Multi-Site tests were an attempt to gauge
the impact of explicitly introducing additional variety into the simulations by having
multiple sites, each site with its own resource and agent profiles.
“Caterpillar-Ant-Fly” Ecological Triangle Test
The caterpillar-ant-fly ecological triangle is mentioned by Holland (1995, p.105, 106)
as an example of a CAS in the insect world. He describes a caterpillar that secretes a
type of nectar on its skin and a fly that lays its eggs on the caterpillar and hence
becomes a predator through its larva. The final corner of the triangle is occupied by
an ant that is a predator of the fly. The following [adapted from Holland (1995, p.106)]
illustrates the relationships between the three entities:
39
CATERPILLAR
cccc
aabb
FLY
Predation
aabb
Trade
ANT
aaaa
Predation
aaaa
cb
Figure 19 Caterpillar-Ant-Fly Ecological Triangle
The tags shown above are the starting points for the simulation. I have changed the
tags provided by Holland (p.106) to better suite the match scoring matrix settings in
jECHO. The tags I provide achieve the same result as those given by Holland. It
needs to be noted that jECHO has some additional mechanisms (such as resource
transformation and adhesion) that were not implemented in the SFI version of ECHO
used by both Holland and by Smith and Bedau (1999). Thus, to undertake the test
with jECHO required making some further tag and condition settings in such a way
as to minimize the impact of these additional mechanisms. The details of the tag and
condition settings along with other parameters are provided in Appendix C.
The following three diagrams show the results of running the Ecological Triangle
configuration under three different sets of model parameters and resource rates.
Following each diagram is a table showing the relevant settings. The red line shows
the number of agents and the blue line shows the number of cell boundaries. In the
40
Ecological Triangle tests the adhesion tags were set in such a way that adhesion
would be minimized and this is indeed what happened.
Figure 20 jECHO simulation 1 of Caterpillar-Ant-Fly Ecological Triangle
Parameter
Value
Number of generations
2500
Number of sites
1
Number of initial agents
50
Interaction Fraction
0.5
Mutation Probability
0.005
Migration Probability
0.0
Probability of Fleeing
0.02
Death Rate
0.05
Site resource
abcd
Site resource rate
4
Table 2 Caterpillar-Ant-Fly - Simulation 1 Parameters
41
In this run it can be seen that the population falls from the initial 50 to around 20
agents and remains stable at this level for about 300 generations. The initial fall is
brought about by the death rate which culls 5% of agents per generation. Then as the
remaining agents begin to begin to accumulate enough resources to be able to
reproduce the rate of new agent creation comes into equilibrium with the death rate.
Around the 300 generation point the system undergoes a change which brings about
a dramatic increase in the population of the agents. This beneficial change which
most likely was a point mutation in the chromosome that then spread throughout the
population by sexual reproduction to offspring as agents gained the necessary
resources through exchange with others (agents and the site), and through resource
transformation. The very rapid rise in the agent population from 20 to around 460
agents is the exploitation of the beneficial chromosome change as more resources
flow into the system through site replenishment and are in-turn accumulated and
propagated into new agents. A minor change can be seen at the top of the population
curve where another beneficial chromosome change brings about greater efficiency
in converting resources into new agents.
42
Figure 21 jECHO simulation 2 of Caterpillar-Ant-Fly Ecological Triangle
Parameter
Value
Number of generations
640
Number of sites
1
Number of initial agents
50
Interaction Fraction
0.5
Mutation Probability
0.1
Migration Probability
0.0
Probability of Fleeing
0.02
Death Rate
0.05
Site resource
abcd
Site resource rate
4
Table 3 Caterpillar-Ant-Fly - Simulation 2 Parameters
The main difference between this run and the prior one is that the mutation
probability was increased from 0.005 to 0.1. This means that the possibility of
mutation in the chromosome of a child agent is increased by a factor of 20. The
nature of the curve produced is quite different. After an initial fall, a change occurs
this time at the 140 generation level where the agent population begins to rise more
43
slowly this time and plateaus at about 160 agents where it remains for about 800
generations. At least one of the agent chromosomes then undergoes a beneficial
mutation and a rapid increase in the agent population is seen up to about 380, where
another change occurs and a yet more rapid increase in agent population occurs. At
the upper reaches of the curve a much increased ability to convert resources into
agents is seen. At this point agents were being produced at such a high rate that the
operation of the system started to be adversely affected due to increased memory
usage and a decision was made to stop the simulation.
The final simulation run for the Ecological Triangle shown on the next page produced
a stair step type of graph. For this run, the mutation probability had been increased to
0.2 and the rate of resource replenishment to the site had been halved from 4 to 2.
In this particular run we observe the same steep initial fall noted in the two previous
runs to a small number of agents, in this case about 12. The lower number reflects
the lower rate of inflow of the site resource (2 instead of 4) and hence the lower rate
at which new agents are created. Then a beneficial mutation occurs and is
propagated through the population by reproduction till the agent population reaches
between 35 and 40 agents where it then stays for about a thousand generations. The
average chromosome is then further improved through a step change to about 50
agents.
44
Figure 22 jECHO simulation 3 of Caterpillar-Ant-Fly Ecological Triangle
Parameter
Value
Number of generations
2500
Number of sites
1
Number of initial agents
50
Interaction Fraction
0.5
Mutation Probability
0.2
Migration Probability
0.0
Probability of Fleeing
0.02
Death Rate
0.08
Site resource
abcd
Site resource rate
2
Table 4 Caterpillar-Ant-Fly - Simulation 3 Parameters
What can this test tell us about the Ecological Triangle and about agent population
dynamics? At a minimum we can see that the modification of the chromosomes held
by each of the three agent types can be improved by the processes of evolution
(crossover and mutation) to make better use of the available resources through
exchange and resource transformation. This can be seen in each case where from a
45
low initial population significant increases occur, either in an step ascent, or by a
series of stair step movements.
Smith and Bedau – Mutation Rate Tests
The following sets of tests were inspired by Smith and Bedau (1999). In their series
of experiments they ran the same simulation while varying the mutation rate over a
wide range to see the effects. They were looking for indications of the creation of
hierarchically organized adaptive structures within ECHO which in light of the
absence of the adhesion mechanism in the SFI code used for the tests most likely
would not be found. The following tests were run using four initial agent types with
an initial agent population of 100 on one site. The mutation rate was varied from 0.1,
through 0.01, 0.001, 0.0001 and 0.00001. The first graph is with mutation rate 0.1.
Figure 23 jECHO simulation 1 of Mutation Rate
46
Parameter
Value
Number of generations
3500
Number of sites
1
Number of initial agents
100
Interaction Fraction
0.5
Mutation Probability
0.1
Migration Probability
0.0
Probability of Fleeing
0.0
Death Rate
0.08
Site resource
abcd
Site resource rate
4
Table 5 Mutation Rate - Simulation 1 Parameters
This graph shows some interesting dynamics in that it illustrates that evolution can
bring about both beneficial and harmful effects to an agent population. A steep rise
that occurs around the 1200 generation point is followed by a rapid descent where
about two thirds of the population is wiped out. The next few figures show the rest of
the runs for the remaining mutation rates.
Figure 24 jECHO simulation 2 of Mutation Rate
47
Parameter
Value
Number of generations
2550
Number of sites
1
Number of initial agents
100
Interaction Fraction
0.5
Mutation Probability
0.01
Migration Probability
0.0
Probability of Fleeing
0.0
Death Rate
0.08
Site resource
abcd
Site resource rate
4
Table 6 Mutation Rate - Simulation 2 Parameters
Figure 25 jECHO simulation 3 of Mutation Rate
48
Parameter
Value
Number of generations
3250
Number of sites
1
Number of initial agents
100
Interaction Fraction
0.5
Mutation Probability
0.001
Migration Probability
0.0
Probability of Fleeing
0.0
Death Rate
0.08
Site resource
abcd
Site resource rate
4
Table 7 Mutation Rate - Simulation 3 Parameters
Figure 26 jECHO simulation 4 of Mutation Rate
49
Parameter
Value
Number of generations
2960
Number of sites
1
Number of initial agents
100
Interaction Fraction
0.5
Mutation Probability
0.0001
Migration Probability
0.0
Probability of Fleeing
0.0
Death Rate
0.08
Site resource
abcd
Site resource rate
4
Table 8 Mutation Rate - Simulation 4 Parameters
Figure 27 jECHO simulation 5 of Mutation Rate
50
Parameter
Value
Number of generations
1275
Number of sites
1
Number of initial agents
100
Interaction Fraction
0.5
Mutation Probability
0.00001
Migration Probability
0.0
Probability of Fleeing
0.0
Death Rate
0.08
Site resource
abcd
Site resource rate
4
Table 9 Mutation Rate - Simulation 5 Parameters
The above graphs show that at higher mutation rates the population becomes more
susceptible to dramatic change which usually results in an adverse decline. In none
of the cases did aggregation become widespread, and those boundaries that did
form were quickly broken apart most likely due to the high agent death rate.
Multi-Site Tests
The following graph shows a test performed with agents spread across sixteen sites,
sites having a mixture of resource profiles. This graph displays shows a pronounced
series of spikes where the population shows a dramatic increase over just a few
generations. What most likely happens at the base of each major up-spike is that
through crossover and mutation a new chromosome emerges that becomes very
efficient at turning resources into offspring. Further, a build-up of the necessary
resources has accumulated over time at both the site level and in the resource
reservoirs of other agents. The new agent chromosome is then able through
exchange and transformation to fully maximize the conversion of the resource
backlog into new agents, resulting in the dramatic trajectories observed.
51
Figure 28 jECHO multi-site simulation
Parameter
Value
Number of generations
3250
Number of sites
16
Number of initial agents
150
Interaction Fraction
0.5
Mutation Probability
0.0005
Migration Probability
0.05
Probability of Fleeing
0.01
Death Rate
0.03
Table 10 Multi-Site – Simulaton Parameters
The following graph showing agent activity over nine sites is interesting in that it
shows the agent population gradually decreasing while the level of boundary
formation shows a marked increase. As noted previously the reason for the sharp
decline of boundary aggregates is due to the random death of a seed agent for the
aggregate.
52
Figure 29 Multi-Site with Aggregation
Parameter
Value
Number of generations
1900
Number of sites
9
Number of initial agents
400
Interaction Fraction
0.5
Mutation Probability
0.05
Migration Probability
0.02
Probability of Fleeing
0.01
Death Rate
0.01
Table 11 Multi-Site with Aggregation - Parameters
The final graph shows a multi-site simulation that is interesting in that it is relatively
stable and contains a large number of boundaries that survive.
53
Figure 30 Multi-Site - Stable
Parameter
Value
Number of generations
1900
Number of sites
9
Number of initial agents
400
Interaction Fraction
0.5
Mutation Probability
0.05
Migration Probability
0.02
Probability of Fleeing
0.01
Death Rate
0.01
Table 12 Multi-Site - Stable - Parameters
Test Results Review
The tests reported in this Chapter show that a rich set of dynamic behaviors can be
elicited from jECHO. These behaviors come about through a complex symphony of
interactions and transformations arising from a combination of initial conditions and
chance events. One small change in a tag value, condition or resource
transformation can have a startling effect on the course of a simulation.
54
Key factors influencing the course of a simulation being the initial tag and condition
values and the selected mutation rate. Using the match scoring rules, agent tags
and conditions can be created in such a way that eventual interaction with other
agents on the same site can be expected (facilitated through mutation and
crossover). The interaction or lack of it between agents and sites (to exchange
resources) can also be influenced by selection of the offense and defense tags for
each site. Likewise the amount of adhesion to be expected from a collection of
agents can be tuned to a certain extent by careful selection of the adhesion tags.
Therefore, some understanding of how to configure a simulation run goes a good
way toward getting the type of behavior you are interested in. The big unknown in
each run is the role that will be played by chance events. The biological throw of the
dice is the final determinant of whether interesting behavior will be observed or not.
Holland (1995, p.10) proposes seven mechanisms and properties that he considers
to be present in a CAS. Are they present in the behavior of jECHO? Considering
each one in turn:
•
Aggregation (Property): Aggregation concerns “the emergence of complex
large-scale behaviors from the aggregate interactions of less complex agents.”
Holland (1995, p.11). What can be said here with regards jECHO is that the
groundwork has been laid for future exploration of emergence through the
adhesion mechanism. Holland mentions that the ability of agents to aggregate
into multi-agents, which exhibit their own properties beyond those shown by the
individual agents, is a feature of CAS. A number of the jECHO simulations
showed the formation of boundary structures as a result of adhesion tag match
scoring. The next step would be to implement the mechanisms described in
Model 6 (1995, p.123), which include multi-agent properties, and behaviors
possessed by an aggregate formed through adhesion.
55
•
Tagging (Mechanism): The Tagging mechanism is designed into ECHO from
scratch, so it is not surprising that it works quite well. The importance of tag
configuration becomes very apparent when setting up a simulation run. What
might appear to be minor changes to one or more tags can have a dramatic
impact on the course of a simulation. Echo clearly has this mechanism. Tag
mediated interaction is an interesting concept that could be a useful technique for
more conventional multi-agent based systems where agents need a way to
quickly distinguish between various agent types.
•
NonLinearity (Property): Holland defines the simple case of linear behavior as
“we can get a value for the whole by adding up the value of its parts” (1995,
p.15). When behavior in jECHO is at a steady state with the population either flat
for, or rising at a steady straight line pace, then I think it is fair to say that we are
observing linear behavior. In other cases when we see rapid whipsaw changes in
direction, this is clearly not linear but seems to have become chaotic. The
disruptive event that causes the emergence of chaotic behavior being a change
in the chromosome of at least one of the agents comprising the population.
•
Flows (Property): Holland (1995, p.23-25) mentions two flow related effects.
These being the “multiplier effect” and the “recycling effect”. The recycling effect
comes into play when agents return their resources to a site through death.
These resources are then available to be acquired by other agents that have
adapted their tags to take advantage of this opportunity. The multiplier effect
becomes particularly noticeable when a resource transformation converts a ready
supply of low use resource to a needed resource, which enables the agent to
reproduce and pass on its resource transforming capabilities.
•
Diversity (Property): Holland (1995, p.31) states that perpetual novelty is the
hallmark of CAS. I believe that a subset of ECHO configurations exist where this
is most likely true. On the other hand, most ECHO configurations (e.g., mutation
56
rate, resource flow rate, tag and condition initial conditions), will not lead to
interesting behavior within a reasonable time span. On some of the graphs it can
be seen that dramatic change can occur through a chance event that brings
about a new adaptation. Diversity is clearly in possible within ECHO.
•
Internal Models (Mechanism): An organism builds an internal model to help it
make predictions about and operate in its environment. Two forms of internal
model may be operational; these are the tacit variety and models that are explicit.
A tacit model could be likened to the impulse that drives a bacterium towards a
food source by following a chemical gradient. The explicit model would be more
akin to the mental exploration of possible chess moves prior to making a move.
[Holland (1995, p.31)]. Having an internal model of the world that enables one to
make predictions and hence anticipate the future could be of significant
evolutionary value. In a sense the agents within ECHO that perform best and
spread their genetic material the furthest through a population could be thought to
have the ‘best’ internal model. The internal model within ECHO is implicit in the
sense that it is coded into the types of interactions that an agent can have with its
environment. These models evolve through the mechanisms of crossover and
mutation. In a related thought, a new internal model encapsulated within a new
agent chromosome can be considered as a new hypothesis about the world and
how best to live successfully in it. Holland makes a similar observation in (1995,
p.53). The agent’s environment and chance events will determine whether the
hypothesis is successful or not.
•
Building Blocks (Mechanism): Building blocks are the fragments of agent
chromosome that become components of a new chromosomal hypothesis on the
birth of a new agent. If the arrangement of building blocks in an agent is effective
at collecting resources it will propagate itself throughout the population. Should
the environment change then the effectiveness of a building block may decrease
to be replaced by a new one more able to exploit its circumstances. On some of
57
the graphs in chapter 5 we can see where an event occurs and either a rapid
ascent or descent follows as the effectiveness or otherwise of particular blocks
responds to the new environment in which it finds itself. Holland (1995, p.37)
claims, “use of building blocks to generate internal models is a pervasive feature
of complex adaptive systems.” ECHO has this feature by design.
58
CHAPTER 6
CONCLUSIONS AND FURTHER WORK
Conclusions
This project has succeeded in delivering a new version of ECHO. The focus of this
project has been the design and implementation of the ECHO models described by
Holland (1995). A subsidiary aim has been to elicit information about the chacteristics
of jECHO’s dynamic behavior.
With respect to the question of whether jECHO exhibits behaviors believed to be
common to CAS, in this research I have concluded that the answer is “it depends”.
Having run literally hundreds of tests with jECHO I have seen all manner of behavior,
from agent populations that show initial vibrant behavior that quickly dies out, to
those that seem to be dead but suddenly sweep into life showing high peaks followed
by dramatic valleys. In between there are a myriad simulations that show stair step
like increases for many generations followed by eventual stagnation or a quick death.
Is perpetual novelty from a system such as jECHO possible? Though not easy it is
certainly possible to configure a simulation that will show interesting evolutionary
behavior that continues over several thousand generations. However, would this
simulation still display interesting behavior after one million generations? How about
after a hundred million generations? What is needed is a way to be able to
characterize a simulation to know whether it has the ability to show perpetual novelty
or will most likely die out at some point in the future. Perhaps a classification
technique can be devised similar to Wolfram’s classification for the behavior of
Cellular Automata (Wolfram 1983) to enable prediction of evolutionary behavior for a
CAS implementation.
59
On the question of whether the seven properties and mechanisms proposed by
Holland (1995, p.10) reveal themselves in the behavior of jECHO. As noted in
Chapter 5, these properties are largely designed in to the model from scratch. What
is perhaps more interesting is whether it would be possible for the ECHO
mechanisms and properties themselves to evolve from a primal soup of resources? A
“Proto” ECHO perhaps.
With the implementation of jECHO as it currently stands it is not possible to quantify
the contribution of each feature to CAS behavior, a lack that will be addressed in the
future work section of this chapter. Better analytical tools and a complete
implementation including the mechanisms in Model 6 Holland (1995, p.123) are
required before we can make a determination as to whether ECHO is truly a CAS.
Given the complexity of the multitude of parallel interactions taking place within
ECHO it is likely that there are interesting behaviors that we just are not aware of.
We need better tools with which to see.
Much still remains to be done before jECHO could be called truly complete. Specific
suggestions for where work on jECHO should go next are included in the “Further
Work” section of this chapter.
Further Work
The following are areas where in my opinion time could be profitably spent
developing jECHO:
•
Improve performance: To be able to set up simulation runs of sufficient
complexity and to be able to run them for hundreds of thousands of
generations will require significant improvements to be made to the
60
performance of jECHO. More analysis needs to be applied to find out where
the bottlenecks are and whether gains can be made in using alternative
collection designs than the ones currently implemented.
•
Implement model 6: The final model described in Holland (1995) is
potentially the most fruitful. The full implementation of a multi-agent aggregate
may open the door to insights on how metazoans develop from a single cell
and cast light on the connection between the genotype and the phenotype.
•
Devise tools that enable observation of complex activity: An immense
number of interactions and events are occurring in parallel within jECHO.
New tools and new ways of observing complexity are needed if much
headway is to be made toward a theory of CAS.
•
Devise classifications that enable predictions about a particular CAS:
Developing the work started by Bedau et al, (1998) on long term evolutionary
dynamics may allow greater insight into where the interesting behavior can be
found within the ECHO model and possibly how the model can be developed
further.
61
References Cited
Axtell, R (2000) Why Agents? On the Varied Motivations for Agent Computing in the Social
Sciences. The Brookings Institution.
<http://www.brookings.edu/es/dynamics/papers/agents/agents.htm>
[Accessed 17 January, 2005]
Bedau, M.A., (1999) Can Unrealistic Computer Models Illuminate Theoretical Biology? In
Proceedings of the 1999 Genetic and EvolutionaryComputation Conference Workshop
Program, Orlando, Florida, July 13, 1999,Annie S. Wu, ed., pp. 20-23.
<http://citeseer.ist.psu.edu/bedau99can.html>
[Accessed 17 January, 2005]
Bedau, M.A., Snyder, E., and Packard, N.H. (1998). A classification of long-term
evolutionary dynamics. In Adami, C., Belew, R., Kitano, H., and Taylor, C., editors, Artificial
Life VI. MIT Press.
<http://citeseer.ist.psu.edu/bedau98classification.html>
[Accessed 17 January, 2005]
Collier et. al. (2004) RePast: MultiAgent Simulation Toolkit version 2.2
<http://repast.sourceforge.net/>
[Accessed 17 January, 2005]
Cuvelier, B., Preux P. and Cambier C. (1997) Studying Adaptation with ECHO.
<http://citeseer.ist.psu.edu/104353.html>
[Accessed 17 January, 2005]
Dominiak, D.M., Rinaldo, F., Evans, M.W. (2001) Effects of limited resources in 3D realtime simulation of an extended ECHO complex adaptive system model. AIP Conference
Proceedings Vol 583(1) pp. 258-260. 2001
<http://conferences.fnal.gov/acat2000/program/papers/posters/p102_paper.doc>
[Accessed 17 January, 2005]
Dooley, K. (1996) A Nominal Definition of Complex Adaptive Systems, "The
Chaos Network, 8(1): 2-3.
<http://www.public.asu.edu/~kdooley/papers/casdef.PDF>
[Accessed 17 January, 2005]
Epstein, J. M. and Axtell, R. (1996) Growing Artificial Societies - Social Science from the
Bottom Up. MIT Press, Cambridge, MA.
Forrest, S. and Jones, T. (1994) Modeling Complex Adaptive Systems with ECHO. In
Complex Systems: Mechanisms of Adaptation. Stoner R.J. and Yu X.H. : IOS Press 1994.
<http://citeseer.ist.psu.edu/stephanie94modeling.html>
[Accessed 17 January, 2005]
Fowler, M. and Scott, K. (2000) UML Distilled. Addison Wesley. Pearson Education.
Gell-Mann, M. (1994) The quark and the jaguar. New York: WH Freeman.
Harris, D.L. (2001) Echo Implemented: A Model for Complex Adaptive Systems
Computer Experimentation. SAND2001-2097. Sandia National Laboratories.
<http://www.osti.gov/energycitations/product.biblio.jsp?osti_id=786628>
[Accessed 17 January, 2005]
62
Holland, John H, Holyoak, K.J., Nisbett, R.E., and Thagard, P.A. (l986) Induction: Processes
of Inference, Learning, and Discovery, MIT Press.
Holland, John. H. (1992) Adaptation in Natural and Artificial Systems, MIT Press.
Holland, John H. (1994) Echoing Emergence: Objectives, Rough Definitions, and
Speculations for ECHO-Class Models (Page 309-333) in Complexity Metaphors, Models, and
Reality, Perseus Books.
Holland, John. H. (1995) Hidden Order, Helix Books.
Holland, John H. (1995) Can There Be a Unified Theory of Complex Adaptive Systems? from
The Mind, The Brain, and Complex Adaptive Systems, Proceedings Volume from Santa Fe
Institute Studies in the Sciences of Complexity. Addison Wesley.
Hraber, P.T., Milne, B.T. (1996) Community assembly in a model ecosystem.
<http://citeseer.ist.psu.edu/hraber96community.html>
[Accessed 17 January, 2005]
Hraber, P.T., Jones, T., and Forrest, S. (1997) The Ecology of Echo. Artificial Life, 3:165190.
<http://citeseer.ist.psu.edu/hraber96ecology.html>
[Accessed 17 January, 2005]
Jones, T. and Forrest, S. (1993) An Introduction to SFI Echo. Technical Report 93-12-074,
Santa Fe Institute.
<ftp://ftp.santafe.edu/pub/echo/how-to.ps.Z>
[Accessed 1 December, 2004]
Larman, C. (2001) Applying UML and Patterns: An Introduction to Object-Oriented Analysis
and Design and the Unified Process (2nd Edition)", Prentice Hall.
Lotka, A.J. (1956) Elements of Mathematical Biology. Dover.
Minar, N., Burkhart, R., Langton, C., Askenazi, M. (1996) The Swarm Simulation System: A
Toolkit for Building Multi-agent Simulations
<http://www.santafe.edu/projects/swarm/swarmdoc/swarmdoc.html>
[Accessed 17 January, 2005]
Mitchell, M. and Forrest, S. (1993) Genetic Algorithms and Artificial Life.
<http://citeseer.ist.psu.edu/mitchell93genetic.html>
[Accessed 17 January, 2005]
Packard. N.H. (1988) Evolving Bugs in a simulated ecosystem. Intrinsic adaptation in a
simple model for evolution. In C.G. Langton, editor, Artificial Life, volume I of Santa Fe
Institute Studies in the Sciences of Complexity, pages 141–155, Reading, MA, 1988. AddisonWesley.
<http://www.santafe.edu/sfi/publications/Bookinforev/al1new.html>
[Accessed 1 December, 2004]
Ray, T.S. (1992) Evolution, Ecology and Optimization of Digital Organisms. Santa Fe
Institute Working Paper 92-08-042
<http://citeseer.ist.psu.edu/27898.html>
[Accessed 17 January, 2005]
63
Reason, P. and Goodwin (1999) Toward a science of qualities in organizations: lessons from
Complexity theory and postmodern biology
<http://www.psych.lse.ac.uk/complexity/PDFiles/publication/goodwen.pdf>
[Accessed 17 January, 2005]
RePast (2004) How to Run a RePast Simulation
<http://repast.sourceforge.net/tutorials/simstart.html>
[Accessed 17 January, 2005]
Schmitz, O.J. and Booth, G. (1997) Modeling food web complexity: the consequences of
individual-based, spatially explicit behavioral ecology on trophic interactions.
Evolutionary Ecology 11:379-398.
<http://www.cbc.yale.edu/old/cce/papers/gecko.html>
[Accessed 17 January, 2005]
Scott, K. (2001) UML Explained. Addison Wesley. Pearson Education.
Smith R.M. and Bedau, M.A. (1997) Emergence of Complex Ecologies in ECHO.
<http://citeseer.ist.psu.edu/smith97emergence.html>
[Accessed 17 January, 2005]
Smith, R.M. and Bedau, M.A. (1999) Is ECHO a Complex Adaptive System?
<http://citeseer.ist.psu.edu/298657.html>
[Accessed 17 January, 2005]
Waldrop, M. (1992) Complexity: the emerging science at the edge of chaos.
Simon & Schuster, New York.
<http://www.amazon.com/exec/obidos/tg/detail//0671872346/ref=ase_principiacyberneA/102-93388110924940?v=glance&s=books>
[Accessed 17 January, 2005]
Wolfram, S. (1983) Cellular Automata
<http://www.stephenwolfram.com/publications/articles/ca/83-cellular/index.html>
[Accessed 3 February, 2005]
ECHO Santa Fe Web Site
http://www.santafe.edu/projects/echo/echo.html
[Accessed 14 February, 2005]
64
Appendix A: GLOSSARY OF TERMS
65
CHROMOSOME
A chromosome is a structure which contains genes.
ENDOGENOUS
Produced from within by the agent as opposed to exogenous which would be
imposed from outside the agent.
GENE
Units of hereditary information passed from parent to offspring. The genes are
carried in the chromosome.
GENOTYPE
The entire genetic makeup of an agent, the set of all genes making up an individual.
PHENOTYPE
The observable characteristics of an agent, the physical expression of its genotype.
TROPHIC
Feeding interrelationships between agents, such as appear in a food web.
66
Appendix B: jECHO USE CASE DESCRIPTIONS
67
Use Case Descriptions
Use Case ID:
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
jECHO Project – Use Case Scenario
JE-001
Configure a Model Run
This is the UI through which a researcher will choose which
parts of the model to configure.
Researcher
A choice of which part of the model to configure has been
made.
Configure Model Menu is invoked.
Actor
System
1. Choose one of the
following options to
configure:
a. Setup World
Parameters
b. Setup Site
Parameters
c. Setup Agent
Parameters
d. Setup Simulation
Parameters
2. The Selected
Configuration screen is
invoked.
Alternative Path:
Exception Path:
Use Case ID:
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
jECHO Project – Use Case Scenario
JE-002
Setup World Parameters
This use case provides the ability to setup and modify
jECHO parameters at the World level
Researcher
World parameters are configured
User invoked Setup World Parameters choice
Actor
System
1. Enter the World
Parameters (to be
identified in the Domain
Model)
2. The System stores the
World Parameters
Alternative Path:
Exception Path:
Use Case ID:
jECHO Project – Use Case Scenario
JE-003
68
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
Setup Site Parameters
This use case provides the ability to setup and modify ECHO
parameters at the Site level
Researcher
Site parameters are configured
User invoked Setup Site Parameters choice
Actor
System
1. Enter the Site Parameters
(to be identified in the
Domain Model)
2. The System stores the
Site Parameters
Alternative Path:
Exception Path:
Use Case ID:
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
jECHO Project – Use Case Scenario
JE-004
Setup Agent Parameters
This use case provides the ability to setup and modify ECHO
parameters at the Agent level
Researcher
Agent parameters are configured
User invoked Setup Agent Parameters choice
Actor
System
1. Enter the Agent
Parameters (to be
identified in the Domain
Model)
2. The System stores the
Agent Parameters
Alternative Path:
Exception Path:
Use Case ID:
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
jECHO Project – Use Case Scenario
JE-005
Setup Simulation Parameters
This use case is for setting up simulation parameters such
as the number of generations to simulate and the specific
ECHO model to run.
Researcher
Simulation parameters are configured
User invoked Setup Simulation Parameters choice
Actor
System
1. Enter the number of
generations to simulate.
69
2. Select the ECHO model to
simulate.
3. The System stores the
Simulation Parameters
Alternative Path:
Exception Path:
Use Case ID:
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
jECHO Project – Use Case Scenario
JE-006
Run a Model
This use case is for the researcher to run the selected
ECHO model.
Researcher
All configuration files have been set up.
The model has executed and the data has been written to a
file.
The researcher signals to run the model.
Actor
System
1. Select the Run option.
2. The System runs the
selected ECHO model.
3. The model run data is
collected in a file.
Alternative Path:
Exception Path:
Use Case ID:
Use Case Name:
Use Case Description:
Actor(s):
Preconditions:
Postconditions:
Trigger:
Normal Path:
jECHO Project – Use Case Scenario
JE-007
Display Data from a Model Run
This use case describes the steps to display the data from a
model run.
Researcher
The model has been executed and a data file exists
The model run data is displayed in both tabular and
graphical form.
The researcher requests to see data for the selected model
run.
Actor
System
1. Select the model run data
to display.
2. Request display of the
selected data.
3. The system displays the
selected model data.
Alternative Path:
Exception Path:
70
Appendix C: DETAILED LIST OF ECHO TEST
PARAMETERS
71
1. Caterpillar-Ant-Fly Ecological Triangle
Agent Tag and Condition configurations
Caterpillar
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
cccc
aabb
aaaa
aaa
c
dca
2
aaaabbbbccccdddd
Ant
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
aaaa
cb
bbbb
cccc
aaa
ca
2
aaaabbbbccccdddd
Fly
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
aabb
aaaa
cccc
abcd
aab
ca
2
aaaabbbbccccdddd
Resource Tags for Ecological Triangle Simulations
Simulation 1 of Caterpillar-Ant-Fly Ecological Triangle
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
aab
cccc
aaabbbcccddd
Simulation 2 of Caterpillar-Ant-Fly Ecological Triangle
72
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
aab
cccc
aaabbbcccddd
Simulation 3 of Caterpillar-Ant-Fly Ecological Triangle
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
aab
cccc
aaabbbcccddd
2. Mutation Rate Simulation
Agent Tag and Condition configurations
Agent 1
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
ccac
dabb
aaaa
d
d
dcb
2
aaaabbbbccccdddd
Agent 2
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
abaa
cbaa
abab
aaad
d
cab
2
aaaabbbbccccdddd
Agent 3
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
aabb
aaaa
acac
d
d
cad
73
Resource Transform Rate
Resource Reservoir (Initial)
2
aaaabbbbccccdddd
Agent 4
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
aacd
abca
abac
d
d
dba
2
aaaaaabbbbbbaacccccddd
Resource Tags for Mutation Rate Simulations
Simulation 1 of Mutation Rate
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
abcd
abbd
aaaabbbbccccdddd
Simulation 2 of Mutation Rate
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
abcd
abbd
aaaabbbbccccdddd
Simulation 3 of Mutation Rate
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
abcd
abbd
aaaabbbbccccdddd
Simulation 4 of Mutation Rate
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
abcd
abbd
aaaabbbbccccdddd
74
Simulation 5 of Mutation Rate
Tag or Condition
Value
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
abcd
abbd
aaaabbbbccccdddd
3. Multi-Site Simulation
Agent Tag and Condition configurations
Agent 1
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
abac
acad
abdc
cd
ad
da
3
aaaabbbbccccdddd
Agent 2
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
acaa
cdad
bbcb
cd
ad
db
3
aaaabbbbccccdddd
Agent 3
Tag or Condition
Value
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
ddac
daac
bac
cd
cd
dab
2
aaaabbbbccccdddd
Agent 4
Tag or Condition
Value
75
Offense Tag
Defense Tag
Adhesion Tag
Exchange Condition
Mating Condition
Resource Transform Condition
Resource Transform Rate
Resource Reservoir (Initial)
cbac
acad
cbc
ad
cd
abc
3
aaaaaabbbbbbaacccccddd
Resource Tags for Multi-Site Simulation
Site 1, 5, 9, 13
Tag or Condition
Value
Site Resource
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
Resource Rate
cbd
accd
aacd
aaaabbbbccccdddd
5
Site 2, 6, 10, 14
Tag or Condition
Value
Site Resource
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
Resource Rate
abcd
ccda
badc
aabbbbbbbbbbddd
3
Site 3, 7, 11, 15
Tag or Condition
Value
Site Resource
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
Resource Rate
bcd
bcda
bcad
aabbbbbddd
6
Site 4, 8, 12, 16
Tag or Condition
Value
Site Resource
Resource Offense Tag
Resource Defense Tag
Resource Reservoir
Resource Rate
bbca
cabd
bcac
aabbbbbccccccddd
7
76
Appendix D: CODE INSTALLATION DETAILS
77
JECHO Requirements and Installation Instructions
Requirements
To run jECHO you will need:
1. Java J2SE 1.4.2_xx Run Time Environment (JRE)
2. RePast Simulator version 2.2
3. jECHO class files installed from the jECHO_install.zip file
4. A fast PC with lots of memory. The faster the better.
To edit jECHO code (e.g., change tags and conditions) you will need:
1. Java J2SE 1.4.2_xx Software Development Kit
(SDK)
2. An IDE for editing and compiling. I recommend
JCreator Lite V3.5at the following site which is a
free download
http://www.jcreator.com/download.htm
Installation
The following instructions cover 2 sets of needs. If you just want to be able to run the
simulator and not change the code, then follow Installation Steps A. If you want
complete control and be able to change the code then follow Installation Steps B.
Installation Steps: A – Run jECHO only
1. You must have a Java Virtual Machine installed. Any of the J2SE 1.4.2_xx
versions should work. If you need to install Java use the following link and
follow Sun’s instructions:
http://java.sun.com/j2se/1.4.2/download.html
2. You will need to install the RePast Simulation environment.
jECHO was developed using RePast version 2.2
If you need to download the RePast Simulator then use the following link:
https://sourceforge.net/project/showfiles.php?group_id=1703&package_id=16
55
(Note: Make sure you download version 2.2 which is repast-2.2.zip, do
NOT download version 3.0 of repast as it is a new release which has not
been tested with jECHO)
To install RePast-2.2.zip, double click on the zip file. Make sure that you
install RePast into the C:\RePast-2.2 directory.
3. You will then need to install the jECHO class files. To do this download
the jECHO_install.zip from
http://www.brianmcindoe.com
Place the file on your desktop and double click on the jECHO_install.zip file
78
4. Make sure that your CLASSPATH environment variable includes the
following:
C:\jECHO\dev\classes;c:\RePast-2.2\lib\repast.jar
To Run jECHO
1. Use Windows Explorer to navigate to the c:\RePast-2.2\lib directory and
Double click on the repast.jar file.
2. You should see the RePast controller displayed on your screen as
follows:
3. Click on the ‘Open Folder’ icon on far left of the RePast controller
You will see the “Load Model” dialog box.
4. Click on the Add button.
You will be presented with “File Open” box. Navigate to the folder location where
the jECHO.class file is located. This will be at the following:
C:\jECHO\dev\classes\com\brianmcindoe\jecho\jEcho.class
79
Click on the JEcho.class file and then click Open.
You will then see the following with a new entry under “Other Models”
5. Highlight jEcho if it is not already highlighted and then press the Load
button.
The jEcho model will then be loaded into RePast and you will be presented
with the following parameter settings box.
80
You can change any of the Parameters but do not change the ‘RePast Parameters’.
6. Some of the buttons in the RePast toolbar will no longer be grayed out. To
start the simulation, press the Play (Triangle pointing to the right) button.
You will then see the following:
81
You may have to rearrange the windows on your screen and resize some of the
boxes to match the display above. In the center is the “Agent Stats.” Graph. At the
bottom is the repast output screen, which just provides Java console output and
messages noting happenings in the model. The “Echo Model Agent” and “Echo
Model Resource” windows are click-able and provide much more information about
the individual agents and resources at each site.
Installation Steps: B – Modify, Compile and Run jECHO
If you are somewhat proficient in Java and need to modify the simulation for your
own purposes, then the best thing to do is to download an IDE and set it up so that
you can edit the jECHO code and rebuild it against the RePast libraries. I use
JCreator v3.5 which is freeware, however, JBuilder or any of the similar IDE’s should
be able to be configured to do something similar.
Assuming you have Jcreator you will need to include the RePast library in your
classpath and you do that by selecting “Project Properties” from the Project menu
and then clicking the New button to add the library to the project.
82
You should now be able to make whatever changes you want and then compile to
class files, and run the main class through the RePast simulator as described above.
83
Appendix E: SOURCE CODE LISTINGS
84
/*********************************************************************************
Module Name:
JEcho.java
Description:
This is the main class for the JEcho multiagent simulation.
This class contains the main method for running the model.
The buildModel() method creates the objects necessary to run
JEcho, the buildSchedule() method schedules when model update
methods are to run, and buildDisplay() takes care of updating
the screen.
Author:
Date:
Version:
This model uses the RePast multiagent toolkit as a foundation.
The mechanisms built into JEcho are based on the descriptions
of the Echo model published in Hidden Order (1995) by John
Holland.
Brian W. McIndoe
2/12/2005
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.awt.Color;
import java.util.ArrayList;
import uchicago.src.sim.analysis.*;
import uchicago.src.sim.engine.BasicAction;
import uchicago.src.sim.engine.Schedule;
import uchicago.src.sim.engine.SimInit;
import uchicago.src.sim.engine.SimModelImpl;
import uchicago.src.sim.gui.DisplaySurface;
import uchicago.src.sim.gui.ColorMap;
import uchicago.src.sim.gui.MultiObject2DDisplay;
import uchicago.src.sim.gui.Object2DDisplay;
import uchicago.src.sim.space.Multi2DTorus;
public class JEcho extends SimModelImpl {
private static final int NUMAGENTS = 150;
// total number of agents
private static final int WORLDXSIZE = 4;
// x dimension of site grid
private static final int WORLDYSIZE = 4;
// y dimension of site grid
private static final float FLEEPROB = 0.01f;
// prob an agent can flee from combat
private static final float MIGRATEPROB = 0.05f; // prob an agent will migrate to another site
private static final float MUTATEPROB = 0.0005f;// prob an agent will suffer mutation
private static final float DEATHRATE = 0.03f;
// prob an agent will die
private static final float INTERACTFRAC = 0.5f;
// fraction of agents interacting each cycle
private int numAgents = NUMAGENTS;
private int worldXSize = WORLDXSIZE;
private int worldYSize = WORLDYSIZE;
private float fleeProb = FLEEPROB;
private float migrateProb = MIGRATEPROB;
private float mutateProb = MUTATEPROB;
private float deathRate = DEATHRATE;
private float interactFrac = INTERACTFRAC;
// variables for repast parameter window
private Schedule schedule;
private DataRecorder recorder;
private DataRecorder recorderO;
// scheduler object for repast
// recorder object for repast
private OpenSequenceGraph graph;
private EchoModel1 echoModel1;
private EchoModel2 echoModel2;
private EchoModel3 echoModel3;
private EchoModel4 echoModel4;
private EchoModel5 echoModel5;
private EchoBoundary echoBoundary;
private EchoSite eSite;
private EchoResource r;
private String resource [] = {"a", "b", "c", "d"};
private String s;
private DisplaySurface displaySurf;
// graph object for repast
// echo model 1 object
// echo model 2 object
// echo model 3 object
// echo model 4 object
// echo model 5 object
// a boundary object for aggregates
// a site object
// an echo resource
// the world alphabet
// display surface object for repast
85
private DisplaySurface displaySurfRes;
// the display object for resources
public JEcho(){}
public String getName(){
return "jEcho";
}
// required for repast simulator
public void setup(){
System.out.println("Running setup");
eSite = null;
// initalize objects
echoModel1 = null;
echoModel2 = null;
echoModel3 = null;
echoModel4 = null;
echoModel5 = null;
echoBoundary = null;
schedule = new Schedule(1);
// Tear down Displays
if (displaySurf != null){
displaySurf.dispose();
}
displaySurf = null;
displaySurf = new DisplaySurface(this, "Echo Model Agents Window");
// Register Displays
registerDisplaySurface("Echo Model Window 1", displaySurf);
if (displaySurfRes != null){
displaySurfRes.dispose();
}
displaySurfRes = null;
displaySurfRes = new DisplaySurface(this, "Echo Model Resources Window");
// Register Displays
registerDisplaySurface("Echo Model Window 2", displaySurfRes);
}
public void begin(){
buildModel();
buildSchedule();
buildDisplay();
displaySurf.display();
displaySurfRes.display();
graph.display();
}
// when the start button is pushed
// create the model objects
// schedule the model steps
// display the model
// The following creates an agent count data source for graphs, files.
class NumDataSource implements NumericDataSource, Sequence {
public double execute() {
return getSValue();
}
public double getSValue(){
return echoModel5.siteAgentCountTotal;
}
};
// The following creates a number of boundaries data source for aggregate reporting
class NumBoundaries implements NumericDataSource, Sequence {
public double execute() {
return getSValue();
}
public double getSValue(){
return echoBoundary.getNumberOfAgentsInABoundary();
}
};
// The following is a test to see if agent toString can be written to a file
class TestDataSource implements DataSource {
86
public Object execute() {
EchoAgent ea = (EchoAgent)echoModel5.siteAgentList.get(0);
String eas = ea.toString();
return eas;
}
};
// Build the objects used by the model
public void buildModel(){
System.out.println("Running BuildModel");
// Build the collection of Echo Sites (the World)
eSite = new EchoSite(worldXSize, worldYSize);
// Add new agents to sites in the world
for(int i = 0; i < numAgents; i++){
addNewAgent(i%4);
}
// Add resources to each site
for(int i = 0; i < worldXSize; i++){
for(int j = 0; j < worldYSize; j++){
int k;
k = j % 4;
addResource(i, j, k);
}
}
// Build the object(s) that contain the logic for Echo
echoBoundary = new EchoBoundary();
echoModel5 = new EchoModel5(eSite, worldXSize, worldYSize, fleeProb,
migrateProb, mutateProb, deathRate, interactFrac);
recorder = new DataRecorder("./data.txt", this, "Model Numeric Values");
recorderO = new DataRecorder("./objects.txt", this, "Model Objects");
recorder.addNumericDataSource("numAgents", new NumDataSource());
recorder.addNumericDataSource("numBoundaries", new NumBoundaries());
recorderO.addObjectDataSource("ToString", new TestDataSource());
graph = new OpenSequenceGraph("Agent Stats.", this);
}
// Add new agents to the new model
private void addNewAgent(int i){
EchoAgent a = new EchoAgent(i);
eSite.addAgent(a);
}
// Add resources to the sites
private void addResource(int x, int y, int resType){
r = new EchoResource(x, y, resType);
eSite.addResource(x, y, r);
}
// The following sets up the model execution schedule
public void buildSchedule(){
System.out.println("Running BuildSchedule");
class EchoStep extends BasicAction {
public void execute() {
//Execute a step of the model1
echoModel5.step(getTickCount());
recorder.record();
recorderO.record();
graph.step();
displaySurf.updateDisplay();
displaySurfRes.updateDisplay();
}
}
schedule.scheduleActionBeginning(0, new EchoStep());
schedule.scheduleActionAtPause(recorder, "writeToFile");
schedule.scheduleActionAtPause(recorderO, "writeToFile");
schedule.scheduleActionAtPause(graph, "writeToFile");
schedule.scheduleActionAtEnd(recorder, "writeToFile");
87
schedule.scheduleActionAtEnd(recorderO, "writeToFile");
schedule.scheduleActionAtEnd(graph, "writeToFile");
}
// The following builds the model display which will be updated every cycle
public void buildDisplay(){
System.out.println("Running BuildDisplay");
ColorMap map = new ColorMap();
for(int i = 1; i<16; i++){
map.mapColor(i, new Color((int)(i * 8 + 127), 0, 0));
}
map.mapColor(0, Color.white);
// Create a probeable display for the agents by site
MultiObject2DDisplay displayAgents = new MultiObject2DDisplay(eSite.getCurrentAgentSite());
displaySurf.addDisplayableProbeable(displayAgents, "Agents");
addSimEventListener(displaySurf);
// Create a probeable display for the resources by site
Object2DDisplay displayResources = new Object2DDisplay(eSite.getCurrentResourceSite());
displaySurfRes.addDisplayableProbeable(displayResources, "Resources");
addSimEventListener(displaySurfRes);
// Add the number of agents and number of boundaries to the updating graph
graph.addSequence("NumAgents", new NumDataSource());
graph.addSequence("NumBoundaries", new NumBoundaries());
// Set up the graph axes dimensions
graph.setAxisTitles("Time", "Population");
graph.setXRange(0, 200);
graph.setYRange(0, 200);
graph.setSize(400, 250);
}
// Required for Repast
public Schedule getSchedule(){
return schedule;
}
// Required for Repast - These are the settable parameters
public String[] getInitParam(){
String[] initParams = { "NumAgents", "WorldXSize", "WorldYSize",
"FleeProb" , "MigrateProb", "MutateProb", "DeathRate", "InteractFrac" };
return initParams;
}
// The getters and setters for this class follow
public int getNumAgents(){
return numAgents;
}
public void setNumAgents(int na){
numAgents = na;
}
public int getWorldXSize(){
return worldXSize;
}
public void setWorldXSize(int wxs){
worldXSize = wxs;
}
public int getWorldYSize(){
return worldYSize;
}
public void setWorldYSize(int wys){
worldYSize = wys;
}
public float getFleeProb(){
return fleeProb;
}
88
public void setFleeProb(float fp){
fleeProb = fp;
}
public float getMigrateProb(){
return migrateProb;
}
public void setMigrateProb(float mp){
migrateProb = mp;
}
public float getMutateProb(){
return mutateProb;
}
public void setMutateProb(float mup){
mutateProb = mup;
}
public float getDeathRate(){
return deathRate;
}
public void setDeathRate(float dr){
deathRate = dr;
}
public float getInteractFrac(){
return interactFrac;
}public void setInteractFrac(float ifr){
interactFrac = ifr;
}
// The JEcho main() method
public static void main(String[] args) {
SimInit init = new SimInit();
JEcho model = new JEcho();
init.loadModel(model, "", false);
}
}
/*********************************************************************************
Module Name:
EchoSite.java
Description:
This is the class which is responsible for creating and managing
sites within the JEcho world.
Author:
Brian W. McIndoe
Date:
2/11/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.util.*;
import uchicago.src.sim.space.Multi2DTorus;
import uchicago.src.sim.space.Object2DGrid;
public class EchoSite {
private Multi2DTorus agentSites;
private Object2DGrid resourceSites;
private int x;
private int y;
// Define the Multi2DTorus on which the sites reside
// Define the 2DGrid for resource management
// The site location in the x dimension
// The site location in the y dimension
// The constuctor to use with x and y dimensions
public EchoSite(int xSize, int ySize){
89
agentSites = new Multi2DTorus(xSize, ySize, false);
resourceSites = new Object2DGrid(xSize, ySize);
x = xSize;
y = ySize;
}
// Add new agent to a random site (Initialization)
public void addAgent(EchoAgent agent){
int x = (int)(Math.random()*(agentSites.getSizeX()));
int y = (int)(Math.random()*(agentSites.getSizeY()));
agentSites.putObjectAt(x,y,agent);
agent.setXY(x,y);
agent.setEchoSite(this);
}
// Add agent to a specific site
public void addAgentToSite(EchoAgent agent){
agentSites.putObjectAt(agent.getX(), agent.getY(), agent);
}
// Add a resource object to a site
public void addResource(int x, int y, EchoResource resource){
resourceSites.putObjectAt(x,y,resource);
}
// Get the resource at a particular site
public EchoResource getResource(int x, int y){
EchoResource rr = null;
if (resourceSites.getObjectAt(x, y) != null){
rr = (EchoResource)resourceSites.getObjectAt(x,y);
}
return rr;
}
// Get an agent at a particular site
public EchoAgent getAgentAt(int x, int y){
EchoAgent retVal = null;
if(agentSites.getObjectAt(x, y) != null){
retVal = (EchoAgent)agentSites.getObjectAt(x,y);
}
return retVal;
}
// Get a reference to the torus
public Multi2DTorus getCurrentAgentSite(){
return agentSites;
}
// Get a reference to the resource grid
public Object2DGrid getCurrentResourceSite(){
return resourceSites;
}
// Get a list of agents at a site
public List getObjectsAt(int x, int y){
return agentSites.getObjectsAt(x, y);
}
// Remove an agent from a site
public void removeAgent(EchoAgent ea){
agentSites.removeObjectAt(ea.getX(), ea.getY(), ea);
}
// Migrate an agent from a site
public void migrateAgent(EchoAgent ea){
// Remove object from its old site
agentSites.removeObjectAt(ea.getX(), ea.getY(), ea);
// Determine its new site randomly
int newX = (int)(Math.random()*(agentSites.getSizeX()));
int newY = (int)(Math.random()*(agentSites.getSizeY()));
// Put the agent at its new site
90
agentSites.putObjectAt(newX, newY, ea);
ea.setXY(newX, newY);
}
// Replenish site reservoirs
public void replenishSites(){
for (int i=0; i<x; i++){
for (int j=0; j<y; j++){
StringBuffer sb = new StringBuffer();
EchoResource r = (EchoResource)resourceSites.getObjectAt(i,j);
int rr = r.getResourceRate();
String rs = r.getSiteResource();
String res = r.getResourceReservoir();
sb.append(res);
for (int k=0; k<rr; k++){
sb.append(rs);
}
r.setResourceReservoir(sb.toString());
r = null;
rs = null;
res = null;
sb = null;
}
}
}
}
/*********************************************************************************
Module Name:
EchoResource.java
Description:
This is the class which is responsible for creating and managing
resources within a JEcho site.
Author:
Brian W. McIndoe
Date:
2/11/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
import java.awt.Color;
import uchicago.src.sim.gui.Drawable;
import uchicago.src.sim.gui.SimGraphics;
import uchicago.src.sim.space.Multi2DTorus;
public class EchoResource implements Drawable {
private static int ResourceIDNumber = 0;
private int resourceID;
private int siteX;
private int siteY;
private String siteResource;
private String resourceOffenseTag;
private String resourceDefenseTag;
private String resourceReservoir;
private int resourceRate;
// A counter to ensure unique numbers are assigned
// A unique id number for the resource
// The site x location of the resource
// The site y location of the resource
// The resource(s) provided by the site
// The offense tag for the resource
// The defense tag for the resource
// The content of the resource reservoir
// The rate at which the resource is replenished
public EchoResource(){}
public EchoResource(int x, int y, int resType) {
System.out.println("You are creating a Resource of type =" + resType);
// The following are 5 'default' resource types that can be used for initialization
switch (resType){
case 0:
System.out.println("This is case 0");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "cbd";
resourceOffenseTag = "accd";
91
resourceDefenseTag = "aacd";
resourceReservoir = "aaaabbbbccccdddd";
resourceRate = 5;
break;
case 1:
System.out.println("This is case 1");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "abcd";
resourceOffenseTag = "ccda";
resourceDefenseTag = "badc";
resourceReservoir = "aabbbbbbbbbbbddd";
resourceRate = 3;
break;
case 2:
System.out.println("This is case 2");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "bcd";
resourceOffenseTag = "bcda";
resourceDefenseTag = "bcad";
resourceReservoir = "aabbbbbddd";
resourceRate = 6;
break;
case 3:
System.out.println("This is case 3");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "bbca";
resourceOffenseTag = "cabd";
resourceDefenseTag = "bcac";
resourceReservoir = "aabbbbbccccccddd";
resourceRate = 7;
break;
default:
System.out.println("This is case Default");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "abd";
resourceOffenseTag = "ad";
resourceDefenseTag = "cd";
resourceReservoir = "aabbbbbccccccddd";
resourceRate = 3;
break;
}
}
// Getters and Setters follow
public String getResourceReservoir() {
return resourceReservoir;
}
public void setResourceReservoir(String rr){
resourceReservoir = rr;
}
public String getSiteResource() {
return siteResource;
}
public void setSiteResource(String r) {
siteResource = r;
}
public int getResourceRate(){
return resourceRate;
}
92
public void setResourceRate(int rr){
resourceRate = rr;
}
public String getResourceOffenseTag(){
return resourceOffenseTag;
}
public void setResourceOffenseTag(String rot){
resourceOffenseTag = rot;
}
public String getResourceDefenseTag(){
return resourceDefenseTag;
}
public void setResourceDefenseTag(String rdt){
resourceDefenseTag = rdt;
}
public void addResource(int x, int y, char c){
resourceReservoir += c;
}
public String getResourceID(){
return "R-" + resourceID;
}
public int getX(){
return siteX;
}
public int getY(){
return siteY;
}
// Add a string amount to the resource reservoir
public void addStringAmtResourceReservoir(String s, int n){
StringBuffer sb = new StringBuffer();
sb.append(resourceReservoir);
for (int i=0; i<n; i++){
sb.append(s);
}
this.resourceReservoir = sb.toString();
sb = null;
}
// Subtract a string amount from the resource reservoir
public void subtractStringAmtResourceReservoir(String s, int n){
for (int i=0; i<n; i++){
for (int j=0; j<s.length(); j++){
this.subtractAmtResourceReservoir(s.charAt(j), 1);
}
}
}
// Subtract a character from the resource reservoir
public void subtractAmtResourceReservoir(char c, int n){
for(int i=0; i<n; i++){
// Check to make sure that the resourceReservoir is not empty
if (resourceReservoir != null){
int indexOf = resourceReservoir.indexOf(c);
if (indexOf == 0){
resourceReservoir = resourceReservoir.substring(1);
}else if(indexOf > 0){
String sub1 = resourceReservoir.substring(0, indexOf);
String sub2 = resourceReservoir.substring(indexOf+1);
resourceReservoir = sub1 + sub2;
sub1 = null;
sub2 = null;
}
}
}
}
93
// Draw a representation of the reservoir
public void draw(SimGraphics G){
if(siteX > 2)
G.drawFastRoundRect(Color.green);
else
G.drawFastRoundRect(Color.blue);
}
// Report the reservoir to the console
public void report(){
System.out.println(getResourceID() +
getSiteResource () +
" at " +
siteX + ", " + siteY);
}
// Create a string representation of the reservoir
public String toString(){return "resourceID=" + resourceID +
" siteX=" + siteX +
" siteY=" + siteY +
" siteResource=" + siteResource +
" resourceOffenseTag=" + resourceOffenseTag +
" resourceDefenseTag=" + resourceDefenseTag +
" resourceReservoir=" + resourceReservoir +
" resourceRate=" + resourceRate;
}
}
/*********************************************************************************
Module Name:
EchoResource.java
Description:
This is the class which is responsible for creating and managing
resources within a JEcho site.
Author:
Brian W. McIndoe
Date:
2/11/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
import java.awt.Color;
import uchicago.src.sim.gui.Drawable;
import uchicago.src.sim.gui.SimGraphics;
import uchicago.src.sim.space.Multi2DTorus;
public class EchoResource implements Drawable {
private static int ResourceIDNumber = 0;
private int resourceID;
private int siteX;
private int siteY;
private String siteResource;
private String resourceOffenseTag;
private String resourceDefenseTag;
private String resourceReservoir;
private int resourceRate;
// A counter to ensure unique numbers are assigned
// A unique id number for the resource
// The site x location of the resource
// The site y location of the resource
// The resource(s) provided by the site
// The offense tag for the resource
// The defense tag for the resource
// The content of the resource reservoir
// The rate at which the resource is replenished
public EchoResource(){}
public EchoResource(int x, int y, int resType) {
System.out.println("You are creating a Resource of type =" + resType);
// The following are 5 'default' resource types that can be used for initialization
switch (resType){
case 0:
System.out.println("This is case 0");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
94
siteResource = "cbd";
resourceOffenseTag = "accd";
resourceDefenseTag = "aacd";
resourceReservoir = "aaaabbbbccccdddd";
resourceRate = 5;
break;
case 1:
System.out.println("This is case 1");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "abcd";
resourceOffenseTag = "ccda";
resourceDefenseTag = "badc";
resourceReservoir = "aabbbbbbbbbbbddd";
resourceRate = 3;
break;
case 2:
System.out.println("This is case 2");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "bcd";
resourceOffenseTag = "bcda";
resourceDefenseTag = "bcad";
resourceReservoir = "aabbbbbddd";
resourceRate = 6;
break;
case 3:
System.out.println("This is case 3");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "bbca";
resourceOffenseTag = "cabd";
resourceDefenseTag = "bcac";
resourceReservoir = "aabbbbbccccccddd";
resourceRate = 7;
break;
default:
System.out.println("This is case Default");
ResourceIDNumber++;
resourceID = ResourceIDNumber;
siteX = x;
siteY = y;
siteResource = "abd";
resourceOffenseTag = "ad";
resourceDefenseTag = "cd";
resourceReservoir = "aabbbbbccccccddd";
resourceRate = 3;
break;
}
}
// Getters and Setters follow
public String getResourceReservoir() {
return resourceReservoir;
}
public void setResourceReservoir(String rr){
resourceReservoir = rr;
}
public String getSiteResource() {
return siteResource;
}
public void setSiteResource(String r) {
siteResource = r;
}
public int getResourceRate(){
95
return resourceRate;
}
public void setResourceRate(int rr){
resourceRate = rr;
}
public String getResourceOffenseTag(){
return resourceOffenseTag;
}
public void setResourceOffenseTag(String rot){
resourceOffenseTag = rot;
}
public String getResourceDefenseTag(){
return resourceDefenseTag;
}
public void setResourceDefenseTag(String rdt){
resourceDefenseTag = rdt;
}
public void addResource(int x, int y, char c){
resourceReservoir += c;
}
public String getResourceID(){
return "R-" + resourceID;
}
public int getX(){
return siteX;
}
public int getY(){
return siteY;
}
// Add a string amount to the resource reservoir
public void addStringAmtResourceReservoir(String s, int n){
StringBuffer sb = new StringBuffer();
sb.append(resourceReservoir);
for (int i=0; i<n; i++){
sb.append(s);
}
this.resourceReservoir = sb.toString();
sb = null;
}
// Subtract a string amount from the resource reservoir
public void subtractStringAmtResourceReservoir(String s, int n){
for (int i=0; i<n; i++){
for (int j=0; j<s.length(); j++){
this.subtractAmtResourceReservoir(s.charAt(j), 1);
}
}
}
// Subtract a character from the resource reservoir
public void subtractAmtResourceReservoir(char c, int n){
for(int i=0; i<n; i++){
// Check to make sure that the resourceReservoir is not empty
if (resourceReservoir != null){
int indexOf = resourceReservoir.indexOf(c);
if (indexOf == 0){
resourceReservoir = resourceReservoir.substring(1);
}else if(indexOf > 0){
String sub1 = resourceReservoir.substring(0, indexOf);
String sub2 = resourceReservoir.substring(indexOf+1);
resourceReservoir = sub1 + sub2;
sub1 = null;
sub2 = null;
}
}
96
}
}
// Draw a representation of the reservoir
public void draw(SimGraphics G){
if(siteX > 2)
G.drawFastRoundRect(Color.green);
else
G.drawFastRoundRect(Color.blue);
}
// Report the reservoir to the console
public void report(){
System.out.println(getResourceID() +
getSiteResource () +
" at " +
siteX + ", " + siteY);
}
// Create a string representation of the reservoir
public String toString(){return "resourceID=" + resourceID +
" siteX=" + siteX +
" siteY=" + siteY +
" siteResource=" + siteResource +
" resourceOffenseTag=" + resourceOffenseTag +
" resourceDefenseTag=" + resourceDefenseTag +
" resourceReservoir=" + resourceReservoir +
" resourceRate=" + resourceRate;
}
}
/*********************************************************************************
Module Name:
EchoAgent.java
Description:
This class is responsible for creating and managing agents within
the JEcho model.
Author:
Brian W. McIndoe
Date:
2/11/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.awt.Color;
import uchicago.src.sim.gui.Drawable;
import uchicago.src.sim.gui.SimGraphics;
import uchicago.src.sim.space.Multi2DGrid;
public class EchoAgent implements Drawable{
private static int IDNumber = 0;
// Counter for unique agent id
private int ID;
// The unique agent id
private double generation;
// The birth generation
private int parentID;
private EchoSite eSite;
private char resourceAlphabet [] = {'a', 'b', 'c', 'd'};
private int x;
private int y;
private int boundaryID = 0;
private EchoBoundary eb;
private String offenseTag;
private String defenseTag;
private String adhesionTag;
private String exchangeCondition;
private String matingCondition;
private String resourceTransformCondition;
private int resourceTransformRate;
private String replicationCondition;
private boolean replicationFlag;
97
private String resourceReservoir;
private int replicationThreshold = 2;
// 2 means double the amt of Genetic Material
public EchoAgent(int agentType){
switch (agentType){
case 0:
case 1:
case 2:
// caterpillar
IDNumber++;
ID = IDNumber;
generation = 0.0;
offenseTag = "abac";
defenseTag = "acad";
adhesionTag = "abdc";
exchangeCondition = "cd";
matingCondition = "ad";
resourceTransformCondition = "da";
resourceTransformRate = 3;
replicationCondition = "acb";
replicationFlag = false;
resourceReservoir = "aaaabbbbccccdddd";
break;
// ant
IDNumber++;
ID = IDNumber;
generation = 0.0;
offenseTag = "acaa";
defenseTag = "cdad";
adhesionTag = "bbcb";
exchangeCondition = "cd";
matingCondition = "ad";
resourceTransformCondition = "db";
resourceTransformRate = 3;
replicationCondition = "bab";
replicationFlag = false;
resourceReservoir = "aaaabbbbccccdddd";
break;
// fly
IDNumber++;
ID = IDNumber;
generation = 0.0;
offenseTag = "ddac";
defenseTag = "daac";
adhesionTag = "bac";
exchangeCondition = "cd";
matingCondition = "cd";
resourceTransformCondition = "dab";
resourceTransformRate = 2;
replicationCondition = "cab";
replicationFlag = false;
resourceReservoir = "aaaabbbbccccdddd";
break;
case 3:
IDNumber++;
ID = IDNumber;
generation = 0.0;
offenseTag = "cbac";
defenseTag = "acad";
adhesionTag = "cbc";
exchangeCondition = "ad";
matingCondition = "cd";
resourceTransformCondition = "abc";
resourceTransformRate = 3;
replicationCondition = "abd";
replicationFlag = false;
resourceReservoir = "aaaaaabbbbbbaacccccddd";
break;
default:
IDNumber++;
ID = IDNumber;
generation = 0.0;
offenseTag = "cabd";
defenseTag = "daab";
98
adhesionTag = "bddc";
exchangeCondition = "ac";
matingCondition = "bd";
resourceTransformCondition = "bdaaa";
resourceTransformRate = 2;
replicationCondition = "adb";
replicationFlag = false;
resourceReservoir = "aaabbbbccddd";
}
}
// Constructor to use when replicating a new agent
public EchoAgent(double tick, EchoAgent ea, EchoSite eSite, int parentID, String offenseTag, String defenseTag,
String adhesionTag, String exchangeCondition, String matingCondition, String
resourceTransformCondition,
int resourceTransformRate, String replicationCondition,boolean replicationFlag,
String resourceReservoir){
IDNumber++;
ID = IDNumber;
this.eSite = eSite;
this.setX(ea.getX());
this.setY(ea.getY());
this.generation = tick;
this.setParentID(parentID);
this.offenseTag = offenseTag;
this.defenseTag = defenseTag;
this.adhesionTag = adhesionTag;
this.exchangeCondition = exchangeCondition;
this.matingCondition = matingCondition;
this.resourceTransformCondition = resourceTransformCondition;
this.resourceTransformRate = resourceTransformRate;
this.replicationCondition = replicationCondition;
this.replicationFlag = replicationFlag;
this.resourceReservoir = offenseTag + defenseTag + adhesionTag +
exchangeCondition + matingCondition + replicationCondition;
this.incrementDecrement(ea);
//
Decrement the parent agent
eSite.addAgentToSite(this);
}
public void setXY(int newX, int newY){
agent
x = newX;
y = newY;
}
// Set the location of an
public void incrementDecrement(EchoAgent ea){
increment the child
int [] amtGenetic = new int [4];
int [] amtReservoir = new int [4];
// Decrement the parent,
for (int i=0; i<resourceAlphabet.length; i++){
amtGenetic [i] = this.amtGeneticMaterial(resourceAlphabet[i]);
}
for (int i=0; i<resourceAlphabet.length; i++){
ea.subtractAmtResourceReservoir(resourceAlphabet[i], amtGenetic[i]);
}
for (int i=0; i<resourceAlphabet.length; i++){
ea.subtractAmtResourceReservoir(resourceAlphabet[i], amtGenetic[i]);
}
}
public boolean canAgentReplicate(){
boolean replicate = false;
boolean sufficient_a = false;
boolean sufficient_b = false;
boolean sufficient_c = false;
boolean sufficient_d = false;
// assume agent cannot replicate
// assume that there is not enough resource a
// assume that there is not enough resource b
// assume that there is not enough resource c
// assume that there is not enough resource d
// Determine how much genetic material is in the agent chromosome
int amt_gen_a = amtGeneticMaterial('a');
99
int amt_gen_b = amtGeneticMaterial('b');
int amt_gen_c = amtGeneticMaterial('c');
int amt_gen_d = amtGeneticMaterial('d');
// Determine how much genetic material is in the reservoir
int amt_res_a = amtResourceReservoir('a');
int amt_res_b = amtResourceReservoir('b');
int amt_res_c = amtResourceReservoir('c');
int amt_res_d = amtResourceReservoir('d');
// Check if there is sufficient a in the reservoir
if(amt_res_a >= (amt_gen_a * replicationThreshold)){
sufficient_a = true;
}
// Check if there is sufficient b in the reservoir
if(amt_res_b >= (amt_gen_b * replicationThreshold)){
sufficient_b = true;
}
// Check if there is sufficient c in the reservoir
if(amt_res_c >= (amt_gen_c * replicationThreshold)){
sufficient_c = true;
}
// Check if there is sufficient d in the reservoir
if(amt_res_d >= (amt_gen_d * replicationThreshold)){
sufficient_d = true;
}
if (sufficient_a && sufficient_b && sufficient_c && sufficient_d){
replicate = true;
}
return replicate;
}
public void mutateAgent(float mutateProbability){
// Mutate one bit in an agent chromosome according to the mutation probability
// First determine whether the agent will mutate or not
int m = (int)(Math.random()*(1.0/mutateProbability));
if(m == 1){
// then determine which part of the chromosome (tag or condition) will mutate
int x = (int)(Math.random()*6);
switch(x){
case 0: mutateTagCondition(0);
break;
case 1: mutateTagCondition(1);
break;
case 2: mutateTagCondition(2);
break;
case 3: mutateTagCondition(3);
break;
case 4: mutateTagCondition(4);
break;
case 5: mutateTagCondition(5);
break;
}
}
}
// Mutate a specific tag
public void mutateTagCondition(int tagCond){
switch(tagCond){
case 0:
// Offense Tag
String ot = this.getOffenseTag();
int x0 = (int)(Math.random()*ot.length());
String newOt = flipBit(ot, x0);
100
this.setOffenseTag(newOt);
ot = null;
newOt = null;
break;
case 1:
// Defense Tag
String dt = this.getDefenseTag();
int x1 = (int)(Math.random()*dt.length());
String newDt = flipBit(dt, x1);
this.setDefenseTag(newDt);
dt = null;
newDt = null;
break;
case 2:
// Adhesion Tag
String at = this.getAdhesionTag();
int x2 = (int)(Math.random()*at.length());
String newAt = flipBit(at, x2);
this.setAdhesionTag(newAt);
at = null;
newAt = null;
break;
case 3:
// Exchange Condition
String ec = this.getExchangeCondition();
int x3 = (int)(Math.random()*ec.length());
String newEc = flipBit(ec, x3);
this.setExchangeCondition(newEc);
ec = null;
newEc = null;
break;
case 4:
// Mating Condition
String mc = this.getMatingCondition();
int x4 = (int)(Math.random()*mc.length());
String newMc = flipBit(mc, x4);
this.setMatingCondition(newMc);
mc = null;
newMc = null;
break;
case 5:
// Replication Condition
String rc = this.getReplicationCondition();
int x5 = (int)(Math.random()*rc.length());
String newRc = flipBit(rc, x5);
this.setReplicationCondition(newRc);
rc = null;
newRc = null;
break;
}
}
public String flipBit(String tagCond, int position){ // Flip a designated bit in a tag
char c = tagCond.charAt(position);
String newTagCond = null;
if(c == 'a'){
if (position == 0){
newTagCond = 'b' + tagCond.substring(1);
}else {
String sub1 = tagCond.substring(0, position);
String sub2 = tagCond.substring(position+1);
newTagCond = sub1 + 'b' + sub2;
sub1 = null;
sub2 = null;
}
}else if(c == 'b'){
if (position == 0){
newTagCond = 'c' + tagCond.substring(1);
}else {
String sub1 = tagCond.substring(0, position);
String sub2 = tagCond.substring(position+1);
newTagCond = sub1 + 'c' + sub2;
sub1 = null;
sub2 = null;
101
}
}else if(c == 'c'){
if (position == 0){
newTagCond = 'd' + tagCond.substring(1);
}else {
String sub1 = tagCond.substring(0, position);
String sub2 = tagCond.substring(position+1);
newTagCond = sub1 + 'd' + sub2;
sub1 = null;
sub2 = null;
}
}else if(c == 'd'){
if (position == 0){
newTagCond = 'a' + tagCond.substring(1);
}else {
String sub1 = tagCond.substring(0, position);
String sub2 = tagCond.substring(position+1);
newTagCond = sub1 + 'a' + sub2;
sub1 = null;
sub2 = null;
}
}
return newTagCond;
}
// Crossover agent with a second agent
public void crossAgent(EchoAgent ea){
// Determine where in the chromosome the crossover will occur
int x = (int)(Math.random()*6);
switch(x){
case 0: this.crossoverChromosome(0, ea);
this.swapTagsAndConds(0, ea);
break;
case 1: this.crossoverChromosome(1, ea);
this.swapTagsAndConds(1, ea);
break;
case 2: this.crossoverChromosome(2, ea);
this.swapTagsAndConds(2, ea);
break;
case 3: this.crossoverChromosome(3, ea);
this.swapTagsAndConds(3, ea);
break;
case 4: this.crossoverChromosome(4, ea);
this.swapTagsAndConds(4, ea);
break;
case 5: this.crossoverChromosome(5, ea);
this.swapTagsAndConds(5, ea);
break;
}
}
// Crossover the agent chromosomes
public void crossoverChromosome(int tagCond, EchoAgent ea){
String tag1 = null;
String tag2 = null;
String a = null;
String b = null;
int tagLength1 = 0;
int tagLength2 = 0;
int shortlen = 0;
int x = 0;
switch(tagCond){
case 0:
// Offense Tag
// How long is the tag/condition
tag1 = this.getOffenseTag();
tag2 = ea.getOffenseTag();
tagLength1 = tag1.length();
tagLength2 = tag2.length();
102
// Determine the shortest length
shortlen = (int)Math.min(tagLength1, tagLength2);
// Determine where it will split
x = (int)(Math.random()*shortlen);
a = tag1.substring(0, x) + tag2.substring(x);
b = tag2.substring(0, x) + tag1.substring(x);
tag1 = a;
tag2 = b;
case 1:
this.setOffenseTag(a);
ea.setOffenseTag(b);
break;
// Defense Tag
// How long is the tag/condition
tag1 = this.getDefenseTag();
tag2 = ea.getDefenseTag();
tagLength1 = tag1.length();
tagLength2 = tag2.length();
// Determine the shortest length
shortlen = (int)Math.min(tagLength1, tagLength2);
// Determine where it will split
x = (int)(Math.random()*shortlen);
a = tag1.substring(0, x) + tag2.substring(x);
b = tag2.substring(0, x) + tag1.substring(x);
tag1 = a;
tag2 = b;
case 2:
this.setDefenseTag(a);
ea.setDefenseTag(b);
break;
// Adhesion Tag
// How long is the tag/condition
tag1 = this.getAdhesionTag();
tag2 = ea.getAdhesionTag();
tagLength1 = tag1.length();
tagLength2 = tag2.length();
// Determine the shortest length
shortlen = (int)Math.min(tagLength1, tagLength2);
// Determine where it will split
x = (int)(Math.random()*shortlen);
a = tag1.substring(0, x) + tag2.substring(x);
b = tag2.substring(0, x) + tag1.substring(x);
tag1 = a;
tag2 = b;
case 3:
this.setAdhesionTag(a);
ea.setAdhesionTag(b);
break;
// Exchange Condition
// How long is the tag/condition
tag1 = this.getExchangeCondition();
tag2 = ea.getExchangeCondition();
tagLength1 = tag1.length();
tagLength2 = tag2.length();
// Determine the shortest length
shortlen = (int)Math.min(tagLength1, tagLength2);
// Determine where it will split
x = (int)(Math.random()*shortlen);
a = tag1.substring(0, x) + tag2.substring(x);
b = tag2.substring(0, x) + tag1.substring(x);
103
tag1 = a;
tag2 = b;
case 4:
this.setExchangeCondition(a);
ea.setExchangeCondition(b);
break;
// Mating Condition
// How long is the tag/condition
tag1 = this.getMatingCondition();
tag2 = ea.getMatingCondition();
tagLength1 = tag1.length();
tagLength2 = tag2.length();
// Determine the shortest length
shortlen = (int)Math.min(tagLength1, tagLength2);
// Determine where it will split
x = (int)(Math.random()*shortlen);
a = tag1.substring(0, x) + tag2.substring(x);
b = tag2.substring(0, x) + tag1.substring(x);
tag1 = a;
tag2 = b;
case 5:
this.setMatingCondition(a);
ea.setMatingCondition(b);
break;
// Replication Condition
// How long is the tag/condition
tag1 = this.getReplicationCondition();
tag2 = ea.getReplicationCondition();
tagLength1 = tag1.length();
tagLength2 = tag2.length();
// Determine the shortest length
shortlen = (int)Math.min(tagLength1, tagLength2);
// Determine where it will split
x = (int)(Math.random()*shortlen);
a = tag1.substring(0, x) + tag2.substring(x);
b = tag2.substring(0, x) + tag1.substring(x);
tag1 = a;
tag2 = b;
this.setReplicationCondition(a);
ea.setReplicationCondition(b);
break;
}
tag1 = null;
tag2 = null;
a = null;
b = null;
}
// Intermediate method to determine where to swap a tag or condition
public void swapTagsAndConds(int tagCond, EchoAgent ea){
switch(tagCond){
case 0: // Offense Tag was Crossed (split), move other tags and conditions
case 1:
case 2:
performSwap(1, ea);
performSwap(2, ea);
performSwap(3, ea);
performSwap(4, ea);
performSwap(5, ea);
break;
// Defense Tag
performSwap(2, ea);
performSwap(3, ea);
performSwap(4, ea);
performSwap(5, ea);
break;
// Adhesion Tag
104
case 3:
case 4:
case 5:
performSwap(3, ea);
performSwap(4, ea);
performSwap(5, ea);
break;
// Exchange Condition
performSwap(4, ea);
performSwap(5, ea);
break;
// Mating Condition
performSwap(5, ea);
break;
// Replication Condition
break;
}
}
public void performSwap(int indicator, EchoAgent ea){
String tag1 = null;
String tag2 = null;
switch(indicator){
case 1:
tag1 = this.getDefenseTag();
tag2 = ea.getDefenseTag();
this.setDefenseTag(tag2);
ea.setDefenseTag(tag1);
break;
case 2:
tag1 = this.getAdhesionTag();
tag2 = ea.getAdhesionTag();
this.setAdhesionTag(tag2);
ea.setAdhesionTag(tag1);
break;
case 3:
tag1 = this.getExchangeCondition();
tag2 = ea.getExchangeCondition();
this.setExchangeCondition(tag2);
ea.setExchangeCondition(tag1);
break;
case 4:
tag1 = this.getMatingCondition();
tag2 = ea.getMatingCondition();
this.setMatingCondition(tag2);
ea.setMatingCondition(tag1);
break;
case 5:
tag1 = this.getReplicationCondition();
tag2 = ea.getReplicationCondition();
this.setReplicationCondition(tag2);
ea.setReplicationCondition(tag1);
break;
}
tag1 = null;
tag2 = null;
}
// Cull agent and return their genetic material and resources to the site reservoir
public void cullAgent(){
// Which site is the agent at?
int x = this.getX();
int y = this.getY();
// Find out what is in the agents reservoir
int [] amtReservoir = new int [4];
for (int i=0; i<resourceAlphabet.length; i++){
amtReservoir [i] = this.amtResourceReservoir(resourceAlphabet[i]);
}
// Find out what is in the agents genetic material
int [] amtGenetic = new int [4];
for (int i=0; i<resourceAlphabet.length; i++){
amtGenetic [i] = this.amtGeneticMaterial(resourceAlphabet[i]);
105
}
// Find out the agents total resources
int [] amtAgentTotal = new int [4];
for (int i=0; i<resourceAlphabet.length; i++){
amtAgentTotal [i] = amtGenetic [i] + amtReservoir [i];
}
StringBuffer sb = new StringBuffer();
EchoResource r = eSite.getResource(x,y);
String rr = r.getResourceReservoir();
sb.append(rr);
// Add the agent resources to the site reservoir
for (int i=0; i<resourceAlphabet.length; i++){
for (int j=0; j<amtAgentTotal[i]; j++){
sb.append(resourceAlphabet[i]);
}
}
r.setResourceReservoir(sb.toString());
r = null;
rr = null;
sb = null;
}
// Count the amount of a character in the resource reservoir
public int amtResourceReservoir(char c){
int amt = 0;
if (resourceReservoir != null) {
for (int i=0; i<resourceReservoir.length(); i++) {
if (c == resourceReservoir.charAt(i)) {
amt++;
}
}
}
return amt;
}
// Count the amount of a character in the genetic material (chromosome)
public int amtGeneticMaterial(char c){
int amt = 0;
// Offense Tag
for (int i=0; i<offenseTag.length(); i++) {
if (c == offenseTag.charAt(i)) {
amt++;
}
}
// Defense Tag
for (int i=0; i<defenseTag.length(); i++) {
if (c == defenseTag.charAt(i)) {
amt++;
}
}
// Adhesion Tag
for (int i=0; i<adhesionTag.length(); i++) {
if (c == adhesionTag.charAt(i)) {
amt++;
}
}
// Exchange Condition
for (int i=0; i<exchangeCondition.length(); i++) {
if (c == exchangeCondition.charAt(i)) {
amt++;
}
}
// Mating Condition
for (int i=0; i<matingCondition.length(); i++) {
if (c == matingCondition.charAt(i)) {
amt++;
}
106
}
// Replication Condition
for (int i=0; i<replicationCondition.length(); i++) {
if (c == replicationCondition.charAt(i)) {
amt++;
}
}
return amt;
}
// Calculate the surplus left behind after replication
public int calculateAgentSurplus(EchoAgent ea, char res){
int surplus = 0;
// find out how much of the resource is in the genetic material of the agent
int geneticMaterial = ea.amtGeneticMaterial(res);
// find out how much of the resource is required to self replicate
int replicateAmount = geneticMaterial * replicationThreshold;
// find out how much of the resource is in the reservoir
int reservoirAmount = ea.amtResourceReservoir(res);
// find out how much of the resource is surplus
if((reservoirAmount - replicateAmount) > 0){
surplus = reservoirAmount - replicateAmount;
}else {
surplus = 0;
}
return surplus;
}
// Acquire the surplus in an agents reservoir beyond what it needs to replicate
public void acquireAgentSurplus (EchoAgent ea, char res){
// get the surplus from the other agent
int amt = calculateAgentSurplus (ea, res);
// add the amount to the current agents reservoir
this.addAmtResourceReservoir(res, amt);
// subtract the amount from the other agents reservoir
ea.subtractAmtResourceReservoir(res, amt);
}
// Acquire the whole reservoir of the agent
public void acquireAgentReservoir(EchoAgent ea){
// get the other agents reservoir and assign it to this agent
StringBuffer sb = new StringBuffer();
String ra = ea.getResourceReservoir();
String rr = this.getResourceReservoir();
sb.append(ra);
sb.append(rr);
rr = sb.toString();
ra = null;
this.setResourceReservoir(rr);
ea.setResourceReservoir(ra);
sb = null;
rr = null;
}
// Kill the agent and acquire its genetic material and resource reservoir
public void killOtherAgent(EchoAgent ea){
// Find out what is in the agents reservoir
int [] amtReservoir = new int [4];
for (int i=0; i<resourceAlphabet.length; i++){
amtReservoir [i] = ea.amtResourceReservoir(resourceAlphabet[i]);
}
// Find out what is in the agents genetic material
int [] amtGenetic = new int [4];
107
for (int i=0; i<resourceAlphabet.length; i++){
amtGenetic [i] = ea.amtGeneticMaterial(resourceAlphabet[i]);
}
// Find out the agents total resources
int [] amtAgentTotal = new int [4];
for (int i=0; i<resourceAlphabet.length; i++){
amtAgentTotal [i] = amtGenetic [i] + amtReservoir [i];
}
// Add the killed agents total genetic material including reservoir to this agent
StringBuffer sb = new StringBuffer();
String rr = this.getResourceReservoir();
sb.append(rr);
for (int i=0; i<resourceAlphabet.length; i++){
for (int j=0; j<amtAgentTotal[i]; j++){
sb.append(resourceAlphabet[i]);
}
}
this.setResourceReservoir(sb.toString());
// Remove the agent from the site
EchoSite es = ea.eSite;
es.removeAgent(ea);
// Set the agents reference to null
es = null;
ea = null;
sb = null;
}
// Transform the agents resource using the transformation condition
public void transformResources(){
// Get the resource transformation condition and rate for this agent.
String rtc = this.getResourceTransformCondition();
int rtr = this.getResourceTransformRate();
// The character at position 0 is the from resource
// The character at position 1 is the to resource
// The characters at position 2 and up are the cost of the transformation
// Get the character at 0
char p0 = rtc.charAt(0);
// Get the character at 1
char p1 = rtc.charAt(1);
char[] c = new char[10];
for (int i=2; i<rtc.length(); i++) {
c[i] = rtc.charAt(i);
}
int p0Amount = this.amtResourceReservoir(p0);
if(p0Amount >= 1){
this.subtractAmtResourceReservoir(p0, 1);
this.addAmtResourceReservoir(p1, rtr);
for (int i=2; i<rtc.length(); i++){
this.subtractAmtResourceReservoir(c[i], 1);
}
}
rtc = null;
}
// Add a string amount to the resource reservoir
public void addStringAmtResourceReservoir(String s, int n){
StringBuffer sb = new StringBuffer();
sb.append(resourceReservoir);
for (int i=0; i<n; i++){
sb.append(s);
}
resourceReservoir = sb.toString();
sb = null;
}
108
// Subtract a string amount from the resource reservoir
public void subtractStringAmtResourceReservoir(String s, int n){
for (int i=0; i<n; i++){
for (int j=0; j<s.length(); j++){
this.subtractAmtResourceReservoir(s.charAt(j), 1);
}
}
}
// Add a character amount to the resource reservoir
public void addAmtResourceReservoir(char c, int n){
StringBuffer sb = new StringBuffer();
sb.append(resourceReservoir);
for(int i=0; i<n; i++){
sb.append(c);
}
resourceReservoir = sb.toString();
sb = null;
}
// Subtract a character amount from the resource reservoir
public void subtractAmtResourceReservoir(char c, int n){
int indexOf = 0;
for(int i=0; i<n; i++){
if (resourceReservoir != null){
indexOf = resourceReservoir.indexOf(c);
if (indexOf == 0){
resourceReservoir = resourceReservoir.substring(1);
}else if (indexOf > 0){
String sub1 = resourceReservoir.substring(0, indexOf);
String sub2 = resourceReservoir.substring(indexOf+1);
resourceReservoir = sub1 + sub2;
sub1 = null;
sub2 = null;
}
}
}
}
// Getter and Setters follow
public void setEchoSite(EchoSite es){
eSite = es;
}
public EchoSite getEchoSite(){
return eSite;
}
public void setBoundaryID(int ID){
boundaryID = ID;
}
public int getBoundaryID(){
return boundaryID;
}
public void setBoundaryObject(EchoBoundary eBoundary){
eb = eBoundary;
}
public EchoBoundary getBoundaryObject(){
return eb;
}
public void setOffenseTag(String ot){
offenseTag = ot;
}
public String getOffenseTag(){
return offenseTag;
}
public void setDefenseTag(String dt){
defenseTag = dt;
109
}
public String getDefenseTag(){
return defenseTag;
}
public void setAdhesionTag(String at){
adhesionTag = at;
}
public String getAdhesionTag(){
return adhesionTag;
}
public void setExchangeCondition(String ec){
exchangeCondition = ec;
}
public String getExchangeCondition(){
return exchangeCondition;
}
public void setMatingCondition(String mc){
this.matingCondition = mc;
}
public String getMatingCondition(){
return matingCondition;
}
public void setResourceTransformCondition(String rt){
this.resourceTransformCondition = rt;
}
public String getResourceTransformCondition(){
return resourceTransformCondition;
}
public void setResourceTransformRate(int r){
this.resourceTransformRate = r;
}
public int getResourceTransformRate(){
return resourceTransformRate;
}
public void setReplicationCondition(String rc){
this.replicationCondition = rc;
}
public String getReplicationCondition(){
return replicationCondition;
}
public void setReplicationFlag(boolean rf){
this.replicationFlag = rf;
}
public boolean getReplicationFlag(){
return replicationFlag;
}
public void setResourceReservoir(String rr){
this.resourceReservoir = rr;
}
public String getResourceReservoir(){
return resourceReservoir;
}
public int getID(){
return ID;
}
public String getAgentID(){
110
return "A-" + ID;
}
public int getParentID(){
return this.parentID;
}
public void setParentID(int pID){
this.parentID = pID;
}
public void report(){
System.out.println(getAgentID() +
" at " +
x + ", " + y);
}
public String toString(){
return getAgentID() + " Gen=" + generation +
" at " +
getX() + ", " + getY() +
" OT= " + offenseTag +
" DT= " + defenseTag +
" AT= " + adhesionTag +
" EC= " + exchangeCondition +
" MC= " + matingCondition +
" RTC= " + resourceTransformCondition +
" RTR= " + resourceTransformRate +
" RC= " + replicationCondition +
" RR= " + resourceReservoir;
}
public int getX(){
return x;
}
public void setX(int X){
this.x = X;
}
public int getY(){
return y;
}
public void setY(int Y){
this.y = Y;
}
public void draw(SimGraphics G){
if(x > 10)
G.drawFastRoundRect(Color.green);
else
G.drawFastRoundRect(Color.blue);
}
/*********************************************************************************
Module Name:
EchoModel1.java
Description:
This class is responsible for implementing the model 1 Echo
mechanisms in JEcho. The model 1 mechanisms are described by
Holland in Hidden Order (1995).
Author:
Brian W. McIndoe
Date:
2/12/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
111
import java.util.*;
import uchicago.src.sim.space.Multi2DGrid;
import uchicago.src.sim.space.AbsMulti2DGrid;
public class EchoModel1 {
protected EchoSite mSite;
protected int x;
protected int y;
protected List l;
protected char resourceAlphabet [] = {'a', 'b', 'c', 'd'};
protected ArrayList siteAgentList;
protected ArrayList siteAgentInteractList1;
protected ArrayList siteAgentInteractList2;
// The percentage of agents that gets to interact
protected float interactionFraction = 0.2f;
protected float agentSiteInteractionNum;
protected int totalScore [] = new int [1000];
protected int totalOffenseTag1 [] = new int [1000];
protected int totalOffenseTag2 [] = new int [1000];
protected int tScore = 0;
protected int tOffenseAdhesionTag1 = 0;
protected int tOffenseAdhesionTag2 = 0;
// Mutation Probability (e.g., 0.05 is 5%)
protected float mutateProbability;
// Death Probability (e.g., 0.1 is 10%)
protected float deathRate;
// 2D array used to score Agent/Agent tag comparisons
protected int [][] modelScore = {
{ 2,-2,-2,-2},
{-2, 2,-2,-2},
{-2,-2, 2,-2},
{-2,-2,-2, 2}
};
// 2D array used to score Agent/Site Resource tag comparisons
protected int [][] siteAgentScore = {
{ 2,-2,-2,-2},
{-2, 2,-2,-2},
{-2,-2, 2,-2},
{-2,-2,-2, 2}
};
public EchoModel1(){}
public EchoModel1(EchoSite eSite, int worldXSize, int worldYSize,
float mutateProb, float deathRate, float interactFrac){
this.x = worldXSize;
this.y = worldYSize;
this.mSite = eSite;
this.mutateProbability = mutateProb;
this.deathRate = deathRate;
this.interactionFraction = interactFrac;
}
// Compare Agent to Agent - Offense and Defense Tags
public void compareOffenseDefenseTags () {
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int count = 0;
while (e1.hasNext() && e2.hasNext()){
int scoreOffenseTag1 = 0;
int scoreOffenseTag2 = 0;
int totalScoreOffenseTag1 = 0;
int totalScoreOffenseTag2 = 0;
EchoAgent ea1 = null;
EchoAgent ea2 = null;
112
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
String defenseTag1 = ea1.getDefenseTag();
String defenseTag2 = ea2.getDefenseTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayDefenseTag1 = defenseTag1.toCharArray();
char[] cArrayDefenseTag2 = defenseTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingDefenseTag1 = new int[10];
int[] mappingDefenseTag2 = new int[10];
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
}
for (int i = 0; i< defenseTag1.length(); i++){
if (cArrayDefenseTag1[i] == 'a') {
mappingDefenseTag1[i] = 1;
}
else if (cArrayDefenseTag1[i] == 'b') {
mappingDefenseTag1[i] = 2;
}
else if (cArrayDefenseTag1[i] == 'c') {
mappingDefenseTag1[i] = 3;
}
else if (cArrayDefenseTag1[i] == 'd') {
mappingDefenseTag1[i] = 4;
}
}
for (int i = 0; i< defenseTag2.length(); i++){
if (cArrayDefenseTag2[i] == 'a') {
mappingDefenseTag2[i] = 1;
}
else if (cArrayDefenseTag2[i] == 'b') {
mappingDefenseTag2[i] = 2;
}
113
else if (cArrayDefenseTag2[i] == 'c') {
mappingDefenseTag2[i] = 3;
}
else if (cArrayDefenseTag2[i] == 'd') {
mappingDefenseTag2[i] = 4;
}
}
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< defenseTag2.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingDefenseTag2[j];
if(i == j){
scoreOffenseTag1 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != defenseTag2.length()){
scoreOffenseTag1--;
}
totalScoreOffenseTag1 += scoreOffenseTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< defenseTag1.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag2[i];
int l = mappingDefenseTag1[j];
if(i == j){
scoreOffenseTag2 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != defenseTag1.length()){
scoreOffenseTag2--;
}
totalScoreOffenseTag2 += scoreOffenseTag2;
}
totalOffenseTag1 [count] = totalScoreOffenseTag1;
totalOffenseTag2 [count] = totalScoreOffenseTag2;
totalScore [count] = totalScoreOffenseTag1 + totalScoreOffenseTag2;
count++;
offenseTag1 = null;
offenseTag2 = null;
}
e1 = null;
e2 = null;
}
// Method uses tag match scores to reallocate resources and genetic material
public void reallocateResources (EchoAgent ea1, EchoAgent ea2,
int totalScore,
int totalOffenseTag1,
int totalOffenseTag2) {
// obtain the difference between OffenseTag1 and OffenseTag2
int difference = totalOffenseTag1 - totalOffenseTag2;
if (difference == 0){
// take no action
} else if ((difference >= 2) && (difference <= 8)){
// take the surplus of agent 2 and give it to agent 1
for (int i=0; i < resourceAlphabet.length; i++){
ea1.acquireAgentSurplus(ea2, resourceAlphabet[i]);
}
} else if ((difference > 8) && (difference <=16)){
// take the reservoir of agent 2 and give it to agent 1
ea1.acquireAgentReservoir(ea2);
114
} else if (difference > 16){
// kill agent 2 and give all of its resources including genetic material to agent 1
ea1.killOtherAgent(ea2);
ea2 = null;
} else if ((difference <= -2) && (difference >= -8)){
// take the surplus of agent 1 and give it to agent 2
for (int i=0; i<resourceAlphabet.length; i++){
ea2.acquireAgentSurplus(ea1, resourceAlphabet[i]);
}
} else if ((difference < -8) && (difference) >= -16){
// take the reservoir of agent 1 and give it to agent 2
ea2.acquireAgentReservoir(ea1);
} else if (difference < -16){
// kill agent 1 and give all of its resources including genetic material to agent 2
ea2.killOtherAgent(ea1);
ea1 = null;
}
}
// Compare the agent offense tag against the site defense tag
public int compareAgentOffenseAgainstSiteDefense(EchoAgent ea, String rdt){
int scoreAgentOffenseTag=0;
int totalScoreAgentOffenseTag=0;
String agentOffenseTag = ea.getOffenseTag();
char[] cArrayAgentOffenseTag = agentOffenseTag.toCharArray();
char[] cArrayResDefenseTag = rdt.toCharArray();
int[] mappingAgentOffenseTag = new int[10];
int[] mappingResDefenseTag = new int[10];
for (int i = 0; i< agentOffenseTag.length(); i++){
if (cArrayAgentOffenseTag [i] == 'a') {
mappingAgentOffenseTag [i] = 1;
}
else if (cArrayAgentOffenseTag [i] == 'b') {
mappingAgentOffenseTag [i] = 2;
}
else if (cArrayAgentOffenseTag [i] == 'c') {
mappingAgentOffenseTag [i] = 3;
}
else if (cArrayAgentOffenseTag [i] == 'd') {
mappingAgentOffenseTag [i] = 4;
}
}
for (int i = 0; i< rdt.length(); i++){
if (cArrayResDefenseTag [i] == 'a') {
mappingResDefenseTag [i] = 1;
}
else if (cArrayResDefenseTag [i] == 'b') {
mappingResDefenseTag [i] = 2;
}
else if (cArrayResDefenseTag [i] == 'c') {
mappingResDefenseTag [i] = 3;
}
else if (cArrayResDefenseTag [i] == 'd') {
mappingResDefenseTag [i] = 4;
}
}
for (int i = 0; i< agentOffenseTag.length(); i++){
for (int j = 0;j< rdt.length(); j++){
int k = mappingAgentOffenseTag [i];
int l = mappingResDefenseTag [j];
if(i == j){
scoreAgentOffenseTag += siteAgentScore[k-1][l-1];
}
}
// take into account unequal length tags
if (agentOffenseTag.length() != rdt.length()){
115
scoreAgentOffenseTag--;
}
totalScoreAgentOffenseTag += scoreAgentOffenseTag;
}
agentOffenseTag = null;
return totalScoreAgentOffenseTag;
}
// Compare the agent defense tag against the site offense tag
public int compareAgentDefenseAgainstSiteOffense(EchoAgent ea, String rot){
int scoreAgentDefenseTag=0;
int totalScoreAgentDefenseTag=0;
String agentDefenseTag = ea.getDefenseTag();
char[] cArrayAgentDefenseTag = agentDefenseTag.toCharArray();
char[] cArrayResOffenseTag = rot.toCharArray();
int[] mappingAgentDefenseTag = new int[10];
int[] mappingResOffenseTag = new int[10];
for (int i = 0; i< agentDefenseTag.length(); i++){
if (cArrayAgentDefenseTag [i] == 'a') {
mappingAgentDefenseTag [i] = 1;
}
else if (cArrayAgentDefenseTag [i] == 'b') {
mappingAgentDefenseTag [i] = 2;
}
else if (cArrayAgentDefenseTag [i] == 'c') {
mappingAgentDefenseTag [i] = 3;
}
else if (cArrayAgentDefenseTag [i] == 'd') {
mappingAgentDefenseTag [i] = 4;
}
}
for (int i = 0; i< rot.length(); i++){
if (cArrayResOffenseTag [i] == 'a') {
mappingResOffenseTag [i] = 1;
}
else if (cArrayResOffenseTag [i] == 'b') {
mappingResOffenseTag [i] = 2;
}
else if (cArrayResOffenseTag [i] == 'c') {
mappingResOffenseTag [i] = 3;
}
else if (cArrayResOffenseTag [i] == 'd') {
mappingResOffenseTag [i] = 4;
}
}
for (int i = 0; i< agentDefenseTag.length(); i++){
for (int j = 0;j< rot.length(); j++){
int k = mappingAgentDefenseTag [i];
int l = mappingResOffenseTag [j];
if(i == j){
scoreAgentDefenseTag += siteAgentScore[k-1][l-1];
}
}
// take into account unequal length tags
if (agentDefenseTag.length() != rot.length()){
scoreAgentDefenseTag--;
}
totalScoreAgentDefenseTag += scoreAgentDefenseTag;
}
agentDefenseTag = null;
return totalScoreAgentDefenseTag;
}
// Reallocate resources between site and agent
public void reallocateAgentSiteResources(EchoAgent ea, EchoResource er,
int tScore,
int aosd, int adso){
116
// obtain the difference between OffenseTag1 and OffenseTag2
int difference = aosd - adso;
String siteResource = er.getSiteResource();
if (difference == 0){
// take no action
} else if ((difference >= 2) && (difference <= 8)){
// the agent gets a small amount of resource from the site
ea.addStringAmtResourceReservoir(siteResource, 1);
er.subtractStringAmtResourceReservoir(siteResource, 1);
} else if ((difference > 8) && (difference <=16)){
// the agent gets a larger amount of resource from the site
ea.addStringAmtResourceReservoir(siteResource, 2);
er.subtractStringAmtResourceReservoir(siteResource, 2);
} else if (difference > 16){
// the agent gets a maximum amount of resource from the site
ea.addStringAmtResourceReservoir(siteResource, 3);
er.subtractStringAmtResourceReservoir(siteResource, 3);
} else if ((difference <= -2) && (difference >= -8)){
// the agent gives up a small amount of its resource reservoir to the site
er.addStringAmtResourceReservoir(siteResource, 1);
ea.subtractStringAmtResourceReservoir(siteResource, 1);
} else if ((difference < -8) && (difference) >= -16){
// the agent gives up a larger amount of its resource reservoir to the site
er.addStringAmtResourceReservoir(siteResource, 2);
ea.subtractStringAmtResourceReservoir(siteResource, 2);
} else if (difference < -16){
// the agent gives up all of its reservoir to the site
er.addStringAmtResourceReservoir(siteResource, 3);
ea.subtractStringAmtResourceReservoir(siteResource, 3);
}
siteResource = null;
}
// The model 1 step routine that is run every cycle
public void step (double tick) {
// Replenish each sites resources as necessary
mSite.replenishSites();
// Iterate through every site and perform agent tag interactions
for (int i = 0; i < x; i++ ){
for (int j = 0; j < y; j++){
siteAgentList = new ArrayList();
siteAgentInteractList1 = new ArrayList();
siteAgentInteractList2 = new ArrayList();
l = mSite.getObjectsAt(i, j);
Iterator e = l.iterator();
// Make a list of all agents at a particular site (Full List)
while (e.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)e.next();
siteAgentList.add(ea);
}
agentSiteInteractionNum = siteAgentList.size()*(interactionFraction/(2*100)) ;
int m = (int)agentSiteInteractionNum;
int count = 0;
for (int k=0; k<siteAgentList.size(); k++) {
117
if ((k % 5 == 0)&&(count <= m)){
// int k = (int)(Math.random()*(siteAgentList.size()));
siteAgentInteractList1.add(siteAgentList.get(k));
siteAgentInteractList2.add(siteAgentList.get(k+1));
count++;
}
}
//obtain the match score of the agents offense and defense tags
compareOffenseDefenseTags();
// reallocateResources - use the match score to determine whether combat, or trade occurs
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int counta = 0;
while (e1.hasNext() && e2.hasNext()){
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
reallocateResources(ea1, ea2, totalScore[counta],
totalOffenseTag1[counta], totalOffenseTag2[counta]);
counta++;
}
// Determine who can reproduce - Reproduce them and mutate them
Iterator sal = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (sal.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)sal.next();
if(ea.canAgentReplicate()){
EchoAgent newAgent = new EchoAgent(tick, ea,
ea.getEchoSite(), ea.getID(),
ea.getOffenseTag(), ea.getDefenseTag(),
ea.getAdhesionTag(), ea.getExchangeCondition(),
ea.getMatingCondition(), ea.getResourceTransformCondition(),
ea.getResourceTransformRate(), ea.getReplicationCondition(),
ea.getReplicationFlag(), ea.getResourceReservoir());
// Mutate the new agent
newAgent.mutateAgent(mutateProbability);
}
}
// Determine who dies and return their resources to the site
Iterator cull = siteAgentList.iterator();
int every = (int)(1.0/deathRate);
while (cull.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)cull.next();
if(ea.getID() % every == 0){
ea.cullAgent();
ea = null;
}
}
// Agents take resources from the site depending upon the match score
// between the agent and site offense and defense tags
Iterator siteInteraction = siteAgentList.iterator();
118
// Obtain the resource characteristics at the site
EchoResource er = (EchoResource)mSite.getResource(i,j);
// Get the site resource Offense tag
String rot = er.getResourceOffenseTag();
// Get the site resource Defense tag
String rdt = er.getResourceDefenseTag();
// Compare each agent with the site resource tags
while (siteInteraction.hasNext()){
EchoAgent ea = null;
int totalScore = 0;
int aosd = 0;
int adso = 0;
ea = (EchoAgent)siteInteraction.next();
// Compare Agent Offense against Site Defense
aosd = compareAgentOffenseAgainstSiteDefense(ea, rdt);
// Compare Agent Defense against Site Offense
adso = compareAgentDefenseAgainstSiteOffense(ea, rot);
// Obtain the match score
totalScore = aosd + adso;
// Reallocate Resources based on the match score
reallocateAgentSiteResources(ea, er, totalScore,
aosd, adso);
}
}
}
}
}
/*********************************************************************************
Module Name:
EchoModel2.java
Description:
This class is responsible for implementing the model 2 Echo
mechanisms in JEcho. The model 2 mechanisms are described by
Holland in Hidden Order (1995).
Author:
Brian W. McIndoe
Date:
2/12/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.util.*;
public class EchoModel2 extends EchoModel1 {
public EchoModel2(){
super();
}
public EchoModel2(EchoSite eSite, int worldXSize, int worldYSize,
float mutateProb, float deathRate, float interactFrac){
super(eSite, worldXSize, worldYSize, mutateProb, deathRate, interactFrac);
}
public void step (double tick) {
119
// Replenish each sites resources as necessary
mSite.replenishSites();
// Iterate through every site and perform agent tag interactions
for (int i = 0; i < x; i++ ){
for (int j = 0; j < y; j++){
siteAgentList = new ArrayList();
siteAgentInteractList1 = new ArrayList();
siteAgentInteractList2 = new ArrayList();
l = mSite.getObjectsAt(i, j);
Iterator e = l.iterator();
// Make a list of all agents at a particular site (Full List)
while (e.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)e.next();
siteAgentList.add(ea);
}
agentSiteInteractionNum = siteAgentList.size()*(interactionFraction/(2*100)) ;
int m = (int)agentSiteInteractionNum;
int count = 0;
for (int k=0; k<siteAgentList.size(); k++) {
if ((k % 5 == 0)&&(count <= m)){
// int k = (int)(Math.random()*(siteAgentList.size()));
siteAgentInteractList1.add(siteAgentList.get(k));
siteAgentInteractList2.add(siteAgentList.get(k+1));
count++;
}
}
//obtain the match score of the agents offense and defense tags
compareOffenseDefenseTags();
// reallocateResources - use the match score to determine whether combat, or trade occurs
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int counta = 0;
while (e1.hasNext() && e2.hasNext()){
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
reallocateResources(ea1, ea2, totalScore[counta],
totalOffenseTag1[counta], totalOffenseTag2[counta]);
counta++;
}
// Determine who can reproduce - Reproduce them and mutate them
Iterator sal = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (sal.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)sal.next();
if(ea.canAgentReplicate()){
EchoAgent newAgent = new EchoAgent(tick, ea,
ea.getEchoSite(), ea.getID(),
ea.getOffenseTag(), ea.getDefenseTag(),
ea.getAdhesionTag(), ea.getExchangeCondition(),
ea.getMatingCondition(), ea.getResourceTransformCondition(),
120
ea.getResourceTransformRate(), ea.getReplicationCondition(),
ea.getReplicationFlag(), ea.getResourceReservoir());
// Mutate the new agent
newAgent.mutateAgent(mutateProbability);
}
}
// Determine who dies and return their resources to the site
Iterator cull = siteAgentList.iterator();
int every = (int)(1.0/deathRate);
while (cull.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)cull.next();
if(ea.getID() % every == 0){
ea.cullAgent();
ea = null;
}
}
// Agents take resources from the site depending upon the match score
// between the agent and site offense and defense tags
Iterator siteInteraction = siteAgentList.iterator();
// Obtain the resource characteristics at the site
EchoResource er = (EchoResource)mSite.getResource(i,j);
// Get the site resource Offense tag
String rot = er.getResourceOffenseTag();
// Get the site resource Defense tag
String rdt = er.getResourceDefenseTag();
// Compare each agent with the site resource tags
while (siteInteraction.hasNext()){
EchoAgent ea = null;
int totalScore = 0;
int aosd = 0;
int adso = 0;
ea = (EchoAgent)siteInteraction.next();
// Compare Agent Offense against Site Defense
aosd = compareAgentOffenseAgainstSiteDefense(ea, rdt);
// Compare Agent Defense against Site Offense
adso = compareAgentDefenseAgainstSiteOffense(ea, rot);
// Obtain the match score
totalScore = aosd + adso;
// Reallocate Resources based on the match score
reallocateAgentSiteResources(ea, er, totalScore,
aosd, adso);
}
}
}
}
// Compare Agent to Agent - Offense and Defense Tags
// In model2 however, first compare the Exchange Conditions of each agent
// with the other agents Offense condition. If both match go ahead and perform
// the exchange. Otherwise, if one matches, give the other agent a chance to
// flee the interaction. Otherwise if both do not match, then abort.
public void compareOffenseDefenseTags () {
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int count = 0;
121
while (e1.hasNext() && e2.hasNext()){
int scoreOffenseTag1 = 0;
int scoreOffenseTag2 = 0;
int totalScoreOffenseTag1 = 0;
int totalScoreOffenseTag2 = 0;
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
String defenseTag1 = ea1.getDefenseTag();
String defenseTag2 = ea2.getDefenseTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayDefenseTag1 = defenseTag1.toCharArray();
char[] cArrayDefenseTag2 = defenseTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingDefenseTag1 = new int[10];
int[] mappingDefenseTag2 = new int[10];
// Check agents exchange conditions to see if they will interact
int exchange = checkAgentExchangeConditions(ea1, ea2);
if (exchange == 0) continue;
if (exchange == 1) {
int x = (int)(Math.random()*20);
if (x == 1) continue;
// let agent 2 flee with some probability
}
if (exchange == 2) {
int x = (int)(Math.random()*20);
if (x == 1) continue;
// let agent 1 flee with some probability
}
// if (exchange == 3) then just proceed as normal with Tag scoring
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
122
}
for (int i = 0; i< defenseTag1.length(); i++){
if (cArrayDefenseTag1[i] == 'a') {
mappingDefenseTag1[i] = 1;
}
else if (cArrayDefenseTag1[i] == 'b') {
mappingDefenseTag1[i] = 2;
}
else if (cArrayDefenseTag1[i] == 'c') {
mappingDefenseTag1[i] = 3;
}
else if (cArrayDefenseTag1[i] == 'd') {
mappingDefenseTag1[i] = 4;
}
}
for (int i = 0; i< defenseTag2.length(); i++){
if (cArrayDefenseTag2[i] == 'a') {
mappingDefenseTag2[i] = 1;
}
else if (cArrayDefenseTag2[i] == 'b') {
mappingDefenseTag2[i] = 2;
}
else if (cArrayDefenseTag2[i] == 'c') {
mappingDefenseTag2[i] = 3;
}
else if (cArrayDefenseTag2[i] == 'd') {
mappingDefenseTag2[i] = 4;
}
}
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< defenseTag2.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingDefenseTag2[j];
if(i == j){
scoreOffenseTag1 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != defenseTag2.length()){
scoreOffenseTag1--;
}
totalScoreOffenseTag1 += scoreOffenseTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< defenseTag1.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag2[i];
int l = mappingDefenseTag1[j];
if(i == j){
scoreOffenseTag2 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != defenseTag1.length()){
scoreOffenseTag2--;
}
totalScoreOffenseTag2 += scoreOffenseTag2;
}
totalOffenseTag1 [count] = totalScoreOffenseTag1;
totalOffenseTag2 [count] = totalScoreOffenseTag2;
totalScore [count] = totalScoreOffenseTag1 + totalScoreOffenseTag2;
count++;
}
}
123
public int checkAgentExchangeConditions(EchoAgent ea1, EchoAgent ea2){
int exchange = 0;
String ea1OffenseTag = null;
String ea2OffenseTag = null;
String ea1ExchangeCondition = null;
String ea2ExchangeCondition = null;
// Get the tags and conditions
ea1OffenseTag = ea1.getOffenseTag();
ea2OffenseTag = ea2.getOffenseTag();
ea1ExchangeCondition = ea1.getExchangeCondition();
ea2ExchangeCondition = ea2.getExchangeCondition();
char[] cArrayOffenseTag1 = ea1OffenseTag.toCharArray();
char[] cArrayOffenseTag2 = ea2OffenseTag.toCharArray();
char[] cArrayExchangeCond1 = ea1ExchangeCondition.toCharArray();
char[] cArrayExchangeCond2 = ea2ExchangeCondition.toCharArray();
// A 'd' in an Exchange Condition counts as a '#' don't care symbol
// Compare agent1 Exchange Condition with agent2 Offense Tag
boolean agent1 = true;
// obtain the length of the Exchange Condition
int ec1 = ea1ExchangeCondition.length();
for (int i=0; i<ea2OffenseTag.length(); i++) {
if ((cArrayOffenseTag2[i] != cArrayExchangeCond1[i]) &&
(cArrayExchangeCond1[i] != 'd') && (i < ec1)) {
agent1 = false;
}
}
// Compare agent2 Exchange Condition with agent1 Offense Tag
boolean agent2 = true;
// obtain the length of the Exchange Condition
int ec2 = ea2ExchangeCondition.length();
for (int i=0; i<ea1OffenseTag.length(); i++) {
if ((cArrayOffenseTag1[i] != cArrayExchangeCond2[i]) &&
(cArrayExchangeCond2[i] != 'd') && (i < ec2)) {
agent2 = false;
}
}
if ((agent1 == true) && (agent2 == true)){
exchange = 3;
}
else if ((agent1 == true) && (agent2 == false)){
exchange = 1;
}
else if ((agent1 == false) && (agent2 == true)){
exchange = 2;
}
else if ((agent1 == false) && (agent2 == false)){
exchange = 0;
}
return exchange;
}
}
/*********************************************************************************
Module Name:
EchoModel3.java
Description:
This class is responsible for implementing the model 3 Echo
mechanisms in JEcho. The model 3 mechanisms are described by
Holland in Hidden Order (1995).
Author:
Brian W. McIndoe
Date:
2/12/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
124
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.util.*;
public class EchoModel3 extends EchoModel2 {
public EchoModel3(){
super();
}
public EchoModel3(EchoSite eSite, int worldXSize, int worldYSize,
float mutateProb, float deathRate, float interactFrac){
super(eSite, worldXSize, worldYSize, mutateProb, deathRate, interactFrac);
}
public void step (double tick) {
// Replenish each sites resources as necessary
mSite.replenishSites();
// Iterate through every site and perform agent tag interactions
for (int i = 0; i < x; i++ ){
for (int j = 0; j < y; j++){
siteAgentList = new ArrayList();
siteAgentInteractList1 = new ArrayList();
siteAgentInteractList2 = new ArrayList();
l = mSite.getObjectsAt(i, j);
Iterator e = l.iterator();
// Make a list of all agents at a particular site (Full List)
while (e.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)e.next();
siteAgentList.add(ea);
}
agentSiteInteractionNum = siteAgentList.size()*(interactionFraction/(2*100)) ;
int m = (int)agentSiteInteractionNum;
int count = 0;
for (int k=0; k<siteAgentList.size(); k++) {
if ((k % 5 == 0)&&(count <= m)){
// int k = (int)(Math.random()*(siteAgentList.size()));
siteAgentInteractList1.add(siteAgentList.get(k));
siteAgentInteractList2.add(siteAgentList.get(k+1));
count++;
}
}
//obtain the match score of the agents offense and defense tags
compareOffenseDefenseTags();
// reallocateResources - use the match score to determine whether combat, or trade occurs
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int counta = 0;
while (e1.hasNext() && e2.hasNext()){
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
125
ea2 = (EchoAgent)e2.next();
reallocateResources(ea1, ea2, totalScore[counta],
totalOffenseTag1[counta], totalOffenseTag2[counta]);
counta++;
}
// Transform resources
// Get the resource transformation condition for each agent and execute it if possible
// Obtain an iterator
Iterator tr = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (tr.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)tr.next();
System.out.println("EchoAgent=" + ea.toString());
ea.transformResources();
System.out.println("EchoAgent=" + ea.toString());
}
// Determine who can reproduce - Reproduce them and mutate them
Iterator sal = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (sal.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)sal.next();
if(ea.canAgentReplicate()){
EchoAgent newAgent = new EchoAgent(tick, ea,
ea.getEchoSite(), ea.getID(),
ea.getOffenseTag(), ea.getDefenseTag(),
ea.getAdhesionTag(), ea.getExchangeCondition(),
ea.getMatingCondition(), ea.getResourceTransformCondition(),
ea.getResourceTransformRate(), ea.getReplicationCondition(),
ea.getReplicationFlag(), ea.getResourceReservoir());
// Mutate the new agent
newAgent.mutateAgent(mutateProbability);
}
// Determine who dies and return their resources to the site
Iterator cull = siteAgentList.iterator();
int every = (int)(1.0/deathRate);
while (cull.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)cull.next();
if(ea.getID() % every == 0){
ea.cullAgent();
ea = null;
}
}
// Agents take resources from the site depending upon the match score
// between the agent and site offense and defense tags
Iterator siteInteraction = siteAgentList.iterator();
// Obtain the resource characteristics at the site
EchoResource er = (EchoResource)mSite.getResource(i,j);
// Get the site resource Offense tag
String rot = er.getResourceOffenseTag();
// Get the site resource Defense tag
String rdt = er.getResourceDefenseTag();
126
// Compare each agent with the site resource tags
while (siteInteraction.hasNext()){
EchoAgent ea = null;
int totalScore = 0;
int aosd = 0;
int adso = 0;
ea = (EchoAgent)siteInteraction.next();
// Compare Agent Offense against Site Defense
aosd = compareAgentOffenseAgainstSiteDefense(ea, rdt);
// Compare Agent Defense against Site Offense
adso = compareAgentDefenseAgainstSiteOffense(ea, rot);
// Obtain the match score
totalScore = aosd + adso;
// Reallocate Resources based on the match score
reallocateAgentSiteResources(ea, er, totalScore,
aosd, adso);
}
}
}
}
// Compare Agent to Agent - Offense and Defense Tags
// In model2 however, first compare the Exchange Conditions of each agent
// with the other agents Offense condition. If both match go ahead and perform
// the exchange. Otherwise, if one matches, give the other agent a chance to
// flee the interaction. Otherwise if both do not match, then abort.
public void compareOffenseDefenseTags () {
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int count = 0;
while (e1.hasNext() && e2.hasNext()){
int scoreOffenseTag1 = 0;
int scoreOffenseTag2 = 0;
int totalScoreOffenseTag1 = 0;
int totalScoreOffenseTag2 = 0;
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
String defenseTag1 = ea1.getDefenseTag();
String defenseTag2 = ea2.getDefenseTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayDefenseTag1 = defenseTag1.toCharArray();
char[] cArrayDefenseTag2 = defenseTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingDefenseTag1 = new int[10];
int[] mappingDefenseTag2 = new int[10];
// Check agents exchange conditions to see if they will interact
// Model 2 mechanism
int exchange = checkAgentExchangeConditions(ea1, ea2);
if (exchange == 0) continue;
if (exchange == 1) {
127
int x = (int)(Math.random()*20);
if (x == 1) continue;
// let agent 2 flee with some probability
}
if (exchange == 2) {
int x = (int)(Math.random()*20);
if (x == 1) continue;
// let agent 1 flee with some probability
}
// if (exchange == 3) then just proceed as normal with Tag scoring
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
}
for (int i = 0; i< defenseTag1.length(); i++){
if (cArrayDefenseTag1[i] == 'a') {
mappingDefenseTag1[i] = 1;
}
else if (cArrayDefenseTag1[i] == 'b') {
mappingDefenseTag1[i] = 2;
}
else if (cArrayDefenseTag1[i] == 'c') {
mappingDefenseTag1[i] = 3;
}
else if (cArrayDefenseTag1[i] == 'd') {
mappingDefenseTag1[i] = 4;
}
}
for (int i = 0; i< defenseTag2.length(); i++){
if (cArrayDefenseTag2[i] == 'a') {
mappingDefenseTag2[i] = 1;
}
else if (cArrayDefenseTag2[i] == 'b') {
mappingDefenseTag2[i] = 2;
}
else if (cArrayDefenseTag2[i] == 'c') {
mappingDefenseTag2[i] = 3;
}
else if (cArrayDefenseTag2[i] == 'd') {
mappingDefenseTag2[i] = 4;
}
}
128
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< defenseTag2.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingDefenseTag2[j];
if(i == j){
scoreOffenseTag1 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != defenseTag2.length()){
scoreOffenseTag1--;
}
totalScoreOffenseTag1 += scoreOffenseTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< defenseTag1.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag2[i];
int l = mappingDefenseTag1[j];
if(i == j){
scoreOffenseTag2 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != defenseTag1.length()){
scoreOffenseTag2--;
}
totalScoreOffenseTag2 += scoreOffenseTag2;
}
totalOffenseTag1 [count] = totalScoreOffenseTag1;
totalOffenseTag2 [count] = totalScoreOffenseTag2;
totalScore [count] = totalScoreOffenseTag1 + totalScoreOffenseTag2;
count++;
}
}
public int checkAgentExchangeConditions(EchoAgent ea1, EchoAgent ea2){
int exchange = 0;
String ea1OffenseTag = null;
String ea2OffenseTag = null;
String ea1ExchangeCondition = null;
String ea2ExchangeCondition = null;
// Get the tags and conditions
ea1OffenseTag = ea1.getOffenseTag();
ea2OffenseTag = ea2.getOffenseTag();
ea1ExchangeCondition = ea1.getExchangeCondition();
ea2ExchangeCondition = ea2.getExchangeCondition();
char[] cArrayOffenseTag1 = ea1OffenseTag.toCharArray();
char[] cArrayOffenseTag2 = ea2OffenseTag.toCharArray();
char[] cArrayExchangeCond1 = ea1ExchangeCondition.toCharArray();
char[] cArrayExchangeCond2 = ea2ExchangeCondition.toCharArray();
// A 'd' in an Exchange Condition counts as a '#' don't care symbol
// Compare agent1 Exchange Condition with agent2 Offense Tag
boolean agent1 = true;
// obtain the length of the Exchange Condition
int ec1 = ea1ExchangeCondition.length();
for (int i=0; i<ec1 && i < cArrayOffenseTag2.length; i++) {
if ((cArrayOffenseTag2[i] != cArrayExchangeCond1[i]) &&
(cArrayExchangeCond1[i] != 'd') && (i < ec1)) {
agent1 = false;
}
}
129
// Compare agent2 Exchange Condition with agent1 Offense Tag
boolean agent2 = true;
// obtain the length of the Exchange Condition
int ec2 = ea2ExchangeCondition.length();
for (int i=0; i<ec2 && i < cArrayOffenseTag1.length; i++) {
if ((cArrayOffenseTag1[i] != cArrayExchangeCond2[i]) &&
(cArrayExchangeCond2[i] != 'd') && (i < ec2)) {
agent2 = false;
}
}
if ((agent1 == true) && (agent2 == true)){
exchange = 3;
}
else if ((agent1 == true) && (agent2 == false)){
exchange = 1;
}
else if ((agent1 == false) && (agent2 == true)){
exchange = 2;
}
else if ((agent1 == false) && (agent2 == false)){
exchange = 0;
}
return exchange;
}
}
/*********************************************************************************
Module Name:
EchoModel4.java
Description:
This class is responsible for implementing the model 4 Echo
mechanisms in JEcho. The model 4 mechanisms are described by
Holland in Hidden Order (1995).
Author:
Brian W. McIndoe
Date:
2/12/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.util.*;
public class EchoModel4 extends EchoModel3 {
protected int [][] adhesionScore = {
// 2D array used to score Agent/Agent Adhesion
{ 2,-2,-2,-2},
{-2, 2,-2,-2},
{-2,-2, 2,-2},
{-2,-2,-2, 2}
};
public EchoModel4(){
super();
}
public EchoModel4(EchoSite eSite, int worldXSize, int worldYSize,
float mutateProb, float deathRate, float interactFrac){
super(eSite, worldXSize, worldYSize, mutateProb, deathRate, interactFrac);
}
public void step (double tick) {
// Replenish each sites resources as necessary
mSite.replenishSites();
130
// Iterate through every site and perform agent tag interactions
for (int i = 0; i < x; i++ ){
for (int j = 0; j < y; j++){
siteAgentList = new ArrayList();
siteAgentInteractList1 = new ArrayList();
siteAgentInteractList2 = new ArrayList();
l = mSite.getObjectsAt(i, j);
Iterator e = l.iterator();
// Make a list of all agents at a particular site (Full List)
while (e.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)e.next();
siteAgentList.add(ea);
}
agentSiteInteractionNum = siteAgentList.size()*(interactionFraction/(2*100)) ;
int m = (int)agentSiteInteractionNum;
int count = 0;
for (int k=0; k<siteAgentList.size(); k++) {
if ((k % 5 == 0)&&(count <= m)){
// int k = (int)(Math.random()*(siteAgentList.size()));
siteAgentInteractList1.add(siteAgentList.get(k));
siteAgentInteractList2.add(siteAgentList.get(k+1));
count++;
}
}
//obtain the match score of the agents offense and defense tags
compareOffenseDefenseTags();
// reallocateResources - use the match score to determine whether combat, or trade occurs
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int counta = 0;
while (e1.hasNext() && e2.hasNext()){
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
reallocateResources(ea1, ea2, totalScore[counta],
totalOffenseTag1[counta], totalOffenseTag2[counta]);
// ADHESION Test takes place here
checkAdhesion(ea1, ea2);
counta++;
}
// Transform resources
// Get the resource transformation condition for each agent and execute it if possible
// Obtain an iterator
Iterator tr = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (tr.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)tr.next();
ea.transformResources();
}
// Determine who can reproduce - Reproduce them and mutate them
131
Iterator sal = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (sal.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)sal.next();
if(ea.canAgentReplicate()){
EchoAgent newAgent = new EchoAgent(tick, ea,
ea.getEchoSite(), ea.getID(),
ea.getOffenseTag(), ea.getDefenseTag(),
ea.getAdhesionTag(), ea.getExchangeCondition(),
ea.getMatingCondition(), ea.getResourceTransformCondition(),
ea.getResourceTransformRate(), ea.getReplicationCondition(),
ea.getReplicationFlag(), ea.getResourceReservoir());
// Mutate the new agent
newAgent.mutateAgent(mutateProbability);
// ADHESION Test takes place here
checkAdhesion(ea, newAgent);
}
}
// Determine who dies and return their resources to the site
Iterator cull = siteAgentList.iterator();
int every = (int)(1.0/deathRate);
while (cull.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)cull.next();
if(ea.getID() % every == 0){
ea.cullAgent();
ea = null;
}
}
// Agents take resources from the site depending upon the match score
// between the agent and site offense and defense tags
Iterator siteInteraction = siteAgentList.iterator();
// Obtain the resource characteristics at the site
EchoResource er = (EchoResource)mSite.getResource(i,j);
// Get the site resource Offense tag
String rot = er.getResourceOffenseTag();
// Get the site resource Defense tag
String rdt = er.getResourceDefenseTag();
// Compare each agent with the site resource tags
while (siteInteraction.hasNext()){
EchoAgent ea = null;
int totalScore = 0;
int aosd = 0;
int adso = 0;
ea = (EchoAgent)siteInteraction.next();
// Compare Agent Offense against Site Defense
aosd = compareAgentOffenseAgainstSiteDefense(ea, rdt);
// Compare Agent Defense against Site Offense
adso = compareAgentDefenseAgainstSiteOffense(ea, rot);
// Obtain the match score
totalScore = aosd + adso;
// Reallocate Resources based on the match score
132
reallocateAgentSiteResources(ea, er, totalScore,
aosd, adso);
}
}
}
}
// Compare Agent to Agent - Offense and Defense Tags
// In model2 however, first compare the Exchange Conditions of each agent
// with the other agents Offense condition. If both match go ahead and perform
// the exchange. Otherwise, if one matches, give the other agent a chance to
// flee the interaction. Otherwise if both do not match, then abort.
public void compareOffenseDefenseTags () {
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int count = 0;
while (e1.hasNext() && e2.hasNext()){
int scoreOffenseTag1 = 0;
int scoreOffenseTag2 = 0;
int totalScoreOffenseTag1 = 0;
int totalScoreOffenseTag2 = 0;
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
String defenseTag1 = ea1.getDefenseTag();
String defenseTag2 = ea2.getDefenseTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayDefenseTag1 = defenseTag1.toCharArray();
char[] cArrayDefenseTag2 = defenseTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingDefenseTag1 = new int[10];
int[] mappingDefenseTag2 = new int[10];
// Check agents exchange conditions to see if they will interact
// Model 2 mechanism
int exchange = checkAgentExchangeConditions(ea1, ea2);
if (exchange == 0) continue;
if (exchange == 1) {
int x = (int)(Math.random()*20);
if (x == 1) continue;
// let agent 2 flee with some probability
}
if (exchange == 2) {
int x = (int)(Math.random()*20);
if (x == 1) continue;
// let agent 1 flee with some probability
}
// if (exchange == 3) then just proceed as normal with Tag scoring
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
133
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
}
for (int i = 0; i< defenseTag1.length(); i++){
if (cArrayDefenseTag1[i] == 'a') {
mappingDefenseTag1[i] = 1;
}
else if (cArrayDefenseTag1[i] == 'b') {
mappingDefenseTag1[i] = 2;
}
else if (cArrayDefenseTag1[i] == 'c') {
mappingDefenseTag1[i] = 3;
}
else if (cArrayDefenseTag1[i] == 'd') {
mappingDefenseTag1[i] = 4;
}
}
for (int i = 0; i< defenseTag2.length(); i++){
if (cArrayDefenseTag2[i] == 'a') {
mappingDefenseTag2[i] = 1;
}
else if (cArrayDefenseTag2[i] == 'b') {
mappingDefenseTag2[i] = 2;
}
else if (cArrayDefenseTag2[i] == 'c') {
mappingDefenseTag2[i] = 3;
}
else if (cArrayDefenseTag2[i] == 'd') {
mappingDefenseTag2[i] = 4;
}
}
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< defenseTag2.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingDefenseTag2[j];
if(i == j){
scoreOffenseTag1 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != defenseTag2.length()){
scoreOffenseTag1--;
}
totalScoreOffenseTag1 += scoreOffenseTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< defenseTag1.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag2[i];
134
int l = mappingDefenseTag1[j];
if(i == j){
scoreOffenseTag2 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != defenseTag1.length()){
scoreOffenseTag2--;
}
totalScoreOffenseTag2 += scoreOffenseTag2;
}
totalOffenseTag1 [count] = totalScoreOffenseTag1;
totalOffenseTag2 [count] = totalScoreOffenseTag2;
totalScore [count] = totalScoreOffenseTag1 + totalScoreOffenseTag2;
count++;
}
}
public int checkAgentExchangeConditions(EchoAgent ea1, EchoAgent ea2){
int exchange = 0;
String ea1OffenseTag = null;
String ea2OffenseTag = null;
String ea1ExchangeCondition = null;
String ea2ExchangeCondition = null;
// Get the tags and conditions
ea1OffenseTag = ea1.getOffenseTag();
ea2OffenseTag = ea2.getOffenseTag();
ea1ExchangeCondition = ea1.getExchangeCondition();
ea2ExchangeCondition = ea2.getExchangeCondition();
char[] cArrayOffenseTag1 = ea1OffenseTag.toCharArray();
char[] cArrayOffenseTag2 = ea2OffenseTag.toCharArray();
char[] cArrayExchangeCond1 = ea1ExchangeCondition.toCharArray();
char[] cArrayExchangeCond2 = ea2ExchangeCondition.toCharArray();
// A 'd' in an Exchange Condition counts as a '#' don't care symbol
// Compare agent1 Exchange Condition with agent2 Offense Tag
boolean agent1 = true;
// obtain the length of the Exchange Condition
int ec1 = ea1ExchangeCondition.length();
for (int i=0; i<ec1 && i < cArrayOffenseTag2.length; i++) {
if ((cArrayOffenseTag2[i] != cArrayExchangeCond1[i]) &&
(cArrayExchangeCond1[i] != 'd') && (i < ec1)) {
agent1 = false;
}
}
// Compare agent2 Exchange Condition with agent1 Offense Tag
boolean agent2 = true;
// obtain the length of the Exchange Condition
int ec2 = ea2ExchangeCondition.length();
for (int i=0; i<ec2 && i < cArrayOffenseTag1.length; i++) {
if ((cArrayOffenseTag1[i] != cArrayExchangeCond2[i]) &&
(cArrayExchangeCond2[i] != 'd') && (i < ec2)) {
agent2 = false;
}
}
if ((agent1 == true) && (agent2 == true)){
exchange = 3;
}
else if ((agent1 == true) && (agent2 == false)){
exchange = 1;
}
else if ((agent1 == false) && (agent2 == true)){
exchange = 2;
}
135
else if ((agent1 == false) && (agent2 == false)){
exchange = 0;
}
return exchange;
}
public void checkAdhesion(EchoAgent ea1, EchoAgent ea2){
int scoreOffenseAdhesionTag1 = 0;
int scoreOffenseAdhesionTag2 = 0;
int tScoreOffenseAdhesionTag1 = 0;
int tScoreOffenseAdhesionTag2 = 0;
int difference = 0;
// Get the Offense Tag for Agent 1 and 2
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
// Get the Adhesion Tag for Agent 1 and 2
String adhesionTag1 = ea1.getAdhesionTag();
String adhesionTag2 = ea2.getAdhesionTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayAdhesionTag1 = adhesionTag1.toCharArray();
char[] cArrayAdhesionTag2 = adhesionTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingAdhesionTag1 = new int[10];
int[] mappingAdhesionTag2 = new int[10];
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
}
for (int i = 0; i< adhesionTag1.length(); i++){
if (cArrayAdhesionTag1[i] == 'a') {
mappingAdhesionTag1[i] = 1;
}
else if (cArrayAdhesionTag1[i] == 'b') {
mappingAdhesionTag1[i] = 2;
}
else if (cArrayAdhesionTag1[i] == 'c') {
mappingAdhesionTag1[i] = 3;
136
}
else if (cArrayAdhesionTag1[i] == 'd') {
mappingAdhesionTag1[i] = 4;
}
}
for (int i = 0; i< adhesionTag2.length(); i++){
if (cArrayAdhesionTag2[i] == 'a') {
mappingAdhesionTag2[i] = 1;
}
else if (cArrayAdhesionTag2[i] == 'b') {
mappingAdhesionTag2[i] = 2;
}
else if (cArrayAdhesionTag2[i] == 'c') {
mappingAdhesionTag2[i] = 3;
}
else if (cArrayAdhesionTag2[i] == 'd') {
mappingAdhesionTag2[i] = 4;
}
}
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< adhesionTag2.length())&&(j< adhesionScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingAdhesionTag2[j];
if(i == j){
scoreOffenseAdhesionTag1 += adhesionScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != adhesionTag2.length()){
scoreOffenseAdhesionTag1--;
}
tScoreOffenseAdhesionTag1 += scoreOffenseAdhesionTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< adhesionTag1.length())&&(j< adhesionScore[i].length); j++){
int k = mappingOffenseTag2[i];
int l = mappingAdhesionTag1[j];
if(i == j){
scoreOffenseAdhesionTag2 += adhesionScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != adhesionTag1.length()){
scoreOffenseAdhesionTag2--;
}
tScoreOffenseAdhesionTag2 += scoreOffenseAdhesionTag2;
}
tOffenseAdhesionTag1 = tScoreOffenseAdhesionTag1;
tOffenseAdhesionTag2 = tScoreOffenseAdhesionTag2;
tScore = tScoreOffenseAdhesionTag1 + tScoreOffenseAdhesionTag2;
// Determine the difference between scores and use this to decide on
// the adhesion relationship of the two agents
difference = tOffenseAdhesionTag1 - tOffenseAdhesionTag2;
// The common boolean signifies whether agents belong to a common boundary or
// not. If not, then the agent listed in the first parameter position is taken
// as the outer boundary agent
boolean common = false;
EchoBoundary eb = null;
if (difference == 0){
137
// No adhesion
} else if ((difference >= 2) && (difference <= 16)){
// Both agents are placed into a common boundary
common = true;
eb = new EchoBoundary(ea1, ea2, common);
} else if (difference > 16){
// Place agent 2 inside agent 1
common = false;
eb = new EchoBoundary(ea1, ea2, common);
} else if ((difference <= -2) && (difference >= -16)){
// Both agents are placed into a common boundary
common = true;
eb = new EchoBoundary(ea1, ea2, common);
} else if (difference < -16){
// Place agent 1 inside agent 2
common = false;
eb = new EchoBoundary(ea2, ea1, common);
}
}
}
/*********************************************************************************
Module Name:
EchoModel5.java
Description:
This class is responsible for implementing the model 5 Echo
mechanisms in JEcho. The model 5 mechanisms are described by
Holland in Hidden Order (1995).
Author:
Brian W. McIndoe
Date:
2/12/2005
Version:
1.0
Statement: This source code is distributed for free use and modification under
the terms of the GNU General Public License.
See http://www.gnu.org/copyleft/gpl.html for more details.
*********************************************************************************/
package com.brianmcindoe.jEcho;
import com.brianmcindoe.*;
import java.util.*;
public class EchoModel5 extends EchoModel4 {
protected float fleeProbability;
protected float migrateProbability;
protected ArrayList reproduceListA;
protected ArrayList reproduceListB;
protected static ArrayList migrateList;
protected ArrayList boundaryList;
protected int siteAgentCountTotal;
protected int [][] siteAgentCount;
protected int [][] adhesionScore = {
// 2D array used to score Agent/Agent Adhesion
{ 2,-2,-2,-2},
{-2, 2,-2,-2},
{-2,-2, 2,-2},
{-2,-2,-2, 2}
};
public EchoModel5(){
super();
}
public EchoModel5(EchoSite eSite, int worldXSize, int worldYSize,
float fleeProb, float migrateProb, float mutateProb, float deathRate, float interactFrac) {
super(eSite, worldXSize, worldYSize, mutateProb, deathRate, interactFrac);
this.fleeProbability = fleeProb;
this.migrateProbability = migrateProb;
138
}
public void step (double tick) {
siteAgentCount = new int[x][y];
siteAgentCountTotal = 0;
int siteAgentCountTmp = 0;
reproduceListA = new ArrayList();
reproduceListB = new ArrayList();
migrateList = new ArrayList();
boundaryList = new ArrayList();
// SITE RESOURCE REPLENISHMENT:
// Replenish each sites resources as necessary
mSite.replenishSites();
// EXCHANGE CONTACT
// Iterate through every site and perform agent tag interactions
for (int i = 0; i < x; i++ ){
for (int j = 0; j < y; j++){
siteAgentList = new ArrayList();
siteAgentInteractList1 = new ArrayList();
siteAgentInteractList2 = new ArrayList();
l = mSite.getObjectsAt(i, j);
Iterator e = l.iterator();
// Make a list of all agents at a particular site (Full List)
while (e.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)e.next();
siteAgentList.add(ea);
}
e = null;
siteAgentCount [i][j] = siteAgentList.size();
siteAgentCountTmp += siteAgentCount [i][j];
agentSiteInteractionNum = siteAgentList.size()*(interactionFraction/(2*100)) ;
int m = (int)agentSiteInteractionNum;
int count = 0;
for (int k=0; k<siteAgentList.size(); k++) {
if ((k % 5 == 0)&&(count <= m)&&((k+1)<siteAgentList.size())){
siteAgentInteractList1.add(siteAgentList.get(k));
siteAgentInteractList2.add(siteAgentList.get(k+1));
count++;
}
}
//obtain the match score of the agents offense and defense tags
compareOffenseDefenseTags();
// EXCHANGE CONTACT - TRADE AND COMBAT
// reallocateResources - use the match score to determine whether combat, or trade occurs
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int counta = 0;
while (e1.hasNext() && e2.hasNext()){
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
reallocateResources(ea1, ea2, totalScore[counta],
totalOffenseTag1[counta], totalOffenseTag2[counta]);
int x = (int)(Math.random() * 2); // 1 in 2 chance adhesion will take
// place
139
if (x == 1){
// ADHESION Test takes place here
checkAdhesion(ea1, ea2);
}
counta++;
}
e1 = null;
e2 = null;
// RESOURCE TRANSFORMATION:
// Get the resource transformation condition for each agent and execute it if possible
// Obtain an iterator
Iterator tr = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (tr.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)tr.next();
ea.transformResources();
}
tr = null;
// AGENT MATING:
// Determine who can reproduce - Reproduce them, cross them and mutate them
Iterator sal = siteAgentList.iterator();
// Make a list of all agents at a particular site (Full List)
while (sal.hasNext()){
EchoAgent ea = null;
ea = (EchoAgent)sal.next();
// Determine if they have enough resources to mate
if(ea.canAgentReplicate()){
// Randomly place agents that can mate into one of two lists
int x = (int)(Math.random() * 2);
switch (x){
case 0:
reproduceListA.add(ea);
break;
case 1:
reproduceListB.add(ea);
break;
}
} else { // Add the agent to the list for potential migration
migrateList.add(ea);
}
}
sal = null;
boolean mate = false;
Iterator rla = reproduceListA.iterator();
Iterator rlb = reproduceListB.iterator();
while (rla.hasNext() && rlb.hasNext()){
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)rla.next();
ea2 = (EchoAgent)rlb.next();
mate = false;
mate = mateAgents (ea1, ea2);
if (mate == true){
// Create two new agents
EchoAgent newAgent1 = new EchoAgent(tick, ea1,
ea1.getEchoSite(), ea1.getID(),
140
ea1.getOffenseTag(), ea1.getDefenseTag(),
ea1.getAdhesionTag(), ea1.getExchangeCondition(),
ea1.getMatingCondition(),
ea1.getResourceTransformCondition(),
ea1.getResourceTransformRate(),
ea1.getReplicationCondition(),
ea1.getReplicationFlag(), ea1.getResourceReservoir());
EchoAgent newAgent2 = new EchoAgent(tick, ea2,
ea2.getEchoSite(), ea2.getID(),
ea2.getOffenseTag(), ea2.getDefenseTag(),
ea2.getAdhesionTag(), ea2.getExchangeCondition(),
ea2.getMatingCondition(),
ea2.getResourceTransformCondition(),
ea2.getResourceTransformRate(),
ea2.getReplicationCondition(),
ea2.getReplicationFlag(), ea2.getResourceReservoir());
// CROSSOVER:
newAgent1.crossAgent(ea1);
newAgent2.crossAgent(ea2);
// MUTATION: Mutate each agent
newAgent1.mutateAgent(mutateProbability);
newAgent2.mutateAgent(mutateProbability);
// ADHESION - Check each new agent for adhesion with its parent
checkAdhesion(ea1, newAgent1);
checkAdhesion(ea2, newAgent2);
}
}
rla = null;
rlb = null;
// MIGRATE AGENTS - Those who were not eligable to reproduce are candidates
//
int migrate = 0;
Iterator ma = migrateList.iterator();
while (ma.hasNext() && ((x != 1) && (y != 1))){
EchoAgent ea = null;
ea = (EchoAgent)ma.next();
migrate = (int)(Math.random()*(1.0/migrateProbability));
if (migrate == 1) {
// Make sure that the agent is not in a boundary
if (ea.getBoundaryID() == 0){
// Migrate the agent to another site
mSite.migrateAgent(ea);
}
}
}
ma = null;
// AGENT DEATH:
// Determine who dies and return their resources to the site
int deathCount = 0;
int deathTarget = (int ) (siteAgentList.size() * deathRate);
Iterator cull = siteAgentList.iterator();
while (cull.hasNext() && (deathCount < deathTarget)){
EchoAgent ea = null;
ea = (EchoAgent)cull.next();
// Remove Agent from its boundary
if(ea.getBoundaryID() > 0){
EchoBoundary eb = new EchoBoundary();
if (otherAgentInBoundary(ea, siteAgentList) == false){
eb.removeAgentFromBoundary(ea);
}
141
}
ea.cullAgent();
mSite.removeAgent(ea);
ea = null;
deathCount++;
}
cull = null;
// AGENT - SITE INTERACTION
// Agents take resources from the site depending upon the match score
// between the agent and site offense and defense tags
Iterator siteInteraction = siteAgentList.iterator();
// Obtain the resource characteristics at the site
EchoResource er = (EchoResource)mSite.getResource(i,j);
// Get the site resource Offense tag
String rot = er.getResourceOffenseTag();
// Get the site resource Defense tag
String rdt = er.getResourceDefenseTag();
// Compare each agent with the site resource tags
while (siteInteraction.hasNext()){
EchoAgent ea = null;
int totalScore = 0;
int aosd = 0;
int adso = 0;
ea = (EchoAgent)siteInteraction.next();
// Compare Agent Offense against Site Defense
aosd = compareAgentOffenseAgainstSiteDefense(ea, rdt);
// Compare Agent Defense against Site Offense
adso = compareAgentDefenseAgainstSiteOffense(ea, rot);
// Obtain the match score
totalScore = aosd + adso;
// Reallocate Resources based on the match score
reallocateAgentSiteResources(ea, er, totalScore,
aosd, adso);
}
siteInteraction = null;
}
}
siteAgentCountTotal = siteAgentCountTmp;
migrateList = null;
System.gc();
}
public boolean otherAgentInBoundary(EchoAgent ea, ArrayList siteAgentList){
boolean otherAgent = false;
EchoAgent e = null;
Iterator it = siteAgentList.iterator();
int aboundaryID = ea.getBoundaryID();
while (it.hasNext()){
e = (EchoAgent)it.next();
if(e.getBoundaryID() > 0 && (e.getBoundaryID() != aboundaryID))
{
otherAgent = true;
}
}
e = null;
ea = null;
return otherAgent;
}
142
// Check the Mating Condition of each paired agent against the Offense tag
// of the other agent
public boolean mateAgents(EchoAgent ea1, EchoAgent ea2){
boolean mate = false;
String ea1OffenseTag = null;
String ea2OffenseTag = null;
String ea1MatingCondition = null;
String ea2MatingCondition = null;
// Get the tags and conditions
ea1OffenseTag = ea1.getOffenseTag();
ea2OffenseTag = ea2.getOffenseTag();
ea1MatingCondition = ea1.getMatingCondition();
ea2MatingCondition = ea2.getMatingCondition();
char[] cArrayOffenseTag1 = ea1OffenseTag.toCharArray();
char[] cArrayOffenseTag2 = ea2OffenseTag.toCharArray();
char[] cArrayMatingCond1 = ea1MatingCondition.toCharArray();
char[] cArrayMatingCond2 = ea2MatingCondition.toCharArray();
// A 'd' in a Mating Condition counts as a '#' don't care symbol
// Compare agent1 Mating Condition with agent2 Offense Tag
boolean agent1 = true;
// obtain the length of the Mating Condition
int em1 = ea1MatingCondition.length();
for (int i=0; i<em1 && i < cArrayOffenseTag2.length; i++) {
if ((cArrayOffenseTag2[i] != cArrayMatingCond1[i]) &&
(cArrayMatingCond1[i] != 'd') && (i < em1)) {
agent1 = false;
}
}
// Compare agent2 Mating Condition with agent1 Offense Tag
boolean agent2 = true;
// obtain the length of the Mating Condition
int em2 = ea2MatingCondition.length();
for (int i=0; i<em2 && i < cArrayOffenseTag1.length; i++) {
if ((cArrayOffenseTag1[i] != cArrayMatingCond2[i]) &&
(cArrayMatingCond2[i] != 'd') && (i < em2)) {
agent2 = false;
}
}
if ((agent1 == true) && (agent2 == true)){
mate = true;
}
ea1OffenseTag = null;
ea2OffenseTag = null;
ea1MatingCondition = null;
ea2MatingCondition = null;
return mate;
}
// Compare Agent to Agent - Offense and Defense Tags
// In model2 however, first compare the Exchange Conditions of each agent
// with the other agents Offense condition. If both match go ahead and perform
// the exchange. Otherwise, if one matches, give the other agent a chance to
// flee the interaction. Otherwise if both do not match, then abort.
public void compareOffenseDefenseTags () {
Iterator e1 = siteAgentInteractList1.iterator();
Iterator e2 = siteAgentInteractList2.iterator();
int count = 0;
while (e1.hasNext() && e2.hasNext()){
int scoreOffenseTag1 = 0;
143
int scoreOffenseTag2 = 0;
int totalScoreOffenseTag1 = 0;
int totalScoreOffenseTag2 = 0;
EchoAgent ea1 = null;
EchoAgent ea2 = null;
ea1 = (EchoAgent)e1.next();
ea2 = (EchoAgent)e2.next();
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
String defenseTag1 = ea1.getDefenseTag();
String defenseTag2 = ea2.getDefenseTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayDefenseTag1 = defenseTag1.toCharArray();
char[] cArrayDefenseTag2 = defenseTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingDefenseTag1 = new int[10];
int[] mappingDefenseTag2 = new int[10];
// Check agents exchange conditions to see if they will interact
// Model 2 mechanism
int exchange = checkAgentExchangeConditions(ea1, ea2);
if (exchange == 0) continue;
if (exchange == 1) {
int x = (int)(Math.random()*(1.0/fleeProbability));
if (x == 1) {
continue;}
// let agent 2 flee with some probability
}
if (exchange == 2) {
int x = (int)(Math.random()*(1.0/fleeProbability));
if (x == 1) continue;
// let agent 1 flee with some probability
}
// if (exchange == 3) then just proceed as normal with Tag scoring
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
}
144
for (int i = 0; i< defenseTag1.length(); i++){
if (cArrayDefenseTag1[i] == 'a') {
mappingDefenseTag1[i] = 1;
}
else if (cArrayDefenseTag1[i] == 'b') {
mappingDefenseTag1[i] = 2;
}
else if (cArrayDefenseTag1[i] == 'c') {
mappingDefenseTag1[i] = 3;
}
else if (cArrayDefenseTag1[i] == 'd') {
mappingDefenseTag1[i] = 4;
}
}
for (int i = 0; i< defenseTag2.length(); i++){
if (cArrayDefenseTag2[i] == 'a') {
mappingDefenseTag2[i] = 1;
}
else if (cArrayDefenseTag2[i] == 'b') {
mappingDefenseTag2[i] = 2;
}
else if (cArrayDefenseTag2[i] == 'c') {
mappingDefenseTag2[i] = 3;
}
else if (cArrayDefenseTag2[i] == 'd') {
mappingDefenseTag2[i] = 4;
}
}
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< defenseTag2.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingDefenseTag2[j];
if(i == j){
scoreOffenseTag1 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != defenseTag2.length()){
scoreOffenseTag1--;
}
totalScoreOffenseTag1 += scoreOffenseTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< defenseTag1.length())&&(j< modelScore[i].length); j++){
int k = mappingOffenseTag2[i];
int l = mappingDefenseTag1[j];
if(i == j){
scoreOffenseTag2 += modelScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != defenseTag1.length()){
scoreOffenseTag2--;
}
totalScoreOffenseTag2 += scoreOffenseTag2;
}
totalOffenseTag1 [count] = totalScoreOffenseTag1;
totalOffenseTag2 [count] = totalScoreOffenseTag2;
totalScore [count] = totalScoreOffenseTag1 + totalScoreOffenseTag2;
count++;
offenseTag1 = null;
offenseTag2 = null;
defenseTag1 = null;
145
defenseTag2 = null;
ea1 = null;
ea2 = null;
}
e1 = null;
e2 = null;
}
public int checkAgentExchangeConditions(EchoAgent ea1, EchoAgent ea2){
int exchange = 0;
String ea1OffenseTag = null;
String ea2OffenseTag = null;
String ea1ExchangeCondition = null;
String ea2ExchangeCondition = null;
// Get the tags and conditions
ea1OffenseTag = ea1.getOffenseTag();
ea2OffenseTag = ea2.getOffenseTag();
ea1ExchangeCondition = ea1.getExchangeCondition();
ea2ExchangeCondition = ea2.getExchangeCondition();
char[] cArrayOffenseTag1 = ea1OffenseTag.toCharArray();
char[] cArrayOffenseTag2 = ea2OffenseTag.toCharArray();
char[] cArrayExchangeCond1 = ea1ExchangeCondition.toCharArray();
char[] cArrayExchangeCond2 = ea2ExchangeCondition.toCharArray();
// A 'd' in an Exchange Condition counts as a '#' don't care symbol
// Compare agent1 Exchange Condition with agent2 Offense Tag
boolean agent1 = true;
// obtain the length of the Exchange Condition
int ec1 = ea1ExchangeCondition.length();
for (int i=0; i<ec1 && i < cArrayOffenseTag2.length; i++) {
if ((cArrayOffenseTag2[i] != cArrayExchangeCond1[i]) &&
(cArrayExchangeCond1[i] != 'd') && (i < ec1)) {
agent1 = false;
}
}
// Compare agent2 Exchange Condition with agent1 Offense Tag
boolean agent2 = true;
// obtain the length of the Exchange Condition
int ec2 = ea2ExchangeCondition.length();
for (int i=0; i<ec2 && i < cArrayOffenseTag1.length; i++) {
if ((cArrayOffenseTag1[i] != cArrayExchangeCond2[i]) &&
(cArrayExchangeCond2[i] != 'd') && (i < ec2)) {
agent2 = false;
}
}
if ((agent1 == true) && (agent2 == true)){
exchange = 3;
}
else if ((agent1 == true) && (agent2 == false)){
exchange = 1;
}
else if ((agent1 == false) && (agent2 == true)){
exchange = 2;
}
else if ((agent1 == false) && (agent2 == false)){
exchange = 0;
}
ea1OffenseTag = null;
ea2OffenseTag = null;
ea1ExchangeCondition = null;
ea2ExchangeCondition = null;
return exchange;
}
public void checkAdhesion(EchoAgent ea1, EchoAgent ea2){
146
int scoreOffenseAdhesionTag1 = 0;
int scoreOffenseAdhesionTag2 = 0;
int tScoreOffenseAdhesionTag1 = 0;
int tScoreOffenseAdhesionTag2 = 0;
int difference = 0;
// Get the Offense Tag for Agent 1 and 2
String offenseTag1 = ea1.getOffenseTag();
String offenseTag2 = ea2.getOffenseTag();
// Get the Adhesion Tag for Agent 1 and 2
String adhesionTag1 = ea1.getAdhesionTag();
String adhesionTag2 = ea2.getAdhesionTag();
char[] cArrayOffenseTag1 = offenseTag1.toCharArray();
char[] cArrayOffenseTag2 = offenseTag2.toCharArray();
char[] cArrayAdhesionTag1 = adhesionTag1.toCharArray();
char[] cArrayAdhesionTag2 = adhesionTag2.toCharArray();
int[] mappingOffenseTag1 = new int[10];
int[] mappingOffenseTag2 = new int[10];
int[] mappingAdhesionTag1 = new int[10];
int[] mappingAdhesionTag2 = new int[10];
for (int i = 0; i< offenseTag1.length(); i++){
if (cArrayOffenseTag1[i] == 'a') {
mappingOffenseTag1[i] = 1;
}
else if (cArrayOffenseTag1[i] == 'b') {
mappingOffenseTag1[i] = 2;
}
else if (cArrayOffenseTag1[i] == 'c') {
mappingOffenseTag1[i] = 3;
}
else if (cArrayOffenseTag1[i] == 'd') {
mappingOffenseTag1[i] = 4;
}
}
for (int i = 0; i< offenseTag2.length(); i++){
if (cArrayOffenseTag2[i] == 'a') {
mappingOffenseTag2[i] = 1;
}
else if (cArrayOffenseTag2[i] == 'b') {
mappingOffenseTag2[i] = 2;
}
else if (cArrayOffenseTag2[i] == 'c') {
mappingOffenseTag2[i] = 3;
}
else if (cArrayOffenseTag2[i] == 'd') {
mappingOffenseTag2[i] = 4;
}
}
for (int i = 0; i< adhesionTag1.length(); i++){
if (cArrayAdhesionTag1[i] == 'a') {
mappingAdhesionTag1[i] = 1;
}
else if (cArrayAdhesionTag1[i] == 'b') {
mappingAdhesionTag1[i] = 2;
}
else if (cArrayAdhesionTag1[i] == 'c') {
mappingAdhesionTag1[i] = 3;
}
else if (cArrayAdhesionTag1[i] == 'd') {
mappingAdhesionTag1[i] = 4;
}
}
for (int i = 0; i< adhesionTag2.length(); i++){
if (cArrayAdhesionTag2[i] == 'a') {
147
mappingAdhesionTag2[i] = 1;
}
else if (cArrayAdhesionTag2[i] == 'b') {
mappingAdhesionTag2[i] = 2;
}
else if (cArrayAdhesionTag2[i] == 'c') {
mappingAdhesionTag2[i] = 3;
}
else if (cArrayAdhesionTag2[i] == 'd') {
mappingAdhesionTag2[i] = 4;
}
}
for (int i = 0; i< offenseTag1.length(); i++){
for (int j = 0;(j< adhesionTag2.length())&&(j< adhesionScore[i].length); j++){
int k = mappingOffenseTag1[i];
int l = mappingAdhesionTag2[j];
if(i == j){
scoreOffenseAdhesionTag1 += adhesionScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag1.length() != adhesionTag2.length()){
scoreOffenseAdhesionTag1--;
}
tScoreOffenseAdhesionTag1 += scoreOffenseAdhesionTag1;
}
for (int i = 0; i< offenseTag2.length(); i++){
for (int j = 0;(j< adhesionTag1.length())&&(j< adhesionScore[i].length); j++){
int k = mappingOffenseTag2[i];
int l = mappingAdhesionTag1[j];
if(i == j){
scoreOffenseAdhesionTag2 += adhesionScore[k-1][l-1];
}
}
// take into account unequal length tags
if (offenseTag2.length() != adhesionTag1.length()){
scoreOffenseAdhesionTag2--;
}
tScoreOffenseAdhesionTag2 += scoreOffenseAdhesionTag2;
}
tOffenseAdhesionTag1 = tScoreOffenseAdhesionTag1;
tOffenseAdhesionTag2 = tScoreOffenseAdhesionTag2;
tScore = tScoreOffenseAdhesionTag1 + tScoreOffenseAdhesionTag2;
// Determine the difference between scores and use this to decide on
// the adhesion relationship of the two agents
difference = tOffenseAdhesionTag1 - tOffenseAdhesionTag2;
// The common boolean signifies whether agents belong to a common boundary or
// not. If not, then the agent listed in the first parameter position is taken
// as the outer boundary agent
boolean common = false;
EchoBoundary eb = null;
if (difference == 0){
// No adhesion
} else if ((difference >= 2) && (difference <= 16)){
// Both agents are placed into a common boundary
common = true;
eb = new EchoBoundary(ea1, ea2, common);
if (eb != null){
boundaryList.add(eb);
148
}
} else if (difference > 16){
// Place agent 2 inside agent 1
common = false;
eb = new EchoBoundary(ea1, ea2, common);
if (eb != null){
boundaryList.add(eb);
}
} else if ((difference <= -2) && (difference >= -16)){
// Both agents are placed into a common boundary
common = true;
eb = new EchoBoundary(ea1, ea2, common);
if (eb != null){
boundaryList.add(eb);
}
} else if (difference < -16){
// Place agent 1 inside agent 2
common = false;
eb = new EchoBoundary(ea2, ea1, common);
if (eb != null){
boundaryList.add(eb);
}
}
offenseTag1 = null;
offenseTag2 = null;
adhesionTag1 = null;
adhesionTag2 = null;
eb = null;
}
public int getNumberOfAgentsInABoundary(){
EchoBoundary eb = new EchoBoundary();
return eb.getNumberOfAgentsInABoundary();
}
}
149