#region License Information /* HeuristicLab * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Encodings.RealVectorEncoding { /// /// Changes one position of a real vector by adding/substracting a value of the interval [(2^-15)*range;~2*range], where range is SearchIntervalFactor * (max - min). /// Note that the interval is not uniformly sampled, but smaller values are sampled more often. /// /// /// It is implemented as described by Mühlenbein, H. and Schlierkamp-Voosen, D. 1993. Predictive Models for the Breeder Genetic Algorithm - I. Continuous Parameter Optimization. Evolutionary Computation, 1(1), pp. 25-49.
///
[Item("BreederGeneticAlgorithmManipulator", "It is implemented as described by Mühlenbein, H. and Schlierkamp-Voosen, D. 1993. Predictive Models for the Breeder Genetic Algorithm - I. Continuous Parameter Optimization. Evolutionary Computation, 1(1), pp. 25-49.")] [StorableClass] public class BreederGeneticAlgorithmManipulator : RealVectorManipulator { private static readonly double[] powerOfTwo = new double[] { 1, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625, 0.001953125, 0.0009765625, 0.00048828125, 0.000244140625, 0.0001220703125, 0.00006103515625, 0.000030517578125 }; public ValueLookupParameter SearchIntervalFactorParameter { get { return (ValueLookupParameter)Parameters["SearchIntervalFactor"]; } } [StorableConstructor] protected BreederGeneticAlgorithmManipulator(bool deserializing) : base(deserializing) { } protected BreederGeneticAlgorithmManipulator(BreederGeneticAlgorithmManipulator original, Cloner cloner) : base(original, cloner) { } /// /// Initializes a new instance of with two /// parameters (Bounds and SearchIntervalFactor). /// public BreederGeneticAlgorithmManipulator() : base() { Parameters.Add(new ValueLookupParameter("SearchIntervalFactor", @"Scales the manipulation strength as a factor of the range. The range is determined by the bounds interval. A value of 0.1 means that certain components of the vector are moved by values in the non-uniform interval [0;0.1*range].", new DoubleValue(0.1))); } public override IDeepCloneable Clone(Cloner cloner) { return new BreederGeneticAlgorithmManipulator(this, cloner); } /// /// Performs a breeder genetic algorithm manipulation on the given . /// /// A random number generator. /// The real vector to manipulate. /// The lower and upper bound (1st and 2nd column) of the positions in the vector. If there are less rows than dimensions, the rows are cycled. /// The factor determining the size of the search interval. public static void Apply(IRandom random, RealVector vector, DoubleMatrix bounds, DoubleValue searchIntervalFactor) { int length = vector.Length; double prob, value; do { value = Sigma(random); } while (value == 0); prob = 1.0 / (double)length; bool wasMutated = false; for (int i = 0; i < length; i++) { if (random.NextDouble() < prob) { double range = bounds[i % bounds.Rows, 1] - bounds[i % bounds.Rows, 0]; if (random.NextDouble() < 0.5) { vector[i] = vector[i] + value * searchIntervalFactor.Value * range; } else { vector[i] = vector[i] - value * searchIntervalFactor.Value * range; } wasMutated = true; } } // make sure at least one gene was mutated if (!wasMutated) { int pos = random.Next(length); double range = bounds[pos % bounds.Rows, 1] - bounds[pos % bounds.Rows, 0]; if (random.NextDouble() < 0.5) { vector[pos] = vector[pos] + value * searchIntervalFactor.Value * range; } else { vector[pos] = vector[pos] - value * searchIntervalFactor.Value * range; } } } private static double Sigma(IRandom random) { double sigma = 0; int limit = 16; for (int i = 0; i < limit; i++) { if (random.Next(limit) == 15) { // execute this statement with a probability of 1/16 sigma += powerOfTwo[i]; } } return sigma; } /// /// Checks the parameters Bounds, and SearchIntervalFactor and forwards the call to . /// /// A random number generator. /// The real vector to manipulate. protected override void Manipulate(IRandom random, RealVector realVector) { if (BoundsParameter.ActualValue == null) throw new InvalidOperationException("BreederGeneticAlgorithmManipulator: Parameter " + BoundsParameter.ActualName + " could not be found."); if (SearchIntervalFactorParameter.ActualValue == null) throw new InvalidOperationException("BreederGeneticAlgorithmManipulator: Paraemter " + SearchIntervalFactorParameter.ActualName + " could not be found."); Apply(random, realVector, BoundsParameter.ActualValue, SearchIntervalFactorParameter.ActualValue); } } }