RouletteWheelSelector.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.0.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;
021 
022 import static java.lang.Math.abs;
023 import static org.jenetics.internal.math.arithmetic.pow;
024 import static org.jenetics.internal.math.base.ulpDistance;
025 import static org.jenetics.internal.math.statistics.min;
026 
027 import java.util.Arrays;
028 
029 import org.jenetics.internal.math.DoubleAdder;
030 import org.jenetics.internal.util.Equality;
031 import org.jenetics.internal.util.Hash;
032 
033 /**
034  * The roulette-wheel selector is also known as fitness proportional selector,
035  * but in the <em>Jenetics</em> library it is implemented as probability selector.
036  * The fitness value <i>f<sub>i</sub></i>  is used to calculate the selection
037  * probability of individual <i>i</i>.
038  *
039  @see <a href="http://en.wikipedia.org/wiki/Roulette_wheel_selection">
040  *          Wikipedia: Roulette wheel selection
041  *      </a>
042  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
043  @since 1.0
044  @version 2.0 &mdash; <em>$Date: 2014-12-28 $</em>
045  */
046 public class RouletteWheelSelector<
047     extends Gene<?, G>,
048     extends Number & Comparable<? super N>
049 >
050     extends ProbabilitySelector<G, N>
051 {
052 
053     private static final long MAX_ULP_DISTANCE = pow(109);
054 
055     public RouletteWheelSelector() {
056     }
057 
058     @Override
059     protected double[] probabilities(
060         final Population<G, N> population,
061         final int count
062     ) {
063         assert(population != null"Population can not be null. ";
064         assert(count > 0"Population to select must be greater than zero. ";
065 
066         // Copy the fitness values to probabilities arrays.
067         final double[] fitness = new double[population.size()];
068         for (int i = population.size(); --i >= 0;) {
069             fitness[i= population.get(i).getFitness().doubleValue();
070         }
071 
072         final double worst = Math.min(min(fitness)0.0);
073         final double sum = DoubleAdder.sum(fitness- worst*population.size();
074 
075         if (abs(ulpDistance(sum, 0.0)) > MAX_ULP_DISTANCE) {
076             for (int i = population.size(); --i >= 0;) {
077                 fitness[i(fitness[i- worst)/sum;
078             }
079         else {
080             Arrays.fill(fitness, 1.0/population.size());
081         }
082 
083         assert (sum2one(fitness)) "Probabilities doesn't sum to one.";
084         return fitness;
085     }
086 
087     @Override
088     public int hashCode() {
089         return Hash.of(getClass()).value();
090     }
091 
092     @Override
093     public boolean equals(final Object obj) {
094         return Equality.ofType(this, obj);
095     }
096 
097     @Override
098     public String toString() {
099         return getClass().getSimpleName();
100     }
101 
102 }