RouletteWheelSelector.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-8.0.0).
003  * Copyright (c) 2007-2024 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@gmail.com)
019  */
020 package io.jenetics;
021 
022 import java.util.Arrays;
023 
024 import io.jenetics.internal.math.DoubleAdder;
025 import io.jenetics.stat.DoubleSummary;
026 import io.jenetics.util.BaseSeq;
027 import io.jenetics.util.Seq;
028 
029 /**
030  * The roulette-wheel selector is also known as fitness proportional selector,
031  * but in the <em>Jenetics</em> library it is implemented as probability selector.
032  * The fitness value <i>f<sub>i</sub></i>  is used to calculate the selection
033  * probability of individual <i>i</i>.
034  *
035  @see <a href="http://en.wikipedia.org/wiki/Roulette_wheel_selection">
036  *          Wikipedia: Roulette wheel selection
037  *      </a>
038  *
039  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040  @since 1.0
041  @version 5.0
042  */
043 public class RouletteWheelSelector<
044     extends Gene<?, G>,
045     extends Number & Comparable<? super N>
046 >
047     extends ProbabilitySelector<G, N>
048 {
049 
050     public RouletteWheelSelector() {
051         this(false);
052     }
053 
054     protected RouletteWheelSelector(final boolean sorted) {
055         super(sorted);
056     }
057 
058     @Override
059     protected double[] probabilities(
060         final Seq<Phenotype<G, N>> population,
061         final int count
062     ) {
063         assert population != null "Population must not be null. ";
064         assert population.nonEmpty() "Population is empty.";
065         assert count > "Population to select must be greater than zero. ";
066 
067         final double[] fitness = fitnessOf(population);
068         sub(fitness, Math.min(DoubleSummary.min(fitness)0.0));
069         final double sum = DoubleAdder.sum(fitness);
070 
071         if (eq(sum, 0.0)) {
072             Arrays.fill(fitness, 1.0/population.size());
073         else {
074             for (int i = fitness.length; --i >= 0;) {
075                 fitness[i= fitness[i]/sum;
076             }
077         }
078 
079         return fitness;
080     }
081 
082     private double[] fitnessOf(final BaseSeq<Phenotype<G, N>> population) {
083         final double[] fitness = new double[population.length()];
084         for (int i = fitness.length; --i >= 0;) {
085             final double fit = population.get(i).fitness().doubleValue();
086             fitness[i= Double.isFinite(fit? fit : 0.0;
087         }
088         return fitness;
089     }
090 
091     private static void sub(final double[] values, final double subtrahend) {
092         if (Double.compare(subtrahend, 0.0!= 0) {
093             for (int i = values.length; --i >= 0;) {
094                 values[i-= subtrahend;
095             }
096         }
097     }
098 
099     @Override
100     public String toString() {
101         return getClass().getSimpleName();
102     }
103 
104 }