1 /**
2 * @(#)Chromosome.java
3 * Copyright (C) 2008-2011 delhezi.com
4 *
5 * This class is released under the:
6 * GNU Lesser General Public License (LGPL) version 3 or later.
7 * http://www.gnu.org/copyleft/lesser.html
8 */
9 package com.delhezi.ga;
10
11 import com.delhezi.ga.exception.GeneticAlgorithmException;
12 import com.delhezi.ga.mutation.IMutation;
13 import java.util.logging.Logger;
14
15 /**
16 * <code>Chromosome</code>: Klasa chromosomu.
17 * @param <GENE_TYPE> typ obiektu charakteryzujący gen np.: Integer, Double,
18 * lub objekt klasy com.delhezi.genes.*.
19 * Uwaga; Genami nie mogą być typy proste np. int, double.
20 * @version 1.0 2009-06-10
21 * @author <a href="mailto:wojciech.wolszczak@delhezi.com">
22 * Wojciech Wolszczak</a>
23 */
24 public class Chromosome<GENE_TYPE> implements Cloneable,
25 Comparable<Chromosome<GENE_TYPE>> {
26 /** Logger object. */
27 private static final Logger LOGGER =
28 Logger.getLogger(Chromosome.class.getName());
29
30 /** Delhezi Error Code. */
31 private static final String DERC = "1-1-";
32
33 /**
34 * Konstruktor.
35 * @param genes Tablica genów.
36 * @param chromosomeProperties Referencja do obiektu przechowującego
37 * parametry wspólne dla wszystkich chromosomów w ramach jednej
38 * instancji populacji.
39 * @since 1.0
40 */
41 public Chromosome(final GENE_TYPE[] genes,
42 final ChromosomeProperties chromosomeProperties) {
43 //W konstruktorze i metodzie clone inicjuj bezposrednio
44 //wartości zmiennych lub wywołuj tylko metody final.
45 this.genes = genes;
46 this.chProperties = chromosomeProperties;
47 this.changed = true;
48 }
49
50 /**
51 * Porównanie dwóch chromosomów;
52 * if x.compareTo(y) == 1 to x jest lepszy niż y.
53 * Wykorzystywane przy sortowaniu.
54 * UWAGA. LISTA POSORTOWANA JEST W ODWROTNEJ KOLEJNOŚCI
55 * CHYAB JAKIŚ BŁĄD W JAVA
56 * @param chromosome Chromosom do porównania.
57 * @return 0 jeśli wartości wskażników przystosowania chromosomów
58 * porównywanych są równe, 1 lub -1 jeśli jeden większy od drugiego.
59 */
60 public final int compareTo(final Chromosome<GENE_TYPE> chromosome) {
61 try {
62 if (this.chProperties.getFitnessFunction().isMaximisation() == true) {
63 if (this.getFitness() > chromosome.getFitness()) {
64 return 1;
65 }
66 if (this.getFitness() < chromosome.getFitness()) {
67 return -1;
68 }
69 } else {
70 if (this.getFitness() < chromosome.getFitness()) {
71 return 1;
72 }
73 if (this.getFitness() > chromosome.getFitness()) {
74 return -1;
75 }
76 }
77 } catch (GeneticAlgorithmException e) {
78 }
79 return 0; //Chromosomy są równe.
80 }
81
82
83 /**
84 * Zwraca parametr określający maksymalizację/minimalizację funkcji
85 * celu.
86 * @return true - maksymalizacja funkcji celu (najlepszym jest osobnik o
87 * najwiekszej wartości wskaźnika przystosowania)
88 * false - minimalizacja funkcji celu (najlepszym jest osobnik o
89 * najmniejszej wartości wskaźnika przystosowania)
90 */
91 public final boolean isFitnessMaximisation() {
92 return this.chProperties.getFitnessFunction().isMaximisation();
93 }
94
95
96 /**
97 * Mutacja.
98 * @param mutation Funkcja mutacji
99 * @since 1.0
100 */
101 public final void mutation(final IMutation mutation) {
102 mutation.mutation(this);
103 //this.changed=true; Infomacja o zmianie chromosomu
104 //ustawiana w funkcji mutation.mutation(..)
105 }
106
107 /**
108 * Zwraca ilość genów w chromosomie.
109 * @return Ilość genów w chromosomie.
110 * @since 1.0
111 */
112 public final int size() {
113 if (this.genes == null) {
114 return 0;
115 } else {
116 return this.genes.length;
117 }
118 }
119
120 /**
121 * Wylicza i zwraca wartość wskaźnika przystosowania.
122 * @return Wartość wskaźnika przystosowania.
123 * @throws GeneticAlgorithmException xxx
124 * @since 1.0
125 */
126 public final double getFitness() throws GeneticAlgorithmException {
127 if (this.changed == true) {
128 this.fitness = this.chProperties.getFitnessFunction()
129 .calculateFitness(genes);
130 this.changed = false;
131 }
132 return this.fitness;
133 }
134
135 /**
136 * Funkcja zmienia status chromosomu na "zmodyfikowany";
137 * Status chromosomu należy zmienić po operacjach:
138 * - bezpośrednio na tabeli genów po uzyskaniu referencji
139 * do tabeli, jeśli zmiana odbyła się z pominięciem
140 * funkcji setGenes() lub setGene();
141 * - przy zmianie referencji do IMutation, jeśli zmiana
142 * odbyła się z pominięciem funkcji setMutation();
143 * - przy zmianie referencji do IFitnessFunction, jeśli zmiana
144 * odbyła się z pominięciem funkcji setFitnessFunction().
145 */
146 public final void changed() {
147 this.changed = true;
148 }
149
150 /**
151 * Zwraca gen ze wskazanej pozycji (locus).
152 * @param locus Pozycja genu (locus).
153 * @return Gen określonego typu.
154 *
155 * @since 1.0
156 */
157 public final GENE_TYPE getGene(final int locus) {
158 return this.genes[locus];
159 }
160
161 /**
162 * Wstawia gen na wskazaną pozycję (locus).
163 * @param locus Locus pod którym ma być wstawiony gen.
164 * @param gene Wstawiany gen określonego typu.
165 *
166 * @since 1.0
167 */
168 public final void setGene(final int locus, final GENE_TYPE gene) {
169 this.genes[locus] = gene;
170 this.changed = true;
171 }
172
173 /**
174 * Zwraca referencję do tablicy genów;
175 * Uwaga;
176 * Zwracana jest referencja do tablicy a nie jej kopia;
177 * Jeśli za pomocą otrzymanej referencji dojdzie do modyfikacji wartości
178 * tablicy należy wykonać funkcję changed() klasy Chromosome w celu
179 * ponownego wyznaczenia wskaźnika przystosowania chromosomu.
180 * @return Referencja do tablicy genów.
181 *
182 * @since 1.0
183 */
184 public final GENE_TYPE[] getGenes() {
185 return this.genes;
186 }
187
188 /**
189 * Wstawia referencję do tablicy genów;
190 * Uwaga;
191 * Wstawiana jest referencja do tablicy a nie jej kopia;
192 * Jeśli po wstawieniu referencji dojdzie do modyfikacji watrości
193 * tablicy należy wykonać funkcję changed() klasy Chromosome w celu
194 * ponownego wyznaczenia wskaźnika przystosowania chromosomu.
195 * @param genes Referencja do tablicy genów.
196 *
197 * @since 1.0
198 */
199 public final void setGenes(final GENE_TYPE[] genes) {
200 this.genes = genes;
201 this.changed = true;
202 }
203
204 /**
205 * Kopiuje chromosom. Ze względu na konieczność skopiowania tablicy
206 * genów wymagane jest "głębokie kopiowanie";
207 *
208 * SPITOLONA FUNCKJA WYMAGA UOGÓLNIENIA DO PRZERÓBKI;
209 *
210 * @return Głęboka kopia chromosomu.
211 * @since 1.0
212 */
213 @Override
214 public final Chromosome<GENE_TYPE> clone() {
215 try {
216 //super.clone() - Metoda klasy Object - zapewnia płytkie kopiowanie
217 //klasy, kopiuje objekt bit po bicie (kopiuje referencje).
218 //UWAGA w przypadku kiedy klasa zawiera referencje do objektów
219 //ZMIENIALNYCH (np. Date, lub w przypadku tablicy skopiuje się
220 //tylko refencja do tablicy) bo kopiowane są referecnje
221 //do objektów.
222 //W przypadku kiedy klasa zawiera referencje do obiektów
223 //NIEZMIENIALNYCH typu String lub Integer nie ma to znaczenia.
224 //W przypadku typów prostych - kopiowane sa wartości.
225 Chromosome result = (Chromosome<GENE_TYPE>) super.clone();
226
227 //Wsytarczy płytkie kopiowanie bo tablica chromosomów jest pusta.
228 if (genes.length < 1) {
229 return result;
230 }
231
232 //Wymagane GLEBOKIE kopiowanie.
233 //Ze względu na możliwe mutacje objekt gene jest ZMIENIALY.
234 if (genes[0] instanceof Cloneable) {
235 result.genes = new Object[genes.length];
236 for (int i = 0; i < genes.length; i++) {
237 //if(((String) genes.getClass().getName()).equals(
238 //"[Lcom.delhezi.ga.genes.KlasaObjektu;"))
239 ////result.genes[i]=((KlasaObjektu) genes[i]).clone();
240
241 //TU TRZEBA DOPISAĆ KOD
242 }
243 } else {
244 result.genes.clone(); //Zakładamy, że elementami tablicy są
245 //objekty NIEZMIENIALNE.
246 //Wystarczy tylko skopiować referencje do nich.
247 }
248
249 return result;
250 } catch (CloneNotSupportedException ex) {
251 throw new AssertionError(); //Błąd JVM.
252 //Nie powinien się zdarzyć.
253 }
254 }
255
256 /**
257 * String charakteryzujący chromosom.
258 * @return String charakteryzujący chromosom.
259 * @since 1.0
260 */
261 @Override
262 public final String toString() {
263 String str = "CHROMOSOME [fitness=" + this.fitness
264 + ", size=" + this.size() + ", genes:";
265 for (int i = 0; i < this.size(); i++) {
266 str += "[" + this.genes[i].toString() + "]";
267 }
268 str += "]";
269 return str;
270 }
271
272 /** Wskaźnik przystosowania. */
273 private double fitness;
274
275 /** Tablica genów składająca się na pojedynczy chromosom. */
276 private GENE_TYPE[] genes;
277
278 /** Parametr określający, czy geny w chromosomie zostały zmienione. */
279 private boolean changed = true;
280
281 /**
282 * Referencja do obiektu przechowującego parametry wspólne dla
283 * wszystkich chromosomów w ramach jednej instancji populacji.
284 */
285 private ChromosomeProperties chProperties;
286 }