001 /*
002 * Java Genetic Algorithm Library (jenetics-4.2.0).
003 * Copyright (c) 2007-2018 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@gmail.com)
019 */
020 package io.jenetics;
021
022 import static io.jenetics.internal.util.Equality.eq;
023
024 import java.io.Serializable;
025 import java.util.Iterator;
026 import java.util.Objects;
027 import java.util.stream.Stream;
028
029 import io.jenetics.util.Factory;
030 import io.jenetics.util.ISeq;
031 import io.jenetics.util.MSeq;
032 import io.jenetics.util.Seq;
033 import io.jenetics.util.Verifiable;
034
035 /**
036 * The central class the GA is working with, is the {@code Genotype}. It is the
037 * structural representative of an individual. This class is the encoded problem
038 * solution with one to many {@link Chromosome}.
039 * <p>
040 * <img alt="Genotype" src="doc-files/Genotype.svg" width="400" height="252" >
041 * </p>
042 * The chromosomes of a genotype doesn't have to have necessarily the same size.
043 * It is only required that all genes are from the same type and the genes within
044 * a chromosome have the same constraints; e. g. the same min- and max values
045 * for number genes.
046 *
047 * <pre>{@code
048 * final Genotype<DoubleGene> genotype = Genotype.of(
049 * DoubleChromosome.of(0.0, 1.0, 8),
050 * DoubleChromosome.of(1.0, 2.0, 10),
051 * DoubleChromosome.of(0.0, 10.0, 9),
052 * DoubleChromosome.of(0.1, 0.9, 5)
053 * );
054 * }</pre>
055 * The code snippet above creates a genotype with the same structure as shown in
056 * the figure above. In this example the {@link DoubleGene} has been chosen as
057 * gene type.
058 *
059 * @see Chromosome
060 * @see Phenotype
061 *
062 * @implNote
063 * This class is immutable and thread-safe.
064 *
065 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
066 * @since 1.0
067 * @version 4.0
068 */
069 public final class Genotype<G extends Gene<?, G>>
070 implements
071 Factory<Genotype<G>>,
072 Iterable<Chromosome<G>>,
073 Verifiable,
074 Serializable
075 {
076 private static final long serialVersionUID = 3L;
077
078 private final ISeq<Chromosome<G>> _chromosomes;
079
080 //Caching isValid value.
081 private volatile Boolean _valid = null;
082
083 /**
084 * Create a new Genotype from a given sequence of {@code Chromosomes}.
085 *
086 * @param chromosomes The {@code Chromosome} array the {@code Genotype}
087 * consists of.
088 * @throws NullPointerException if {@code chromosomes} is null or one of its
089 * element.
090 * @throws IllegalArgumentException if {@code chromosome.length == 0}.
091 */
092 Genotype(final ISeq<? extends Chromosome<G>> chromosomes) {
093 if (chromosomes.isEmpty()) {
094 throw new IllegalArgumentException("No chromosomes given.");
095 }
096
097 _chromosomes = ISeq.upcast(chromosomes);
098 }
099
100 private static int ngenes(final Seq<? extends Chromosome<?>> chromosomes) {
101 int count = 0;
102 for (int i = 0, n = chromosomes.length(); i < n; ++i) {
103 count += chromosomes.get(i).length();
104 }
105 return count;
106 }
107
108 /**
109 * Return the chromosome at the given index. It is guaranteed, that the
110 * returned chromosome is not null.
111 *
112 * @param index Chromosome index.
113 * @return The Chromosome.
114 * @throws IndexOutOfBoundsException if
115 * {@code (index < 0 || index >= _length)}.
116 */
117 public Chromosome<G> getChromosome(final int index) {
118 assert _chromosomes != null;
119 assert _chromosomes.get(index) != null;
120
121 return _chromosomes.get(index);
122 }
123
124 /**
125 * Return the first chromosome. This is a shortcut for
126 * <pre>{@code
127 * final Genotype<DoubleGene>; gt = ...
128 * final Chromosome<DoubleGene> chromosome = gt.getChromosome(0);
129 * }</pre>
130 *
131 * @return The first chromosome.
132 */
133 public Chromosome<G> getChromosome() {
134 assert _chromosomes != null;
135 assert _chromosomes.get(0) != null;
136
137 return _chromosomes.get(0);
138 }
139
140 /**
141 * Return the first {@link Gene} of the first {@link Chromosome} of this
142 * {@code Genotype}. This is a shortcut for
143 * <pre>{@code
144 * final Genotype<DoubleGene> gt = ...
145 * final DoubleGene gene = gt.getChromosome(0).getGene(0);
146 * }</pre>
147 *
148 * @return the first {@link Gene} of the first {@link Chromosome} of this
149 * {@code Genotype}.
150 */
151 public G getGene() {
152 assert _chromosomes != null;
153 assert _chromosomes.get(0) != null;
154
155 return _chromosomes.get(0).getGene();
156 }
157
158 /**
159 * Return the gene from the given chromosome- and gene index. This is a
160 * shortcut for {@code gt.getChromosome(chromosomeIndex).getGene(geneIndex)}.
161 *
162 * @since 3.0
163 *
164 * @param chromosomeIndex the chromosome index
165 * @param geneIndex the gene index within the chromosome
166 * @return the gene with the given indexes
167 * @throws IndexOutOfBoundsException if the given indexes are not within the
168 * allowed range
169 */
170 public G get(final int chromosomeIndex, final int geneIndex) {
171 return getChromosome(chromosomeIndex).getGene(geneIndex);
172 }
173
174 /**
175 * Return the chromosome at the given index. It is guaranteed, that the
176 * returned chromosome is not null.
177 *
178 * @see #getChromosome(int)
179 * @since 4.0
180 *
181 * @param chromosomeIndex Chromosome index.
182 * @return The Chromosome.
183 * @throws IndexOutOfBoundsException if
184 * {@code (index < 0 || index >= _length)}.
185 */
186 public Chromosome<G> get(final int chromosomeIndex) {
187 return getChromosome(chromosomeIndex);
188 }
189
190 public ISeq<Chromosome<G>> toSeq() {
191 return _chromosomes;
192 }
193
194 @Override
195 public Iterator<Chromosome<G>> iterator() {
196 return _chromosomes.iterator();
197 }
198
199 /**
200 * Returns a sequential {@code Stream} of chromosomes with this genotype as
201 * its source.
202 *
203 * @since 3.4
204 *
205 * @return a sequential {@code Stream} of chromosomes
206 */
207 public Stream<Chromosome<G>> stream() {
208 return _chromosomes.stream();
209 }
210
211 /**
212 * Getting the number of chromosomes of this genotype.
213 *
214 * @return number of chromosomes.
215 */
216 public int length() {
217 return _chromosomes.length();
218 }
219
220 /**
221 * Return the number of genes this genotype consists of. This is the sum of
222 * the number of genes of the genotype chromosomes.
223 *
224 * @return Return the number of genes this genotype consists of.
225 */
226 public int geneCount() {
227 int count = 0;
228 for (int i = 0, n = _chromosomes.length(); i < n; ++i) {
229 count += _chromosomes.get(i).length();
230 }
231 return count;
232 }
233
234 /**
235 * Test if this genotype is valid. A genotype is valid if all its
236 * {@link Chromosome}s are valid.
237 *
238 * @return true if this genotype is valid, false otherwise.
239 */
240 @Override
241 public boolean isValid() {
242 Boolean valid = _valid;
243 if (valid == null) {
244 valid = _chromosomes.forAll(Verifiable::isValid);
245 _valid = valid;
246 }
247
248 return _valid;
249 }
250
251 /**
252 * Return a new, random genotype by creating new, random chromosomes (calling
253 * the {@link Chromosome#newInstance()} method) from the chromosomes of this
254 * genotype.
255 */
256 @Override
257 public Genotype<G> newInstance() {
258 return new Genotype<>(_chromosomes.map(Factory::newInstance));
259 }
260
261 @Override
262 public int hashCode() {
263 int hash = 17;
264 hash += 31*Objects.hashCode(_chromosomes) + 37;
265 return hash;
266 }
267
268 @Override
269 public boolean equals(final Object obj) {
270 return obj == this ||
271 obj instanceof Genotype &&
272 eq(_chromosomes, ((Genotype<?>)obj)._chromosomes);
273 }
274
275 @Override
276 public String toString() {
277 return _chromosomes.toString();
278 }
279
280 /**
281 * Create a new {@code Genotype} from a given array of {@code Chromosomes}.
282 *
283 * @since 3.0
284 *
285 * @param <G> the gene type
286 * @param first the first {@code Chromosome} of the {@code Genotype}
287 * @param rest the rest of the genotypes chromosomes.
288 * @return a new {@code Genotype} from the given chromosomes
289 * @throws NullPointerException if {@code chromosomes} is {@code null} or
290 * one of its element.
291 */
292 @SafeVarargs
293 public static <G extends Gene<?, G>> Genotype<G> of(
294 final Chromosome<G> first,
295 final Chromosome<G>... rest
296 ) {
297 final MSeq<Chromosome<G>> seq = MSeq.ofLength(1 + rest.length);
298 seq.set(0, first);
299 for (int i = 0; i < rest.length; ++i) {
300 seq.set(i + 1, rest[i]);
301 }
302 return new Genotype<>(seq.toISeq());
303 }
304
305 /**
306 * Create a new {@code Genotype} which consists of {@code n} chromosomes,
307 * which are created by the given {@code factory}. This method can be used
308 * for easily creating a <i>gene matrix</i>. The following example will
309 * create a 10x5 {@code DoubleGene} <i>matrix</i>.
310 *
311 * <pre>{@code
312 * final Genotype<DoubleGene> gt = Genotype
313 * .of(DoubleChromosome.of(0.0, 1.0, 10), 5);
314 * }</pre>
315 *
316 * @since 3.0
317 *
318 * @param <G> the gene type
319 * @param factory the factory which creates the chromosomes this genotype
320 * consists of
321 * @param n the number of chromosomes this genotype consists of
322 * @return new {@code Genotype} containing {@code n} chromosomes
323 * @throws IllegalArgumentException if {@code n < 1}.
324 * @throws NullPointerException if the {@code factory} is {@code null}.
325 */
326 public static <G extends Gene<?, G>> Genotype<G>
327 of(final Factory<? extends Chromosome<G>> factory, final int n) {
328 final ISeq<Chromosome<G>> ch = ISeq.of(factory::newInstance, n);
329 return new Genotype<>(ch);
330 }
331
332 /**
333 * Create a new {@code Genotype} from a given array of {@code chromosomes}.
334 *
335 * @since 3.0
336 *
337 * @param <G> the gene type
338 * @param chromosomes the {@code Chromosome}s the returned genotype consists
339 * of
340 * @return a new {@code Genotype} from the given chromosomes
341 * @throws NullPointerException if {@code chromosomes} is {@code null} or
342 * one of its element.
343 * @throws IllegalArgumentException if {@code chromosome.length() < 1}.
344 */
345 public static <G extends Gene<?, G>> Genotype<G>
346 of(final Iterable<? extends Chromosome<G>> chromosomes) {
347 return new Genotype<>(ISeq.of(chromosomes));
348 }
349
350 }
|