Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified input/DatabaseCountryYear.xlsx
Binary file not shown.
76 changes: 76 additions & 0 deletions src/main/java/simpaths/model/InSchoolAlignment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package simpaths.model;

import microsim.engine.SimulationEngine;
import simpaths.data.IEvaluation;
import simpaths.data.Parameters;
import simpaths.model.enums.Les_c4;
import simpaths.model.enums.TargetShares;

import java.util.Set;


/**
* InSchoolAlignment adjusts the probability of being a student.
* The object is designed to assist modification of the intercept of the "inSchool" models.
*
* A search routine is used to find the value by which the intercept should be adjusted.
* If the projected share of students in the population differs from the desired target by more than a specified threshold,
* then the intercept is adjusted and the share re-evaluated.
*
* Importantly, the adjustment needs to be only found once. Modified intercepts can then be used in subsequent simulations.
*/
public class InSchoolAlignment implements IEvaluation {

private double targetStudentShare;
private Set<Person> persons;
private SimPathsModel model;


// CONSTRUCTOR
public InSchoolAlignment(Set<Person> persons) {
this.model = (SimPathsModel) SimulationEngine.getInstance().getManager(SimPathsModel.class.getCanonicalName());
this.persons = persons;
targetStudentShare = Parameters.getTargetShare(model.getYear(), TargetShares.Students);
}


/**
* Evaluates the discrepancy between the simulated and target total student share and adjusts probabilities if necessary.
*
* This method focuses on the influence of the adjustment parameter 'args[0]' on the difference between the target and
* simulated student share (error).
*
* The error value is returned and serves as the stopping condition in root search routines.
*
* @param args An array of parameters, where args[0] represents the adjustment parameter.
* @return The error in the target aggregate share of students after potential adjustments.
*/
@Override
public double evaluate(double[] args) {

persons.parallelStream()
.forEach(person -> person.inSchool(args[0]));

return targetStudentShare - evalStudentShare();
}


/**
* Evaluates the aggregate share of students.
*
* This method uses Java streams to count the number of students over the total number of individuals.
*
* @return The aggregate share of partnered persons among those eligible, or 0.0 if no eligible persons are found.
*/
private double evalStudentShare() {

long numStudents = model.getPersons().stream()
.filter(person -> (!person.isToLeaveSchool() && !Les_c4.EmployedOrSelfEmployed.equals(person.getLes_c4()) && !Les_c4.NotEmployed.equals(person.getLes_c4()) && !Les_c4.Retired.equals(person.getLes_c4()))) // count number of students who are not supposed to leave school
.count();
long numPeople = model.getPersons().stream()
.filter(person -> person.getLes_c4() != null)
.count();

return (numStudents > 0) ? (double) numStudents / numPeople : 0.0;
}
}
199 changes: 159 additions & 40 deletions src/main/java/simpaths/model/Person.java

Large diffs are not rendered by default.

62 changes: 9 additions & 53 deletions src/main/java/simpaths/model/SimPathsModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -2108,60 +2108,14 @@ public void resample(Person person) {
*/
private void inSchoolAlignment() {

int numStudents = 0;
int num16to29 = 0;
ArrayList<Person> personsLeavingSchool = new ArrayList<Person>();
for (Person person : persons) {
if (person.getDemAge() > 15 && person.getDemAge() < 30) { //Could introduce separate alignment for different age groups, but this is more flexible as it depends on the regression process within the larger alignment target
num16to29++;
if (person.getLes_c4().equals(Les_c4.Student)) {
numStudents++;
}
if (person.isToLeaveSchool()) { //Only those who leave school for the first time have toLeaveSchool set to true
personsLeavingSchool.add(person);
}
}
}

int targetNumberOfPeopleLeavingSchool = numStudents - (int)( (double)num16to29 * ((Number) Parameters.getStudentShareProjections().getValue(country.toString(), year)).doubleValue() );
InSchoolAlignment inSchoolAlignment = new InSchoolAlignment(persons);
double inSchoolAdjustment = Parameters.getTimeSeriesValue(getYear(), TimeSeriesVariable.InSchoolAdjustment);
RootSearch search = getRootSearch(inSchoolAdjustment, inSchoolAlignment, 1.0E-2, 1.0E-2, 4); // epsOrdinates and epsFunction determine the stopping condition for the search. For inSchoolAlignment error term is the difference between target and observed share of partnered individuals.

System.out.println("Number of students < 30 is " + numStudents + " Persons set to leave school " + personsLeavingSchool.size() + " Number of people below 30 " + num16to29
+ " Target number of people leaving school " + targetNumberOfPeopleLeavingSchool);

if (targetNumberOfPeopleLeavingSchool <= 0) {
for(Person person : personsLeavingSchool) {
person.setToLeaveSchool(false); //Best case scenario is to prevent anyone from leaving school in this year as the target share of students is higher than the number of students. Although we cannot match the target, this is the nearest we can get to it.
if(Parameters.systemOut) {
System.out.println("target number of school leavers is not positive. Force all school leavers to stay at school.");
}
}
} else if (targetNumberOfPeopleLeavingSchool < personsLeavingSchool.size()) {
if(Parameters.systemOut) {
System.out.println("Schooling alignment: target number of students is " + targetNumberOfPeopleLeavingSchool);
}
new ResamplingAlignment<Person>().align(
personsLeavingSchool,
null,
new AlignmentOutcomeClosure<Person>() {
@Override
public boolean getOutcome(Person agent) {
return agent.isToLeaveSchool();
}

@Override
public void resample(Person agent) {
agent.setToLeaveSchool(false);
}
},
targetNumberOfPeopleLeavingSchool);

int numPostAlign = 0;
for(Person person : persons) {
if(person.isToLeaveSchool()) {
numPostAlign++;
}
}
System.out.println("Schooling alignment: aligned number of students is " + numPostAlign);
// update and exit
if (search.isTargetAltered()) {
Parameters.putTimeSeriesValue(getYear(), search.getTarget()[0], TimeSeriesVariable.InSchoolAdjustment); // If adjustment is altered from the initial value, update the map
System.out.println("InSchool adjustment value was " + search.getTarget()[0]);
}
}

Expand Down Expand Up @@ -3077,6 +3031,8 @@ public void setAlignInSchool(boolean flag) {
alignInSchool = flag;
}

public boolean isAlignInSchool() { return alignInSchool; }

public void setYear(int year) {
this.year = year;
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/simpaths/model/enums/TargetShares.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

public enum TargetShares {
Partnership,
Retirement,
Disability,
Students,
EmploymentSingleMales,
EmploymentSingleFemales,
EmploymentCouples;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/simpaths/model/enums/TimeSeriesVariable.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ public enum TimeSeriesVariable {
UtilityAdjustmentSingleMales,
UtilityAdjustmentSingleFemales,
UtilityAdjustmentCouples,
InSchoolAdjustment,
WageGrowth,
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
run,time,id_EmploymentStatistics1,labEmpShare,labEmpToNotEmpShare,labNotEmpToEmpShare,labUnempShare
1,2019.0,1,0.7375197275521223,0.04822544511260465,0.4428874734607219,0.12592408007309577
1,2020.0,1,0.7638024076380241,0.013328890369876709,0.26879699248120303,0.10585305105853052
1,2021.0,1,0.7744079767345243,0.013477377259599957,0.20364741641337386,0.09729954299958454
1,2022.0,1,0.7832958988436902,0.016548961737113944,0.19237147595356552,0.09458447716496132
1,2020.0,1,0.6523038605230386,0.01010774186382317,0.23182957393483708,0.08684101286841013
1,2021.0,1,0.7274615704196095,0.010578638796839153,0.2099712368168744,0.09488990444536768
1,2022.0,1,0.680891772731054,0.011519716437749225,0.1648,0.080026620081524
2,2019.0,1,0.7375197275521223,0.04822544511260465,0.4428874734607219,0.12592408007309577
2,2020.0,1,0.7638024076380241,0.013328890369876709,0.26879699248120303,0.10585305105853052
2,2021.0,1,0.7744079767345243,0.013477377259599957,0.20364741641337386,0.09729954299958454
2,2022.0,1,0.7832958988436902,0.016548961737113944,0.19237147595356552,0.09458447716496132
2,2020.0,1,0.6523038605230386,0.01010774186382317,0.23182957393483708,0.08684101286841013
2,2021.0,1,0.7274615704196095,0.010578638796839153,0.2099712368168744,0.09488990444536768
2,2022.0,1,0.680891772731054,0.011519716437749225,0.1648,0.080026620081524
Loading