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 }