View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package p3j.simulation;
17  
18  import james.SimSystem;
19  import james.core.math.random.generators.IRandom;
20  import james.core.util.misc.Pair;
21  
22  import java.util.ArrayList;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  
28  import p3j.database.IP3MDatabase;
29  import p3j.experiment.results.ExecutionSummary;
30  import p3j.experiment.results.ResultsOfTrial;
31  import p3j.misc.errors.GeneratorError;
32  import p3j.misc.math.Matrix2D;
33  import p3j.pppm.IProjectionModel;
34  import p3j.pppm.parameters.Parameter;
35  import p3j.pppm.parameters.ParameterAssignment;
36  import p3j.pppm.parameters.ParameterInstance;
37  import p3j.pppm.parameters.Parameters;
38  import p3j.simulation.assignments.plugintype.IParamAssignmentGenerator;
39  import p3j.simulation.calculation.deterministic.MigChildPopulation;
40  import p3j.simulation.calculation.deterministic.MigPopulation;
41  import p3j.simulation.calculation.deterministic.NativePopulation;
42  import p3j.simulation.calculation.deterministic.parameters.BasicParameters;
43  import p3j.simulation.calculation.deterministic.parameters.MigChildParameters;
44  import p3j.simulation.calculation.deterministic.parameters.MigParameters;
45  import p3j.simulation.calculation.deterministic.parameters.NativeParameters;
46  
47  /**
48   * This class holds all data structures and methods that are required to use an
49   * {@link IParamAssignmentGenerator} for a single execution of the PPPM.
50   * 
51   * Created: August 17, 2008
52   * 
53   * @author Christina Bohk
54   * @author Roland Ewald
55   * 
56   */
57  public class SingleExecution {
58  
59  	/**
60  	 * Auxiliary mapping of generation-independent parameters. The key is the name
61  	 * of the associated parameters.
62  	 */
63  	private Map<String, ParameterAssignment> genIndepParameters;
64  
65  	/**
66  	 * Auxiliary mapping of generation-dependent parameters. The i-th element is a
67  	 * map containing all parameter assignments for the i-th generation. The key
68  	 * is the name of the associated parameters.
69  	 */
70  	private List<Map<String, ParameterAssignment>> genDepParameters;
71  
72  	/** The projection setup, contains all input data. */
73  	private IProjectionModel projection;
74  
75  	/** The database to store results in. */
76  	private final IP3MDatabase database;
77  
78  	/** The random number generator to be used. */
79  	private final IRandom random;
80  
81  	/**
82  	 * Default constructor.
83  	 * 
84  	 * @param proj
85  	 *          the projection containing all input data
86  	 * @param dataBase
87  	 *          the database to store results in
88  	 */
89  	public SingleExecution(IProjectionModel proj, IP3MDatabase dataBase) {
90  		projection = proj;
91  		database = dataBase;
92  		random = SimSystem.getRNGGenerator().getNextRNG();
93  	}
94  
95  	/**
96  	 * Sets up and executes a single variable assignment for the PPPM.
97  	 * 
98  	 * @param generator
99  	 *          the assignment generator to be used
100 	 * @return error log from the {@link IParamAssignmentGenerator}
101 	 */
102 	public Pair<ExecutionSummary, List<GeneratorError>> execute(
103 	    IParamAssignmentGenerator generator) {
104 
105 		Pair<Map<ParameterInstance, ParameterAssignment>, List<GeneratorError>> assignment = chooseAssignment(
106 		    generator, random);
107 
108 		// Create parameter classes
109 		int years = projection.getYears();
110 		NativeParameters nativeParameters = setupBasicNativeParameters(years);
111 		NativePopulation nativePopulation = new NativePopulation();
112 
113 		ExecutionSummary executionSummary = new ExecutionSummary(
114 		    assignment.getFirstValue());
115 		executionSummary.setNativeParameters(nativeParameters);
116 		executionSummary.setNativeResults(nativePopulation
117 		    .calculatePopulation(nativeParameters));
118 
119 		for (int i = 0; i < projection.getGenerations(); i++) {
120 			// Calculate emigration population
121 			if (i == 0) {
122 				calculateFirstEmigrantPopulation(executionSummary, years);
123 			} else {
124 				calculateEmigrantChildPopulation(executionSummary, i, years);
125 			}
126 			// Calculate immigration population
127 			if (i == 0) {
128 				calculateFirstImmigrantPopulation(executionSummary, years);
129 			} else {
130 				calculateImmigrantChildPopulation(executionSummary, i, years);
131 			}
132 		}
133 
134 		storeResultsToDB(executionSummary);
135 
136 		return new Pair<ExecutionSummary, List<GeneratorError>>(executionSummary,
137 		    assignment.getSecondValue());
138 	}
139 
140 	/**
141 	 * Stores results to database.
142 	 * 
143 	 * @param executionSummary
144 	 *          the execution summary
145 	 */
146 	private void storeResultsToDB(ExecutionSummary executionSummary) {
147 		ResultsOfTrial results = new ResultsOfTrial(projection, executionSummary);
148 		database.saveTrialResults(results);
149 	}
150 
151 	/**
152 	 * Lets the {@link IParamAssignmentGenerator} choose a valid assignment and
153 	 * sets up all auxiliary data structures according to this.
154 	 * 
155 	 * @param generator
156 	 *          the component for generating the assignment to be calculated
157 	 * @param rng
158 	 *          the random number generator
159 	 * @return error log from the {@link IParamAssignmentGenerator}
160 	 */
161 	protected Pair<Map<ParameterInstance, ParameterAssignment>, List<GeneratorError>> chooseAssignment(
162 	    IParamAssignmentGenerator generator, IRandom rng) {
163 
164 		Pair<Map<ParameterInstance, ParameterAssignment>, List<GeneratorError>> generatorResults = generator
165 		    .chooseParamAssignments(rng);
166 
167 		// Generate parameter assignment
168 		Map<ParameterInstance, ParameterAssignment> assignments = generatorResults
169 		    .getFirstValue();
170 
171 		// Create data structures to hold generation-dependent and
172 		// generation-independent parameters
173 		genIndepParameters = new HashMap<String, ParameterAssignment>();
174 		genDepParameters = new ArrayList<Map<String, ParameterAssignment>>();
175 		for (int i = 0; i < projection.getGenerations(); i++) {
176 			genDepParameters.add(new HashMap<String, ParameterAssignment>());
177 		}
178 
179 		for (Entry<ParameterInstance, ParameterAssignment> assignmentEntry : assignments
180 		    .entrySet()) {
181 			if (assignmentEntry.getKey().getParameter().isGenerationDependent()) {
182 				genDepParameters.get(assignmentEntry.getKey().getGeneration()).put(
183 				    assignmentEntry.getKey().getParameter().getName(),
184 				    assignmentEntry.getValue());
185 			} else {
186 				genIndepParameters.put(assignmentEntry.getKey().getParameter()
187 				    .getName(), assignmentEntry.getValue());
188 			}
189 		}
190 
191 		return generatorResults;
192 	}
193 
194 	/**
195 	 * Retrieve the value for a generation-independent parameter.
196 	 * 
197 	 * @param parameter
198 	 *          the parameter for which the value shall be retrieved
199 	 * 
200 	 * @return value for the given parameter
201 	 */
202 	protected Matrix2D getGenIndepParameter(Parameter parameter) {
203 		ParameterAssignment parameterAssignment = genIndepParameters.get(parameter
204 		    .getName());
205 		return DeviationCalculator.calculateAssignmentDeviation(
206 		    parameterAssignment, random);
207 	}
208 
209 	/**
210 	 * Retrieve the value for a generation-dependent parameter.
211 	 * 
212 	 * @param parameter
213 	 *          the parameter for which the value shall be retrieved
214 	 * @param generation
215 	 *          the generation of the parameter
216 	 * @return value for the given parameter
217 	 */
218 	protected Matrix2D getGenDepParameter(Parameter parameter, int generation) {
219 		ParameterAssignment parameterAssignment = genDepParameters.get(generation)
220 		    .get(parameter.getName());
221 		return DeviationCalculator.calculateAssignmentDeviation(
222 		    parameterAssignment, random);
223 	}
224 
225 	/**
226 	 * Calculates the first generation of emigrants.
227 	 * 
228 	 * @param experimentSummary
229 	 *          experiment summary to be filled with the results
230 	 * @param years
231 	 *          the number of years for which shall be predicted
232 	 */
233 	void calculateFirstEmigrantPopulation(ExecutionSummary experimentSummary,
234 	    int years) {
235 		MigParameters parameters = new MigParameters(years,
236 		    projection.getMaximumAge());
237 		parameters.setMigrantsXm(getGenIndepParameter(Parameters.EMIGRANTS_M));
238 		parameters.setMigrantsXf(getGenIndepParameter(Parameters.EMIGRANTS_F));
239 		setupBasicEmigrantParameters(parameters, 0);
240 		MigPopulation migPopulation = new MigPopulation();
241 		experimentSummary.setFirstEmigrantParameters(parameters);
242 		experimentSummary.addEmigrantResult(migPopulation
243 		    .calculatePopulation(parameters));
244 	}
245 
246 	/**
247 	 * Calculates the first generation of immigrants.
248 	 * 
249 	 * @param experimentSummary
250 	 *          experiment summary to be filled with the results
251 	 * @param years
252 	 *          the number of years for which shall be predicted
253 	 */
254 	void calculateFirstImmigrantPopulation(ExecutionSummary experimentSummary,
255 	    int years) {
256 		MigParameters immigrantsParameters = new MigParameters(years,
257 		    projection.getMaximumAge());
258 		immigrantsParameters
259 		    .setMigrantsXm(getGenIndepParameter(Parameters.IMMIG_M));
260 		immigrantsParameters
261 		    .setMigrantsXf(getGenIndepParameter(Parameters.IMMIG_F));
262 		setupBasicImmigrantParameters(immigrantsParameters, 0);
263 
264 		MigPopulation migPopulation = new MigPopulation();
265 		experimentSummary.setFirstImmigrantParameters(immigrantsParameters);
266 		experimentSummary.addImmigrantResult(migPopulation
267 		    .calculatePopulation(immigrantsParameters));
268 	}
269 
270 	/**
271 	 * Calculates a child population of the emigrants sub-population.
272 	 * 
273 	 * @param experimentSummary
274 	 *          experiment summary to be filled with the results
275 	 * @param generation
276 	 *          the generation of the child population
277 	 * @param years
278 	 *          the number of years for which shall be predicted
279 	 */
280 	void calculateEmigrantChildPopulation(ExecutionSummary experimentSummary,
281 	    int generation, int years) {
282 
283 		MigChildParameters parameters = new MigChildParameters(years,
284 		    projection.getMaximumAge());
285 		parameters.setOldFertX((generation == 1) ? experimentSummary
286 		    .getFirstEmigrantParameters().getFertX() : experimentSummary
287 		    .getEmigrantParameters().get(generation - 2).getFertX());
288 		parameters.setOldMeanXf(experimentSummary.getEmigrantResults()
289 		    .get(generation - 1).getMeanXf());
290 		setupBasicEmigrantParameters(parameters, generation);
291 
292 		MigChildPopulation migChildPopulation = new MigChildPopulation();
293 		experimentSummary.addEmigrantParameters(parameters);
294 		experimentSummary.addEmigrantResult(migChildPopulation
295 		    .calculatePopulation(parameters));
296 	}
297 
298 	/**
299 	 * Calculates a child population of the immigrants sub-population.
300 	 * 
301 	 * @param experimentSummary
302 	 *          experiment summary to be filled with the results
303 	 * @param generation
304 	 *          the generation of the child population
305 	 * @param years
306 	 *          the number of years for which shall be predicted
307 	 */
308 	void calculateImmigrantChildPopulation(ExecutionSummary experimentSummary,
309 	    int generation, int years) {
310 
311 		MigChildParameters parameters = new MigChildParameters(years,
312 		    projection.getMaximumAge());
313 		parameters.setOldFertX((generation == 1) ? experimentSummary
314 		    .getFirstImmigrantParameters().getFertX() : experimentSummary
315 		    .getImmigrantParameters().get(generation - 2).getFertX());
316 		parameters.setOldMeanXf(experimentSummary.getImmigrantResults()
317 		    .get(generation - 1).getMeanXf());
318 		setupBasicImmigrantParameters(parameters, generation);
319 
320 		MigChildPopulation migChildPopulation = new MigChildPopulation();
321 		experimentSummary.addImmigrantParameter(parameters);
322 		experimentSummary.addImmigrantResult(migChildPopulation
323 		    .calculatePopulation(parameters));
324 	}
325 
326 	/**
327 	 * Creates basic native parameters.
328 	 * 
329 	 * @param years
330 	 *          number of years for which shall be predicted
331 	 * @return parameters to calculate native population prediction
332 	 */
333 	NativeParameters setupBasicNativeParameters(int years) {
334 		NativeParameters nativeParameters = new NativeParameters(years,
335 		    projection.getMaximumAge());
336 		nativeParameters.setMortXm(getGenIndepParameter(Parameters.NAT_MORT_X_M));
337 		nativeParameters.setMortXf(getGenIndepParameter(Parameters.NAT_MORT_X_F));
338 		nativeParameters
339 		    .setDeathProbInfant1halfMale(getGenIndepParameter(Parameters.NAT_DEATHPROB_INFANT_1STHALF_M));
340 		nativeParameters
341 		    .setDeathProbInfant1halfFemale(getGenIndepParameter(Parameters.NAT_DEATHPROB_INFANT_1STHALF_F));
342 		nativeParameters
343 		    .setSurviveProbO100m(getGenIndepParameter(Parameters.NAT_SURV_PROB_O100_M));
344 		nativeParameters
345 		    .setSurviveProbO100f(getGenIndepParameter(Parameters.NAT_SURV_PROB_O100_F));
346 		nativeParameters.setFertX(getGenIndepParameter(Parameters.NAT_FERT));
347 		nativeParameters
348 		    .setPEndSYm(getGenIndepParameter(Parameters.NAT_P_END_SY_M));
349 		nativeParameters
350 		    .setPEndSYf(getGenIndepParameter(Parameters.NAT_P_END_SY_F));
351 		nativeParameters
352 		    .setMaleRateLiveBirth(getGenIndepParameter(Parameters.NAT_PROP_LIVEBIRTH_M));
353 		return nativeParameters;
354 	}
355 
356 	/**
357 	 * Sets up immigrant parameters.
358 	 * 
359 	 * @param parameters
360 	 *          basic parameters (to be filled)
361 	 * @param generation
362 	 *          the generation for which the parameters should be set
363 	 */
364 	void setupBasicImmigrantParameters(BasicParameters parameters, int generation) {
365 		parameters.setDeathProbInfant1halfFemale(getGenDepParameter(
366 		    Parameters.IMMIG_DEATHPROB_INFANT_1STHALF_F, generation));
367 		parameters.setDeathProbInfant1halfMale(getGenDepParameter(
368 		    Parameters.IMMIG_DEATHPROB_INFANT_1STHALF_M, generation));
369 		parameters.setFertX(getGenDepParameter(Parameters.IMMIG_FERT, generation));
370 		parameters.setMortXf(getGenDepParameter(Parameters.IMMIG_MORT_X_F,
371 		    generation));
372 		parameters.setMortXm(getGenDepParameter(Parameters.IMMIG_MORT_X_M,
373 		    generation));
374 		parameters.setSurviveProbO100f(getGenDepParameter(
375 		    Parameters.IMMIG_SURV_PROB_O100_F, generation));
376 		parameters.setSurviveProbO100m(getGenDepParameter(
377 		    Parameters.IMMIG_SURV_PROB_O100_M, generation));
378 		parameters.setMaleRateLiveBirth(getGenDepParameter(
379 		    Parameters.IMMIG_PROP_LIVEBIRTH_M, generation));
380 	}
381 
382 	/**
383 	 * Sets up emigrant parameters.
384 	 * 
385 	 * @param parameters
386 	 *          the basic parameters (to be filled)
387 	 * @param generation
388 	 *          the generation for which the parameters should be set
389 	 */
390 	void setupBasicEmigrantParameters(BasicParameters parameters, int generation) {
391 		parameters.setDeathProbInfant1halfFemale(getGenDepParameter(
392 		    Parameters.EMIG_DEATHPROB_INFANT_1STHALF_F, generation));
393 		parameters.setDeathProbInfant1halfMale(getGenDepParameter(
394 		    Parameters.EMIG_DEATHPROB_INFANT_1STHALF_M, generation));
395 		parameters.setFertX(getGenDepParameter(Parameters.EMIG_FERT, generation));
396 		parameters.setMortXf(getGenDepParameter(Parameters.EMIG_MORT_X_F,
397 		    generation));
398 		parameters.setMortXm(getGenDepParameter(Parameters.EMIG_MORT_X_M,
399 		    generation));
400 		parameters.setSurviveProbO100f(getGenDepParameter(
401 		    Parameters.EMIG_SURV_PROB_O100_F, generation));
402 		parameters.setSurviveProbO100m(getGenDepParameter(
403 		    Parameters.EMIG_SURV_PROB_O100_M, generation));
404 		parameters.setMaleRateLiveBirth(getGenDepParameter(
405 		    Parameters.EMIG_PROP_LIVEBIRTH_M, generation));
406 	}
407 
408 }