5.8. Step 8: The Micro-Simulation Implementation of a Cohort-Component Model

5.8.1. Model Description

This step is a fully functional micro-simulation implementation of a typical cohort-component population projection model. It consolidates all previous steps by adding rich table output and expanding micro-data output.

../_images/Step08_Tables.png

Figure: The complete micro-simulation implementation of a cohort-component model

5.8.2. The Updated Collection of Tables: TablesPopulation.mpp

This module contains demographic output tables of the model. The information of this collection of tables corresponds with the simulation output of typical cohort-component models projecting populations by age, sex and geographical region. It includes projected population numbers, age pyramds at various points in time, and the number of births, deaths, immigrants and emigrants.



////////////////////////////////////////////////////////////////////////////////////////////////////
// Types and States used in tables only
////////////////////////////////////////////////////////////////////////////////////////////////////

classification SEL_YEAR   //EN Selected Year
{
    SY_START,   //EN Start Year
    SY_2025,    //EN 2025
    SY_2050,    //EN 2050
    SY_2075,    //EN 2075
    SY_2100     //EN 2100
};

//EN Age Group
partition TAB_AGE5 { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95 };

//EN Age Group
partition TAB_AGEC5 {1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95};

actor Person
{
    //EN Year
    SIM_YEAR_RANGE sim_year = COERCE(SIM_YEAR_RANGE, calendar_year);

    //EN Selected year
    SEL_YEAR sel_year = ( calendar_year == MIN(SIM_YEAR_RANGE) ) ? SY_START :
                        ( calendar_year == 2025 ) ? SY_2025 :
                        ( calendar_year == 2050 ) ? SY_2050 :
                        ( calendar_year == 2075 ) ? SY_2075 : SY_2100;

    //EN In selected year
    logical in_sel_year = ( calendar_year == MIN(SIM_YEAR_RANGE) || calendar_year == 2025
                        || calendar_year == 2050 || calendar_year == 2075 || calendar_year == 2100);
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Population Tables
////////////////////////////////////////////////////////////////////////////////////////////////////

table_group TG_PopulationTables                     //EN Population
{
    TabTotalPopulation,
    TabPopPyramids,
    TabNumberBirths,
    TabNumberDeaths,
    TabDeathsByAge,
    TabInternalMigrationRate,
    TabNumberImmigrants,
    TabNumberEmigrants,
    TabEmigrationRates
};

table Person TabTotalPopulation                     //EN Total population
[ in_projected_time && is_resident]
{
    sex+ *
    person_type+ *
    {
        duration()                                  //EN Average population in year
    }
    * sim_year
    * district_nat+
};

table Person TabNumberBirths                                            //EN Births
[in_projected_time && person_type == PT_CHILD && is_resident]
{
    sex+ *
    {
        entrances(is_alive, TRUE)                                       //EN Births
    }
    * sim_year
    * district_nat+
};

table Person TabNumberDeaths                        //EN Deaths
[in_projected_time && is_resident]
{
    sex+ *
    {
        transitions(is_alive, TRUE, FALSE)          //EN Deaths
    }
    * sim_year
    * district_nat+
};

table Person TabNumberImmigrants                    //EN Immigrants
[in_projected_time && person_type == PT_IMMIGRANT]
{
    sex+ *
    {
        entrances(is_resident, TRUE)                //EN Immigrants
    }
    * sim_year
    * district_immi+
};

table Person TabPopPyramids                         //EN Population by age
[in_sel_year && is_resident]
{
    sel_year *
    district_nat+ *
    {
        duration()                                  //EN Population
    }
    * split(integer_age, TAB_AGE5)+                 //EN Age Group
    * sex+
};

table Person TabNumberEmigrants                     //EN Emigrants
[in_projected_time]
{
    sex+ *
    {
        entrances(has_emigrated, TRUE)              //EN Number Emigrants
    }
    * sim_year
    * district_nat+
};

table Person TabEmigrationRates                     //EN Emigration rates
[in_projected_time]
{
    sex+ *
    {
        //EN Emigration Rate decimals=4
        entrances(has_emigrated, TRUE)/duration(is_resident, TRUE)
    }
    * split(integer_age, AGE5_PART)+                //EN Age Group
    * district_nat+
};

table Person TabDeathsByAge                                 //EN Mortality by age
[in_projected_time && is_resident]
{   sex+ *
    {
        transitions(is_alive, TRUE, FALSE),                 //EN Deaths
        transitions(is_alive, TRUE, FALSE) / duration()     //EN Mortality Rate decimals=4
    }
    * split(integer_age, TAB_AGEC5)                         //EN Age group
    * sim_year                                              //EN Calendar Year
};

table Person TabInternalMigrationRate                       //EN Internal out migration rate
[ in_projected_time  && is_resident ]
{
    sex + *
    {
        number_migrations / duration()                      //EN Migration rate decimals=4
    }
    * split(integer_age, AGE5_PART)                         //EN Age group
    * district_nat +
};

5.8.3. Adding Districts in MicroDataOutput.mpp

The state district_nat is added to the list of output variables and the header row of micro-data output.


void Person::WriteMicroRecord()
{
    // Only output data if current resident
    if (is_resident)
    {

        // Push the fields into the output record.

        // ==============================================================
        // When adding additional variables, this list has to be extended
        // ==============================================================
        out_csv << actor_id;            // Actor ID
        out_csv << actor_weight;        // Weight
        out_csv << time;                // Time
        out_csv << time_of_birth;       // Time of birth
        out_csv << ( int )sex;          // Sex
        out_csv << (int)district_int;   // District of residence

        out_csv.write_record();         // All fields have been pushed, now write the record.

    }

    // set next output
    if (time_microdata_output + TimeMicroOutput[OT_INTERVAL] > time &&
        time_microdata_output + TimeMicroOutput[OT_INTERVAL] <= TimeMicroOutput[OT_LAST])
    {
        time_microdata_output = time_microdata_output + TimeMicroOutput[OT_INTERVAL];
    }
    else
    {
        time_microdata_output = TIME_INFINITE;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Pre- and Post-Simulation
////////////////////////////////////////////////////////////////////////////////////////////////////

void PreSimulation()
{
    // In the pre-simulation phase of MicroDataOutput.mpp module, the micro-data file is prepared
    // for writing records in the simulation. If the user selects micro-data output, a file is
    // opened and the header row is written containing all selected states

    if (WriteMicrodata)
        {
        // ==============================================================
        // When adding additional variables, this list has to be extended
        // ==============================================================
        std_string  myString = "ID,";            // Actor ID
        myString  = myString + "WEIGHT,";        // Weight
        myString  = myString + "TIME,";          // Output Time
        myString  = myString + "BIRTH,";         // Time of birth
        myString  = myString + "MALE,";          // Sex
        myString  = myString + "DISTRICT,";      // District

        out_csv.open(MicroRecordFileName);
                out_csv.write_header(myString);
        }
}