/* Copyright 2009-2016 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * The MOEA Framework is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package org.moeaframework.algorithm.single; import org.moeaframework.core.PRNG; import org.moeaframework.core.Solution; import org.moeaframework.core.Variation; import org.moeaframework.core.variable.RealVariable; /** * Self adaptive variation based on the normal distribution. The self adaptive * parameter {@code sigma} is stored as the {@value SIGMA} attribute. Each * call to {@link #evolve(Solution[])} performs the following changes: * <pre> * sigma = sigma * e^(tau * N(0,1)) * vars = vars + sigma * N(0,I) * </pre> * where {@code N(0,1)} and {@code N(0,I)} are normally-distributed random * numbers with mean {@code 0} and standard deviation {@code 1}. */ public class SelfAdaptiveNormalVariation implements Variation { /** * The attribute for storing the self adaptive parameter. */ public static final String SIGMA = "sigma"; @Override public int getArity() { return 1; } @Override public Solution[] evolve(Solution[] parents) { Solution child = parents[0].copy(); double sigma = 1.0; double tau = 1.0 / Math.sqrt(2.0 * child.getNumberOfVariables()); if (child.hasAttribute(SIGMA)) { sigma = (Double)child.getAttribute(SIGMA); } sigma *= Math.exp(tau*PRNG.nextGaussian()); child.setAttribute(SIGMA, sigma); for (int i = 0; i < child.getNumberOfVariables(); i++) { RealVariable variable = (RealVariable)child.getVariable(i); double value = variable.getValue(); value += sigma * PRNG.nextGaussian(); if (value < variable.getLowerBound()) { value = variable.getLowerBound(); } else if (value > variable.getUpperBound()) { value = variable.getUpperBound(); } variable.setValue(value); } return new Solution[] { child }; } }