public static void main(String[] args) throws IOException {
if (args.length == 0) {
throw new RuntimeException("One output directory argument is required");
}
= Paths.get(args[0]);
Path outputDirectory if (!Files.exists(outputDirectory)) {
.createDirectory(outputDirectory);
Files} else {
if (!Files.isDirectory(outputDirectory)) {
throw new IOException("Provided path is not a directory");
}
}
new Example_15(outputDirectory).execute();
}
8 Regions Plugin
The regions plugin manages the assignment of people to regions. As such, it is dependent on the people plugin. A region does not have an associated geo-location and does not specifically designate a county, state or any other regional concept. The interpretation of what defines a region is left to the modeler, although it will usually represent some sort of contiguous land area. When the regions plugin is being used, each person has a region association at all times and regions can be associated with zero to many people. Regions may also have a set of associated property values that can be dynamically defined. Regions are identified via the RegionId marker interface that does not define any methods. It is left to the modeler to implement a RegionId data type. When the number of regions is fixed and relatively small this can be accomplished via an enumeration. For larger or dynamic sets of region id values it is typical to implement a simple immutable class that wraps an integer.
8.1 Plugin Data Initialization
The plugin is initialized using a RegionsPluginData object that collects person to region assignments and region property values.
8.2 Plugin Behavior
The plugin adds a single data manager to the simulation as an instance of the RegionsDataManager that is initialized with the RegionsPluginData.
8.3 Data Manager
The data manager controls regions, their properties and the assignment of people to those regions. The data manager provides public methods that:
- Add a region
- Define a region property
- Set a region property value
- Move a person from one region to another
- Answer various questions about:
- Person membership in regions
- Region property values
The data manager also produces observable events:
- PersonRegionUpdateEvent – when a person is moved from one region to another
- RegionAdditionEvent – when a region is added to the simulation
- RegionPropertyDefintionEvent – when a new region property is defined
- RegionPropertyUpdateEvent – when a region property value is assigned
8.4 Example Code (Lesson 15)
Example_15.java shows the use of the regions plugin. In it we will examine
- The initialization of the regions plugin
- The movement of people between regions
- The dynamic addition of regions
- The dynamic addition of region properties
- The update of region property values
The example includes five plugins:
- Regions Plugin– (GCM core plugin) used to manage regions, their properties and person membership in regions
- People plugin – (GCM core plugin) used to manage people
- Stochastics plugin – (GCM core plugin) used to generate random numbers used in various decisions
- Model plugin – (local plugin) used to introduce three actors that will:
- Move people between regions
- Create new regions
- Vaccinate people, reacting to changes in region properties
- Vaccine plugin – (local plugin) used to track vaccinations for each person
The example’s main method starts in Code Block 8.1 by creating an instance of the example class rather than building the experiment directly since this example is somewhat more complex than previous examples.
The execution method first gathers together the five plugins in Code Block 8.2:
private void execute() {
/*
* Create person ids and region ids that are shared across the plugins
*/
initializePeopleAndRegions();
/*
* Create the reports
*/
= getNIOReportItemHandler();
NIOReportItemHandler nioReportItemHandler
/*
* Create the people plugin filled with 1000 people
*/
= getPeoplePlugin();
Plugin peoplePlugin
/*
* Create the region plugin 5 regions, each having a lat and lon and assign the
* people to random regions.
*
*/
= getRegionsPlugin();
Plugin regionsPlugin
/*
* create the stochastics plugin and build a dimension with 5 seed values
*/
= getStochasticsPlugin();
Plugin stochasticsPlugin Dimension stochasticsDimension = getStochasticsDimension(5, randomGenerator.nextLong());
/*
* Create the vaccine and model plugins
*/
= VaccinePlugin.getVaccinePlugin();
Plugin vaccinePlugin
= ModelPlugin.getModelPlugin(); Plugin modelPlugin
The first action is to create 1000 people and 5 regions that will be used in the creation of both the people plugin and the regions plugin.
private void initializePeopleAndRegions() {
for (int i = 0; i < 1000; i++) {
.add(new PersonId(i));
initialPeople}
for (int i = 0; i < 5; i++) {
.add(new Region(i));
initialRegions}
}
The regions plugin defines a region id with a marker interface. Marker interfaces are used to differentiate arguments and reduce variable type ambiguities while not imposing any particular implementation on the modeler. Region ids might reasonably be implemented as integer based identifiers or as strings that represent place names. In this example we will implement the region ids with an integer based class, the Region (Code Block 8.4), which is a boiler-plate wrapper around an int id value.
public final class Region implements RegionId {
private final int id;
/**
* Constructs the region
*
* @throws ContractException
* <li>{@linkplain ModelError#NEGATIVE_REGION_ID}</li>
*/
public Region(int id) {
if (id < 0) {
throw new ContractException(ModelError.NEGATIVE_REGION_ID);
}
this.id = id;
}
public int getValue() {
return id;
}
@Override
public int hashCode() {
return id;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Region)) {
return false;
}
Region other = (Region) obj;
if (id != other.id) {
return false;
}
return true;
}
@Override
public String toString() {
return "Region_" + id;
}
}
The example contains three reports in Code Block 8.5:
- RegionPropertyReport - shows changes to region property values
- RegionTransferReport - shows movements of people between regions
- VaccinationReport - shows vaccinations of people
private NIOReportItemHandler getNIOReportItemHandler() {
return NIOReportItemHandler.builder()//
.addReport(ModelReportLabel.REGION_PROPERTY_REPORT, //
.resolve("region_property_report.csv"))//
outputDirectory.addReport(ModelReportLabel.REGION_TRANSFER_REPORT, //
.resolve("region_transfer_report.csv"))//
outputDirectory.addReport(ModelReportLabel.VACCINATION, //
.resolve("vaccine_report.csv"))//
outputDirectory.build();
}
The people plugin, Code Block 8.6, is built from the 1000 people created earlier.
private Plugin getPeoplePlugin() {
.Builder peoplePluginDataBuilder = PeoplePluginData.builder();
PeoplePluginDatafor (PersonId personId : initialPeople) {
.addPersonRange(new PersonRange(personId.getValue(), personId.getValue()));
peoplePluginDataBuilder}
= peoplePluginDataBuilder.build();
PeoplePluginData peoplePluginData return PeoplePlugin.getPeoplePlugin(peoplePluginData);
}
Creating the regions plugin Code Block 8.7 is a bit more involved. First, the five regions created before are added to the plugin. Since the plugin requires that every person always have a region assignment, we assign a randomly selected region to each person. We define the LAT and LON properties to give the regions a geographic location. Notice that the definitions do not have default values since it does not make sense to say a region has a default position. This then will require that we assign specific latitude and longitude values for each region. Later on we will examine adding a new region property definition dynamically as the simulation is running.
private Plugin getRegionsPlugin() {
// create the region plugin with an initial five regions, each region
// having 200 people
.Builder regionsPluginDataBuilder = RegionsPluginData.builder();
RegionsPluginDatafor (Region region : initialRegions) {
.addRegion(region);
regionsPluginDataBuilder}
for (PersonId personId : initialPeople) {
Region region = initialRegions.get(randomGenerator.nextInt(initialRegions.size()));
.addPerson(personId, region);
regionsPluginDataBuilder}
= PropertyDefinition.builder()//
PropertyDefinition propertyDefinition .setType(Double.class)//
.setPropertyValueMutability(false)//
.build();
.defineRegionProperty(RegionProperty.LAT, propertyDefinition);
regionsPluginDataBuilder.defineRegionProperty(RegionProperty.LON, propertyDefinition);
regionsPluginDataBuilder
for (Region region : initialRegions) {
.setRegionPropertyValue(region, RegionProperty.LAT,
regionsPluginDataBuilder.nextDouble() + 45.0);
randomGenerator.setRegionPropertyValue(region, RegionProperty.LON,
regionsPluginDataBuilder.nextDouble() + 128.0);
randomGenerator}
= regionsPluginDataBuilder.build();
RegionsPluginData regionsPluginData
= //
RegionPropertyReportPluginData regionPropertyReportPluginData .builder()//
RegionPropertyReportPluginData.setReportLabel(ModelReportLabel.REGION_PROPERTY_REPORT)//
.build();
= RegionTransferReportPluginData.builder()//
RegionTransferReportPluginData regionTransferReportPluginData .setReportLabel(ModelReportLabel.REGION_TRANSFER_REPORT)//
.setReportPeriod(ReportPeriod.END_OF_SIMULATION)//
.build();//
return RegionsPlugin.builder()//
.setRegionsPluginData(regionsPluginData)//
.setRegionPropertyReportPluginData(regionPropertyReportPluginData)//
.setRegionTransferReportPluginData(regionTransferReportPluginData)//
.getRegionsPlugin();
}
Adding the stochastics plugin with a corresponding dimension that will create five scenarios proceeds in the usual way in Code Block 8.8:
private Plugin getStochasticsPlugin() {
= WellState.builder().setSeed(randomGenerator.nextLong()).build();
WellState wellState = StochasticsPluginData.builder()//
StochasticsPluginData stochasticsPluginData .setMainRNGState(wellState).build();
return StochasticsPlugin.getStochasticsPlugin(stochasticsPluginData);
}
private Dimension getStochasticsDimension(int replicationCount, long seed) {
.Builder builder = FunctionalDimensionData.builder();//
FunctionalDimensionData
= RandomGeneratorProvider.getRandomGenerator(seed);
RandomGenerator randomGenerator
List<Long> seedValues = new ArrayList<>();
for (int i = 0; i < replicationCount; i++) {
.add(randomGenerator.nextLong());
seedValues}
.range(0, seedValues.size()).forEach((i) -> {
IntStream.addValue("Level_" + i, (context) -> {
builder.Builder stochasticsPluginDataBuilder = context
StochasticsPluginData.getPluginDataBuilder(StochasticsPluginData.Builder.class);
long seedValue = seedValues.get(i);
= WellState.builder().setSeed(seedValue).build();
WellState wellState .setMainRNGState(wellState);
stochasticsPluginDataBuilder
ArrayList<String> result = new ArrayList<>();
.add(Integer.toString(i));
result.add(Long.toString(seedValue) + "L");
result
return result;
});//
});
.addMetaDatum("seed index");//
builder.addMetaDatum("seed value");//
builder
= builder.build();
FunctionalDimensionData functionalDimensionData return new FunctionalDimension(functionalDimensionData);
}
Finally, we add the vaccine and model plugins. This will add the vaccine data manager as well as three previously mentioned actors that will be used to demonstrate the various capabilities of the regions plugin.
- PersonMover – used to move people between regions
- RegionCreator – used to create new regions during the simulation run
- Vaccinator – used to vaccinate people, reacting to changes in region properties
The execute method finishes (Code Block 8.9) by constructing and executing the experiment:
.builder()//
Experiment.addPlugin(modelPlugin)//
.addPlugin(regionsPlugin)//
.addPlugin(peoplePlugin)//
.addPlugin(stochasticsPlugin)//
.addPlugin(vaccinePlugin)//
.addExperimentContextConsumer(nioReportItemHandler)//
.addDimension(stochasticsDimension)//
.build()//
.execute();//
8.5 The actors
We will finish this chapter by reviewing the three actors of the model plugin and then examine the three reports.
The PersonMover actor, in Code Block 8.10 and Code Block 8.11, schedules 1000 random moves of a person from one region to another over the course of 100 days.
public void init(ActorContext actorContext) {
for (int i = 0; i < 1000; i++) {
double planTime = ((double) i) * 0.1;
.addPlan(this::moveRandomPerson, planTime);
actorContext}
}
Moving the person requires that we use the stochastics plugin and the people plugin to select a random person. We next use the regions plugin to first select a random new region for the person and then move the person to that region.
private void moveRandomPerson(ActorContext actorContext) {
= actorContext.getDataManager(StochasticsDataManager.class);
StochasticsDataManager stochasticsDataManager = stochasticsDataManager.getRandomGenerator();
RandomGenerator randomGenerator = actorContext.getDataManager(PeopleDataManager.class);
PeopleDataManager peopleDataManager = actorContext.getDataManager(RegionsDataManager.class);
RegionsDataManager regionsDataManager
// pick a random person
List<PersonId> people = peopleDataManager.getPeople();
if (people.isEmpty()) {
return;
}
= people.get(randomGenerator.nextInt(people.size()));
PersonId personId
// pick a new random new region for that person
List<RegionId> regionIds = new ArrayList<>(regionsDataManager.getRegionIds());
= regionsDataManager.getPersonRegion(personId);
RegionId personRegion .remove(personRegion);
regionIdsif (regionIds.isEmpty()) {
return;
}
= regionIds.get(randomGenerator.nextInt(regionIds.size()));
RegionId newPersonRegion
// assign the region to the person
.setPersonRegion(personId, newPersonRegion);
regionsDataManager}
The RegionCreator actor, in Code Block 8.12 and Code Block 8.13, follows a similar pattern, scheduling the creation of five new regions over 101 days.
public void init(ActorContext actorContext) {
for (int i = 0; i < 5; i++) {
double planTime = 20 * i + 1;
.addPlan(this::addRegion, planTime);
actorContext}
}
When adding a region, we have to be aware that the region will have LAT and LON properties and that these properties were not defined with default values. Thus we must supply values for the region’s latitude and longitude as part of the RegionConstructionData object that is passed to the regions data manager. We will similarly assign a new random Boolean value for the VACCINE_PRIORITY property. The VACCINE_PRIORITY is a dynamically added property that is introduced later. Note that we first check for the existence of the property and only then set a value since setting such a value before the property is defined will result in a runtime exception.
Such considerations are unusual since properties are usually defined in the plugin initialization data or added very early in the simulation before any actors have initialized. We do so here for the purposes of demonstrating dynamic property definitions.
private void addRegion(ActorContext actorContext) {
= actorContext.getDataManager(RegionsDataManager.class);
RegionsDataManager regionsDataManager = actorContext.getDataManager(StochasticsDataManager.class);
StochasticsDataManager stochasticsDataManager = stochasticsDataManager.getRandomGenerator();
RandomGenerator randomGenerator
Set<Region> regions = regionsDataManager.getRegionIds();
int maxRegionValue = -1;
for (Region region : regions) {
int value = region.getValue();
= FastMath.max(value, maxRegionValue);
maxRegionValue }
Region newRegion = new Region(maxRegionValue + 1);
= RegionConstructionData.builder().setRegionId(newRegion);
Builder regionBuilder .setRegionPropertyValue(RegionProperty.LAT, 35 + randomGenerator.nextDouble());
regionBuilder.setRegionPropertyValue(RegionProperty.LON, 128 + randomGenerator.nextDouble());
regionBuilder
if (regionsDataManager.regionPropertyIdExists(RegionProperty.VACCINE_PRIORITY)) {
.setRegionPropertyValue(RegionProperty.VACCINE_PRIORITY, randomGenerator.nextBoolean());
regionBuilder}
= regionBuilder.build();
RegionConstructionData regionConstructionData .addRegion(regionConstructionData);
regionsDataManager}
The Vaccinator actor is somewhat more complicated than the other actors. It initializes (Code Block 8.14) by storing references to various data managers for convenience and then plans 5000 vaccinations spread over 100 days. It also plans to add the VACCINE_PRIORITY property on day 50.
public void init(ActorContext actorContext) {
= actorContext.getDataManager(StochasticsDataManager.class);
StochasticsDataManager stochasticsDataManager = stochasticsDataManager.getRandomGenerator();
randomGenerator = actorContext.getDataManager(RegionsDataManager.class);
regionsDataManager = actorContext.getDataManager(VaccinationDataManager.class);
vaccinationDataManager
double planTime = randomGenerator.nextDouble();
for (int i = 0; i < 5000; i++) {
.addPlan(this::vaccinateRandomPerson, planTime);
actorContext+= randomGenerator.nextDouble() * 0.02;
planTime }
.addPlan(this::addVaccinePriorityPropertyToRegions, 50);
actorContext}
Let’s first look at the addition of the new region property on day 50 in Code Block 8.15. The new property is a Boolean value defaulted to false and indicates whether people should be chosen from regions randomly or by preferring people with the fewest vaccinations. Since the property has a default value, we do not have to set values for each region in the RegionPropertyDefinitionInitialization object that is passed to the regions data manager when creating the region. We do so anyway to demonstrate such value assignments. Once the new property is in place, the Vaccinator schedules the switching of the value for random regions once per day for the next 50 days.
private void addVaccinePriorityPropertyToRegions(ActorContext actorContext) {
= //
PropertyDefinition propertyDefinition .builder()//
PropertyDefinition.setType(Boolean.class)//
.setDefaultValue(false)//
.build();
.Builder defBuilder = RegionPropertyDefinitionInitialization.builder()//
RegionPropertyDefinitionInitialization.setPropertyDefinition(propertyDefinition)//
.setRegionPropertyId(RegionProperty.VACCINE_PRIORITY);
for (RegionId regionId : regionsDataManager.getRegionIds()) {
.addPropertyValue(regionId, randomGenerator.nextBoolean());
defBuilder}
= defBuilder.build();
RegionPropertyDefinitionInitialization regionPropertyDefinitionInitialization .defineRegionProperty(regionPropertyDefinitionInitialization);
regionsDataManager
for (int i = 0; i < 50; i++) {
double planTime = actorContext.getTime() + i;
.addPlan(this::alterVaccinePriorityPropertyOnRandomRegion, planTime);
actorContext}
}
In Code Block 8.16 the Vaccinator performs this value switching:
private void alterVaccinePriorityPropertyOnRandomRegion(ActorContext actorContext) {
List<RegionId> regionids = new ArrayList<>(regionsDataManager.getRegionIds());
if (regionids.isEmpty()) {
return;
}
= regionids.get(randomGenerator.nextInt(regionids.size()));
RegionId regionId Boolean vaccinePriority = regionsDataManager.getRegionPropertyValue(regionId, RegionProperty.VACCINE_PRIORITY);
.setRegionPropertyValue(regionId, RegionProperty.VACCINE_PRIORITY, !vaccinePriority);
regionsDataManager}
The Vaccinator vaccinates people at random (Code Block 8.17) by first selecting a random region and then selecting a random person in that region. The selection of the person is subject to the presence of the VACCINE_PRIORITY property and whether the value of the property is true for the selected region. If the priority selection is being used, then a first pass through the people in the region establishes the lowest number of vaccines received by any person. A second pass through the same people now selects only those having this number of vaccinations. Finally, a person is selected at random from the eligible people.
private void vaccinateRandomPerson(ActorContext actorContext) {
List<RegionId> regionIds = new ArrayList<>(regionsDataManager.getRegionIds());
if (regionIds.isEmpty()) {
return;
}
= regionIds.get(randomGenerator.nextInt(regionIds.size()));
RegionId regionId List<PersonId> peopleInRegion = regionsDataManager.getPeopleInRegion(regionId);
Boolean prioritizePeople = false;
boolean vaccinePriorityPropertyExists = regionsDataManager
.regionPropertyIdExists(RegionProperty.VACCINE_PRIORITY);
if (vaccinePriorityPropertyExists) {
= regionsDataManager.getRegionPropertyValue(regionId, RegionProperty.VACCINE_PRIORITY);
prioritizePeople }
= null;
PersonId selectedPersonId if (prioritizePeople) {
int minVaccinationCount = Integer.MAX_VALUE;
for (PersonId personId : peopleInRegion) {
int personVaccinationCount = vaccinationDataManager.getPersonVaccinationCount(personId);
if (personVaccinationCount < minVaccinationCount) {
= personVaccinationCount;
minVaccinationCount }
}
List<PersonId> eligiblePeople = new ArrayList<>();
for (PersonId personId : peopleInRegion) {
int personVaccinationCount = vaccinationDataManager.getPersonVaccinationCount(personId);
if (personVaccinationCount == minVaccinationCount) {
.add(personId);
eligiblePeople}
}
if (!eligiblePeople.isEmpty()) {
= eligiblePeople.get(randomGenerator.nextInt(eligiblePeople.size()));
selectedPersonId }
} else {
if (!peopleInRegion.isEmpty()) {
= peopleInRegion.get(randomGenerator.nextInt(peopleInRegion.size()));
selectedPersonId }
}
if (selectedPersonId != null) {
.vaccinatePerson(selectedPersonId);
vaccinationDataManager}
}
8.6 Inspecting the output
The region transfer report shows the number of transfers of a person from one region to another across all days in the simulation. The rows where the source and destination regions are the same represent the addition of people at the start of the simulation and, as expected, the sum of such transfers equals to 1000. We also expect to see regions that were added beyond the original five regions and that transfers in and out of those regions should be reduced compared to the original regions since they start out with no people and come into the simulation only after day 50.
scenario | seed_index | seed_value | source_region | destination_region | transfers |
---|---|---|---|---|---|
0 | 0 | -7834265884293137617L | Region_2 | Region_2 | 215 |
0 | 0 | -7834265884293137617L | Region_0 | Region_0 | 188 |
0 | 0 | -7834265884293137617L | Region_3 | Region_3 | 208 |
0 | 0 | -7834265884293137617L | Region_4 | Region_4 | 215 |
0 | 0 | -7834265884293137617L | Region_1 | Region_1 | 174 |
0 | 0 | -7834265884293137617L | Region_4 | Region_3 | 26 |
0 | 0 | -7834265884293137617L | Region_4 | Region_0 | 36 |
0 | 0 | -7834265884293137617L | Region_3 | Region_4 | 24 |
… | |||||
1 | 1 | -7320358285742045393L | Region_2 | Region_2 | 215 |
1 | 1 | -7320358285742045393L | Region_0 | Region_0 | 188 |
1 | 1 | -7320358285742045393L | Region_3 | Region_3 | 208 |
1 | 1 | -7320358285742045393L | Region_4 | Region_4 | 215 |
1 | 1 | -7320358285742045393L | Region_1 | Region_1 | 174 |
… | |||||
2 | 2 | -4619948863677044400L | Region_3 | Region_0 | 26 |
2 | 2 | -4619948863677044400L | Region_3 | Region_1 | 33 |
2 | 2 | -4619948863677044400L | Region_0 | Region_4 | 22 |
2 | 2 | -4619948863677044400L | Region_1 | Region_4 | 29 |
2 | 2 | -4619948863677044400L | Region_4 | Region_0 | 32 |
… | |||||
4 | 4 | -7584580254621783722L | Region_8 | Region_4 | 1 |
4 | 4 | -7584580254621783722L | Region_9 | Region_1 | 1 |
4 | 4 | -7584580254621783722L | Region_9 | Region_0 | 2 |
4 | 4 | -7584580254621783722L | Region_9 | Region_6 | 2 |
In the region property report (Figure 8.2) we see that the LAT and LON properties were set for the first five regions at the start of the simulation. Starting on day 1, new regions were added and each has an assigned LAT and LON value at that time. Beginning on day 50, all regions are assigned a VACCINE_PRIOITY value and assignments to that property continue daily for random regions.
scenario | seed_index | seed_value | time | region | property | value |
---|---|---|---|---|---|---|
0 | 0 | -7834265884293137617L | 0.0 | Region_0 | LAT | 45.08307901948476 |
0 | 0 | -7834265884293137617L | 0.0 | Region_0 | LON | 128.5497267736204 |
0 | 0 | -7834265884293137617L | 0.0 | Region_1 | LAT | 45.73317078392115 |
0 | 0 | -7834265884293137617L | 0.0 | Region_1 | LON | 128.98292164396958 |
0 | 0 | -7834265884293137617L | 0.0 | Region_2 | LAT | 45.74702447122078 |
0 | 0 | -7834265884293137617L | 0.0 | Region_2 | LON | 128.5118606592755 |
0 | 0 | -7834265884293137617L | 0.0 | Region_3 | LAT | 45.8303102139607 |
0 | 0 | -7834265884293137617L | 0.0 | Region_3 | LON | 128.55192626408567 |
0 | 0 | -7834265884293137617L | 0.0 | Region_4 | LAT | 45.59334365958997 |
0 | 0 | -7834265884293137617L | 0.0 | Region_4 | LON | 128.7915941303198 |
0 | 0 | -7834265884293137617L | 1.0 | Region_5 | LAT | 35.99754757587744 |
0 | 0 | -7834265884293137617L | 1.0 | Region_5 | LON | 128.2594279657217 |
0 | 0 | -7834265884293137617L | 21.0 | Region_6 | LAT | 35.84682720256188 |
0 | 0 | -7834265884293137617L | 21.0 | Region_6 | LON | 128.2211833000355 |
0 | 0 | -7834265884293137617L | 41.0 | Region_7 | LAT | 35.07267582475035 |
0 | 0 | -7834265884293137617L | 41.0 | Region_7 | LON | 128.37457313813837 |
0 | 0 | -7834265884293137617L | 50.0 | Region_0 | VACCINE_PRIORITY | false |
0 | 0 | -7834265884293137617L | 50.0 | Region_1 | VACCINE_PRIORITY | false |
… | ||||||
4 | 4 | -7584580254621783722L | 93.0 | Region_2 | VACCINE_PRIORITY | false |
4 | 4 | -7584580254621783722L | 94.0 | Region_1 | VACCINE_PRIORITY | true |
4 | 4 | -7584580254621783722L | 95.0 | Region_2 | VACCINE_PRIORITY | true |
4 | 4 | -7584580254621783722L | 96.0 | Region_7 | VACCINE_PRIORITY | true |
4 | 4 | -7584580254621783722L | 97.0 | Region_0 | VACCINE_PRIORITY | false |
4 | 4 | -7584580254621783722L | 98.0 | Region_1 | VACCINE_PRIORITY | false |
4 | 4 | -7584580254621783722L | 99.0 | Region_0 | VACCINE_PRIORITY | true |
Finally, the vaccine report shows the number of people having various vaccine counts at the end of each simulation. Although the priority policy was being used, most vaccinations were for randomly selected people so we expect a fairly wide distribution in those values.
scenario | seed_index | seed_value | count_0 | count_1 | count_2 | count_3 | count_4 | count_5 | count_6+ |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | -7834265884293137617L | 13 | 67 | 145 | 168 | 170 | 148 | 289 |
1 | 1 | -7320358285742045393L | 13 | 63 | 141 | 181 | 187 | 133 | 282 |
2 | 2 | -4619948863677044400L | 17 | 53 | 157 | 196 | 176 | 140 | 261 |
3 | 3 | 3282202756261196294L | 10 | 72 | 159 | 166 | 163 | 146 | 284 |
4 | 4 | -7584580254621783722L | 4 | 66 | 153 | 198 | 163 | 136 | 280 |