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 */ 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; 027import java.util.concurrent.Executor; 028 029import org.jenetics.internal.util.Concurrency; 030import 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 */ 040public 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}