View Javadoc
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 }