1 | package de.uka.ipd.sdq.dsexplore.opt4j.archive; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.LinkedList; |
5 | import java.util.List; |
6 | |
7 | import org.apache.log4j.Logger; |
8 | import org.opt4j.config.Task; |
9 | import org.opt4j.core.Individual; |
10 | import org.opt4j.core.IndividualCollection; |
11 | import org.opt4j.core.IndividualCollectionListener; |
12 | import org.opt4j.core.Population; |
13 | |
14 | import com.google.inject.Inject; |
15 | |
16 | import de.uka.ipd.sdq.dsexplore.analysis.PCMPhenotype; |
17 | import de.uka.ipd.sdq.dsexplore.helper.FilterParetoOptimalIndividuals; |
18 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividual; |
19 | |
20 | |
21 | /** |
22 | * Stores all individuals ever added to the tracked population |
23 | * |
24 | * This is an {@link IndividualCollectionListener} that listens on the |
25 | * {@link Population} instance from the Opt4J {@link Task}. |
26 | * |
27 | * Additionally, a set Pareto-optimal candidates is maintained that can be retrieved |
28 | * by {@link PopulationTracker#getParetoOptimalIndividuals()}. |
29 | * |
30 | * @author Anne |
31 | * |
32 | */ |
33 | public class PopulationTracker implements |
34 | IndividualCollectionListener { |
35 | |
36 | private List<DSEIndividual> individuals = new LinkedList<DSEIndividual>(); |
37 | |
38 | /** Logger for log4j. */ |
39 | private static Logger logger = |
40 | Logger.getLogger("de.uka.ipd.sdq.dsexplore.opt4j.archive.DSEListener"); |
41 | |
42 | |
43 | @Inject |
44 | public PopulationTracker(Population population){ |
45 | super(); |
46 | population.addListener(this); |
47 | } |
48 | |
49 | @Override |
50 | public void individualAdded(IndividualCollection collection, |
51 | Individual individual) { |
52 | |
53 | if (individual instanceof DSEIndividual){ |
54 | //This itselfs stores all |
55 | this.individuals.add((DSEIndividual)individual); |
56 | } else { |
57 | logger.error("It has been attempted to add an individual that is not a DSEIndividual to the archive. Fix your implementation."); |
58 | } |
59 | } |
60 | |
61 | public List<DSEIndividual> getIndividuals(){ |
62 | return this.individuals; |
63 | } |
64 | |
65 | @Override |
66 | public void individualRemoved(IndividualCollection collection, |
67 | Individual individual) { |
68 | // do nothing |
69 | |
70 | } |
71 | |
72 | /** |
73 | * Careful: This can 20 minutes to calculate if you have over 1000 candidates in the {@link PopulationTracker}. |
74 | * @return |
75 | */ |
76 | public List<DSEIndividual> getParetoOptimalIndividuals(){ |
77 | |
78 | List<DSEIndividual> optimalList = new ArrayList<DSEIndividual>(this.individuals.size()); |
79 | |
80 | optimalList.addAll(this.individuals); |
81 | |
82 | return FilterParetoOptimalIndividuals.filterPareto(optimalList); |
83 | } |
84 | |
85 | /** |
86 | * Returns the individual for the given phenotype or null if none can be found. |
87 | * @param pheno |
88 | * @return the individual or null |
89 | */ |
90 | public DSEIndividual getIndividualForPhenotype(PCMPhenotype pheno){ |
91 | for (DSEIndividual i : this.individuals) { |
92 | if (i.getPhenotype() != null && i.getPhenotype() == pheno){ |
93 | return i; |
94 | } |
95 | } |
96 | return null; |
97 | } |
98 | |
99 | public int size() { |
100 | return this.individuals.size(); |
101 | } |
102 | |
103 | /** |
104 | * Has to be an evaluated individual. |
105 | * @param individual |
106 | * @throws RuntimeException if the individual is null or not yet evaluated (i.e. individual.isEvaluated returns false). |
107 | */ |
108 | public boolean addIndividualsManually(DSEIndividual individual){ |
109 | if (individual != null && individual.isEvaluated()){ |
110 | return this.individuals.add(individual); |
111 | } else { |
112 | throw new RuntimeException("Only evaluated candidates may be added to PopulationTracker!"); |
113 | } |
114 | } |
115 | |
116 | } |