source: branches/2989_MovingPeaksBenchmark/HeuristicLab.Problems.MovingPeaksBenchmark/3.3/MovingPeaksBenchmarkProblemEvaluator.cs @ 16613

Last change on this file since 16613 was 16613, checked in by swagner, 3 years ago

#2989: Moving Peaks Benchmark

  • fixed updates of best known quality
  • added bounds for peak movement
File size: 13.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Linq;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.Encodings.RealVectorEncoding;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32using HeuristicLab.Random;
33
34namespace HeuristicLab.Problems.MovingPeaksBenchmark {
35  [Item("MovingPeaksBenchmarkProblemEvaluator", "Evaluation operator for the Moving Peaks Benchmark.")]
36  [StorableClass]
37  public class MovingPeaksBenchmarkProblemEvaluator : InstrumentedOperator, IMovingPeaksBenchmarkProblemEvaluator {
38    [Storable]
39    IRandom uniformRandom;
40    [Storable]
41    long executions;
42    [Storable]
43    double currentBest;
44    [Storable]
45    double offlineErrorSum;
46
47    #region Parameters
48    public ILookupParameter<DoubleMatrix> BoundsParameter {
49      get { return (ILookupParameter<DoubleMatrix>)Parameters["Bounds"]; }
50    }
51    public IValueLookupParameter<DoubleMatrix> PeakLocationsParameter {
52      get { return (IValueLookupParameter<DoubleMatrix>)Parameters["PeakLocations"]; }
53    }
54    public IValueLookupParameter<DoubleArray> PeakWidthsParameter {
55      get { return (IValueLookupParameter<DoubleArray>)Parameters["PeakWidths"]; }
56    }
57    public IValueLookupParameter<DoubleArray> PeakHeightsParameter {
58      get { return (IValueLookupParameter<DoubleArray>)Parameters["PeakHeights"]; }
59    }
60    public ILookupParameter<IntValue> MovingPeaksRandomSeedParameter {
61      get { return (ILookupParameter<IntValue>)Parameters["MovingPeaksRandomSeed"]; }
62    }
63    public ILookupParameter<DoubleValue> MinPeakWidthParameter {
64      get { return (ILookupParameter<DoubleValue>)Parameters["MinPeakWidth"]; }
65    }
66    public ILookupParameter<DoubleValue> MaxPeakWidthParameter {
67      get { return (ILookupParameter<DoubleValue>)Parameters["MaxPeakWidth"]; }
68    }
69    public ILookupParameter<DoubleValue> MinPeakHeightParameter {
70      get { return (ILookupParameter<DoubleValue>)Parameters["MinPeakHeight"]; }
71    }
72    public ILookupParameter<DoubleValue> MaxPeakHeightParameter {
73      get { return (ILookupParameter<DoubleValue>)Parameters["MaxPeakHeight"]; }
74    }
75    public ILookupParameter<IntValue> PeakMovementIntervalParameter {
76      get { return (ILookupParameter<IntValue>)Parameters["PeakMovementInterval"]; }
77    }
78    public ILookupParameter<DoubleValue> PeakMovementStrengthParameter {
79      get { return (ILookupParameter<DoubleValue>)Parameters["PeakMovementStrength"]; }
80    }
81    public ILookupParameter<RealVector> PointParameter {
82      get { return (ILookupParameter<RealVector>)Parameters["Point"]; }
83    }
84    public ILookupParameter<DoubleValue> QualityParameter {
85      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
86    }
87    public ILookupParameter<DoubleValue> BestKnownQualityParameter {
88      get { return (ILookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
89    }
90    public ILookupParameter<RealVector> BestKnownSolutionParameter {
91      get { return (ILookupParameter<RealVector>)Parameters["BestKnownSolution"]; }
92    }
93    public IValueLookupParameter<ResultCollection> ResultsParameter {
94      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
95    }
96    #endregion
97
98    [StorableConstructor]
99    protected MovingPeaksBenchmarkProblemEvaluator(bool deserializing) : base(deserializing) { }
100    protected MovingPeaksBenchmarkProblemEvaluator(MovingPeaksBenchmarkProblemEvaluator original, Cloner cloner) : base(original, cloner) { }
101    public MovingPeaksBenchmarkProblemEvaluator() : base() {
102      Parameters.Add(new LookupParameter<DoubleMatrix>("Bounds", "The lower and upper bounds in each dimension."));
103      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("PeakLocations", "Current position of the peaks."));
104      PeakLocationsParameter.ActualName = "InitialPeakLocations";
105      Parameters.Add(new ValueLookupParameter<DoubleArray>("PeakWidths", "Current width of the peaks."));
106      PeakWidthsParameter.ActualName = "InitialPeakWidths";
107      Parameters.Add(new ValueLookupParameter<DoubleArray>("PeakHeights", "Current height of the peaks."));
108      PeakHeightsParameter.ActualName = "InitialPeakHeights";
109      Parameters.Add(new LookupParameter<IntValue>("MovingPeaksRandomSeed", "The random seed for initializing the PRNG for changing the peaks."));
110      Parameters.Add(new LookupParameter<DoubleValue>("MinPeakWidth", "The minimum width of each peak."));
111      Parameters.Add(new LookupParameter<DoubleValue>("MaxPeakWidth", "The maximum width of each peak."));
112      Parameters.Add(new LookupParameter<DoubleValue>("MinPeakHeight", "The minimum height of each peak."));
113      Parameters.Add(new LookupParameter<DoubleValue>("MaxPeakHeight", "The maximum height of each peak."));
114      Parameters.Add(new LookupParameter<IntValue>("PeakMovementInterval", "The interval in evaluated solutions in which peaks are moved."));
115      Parameters.Add(new LookupParameter<DoubleValue>("PeakMovementStrength", "The length of the random vector used for changing peak locations."));
116      Parameters.Add(new LookupParameter<RealVector>("Point", "The point which should be evaluated."));
117      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "Quality value of the evaluated point."));
118      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "Quality value of the highest peak."));
119      Parameters.Add(new LookupParameter<RealVector>("BestKnownSolution", "The location of the highest peak."));
120      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection for storing result values."));
121
122      PeakLocationsParameter.Hidden = true;
123      PeakWidthsParameter.Hidden = true;
124      PeakHeightsParameter.Hidden = true;
125      MovingPeaksRandomSeedParameter.Hidden = true;
126      MinPeakWidthParameter.Hidden = true;
127      MaxPeakWidthParameter.Hidden = true;
128      MinPeakHeightParameter.Hidden = true;
129      MaxPeakHeightParameter.Hidden = true;
130      PeakMovementIntervalParameter.Hidden = true;
131      PeakMovementStrengthParameter.Hidden = true;
132      BestKnownQualityParameter.Hidden = true;
133      BestKnownSolutionParameter.Hidden = true;
134      ResultsParameter.Hidden = true;
135    }
136
137    public override IDeepCloneable Clone(Cloner cloner) {
138      return new MovingPeaksBenchmarkProblemEvaluator(this, cloner);
139    }
140
141    public override IOperation InstrumentedApply() {
142      lock (this) {
143        if (uniformRandom == null) {
144          uniformRandom = new MersenneTwister();
145          uniformRandom.Reset(MovingPeaksRandomSeedParameter.ActualValue.Value);
146        }
147      }
148
149      DoubleMatrix peaks = PeakLocationsParameter.ActualValue;
150      DoubleArray widths = PeakWidthsParameter.ActualValue;
151      DoubleArray heights = PeakHeightsParameter.ActualValue;
152
153      if (PeakLocationsParameter.Value == null) {
154        peaks = peaks.Clone() as DoubleMatrix;
155        widths = widths.Clone() as DoubleArray;
156        heights = heights.Clone() as DoubleArray;
157        PeakLocationsParameter.Value = peaks;
158        PeakWidthsParameter.Value = widths;
159        PeakHeightsParameter.Value = heights;
160
161        ResultCollection results = ResultsParameter.ActualValue;
162        results.Add(new Result("Current Peak Locations", peaks));
163        results.Add(new Result("Current Peak Widths", widths));
164        results.Add(new Result("Current Peak Heights", heights));
165
166        for (int i = 0; i < widths.Length; i++) {
167          if (widths[i] < 0) {
168            widths[i] = MinPeakWidthParameter.ActualValue.Value + uniformRandom.NextDouble() * (MaxPeakWidthParameter.ActualValue.Value - MinPeakWidthParameter.ActualValue.Value);
169          }
170          if (heights[i] < 0) {
171            heights[i] = MinPeakHeightParameter.ActualValue.Value + uniformRandom.NextDouble() * (MaxPeakHeightParameter.ActualValue.Value - MinPeakHeightParameter.ActualValue.Value);
172          }
173        }
174      }
175
176      lock (this) {
177        // move peaks if peaks movement interval is reached
178        if ((executions % PeakMovementIntervalParameter.ActualValue.Value) == 0) {
179          MovePeaks(uniformRandom, peaks, widths, heights,
180                    PeakMovementStrengthParameter.ActualValue.Value,
181                    MinPeakWidthParameter.ActualValue.Value, MaxPeakWidthParameter.ActualValue.Value,
182                    MinPeakHeightParameter.ActualValue.Value, MaxPeakHeightParameter.ActualValue.Value,
183                    BoundsParameter.ActualValue[0, 0], BoundsParameter.ActualValue[0, 1]);
184
185          // update best known solution & quality according to highest peak
186          double maxHeight = heights.Max();
187          int peakIndex = Array.IndexOf(heights.CloneAsArray(), maxHeight);
188          double[] peak = new double[peaks.Columns];
189          for (int i = 0; i < peak.Length; i++) {
190            peak[i] = peaks[peakIndex, i];
191          }
192          BestKnownSolutionParameter.ActualValue = new RealVector(peak);
193          BestKnownQualityParameter.ActualValue.Value = heights.Max();
194          currentBest = -1;
195        }
196        executions++;
197      }
198
199      RealVector point = PointParameter.ActualValue;
200      double quality = Apply(peaks, widths, heights, point);
201      QualityParameter.ActualValue = new DoubleValue(quality);
202
203      lock (this) {
204        if (quality > currentBest) {
205          currentBest = quality;
206        }
207        offlineErrorSum += heights.Max() - currentBest;
208        ResultCollection results = ResultsParameter.ActualValue;
209        IResult offlineError;
210        if (results.TryGetValue("Offline Error", out offlineError)) {
211          (offlineError.Value as DoubleValue).Value = offlineErrorSum / executions;
212        } else {
213          results.Add(new Result("Offline Error", new DoubleValue(offlineErrorSum / executions)));
214        }
215      }
216      return base.InstrumentedApply();
217    }
218
219    public override void InitializeState() {
220      base.InitializeState();
221      executions = 0;
222      currentBest = -1;
223      offlineErrorSum = 0;
224    }
225
226    public override void ClearState() {
227      base.ClearState();
228      uniformRandom = null;
229      PeakLocationsParameter.Value = null;
230      PeakWidthsParameter.Value = null;
231      PeakHeightsParameter.Value = null;
232    }
233
234    public double Apply(DoubleMatrix peaks, DoubleArray widths, DoubleArray heights, RealVector point) {
235      double max = 0;
236      double val = 0;
237
238      for (int i = 0; i < widths.Length; i++) {
239        val = 0;
240        for (int j = 0; j < point.Length; j++) {
241          val += (point[j] - peaks[i, j]) * (point[j] - peaks[i, j]);
242        }
243        val = heights[i] / (1 + widths[i] * val);
244        if (val > max) max = val;
245      }
246      return max;
247    }
248
249    private void MovePeaks(IRandom uniformRandom, DoubleMatrix peaks, DoubleArray widths, DoubleArray heights, double strength,
250                           double minWidth, double maxWidth, double minHeight, double maxHeight, double minLocation, double maxLocation) {
251      IRandom normalRandom = new NormalDistributedRandom(uniformRandom, 0, 1);
252      for (int i = 0; i < peaks.Rows; i++) {
253        double[] v = RandomVector(uniformRandom, peaks.Columns, strength);
254        for (int j = 0; j < v.Length; j++) {
255          peaks[i, j] += v[j];
256          if (peaks[i, j] < minLocation) peaks[i, j] = minLocation;
257          if (peaks[i, j] > maxLocation) peaks[i, j] = maxLocation;
258        }
259
260        widths[i] = NewRandomValue(normalRandom, widths[i], 1.0, minWidth, maxWidth);
261        heights[i] = NewRandomValue(normalRandom, heights[i], 7, minHeight, maxHeight);
262      }
263    }
264
265    private double[] RandomVector(IRandom uniformRandom, int dimensions, double length) {
266      double[] vector = new double[dimensions];
267
268      for (int i = 0; i < vector.Length; i++) {
269        vector[i] = uniformRandom.NextDouble() - 0.5;
270      }
271      double factor = length / Math.Sqrt(vector.Select(x => x * x).Sum());
272      for (int i = 0; i < vector.Length; i++) {
273        vector[i] *= factor;
274      }
275      return vector;
276    }
277
278    private double NewRandomValue(IRandom normalRandom, double value, double factor, double min, double max) {
279      double r, newValue;
280      do {
281        r = normalRandom.NextDouble();
282        newValue = value + factor * r;
283      } while ((newValue < min) || (newValue > max));
284      return newValue;
285    }
286  }
287}
Note: See TracBrowser for help on using the repository browser.