Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SegmentOptimization/SegmentOptimizationProblem.cs @ 18098

Last change on this file since 18098 was 18098, checked in by pfleck, 2 years ago

#3040 Added support for multi-row data for SOP instances where the segment aggregation results are averaged over multiple rows.

File size: 9.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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 HEAL.Attic;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.IntegerVectorEncoding;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Problems.Instances;
32using HeuristicLab.Problems.Instances.Types;
33
34using DoubleVector = MathNet.Numerics.LinearAlgebra.Vector<double>;
35
36namespace HeuristicLab.Problems.DataAnalysis.Symbolic.SegmentOptimization {
37  [Item("Segment Optimization Problem (SOP)", "")]
38  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 1200)]
39  [StorableType("64107939-34A7-4530-BFAB-8EA1C321BF6F")]
40  public class SegmentOptimizationProblem : SingleObjectiveBasicProblem<IntegerVectorEncoding>, IProblemInstanceConsumer<SOPData> {
41
42    [StorableType("63243591-5A56-41A6-B079-122B83583993")]
43    public enum Aggregation {
44      Sum,
45      Mean,
46      StandardDeviation
47    }
48
49    public override bool Maximization => false;
50
51    [Storable]
52    private IValueParameter<DoubleMatrix> dataParameter;
53    public IValueParameter<DoubleMatrix> DataParameter {
54      get { return dataParameter; }
55    }
56    [Storable]
57    private IValueParameter<IntRange> knownBoundsParameter;
58    public IValueParameter<IntRange> KnownBoundsParameter {
59      get { return knownBoundsParameter; }
60    }
61    [Storable]
62    private IValueParameter<EnumValue<Aggregation>> aggregationParameter;
63    public IValueParameter<EnumValue<Aggregation>> AggregationParameter {
64      get { return aggregationParameter; }
65    }
66   
67    public SegmentOptimizationProblem() {
68      Encoding = new IntegerVectorEncoding("bounds");
69
70      Parameters.Add(dataParameter = new ValueParameter<DoubleMatrix>("Data", ""));
71      Parameters.Add(knownBoundsParameter = new ValueParameter<IntRange>("Known Bounds", ""));
72      Parameters.Add(aggregationParameter = new ValueParameter<EnumValue<Aggregation>>("Aggregation Function", ""));
73
74      RegisterEventHandlers();
75
76      #region Default Instance
77      Load(new SOPData() {
78        Data = ToNdimArray(Enumerable.Range(1, 50).Select(x => (double)x * x).ToArray()),
79        Lower = 20, Upper = 30,
80        Aggregation = "mean"
81      });
82      #endregion
83    }
84    private SegmentOptimizationProblem(SegmentOptimizationProblem original, Cloner cloner)
85      : base(original, cloner) {
86      dataParameter = cloner.Clone(original.dataParameter);
87      knownBoundsParameter = cloner.Clone(original.knownBoundsParameter);
88      aggregationParameter = cloner.Clone(original.aggregationParameter);
89
90      RegisterEventHandlers();
91    }
92    public override IDeepCloneable Clone(Cloner cloner) {
93      return new SegmentOptimizationProblem(this, cloner);
94    }
95
96    [StorableConstructor]
97    private SegmentOptimizationProblem(StorableConstructorFlag _) : base(_) { }
98    [StorableHook(HookType.AfterDeserialization)]
99    private void AfterDeserialization() {
100      if (Parameters.ContainsKey("Data Vector") && Parameters["Data Vector"] is ValueParameter<DoubleArray> arrayParameter) {
101        Parameters.Remove(arrayParameter);
102        var array = arrayParameter.Value;
103        var matrix = new DoubleMatrix(1, array.Length);
104        for (int i = 0; i < array.Length; i++) matrix[0, i] = array[i];
105        Parameters.Add(dataParameter = new ValueParameter<DoubleMatrix>("Data", "", matrix));
106      }
107
108      RegisterEventHandlers();
109    }
110   
111    private void RegisterEventHandlers() {
112      dataParameter.ValueChanged += DataChanged;
113      knownBoundsParameter.ValueChanged += KnownBoundsChanged;
114      aggregationParameter.Value.ValueChanged += AggregationFunctionChanged;
115    }
116    private void DataChanged(object sender, EventArgs eventArgs) {
117      Encoding.Bounds = new IntMatrix(new[,] { { 0, DataParameter.Value.Columns } });
118    }
119    private void KnownBoundsChanged(object sender, EventArgs e) {
120    }
121    private void AggregationFunctionChanged(object sender, EventArgs eventArgs) {
122    }
123
124    public override double Evaluate(Individual individual, IRandom random) {
125      var data = DataParameter.Value;
126      var knownBounds = KnownBoundsParameter.Value;
127      var aggregation = aggregationParameter.Value.Value;
128
129      var solution = individual.IntegerVector(Encoding.Name);
130      var bounds = new IntRange(solution.Min(), solution.Max());
131
132      double target = BoundedAggregation(data, knownBounds, aggregation);
133      double prediction = BoundedAggregation(data, bounds, aggregation);
134
135      return Math.Pow(target - prediction, 2);
136    }
137
138    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
139      var orderedIndividuals = individuals.Zip(qualities, (i, q) => new { Individual = i, Quality = q }).OrderBy(z => z.Quality);
140      var best = Maximization ? orderedIndividuals.Last().Individual.IntegerVector(Encoding.Name) : orderedIndividuals.First().Individual.IntegerVector(Encoding.Name);
141
142      var bounds = new IntRange(best.Min(), best.Max());
143
144      var data = DataParameter.Value;
145      var knownBounds = KnownBoundsParameter.Value;
146      var aggregation = aggregationParameter.Value.Value;
147
148      double target = BoundedAggregation(data, knownBounds, aggregation);
149      double prediction = BoundedAggregation(data, bounds, aggregation);
150      double diff = target - prediction;
151
152      results.AddOrUpdateResult("Bounds", bounds);
153
154      results.AddOrUpdateResult("AggValue Diff", new DoubleValue(diff));
155      results.AddOrUpdateResult("AggValue Squared Diff", new DoubleValue(Math.Pow(diff, 2)));
156
157      results.AddOrUpdateResult("Lower Diff", new IntValue(knownBounds.Start - bounds.Start));
158      results.AddOrUpdateResult("Upper Diff", new IntValue(knownBounds.End - bounds.End));
159      results.AddOrUpdateResult("Length Diff", new IntValue(knownBounds.Size - bounds.Size));
160    }
161
162    private static double BoundedAggregation(DoubleArray data, IntRange bounds, Aggregation aggregation) {
163      var matrix = new DoubleMatrix(1, data.Length);
164      for (int i = 0; i < data.Length; i++) matrix[0, i] = data[i];
165      return BoundedAggregation(matrix, bounds, aggregation);
166    }
167
168    private static double BoundedAggregation(DoubleMatrix data, IntRange bounds, Aggregation aggregation) {
169      if (bounds.Size == 0) {
170        return 0;
171      }
172
173      var resultValues = new double[data.Rows];
174      var array = new double[data.Columns];
175      for (int row = 0; row < data.Rows; row++) {
176        for (int i = 0; i < array.Length; i++) array[i] = data[row, i];
177
178        var vector = DoubleVector.Build.DenseOfArray(array);
179        var segment = vector.SubVector(bounds.Start, bounds.Size);
180
181        switch (aggregation) {
182          case Aggregation.Sum:
183            resultValues[row] = segment.Sum();
184            break;
185          case Aggregation.Mean:
186            resultValues[row] = segment.Average();
187            break;
188          case Aggregation.StandardDeviation:
189            resultValues[row] = segment.StandardDeviationPop();
190            break;
191          default:
192            throw new NotImplementedException();
193        }
194      }
195
196      return resultValues.Average();
197    }
198
199    public void Load(SOPData data) {
200      DataParameter.Value = new DoubleMatrix(data.Data);
201      KnownBoundsParameter.Value = new IntRange(data.Lower, data.Upper);
202      switch (data.Aggregation.ToLower()) {
203        case "sum":
204          AggregationParameter.Value.Value = Aggregation.Sum;
205          break;
206        case "mean":
207        case "avg":
208          AggregationParameter.Value.Value = Aggregation.Mean;
209          break;
210        case "standarddeviation":
211        case "std":
212        case "sd":
213          AggregationParameter.Value.Value = Aggregation.StandardDeviation;
214          break;
215        default:
216          throw new NotSupportedException();
217      }
218                                           
219      Encoding.Length = 2;
220      Encoding.Bounds = new IntMatrix(new[,] { { 0, DataParameter.Value.Columns } });
221
222      BestKnownQuality = 0;
223
224      Name = data.Name;
225      Description = data.Description;
226    }
227
228    public static T[,] ToNdimArray<T>(T[] array) {
229      var matrix = new T[1, array.Length];
230      for (int i = 0; i < array.Length; i++)
231        matrix[0, i] = array[i];
232      return matrix;
233    }
234  }
235}
Note: See TracBrowser for help on using the repository browser.