HIGHLIGHT Simplified iteration of range, classification, partition - openmpp/openmpp.github.io GitHub Wiki
Home > Model Development Topics > Highlight Topic
OpenM++ implements enhancements which can simplify model code which iterates ranges, classifications, or partitions. This was implemented some time ago, when ranges, classifications, and partitions were originally implemented in OpenM++ circa 2015.
The enhancement is not Modgen-compatible, so was of limited interest at the time. But it’s of greater interest now, with Modgen in the rear-view mirror.
The wiki reference subtopic is Iterating enumerations. Here’s a sketch and some examples:
In OpenM++, any range, classification, or partition has a special member function indices()
, which is designed to be used in a C++ “range-based for” statement. Here’s an example from GMM, where RISK_FACTOR
is a classification:
// Verify that SimulateRiskFactor is true if the risk factor is passed to Boadicea in RA_BoadiceaUseRiskFactor.
for (auto j : RISK_FACTOR::indices()) {
if (RA_BoadiceaUseRiskFactor[j] && !SimulateRiskFactor[j]) {
ModelExit("Risk factors passed to Boadicea in RA_BoadiceaUseRiskFactor must be simulated in SimulateRiskFactor");
break; // not reached
}
}
The auto
keyword is not required, one could use int
(or size_t
for the illuminati). It can make sense to use auto
wherever it works, for code simplicity and generality. auto
is a message from the coder to the C++ compiler which says: “You know what I mean, figure it out yourself”.
Here’s another example, where ONCOGENESIS_AGE_GROUP
is a partition, and ONCOGENESIS_LAG
is a range:
for (auto j : ONCOGENESIS_AGE_GROUP::indices()) {
for (auto k : ONCOGENESIS_LAG::indices()) {
double dValue = OncogenesisLags[j][k];
SetTableValue("IM_OncogenesisLags.VALUE", dValue, j, k);
}
}
For ranges, OpenM++ also includes the member function values()
, which iterates the values of the range rather than the indices. Here’s an example where YEAR
is a range:
for (auto year : YEAR::values()) {
if (year == 1970) {
theLog->logMsg("begin peak disco decade");
}
}
A possible OpenM++ enhancement might be a member function for ranges which iterates indices and values as a std::pair
, allowing one to access either inside the same range-based for, something like:
for (auto pr : YEAR::indices_values()) {
auto j = pr.first();
auto year = pr.second();
…
}