EvolutionParams.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-6.3.0).
003  * Copyright (c) 2007-2021 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.engine;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static io.jenetics.internal.util.Requires.probability;
025 import static io.jenetics.internal.util.SerialIO.readInt;
026 import static io.jenetics.internal.util.SerialIO.readLong;
027 import static io.jenetics.internal.util.SerialIO.writeInt;
028 import static io.jenetics.internal.util.SerialIO.writeLong;
029 
030 import java.io.IOException;
031 import java.io.InvalidObjectException;
032 import java.io.ObjectInput;
033 import java.io.ObjectInputStream;
034 import java.io.ObjectOutput;
035 import java.io.Serializable;
036 import java.util.Objects;
037 import java.util.stream.Stream;
038 
039 import io.jenetics.Alterer;
040 import io.jenetics.Gene;
041 import io.jenetics.Mutator;
042 import io.jenetics.Selector;
043 import io.jenetics.SinglePointCrossover;
044 import io.jenetics.TournamentSelector;
045 import io.jenetics.internal.util.Requires;
046 
047 /**
048  * This class collects the parameters which control the behaviour of the
049  * evolution process. This doesn't include the parameters for the
050  <em>technical</em> execution like the used execution service.
051  *
052  @see Engine
053  @see Engine.Builder
054  *
055  @param <G> the gene type
056  @param <C> the fitness function result type
057  *
058  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
059  @version 5.2
060  @since 5.2
061  */
062 public final class EvolutionParams<
063     extends Gene<?, G>,
064     extends Comparable<? super C>
065 >
066     implements Serializable
067 {
068 
069     private static final long serialVersionUID = 1L;
070 
071     private final Selector<G, C> _survivorsSelector;
072     private final Selector<G, C> _offspringSelector;
073     private final Alterer<G, C> _alterer;
074     private final int _populationSize;
075     private final double _offspringFraction;
076     private final long _maximalPhenotypeAge;
077 
078     private EvolutionParams(
079         final Selector<G, C> survivorsSelector,
080         final Selector<G, C> offspringSelector,
081         final Alterer<G, C> alterer,
082         final int populationSize,
083         final double offspringFraction,
084         final long maximalPhenotypeAge
085     ) {
086         _survivorsSelector = requireNonNull(survivorsSelector);
087         _offspringSelector = requireNonNull(offspringSelector);
088         _alterer = requireNonNull(alterer);
089         _populationSize = Requires.positive(populationSize);
090         _offspringFraction = Requires.probability(offspringFraction);
091         _maximalPhenotypeAge = Requires.positive(maximalPhenotypeAge);
092     }
093 
094 
095     /**
096      * Return the used survivor {@link Selector} of the GA.
097      *
098      @return the used survivor {@link Selector} of the GA.
099      */
100     public Selector<G, C> survivorsSelector() {
101         return _survivorsSelector;
102     }
103 
104     /**
105      * Return the used offspring {@link Selector} of the GA.
106      *
107      @return the used offspring {@link Selector} of the GA.
108      */
109     public Selector<G, C> offspringSelector() {
110         return _offspringSelector;
111     }
112 
113     /**
114      * Return the used {@link Alterer} of the GA.
115      *
116      @return the used {@link Alterer} of the GA.
117      */
118     public Alterer<G, C> alterer() {
119         return _alterer;
120     }
121 
122 
123     /**
124      * Return the population size.
125      *
126      @return the population size
127      */
128     public int populationSize() {
129         return _populationSize;
130     }
131 
132     /**
133      * Return the offspring fraction.
134      *
135      @return the offspring fraction.
136      */
137     public double offspringFraction() {
138         return _offspringFraction;
139     }
140 
141     /**
142      * Return the maximal allowed phenotype age.
143      *
144      @return the maximal allowed phenotype age
145      */
146     public long maximalPhenotypeAge() {
147         return _maximalPhenotypeAge;
148     }
149 
150 
151     /* *************************************************************************
152      * Derived properties.
153      **************************************************************************/
154 
155     /**
156      * Return the number of offspring. <em>This is a derived property.</em>
157      *
158      @return the offspring count.
159      */
160     public int offspringSize() {
161         return (int)Math.rint(_populationSize*_offspringFraction);
162     }
163 
164     /**
165      * Return the number of survivors. <em>This is a derived property.</em>
166      *
167      @return the number of survivors
168      */
169     public int survivorsSize() {
170         return _populationSize - offspringSize();
171     }
172 
173     /**
174      * Return a new builder object, initialized with {@code this} parameters.
175      *
176      @return a new pre-filled builder object
177      */
178     public EvolutionParams.Builder<G, C> toBuilder() {
179         return EvolutionParams.<G, C>builder()
180             .survivorsSelector(survivorsSelector())
181             .offspringSelector(offspringSelector())
182             .alterers(alterer())
183             .populationSize(populationSize())
184             .offspringFraction(offspringFraction())
185             .maximalPhenotypeAge(maximalPhenotypeAge());
186     }
187 
188     /**
189      * Create a new evolution parameter builder.
190      *
191      @param <G> the gene type
192      @param <C> the fitness function result type
193      @return a new parameter builder
194      */
195     public static  <G extends Gene<?, G>, C extends Comparable<? super C>>
196     Builder<G, C> builder() {
197         return new Builder<>();
198     }
199 
200 
201     /* *************************************************************************
202      * Params builder
203      **************************************************************************/
204 
205     /**
206      * Builder class for the evolution parameter.
207      *
208      @param <G> the gene type
209      @param <C> the fitness function result type
210      */
211     public static final class Builder<
212         extends Gene<?, G>,
213         extends Comparable<? super C>
214     {
215 
216         private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3);
217         private Selector<G, C> _offspringSelector = new TournamentSelector<>(3);
218         private Alterer<G, C> _alterer = Alterer.of(
219             new SinglePointCrossover<G, C>(0.2),
220             new Mutator<>(0.15)
221         );
222         private int _populationSize = 50;
223         private double _offspringFraction = 0.6;
224         private long _maximalPhenotypeAge = 70;
225 
226 
227         private Builder() {
228         }
229 
230         public Builder<G, C> evolutionParams(final EvolutionParams<G, C> params) {
231             survivorsSelector(params.survivorsSelector());
232             offspringSelector(params.offspringSelector());
233             alterers(params.alterer());
234             populationSize(params.populationSize());
235             offspringFraction(params.offspringFraction());
236             maximalPhenotypeAge(params.maximalPhenotypeAge());
237             return this;
238         }
239 
240         /**
241          * The selector used for selecting the offspring population. <i>Default
242          * values is set to {@code TournamentSelector<>(3)}.</i>
243          *
244          @param selector used for selecting the offspring population
245          @return {@code this} builder, for command chaining
246          */
247         public Builder<G, C> offspringSelector(
248             final Selector<G, C> selector
249         ) {
250             _offspringSelector = requireNonNull(selector);
251             return this;
252         }
253 
254         /**
255          * The selector used for selecting the survivors population. <i>Default
256          * values is set to {@code TournamentSelector<>(3)}.</i>
257          *
258          @param selector used for selecting survivors population
259          @return {@code this} builder, for command chaining
260          */
261         public Builder<G, C> survivorsSelector(
262             final Selector<G, C> selector
263         ) {
264             _survivorsSelector = requireNonNull(selector);
265             return this;
266         }
267 
268         /**
269          * The selector used for selecting the survivors and offspring
270          * population. <i>Default values is set to
271          * {@code TournamentSelector<>(3)}.</i>
272          *
273          @param selector used for selecting survivors and offspring population
274          @return {@code this} builder, for command chaining
275          */
276         public Builder<G, C> selector(final Selector<G, C> selector) {
277             _offspringSelector = requireNonNull(selector);
278             _survivorsSelector = requireNonNull(selector);
279             return this;
280         }
281 
282         /**
283          * The alterers used for alter the offspring population. <i>Default
284          * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
285          * {@code new Mutator<>(0.15)}.</i>
286          *
287          @param first the first alterer used for alter the offspring
288          *        population
289          @param rest the rest of the alterers used for alter the offspring
290          *        population
291          @return {@code this} builder, for command chaining
292          @throws java.lang.NullPointerException if one of the alterers is
293          *         {@code null}.
294          */
295         @SafeVarargs
296         public final Builder<G, C> alterers(
297             final Alterer<G, C> first,
298             final Alterer<G, C>... rest
299         ) {
300             requireNonNull(first);
301             Stream.of(rest).forEach(Objects::requireNonNull);
302 
303             _alterer = rest.length == 0
304                 ? first
305                 : Alterer.of(rest).compose(first);
306 
307             return this;
308         }
309 
310         /**
311          * The number of individuals which form the population. <i>Default
312          * values is set to {@code 50}.</i>
313          *
314          @param size the number of individuals of a population
315          @return {@code this} builder, for command chaining
316          @throws IllegalArgumentException if {@code size < 1}
317          */
318         public Builder<G, C> populationSize(final int size) {
319             if (size < 1) {
320                 throw new IllegalArgumentException(format(
321                     "Population size must be greater than zero, but was %s.",
322                     size
323                 ));
324             }
325 
326             _populationSize = size;
327             return this;
328         }
329 
330 
331         /**
332          * The offspring fraction.
333          *
334          @param fraction the offspring fraction
335          @return {@code this} builder, for command chaining
336          @throws IllegalArgumentException if the fraction is not within the
337          *         range [0, 1].
338          */
339         public Builder<G, C> offspringFraction(final double fraction) {
340             _offspringFraction = probability(fraction);
341             return this;
342         }
343 
344         /**
345          * The maximal allowed age of a phenotype. <i>Default values is set to
346          * {@code 70}.</i>
347          *
348          @param age the maximal phenotype age
349          @return {@code this} builder, for command chaining
350          @throws IllegalArgumentException if {@code age < 1}
351          */
352         public Builder<G, C> maximalPhenotypeAge(final long age) {
353             if (age < 1) {
354                 throw new IllegalArgumentException(format(
355                     "Phenotype age must be greater than one, but was %s.", age
356                 ));
357             }
358             _maximalPhenotypeAge = age;
359             return this;
360         }
361 
362         /**
363          * Builds an new {@code EvolutionParams} instance from the set properties.
364          *
365          @return an new {@code EvolutionParams} instance from the set properties
366          */
367         public EvolutionParams<G, C> build() {
368             return new EvolutionParams<>(
369                 _survivorsSelector,
370                 _offspringSelector,
371                 _alterer,
372                 _populationSize,
373                 _offspringFraction,
374                 _maximalPhenotypeAge
375             );
376         }
377 
378 
379         /* *********************************************************************
380          * Current properties
381          ***********************************************************************/
382 
383         /**
384          * Return the used {@link Alterer} of the GA.
385          *
386          @return the used {@link Alterer} of the GA.
387          */
388         public Alterer<G, C> alterer() {
389             return _alterer;
390         }
391 
392 
393         /**
394          * Return the maximal allowed phenotype age.
395          *
396          @return the maximal allowed phenotype age
397          */
398         public long maximalPhenotypeAge() {
399             return _maximalPhenotypeAge;
400         }
401 
402         /**
403          * Return the used offspring {@link Selector} of the GA.
404          *
405          @return the used offspring {@link Selector} of the GA.
406          */
407         public Selector<G, C> offspringSelector() {
408             return _offspringSelector;
409         }
410 
411         /**
412          * Return the used survivor {@link Selector} of the GA.
413          *
414          @return the used survivor {@link Selector} of the GA.
415          */
416         public Selector<G, C> survivorsSelector() {
417             return _survivorsSelector;
418         }
419 
420         /**
421          * Return the number of individuals of a population.
422          *
423          @return the number of individuals of a population
424          */
425         public int populationSize() {
426             return _populationSize;
427         }
428 
429         /**
430          * Return the offspring fraction.
431          *
432          @return the offspring fraction.
433          */
434         public double offspringFraction() {
435             return _offspringFraction;
436         }
437 
438         /* *************************************************************************
439          * Derived properties.
440          **************************************************************************/
441 
442         /**
443          * Return the number of offspring. <em>This is a derived property.</em>
444          *
445          @return the offspring count.
446          */
447         public int offspringSize() {
448             return (int)Math.round(_populationSize*_offspringFraction);
449         }
450 
451         /**
452          * Return the number of survivors. <em>This is a derived property.</em>
453          *
454          @return the number of survivors
455          */
456         public int survivorsSize() {
457             return _populationSize - offspringSize();
458         }
459 
460     }
461 
462     /* *************************************************************************
463      *  Java object serialization
464      * ************************************************************************/
465 
466     private Object writeReplace() {
467         return new Serial(Serial.EVOLUTION_PARAMS, this);
468     }
469 
470     private void readObject(final ObjectInputStream stream)
471         throws InvalidObjectException
472     {
473         throw new InvalidObjectException("Serialization proxy required.");
474     }
475 
476     void write(final ObjectOutput outthrows IOException {
477         out.writeObject(survivorsSelector());
478         out.writeObject(offspringSelector());
479         out.writeObject(alterer());
480         writeInt(populationSize(), out);
481         out.writeDouble(offspringFraction());
482         writeLong(maximalPhenotypeAge(), out);
483     }
484 
485     @SuppressWarnings({"unchecked""rawtypes"})
486     static EvolutionParams read(final ObjectInput in)
487         throws IOException, ClassNotFoundException
488     {
489         return new EvolutionParams(
490             (Selector)in.readObject(),
491             (Selector)in.readObject(),
492             (Alterer)in.readObject(),
493             readInt(in),
494             in.readDouble(),
495             readLong(in)
496         );
497     }
498 
499 }