EvolutionDurations.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.2.0).
003  * Copyright (c) 2007-2020 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 io.jenetics.internal.util.SerialIO.readInt;
023 import static io.jenetics.internal.util.SerialIO.readLong;
024 import static io.jenetics.internal.util.SerialIO.writeInt;
025 import static io.jenetics.internal.util.SerialIO.writeLong;
026 import static java.util.Objects.requireNonNull;
027 import static io.jenetics.internal.util.Hashes.hash;
028 
029 import java.io.DataInput;
030 import java.io.DataOutput;
031 import java.io.IOException;
032 import java.io.InvalidObjectException;
033 import java.io.ObjectInput;
034 import java.io.ObjectInputStream;
035 import java.io.ObjectOutput;
036 import java.io.Serializable;
037 import java.time.Duration;
038 import java.util.Objects;
039 
040 /**
041  * This class contains timing information about one evolution step.
042  *
043  * @implNote
044  * This class is immutable and thread-safe.
045  *
046  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
047  @since 3.0
048  @version 5.2
049  */
050 public final /*record*/ class EvolutionDurations
051     implements
052         Comparable<EvolutionDurations>,
053         Serializable
054 {
055     private static final long serialVersionUID = 2L;
056 
057     /**
058      * Constant for zero evolution durations.
059      */
060     public static final EvolutionDurations ZERO = EvolutionDurations.of(
061         Duration.ZERO,
062         Duration.ZERO,
063         Duration.ZERO,
064         Duration.ZERO,
065         Duration.ZERO,
066         Duration.ZERO,
067         Duration.ZERO
068     );
069 
070     private final Duration _offspringSelectionDuration;
071     private final Duration _survivorsSelectionDuration;
072     private final Duration _offspringAlterDuration;
073     private final Duration _offspringFilterDuration;
074     private final Duration _survivorFilterDuration;
075     private final Duration _evaluationDuration;
076     private final Duration _evolveDuration;
077 
078     EvolutionDurations(
079         final Duration offspringSelectionDuration,
080         final Duration survivorsSelectionDuration,
081         final Duration offspringAlterDuration,
082         final Duration offspringFilterDuration,
083         final Duration survivorFilterDuration,
084         final Duration evaluationDuration,
085         final Duration evolveDuration
086     ) {
087         _offspringSelectionDuration = requireNonNull(offspringSelectionDuration);
088         _survivorsSelectionDuration = requireNonNull(survivorsSelectionDuration);
089         _offspringAlterDuration = requireNonNull(offspringAlterDuration);
090         _offspringFilterDuration = requireNonNull(offspringFilterDuration);
091         _survivorFilterDuration = requireNonNull(survivorFilterDuration);
092         _evaluationDuration = requireNonNull(evaluationDuration);
093         _evolveDuration = requireNonNull(evolveDuration);
094     }
095 
096     /**
097      * Return the duration needed for selecting the offspring population.
098      *
099      @return the duration needed for selecting the offspring population
100      */
101     public Duration offspringSelectionDuration() {
102         return _offspringSelectionDuration;
103     }
104 
105     /**
106      * Return the duration needed for selecting the offspring population.
107      *
108      @return the duration needed for selecting the offspring population
109      @deprecated Use {@link #offspringSelectionDuration()} instead
110      */
111     @Deprecated
112     public Duration getOffspringSelectionDuration() {
113         return _offspringSelectionDuration;
114     }
115 
116     /**
117      * Return the duration needed for selecting the survivors population.
118      *
119      @return the duration needed for selecting the survivors population
120      */
121     public Duration survivorsSelectionDuration() {
122         return _survivorsSelectionDuration;
123     }
124 
125     /**
126      * Return the duration needed for selecting the survivors population.
127      *
128      @return the duration needed for selecting the survivors population
129      @deprecated Use {@link #survivorsSelectionDuration()} instead
130      */
131     @Deprecated
132     public Duration getSurvivorsSelectionDuration() {
133         return _survivorsSelectionDuration;
134     }
135 
136     /**
137      * Return the duration needed for altering the offspring population.
138      *
139      @return the duration needed for altering the offspring population
140      */
141     public Duration offspringAlterDuration() {
142         return _offspringAlterDuration;
143     }
144 
145     /**
146      * Return the duration needed for altering the offspring population.
147      *
148      @return the duration needed for altering the offspring population
149      @deprecated Use {@link #offspringAlterDuration()} instead
150      */
151     @Deprecated
152     public Duration getOffspringAlterDuration() {
153         return _offspringAlterDuration;
154     }
155 
156     /**
157      * Return the duration needed for removing and replacing invalid offspring
158      * individuals.
159      *
160      @return the duration needed for removing and replacing invalid offspring
161      *         individuals
162      */
163     public Duration offspringFilterDuration() {
164         return _offspringFilterDuration;
165     }
166 
167     /**
168      * Return the duration needed for removing and replacing invalid offspring
169      * individuals.
170      *
171      @return the duration needed for removing and replacing invalid offspring
172      *         individuals
173      @deprecated Use {@link #offspringFilterDuration()} instead
174      */
175     @Deprecated
176     public Duration getOffspringFilterDuration() {
177         return _offspringFilterDuration;
178     }
179 
180     /**
181      * Return the duration needed for removing and replacing old and invalid
182      * survivor individuals.
183      *
184      @return the duration needed for removing and replacing old and invalid
185      *         survivor individuals
186      */
187     public Duration survivorFilterDuration() {
188         return _survivorFilterDuration;
189     }
190 
191     /**
192      * Return the duration needed for removing and replacing old and invalid
193      * survivor individuals.
194      *
195      @return the duration needed for removing and replacing old and invalid
196      *         survivor individuals
197      @deprecated Use {@link #survivorFilterDuration()} instead
198      */
199     @Deprecated
200     public Duration getSurvivorFilterDuration() {
201         return _survivorFilterDuration;
202     }
203 
204     /**
205      * Return the duration needed for evaluating the fitness function of the new
206      * individuals.
207      *
208      @return the duration needed for evaluating the fitness function of the new
209      *         individuals
210      */
211     public Duration evaluationDuration() {
212         return _evaluationDuration;
213     }
214 
215     /**
216      * Return the duration needed for evaluating the fitness function of the new
217      * individuals.
218      *
219      @return the duration needed for evaluating the fitness function of the new
220      *         individuals
221      @deprecated Use {@link #evaluationDuration()} instead
222      */
223     @Deprecated
224     public Duration getEvaluationDuration() {
225         return _evaluationDuration;
226     }
227 
228     /**
229      * Return the duration needed for the whole evolve step.
230      *
231      @return the duration needed for the whole evolve step
232      */
233     public Duration evolveDuration() {
234         return _evolveDuration;
235     }
236 
237     /**
238      * Return the duration needed for the whole evolve step.
239      *
240      @return the duration needed for the whole evolve step
241      @deprecated Use {@link #evolveDuration()} instead
242      */
243     @Deprecated
244     public Duration getEvolveDuration() {
245         return _evolveDuration;
246     }
247 
248     /**
249      * Returns a copy of this duration with the specified duration added.
250      <p>
251      * This instance is immutable and unaffected by this method call.
252      *
253      @param other the duration to add
254      @return a {@code EvolutionDurations} based on this duration with the
255      *         specified duration added
256      @throws NullPointerException if the {@code other} duration is {@code null}
257      @throws ArithmeticException if numeric overflow occurs
258      */
259     public EvolutionDurations plus(final EvolutionDurations other) {
260         requireNonNull(other);
261         return of(
262             _offspringSelectionDuration.plus(other._offspringSelectionDuration),
263             _survivorsSelectionDuration.plus(other._survivorsSelectionDuration),
264             _offspringAlterDuration.plus(other._offspringAlterDuration),
265             _offspringFilterDuration.plus(other._offspringFilterDuration),
266             _survivorFilterDuration.plus(other._survivorFilterDuration),
267             _evaluationDuration.plus(other._evaluationDuration),
268             _evolveDuration.plus(other._evolveDuration)
269         );
270     }
271 
272     EvolutionDurations plusEvaluation(final Duration duration) {
273         return of(
274             _offspringSelectionDuration,
275             _survivorsSelectionDuration,
276             _offspringAlterDuration,
277             _offspringFilterDuration,
278             _survivorFilterDuration,
279             _evaluationDuration.plus(duration),
280             _evolveDuration
281         );
282     }
283 
284     EvolutionDurations plusEvolve(final Duration duration) {
285         return of(
286             _offspringSelectionDuration,
287             _survivorsSelectionDuration,
288             _offspringAlterDuration,
289             _offspringFilterDuration,
290             _survivorFilterDuration,
291             _evaluationDuration,
292             _evolveDuration.plus(duration)
293         );
294     }
295 
296     /**
297      * Compares two durations objects. Only the {@link #evolveDuration()}
298      * property is taken into account for the comparison.
299      *
300      @param other the other durations object this object is compared with
301      @return a integer smaller/equal/greater than 0 if the
302      *         {@link #evolveDuration()} property of {@code this} object is
303      *         smaller/equal/greater than the corresponding property of the
304      *         {@code other} project.
305      */
306     @Override
307     public int compareTo(final EvolutionDurations other) {
308         return _evolveDuration.compareTo(other._evolveDuration);
309     }
310 
311     @Override
312     public int hashCode() {
313         return
314             hash(_offspringSelectionDuration,
315             hash(_survivorFilterDuration,
316             hash(_offspringAlterDuration,
317             hash(_offspringFilterDuration,
318             hash(_survivorsSelectionDuration,
319             hash(_evaluationDuration,
320             hash(_evolveDuration)))))));
321     }
322 
323     @Override
324     public boolean equals(final Object obj) {
325         return obj == this ||
326             obj instanceof EvolutionDurations &&
327             Objects.equals(_offspringSelectionDuration,
328                 ((EvolutionDurations)obj)._offspringSelectionDuration&&
329             Objects.equals(_survivorsSelectionDuration,
330                 ((EvolutionDurations)obj)._survivorsSelectionDuration&&
331             Objects.equals(_offspringAlterDuration,
332                 ((EvolutionDurations)obj)._offspringAlterDuration&&
333             Objects.equals(_offspringFilterDuration,
334                 ((EvolutionDurations)obj)._offspringFilterDuration&&
335             Objects.equals(_survivorFilterDuration,
336                 ((EvolutionDurations)obj)._survivorFilterDuration&&
337             Objects.equals(_evaluationDuration,
338                 ((EvolutionDurations)obj)._evaluationDuration&&
339             Objects.equals(_evolveDuration,
340                 ((EvolutionDurations)obj)._evolveDuration);
341     }
342 
343     /**
344      * Return an new {@code EvolutionDurations} object with the given values.
345      *
346      @param offspringSelectionDuration the duration needed for selecting the
347      *        offspring population
348      @param survivorsSelectionDuration the duration needed for selecting the
349      *        survivors population
350      @param offspringAlterDuration the duration needed for altering the
351      *        offspring population
352      @param offspringFilterDuration the duration needed for removing and
353      *        replacing invalid offspring individuals
354      @param survivorFilterDuration the duration needed for removing and
355      *        replacing old and invalid survivor individuals
356      @param evaluationDuration the duration needed for evaluating the fitness
357      *        function of the new individuals
358      @param evolveDuration the duration needed for the whole evolve step
359      @return an new durations object
360      @throws NullPointerException if one of the arguments is
361      *         {@code null}
362      */
363     public static EvolutionDurations of(
364         final Duration offspringSelectionDuration,
365         final Duration survivorsSelectionDuration,
366         final Duration offspringAlterDuration,
367         final Duration offspringFilterDuration,
368         final Duration survivorFilterDuration,
369         final Duration evaluationDuration,
370         final Duration evolveDuration
371     ) {
372         return new EvolutionDurations(
373             offspringSelectionDuration,
374             survivorsSelectionDuration,
375             offspringAlterDuration,
376             offspringFilterDuration,
377             survivorFilterDuration,
378             evaluationDuration,
379             evolveDuration
380         );
381     }
382 
383 
384     /* *************************************************************************
385      *  Java object serialization
386      * ************************************************************************/
387 
388     private Object writeReplace() {
389         return new Serial(Serial.EVOLUTION_DURATIONS, this);
390     }
391 
392     private void readObject(final ObjectInputStream stream)
393         throws InvalidObjectException
394     {
395         throw new InvalidObjectException("Serialization proxy required.");
396     }
397 
398     void write(final ObjectOutput outthrows IOException {
399         writeDuration(_offspringSelectionDuration, out);
400         writeDuration(_survivorsSelectionDuration, out);
401         writeDuration(_offspringAlterDuration, out);
402         writeDuration(_offspringFilterDuration, out);
403         writeDuration(_survivorFilterDuration, out);
404         writeDuration(_evaluationDuration, out);
405         writeDuration(_evolveDuration, out);
406     }
407 
408     private static void writeDuration(final Duration duration, final DataOutput out)
409         throws IOException
410     {
411         writeLong(duration.getSeconds(), out);
412         writeInt(duration.getNano(), out);
413     }
414 
415     @SuppressWarnings({"unchecked""rawtypes"})
416     static EvolutionDurations read(final ObjectInput inthrows IOException {
417         return new EvolutionDurations(
418             readDuration(in),
419             readDuration(in),
420             readDuration(in),
421             readDuration(in),
422             readDuration(in),
423             readDuration(in),
424             readDuration(in)
425         );
426     }
427 
428     private static Duration readDuration(final DataInput inthrows IOException {
429         final long seconds = readLong(in);
430         final int nanos = readInt(in);
431         return Duration.ofSeconds(seconds, nanos);
432     }
433 
434 }