001 /*
002 * Java Genetic Algorithm Library (jenetics-4.0.0).
003 * Copyright (c) 2007-2017 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 static java.lang.Math.exp;
023 import static java.lang.String.format;
024 import static io.jenetics.internal.math.base.normalize;
025
026 import java.util.Arrays;
027
028 import io.jenetics.internal.util.Hash;
029 import io.jenetics.util.Seq;
030
031 /**
032 * <p>
033 * In this {@code Selector}, the probability for selection is defined as.
034 * </p>
035 * <p><img
036 * src="doc-files/boltzmann-formula1.gif"
037 * alt="P(i)=\frac{\textup{e}^{b\cdot f_i}}{Z}"
038 * >
039 * </p>
040 * where <i>b</i> controls the selection intensity, and
041 * <p><img
042 * src="doc-files/boltzmann-formula2.gif"
043 * alt="Z=\sum_{j=1}^{n}\textrm{e}^{f_j}"
044 * >.
045 * </p>
046 *
047 * <i>f</i><sub><i>j</i></sub> denotes the fitness value of the
048 * <i>j<sup>th</sup></i> individual.
049 * <br>
050 * Positive values of <i>b</i> increases the selection probability of the phenotype
051 * with high fitness values. Negative values of <i>b</i> increases the selection
052 * probability of phenotypes with low fitness values. If <i>b</i> is zero the
053 * selection probability of all phenotypes is set to <sup>1</sup>/<sub>N</sub>.
054 *
055 * @param <G> the gene type.
056 * @param <N> the BoltzmannSelector requires a number type.
057 *
058 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
059 * @since 1.0
060 * @version 4.0
061 */
062 public final class BoltzmannSelector<
063 G extends Gene<?, G>,
064 N extends Number & Comparable<? super N>
065 >
066 extends ProbabilitySelector<G, N>
067 {
068
069 private final double _b;
070
071 /**
072 * Create a new BoltzmannSelector with the given <i>b</i> value. <b>High
073 * absolute values of <i>b</i> can create numerical overflows while
074 * calculating the selection probabilities.</b>
075 *
076 * @param b the <i>b</i> value of this BoltzmannSelector
077 */
078 public BoltzmannSelector(final double b) {
079 _b = b;
080 }
081
082 /**
083 * Create a new BoltzmannSelector with a default beta of 4.0.
084 */
085 public BoltzmannSelector() {
086 this(4.0);
087 }
088
089 @Override
090 protected double[] probabilities(
091 final Seq<Phenotype<G, N>> population,
092 final int count
093 ) {
094 assert population != null : "Population must not be null. ";
095 assert !population.isEmpty() : "Population is empty.";
096 assert count > 0 : "Population to select must be greater than zero. ";
097
098 // Copy the fitness values to probabilities arrays.
099 final double[] fitness = new double[population.size()];
100
101 fitness[0] = population.get(0).getFitness().doubleValue();
102 double min = fitness[0];
103 double max = fitness[0];
104 for (int i = 1; i < fitness.length; ++i) {
105 fitness[i] = population.get(i).getFitness().doubleValue();
106 if (fitness[i] < min) min = fitness[i];
107 else if (fitness[i] > max) max = fitness[i];
108 }
109
110 final double diff = max - min;
111 if (eq(diff, 0.0)) {
112 // Set equal probabilities if diff (almost) zero.
113 Arrays.fill(fitness, 1.0/fitness.length);
114 } else {
115 // Scale fitness values to avoid overflow.
116 for (int i = fitness.length; --i >= 0;) {
117 fitness[i] = (fitness[i] - min)/diff;
118 }
119
120 // Apply the "Boltzmann" function.
121 for (int i = fitness.length; --i >= 0;) {
122 fitness[i] = exp(_b*fitness[i]);
123 }
124 }
125
126 return normalize(fitness);
127 }
128
129 @Override
130 public int hashCode() {
131 return Hash.of(getClass()).and(_b).value();
132 }
133
134 @Override
135 public boolean equals(final Object obj) {
136 return obj instanceof BoltzmannSelector &&
137 Double.compare(((BoltzmannSelector)obj)._b, _b) == 0;
138 }
139
140 @Override
141 public String toString() {
142 return format("BoltzmannSelector[b=%f]", _b);
143 }
144
145 }
|