001/* 002 * Java Genetic Algorithm Library (jenetics-7.1.0). 003 * Copyright (c) 2007-2022 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.nextDown; 023import static java.lang.String.format; 024import static io.jenetics.internal.math.Basics.clamp; 025 026import java.util.random.RandomGenerator; 027 028/** 029 * The GaussianMutator class performs the mutation of a {@link NumericGene}. 030 * This mutator picks a new value based on a Gaussian distribution around the 031 * current value of the gene. The variance of the new value (before clipping to 032 * the allowed gene range) will be 033 * <p> 034 * <img 035 * src="doc-files/gaussian-mutator-var.svg" 036 * alt="\hat{\sigma }^2 = \left ( \frac{ g_{max} - g_{min} }{4}\right )^2" 037 * > 038 * </p> 039 * The new value will be cropped to the gene's boundaries. 040 * 041 * 042 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 043 * @since 1.0 044 * @version 6.1 045 */ 046public class GaussianMutator< 047 G extends NumericGene<?, G>, 048 C extends Comparable<? super C> 049> 050 extends Mutator<G, C> 051{ 052 053 public GaussianMutator(final double probability) { 054 super(probability); 055 } 056 057 public GaussianMutator() { 058 this(DEFAULT_ALTER_PROBABILITY); 059 } 060 061 @Override 062 protected G mutate(final G gene, final RandomGenerator random) { 063 return gene.isValid() ? mutate0(gene, random) : gene; 064 } 065 066 private G mutate0(final G gene, final RandomGenerator random) { 067 final double min = gene.min().doubleValue(); 068 final double max = gene.max().doubleValue(); 069 final double std = (max - min)*0.25; 070 071 final double value = gene.doubleValue(); 072 final double gaussian = random.nextGaussian(); 073 return gene.newInstance(clamp(gaussian*std + value, min, nextDown(max))); 074 } 075 076 @Override 077 public String toString() { 078 return format("%s[p=%f]", getClass().getSimpleName(), _probability); 079 } 080 081}