ExponentialRankSelector.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;
021 
022 import static java.lang.Math.pow;
023 import static java.lang.String.format;
024 import static org.jenetics.internal.util.object.eq;
025 
026 import javolution.lang.Immutable;
027 
028 import org.jenetics.internal.util.HashBuilder;
029 
030 /**
031  <p>
032  * An alternative to the "weak" {@code LinearRankSelector} is to assign
033  * survival probabilities to the sorted individuals using an exponential
034  * function.
035  </p>
036  <p><img
037  *        src="doc-files/exponential-rank-selector.gif"
038  *        alt="P(i)=\left(c-1\right)\frac{c^{i-1}}{c^{N}-1}"
039  *     >,
040  </p>
041  * where <i>c</i> must within the range {@code [0..1)}.
042  *
043  <p>
044  * A small value of <i>c</i> increases the probability of the best phenotypes to
045  * be selected. If <i>c</i> is set to zero, the selection probability of the best
046  * phenotype is set to one. The selection probability of all other phenotypes is
047  * zero. A value near one equalizes the selection probabilities.
048  </p>
049  <p>
050  * This selector sorts the population in descending order while calculating the
051  * selection probabilities.
052  </p>
053  *
054  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
055  @since 1.0
056  @version 1.0 &mdash; <em>$Date: 2014-03-01 $</em>
057  */
058 public final class ExponentialRankSelector<
059     extends Gene<?, G>,
060     extends Comparable<? super C>
061 >
062     extends ProbabilitySelector<G, C>
063     implements Immutable
064 {
065 
066     private final double _c;
067 
068     /**
069      * Create a new exponential rank selector.
070      *
071      @param c the <i>c</i> value.
072      @throws IllegalArgumentException if {@code c} is not within the range
073      *         {@code [0..1)}.
074      */
075     public ExponentialRankSelector(final double c) {
076         if (c < 0.0 || c >= 1.0) {
077             throw new IllegalArgumentException(format(
078                 "Value %s is out of range [0..1): ", c
079             ));
080         }
081         _c = c;
082     }
083 
084     /**
085      * This method sorts the population in descending order while calculating the
086      * selection probabilities. (The method {@link Population#sort()} is called
087      * by this method.)
088      */
089     @Override
090     protected double[] probabilities(
091         final Population<G, C> population,
092         final int count
093     ) {
094         assert(population != null"Population can not be null. ";
095         assert(count > 0"Population to select must be greater than zero. ";
096 
097         //Sorted population required.
098         population.sort();
099 
100         final double N = population.size();
101         final double[] probabilities = new double[population.size()];
102 
103         final double b = pow(_c, N1;
104         for (int i = probabilities.length; --i >= 0;) {
105             probabilities[i((_c - 1)*pow(_c, i))/b;
106         }
107 
108         assert (sum2one(probabilities)) "Probabilities doesn't sum to one.";
109         return probabilities;
110     }
111 
112     @Override
113     public int hashCode() {
114         return HashBuilder.of(getClass()).and(_c).value();
115     }
116 
117     @Override
118     public boolean equals(final Object obj) {
119         if (obj == this) {
120             return true;
121         }
122         if (obj == null || obj.getClass() != getClass()) {
123             return false;
124         }
125 
126         final ExponentialRankSelector<?, ?> selector = (ExponentialRankSelector<?, ?>)obj;
127         return eq(_c, selector._c);
128     }
129 
130     @Override
131     public String toString() {
132         return format("%s[c=%f]", getClass().getSimpleName(), _c);
133     }
134 
135 }