001 /*
002 * Java Genetic Algorithm Library (jenetics-2.0.2).
003 * Copyright (c) 2007-2014 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@gmx.at)
019 */
020 package org.jenetics.util;
021
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static org.jenetics.internal.util.object.eq;
025
026 import java.util.Iterator;
027 import java.util.concurrent.Executor;
028
029 import org.jenetics.internal.util.Concurrency;
030 import org.jenetics.internal.util.HashBuilder;
031
032 /**
033 * Collection of some general purpose Accumulators and some static helper classes
034 * for accumulating.
035 *
036 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
037 * @since 1.0
038 * @version 2.0 — <em>$Date: 2014-04-11 $</em>
039 */
040 public final class accumulators extends StaticObject {
041 private accumulators() {}
042
043 public static final Accumulator<Object> NULL = new Accumulator<Object>() {
044 @Override
045 public void accumulate(final Object value) {
046 }
047 };
048
049 /**
050 * Calculates min value.
051 *
052 * <p>
053 * <strong>Note that this implementation is not synchronized.</strong> If
054 * multiple threads access this object concurrently, and at least one of the
055 * threads modifies it, it must be synchronized externally.
056 *
057 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
058 * @since 1.0
059 * @version 1.0 – <em>$Date: 2014-04-11 $</em>
060 */
061 public static final class Min<C extends Comparable<? super C>>
062 extends MappedAccumulator<C>
063 {
064 private C _min;
065
066 /**
067 * Create a new Min accumulator.
068 */
069 public Min() {
070 }
071
072 /**
073 * Copy constructor.
074 *
075 * @param min the accumulator to copy.
076 * @throws NullPointerException if {@code min} is {@code null}.
077 */
078 public Min(final Min<C> min) {
079 requireNonNull(min, "Min");
080 _samples = min._samples;
081 _min = min._min;
082 }
083
084 /**
085 * Return the min value, accumulated so far.
086 *
087 * @return the min value, accumulated so far.
088 */
089 public C getMin() {
090 return _min;
091 }
092
093 /**
094 * @throws NullPointerException if the given {@code value} is {@code null}.
095 */
096 @Override
097 public void accumulate(final C value) {
098 if (_min == null) {
099 _min = value;
100 } else {
101 if (value.compareTo(_min) < 0) {
102 _min = value;
103 }
104 }
105
106 ++_samples;
107 }
108
109 @Override
110 public int hashCode() {
111 return HashBuilder.of(getClass()).and(super.hashCode()).and(_min).value();
112 }
113
114 @Override
115 public boolean equals(final Object obj) {
116 if (obj == this) {
117 return true;
118 }
119 if (obj == null || obj.getClass() != getClass()) {
120 return false;
121 }
122
123 final Min<?> min = (Min<?>)obj;
124 return super.equals(obj) && eq(_min, min._min);
125 }
126
127 @Override
128 public String toString() {
129 return format(
130 "%s[samples=%d, min=%s]",
131 getClass().getSimpleName(), getSamples(), getMin()
132 );
133 }
134
135 @Override
136 public Min<C> clone() {
137 return (Min<C>)super.clone();
138 }
139 }
140
141
142 /**
143 * Calculates max value.
144 *
145 * <p>
146 * <strong>Note that this implementation is not synchronized.</strong> If
147 * multiple threads access this object concurrently, and at least one of the
148 * threads modifies it, it must be synchronized externally.
149 *
150 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
151 * @since 1.0
152 * @version 1.0 – <em>$Date: 2014-04-11 $</em>
153 */
154 public static final class Max<C extends Comparable<? super C>>
155 extends MappedAccumulator<C>
156 {
157 private C _max;
158
159 /**
160 * Create a new Max accumulator.
161 */
162 public Max() {
163 }
164
165 /**
166 * Copy constructor.
167 *
168 * @param max the accumulator to copy.
169 * @throws NullPointerException if {@code max} is {@code null}.
170 */
171 public Max(final Max<C> max) {
172 requireNonNull(max, "Max");
173 _samples = max._samples;
174 _max = max._max;
175 }
176
177 /**
178 * Return the max value, accumulated so far.
179 *
180 * @return the max value, accumulated so far.
181 */
182 public C getMax() {
183 return _max;
184 }
185
186 /**
187 * @throws NullPointerException if the given {@code value} is {@code null}.
188 */
189 @Override
190 public void accumulate(final C value) {
191 if (_max == null) {
192 _max = value;
193 } else {
194 if (value.compareTo(_max) > 0) {
195 _max = value;
196 }
197 }
198
199 ++_samples;
200 }
201
202 @Override
203 public int hashCode() {
204 return HashBuilder.of(getClass()).and(super.hashCode()).and(_max).value();
205 }
206
207 @Override
208 public boolean equals(final Object obj) {
209 if (obj == this) {
210 return true;
211 }
212 if (obj == null || obj.getClass() != getClass()) {
213 return false;
214 }
215
216 final Max<?> max = (Max<?>)obj;
217 return super.equals(obj) && eq(_max, max._max);
218 }
219
220 @Override
221 public String toString() {
222 return format(
223 "%s[samples=%d, max=%s]",
224 getClass().getSimpleName(), getSamples(), getMax()
225 );
226 }
227
228 @Override
229 public Max<C> clone() {
230 return (Max<C>)super.clone();
231 }
232 }
233
234
235 /**
236 * Calculates min and max values.
237 *
238 * <p>
239 * <strong>Note that this implementation is not synchronized.</strong> If
240 * multiple threads access this object concurrently, and at least one of the
241 * threads modifies it, it must be synchronized externally.
242 *
243 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
244 * @since 1.0
245 * @version 1.0 – <em>$Date: 2014-04-11 $</em>
246 */
247 public static final class MinMax<C extends Comparable<? super C>>
248 extends MappedAccumulator<C>
249 {
250 private C _min;
251 private C _max;
252
253 /**
254 * Create a new min-max accumulator.
255 */
256 public MinMax() {
257 }
258
259 /**
260 * Copy constructor.
261 *
262 * @param mm the accumulator to copy.
263 * @throws NullPointerException if {@code mm} is {@code null}.
264 */
265 public MinMax(final MinMax<C> mm) {
266 requireNonNull(mm, "MinMax");
267 _samples = mm._samples;
268 _min = mm._min;
269 _max = mm._max;
270 }
271
272 /**
273 * Return the min value, accumulated so far.
274 *
275 * @return the min value, accumulated so far.
276 */
277 public C getMin() {
278 return _min;
279 }
280
281 /**
282 * Return the max value, accumulated so far.
283 *
284 * @return the max value, accumulated so far.
285 */
286 public C getMax() {
287 return _max;
288 }
289
290 /**
291 * @throws NullPointerException if the given {@code value} is {@code null}.
292 */
293 @Override
294 public void accumulate(final C value) {
295 if (_min == null) {
296 _min = value;
297 _max = value;
298 } else {
299 if (value.compareTo(_min) < 0) {
300 _min = value;
301 } else if (value.compareTo(_max) > 0) {
302 _max = value;
303 }
304 }
305
306 ++_samples;
307 }
308
309 @Override
310 public int hashCode() {
311 return HashBuilder.of(getClass()).
312 and(super.hashCode()).
313 and(_min).
314 and(_max).value();
315 }
316
317 @Override
318 public boolean equals(final Object obj) {
319 if (obj == this) {
320 return true;
321 }
322 if (obj == null || obj.getClass() != getClass()) {
323 return false;
324 }
325
326 final MinMax<?> mm = (MinMax<?>)obj;
327 return super.equals(obj) && eq(_min, mm._min) && eq(_max, mm._max);
328 }
329
330 @Override
331 public String toString() {
332 return format(
333 "%s[samples=%d, min=%s, max=%s]",
334 getClass().getSimpleName(), getSamples(), getMin(), getMax()
335 );
336 }
337
338 @Override
339 public MinMax<C> clone() {
340 return (MinMax<C>)super.clone();
341 }
342 }
343
344 /**
345 * Calls the {@link Accumulator#accumulate(Object)} method of all given
346 * {@code accumulators} with each value of the given {@code values}. The
347 * accumulation is done in parallel.
348 *
349 * @param <T> the value type.
350 * @param values the values to accumulate.
351 * @param accus the accumulators to apply.
352 * @throws NullPointerException if one of the given arguments is {@code null}.
353 */
354 public static <T> void accumulate(
355 final Executor executor,
356 final Iterable<? extends T> values,
357 final Seq<? extends Accumulator<? super T>> accus
358 ) {
359 switch (accus.length()) {
360 case 1:
361 accumulate(
362 values,
363 accus.get(0)
364 );
365 break;
366 case 2:
367 accumulate(
368 executor,
369 values,
370 accus.get(0),
371 accus.get(1)
372 );
373 break;
374 case 3:
375 accumulate(
376 executor,
377 values,
378 accus.get(0),
379 accus.get(1),
380 accus.get(2)
381 );
382 break;
383 case 4:
384 accumulate(
385 executor,
386 values,
387 accus.get(0),
388 accus.get(1),
389 accus.get(2),
390 accus.get(3)
391 );
392 break;
393 case 5:
394 accumulate(
395 executor,
396 values,
397 accus.get(0),
398 accus.get(1),
399 accus.get(2),
400 accus.get(3),
401 accus.get(4)
402 );
403 break;
404 default:
405 try (Concurrency c = Concurrency.with(executor)) {
406 c.execute(accus.map(AccumulatorToRunnable(values)).asList());
407 }
408 }
409 }
410
411 private static <T> Function<Accumulator<? super T>, Runnable>
412 AccumulatorToRunnable(final Iterable<? extends T> values) {
413 return new Function<Accumulator<? super T>, Runnable>() {
414 @Override
415 public Runnable apply(final Accumulator<? super T> accumulator) {
416 return new Acc<>(values, accumulator);
417 }
418 };
419 }
420
421 /**
422 * Calls the {@link Accumulator#accumulate(Object)} method of all given
423 * {@code accumulators} with each value of the given {@code values}. The
424 * accumulation is done in parallel.
425 *
426 * @param <T> the value type.
427 * @param values the values to accumulate.
428 * @param accus the accumulators to apply.
429 * @throws NullPointerException if one of the given arguments is {@code null}.
430 */
431 @SafeVarargs
432 public static <T> void accumulate(
433 final Executor executor,
434 final Iterable<? extends T> values,
435 final Accumulator<? super T>... accus
436 ) {
437 accumulate(executor, values, Array.of(accus));
438 }
439
440 /**
441 * Calls the {@link Accumulator#accumulate(Object)} method of the given
442 * {@code accumulator} with each value of the given {@code values}.
443 *
444 * @param <T> the value type.
445 * @param values the values to accumulate.
446 * @param a the accumulator.
447 * @throws NullPointerException if one of the given arguments is {@code null}.
448 */
449 public static <T> void accumulate(
450 final Iterator<? extends T> values,
451 final Accumulator<? super T> a
452 ) {
453 while (values.hasNext()) {
454 a.accumulate(values.next());
455 }
456 }
457
458 /**
459 * Calls the {@link Accumulator#accumulate(Object)} method of the given
460 * {@code accumulator} with each value of the given {@code values}.
461 *
462 * @param <T> the value type.
463 * @param values the values to accumulate.
464 * @param a the accumulator.
465 * @throws NullPointerException if one of the given arguments is {@code null}.
466 */
467 public static <T> void accumulate(
468 final Iterable<? extends T> values,
469 final Accumulator<? super T> a
470 ) {
471 for (final T value : values) {
472 a.accumulate(value);
473 }
474 }
475
476 /**
477 * Calls the {@link Accumulator#accumulate(Object)} method of all given
478 * {@code accumulators} with each value of the given {@code values}. The
479 * accumulation is done in parallel.
480 *
481 * @param <T> the value type.
482 * @param values the values to accumulate.
483 * @param a1 the first accumulator.
484 * @param a2 the second accumulator.
485 * @throws NullPointerException if one of the given arguments is {@code null}.
486 */
487 public static <T> void accumulate(
488 final Executor executor,
489 final Iterable<? extends T> values,
490 final Accumulator<? super T> a1,
491 final Accumulator<? super T> a2
492 ) {
493 try (Concurrency c = Concurrency.with(executor)) {
494 c.execute(new Acc<>(values, a1));
495 c.execute(new Acc<>(values, a2));
496 }
497 }
498
499 /**
500 * Calls the {@link Accumulator#accumulate(Object)} method of all given
501 * {@code accumulators} with each value of the given {@code values}. The
502 * accumulation is done in parallel.
503 *
504 * @param <T> the value type.
505 * @param values the values to accumulate.
506 * @param a1 the first accumulator.
507 * @param a2 the second accumulator.
508 * @param a3 the third accumulator
509 * @throws NullPointerException if one of the given arguments is {@code null}.
510 */
511 public static <T> void accumulate(
512 final Executor executor,
513 final Iterable<? extends T> values,
514 final Accumulator<? super T> a1,
515 final Accumulator<? super T> a2,
516 final Accumulator<? super T> a3
517 ) {
518 try (Concurrency c = Concurrency.with(executor)) {
519 c.execute(new Acc<>(values, a1));
520 c.execute(new Acc<>(values, a2));
521 c.execute(new Acc<>(values, a3));
522 }
523 }
524
525 /**
526 * Calls the {@link Accumulator#accumulate(Object)} method of all given
527 * {@code accumulators} with each value of the given {@code values}. The
528 * accumulation is done in parallel.
529 *
530 * @param <T> the value type.
531 * @param values the values to accumulate.
532 * @param a1 the first accumulator.
533 * @param a2 the second accumulator.
534 * @param a3 the third accumulator.
535 * @param a4 the fourth accumulator.
536 * @throws NullPointerException if one of the given arguments is {@code null}.
537 */
538 public static <T> void accumulate(
539 final Executor executor,
540 final Iterable<? extends T> values,
541 final Accumulator<? super T> a1,
542 final Accumulator<? super T> a2,
543 final Accumulator<? super T> a3,
544 final Accumulator<? super T> a4
545 ) {
546 try (Concurrency c = Concurrency.with(executor)) {
547 c.execute(new Acc<>(values, a1));
548 c.execute(new Acc<>(values, a2));
549 c.execute(new Acc<>(values, a3));
550 c.execute(new Acc<>(values, a4));
551 }
552 }
553
554 /**
555 * Calls the {@link Accumulator#accumulate(Object)} method of all given
556 * {@code accumulators} with each value of the given {@code values}. The
557 * accumulation is done in parallel.
558 *
559 * @param <T> the value type.
560 * @param values the values to accumulate.
561 * @param a1 the first accumulator.
562 * @param a2 the second accumulator.
563 * @param a3 the third accumulator.
564 * @param a4 the fourth accumulator.
565 * @param a5 the fifth accumulator.
566 * @throws NullPointerException if one of the given arguments is {@code null}.
567 */
568 public static <T> void accumulate(
569 final Executor executor,
570 final Iterable<? extends T> values,
571 final Accumulator<? super T> a1,
572 final Accumulator<? super T> a2,
573 final Accumulator<? super T> a3,
574 final Accumulator<? super T> a4,
575 final Accumulator<? super T> a5
576 ) {
577 try (Concurrency c = Concurrency.with(executor)) {
578 c.execute(new Acc<>(values, a1));
579 c.execute(new Acc<>(values, a2));
580 c.execute(new Acc<>(values, a3));
581 c.execute(new Acc<>(values, a4));
582 c.execute(new Acc<>(values, a5));
583 }
584 }
585
586 private static final class Acc<T> implements Runnable {
587 private final Iterable<? extends T> _values;
588 private final Accumulator<? super T> _accumulator;
589
590 public Acc(
591 final Iterable<? extends T> values,
592 final Accumulator<? super T> accumulator
593 ) {
594 _values = values;
595 _accumulator = accumulator;
596 }
597
598 @Override
599 public void run() {
600 for (final T value : _values) {
601 _accumulator.accumulate(value);
602 }
603 }
604 }
605
606 }
|