This second step illustrates how to create monitors and charts to follows the evolution of variables and to add an ending condition to the simulation.
GAMA offers the possibility to define dynamic variable that will be recomputed at each simulation step by using the update facet when defining a variable. When an agent is activated, first, it recomputes each of its variables with a update facet (in their definition order), then it activates each of its reflexes (in their definition order).
To better follow the evolution of sick people, we add three new global variables to the model:
global{
//... other attributes
int nb_people_infected <- nb_infected_init update: people count (each.is_infected);
int nb_people_not_infected <- nb_people - nb_infected_init update: nb_people - nb_people_infected;
float infected_rate update: nb_people_infected/nb_people;
//... init
}
We used the count operator that allows to count the number of elements of a list for which the left condition is true. The keyword each represents each element of the list.
The simplest way to add an ending condition to a model is to add a global reflex that is activated at the end of the simulation that will pause the simulation (use of the pause global action).
In our model, we add a new reflex called end_simulation that will be activated when the infected rate is 1.0 (i.e. all the people agents are infected) and that will apply the pause action.
global {
//.. variable and init definition
reflex end_simulation when: infected_rate = 1.0 {
do pause;
}
}
GAMA provides modelers with the possibility to define monitors. A monitor allows to follow the value of an arbitrary expression in GAML. It will appear, in the User Interface, in a small window on its own and be recomputed every time step (or according to its ‘refresh’ facet).
Definition of a monitor:
For our model, we define a monitor to follow the value of the infected_rate variable:
experiment main_experiment type:gui{
//...parameters
output {
monitor "Infected people rate" value: infected_rate;
//...display
}
}
In GAMA, charts are considered as a display layer. GAMA can display 3 main types of charts using the type facet:
In our model, we define a new display called _ chart_display_ that will be refresh every 10 simulation steps. In this display, we add a series charts with 2 layers of data:
experiment main_experiment type:gui{
//...parameters
output {
//...display and monitors
display chart_display refresh:every(10) {
chart "Disease spreading" type: series {
data "susceptible" value: nb_people_not_infected color: #green;
data "infected" value: nb_people_infected color: #red;
}
}
}
}
model SI_city2
global{
int nb_people <- 2147;
int nb_infected_init <- 5;
float step <- 1 #mn;
geometry shape<-square(1500 #m);
int nb_people_infected <- nb_infected_init update: people count (each.is_infected);
int nb_people_not_infected <- nb_people - nb_infected_init update: nb_people - nb_people_infected;
float infected_rate update: nb_people_infected/nb_people;
init{
create people number:nb_people;
ask nb_infected_init among people {
is_infected <- true;
}
}
reflex end_simulation when: infected_rate = 1.0 {
do pause;
}
}
species people skills:[moving]{
float speed <- (2 + rnd(3)) #km/#h;
bool is_infected <- false;
reflex move{
do wander;
}
reflex infect when: is_infected{
ask people at_distance 10 #m {
if flip(0.05) {
is_infected <- true;
}
}
}
aspect circle{
draw circle(10) color:is_infected ? #red : #green;
}
}
experiment main_experiment type:gui{
parameter "Nb people infected at init" var: nb_infected_init min: 1 max: 2147;
output {
monitor "Infected people rate" value: infected_rate;
display map type: opengl{
species people aspect:circle;
}
display chart refresh:every(10) {
chart "Disease spreading" type: series {
data "susceptible" value: nb_people_not_infected color: #green;
data "infected" value: nb_people_infected color: #red;
}
}
}
}