accumulators.java
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 &mdash; <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 &ndash; <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(_min0) {
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 &ndash; <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(_max0) {
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 &ndash; <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(_min0) {
300                     _min = value;
301                 else if (value.compareTo(_max0) {
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 }