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