001 /*
002 * Java Genetic Algorithm Library (jenetics-6.0.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 java.util.Objects.requireNonNull;
023 import static io.jenetics.internal.util.Hashes.hash;
024 import static io.jenetics.internal.util.SerialIO.readInt;
025 import static io.jenetics.internal.util.SerialIO.readLong;
026 import static io.jenetics.internal.util.SerialIO.writeInt;
027 import static io.jenetics.internal.util.SerialIO.writeLong;
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 6.0
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 survivors population.
107 *
108 * @return the duration needed for selecting the survivors population
109 */
110 public Duration survivorsSelectionDuration() {
111 return _survivorsSelectionDuration;
112 }
113
114 /**
115 * Return the duration needed for altering the offspring population.
116 *
117 * @return the duration needed for altering the offspring population
118 */
119 public Duration offspringAlterDuration() {
120 return _offspringAlterDuration;
121 }
122
123 /**
124 * Return the duration needed for removing and replacing invalid offspring
125 * individuals.
126 *
127 * @return the duration needed for removing and replacing invalid offspring
128 * individuals
129 */
130 public Duration offspringFilterDuration() {
131 return _offspringFilterDuration;
132 }
133
134 /**
135 * Return the duration needed for removing and replacing old and invalid
136 * survivor individuals.
137 *
138 * @return the duration needed for removing and replacing old and invalid
139 * survivor individuals
140 */
141 public Duration survivorFilterDuration() {
142 return _survivorFilterDuration;
143 }
144
145 /**
146 * Return the duration needed for evaluating the fitness function of the new
147 * individuals.
148 *
149 * @return the duration needed for evaluating the fitness function of the new
150 * individuals
151 */
152 public Duration evaluationDuration() {
153 return _evaluationDuration;
154 }
155
156 /**
157 * Return the duration needed for the whole evolve step.
158 *
159 * @return the duration needed for the whole evolve step
160 */
161 public Duration evolveDuration() {
162 return _evolveDuration;
163 }
164
165 /**
166 * Returns a copy of this duration with the specified duration added.
167 * <p>
168 * This instance is immutable and unaffected by this method call.
169 *
170 * @param other the duration to add
171 * @return a {@code EvolutionDurations} based on this duration with the
172 * specified duration added
173 * @throws NullPointerException if the {@code other} duration is {@code null}
174 * @throws ArithmeticException if numeric overflow occurs
175 */
176 public EvolutionDurations plus(final EvolutionDurations other) {
177 requireNonNull(other);
178 return of(
179 _offspringSelectionDuration.plus(other._offspringSelectionDuration),
180 _survivorsSelectionDuration.plus(other._survivorsSelectionDuration),
181 _offspringAlterDuration.plus(other._offspringAlterDuration),
182 _offspringFilterDuration.plus(other._offspringFilterDuration),
183 _survivorFilterDuration.plus(other._survivorFilterDuration),
184 _evaluationDuration.plus(other._evaluationDuration),
185 _evolveDuration.plus(other._evolveDuration)
186 );
187 }
188
189 EvolutionDurations plusEvaluation(final Duration duration) {
190 return of(
191 _offspringSelectionDuration,
192 _survivorsSelectionDuration,
193 _offspringAlterDuration,
194 _offspringFilterDuration,
195 _survivorFilterDuration,
196 _evaluationDuration.plus(duration),
197 _evolveDuration
198 );
199 }
200
201 EvolutionDurations plusEvolve(final Duration duration) {
202 return of(
203 _offspringSelectionDuration,
204 _survivorsSelectionDuration,
205 _offspringAlterDuration,
206 _offspringFilterDuration,
207 _survivorFilterDuration,
208 _evaluationDuration,
209 _evolveDuration.plus(duration)
210 );
211 }
212
213 /**
214 * Compares two durations objects. Only the {@link #evolveDuration()}
215 * property is taken into account for the comparison.
216 *
217 * @param other the other durations object this object is compared with
218 * @return a integer smaller/equal/greater than 0 if the
219 * {@link #evolveDuration()} property of {@code this} object is
220 * smaller/equal/greater than the corresponding property of the
221 * {@code other} project.
222 */
223 @Override
224 public int compareTo(final EvolutionDurations other) {
225 return _evolveDuration.compareTo(other._evolveDuration);
226 }
227
228 @Override
229 public int hashCode() {
230 return
231 hash(_offspringSelectionDuration,
232 hash(_survivorFilterDuration,
233 hash(_offspringAlterDuration,
234 hash(_offspringFilterDuration,
235 hash(_survivorsSelectionDuration,
236 hash(_evaluationDuration,
237 hash(_evolveDuration)))))));
238 }
239
240 @Override
241 public boolean equals(final Object obj) {
242 return obj == this ||
243 obj instanceof EvolutionDurations &&
244 Objects.equals(_offspringSelectionDuration,
245 ((EvolutionDurations)obj)._offspringSelectionDuration) &&
246 Objects.equals(_survivorsSelectionDuration,
247 ((EvolutionDurations)obj)._survivorsSelectionDuration) &&
248 Objects.equals(_offspringAlterDuration,
249 ((EvolutionDurations)obj)._offspringAlterDuration) &&
250 Objects.equals(_offspringFilterDuration,
251 ((EvolutionDurations)obj)._offspringFilterDuration) &&
252 Objects.equals(_survivorFilterDuration,
253 ((EvolutionDurations)obj)._survivorFilterDuration) &&
254 Objects.equals(_evaluationDuration,
255 ((EvolutionDurations)obj)._evaluationDuration) &&
256 Objects.equals(_evolveDuration,
257 ((EvolutionDurations)obj)._evolveDuration);
258 }
259
260 /**
261 * Return an new {@code EvolutionDurations} object with the given values.
262 *
263 * @param offspringSelectionDuration the duration needed for selecting the
264 * offspring population
265 * @param survivorsSelectionDuration the duration needed for selecting the
266 * survivors population
267 * @param offspringAlterDuration the duration needed for altering the
268 * offspring population
269 * @param offspringFilterDuration the duration needed for removing and
270 * replacing invalid offspring individuals
271 * @param survivorFilterDuration the duration needed for removing and
272 * replacing old and invalid survivor individuals
273 * @param evaluationDuration the duration needed for evaluating the fitness
274 * function of the new individuals
275 * @param evolveDuration the duration needed for the whole evolve step
276 * @return an new durations object
277 * @throws NullPointerException if one of the arguments is
278 * {@code null}
279 */
280 public static EvolutionDurations of(
281 final Duration offspringSelectionDuration,
282 final Duration survivorsSelectionDuration,
283 final Duration offspringAlterDuration,
284 final Duration offspringFilterDuration,
285 final Duration survivorFilterDuration,
286 final Duration evaluationDuration,
287 final Duration evolveDuration
288 ) {
289 return new EvolutionDurations(
290 offspringSelectionDuration,
291 survivorsSelectionDuration,
292 offspringAlterDuration,
293 offspringFilterDuration,
294 survivorFilterDuration,
295 evaluationDuration,
296 evolveDuration
297 );
298 }
299
300
301 /* *************************************************************************
302 * Java object serialization
303 * ************************************************************************/
304
305 private Object writeReplace() {
306 return new Serial(Serial.EVOLUTION_DURATIONS, this);
307 }
308
309 private void readObject(final ObjectInputStream stream)
310 throws InvalidObjectException
311 {
312 throw new InvalidObjectException("Serialization proxy required.");
313 }
314
315 void write(final ObjectOutput out) throws IOException {
316 writeDuration(_offspringSelectionDuration, out);
317 writeDuration(_survivorsSelectionDuration, out);
318 writeDuration(_offspringAlterDuration, out);
319 writeDuration(_offspringFilterDuration, out);
320 writeDuration(_survivorFilterDuration, out);
321 writeDuration(_evaluationDuration, out);
322 writeDuration(_evolveDuration, out);
323 }
324
325 private static void writeDuration(final Duration duration, final DataOutput out)
326 throws IOException
327 {
328 writeLong(duration.getSeconds(), out);
329 writeInt(duration.getNano(), out);
330 }
331
332 static EvolutionDurations read(final ObjectInput in) throws IOException {
333 return new EvolutionDurations(
334 readDuration(in),
335 readDuration(in),
336 readDuration(in),
337 readDuration(in),
338 readDuration(in),
339 readDuration(in),
340 readDuration(in)
341 );
342 }
343
344 private static Duration readDuration(final DataInput in) throws IOException {
345 final long seconds = readLong(in);
346 final int nanos = readInt(in);
347 return Duration.ofSeconds(seconds, nanos);
348 }
349
350 }
|