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.pppm;
17  
18  import java.util.ArrayList;
19  import java.util.Calendar;
20  import java.util.Collections;
21  import java.util.Comparator;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.jamesii.core.model.Model;
27  
28  import p3j.pppm.parameters.Parameter;
29  import p3j.pppm.parameters.ParameterAssignment;
30  import p3j.pppm.parameters.ParameterAssignmentSet;
31  import p3j.pppm.parameters.ParameterInstance;
32  import p3j.pppm.sets.Set;
33  import p3j.pppm.sets.SetType;
34  import p3j.simulation.calculation.deterministic.Constants;
35  
36  /**
37   * Stores a complete configuration for the PPPM, containing {@link Set} objects
38   * associated with different {@link SetType} instances. Such a scenario can be
39   * used for forecasting, it comprises all information necessary for basic
40   * reproducibility of the Monte-Carlo-simulation. Each scenario holds a list of
41   * all {@link ParameterInstance} objects that need an assignment. Disjunct
42   * subsets of this list will be managed by {@link SetType}.
43   * 
44   * TODO: Store RNG seed to ensure exact reproducibility.
45   * 
46   * Created on January 22, 2007
47   * 
48   * @author Christina Bohk
49   * @author Roland Ewald
50   */
51  public class ProjectionModel extends Model implements IProjectionModel {
52  
53    /** Serialization ID. */
54    private static final long serialVersionUID = -1984182268566219449L;
55  
56    /** The ID of this scenario. */
57    private int id;
58  
59    /** Name of the scenario. */
60    private String name;
61  
62    /** Description of the scenario. */
63    private String description;
64  
65    /**
66     * Default Settype. This will always be there and contain all parameters that
67     * do not belong to specific Settypes.
68     */
69    private SetType defaultType = new SetType("Default Settype",
70        "This is the default Settype.");
71  
72    /** Default set. */
73    private Set defaultSet = defaultType.createSet("Default Set",
74        "This is the default set.", 1);
75  
76    /** List of user defined Settypes. */
77    private List<SetType> userDefinedTypes = new ArrayList<SetType>();
78  
79    /** List of all parameter instances available in this scenario. */
80    private List<ParameterInstance> allParameterInstances = new ArrayList<ParameterInstance>();
81  
82    /** Mapping {@link ParameterInstance} to {@link SetType} that manages it. */
83    private Map<ParameterInstance, SetType> instanceSetTypes = new HashMap<ParameterInstance, SetType>();
84  
85    /** The sub-population model that is assumed. */
86    private SubPopulationModel subPopulationModel = PPPModelFactory.DEFAULT_SUBPOPULATION_MODEL;
87  
88    /**
89     * Number of generations to be taken into account. Is initially set to
90     * {@link Constants#DEFAULT_NUM_GENERATIONS}.
91     */
92    private int generations = Constants.DEFAULT_NUM_GENERATIONS;
93  
94    /**
95     * Number of years to be predicted. Is initially set to
96     * {@link Constants#DEFAULT_NUM_YEARS}.
97     */
98    private int years = Constants.DEFAULT_NUM_YEARS;
99  
100   /**
101    * Maximum age of individual. Is initially set to
102    * {@link Constants#DEFAULT_MAXIMUM_AGE}.
103    */
104   private int maximumAge = Constants.DEFAULT_MAXIMUM_AGE;
105 
106   /** The jump-off year. */
107   private int jumpOffYear = Calendar.getInstance().get(Calendar.YEAR);
108 
109   /**
110    * Constructor for bean compatibility (do NOT use manually!).
111    */
112   public ProjectionModel() {
113   }
114 
115   /**
116    * Default constructor.
117    * 
118    * @param scenName
119    *          name of the scenario
120    * @param desc
121    *          description of the scenario
122    * @param numOfGenerations
123    *          number of generations to be considered
124    * @param predYears
125    *          number of years to be predicted
126    * @param maxAge
127    *          maximum age to be considered
128    * @param jumpOffYear
129    *          the jump off year
130    * @param subPopModel
131    *          the model of sub-populations
132    */
133   public ProjectionModel(String scenName, String desc, int numOfGenerations,
134       int predYears, int maxAge, int jumpOffYear, SubPopulationModel subPopModel) {
135     this.name = scenName;
136     this.description = desc;
137     this.generations = numOfGenerations;
138     this.years = predYears;
139     this.maximumAge = maxAge;
140     this.jumpOffYear = jumpOffYear;
141     this.subPopulationModel = subPopModel;
142   }
143 
144   /**
145    * Initializes projection. Needs to be called after
146    * {@link #allParameterInstances} has been initialized.
147    */
148   @Override
149   public void init() {
150     for (int i = 0; i < allParameterInstances.size(); i++) {
151       instanceSetTypes.put(allParameterInstances.get(i), defaultType);
152       defaultType.addInstance(allParameterInstances.get(i));
153     }
154   }
155 
156   /**
157    * Defines a new Settype for this scenario.
158    * 
159    * @param stName
160    *          name of the Settype
161    * @param stDesc
162    *          description of the Settype
163    * 
164    * @return newly defined Settype for this scenario
165    */
166   public SetType createSetType(String stName, String stDesc) {
167     SetType setType = new SetType(stName, stDesc);
168     userDefinedTypes.add(setType);
169     return setType;
170   }
171 
172   /**
173    * Get all {@link ParameterInstance} objects that still belong to the default
174    * {@link SetType}. These have not yet been assigned to any custom
175    * {@link SetType}.
176    * 
177    * @return list of all parameter instances that are not yet assigned to user
178    *         defined Settypes
179    */
180   public List<ParameterInstance> getUnassignedParameterInstances() {
181     return this.defaultType.getDefinedParameters();
182   }
183 
184   /**
185    * Assign a {@link ParameterInstance} to a specific {@link SetType}.
186    * 
187    * @param instance
188    *          the parameter instance to be assigned
189    * @param type
190    *          the {@link SetType} that shall manage the
191    *          {@link ParameterInstance} from now on
192    * @param migrate
193    *          flag to switch migration of existing assumption to new Settype
194    *          on/off
195    * 
196    * @return true, if parameter instance could be assigned (i.e., former set
197    *         type is default Settype), otherwise false
198    */
199   public boolean assignParameterInstance(ParameterInstance instance,
200       SetType type, boolean migrate) {
201 
202     if (type.equals(defaultType)) {
203       removeParameterInstanceAssignment(instance);
204     }
205 
206     SetType associatedSetType = instanceSetTypes.get(instance);
207 
208     if (!associatedSetType.equals(defaultType)) {
209       return false;
210     }
211 
212     type.addInstance(instance);
213     if (migrate) {
214       migrateAssignmentsFromDefaultType(instance, type);
215     }
216     defaultType.removeInstance(instance);
217     instanceSetTypes.put(instance, type);
218     return true;
219   }
220 
221   /**
222    * Migrate assignments from default type.
223    * 
224    * @param instance
225    *          the parameter instance of the assignments to be migrated
226    * @param newType
227    *          the destination Settype
228    */
229   private void migrateAssignmentsFromDefaultType(ParameterInstance instance,
230       SetType newType) {
231     ParameterAssignmentSet paramAssignmentSet = getDefaultSet()
232         .getParameterAssignments(instance);
233 
234     // Stop if there is nothing to migrate
235     if (paramAssignmentSet.getAssignments().isEmpty())
236       return;
237 
238     Set set = newType.getNumOfSets() == 0 ? newType.createSet(
239         "Migrated parameter assignments",
240         "Automatically created during Settype definition.", 0.0) : newType
241         .getSets().get(0);
242 
243     for (ParameterAssignment pa : paramAssignmentSet.getAssignments()) {
244       set.addParameterAssignment(pa);
245     }
246   }
247 
248   /**
249    * Removes a {@link ParameterInstance} from a certain {@link SetType}.
250    * 
251    * @param instance
252    *          the instance that should from now on be managed by the default
253    *          {@link SetType}
254    * 
255    * @return true, if instance could be removed from its Settype (i.e., if set
256    *         type is not default Settype)
257    */
258   public boolean removeParameterInstanceAssignment(ParameterInstance instance) {
259     SetType associatedSetType = instanceSetTypes.get(instance);
260 
261     if (associatedSetType.equals(defaultType)) {
262       return false;
263     }
264 
265     associatedSetType.removeInstance(instance);
266     defaultType.addInstance(instance);
267     instanceSetTypes.put(instance, defaultType);
268     return true;
269   }
270 
271   /**
272    * Retrieves a custom {@link SetType}.
273    * 
274    * @param index
275    *          index of the Settype
276    * 
277    * @return Settype with given index
278    */
279   public SetType getSetType(int index) {
280     return userDefinedTypes.get(index);
281   }
282 
283   /**
284    * Removes {@link SetType} with given index from scenario.
285    * 
286    * @param index
287    *          index of the Settype
288    * 
289    * @return true, if operation could be executed
290    */
291   public boolean removeSetType(int index) {
292     SetType removedSetType = userDefinedTypes.remove(index);
293 
294     if (removedSetType == null) {
295       return false;
296     }
297 
298     List<ParameterInstance> parameterInstances = new ArrayList<ParameterInstance>(
299         removedSetType.getDefinedParameters());
300     for (ParameterInstance instance : parameterInstances) {
301       removeParameterInstanceAssignment(instance);
302     }
303     return true;
304   }
305 
306   @Override
307   public List<SetType> getAllSetTypes() {
308     List<SetType> setTypes = new ArrayList<SetType>();
309     setTypes.add(defaultType);
310     setTypes.addAll(userDefinedTypes);
311     return setTypes;
312   }
313 
314   // Getters/Setter to ensure bean compatibility
315 
316   /**
317    * Gets the default set.
318    * 
319    * @return the default set
320    */
321   public Set getDefaultSet() {
322     return defaultSet;
323   }
324 
325   /**
326    * Sets the default set.
327    * 
328    * @param defaultSet
329    *          the new default set
330    */
331   public void setDefaultSet(Set defaultSet) {
332     this.defaultSet = defaultSet;
333   }
334 
335   /**
336    * Gets the default type.
337    * 
338    * @return the default type
339    */
340   public SetType getDefaultType() {
341     return defaultType;
342   }
343 
344   /**
345    * Sets the default type.
346    * 
347    * @param defaultType
348    *          the new default type
349    */
350   public void setDefaultType(SetType defaultType) {
351     this.defaultType = defaultType;
352   }
353 
354   /**
355    * Gets the default Settype.
356    * 
357    * @return the default Settype
358    */
359   public SetType getDefaultSetType() {
360     return defaultType;
361   }
362 
363   @Override
364   public int getGenerations() {
365     return generations;
366   }
367 
368   /**
369    * Sets the generations.
370    * 
371    * @param generations
372    *          the new generations
373    */
374   public void setGenerations(int generations) {
375     // TODO: Remove obsolete generations if necessary.
376     this.generations = generations;
377   }
378 
379   @Override
380   public int getMaximumAge() {
381     return maximumAge;
382   }
383 
384   /**
385    * Sets the maximum age.
386    * 
387    * @param maximumAge
388    *          the new maximum age
389    */
390   public void setMaximumAge(int maximumAge) {
391     // TODO: Adjust matrix size if necessary.
392     this.maximumAge = maximumAge;
393   }
394 
395   @Override
396   public int getYears() {
397     return years;
398   }
399 
400   /**
401    * Sets the years.
402    * 
403    * @param years
404    *          the new years
405    */
406   public void setYears(int years) {
407     // TODO: Adjust matrix size if necessary.
408     this.years = years;
409   }
410 
411   /**
412    * Gets the user defined types.
413    * 
414    * @return the user defined types
415    */
416   public List<SetType> getUserDefinedTypes() {
417     return userDefinedTypes;
418   }
419 
420   /**
421    * Sets the user defined types.
422    * 
423    * @param userDefinedTypes
424    *          the new user defined types
425    */
426   public void setUserDefinedTypes(List<SetType> userDefinedTypes) {
427     this.userDefinedTypes = userDefinedTypes;
428   }
429 
430   /**
431    * Gets the all parameter instances.
432    * 
433    * @return the all parameter instances
434    */
435   public List<ParameterInstance> getAllParameterInstances() {
436     return this.allParameterInstances;
437   }
438 
439   /**
440    * Sets the all parameter instances.
441    * 
442    * @param allParameterInstances
443    *          the new all parameter instances
444    */
445   public void setAllParameterInstances(
446       List<ParameterInstance> allParameterInstances) {
447     this.allParameterInstances = allParameterInstances;
448   }
449 
450   @Override
451   public Map<ParameterInstance, SetType> getInstanceSetTypes() {
452     return instanceSetTypes;
453   }
454 
455   /**
456    * Sets the instance Settypes.
457    * 
458    * @param instanceSetTypes
459    *          the instance Settypes
460    */
461   public void setInstanceSetTypes(
462       Map<ParameterInstance, SetType> instanceSetTypes) {
463     this.instanceSetTypes = instanceSetTypes;
464   }
465 
466   /**
467    * Removes the Settype.
468    * 
469    * @param setType
470    *          the Settype
471    * 
472    * @return true, if successful
473    */
474   public boolean removeSetType(SetType setType) {
475     return removeSetType(userDefinedTypes.indexOf(setType));
476   }
477 
478   /**
479    * Gets the number of (user-defined) of Settypes.
480    * 
481    * @return the number of Settypes
482    */
483   public int getNumOfSetTypes() {
484     return userDefinedTypes.size();
485   }
486 
487   /**
488    * Gets the id.
489    * 
490    * @return the id
491    */
492   public int getID() {
493     return id;
494   }
495 
496   /**
497    * Sets the id.
498    * 
499    * @param uniqueID
500    *          the new id
501    */
502   public void setID(int uniqueID) {
503     id = uniqueID;
504   }
505 
506   @Override
507   public String getName() {
508     return name;
509   }
510 
511   @Override
512   public void setName(String name) {
513     this.name = name;
514   }
515 
516   /**
517    * Gets the description.
518    * 
519    * @return the description
520    */
521   public String getDescription() {
522     return description;
523   }
524 
525   /**
526    * Sets the description.
527    * 
528    * @param description
529    *          the new description
530    */
531   public void setDescription(String description) {
532     this.description = description;
533   }
534 
535   /**
536    * Gets the number of age classes. Is calculated by adding 1 to
537    * {@link ProjectionModel#maximumAge}.
538    * 
539    * @return the number of age classes
540    */
541   public int getNumberOfAgeClasses() {
542     return maximumAge + 1;
543   }
544 
545   /**
546    * Gets the jump off year.
547    * 
548    * @return the jump off year
549    */
550   public int getJumpOffYear() {
551     return jumpOffYear;
552   }
553 
554   /**
555    * Sets the jump off year.
556    * 
557    * @param jumpOffYear
558    *          the new jump off year
559    */
560   public void setJumpOffYear(int jumpOffYear) {
561     this.jumpOffYear = jumpOffYear;
562   }
563 
564   /**
565    * Gets the sub-population model.
566    * 
567    * @return the sub-population model
568    */
569   @Override
570   public SubPopulationModel getSubPopulationModel() {
571     // For compatibility with old projections without a sub-population model:
572     if (subPopulationModel == null)
573       subPopulationModel = PPPModelFactory.createDefaultSubPopulationModel();
574     return subPopulationModel;
575   }
576 
577   /**
578    * Sets the sub-population model.
579    * 
580    * @param subPopulationModel
581    *          the new sub-population model
582    */
583   public void setSubPopulationModel(SubPopulationModel subPopulationModel) {
584     this.subPopulationModel = subPopulationModel;
585   }
586 
587   /**
588    * Counts the number of parameter assignments contained in this projection.
589    * 
590    * @return the number of parameter assignments
591    */
592   public int countNumberOfParameterAssignments() {
593     int numOfAssignments = 0;
594     for (SetType setType : getAllSetTypes())
595       for (Set set : setType.getSets())
596         for (ParameterAssignmentSet assignSet : set.getSetData().values())
597           numOfAssignments += assignSet.size();
598     return numOfAssignments;
599   }
600 
601   /**
602    * Filters all parameter instances from a given list by a given
603    * sub-population. The parameter instances in the new list are sorted by
604    * {@link Parameter#getSortingIndex()}.
605    * 
606    * @param originalInstances
607    *          the original list of parameter instances
608    * @param subPopulation
609    *          the sub population
610    * @return the parameter instances
611    */
612   public static List<ParameterInstance> filterParamInstancesBySubPopulation(
613       List<ParameterInstance> originalInstances, SubPopulation subPopulation) {
614     List<ParameterInstance> instances = new ArrayList<>();
615     for (ParameterInstance instance : originalInstances)
616       if (instance.getParameter().getName().startsWith(subPopulation.getName()))
617         instances.add(instance);
618     Collections.sort(instances, new Comparator<ParameterInstance>() {
619       @Override
620       public int compare(ParameterInstance p1, ParameterInstance p2) {
621         return Integer.compare(p1.getParameter().getSortingIndex(), p2
622             .getParameter().getSortingIndex());
623       }
624     });
625     return instances;
626   }
627 }