EvolutionStart.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.Hashes.hash;
025 import static io.jenetics.internal.util.SerialIO.readLong;
026 import static io.jenetics.internal.util.SerialIO.writeLong;
027 
028 import java.io.IOException;
029 import java.io.InvalidObjectException;
030 import java.io.ObjectInput;
031 import java.io.ObjectInputStream;
032 import java.io.ObjectOutput;
033 import java.io.Serializable;
034 import java.util.Objects;
035 
036 import io.jenetics.Gene;
037 import io.jenetics.Phenotype;
038 import io.jenetics.internal.util.Requires;
039 import io.jenetics.util.ISeq;
040 
041 /**
042  * Represents a state of the GA at the start of an evolution step.
043  *
044  @see EvolutionResult
045  @see EvolutionInit
046  @see EvolutionStreamable#stream(EvolutionStart)
047  *
048  @param <G> the gene type
049  @param <C> the fitness type
050  *
051  * @implNote
052  * This class is immutable and thread-safe.
053  *
054  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
055  @since 3.1
056  @version 6.0
057  */
058 public final class EvolutionStart<
059     extends Gene<?, G>,
060     extends Comparable<? super C>
061 >
062     implements Serializable
063 {
064 
065     private static final long serialVersionUID = 2L;
066 
067     private final ISeq<Phenotype<G, C>> _population;
068     private final long _generation;
069 
070     private final boolean _dirty;
071 
072     EvolutionStart(
073         final ISeq<Phenotype<G, C>> population,
074         final long generation,
075         final boolean dirty
076     ) {
077         _population = requireNonNull(population);
078         _generation = Requires.positive(generation);
079         _dirty = dirty;
080     }
081 
082     /**
083      * Return the population before the evolution step.
084      *
085      @return the start population
086      */
087     public ISeq<Phenotype<G, C>> population() {
088         return _population;
089     }
090 
091     /**
092      * Return the generation of the start population.
093      *
094      @return the start generation
095      */
096     public long generation() {
097         return _generation;
098     }
099 
100     /**
101      * Indicates whether the population is guaranteed to be evaluated. If this
102      * flag is {@code true}, the population possibly contains unevaluated
103      * individuals.
104      *
105      @return {@code false}, if it is guaranteed that all individuals has
106      *         already been evaluated, {@code true} otherwise
107      */
108     boolean isDirty() {
109         return _dirty;
110     }
111 
112     @Override
113     public int hashCode() {
114         return hash(_generation, hash(_population, hash(getClass())));
115     }
116 
117     @Override
118     public boolean equals(final Object obj) {
119         return obj == this ||
120             obj instanceof EvolutionStart &&
121             _generation == ((EvolutionStart)obj)._generation &&
122             Objects.equals(_population, ((EvolutionStart)obj)._population);
123     }
124 
125     @Override
126     public String toString() {
127         return format(
128             "EvolutionStart[population-size=%d, generation=%d]",
129             _population.size(), _generation
130         );
131     }
132 
133     /**
134      * Create a new evolution start object with the given population and for the
135      * given generation.
136      *
137      @param <G> the gene type
138      @param <C> the fitness type
139      @param population the start population.
140      @param generation the start generation of the population
141      @return a new evolution start object
142      @throws java.lang.NullPointerException if the given {@code population} is
143      *         {@code null}.
144      @throws IllegalArgumentException if the given {@code generation} is
145      *         smaller then one
146      */
147     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
148     EvolutionStart<G, C> of(
149         final ISeq<Phenotype<G, C>> population,
150         final long generation
151     ) {
152         return new EvolutionStart<>(population, generation, true);
153     }
154 
155     /**
156      * An empty evolution start object, which can be used as initial evolution
157      * value. The evolution {@link Engine} is then responsible for creating the
158      * proper initial population,
159      *
160      @since 5.1
161      *
162      @param <G> the gene type
163      @param <C> the fitness type
164      @return an empty evolution start object
165      */
166     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
167     EvolutionStart<G, C> empty() {
168         return new EvolutionStart<>(ISeq.empty()1false);
169     }
170 
171 
172     /* *************************************************************************
173      *  Java object serialization
174      * ************************************************************************/
175 
176     private Object writeReplace() {
177         return new Serial(Serial.EVOLUTION_START, this);
178     }
179 
180     private void readObject(final ObjectInputStream stream)
181         throws InvalidObjectException
182     {
183         throw new InvalidObjectException("Serialization proxy required.");
184     }
185 
186     void write(final ObjectOutput outthrows IOException {
187         out.writeObject(_population);
188         writeLong(_generation, out);
189     }
190 
191     @SuppressWarnings({"unchecked""rawtypes"})
192     static Object read(final ObjectInput in)
193         throws IOException, ClassNotFoundException
194     {
195         return new EvolutionStart(
196             (ISeq)in.readObject(),
197             readLong(in),
198             true
199         );
200     }
201 
202 }