SIRAnalysis_step7 - gama-platform/gama GitHub Wiki

7. Beta^d Sensitivity Analysis

This final step introduces Beta^d, the third sensitivity analysis method available in GAMA. It complements Morris and Sobol by taking a fundamentally different perspective: instead of measuring how much a parameter contributes to output variance, it measures how much fixing a parameter shifts the entire output distribution.

In particular, this step presents:

  • The principle of the Beta^d method and what distinguishes it from Morris and Sobol
  • How to declare method betad and configure its facets
  • How to choose a sampling strategy for Beta^d
  • How to read the report and combine results across all three methods

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


How Beta^d works

Beta^d is a distribution-based sensitivity analysis method, proposed by Baucells and Borgonovo (2013). For each parameter Xi, it computes the expected maximum absolute difference between the unconditional output distribution F(Y) and the conditional distribution F(Y|Xi):

β^d_i = E[ max | F(Y) − F(Y|Xi) | ]

Intuitively, a parameter with a high Beta^d index is one where knowing its value substantially changes what we expect the output distribution to look like — regardless of whether it shifts the mean, the variance, or the tails.

This makes Beta^d sensitive to effects that Morris and Sobol can miss:

  • A parameter that shifts only the tails of the distribution without changing the mean or variance will have low S1 and low μ*, but high Beta^d.
  • A parameter that causes bimodal output distributions will be detected by Beta^d but not by variance-based methods.

Comparing all three methods

Morris Sobol Beta^d
Basis Elementary effects Variance decomposition Distribution shift
Main index μ* ST β^d
Interactions Detected via σ Quantified via ST Fully included
Detects tail effects No No Yes
Cost r × (k+1) N × (2k+2) sample
Best for Screening Quantification Distribution-aware screening

Used together, the three methods provide a comprehensive picture of parameter sensitivity. A parameter that ranks high across all three can be considered robustly influential. A parameter that ranks high only in Beta^d is worth investigating for distributional effects.


Sampling strategy

Unlike Morris and Sobol, Beta^d has no dedicated sampling algorithm. The sampling: facet accepts any of the standard strategies: latinhypercube, orthogonal, uniform, factorial. Orthogonal sampling is recommended because it guarantees uniform marginal coverage across all parameters simultaneously, which is important for accurately estimating conditional distributions.

Total runs = sample. With sample: 200:

200 runs

This is the cheapest of the three methods in terms of run count, though the quality of the Beta^d estimates improves with larger samples.


The method betad statement

The facets are:

  • outputs: — list of global variables to analyse. Mandatory.
  • sample: — number of parameter points to draw. Mandatory.
  • sampling: — sampling algorithm. orthogonal is recommended.
  • report: — path to the output file. Use .txt for a human-readable report. Mandatory.
  • results: — path to the raw CSV with one row per run. Optional but recommended.
  • bootstrap: — number of resamples for confidence interval estimation. Optional.
method betad
    outputs:  ["nb_recovered"]
    sample:   200
    sampling: orthogonal
    report:   "../results/betad_report.txt"
    results:  "../results/betad_raw.csv";

Reading the report

Our experiment resulted in the following report :

Beta^d report

After the run, betad_report.txt lists one Beta^d index per parameter. Higher values indicate parameters whose variation causes larger shifts in the output distribution. The ranking should be broadly consistent with the Morris μ* and Sobol ST rankings for parameters with strong direct effects. Divergences between the rankings are informative — they suggest that some parameters influence the distribution in ways that go beyond their variance contribution.


Complete model

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;
    }
}

// Total runs = sample = 200 runs
experiment SIR_Betad type: batch
    repeat:    1
    keep_seed: false
    until: (cycle >= max_steps or nb_infected = 0) {

    parameter "Number of agents"    var: nb_agents          min: 50  max: 500;
    parameter "Initially infected"  var: nb_infected_init   min: 1   max: 50;
    parameter "Infection rate"      var: infection_rate     min: 0.0 max: 1.0;
    parameter "Infection distance"  var: infection_distance min: 1   max: 20;
    parameter "Recovery time"       var: recovery_time      min: 10  max: 200;

    method betad
        outputs:  ["nb_recovered"]
        sample:   200
        sampling: orthogonal
        report:   "../results/betad_report.txt"
        results:  "../results/betad_raw.csv";
}

Conclusion

This tutorial has walked through the full exploration and sensitivity analysis workflow available in GAMA, from a simple GUI experiment to three complementary sensitivity analysis methods:

  1. LHS exploration — covers the parameter space efficiently and saves raw results
  2. Stochastic analysis — determines how many replications are needed before interpreting any sensitivity index
  3. Morris — screens parameters cheaply and ranks them by μ*
  4. Sobol — quantifies variance contributions via S1 and ST
  5. Beta^d — detects distributional sensitivity invisible to variance-based methods

The recommended workflow is always to run them in this order: stochanalyse first to calibrate the replication count, Morris next to screen and reduce the parameter space, then Sobol and Beta^d on the reduced set for quantification and cross-validation.

For further reading, refer to the Exploration Methods reference page and the Batch Experiments documentation.