GaussianMutator.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.6.0).
003  * Copyright (c) 2007-2014 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.String.format;
023 
024 import java.util.Random;
025 
026 import javolution.lang.Immutable;
027 
028 import org.jenetics.internal.util.HashBuilder;
029 
030 import org.jenetics.util.IndexStream;
031 import org.jenetics.util.MSeq;
032 import org.jenetics.util.RandomRegistry;
033 import org.jenetics.util.math;
034 
035 /**
036  * The GaussianMutator class performs the mutation of a {@link NumericGene}.
037  * This mutator picks a new value based on a Gaussian distribution around the
038  * current value of the gene. The variance of the new value (before clipping to
039  * the allowed gene range) will be
040  <p>
041  <img
042  *     src="doc-files/gaussian-mutator-var.gif"
043  *     alt="\hat{\sigma }^2 = \left ( \frac{ g_{max} - g_{min} }{4}\right )^2"
044  * >
045  </p>
046  * The new value will be cropped to the gene's boundaries.
047  *
048  *
049  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
050  @since 1.0
051  @version 1.6 &mdash; <em>$Date: 2014-03-05 $</em>
052  */
053 public final class GaussianMutator<G extends NumericGene<?, G>>
054     extends Mutator<G>
055     implements Immutable
056 {
057 
058     public GaussianMutator() {
059     }
060 
061     public GaussianMutator(final double probability) {
062         super(probability);
063     }
064 
065     @Override
066     protected int mutate(final MSeq<G> genes, final double p) {
067         final Random random = RandomRegistry.getRandom();
068         final IndexStream stream = IndexStream.Random(genes.length(), p);
069 
070         int alterations = 0;
071         for (int i = stream.next(); i != -1; i = stream.next()) {
072             genes.set(i, mutate(genes.get(i), random));
073 
074             ++alterations;
075         }
076 
077         return alterations;
078     }
079 
080     G mutate(final G gene, final Random random) {
081         final double std = (
082             gene.getMax().doubleValue() - gene.getMin().doubleValue()
083         )*0.25;
084 
085         return gene.newInstance(math.clamp(
086             random.nextGaussian()*std + gene.doubleValue(),
087             gene.getMin().doubleValue(),
088             gene.getMax().doubleValue()
089         ));
090     }
091 
092     @Override
093     public int hashCode() {
094         return HashBuilder.of(getClass()).and(super.hashCode()).value();
095     }
096 
097     @Override
098     public boolean equals(final Object obj) {
099         if (obj == this) {
100             return true;
101         }
102         if (obj == null || obj.getClass() != getClass()) {
103             return false;
104         }
105 
106         return super.equals(obj);
107     }
108 
109     @Override
110     public String toString() {
111         return format(
112             "%s[p=%f]",
113             getClass().getSimpleName(),
114             _probability
115         );
116     }
117 
118 }