| 1 | package de.uka.ipd.sdq.dsexplore.opt4j.representation; |
| 2 | |
| 3 | import java.util.Set; |
| 4 | |
| 5 | import org.apache.log4j.Logger; |
| 6 | import org.opt4j.core.problem.Genotype; |
| 7 | import org.opt4j.core.Individual; |
| 8 | import org.opt4j.core.IndividualStateListener; |
| 9 | import org.opt4j.core.Objectives; |
| 10 | |
| 11 | import de.uka.ipd.sdq.dsexplore.opt4j.genotype.DesignDecisionGenotype; |
| 12 | import de.uka.ipd.sdq.dsexplore.opt4j.start.Opt4JStarter; |
| 13 | import de.uka.ipd.sdq.pcm.designdecision.DecisionSpace; |
| 14 | |
| 15 | |
| 16 | public class DSEIndividual extends Individual { |
| 17 | |
| 18 | |
| 19 | private DecisionSpace problem; |
| 20 | |
| 21 | public DSEIndividual(DecisionSpace problem){ |
| 22 | this.problem = problem; |
| 23 | } |
| 24 | |
| 25 | protected DSEIndividual(){ |
| 26 | this.problem = Opt4JStarter.getProblem().getEMFProblem(); |
| 27 | } |
| 28 | |
| 29 | /** Logger for log4j. */ |
| 30 | private static Logger logger = |
| 31 | Logger.getLogger("de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividual"); |
| 32 | |
| 33 | |
| 34 | @Override |
| 35 | public DesignDecisionGenotype getGenotype(){ |
| 36 | return (DesignDecisionGenotype)super.getGenotype(); |
| 37 | } |
| 38 | |
| 39 | |
| 40 | |
| 41 | /** |
| 42 | * Checks the equality of this and o. |
| 43 | * Returns false if o is not a DSEIndividual or subtype. |
| 44 | * If both this and o are not genotyped, super.equals(o) is called. |
| 45 | * Returns false if either this or o (exclusive) are not genotyped. |
| 46 | * Finally, if none of the above matches, this method returns whether the |
| 47 | * genotype strings of o and this are equal. |
| 48 | * @param o The other object |
| 49 | * @return true if o and this are equal as defined above. |
| 50 | */ |
| 51 | @Override |
| 52 | public boolean equals(Object o){ |
| 53 | if (o == this){ |
| 54 | return true; |
| 55 | } |
| 56 | if (!(o instanceof DSEIndividual)){ |
| 57 | return false; |
| 58 | } else { |
| 59 | DSEIndividual other = (DSEIndividual)o; |
| 60 | String otherGenotypeString = other.getGenotypeString(); |
| 61 | String myGenotypeString = this.getGenotypeString(); |
| 62 | if (otherGenotypeString == null && myGenotypeString == null){ |
| 63 | return super.equals(other); |
| 64 | } else if (otherGenotypeString == null || myGenotypeString == null){ |
| 65 | // I need to say we are not equal and cannot ask my super type, |
| 66 | // because of the hash code equivalence rule. |
| 67 | // If the other does not have a genotype string, but I do, and |
| 68 | // my super type says we are equal, then there is a conflict |
| 69 | // because the hash codes are not equal. |
| 70 | return false; |
| 71 | } else { |
| 72 | return otherGenotypeString.equals(myGenotypeString); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | |
| 77 | } |
| 78 | |
| 79 | /** |
| 80 | * |
| 81 | * @return may be null if this individual does not have a genotype yet. |
| 82 | */ |
| 83 | public String getGenotypeString() { |
| 84 | if (genotype instanceof DesignDecisionGenotype){ |
| 85 | String genotypeString = DSEDecoder.getGenotypeString((DesignDecisionGenotype)genotype); |
| 86 | return genotypeString; |
| 87 | } else { |
| 88 | throw new RuntimeException("DSEIndividual cannot handle arbitrary genotypes yet, fix the code"); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * {@inheritDoc} |
| 94 | */ |
| 95 | @Override |
| 96 | public void setIndividualStatusListeners( |
| 97 | Set<IndividualStateListener> individualStateListeners) { |
| 98 | super.setIndividualStatusListeners(individualStateListeners); |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * Returns the hash code of the getGenotypeString() string if this individual |
| 103 | * is already genotyped. Returns super.hashCode() if this inidividual is not |
| 104 | * yet genotyped. |
| 105 | */ |
| 106 | @Override |
| 107 | public int hashCode(){ |
| 108 | if (this.genotype != null){ |
| 109 | return this.getGenotypeString().hashCode(); |
| 110 | } else { |
| 111 | return super.hashCode(); |
| 112 | } |
| 113 | |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Returns the objectives. |
| 118 | * |
| 119 | * @return the objectives |
| 120 | */ |
| 121 | @Override |
| 122 | public DSEObjectives getObjectives() { |
| 123 | return (DSEObjectives)super.getObjectives(); |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Sets the objectives. They have to be instances of type {@link DSEObjective}, or |
| 128 | * an {@link IllegalArgumentException} is thrown |
| 129 | * |
| 130 | * @param objectives |
| 131 | * the objectives to be set |
| 132 | * @throws IllegalArgumentException if objectives are not of type |
| 133 | * {@link DSEObjective}. |
| 134 | */ |
| 135 | @Override |
| 136 | public void setObjectives(Objectives objectives) { |
| 137 | if (! (objectives instanceof DSEObjectives)){ |
| 138 | String error = "DSEIndividual only supports DSEObjectives to contain the analysis results. Contact developers."; |
| 139 | logger.error(error); |
| 140 | throw new IllegalArgumentException(error); |
| 141 | } |
| 142 | super.setObjectives(objectives); |
| 143 | } |
| 144 | |
| 145 | public String getID() { |
| 146 | return this.getGenotypeString(); |
| 147 | } |
| 148 | |
| 149 | public long getNumericID() { |
| 150 | return this.getGenotype().getNumericID(); |
| 151 | } |
| 152 | |
| 153 | public DecisionSpace getProblem(){ |
| 154 | return this.problem; |
| 155 | } |
| 156 | |
| 157 | } |