accumulators.java
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  */
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 
028 import org.jscience.mathematics.structure.GroupAdditive;
029 
030 import 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  */
041 public 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(_min0) {
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(_max0) {
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(_min0) {
301                     _min = value;
302                 else if (value.compareTo(_max0) {
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 }