#region License Information /* HeuristicLab * Copyright (C) 2002-2019 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 System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Random; namespace HeuristicLab.Problems.MovingPeaksBenchmark { [Item("MovingPeaksBenchmarkProblemEvaluator", "Evaluation operator for the Moving Peaks Benchmark.")] [StorableClass] public class MovingPeaksBenchmarkProblemEvaluator : InstrumentedOperator, IMovingPeaksBenchmarkProblemEvaluator { [Storable] IRandom uniformRandom; [Storable] long executions; public IValueLookupParameter PeakLocationsParameter { get { return (IValueLookupParameter)Parameters["PeakLocations"]; } } public IValueLookupParameter PeakWidthsParameter { get { return (IValueLookupParameter)Parameters["PeakWidths"]; } } public IValueLookupParameter PeakHeightsParameter { get { return (IValueLookupParameter)Parameters["PeakHeights"]; } } public ILookupParameter MovingPeaksRandomSeedParameter { get { return (ILookupParameter)Parameters["MovingPeaksRandomSeed"]; } } public ILookupParameter PeakMovementIntervalParameter { get { return (ILookupParameter)Parameters["PeakMovementInterval"]; } } public ILookupParameter PeakMovementStrengthParameter { get { return (ILookupParameter)Parameters["PeakMovementStrength"]; } } public ILookupParameter PointParameter { get { return (ILookupParameter)Parameters["Point"]; } } public ILookupParameter QualityParameter { get { return (ILookupParameter)Parameters["Quality"]; } } public ILookupParameter BestKnownQualityParameter { get { return (ILookupParameter)Parameters["BestKnownQuality"]; } } public ILookupParameter BestKnownSolutionParameter { get { return (ILookupParameter)Parameters["BestKnownSolution"]; } } public IValueLookupParameter ResultsParameter { get { return (IValueLookupParameter)Parameters["Results"]; } } [StorableConstructor] protected MovingPeaksBenchmarkProblemEvaluator(bool deserializing) : base(deserializing) { } protected MovingPeaksBenchmarkProblemEvaluator(MovingPeaksBenchmarkProblemEvaluator original, Cloner cloner) : base(original, cloner) { } public MovingPeaksBenchmarkProblemEvaluator() : base() { Parameters.Add(new ValueLookupParameter("PeakLocations", "Current position of the peaks.")); PeakLocationsParameter.ActualName = "InitialPeakLocations"; Parameters.Add(new ValueLookupParameter("PeakWidths", "Current width of the peaks.")); PeakWidthsParameter.ActualName = "InitialPeakWidths"; Parameters.Add(new ValueLookupParameter("PeakHeights", "Current height of the peaks.")); PeakHeightsParameter.ActualName = "InitialPeakHeights"; Parameters.Add(new LookupParameter("MovingPeaksRandomSeed", "The random seed for initializing the PRNG for changing the peaks.")); Parameters.Add(new LookupParameter("PeakMovementInterval", "The interval in evaluated solutions in which peaks are moved.")); Parameters.Add(new LookupParameter("PeakMovementStrength", "The length of the random vector used for changing peak locations.")); Parameters.Add(new LookupParameter("Point", "The point which should be evaluated.")); Parameters.Add(new LookupParameter("Quality", "Quality value of the evaluated point.")); Parameters.Add(new LookupParameter("BestKnownQuality", "Quality value of the highest peak.")); Parameters.Add(new LookupParameter("BestKnownSolution", "The location of the highest peak.")); Parameters.Add(new ValueLookupParameter("Results", "The result collection for storing result values.")); PeakLocationsParameter.Hidden = true; PeakWidthsParameter.Hidden = true; PeakHeightsParameter.Hidden = true; BestKnownQualityParameter.Hidden = true; BestKnownSolutionParameter.Hidden = true; ResultsParameter.Hidden = true; } public override IDeepCloneable Clone(Cloner cloner) { return new MovingPeaksBenchmarkProblemEvaluator(this, cloner); } public override IOperation InstrumentedApply() { DoubleMatrix peaks = PeakLocationsParameter.ActualValue; DoubleArray widths = PeakWidthsParameter.ActualValue; DoubleArray heights = PeakHeightsParameter.ActualValue; if (PeakLocationsParameter.Value == null) { peaks = peaks.Clone() as DoubleMatrix; widths = widths.Clone() as DoubleArray; heights = heights.Clone() as DoubleArray; PeakLocationsParameter.Value = peaks; PeakWidthsParameter.Value = widths; PeakHeightsParameter.Value = heights; ResultCollection results = ResultsParameter.ActualValue; results.Add(new Result("Current Peak Locations", peaks)); results.Add(new Result("Current Peak Widths", widths)); results.Add(new Result("Current Peak Heights", heights)); } if (uniformRandom == null) { uniformRandom = new MersenneTwister(); uniformRandom.Reset(MovingPeaksRandomSeedParameter.ActualValue.Value); } // move peaks if peaks movement interval is reached lock (this) { if ((executions % PeakMovementIntervalParameter.ActualValue.Value) == 0) { MovePeaks(uniformRandom, peaks, widths, heights, PeakMovementStrengthParameter.ActualValue.Value); // update best known solution & quality according to highest peak double maxHeight = heights.Max(); int peakIndex = Array.IndexOf(heights.CloneAsArray(), maxHeight); double[] peak = new double[peaks.Columns]; for (int i = 0; i < peak.Length; i++) { peak[i] = peaks[peakIndex, i]; } BestKnownSolutionParameter.ActualValue = new RealVector(peak); BestKnownQualityParameter.ActualValue.Value = heights.Max(); } executions++; } RealVector point = PointParameter.ActualValue; double quality = Apply(peaks, widths, heights, point); QualityParameter.ActualValue = new DoubleValue(quality); return base.InstrumentedApply(); } public override void InitializeState() { base.InitializeState(); executions = 0; } public override void ClearState() { base.ClearState(); uniformRandom = null; PeakLocationsParameter.Value = null; PeakWidthsParameter.Value = null; PeakHeightsParameter.Value = null; } public double Apply(DoubleMatrix peaks, DoubleArray widths, DoubleArray heights, RealVector point) { double max = 0; double val = 0; for (int i = 0; i < widths.Length; i++) { val = 0; for (int j = 0; j < point.Length; j++) { val += (point[j] - peaks[i, j]) * (point[j] - peaks[i, j]); } val = heights[i] / (1 + widths[i] * val); if (val > max) max = val; } return max; } private void MovePeaks(IRandom uniformRandom, DoubleMatrix peaks, DoubleArray widths, DoubleArray heights, double strength) { IRandom normalRandom = new NormalDistributedRandom(uniformRandom, 0, 1); for (int i = 0; i < peaks.Rows; i++) { double[] v = RandomVector(uniformRandom, peaks.Columns, strength); for (int j = 0; j < v.Length; j++) { peaks[i, j] += v[j]; } widths[i] = widths[i] + 0.01 * normalRandom.NextDouble(); heights[i] = heights[i] + 7 * normalRandom.NextDouble(); } } private double[] RandomVector(IRandom uniformRandom, int dimensions, double length) { double[] vector = new double[dimensions]; for (int i = 0; i < vector.Length; i++) { vector[i] = uniformRandom.NextDouble() - 0.5; } double factor = length / Math.Sqrt(vector.Select(x => x * x).Sum()); for (int i = 0; i < vector.Length; i++) { vector[i] *= factor; } return vector; } } }