View Javadoc
1   /**
2    * @(#)InversionMutation.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.mutation;
10  
11  import com.delhezi.ga.Chromosome;
12  import java.util.Random;
13  //import java.util.logging.Logger;
14  
15  /**
16   * Klasa <code>InversionMutation</code>: Mutacja przez inwersję
17   * Inversion Mutation (IVM).
18   * @version 1.0 2009-06-10
19   * @author <a href="mailto:wojciech.wolszczak@delhezi.com">
20   * Wojciech Wolszczak</a>
21   */
22  public class InversionMutation implements IMutation {
23  
24      /** Logger object. */
25      //private static final Logger LOGGER =
26      //    Logger.getLogger(InversionMutation.class.getName());
27  
28      /** Delhezi Error Code. */
29      //private static final String DERC = "1-6-1-";
30  
31      /** Random.*/
32      private static Random random = new Random();
33  
34      /**
35       * Implementacja funkcji mutacji przez inwersję.
36       * @param chromosome Chromosom podlegający mutacji.
37       * @since 1.0
38       */
39      @Override
40      public final void mutation(final Chromosome chromosome) {
41  
42          if (chromosome == null) {
43              throw new IllegalArgumentException("Chromosome is null.");
44              }
45          int chromosomeSize = chromosome.size();
46          //Chromosom ma tylko 1 gen.
47          if (chromosomeSize < 2) {
48              return;
49              }
50  
51          //Losuje liczny z zakresu od 0 do chromosomeSize.
52          //Początkowy punkt fragmentu inwersji cutPoint1=2 dla xx|iiixxxxx.
53          int cutPoint1 = (int) (random.nextDouble() * (chromosomeSize + 1));
54          //Końcowy punkt fragmentu inwersji cutPoint2=5 dla xxiii|xxxxx.
55          int cutPoint2 = (int) (random.nextDouble() * (chromosomeSize + 1));
56  
57          //Korekta wyniku.
58          //Istnieje bardzo małe prawdopodobienstwo wylosowania liczby o
59          //wartosci chromosomeSize (poza zakresem), np. 4.999999999999999
60          //zaokraglane jest do 4, ale sprawdzę:
61          if (cutPoint1 == chromosomeSize + 1) {
62              cutPoint1--;
63          }
64          if (cutPoint2 == chromosomeSize + 1) {
65              cutPoint2--;
66          }
67  
68          //Liczba genów poza fragmentem inwersji.
69          int differentGenesSize = (cutPoint2 >= cutPoint1)
70              ? chromosomeSize - (cutPoint2 - cutPoint1)
71              : chromosomeSize - (chromosomeSize - cutPoint1) - cutPoint2;
72  
73          //Jeśli liczba genów fragmentu inwersji==0
74          if (chromosomeSize - differentGenesSize == 0) {
75              return;
76          }
77  
78          //Losuje liczny z zakresu od 0 do chromosomeSize.
79          //Liczby miejsc do wstawienia genów fragmentu inwersji jest
80          //równa differentGenes + 1.
81          //insertPoint=2 dla xx|xxxxx
82          int insertPoint =
83              (int) (random.nextDouble() * (differentGenesSize + 1));
84          //Istnieje bardzo małe prawdopodobienstwo wylosowania liczby o
85          //wartosci differentGenesSize + 1 (poza zakresem),
86          //np. 4.999999999999999 zaokraglane jest do 4, ale sprawdzę:
87          if (insertPoint == differentGenesSize + 1) {
88              insertPoint--;
89              }
90  
91          this.mutation(chromosome, cutPoint1, cutPoint2, insertPoint);
92      }
93  
94       /**
95       * Implementacja funkcji mutacji przez inwersję;
96       * W przypadku kiedy
97       * (cutPoint1==cutPoint2 || (cutPoint1==chromosomeSize && cutPoint2==0))
98       * funkcja traktuje fragment dopasowania jako pusty.
99       * @param chromosome Chromosom podlegający mutacji.
100      * @param cutPoint1 Początkowy punkt fragmentu inwersji, wartość z
101      * zakresu <0, chromosomeSize>.
102      * Przykład: cutPoint1=2 dla xx|iiixxxxx.
103      * @param cutPoint2 Końcowy punkt fragmentu inwersji, wartość z
104      * zakresu <0, chromosomeSize>.
105      * Przykład: cutPoint2=5 dla xxiii|xxxxx.
106      * @param insertPoint Punkt do wstawienia odwróconych genów, wartość z
107      * zakresu <0, differentGenesSize>.
108      * Przykład: insertPoint=2 dla xx|xxxxx.
109      * Nie są brane pod uwagę geny fragmentu inwersji.
110      * @since 1.0
111      */
112     protected final void mutation(final Chromosome chromosome,
113                                   final int cutPoint1,
114                                   final int cutPoint2,
115                                   final int insertPoint) {
116          //Walidacja parametrów wejściowych.
117 
118          //Chromosom nie może być wartością null.
119          assert chromosome != null : "Illegal argument chromosome: null";
120 
121          int chromosomeSize = chromosome.size();
122 
123          //Punkt cutPoint1 powinien zawierać się w obszare chromosomu.
124          assert (cutPoint1 >= 0 && cutPoint1 <= chromosomeSize)
125             : "Illegal argument cutPoint1: " + cutPoint1;
126          //Punkt cutPoint2 powinien zawierać się w obszare chromosomu.
127          assert (cutPoint2 >= 0 && cutPoint2 <= chromosomeSize)
128              : "Illegal argument cutPoint2: " + cutPoint2;
129          //Funkcja traktuje fragment dopasowania jako pusty.
130          if (cutPoint1 == cutPoint2 || (cutPoint1 == chromosomeSize
131                                         && cutPoint2 == 0)) {
132              return;
133              }
134          //Dla mniej niż 2 genów mutacja przez inwersję nie spowoduje
135          //żadnych zmian.
136          if (chromosomeSize < 2) {
137              return;
138              }
139 
140          //Liczba genów podlegających inwersji.
141          int inversionGenesSize = (cutPoint1 < cutPoint2)
142              ? cutPoint2 - cutPoint1
143              : (chromosomeSize - cutPoint1) + cutPoint2;
144          int differentGenesSize =  chromosomeSize - inversionGenesSize;
145          //Punkt insertPoint powinien zawierać się w obszare chromosomu z
146          //pominięciem obszaru inwersji.
147          assert (insertPoint >= 0 && insertPoint <= differentGenesSize)
148              : "Illegal argument insertPoint: " + insertPoint;
149 
150         //Koniec walidacji parametrów wejściowych.
151 
152         //IMPLEMENTACJA DO ZMIANY, ZASTĄPIĆ WEKTORAMI.
153 
154         //invGenes - sekcja inwersji po operacji inwersji.
155         Object[] invGenes = new Object[inversionGenesSize];
156         int ii = cutPoint2;
157         for (int i = 0; i < inversionGenesSize; i++) {
158             ii = (ii < 1) ? chromosomeSize - 1 : ii - 1;
159             invGenes[i] = chromosome.getGene(ii);
160             }
161 
162         //cpGenes - pozostałe geny.
163         Object[] cpGenes = new Object[chromosomeSize - inversionGenesSize];
164         ii = 0;
165         int ii2 = cutPoint2;
166         if (cutPoint1 < cutPoint2) {
167             for (int i = 0; i < cpGenes.length; i++) {
168                 ii = (ii < cutPoint1) ? ii : ii2++;
169                 cpGenes[i] = chromosome.getGene(ii);
170                 ii++;
171                 }
172             }
173         ii = 0;
174         if (cutPoint2 < cutPoint1) {
175             for (int i = cutPoint2; i < cutPoint1; i++) {
176                 cpGenes[ii] = chromosome.getGene(i);
177                 ii++;
178                 }
179             }
180 
181         int inv = 0;
182         int cp = 0;
183         for (int i = 0; i < chromosomeSize; i++) {
184             if ((i < insertPoint) || (i >= insertPoint + inversionGenesSize)) {
185                 chromosome.setGene(i, cpGenes[cp]);
186                 cp++;
187             } else {
188                 chromosome.setGene(i, invGenes[inv]);
189                 inv++;
190                 }
191             }
192 
193         //Zasygnalizuj, ze chromosom został zmieniony.
194         chromosome.changed();
195         }
196      }