6  Global Properties Plugin

The global property plugin implements a flexible property system for properties that have global scope. Specifically, global properties have no association with a specific person, place or other instance-based concept.

6.1 Plugin Data Initialization

The plugin is initialized using a GlobalPropertiesPluginData object that collects global property definitions and global property values. Even though the property definitions can contain default property values, the ability to set property values is included to add some flexibility to the collection process since the client model may separate definitions from values in its input files.

6.2 Plugin Behavior

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

6.3 Data Manager

The data manager provides access to the global properties and provides the ability to:

  • Define new global properties (not contained in the initial data)
  • Retrieve global property definitions
  • Retrieve global property ids
  • Retrieve global property values and the times when they were set
  • Set global property values

The data manager also produces observable events when a new global property is defined or when a global property value is assigned. The plugin provides the GlobalPropertyReport that subscribes to these events and produces a trace report of property value assignments.

6.4 Example Code (Lesson 13)

Example_13.java shows a simple usage of the global properties plugin. In it we will add three double valued properties: ALPHA, BETA, and GAMMA. ALPHA and BETA will be used to vary the scenarios in the experiment and GAMMA will be set to a simple function of ALPHA and BETA that will change over time in the simulation. This will culminate in a report that shows each time the global variables are defined or their values are set.

The example includes two plugins:

  • Global properties plugin – (GCM core plugin) used to manage the properties
  • Model plugin – (local plugin) used to introduce a single actor that will alter the value of GAMMA over time

The example’s main method in Code Block 6.1 adds the two plugins:

  • Global properties plugin
    • initialized with the three global properties
    • adds the GlobalPropertyReport
  • Model plugin
    • Uses no inputs, but will add a single instance of the GammaActor class

The main method continues by associating the report to a file via the NIOReportItemHandler. It then forms a dimension for the experiment from variant values of ALPHA and BETA. Finally, it executes the experiment.

Code Block 6.1: Using the global properties plugin to add three global properties.
public static void main(String[] args) throws IOException {
    if (args.length == 0) {
        throw new RuntimeException("One output directory argument is required");
    }
    Path outputDirectory = Paths.get(args[0]);
    if (!Files.exists(outputDirectory)) {
        Files.createDirectory(outputDirectory);
    } else {
        if (!Files.isDirectory(outputDirectory)) {
            throw new IOException("Provided path is not a directory");
        }
    }

    GlobalPropertiesPluginData globalPropertiesPluginData = getGlobalPropertiesPluginData();

    GlobalPropertyReportPluginData globalPropertyReportPluginData = GlobalPropertyReportPluginData.builder()//
            .setReportLabel(ModelReportLabel.GLOBAL_PROPERTY_REPORT)//
            .setDefaultInclusion(true)//
            .build();

    Plugin globalPropertiesPlugin = GlobalPropertiesPlugin.builder()
            .setGlobalPropertiesPluginData(globalPropertiesPluginData)
            .setGlobalPropertyReportPluginData(globalPropertyReportPluginData)//
            .getGlobalPropertiesPlugin();

    Plugin modelPlugin = ModelPlugin.getModelPlugin();

    NIOReportItemHandler nioReportItemHandler = //
            NIOReportItemHandler.builder()//
                    .addReport(ModelReportLabel.GLOBAL_PROPERTY_REPORT, //
                            outputDirectory.resolve("global property report.csv"))//
                    .build();

    Dimension alphaBetaDimension = getAlphaBetaDimension();

    Experiment.builder()//
            .addPlugin(globalPropertiesPlugin)//
            .addPlugin(modelPlugin)//
            .addExperimentContextConsumer(nioReportItemHandler)//
            .addDimension(alphaBetaDimension)//
            .build()//
            .execute();//

}

Initialization of the global properties is shown in Code Block 6.2.

Code Block 6.2: Initializing the global properties plugin data with three property definitions.
private static GlobalPropertiesPluginData getGlobalPropertiesPluginData() {
    GlobalPropertiesPluginData.Builder builder = GlobalPropertiesPluginData.builder();//

    PropertyDefinition propertyDefinition = PropertyDefinition.builder()//
            .setType(Double.class)//
            .setDefaultValue(2.0)//
            .setPropertyValueMutability(false)//
            .build();
    builder.defineGlobalProperty(GlobalProperty.ALPHA, propertyDefinition, 0);

    propertyDefinition = PropertyDefinition.builder()//
            .setType(Double.class)//
            .setDefaultValue(5.0)//
            .setPropertyValueMutability(false)//
            .build();

    builder.defineGlobalProperty(GlobalProperty.BETA, propertyDefinition, 0);

    propertyDefinition = PropertyDefinition.builder()//
            .setType(Double.class)//
            .setDefaultValue(1.0)//
            .setPropertyValueMutability(true)//
            .build();

    builder.defineGlobalProperty(GlobalProperty.GAMMA, propertyDefinition, 0);

    return builder.build();
}

Code Block 6.3 shows the construction of the experiment’s single dimension.

Code Block 6.3: A dimension is created that adds five pairs of values over the ALPHA and BETA global properties.
private static Dimension getAlphaBetaDimension() {
    List<Pair<Double, Double>> alphaBetaPairs = new ArrayList<>();
    alphaBetaPairs.add(new Pair<>(3.0, 10.0));
    alphaBetaPairs.add(new Pair<>(12.0, 25.0));
    alphaBetaPairs.add(new Pair<>(30.0, 40.0));
    alphaBetaPairs.add(new Pair<>(45.0, 70.0));
    alphaBetaPairs.add(new Pair<>(80.0, 100.0));

    FunctionalDimensionData.Builder dimensionDataBuilder = FunctionalDimensionData.builder();

    for (int i = 0; i < alphaBetaPairs.size(); i++) {
        Pair<Double, Double> pair = alphaBetaPairs.get(i);
        dimensionDataBuilder.addValue("Level_" + i, (c) -> {
            List<String> result = new ArrayList<>();
            GlobalPropertiesPluginData.Builder builder = c
                    .getPluginDataBuilder(GlobalPropertiesPluginData.Builder.class);
            builder.setGlobalPropertyValue(GlobalProperty.ALPHA, pair.getFirst(), 0);
            builder.setGlobalPropertyValue(GlobalProperty.BETA, pair.getSecond(), 0);
            result.add(pair.getFirst().toString());
            result.add(pair.getSecond().toString());
            return result;
        });
    }

    dimensionDataBuilder.addMetaDatum(GlobalProperty.ALPHA.toString());
    dimensionDataBuilder.addMetaDatum(GlobalProperty.BETA.toString());

    FunctionalDimensionData functionalDimensionData = dimensionDataBuilder.build();
    return new FunctionalDimension(functionalDimensionData);
}

The GammaActor class in Code Block 6.4 schedules 10 plans, set one day apart, to change the GAMMA value as a successive interpolation between the ALPHA and BETA values that are in turn controlled by the experiment.

Code Block 6.4: The gamma actor sets the value of the GAMMA property over time as a function of the ALPHA and BETA properties.
public final class GammaActor {

    public void init(ActorContext actorContext) {
        int count = 10;
        IntStream.range(0, count).forEach((i) -> {
            actorContext.addPlan((c) -> {
                GlobalPropertiesDataManager globalPropertiesDataManager = c
                        .getDataManager(GlobalPropertiesDataManager.class);
                Double alpha = globalPropertiesDataManager.getGlobalPropertyValue(GlobalProperty.ALPHA);
                Double beta = globalPropertiesDataManager.getGlobalPropertyValue(GlobalProperty.BETA);
                double gamma = (beta - alpha) * i / count + alpha;
                globalPropertiesDataManager.setGlobalPropertyValue(GlobalProperty.GAMMA, gamma);
            }, i + 1);
        });
    }
}

The resultant global properties report shows the correct interpolated values for the five scenarios in Figure 6.1.

Figure 6.1: An excerpt of the global property report showing the three global property values over time in the five scenarios.
scenario ALPHA BETA time property value
0 3.0 10.0 0.0 ALPHA 3.0
0 3.0 10.0 0.0 BETA 10.0
0 3.0 10.0 0.0 GAMMA 1.0
0 3.0 10.0 1.0 GAMMA 3.0
0 3.0 10.0 2.0 GAMMA 3.7
0 3.0 10.0 3.0 GAMMA 4.4
0 3.0 10.0 4.0 GAMMA 5.1
0 3.0 10.0 5.0 GAMMA 5.8
0 3.0 10.0 6.0 GAMMA 6.5
0 3.0 10.0 7.0 GAMMA 7.2
1 12.0 25.0 9.0 GAMMA 22.4
1 12.0 25.0 10.0 GAMMA 23.7
2 30.0 40.0 0.0 ALPHA 30.0
2 30.0 40.0 0.0 BETA 40.0
2 30.0 40.0 0.0 GAMMA 1.0
2 30.0 40.0 1.0 GAMMA 30.0
4 80.0 100.0 7.0 GAMMA 92.0
4 80.0 100.0 8.0 GAMMA 94.0
4 80.0 100.0 9.0 GAMMA 96.0
4 80.0 100.0 10.0 GAMMA 98.0