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