3  Stochastics Plugin

The stochastics plugin provides for the management of random number generators. It contains a default random number generator (RNG) as well as any number of RNGs associated with identifiers.

3.1 Plugin Data Initialization

The plugin is initialized using a StochasticsPluginData object that collects starting seed values for the default RNG as well as any number of RNG identifiers. These identifiers are implemented via the RandomGeneratorId interface which only specifies that such an identifier have a non-null, non-empty and stable implementation of the Object.toString() method.

All RNGs in GCM are implemented using the org.apache.commons.math3.random.Well44497b random number generator. GCM introduces the class Well.java that extends the Well44497b to allow for the serialization of its internal state. The data that supports this serialization is contained in the WellState.java class that uses a standard builder pattern. Serialization concerns are beyond the scope of this chapter, so all WellState objects will be seeded with long values only.

3.2 Plugin Behavior

The plugin adds a single data manager to the simulation as an instance of the StochasticsDataManager that is initialized with the StochasticsPluginData.

3.3 Data Manager

The data manager provides access to its RNGs via various getter methods.

3.4 (Lesson 11) Example 11A

Our first example lesson uses the disease, model and policy plugins again. This time we will have the single ModelActor schedule three random times to set the R0 value to a random number between 1 and 2. Four scenarios will result from a policy based dimension that alters the school closing infection rates, which will not influence the ModelActor.

Code Block 3.1: The policy dimension has four levels for the infection rates that trigger school closure.
private static Dimension getPolicyDimension() {
    FunctionalDimensionData.Builder builder = FunctionalDimensionData.builder();//

    List<Double> schoolClosingInfectionRates = new ArrayList<>();
    schoolClosingInfectionRates.add(0.05);
    schoolClosingInfectionRates.add(0.10);
    schoolClosingInfectionRates.add(0.15);
    schoolClosingInfectionRates.add(0.20);

    for (int i = 0; i < schoolClosingInfectionRates.size(); i++) {
        Double schoolClosingInfectionRate = schoolClosingInfectionRates.get(i);
        builder.addValue("Level_" + i, (context) -> {
            PolicyPluginData.Builder pluginDataBuilder = context
                    .getPluginDataBuilder(PolicyPluginData.Builder.class);
            pluginDataBuilder.setSchoolClosingInfectionRate(schoolClosingInfectionRate);

            ArrayList<String> result = new ArrayList<>();
            result.add(Double.toString(schoolClosingInfectionRate));

            return result;
        });//
    }

    builder.addMetaDatum("school_closing_infection_rate");//

    FunctionalDimensionData functionalDimensionData = builder.build();
    return new FunctionalDimension(functionalDimensionData);

}
Code Block 3.2: Example 11 introduces the stochastics plugin and executes four scenarios. The random seed for each scenario will be identical.
public static void main(String[] args) {

    DiseasePluginData diseasePluginData = getDiseasePluginData();
    Plugin diseasePlugin = DiseasePlugin.getDiseasePlugin(diseasePluginData);

    PolicyPluginData policyPluginData = getPolicyPluginData();
    Plugin policyPlugin = PolicyPlugin.getPolicyPlugin(policyPluginData);

    Plugin modelPlugin = ModelPlugin.getModelPlugin();

    WellState wellState = WellState.builder().setSeed(0).build();
    StochasticsPluginData stochasticsPluginData = StochasticsPluginData.builder().setMainRNGState(wellState)
            .build();
    Plugin stochasticsPlugin = StochasticsPlugin.getStochasticsPlugin(stochasticsPluginData);

    Dimension policyDimension = getPolicyDimension();

    ExperimentParameterData experimentParameterData = ExperimentParameterData.builder()//
            .setThreadCount(4)//
            .setHaltOnException(true)//
            .build();

    Experiment.builder()//
            .addPlugin(stochasticsPlugin)//
            .addPlugin(diseasePlugin)//
            .addPlugin(modelPlugin)//
            .addPlugin(policyPlugin)//
            .addDimension(policyDimension)//
            .addExperimentContextConsumer(new SimpleOutputConsumer())//
            .setExperimentParameterData(experimentParameterData)//
            .build()//
            .execute();
}

The stochastics plugin is initialized with a seed value of zero and that seed will be used in each scenario as the initial seeding for the default random generator. Thus we expect that each scenario will have identical output.

Figure 3.1: The output for example 11 shows the four scenarios each reporting three changes to R0 by the model actor.
scenario school_closing_infection_rate output
1 0.10 setting R0 to 1.432233562051883 at time = 3.252869296309885
1 0.10 setting R0 to 1.1828080336720215 at time = 4.115633147309184
0 0.05 setting R0 to 1.432233562051883 at time = 3.252869296309885
3 0.20 setting R0 to 1.432233562051883 at time = 3.252869296309885
1 0.10 setting R0 to 1.895526664357549 at time = 8.614888683848772
0 0.05 setting R0 to 1.1828080336720215 at time = 4.115633147309184
2 0.15 setting R0 to 1.432233562051883 at time = 3.252869296309885
3 0.20 setting R0 to 1.1828080336720215 at time = 4.115633147309184
0 0.05 setting R0 to 1.895526664357549 at time = 8.614888683848772
2 0.15 setting R0 to 1.1828080336720215 at time = 4.115633147309184
3 0.20 setting R0 to 1.895526664357549 at time = 8.614888683848772
2 0.15 setting R0 to 1.895526664357549 at time = 8.614888683848772

3.5 Example 11B

Our next example lesson adds a dimension used to alter the initial seed value of the stochastics plugin data to one of three values. Combined with the policy dimension, this will result in 12 scenarios.

Code Block 3.3: The stochastics dimension introduces three random seeds that will be used in creating the scenarios. Note that seeds are generated outside of the levels within the dimension.
private static Dimension getStochasticsDimension(long seed) {
    FunctionalDimensionData.Builder builder = FunctionalDimensionData.builder();//

    Random random = new Random(seed);

    List<Long> seedValues = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        seedValues.add(random.nextLong());
    }

    IntStream.range(0, seedValues.size()).forEach((i) -> {
        builder.addValue("Level_" + i, (context) -> {
            StochasticsPluginData.Builder stochasticsPluginDataBuilder = context
                    .getPluginDataBuilder(StochasticsPluginData.Builder.class);
            long seedValue = seedValues.get(i);
            WellState wellState = WellState.builder().setSeed(seedValue).build();
            stochasticsPluginDataBuilder.setMainRNGState(wellState);

            ArrayList<String> result = new ArrayList<>();
            result.add(Integer.toString(i));
            result.add(Long.toString(seedValue) + "L");

            return result;
        });
    });

    builder.addMetaDatum("seed index");//
    builder.addMetaDatum("seed value");//

    FunctionalDimensionData functionalDimensionData = builder.build();
    return new FunctionalDimension(functionalDimensionData);
}
Code Block 3.4: The experiment uses the stochastics dimension, resulting in twelve scenarios.
public static void main(String[] args) {

    DiseasePluginData diseasePluginData = getDiseasePluginData();
    Plugin diseasePlugin = DiseasePlugin.getDiseasePlugin(diseasePluginData);

    PolicyPluginData policyPluginData = getPolicyPluginData();
    Plugin policyPlugin = PolicyPlugin.getPolicyPlugin(policyPluginData);

    Plugin modelPlugin = ModelPlugin.getModelPlugin();
    WellState wellState = WellState.builder().setSeed(0).build();
    StochasticsPluginData stochasticsPluginData = StochasticsPluginData.builder().setMainRNGState(wellState)
            .build();
    Plugin stochasticsPlugin = StochasticsPlugin.getStochasticsPlugin(stochasticsPluginData);

    Dimension policyDimension = getPolicyDimension();
    Dimension stochasticsDimension = getStochasticsDimension(539847398756272L);

    ExperimentParameterData experimentParameterData = ExperimentParameterData.builder()//
            .setThreadCount(4)//
            .build();

    Experiment.builder()//
            .addPlugin(stochasticsPlugin)//
            .addPlugin(diseasePlugin)//
            .addPlugin(modelPlugin)//
            .addPlugin(policyPlugin)//
            .addDimension(policyDimension)//
            .addDimension(stochasticsDimension)//
            .addExperimentContextConsumer(new SimpleOutputConsumer())//
            .setExperimentParameterData(experimentParameterData)//
            .build()//
            .execute();
}

The resulting output shows the varying random number generation:

Figure 3.2: The output show that twelve scearnios result in 36 output lines since the model actor update R0 three times per scenario.
scenario school_closing_infection_rate seed_index seed_value output
3 0.2 0 1768604912325913878L setting R0 to 1.4595120508977955 at time = 5.672294645832067
2 0.15 0 1768604912325913878L setting R0 to 1.4595120508977955 at time = 5.672294645832067
3 0.2 0 1768604912325913878L setting R0 to 1.672857576347001 at time = 9.396161237311702
1 0.1 0 1768604912325913878L setting R0 to 1.4595120508977955 at time = 5.672294645832067
0 0.05 0 1768604912325913878L setting R0 to 1.4595120508977955 at time = 5.672294645832067
3 0.2 0 1768604912325913878L setting R0 to 1.4552243930124602 at time = 9.545450999459224
1 0.1 0 1768604912325913878L setting R0 to 1.672857576347001 at time = 9.396161237311702
2 0.15 0 1768604912325913878L setting R0 to 1.672857576347001 at time = 9.396161237311702
0 0.05 0 1768604912325913878L setting R0 to 1.672857576347001 at time = 9.396161237311702
1 0.1 0 1768604912325913878L setting R0 to 1.4552243930124602 at time = 9.545450999459224
2 0.15 0 1768604912325913878L setting R0 to 1.4552243930124602 at time = 9.545450999459224
0 0.05 0 1768604912325913878L setting R0 to 1.4552243930124602 at time = 9.545450999459224
4 0.05 1 2407662077113051075L setting R0 to 1.7124977513361193 at time = 1.878219018807409
4 0.05 1 2407662077113051075L setting R0 to 1.4297609713254456 at time = 2.4215934269433106
4 0.05 1 2407662077113051075L setting R0 to 1.5167619787625548 at time = 5.992476899450338
5 0.1 1 2407662077113051075L setting R0 to 1.7124977513361193 at time = 1.878219018807409
5 0.1 1 2407662077113051075L setting R0 to 1.4297609713254456 at time = 2.4215934269433106
5 0.1 1 2407662077113051075L setting R0 to 1.5167619787625548 at time = 5.992476899450338
6 0.15 1 2407662077113051075L setting R0 to 1.7124977513361193 at time = 1.878219018807409
6 0.15 1 2407662077113051075L setting R0 to 1.4297609713254456 at time = 2.4215934269433106
6 0.15 1 2407662077113051075L setting R0 to 1.5167619787625548 at time = 5.992476899450338
7 0.2 1 2407662077113051075L setting R0 to 1.7124977513361193 at time = 1.878219018807409
7 0.2 1 2407662077113051075L setting R0 to 1.4297609713254456 at time = 2.4215934269433106
7 0.2 1 2407662077113051075L setting R0 to 1.5167619787625548 at time = 5.992476899450338
9 0.1 2 -2698580492431892402L setting R0 to 1.9665140789775497 at time = 4.990978097055602
9 0.1 2 -2698580492431892402L setting R0 to 1.9525439902956225 at time = 6.227836574620975
9 0.1 2 -2698580492431892402L setting R0 to 1.8972135699711736 at time = 7.764180353240558
8 0.05 2 -2698580492431892402L setting R0 to 1.9665140789775497 at time = 4.990978097055602
8 0.05 2 -2698580492431892402L setting R0 to 1.9525439902956225 at time = 6.227836574620975
8 0.05 2 -2698580492431892402L setting R0 to 1.8972135699711736 at time = 7.764180353240558
10 0.15 2 -2698580492431892402L setting R0 to 1.9665140789775497 at time = 4.990978097055602
10 0.15 2 -2698580492431892402L setting R0 to 1.9525439902956225 at time = 6.227836574620975
10 0.15 2 -2698580492431892402L setting R0 to 1.8972135699711736 at time = 7.764180353240558
11 0.2 2 -2698580492431892402L setting R0 to 1.9665140789775497 at time = 4.990978097055602
11 0.2 2 -2698580492431892402L setting R0 to 1.9525439902956225 at time = 6.227836574620975
11 0.2 2 -2698580492431892402L setting R0 to 1.8972135699711736 at time = 7.764180353240558