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