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