001 /*
002 * Java Genetic Algorithm Library (jenetics-1.5.0).
003 * Copyright (c) 2007-2013 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics;
021
022 import static java.util.Objects.requireNonNull;
023 import static org.jenetics.util.object.Verify;
024 import static org.jenetics.util.object.eq;
025 import static org.jenetics.util.object.hashCodeOf;
026
027 import java.util.Iterator;
028
029 import javolution.lang.Immutable;
030 import javolution.lang.Realtime;
031 import javolution.text.Text;
032 import javolution.xml.XMLFormat;
033 import javolution.xml.XMLSerializable;
034 import javolution.xml.stream.XMLStreamException;
035
036 import org.jenetics.util.Array;
037 import org.jenetics.util.Factory;
038 import org.jenetics.util.Function;
039 import org.jenetics.util.ISeq;
040 import org.jenetics.util.Seq;
041 import org.jenetics.util.Verifiable;
042
043 /**
044 * The central class the GA is working with, is the {@code Genotype}. It is the
045 * structural representative of an individual. This class is the encoded problem
046 * solution with one to many {@link Chromosome}.
047 * <p><div align="center">
048 * <img src="doc-files/Genotype.svg" width="400" height="252" >
049 * </p></div>
050 * The chromosomes of a genotype doesn't have to have necessarily the same size.
051 * It is only required that all genes are from the same type and the genes within
052 * a chromosome have the same constraints; e. g. the same min- and max values
053 * for number genes.
054 *
055 * [code]
056 * final Genotype〈Float64Gene〉 genotype = Genotype.valueOf(
057 * new Float64Chromosome(0.0, 1.0, 8),
058 * new Float64Chromosome(1.0, 2.0, 10),
059 * new Float64Chromosome(0.0, 10.0, 9),
060 * new Float64Chromosome(0.1, 0.9, 5)
061 * );
062 * [/code]
063 * The code snippet above creates a genotype with the same structure as shown in
064 * the figure above. In this example the {@link Float64Gene} has been chosen as
065 * gene type.
066 *
067 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
068 * @since 1.0
069 * @version 1.0 — <em>$Date: 2013-11-28 $</em>
070 */
071 public final class Genotype<G extends Gene<?, G>>
072 implements
073 Factory<Genotype<G>>,
074 Iterable<Chromosome<G>>,
075 Verifiable,
076 XMLSerializable,
077 Realtime,
078 Immutable
079 {
080 private static final long serialVersionUID = 2L;
081
082 private final ISeq<Chromosome<G>> _chromosomes;
083 private final int _ngenes;
084
085 //Caching isValid value.
086 private volatile Boolean _valid = null;
087
088 private Genotype(final ISeq<Chromosome<G>> chromosomes, final int ngenes) {
089 _chromosomes = chromosomes;
090 _ngenes = ngenes;
091 }
092
093 private static int ngenes(final Seq<? extends Chromosome<?>> chromosomes) {
094 int ngenes = 0;
095 for (int i = chromosomes.length(); --i >= 0;) {
096 ngenes += chromosomes.get(i).length();
097 }
098 return ngenes;
099 }
100
101 /**
102 * Return the chromosome at the given index. It is guaranteed, that the
103 * returned chromosome is not null.
104 *
105 * @param index Chromosome index.
106 * @return The Chromosome.
107 * @throws IndexOutOfBoundsException if (index < 0 || index >= _length).
108 */
109 public Chromosome<G> getChromosome(final int index) {
110 assert(_chromosomes != null);
111 assert(_chromosomes.get(index) != null);
112
113 return _chromosomes.get(index);
114 }
115
116 /**
117 * Return the first chromosome. This is a shortcut for
118 * [code]
119 * final Genotype〈Float64Gene〉 gt = ...
120 * final Chromosome〈Float64Gene〉 chromosome = gt.getChromosome(0);
121 * [/code]
122 *
123 * @return The first chromosome.
124 */
125 public Chromosome<G> getChromosome() {
126 assert(_chromosomes != null);
127 assert(_chromosomes.get(0) != null);
128
129 return _chromosomes.get(0);
130 }
131
132 /**
133 * Return the first {@link Gene} of the first {@link Chromosome} of this
134 * {@code Genotype}. This is a shortcut for
135 * [code]
136 * final Genotype〈Float64Gene〉 gt = ...
137 * final Float64Gene gene = gt.getChromosome(0).getGene(0);
138 * [/code]
139 *
140 * @return the first {@link Gene} of the first {@link Chromosome} of this
141 * {@code Genotype}.
142 */
143 public G getGene() {
144 assert(_chromosomes != null);
145 assert(_chromosomes.get(0) != null);
146
147 return _chromosomes.get(0).getGene();
148 }
149
150
151 public ISeq<Chromosome<G>> toSeq() {
152 return _chromosomes;
153 }
154
155 @Override
156 public Iterator<Chromosome<G>> iterator() {
157 return _chromosomes.iterator();
158 }
159
160 /**
161 * Getting the number of chromosomes of this genotype.
162 *
163 * @return number of chromosomes.
164 */
165 public int length() {
166 return _chromosomes.length();
167 }
168
169 /**
170 * Return the number of genes this genotype consists of. This is the sum of
171 * the number of genes of the genotype chromosomes.
172 *
173 * @return Return the number of genes this genotype consists of.
174 */
175 public int getNumberOfGenes() {
176 return _ngenes;
177 }
178
179 /**
180 * Test if this genotype is valid. A genotype is valid if all its
181 * {@link Chromosome}s are valid.
182 *
183 * @return true if this genotype is valid, false otherwise.
184 */
185 @Override
186 public boolean isValid() {
187 if (_valid == null) {
188 _valid = _chromosomes.forAll(Verify);
189 }
190 return _valid;
191 }
192
193 /**
194 * Return a new, random genotype by creating new, random chromosomes (calling
195 * the {@link Chromosome#newInstance()} method) from the chromosomes of this
196 * genotype.
197 */
198 @Override
199 public Genotype<G> newInstance() {
200 final Array<Chromosome<G>> chromosomes = new Array<>(length());
201 for (int i = 0; i < length(); ++i) {
202 chromosomes.set(i, _chromosomes.get(i).newInstance());
203 }
204
205 return new Genotype<>(chromosomes.toISeq(), _ngenes);
206 }
207
208 Genotype<G> newInstance(final ISeq<Chromosome<G>> chromosomes) {
209 return new Genotype<>(chromosomes, _ngenes);
210 }
211
212 @Override
213 public int hashCode() {
214 return hashCodeOf(getClass()).and(_chromosomes).value();
215 }
216
217 @Override
218 public boolean equals(final Object o) {
219 if (o == this) {
220 return true;
221 }
222 if (!(o instanceof Genotype<?>)) {
223 return false;
224 }
225
226 final Genotype<?> gt = (Genotype<?>)o;
227 return eq(_chromosomes, gt._chromosomes);
228 }
229
230 @Override
231 public Text toText() {
232 return new Text(_chromosomes.toString());
233 }
234
235 @Override
236 public String toString() {
237 return _chromosomes.toString();
238 }
239
240
241 /* *************************************************************************
242 * Property access methods
243 * ************************************************************************/
244
245 /**
246 * Return a converter which access the chromosome array of this genotype.
247 */
248 public static <T extends Gene<?, T>>
249 Function<Genotype<T>, ISeq<Chromosome<T>>> Chromosomes()
250 {
251 return new Function<Genotype<T>, ISeq<Chromosome<T>>>() {
252 @Override public ISeq<Chromosome<T>> apply(final Genotype<T> value) {
253 return value.toSeq();
254 }
255 };
256 }
257
258 /**
259 * Return a converter which access the chromosome with the given index of
260 * this genotype.
261 */
262 public static <T extends Gene<?, T>>
263 Function<Genotype<T>, Chromosome<T>> Chromosome(final int index)
264 {
265 return new Function<Genotype<T>, Chromosome<T>>() {
266 @Override public Chromosome<T> apply(final Genotype<T> value) {
267 return value.getChromosome(index);
268 }
269 };
270 }
271
272 /**
273 * Return a converter which access the first chromosome of this genotype.
274 */
275 public static <T extends Gene<?, T>>
276 Function<Genotype<T>, Chromosome<T>> Chromosome()
277 {
278 return new Function<Genotype<T>, Chromosome<T>>() {
279 @Override public Chromosome<T> apply(final Genotype<T> value) {
280 return value.getChromosome();
281 }
282 };
283 }
284
285
286 /**
287 * Create a new Genotype from a given array of {@code Chromosomes}.
288 *
289 * @param chromosomes The {@code Chromosome} array the {@code Genotype}
290 * consists of.
291 * @throws NullPointerException if {@code chromosomes} is null or one of its
292 * element.
293 * @throws IllegalArgumentException if {@code chromosome.length == 0}.
294 */
295 public static <G extends Gene<?, G>> Genotype<G> valueOf(
296 final ISeq<? extends Chromosome<G>> chromosomes
297 ) {
298 requireNonNull(chromosomes, "Chromosomes");
299 if (chromosomes.length() == 0) {
300 throw new IllegalArgumentException("Chromosomes must be given.");
301 }
302
303 @SuppressWarnings("unchecked")
304 ISeq<Chromosome<G>> c = (ISeq<Chromosome<G>>)chromosomes;
305 return new Genotype<>(c, ngenes(chromosomes));
306 }
307
308 /**
309 * Create a new Genotype from a given array of {@code Chromosomes}.
310 *
311 * @param chromosomes The {@code Chromosome} array the {@code Genotype}
312 * consists of.
313 * @throws NullPointerException if {@code chromosomes} is null or one of its
314 * element.
315 * @throws IllegalArgumentException if {@code chromosome.length == 0}.
316 */
317 @SafeVarargs
318 public static <G extends Gene<?, G>> Genotype<G> valueOf(
319 final Chromosome<G>... chromosomes
320 ) {
321 return valueOf(Array.valueOf(chromosomes).toISeq());
322 }
323
324 /* *************************************************************************
325 * XML object serialization
326 * ************************************************************************/
327
328 @SuppressWarnings({ "unchecked", "rawtypes"})
329 static final XMLFormat<Genotype>
330 XML = new XMLFormat<Genotype>(Genotype.class)
331 {
332 private static final String LENGTH = "length";
333 private static final String NGENES = "ngenes";
334
335 @Override
336 public Genotype newInstance(
337 final Class<Genotype> cls, final InputElement xml
338 )
339 throws XMLStreamException
340 {
341 final int length = xml.getAttribute(LENGTH, 0);
342 final int ngenes = xml.getAttribute(NGENES, 0);
343 final Array<Chromosome> chromosomes = new Array<>(length);
344 for (int i = 0; i < length; ++i) {
345 final Chromosome<?> c = xml.getNext();
346 chromosomes.set(i, c);
347 }
348
349 return new Genotype(chromosomes.toISeq(), ngenes);
350 }
351 @Override
352 public void write(final Genotype gt, final OutputElement xml)
353 throws XMLStreamException
354 {
355 xml.setAttribute(LENGTH, gt.length());
356 xml.setAttribute(NGENES, gt.getNumberOfGenes());
357 for (int i = 0; i < gt.length(); ++i) {
358 xml.add(gt._chromosomes.get(i));
359 }
360 }
361 @Override
362 public void read(final InputElement xml, final Genotype gt) {
363 }
364 };
365 }
366
367
368
369
|