diff --git a/config/default.yml b/config/default.yml index ca449ce17..d2dcda063 100644 --- a/config/default.yml +++ b/config/default.yml @@ -143,7 +143,7 @@ innovation_args: # Output files: # Statistics1.csv — income distribution: Gini coefficients, income percentiles, median EDI, S-Index # Statistics2.csv — demographic validation: partnership rates, employment, health, disability by age/gender -# Statistics3.csv — alignment diagnostics: simulated vs target rates and adjustment factors +# AlignmentAdjustmentFactors1.csv — alignment diagnostics: factors, simulated shares, and target shares # EmploymentStatistics.csv — labour market transitions and participation rates # HealthStatistics.csv — health measures (SF-12, GHQ-12, EQ-5D) by age/gender @@ -153,7 +153,7 @@ collector_args: # exportToCSV: true # write outputs to CSV files under output//csv/ # persistStatistics: true # write Statistics1.csv (income distribution) # persistStatistics2: true # write Statistics2.csv (demographic validation outputs) -# persistStatistics3: true # write Statistics3.csv (alignment diagnostics) +# persistAlignmentAdjustmentFactors: true # write AlignmentAdjustmentFactors1.csv # persistPersons: false # write one row per person per year (large files) # persistBenefitUnits: false # write one row per benefit unit per year (large files) # persistHouseholds: false # write one row per household per year diff --git a/config/test_run.yml b/config/test_run.yml index 8895a6b60..92a0cf6a6 100644 --- a/config/test_run.yml +++ b/config/test_run.yml @@ -12,7 +12,7 @@ integrationTest: true collector_args: persistStatistics: true persistStatistics2: true - persistStatistics3: true + persistAlignmentAdjustmentFactors: true persistPersons: false persistBenefitUnits: false - persistHouseholds: false \ No newline at end of file + persistHouseholds: false diff --git a/src/main/java/simpaths/data/statistics/AlignmentAdjustmentFactors.java b/src/main/java/simpaths/data/statistics/AlignmentAdjustmentFactors.java new file mode 100644 index 000000000..439c4c06a --- /dev/null +++ b/src/main/java/simpaths/data/statistics/AlignmentAdjustmentFactors.java @@ -0,0 +1,347 @@ +package simpaths.data.statistics; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import microsim.data.db.PanelEntityKey; +import simpaths.data.Parameters; +import simpaths.data.filters.FertileFilter; +import simpaths.model.BenefitUnit; +import simpaths.model.Person; +import simpaths.model.SimPathsModel; +import simpaths.model.enums.*; + +/** + * + * CLASS TO REPORT ALIGNMENT ADJUSTMENT FACTORS AND SIMULATED VS TARGET SHARES + * + * Covers: partnership, fertility, in-school, utility adjustment factors, and + * employment shares by occupancy type. Disability and retirement are excluded. + * + */ +@Entity +public class AlignmentAdjustmentFactors { + + @Id + private PanelEntityKey key = new PanelEntityKey(1L); + + // ------------------------------------------------------------------ + // Partnership + // ------------------------------------------------------------------ + @Column(name = "partnership_adj_factor") + private double partnershipAdjFactor; + + @Column(name = "share_cohabiting_sim") + private double shareCohabitingSim; + + @Column(name = "share_cohabiting_tgt") + private double shareCohabitingTgt; + + // ------------------------------------------------------------------ + // Fertility + // ------------------------------------------------------------------ + @Column(name = "fertility_adj_factor") + private double fertilityAdjFactor; + + @Column(name = "fertility_rate_sim") + private double fertilityRateSim; + + @Column(name = "fertility_rate_tgt") + private double fertilityRateTgt; + + // ------------------------------------------------------------------ + // In-school + // ------------------------------------------------------------------ + @Column(name = "in_school_adj_factor") + private double inSchoolAdjFactor; + + @Column(name = "in_school_share_sim") + private double inSchoolShareSim; + + @Column(name = "in_school_share_tgt") + private double inSchoolShareTgt; + + // ------------------------------------------------------------------ + // Utility adjustment factors (one per occupancy type) + // ------------------------------------------------------------------ + @Column(name = "utility_adj_single_males") + private double utilityAdjSingleMales; + + @Column(name = "utility_adj_ac_males") + private double utilityAdjACMales; + + @Column(name = "utility_adj_single_females") + private double utilityAdjSingleFemales; + + @Column(name = "utility_adj_ac_females") + private double utilityAdjACFemales; + + @Column(name = "utility_adj_couples") + private double utilityAdjCouples; + + @Column(name = "utility_adj_single_dep_males") + private double utilityAdjSingleDepMales; + + @Column(name = "utility_adj_single_dep_females") + private double utilityAdjSingleDepFemales; + + // ------------------------------------------------------------------ + // Employment shares — simulated + // ------------------------------------------------------------------ + @Column(name = "emp_share_sim_single_males") + private double empShareSimSingleMales; + + @Column(name = "emp_share_sim_single_females") + private double empShareSimSingleFemales; + + @Column(name = "emp_share_sim_ac_males") + private double empShareSimACMales; + + @Column(name = "emp_share_sim_ac_females") + private double empShareSimACFemales; + + @Column(name = "emp_share_sim_couples") + private double empShareSimCouples; + + @Column(name = "emp_share_sim_single_dep_males") + private double empShareSimSingleDepMales; + + @Column(name = "emp_share_sim_single_dep_females") + private double empShareSimSingleDepFemales; + + // ------------------------------------------------------------------ + // Employment shares — target + // ------------------------------------------------------------------ + @Column(name = "emp_share_tgt_single_males") + private double empShareTgtSingleMales; + + @Column(name = "emp_share_tgt_single_females") + private double empShareTgtSingleFemales; + + @Column(name = "emp_share_tgt_ac_males") + private double empShareTgtACMales; + + @Column(name = "emp_share_tgt_ac_females") + private double empShareTgtACFemales; + + @Column(name = "emp_share_tgt_couples") + private double empShareTgtCouples; + + @Column(name = "emp_share_tgt_single_dep_males") + private double empShareTgtSingleDepMales; + + @Column(name = "emp_share_tgt_single_dep_females") + private double empShareTgtSingleDepFemales; + + + // ------------------------------------------------------------------ + // Getters and setters + // ------------------------------------------------------------------ + + public double getPartnershipAdjFactor() { return partnershipAdjFactor; } + public void setPartnershipAdjFactor(double v) { partnershipAdjFactor = v; } + + public double getShareCohabitingSim() { return shareCohabitingSim; } + public void setShareCohabitingSim(double v) { shareCohabitingSim = v; } + + public double getShareCohabitingTgt() { return shareCohabitingTgt; } + public void setShareCohabitingTgt(double v) { shareCohabitingTgt = v; } + + public double getFertilityAdjFactor() { return fertilityAdjFactor; } + public void setFertilityAdjFactor(double v) { fertilityAdjFactor = v; } + + public double getFertilityRateSim() { return fertilityRateSim; } + public void setFertilityRateSim(double v) { fertilityRateSim = v; } + + public double getFertilityRateTgt() { return fertilityRateTgt; } + public void setFertilityRateTgt(double v) { fertilityRateTgt = v; } + + public double getInSchoolAdjFactor() { return inSchoolAdjFactor; } + public void setInSchoolAdjFactor(double v) { inSchoolAdjFactor = v; } + + public double getInSchoolShareSim() { return inSchoolShareSim; } + public void setInSchoolShareSim(double v) { inSchoolShareSim = v; } + + public double getInSchoolShareTgt() { return inSchoolShareTgt; } + public void setInSchoolShareTgt(double v) { inSchoolShareTgt = v; } + + public double getUtilityAdjSingleMales() { return utilityAdjSingleMales; } + public void setUtilityAdjSingleMales(double v) { utilityAdjSingleMales = v; } + + public double getUtilityAdjACMales() { return utilityAdjACMales; } + public void setUtilityAdjACMales(double v) { utilityAdjACMales = v; } + + public double getUtilityAdjSingleFemales() { return utilityAdjSingleFemales; } + public void setUtilityAdjSingleFemales(double v) { utilityAdjSingleFemales = v; } + + public double getUtilityAdjACFemales() { return utilityAdjACFemales; } + public void setUtilityAdjACFemales(double v) { utilityAdjACFemales = v; } + + public double getUtilityAdjCouples() { return utilityAdjCouples; } + public void setUtilityAdjCouples(double v) { utilityAdjCouples = v; } + + public double getUtilityAdjSingleDepMales() { return utilityAdjSingleDepMales; } + public void setUtilityAdjSingleDepMales(double v) { utilityAdjSingleDepMales = v; } + + public double getUtilityAdjSingleDepFemales() { return utilityAdjSingleDepFemales; } + public void setUtilityAdjSingleDepFemales(double v) { utilityAdjSingleDepFemales = v; } + + public double getEmpShareSimSingleMales() { return empShareSimSingleMales; } + public void setEmpShareSimSingleMales(double v) { empShareSimSingleMales = v; } + + public double getEmpShareSimSingleFemales() { return empShareSimSingleFemales; } + public void setEmpShareSimSingleFemales(double v) { empShareSimSingleFemales = v; } + + public double getEmpShareSimACMales() { return empShareSimACMales; } + public void setEmpShareSimACMales(double v) { empShareSimACMales = v; } + + public double getEmpShareSimACFemales() { return empShareSimACFemales; } + public void setEmpShareSimACFemales(double v) { empShareSimACFemales = v; } + + public double getEmpShareSimCouples() { return empShareSimCouples; } + public void setEmpShareSimCouples(double v) { empShareSimCouples = v; } + + public double getEmpShareSimSingleDepMales() { return empShareSimSingleDepMales; } + public void setEmpShareSimSingleDepMales(double v) { empShareSimSingleDepMales = v; } + + public double getEmpShareSimSingleDepFemales() { return empShareSimSingleDepFemales; } + public void setEmpShareSimSingleDepFemales(double v) { empShareSimSingleDepFemales = v; } + + public double getEmpShareTgtSingleMales() { return empShareTgtSingleMales; } + public void setEmpShareTgtSingleMales(double v) { empShareTgtSingleMales = v; } + + public double getEmpShareTgtSingleFemales() { return empShareTgtSingleFemales; } + public void setEmpShareTgtSingleFemales(double v) { empShareTgtSingleFemales = v; } + + public double getEmpShareTgtACMales() { return empShareTgtACMales; } + public void setEmpShareTgtACMales(double v) { empShareTgtACMales = v; } + + public double getEmpShareTgtACFemales() { return empShareTgtACFemales; } + public void setEmpShareTgtACFemales(double v) { empShareTgtACFemales = v; } + + public double getEmpShareTgtCouples() { return empShareTgtCouples; } + public void setEmpShareTgtCouples(double v) { empShareTgtCouples = v; } + + public double getEmpShareTgtSingleDepMales() { return empShareTgtSingleDepMales; } + public void setEmpShareTgtSingleDepMales(double v) { empShareTgtSingleDepMales = v; } + + public double getEmpShareTgtSingleDepFemales() { return empShareTgtSingleDepFemales; } + public void setEmpShareTgtSingleDepFemales(double v) { empShareTgtSingleDepFemales = v; } + + + // ------------------------------------------------------------------ + // update() + // ------------------------------------------------------------------ + + public void update(SimPathsModel model) { + + int year = model.getYear() - 1; // year just simulated (consistent with annual collector exports) + + // --- Partnership --- + setPartnershipAdjFactor( + Parameters.getTimeSeriesValue(year, TimeSeriesVariable.PartnershipAdjustment) + + model.getPartnershipAdjustment(year)); + long numPersonsCohabEligible = model.getPersons().stream() + .filter(p -> p.getDemAge() >= Parameters.MIN_AGE_COHABITATION) + .count(); + long numPersonsPartnered = model.getPersons().stream() + .filter(p -> Dcpst.Partnered.equals(p.getDcpst())) + .count(); + setShareCohabitingSim(numPersonsCohabEligible > 0 + ? (double) numPersonsPartnered / numPersonsCohabEligible : 0.0); + setShareCohabitingTgt(Parameters.getTargetShare(year, TargetShares.Partnership)); + + // --- Fertility --- + setFertilityAdjFactor( + Parameters.getTimeSeriesValue(year, TimeSeriesVariable.FertilityAdjustment) + + model.getFertilityAdjustment(year)); + FertileFilter fertileFilter = new FertileFilter(); + long numFertile = model.getPersons().stream() + .filter(p -> fertileFilter.evaluate(p)) + .count(); + long numBirths = model.getPersons().stream() + .filter(p -> p.getDemAge() < 1) + .count(); + setFertilityRateSim(numFertile > 0 ? (double) numBirths / numFertile : 0.0); + setFertilityRateTgt(Parameters.getFertilityRateByYear(year)); + + // --- In-school --- + setInSchoolAdjFactor(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.InSchoolAdjustment)); + long numStudents = model.getPersons().stream() + .filter(p -> p.getDemAge() >= Parameters.MIN_AGE_TO_LEAVE_EDUCATION + && p.getDemAge() <= Parameters.MAX_AGE_TO_STAY_IN_CONTINUOUS_EDUCATION + && !p.isToLeaveSchool() + && Les_c4.Student.equals(p.getLes_c4())) + .count(); + long numInSchoolAge = model.getPersons().stream() + .filter(p -> p.getDemAge() >= Parameters.MIN_AGE_TO_LEAVE_EDUCATION + && p.getDemAge() <= Parameters.MAX_AGE_TO_STAY_IN_CONTINUOUS_EDUCATION + && p.getLes_c4() != null) + .count(); + setInSchoolShareSim(numInSchoolAge > 0 ? (double) numStudents / numInSchoolAge : 0.0); + setInSchoolShareTgt(Parameters.getTargetShare(year, TargetShares.Students)); + + // --- Utility adjustment factors --- + setUtilityAdjSingleMales(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentSingleMales)); + setUtilityAdjACMales(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentACMales)); + setUtilityAdjSingleFemales(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentSingleFemales)); + setUtilityAdjACFemales(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentACFemales)); + setUtilityAdjCouples(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentCouples)); + setUtilityAdjSingleDepMales(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentSingleDepMen)); + setUtilityAdjSingleDepFemales(Parameters.getTimeSeriesValue(year, TimeSeriesVariable.UtilityAdjustmentSingleDepWomen)); + + // --- Employment shares --- + double[] totSM = new double[2]; // [count, fracEmployed sum] + double[] totSF = new double[2]; + double[] totACM = new double[2]; + double[] totACF = new double[2]; + double[] totCou = new double[2]; + double[] totSDM = new double[2]; + double[] totSDF = new double[2]; + + for (BenefitUnit bu : model.getBenefitUnits()) { + Occupancy occ = bu.getOccupancy(); + Person male = bu.getMale(); + Person female = bu.getFemale(); + boolean maleAtRisk = (male != null) && male.atRiskOfWork(); + boolean femaleAtRisk = (female != null) && female.atRiskOfWork(); + int acFlag = 0; + if (occ == Occupancy.Single_Male && male != null) acFlag = male.getAdultChildFlag(); + if (occ == Occupancy.Single_Female && female != null) acFlag = female.getAdultChildFlag(); + + double frac = bu.fracEmployed(); + + if (occ == Occupancy.Single_Male && acFlag != 1) { + totSM[0]++; totSM[1] += frac; + } else if (occ == Occupancy.Single_Male && acFlag == 1) { + totACM[0]++; totACM[1] += frac; + } else if (occ == Occupancy.Single_Female && acFlag != 1) { + totSF[0]++; totSF[1] += frac; + } else if (occ == Occupancy.Single_Female && acFlag == 1) { + totACF[0]++; totACF[1] += frac; + } else if (occ == Occupancy.Couple && maleAtRisk && femaleAtRisk) { + totCou[0]++; totCou[1] += frac; + } else if (occ == Occupancy.Couple && maleAtRisk && !femaleAtRisk) { + totSDM[0]++; totSDM[1] += frac; + } else if (occ == Occupancy.Couple && !maleAtRisk && femaleAtRisk) { + totSDF[0]++; totSDF[1] += frac; + } + } + + setEmpShareSimSingleMales( totSM[0] > 0 ? totSM[1] / totSM[0] : 0.0); + setEmpShareSimSingleFemales(totSF[0] > 0 ? totSF[1] / totSF[0] : 0.0); + setEmpShareSimACMales( totACM[0] > 0 ? totACM[1] / totACM[0] : 0.0); + setEmpShareSimACFemales( totACF[0] > 0 ? totACF[1] / totACF[0] : 0.0); + setEmpShareSimCouples( totCou[0] > 0 ? totCou[1] / totCou[0] : 0.0); + setEmpShareSimSingleDepMales( totSDM[0] > 0 ? totSDM[1] / totSDM[0] : 0.0); + setEmpShareSimSingleDepFemales(totSDF[0] > 0 ? totSDF[1] / totSDF[0] : 0.0); + + setEmpShareTgtSingleMales( Parameters.getTargetShare(year, TargetShares.EmploymentSingleMales)); + setEmpShareTgtSingleFemales(Parameters.getTargetShare(year, TargetShares.EmploymentSingleFemales)); + setEmpShareTgtACMales( Parameters.getTargetShare(year, TargetShares.EmploymentACMales)); + setEmpShareTgtACFemales( Parameters.getTargetShare(year, TargetShares.EmploymentACFemales)); + setEmpShareTgtCouples( Parameters.getTargetShare(year, TargetShares.EmploymentCouples)); + setEmpShareTgtSingleDepMales( Parameters.getTargetShare(year, TargetShares.EmploymentSingleDepMales)); + setEmpShareTgtSingleDepFemales(Parameters.getTargetShare(year, TargetShares.EmploymentSingleDepFemales)); + } +} diff --git a/src/main/java/simpaths/data/statistics/Statistics3.java b/src/main/java/simpaths/data/statistics/Statistics3.java deleted file mode 100644 index 4b2c5bdb1..000000000 --- a/src/main/java/simpaths/data/statistics/Statistics3.java +++ /dev/null @@ -1,200 +0,0 @@ -package simpaths.data.statistics; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import microsim.data.db.PanelEntityKey; -import simpaths.data.Parameters; -import simpaths.data.filters.FertileFilter; -import simpaths.model.SimPathsModel; -import simpaths.model.enums.AlignmentVariable; -import simpaths.model.enums.Dcpst; -import simpaths.model.enums.TargetShares; -import simpaths.model.enums.TimeSeriesVariable; - -@Entity -public class Statistics3 { - - @Id - private PanelEntityKey key = new PanelEntityKey(1L); - - @Column(name= "social_care_adj_factor") - private double careAdj; - - @Column(name = "partnership_adj_factor") - private double demPartnerAdj; - - @Column(name = "share_cohabiting_sim") - private double demPartnerSimShare; - - @Column(name = "share_cohabiting_tgt") - private double demPartnerTargetShare; - - @Column(name = "fertility_adj_factor") - private double demFertAdj; - - @Column(name = "fertiilty_rate_sim") - private double demFertRateSim; - - @Column(name = "fertiilty_rate_tgt") - private double demFertRateTarget; - - @Column(name = "utility_adj_factor_smales") - private double demUtilAdjSingleM; - - @Column(name = "utility_adj_factor_ac_males") - private double demUtilAdjSingleACM; - - @Column(name = "utility_adj_factor_sfemales") - private double demUtilAdjSingleF; - - @Column(name = "utility_adj_factor_ac_females") - private double demUtilAdjSingleACF; - - @Column(name = "utility_adj_factor_couples") - private double demUtilAdjCouple; - - @Column(name = "utility_adj_factor_smales_dep") - private double demUtilAdjSDepM; - - @Column(name = "utility_adj_factor_sfemales_dep") - private double demUtilAdjSDepF; - - public double getPartnershipAdjustmentFactor() { - return demPartnerAdj; - } - - public void setPartnershipAdjustmentFactor(double demPartnerAdj) { - this.demPartnerAdj = demPartnerAdj; - } - - public double getFertilityAdjustmentFactor() { - return demFertAdj; - } - - public void setFertilityAdjustmentFactor(double factor) { - this.demFertAdj = factor; - } - - public double getUtilityAdjustmentFactorSmales() { - return demUtilAdjSingleM; - } - - public void setUtilityAdjustmentFactorSmales(double demUtilAdjSingleM) { - this.demUtilAdjSingleM = demUtilAdjSingleM; - } - - public double getUtilityAdjustmentFactorACmales() {return demUtilAdjSingleACM; } - - public void setUtilityAdjustmentFactorACmales(double demUtilAdjACM) { - this.demUtilAdjSingleACM = demUtilAdjACM; - } - - public double getUtilityAdjustmentFactorSfemales() { - return demUtilAdjSingleF; - } - - public void setUtilityAdjustmentFactorSfemales(double demUtilAdjSingleF) { - this.demUtilAdjSingleF = demUtilAdjSingleF; - } - - public double getUtilityAdjustmentFactorACfemales() { return demUtilAdjSingleACF;} - - public void setUtilityAdjustmentFactorACfemales(double demUtilAdjACF) { - this.demUtilAdjSingleACF = demUtilAdjACF; - } - - public double getUtilityAdjustmentFactorCouples() { - return demUtilAdjCouple; - } - - public void setUtilityAdjustmentFactorCouples(double demUtilAdjCouple) { - this.demUtilAdjCouple = demUtilAdjCouple; - } - - public double getUtilityAdjustmentFactorSDepFemales() {return demUtilAdjSDepF;} - - public void setUtilityAdjustmentFactorSDepFemales(double demUtilAdjSDepF) { - this.demUtilAdjSDepF = demUtilAdjSDepF; - } - - public double getUtilityAdjustmentFactorSDepMales(){return demUtilAdjSDepM;} - - public void setUtilityAdjustmentFactorSDepMales(double demUtilAdjSDepM) { - this.demUtilAdjSDepM = demUtilAdjSDepM; - } - - public double getSocialCareAdjustmentFactor() { return careAdj; } - - public void setSocialCareAdjustmentFactor(double factor) { - careAdj = factor;} - - public double getShareCohabitingSimulated() {return demPartnerSimShare;} - - public void setShareCohabitingSimulated(double demPartnerSimShare) { this.demPartnerSimShare = demPartnerSimShare; } - - public double getFertilityRateSimulated() { - return demFertRateSim; - } - - public void setFertilityRateSimulated(double demFertRateSim) { - this.demFertRateSim = demFertRateSim; - } - - public double getFertilityRateTarget() { - return demFertRateTarget; - } - - public void setFertilityRateTarget(double demFertRateTarget) { - this.demFertRateTarget = demFertRateTarget; - } - - public double getShareCohabitingTarget() { - return demPartnerTargetShare; - } - - public void setShareCohabitingTarget(double demPartnerTargetShare) { - this.demPartnerTargetShare = demPartnerTargetShare; - } - - public void update(SimPathsModel model) { - - // cohabitation - double val = Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.PartnershipAdjustment) + - model.getPartnershipAdjustment(model.getYear()-1); - setPartnershipAdjustmentFactor(val); - long numPersonsWhoCanHavePartner = model.getPersons().stream() - .filter(person -> person.getDemAge() >= Parameters.MIN_AGE_COHABITATION) - .count(); - long numPersonsPartnered = model.getPersons().stream() - .filter(person -> (person.getDcpst().equals(Dcpst.Partnered))) - .count(); - val = (numPersonsWhoCanHavePartner > 0) ? (double) numPersonsPartnered / numPersonsWhoCanHavePartner : 0.0; - setShareCohabitingSimulated(val); - setShareCohabitingTarget(Parameters.getTargetShare(model.getYear()-1, TargetShares.Partnership)); - - // fertility - val = Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.FertilityAdjustment) + - model.getFertilityAdjustment(model.getYear()-1); - setFertilityAdjustmentFactor(val); - FertileFilter filter = new FertileFilter(); - long numFertilePersons = model.getPersons().stream() - .filter(person -> filter.evaluate(person)) - .count(); - long numBirths = model.getPersons().stream() - .filter(person -> (person.getDemAge() < 1)) - .count(); - val = (numFertilePersons > 0) ? (double) numBirths / numFertilePersons : 0.0; - setFertilityRateSimulated(val); - setFertilityRateTarget(Parameters.getFertilityRateByYear(model.getYear()-1)); - - setSocialCareAdjustmentFactor(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.CareProvisionAdjustment)); - setUtilityAdjustmentFactorSmales(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentSingleMales)); - setUtilityAdjustmentFactorACmales(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentACMales)); - setUtilityAdjustmentFactorSfemales(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentSingleFemales)); - setUtilityAdjustmentFactorACfemales(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentACFemales)); - setUtilityAdjustmentFactorCouples(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentCouples)); - setUtilityAdjustmentFactorSDepFemales(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentSingleDepWomen)); - setUtilityAdjustmentFactorSDepMales(Parameters.getTimeSeriesValue(model.getYear()-1, TimeSeriesVariable.UtilityAdjustmentSingleDepMen)); - } -} diff --git a/src/main/java/simpaths/experiment/SimPathsCollector.java b/src/main/java/simpaths/experiment/SimPathsCollector.java index 6b9dc53a9..349450642 100644 --- a/src/main/java/simpaths/experiment/SimPathsCollector.java +++ b/src/main/java/simpaths/experiment/SimPathsCollector.java @@ -31,9 +31,9 @@ import microsim.statistics.IDoubleSource; // import LABOURsim packages import simpaths.data.Parameters; +import simpaths.data.statistics.AlignmentAdjustmentFactors; import simpaths.data.statistics.Statistics; import simpaths.data.statistics.Statistics2; -import simpaths.data.statistics.Statistics3; import simpaths.model.Person; import simpaths.model.enums.Region; @@ -56,8 +56,8 @@ public class SimPathsCollector extends AbstractSimulationCollectorManager implem @GUIparameter(description="Calculate extended set of population characteristics (useful for validation)") private boolean persistStatistics2 = true; - @GUIparameter(description="Report alignment adjustments") - private boolean persistStatistics3 = true; + @GUIparameter(description="Report alignment adjustment factors (AlignmentAdjustmentFactors1.csv)") + private boolean persistAlignmentAdjustmentFactors = true; private boolean persistEmploymentStatistics = true; @@ -96,7 +96,7 @@ public class SimPathsCollector extends AbstractSimulationCollectorManager implem private Statistics2 stats2; - private Statistics3 stats3; + private AlignmentAdjustmentFactors alignmentAdjustmentFactors; private EmploymentStatistics statsEmployment; @@ -122,7 +122,7 @@ public class SimPathsCollector extends AbstractSimulationCollectorManager implem private DataExport exportStatistics2; - private DataExport exportStatistics3; + private DataExport exportAlignmentAdjustmentFactors; private DataExport exportStatisticsEmployment; @@ -161,7 +161,7 @@ public enum Processes { DumpHouseholds, DumpStatistics, DumpStatistics2, - DumpStatistics3, + DumpAlignmentAdjustmentFactors, DumpStatisticsEmployment, DumpHealthStatistics } @@ -222,14 +222,14 @@ public void onEvent(Enum type) { log.error(e.getMessage()); } break; - case DumpStatistics3: - stats3.update(model); - try { - exportStatistics3.export(); - } catch (Exception e) { - log.error(e.getMessage()); - } - break; + case DumpAlignmentAdjustmentFactors: + alignmentAdjustmentFactors.update(model); + try { + exportAlignmentAdjustmentFactors.export(); + } catch (Exception e) { + log.error(e.getMessage()); + } + break; case DumpStatisticsEmployment: statsEmployment.update(model); try { @@ -264,7 +264,7 @@ public void buildObjects() { stats = new Statistics(); stats2 = new Statistics2(); - stats3 = new Statistics3(); + alignmentAdjustmentFactors = new AlignmentAdjustmentFactors(); statsEmployment = new EmploymentStatistics(); statsHealth = new HealthStatistics(); @@ -279,8 +279,8 @@ public void buildObjects() { exportStatistics = new DataExport(stats, exportToDatabase, exportToCSV); if (persistStatistics2) exportStatistics2 = new DataExport(stats2, exportToDatabase, exportToCSV); - if (persistStatistics3) - exportStatistics3 = new DataExport(stats3, exportToDatabase, exportToCSV); + if (persistAlignmentAdjustmentFactors) + exportAlignmentAdjustmentFactors = new DataExport(alignmentAdjustmentFactors, exportToDatabase, exportToCSV); if (persistEmploymentStatistics) exportStatisticsEmployment = new DataExport(statsEmployment, exportToDatabase, exportToCSV); if (persistHealthStatistics) @@ -338,9 +338,9 @@ public void buildSchedule() { getEngine().getEventQueue().scheduleRepeat(new SingleTargetEvent(this, Processes.DumpStatistics2), model.getStartYear() + dataDumpStartTime, ordering, dataDumpTimePeriod); } - if (persistStatistics3) { - getEngine().getEventQueue().scheduleRepeat(new SingleTargetEvent(this, Processes.DumpStatistics3), model.getStartYear() + dataDumpStartTime, ordering, dataDumpTimePeriod); - } + if (persistAlignmentAdjustmentFactors) { + getEngine().getEventQueue().scheduleRepeat(new SingleTargetEvent(this, Processes.DumpAlignmentAdjustmentFactors), model.getStartYear() + dataDumpStartTime, ordering, dataDumpTimePeriod); + } if (persistEmploymentStatistics) { getEngine().getEventQueue().scheduleRepeat(new SingleTargetEvent(this, Processes.DumpStatisticsEmployment), model.getStartYear() + dataDumpStartTime, ordering, dataDumpTimePeriod); @@ -822,12 +822,6 @@ public void setStats(Statistics stats) { public void setStats2(Statistics2 stats2) { this.stats2 = stats2; } - public Statistics3 getStats3() { return stats3; } - - public void setStats3(Statistics3 stats3) { - this.stats3 = stats3; - } - public boolean isExportToDatabase() { return exportToDatabase; } @@ -868,14 +862,6 @@ public void setPersistStatistics2(boolean val) { persistStatistics2 = val; } - public boolean isPersistStatistics3() { - return persistStatistics3; - } - - public void setPersistStatistics3(boolean val) { - persistStatistics3 = val; - } - public void calculateAtRiskOfPoverty() { calculateEquivalisedHouseholdDisposableIncome(); } diff --git a/src/main/java/simpaths/model/SimPathsModel.java b/src/main/java/simpaths/model/SimPathsModel.java index 2d3fdd196..2f82299df 100644 --- a/src/main/java/simpaths/model/SimPathsModel.java +++ b/src/main/java/simpaths/model/SimPathsModel.java @@ -4,6 +4,7 @@ // import Java packages import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.EntityTransaction; import jakarta.persistence.Persistence; import jakarta.persistence.Transient; @@ -329,6 +330,8 @@ public void setFirstRun(boolean firstRun) { private static String RunDatabasePath; private static String PersistDatabasePath; private static boolean PersistPopulation = false; + private static EntityManagerFactory emfStartingPopulationRun = null; + private static EntityManagerFactory emfStartingPopulationPersist = null; @@ -3633,7 +3636,6 @@ private Processed getProcessed() { private Processed getProcessed(Country country, int startYear, int popSize, boolean ignoreTargetsAtPopulationLoad) { Processed processed = null; - Processed processed_return = null; EntityTransaction txn = null; try { @@ -3641,7 +3643,9 @@ private Processed getProcessed(Country country, int startYear, int popSize, bool // query database Map propertyMap = new HashMap(); propertyMap.put("hibernate.connection.url", "jdbc:h2:file:" + getPersistDatabasePath() + ";TRACE_LEVEL_FILE=0;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE"); - EntityManager em = Persistence.createEntityManagerFactory("starting-population", propertyMap).createEntityManager(); + if (emfStartingPopulationPersist == null) + emfStartingPopulationPersist = Persistence.createEntityManagerFactory("starting-population", propertyMap); + EntityManager em = emfStartingPopulationPersist.createEntityManager(); txn = em.getTransaction(); txn.begin(); // String query = "SELECT DISTINCT processed FROM Processed processed LEFT JOIN FETCH processed.households households LEFT JOIN FETCH households.benefitUnits benefitUnits LEFT JOIN FETCH benefitUnits.members members WHERE processed.startYear = " + startYear + " AND processed.popSize = " + popSize + " AND processed.country = " + country + " AND processed.noTargets = " + ignoreTargetsAtPopulationLoad + " ORDER BY households.key.id"; @@ -3655,16 +3659,15 @@ private Processed getProcessed(Country country, int startYear, int popSize, bool if (processedList.size()>1) throw new RuntimeException("more than one relevant dataset returned from database"); processed = processedList.get(0); + // force-initialize lazy collections within the open session (triggers SUBSELECT batch loads) processed.resetDependents(); -// // Now fetch households for THIS specific Processed instance only - processed_return = em.createQuery( + em.createQuery( "SELECT p FROM Processed p LEFT JOIN FETCH p.households h WHERE p = :proc ORDER BY h.key.id", Processed.class) .setParameter("proc", processed) - .getSingleResult(); - - processed_return.resetDependents(); + .getSingleResult() + .resetDependents(); } // close database connection @@ -3689,7 +3692,9 @@ private List loadStartingPopulation() { Map propertyMap = new HashMap(); propertyMap.put("hibernate.connection.url", "jdbc:h2:file:" + RunDatabasePath + ";TRACE_LEVEL_FILE=0;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE"); - EntityManager em = Persistence.createEntityManagerFactory("starting-population", propertyMap).createEntityManager(); + if (emfStartingPopulationRun == null) + emfStartingPopulationRun = Persistence.createEntityManagerFactory("starting-population", propertyMap); + EntityManager em = emfStartingPopulationRun.createEntityManager(); txn = em.getTransaction(); txn.begin(); String query = "SELECT households FROM Household households"; @@ -3698,6 +3703,13 @@ private List loadStartingPopulation() { households = em.createQuery(query).getResultList(); log.info("Query complete"); + // force-initialize lazy collections within the open session (triggers SUBSELECT batch loads) + for (Household hh : households) { + for (BenefitUnit bu : hh.getBenefitUnits()) { + bu.getMembers().size(); + } + } + // close database connection em.close(); } catch (Exception e) { @@ -3722,7 +3734,9 @@ private void persistProcessed(Set households, Country country, int st Map propertyMap = new HashMap(); propertyMap.put("hibernate.connection.url", "jdbc:h2:file:" + getPersistDatabasePath() + ";TRACE_LEVEL_FILE=0;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE"); - EntityManager em = Persistence.createEntityManagerFactory("starting-population", propertyMap).createEntityManager(); + if (emfStartingPopulationPersist == null) + emfStartingPopulationPersist = Persistence.createEntityManagerFactory("starting-population", propertyMap); + EntityManager em = emfStartingPopulationPersist.createEntityManager(); txn = em.getTransaction(); txn.begin(); diff --git a/src/main/java/simpaths/model/taxes/DonorTaxImputation.java b/src/main/java/simpaths/model/taxes/DonorTaxImputation.java index 0f0191574..d0aa8edd1 100644 --- a/src/main/java/simpaths/model/taxes/DonorTaxImputation.java +++ b/src/main/java/simpaths/model/taxes/DonorTaxImputation.java @@ -1,6 +1,7 @@ package simpaths.model.taxes; +import microsim.engine.SimulationEngine; import org.apache.commons.lang3.tuple.Triple; import simpaths.model.enums.UpratingCase; @@ -366,7 +367,7 @@ public void evaluate() { disposableIncomePerWeek *= (1.0 + Parameters.disposableIncomeFromLabourInnov); benefitsReceivedPerWeek *= (1.0 + Parameters.disposableIncomeFromLabourInnov); } - if (UCmean > Math.random()) { // Weighted probability of receiving UC + if (UCmean > SimulationEngine.getRnd().nextDouble()) { // Weighted probability of receiving UC setReceivedUC(1); } if (LBmean > 0 && getReceivedUC() == 0) { // Setting as received LB if benefits but not UC diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 8fb382283..0f15f9f4f 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -59,7 +59,7 @@ simpaths.model.BenefitUnit simpaths.data.statistics.Statistics simpaths.data.statistics.Statistics2 - simpaths.data.statistics.Statistics3 + simpaths.data.statistics.AlignmentAdjustmentFactors simpaths.data.statistics.HealthStatistics simpaths.data.statistics.EmploymentStatistics false diff --git a/src/test/java/simpaths/integrationtest/RunSimPathsIntegrationTest.java b/src/test/java/simpaths/integrationtest/RunSimPathsIntegrationTest.java index 8cb7ae4b5..313062a01 100644 --- a/src/test/java/simpaths/integrationtest/RunSimPathsIntegrationTest.java +++ b/src/test/java/simpaths/integrationtest/RunSimPathsIntegrationTest.java @@ -77,11 +77,11 @@ public void compareStatistics21() throws IOException { ); } @Test - public void compareStatistics31() throws IOException { - compareFiles( - latestOutputDir.resolve("csv/Statistics31.csv"), - Paths.get("src/test/java/simpaths/integrationtest/expected/Statistics31.csv") - ); + public void verifyAlignmentAdjustmentFactorsExported() { + assertTrue( + Files.exists(latestOutputDir.resolve("csv/AlignmentAdjustmentFactors1.csv")), + "Expected output file is missing: " + latestOutputDir.resolve("csv/AlignmentAdjustmentFactors1.csv") + ); } @Test public void compareHealthStatistics1() throws IOException {