SIRAnalysis_step2 - gama-platform/gama GitHub Wiki

2. Stop Condition and Simulation Timer

This second step adds a stop condition to the model so that the simulation halts automatically. This is a necessary prerequisite before running any batch experiment — without it, each simulation run would continue indefinitely and the batch scheduler would never move to the next parameter configuration.

In particular, this step presents:

  • Why do halt must be used instead of do pause in the context of batch experiments
  • How to combine two stopping criteria with or
  • How the until: facet of a batch experiment relates to the model's stop condition

The model file for this step can be found in: Library models/Tutorials/SIRAnalysis/models/SIR.gaml


do halt vs do pause

GAMA provides two ways to stop a running simulation:

Statement Effect
do pause Freezes the entire experiment, including the batch scheduler. Subsequent runs never start.
do halt Terminates only the current simulation instance. The batch scheduler continues to the next run.

For a GUI experiment used interactively, both work fine. But as soon as you introduce a batch experiment, do pause breaks the exploration — every run stops at the first simulation and the batch never completes. Always use do halt in models intended for batch.


Adding the stop condition

A single reflex added to the global block is sufficient. It fires when either of two conditions is true: the epidemic is over (no infected agents remain) or the simulation has run for the maximum number of cycles.

global {
    // ... (unchanged from step 1)
    int max_steps <- 1000;

    reflex stop when: cycle >= max_steps or nb_infected = 0 {
        do halt;
    }
}

Note: nb_infected is already updated each step by the update_counts reflex defined in step 1. The two reflexes are independent — GAMA executes all reflexes whose when: condition is true at each step, in the order they are declared.


Complete model

The only changes from step 1 are the addition of max_steps and the stop reflex. Everything else is identical.

model SIR

global {
    int    nb_agents          <- 200  min: 50   max: 500;
    int    nb_infected_init   <- 5    min: 1    max: 50;
    float  infection_rate     <- 0.5  min: 0.0  max: 1.0;
    int    infection_distance <- 5    min: 1    max: 20;
    int    recovery_time      <- 50   min: 10   max: 200;
    int    max_steps          <- 1000;

    int nb_susceptible <- 0;
    int nb_infected    <- 0;
    int nb_recovered   <- 0;

    init {
        create person number: nb_agents;
        ask nb_infected_init among (person as list) {
            status          <- "infected";
            infection_timer <- recovery_time;
        }
    }

    reflex update_counts {
        nb_susceptible <- person count (each.status = "susceptible");
        nb_infected    <- person count (each.status = "infected");
        nb_recovered   <- person count (each.status = "recovered");
    }

    reflex stop when: cycle >= max_steps or nb_infected = 0 {
        do halt;
    }
}

species person skills: [moving] {
    string status <- "susceptible";
    int infection_timer <- 0;
    float speed <- 1.0;

    reflex move {
        do wander();
    }

    reflex infect when: status = "infected" {
        ask (person at_distance infection_distance) where (each.status = "susceptible") {
            if flip(infection_rate) {
                status          <- "infected";
                infection_timer <- recovery_time;
            }
        }
        infection_timer <- infection_timer - 1;
        if infection_timer <= 0 {
            status <- "recovered";
        }
    }

    aspect base {
        draw circle(1) at: location color:
    		(status = "infected") ? #red : ((status = "recovered") ? #blue : #green);
    }
}

experiment SIR_gui type: gui {
    parameter "Number of agents"    var: nb_agents;
    parameter "Initially infected"  var: nb_infected_init;
    parameter "Infection rate"      var: infection_rate;
    parameter "Infection distance"  var: infection_distance;
    parameter "Recovery time"       var: recovery_time;

    output {
        display "Population" type: java2D {
            species person aspect: base;
        }
        display "SIR Chart" type: java2D {
            chart "SIR dynamics" type: series {
                data "Susceptible" value: nb_susceptible color: #green;
                data "Infected"    value: nb_infected    color: #red;
                data "Recovered"   value: nb_recovered   color: #blue;
            }
        }
        monitor "Susceptible" value: nb_susceptible;
        monitor "Infected"    value: nb_infected;
        monitor "Recovered"   value: nb_recovered;
        monitor "Cycle"       value: cycle;
    }
}

What's next?

In Step 3, we add a batch experiment to the model and use Latin Hypercube Sampling to systematically explore the five-dimensional parameter space and save the results to a CSV file.