source: trunk/sources/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs @ 12076

Last change on this file since 12076 was 12076, checked in by bburlacu, 7 years ago

#2332: Changed the way the update counter is incremented in the PopulationSimilarityAnalyzer so that it's easier to use in the analyzers derived from this class.

File size: 14.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32
33namespace HeuristicLab.Analysis {
34  /// <summary>
35  /// An operator for analyzing the solution similarity in a population.
36  /// </summary>
37  [Item("PopulationSimilarityAnalyzer", "An operator for analyzing the solution similarity in a population.")]
38  [StorableClass]
39  public class PopulationSimilarityAnalyzer : SingleSuccessorOperator, IAnalyzer, ISimilarityBasedOperator {
40    private const string DiversityResultNameParameterName = "DiversityResultsName";
41
42    #region Backwards compatible code, remove with 3.4
43    private ISolutionSimilarityCalculator oldSimilarityCalculator;
44    [Storable(AllowOneWay = true, Name = "SimilarityCalculator")]
45    [Obsolete]
46    private ISolutionSimilarityCalculator SimilarityCalculator { set { oldSimilarityCalculator = value; } }
47    #endregion
48
49    public virtual bool EnabledByDefault {
50      get { return false; }
51    }
52    public ScopeParameter CurrentScopeParameter {
53      get { return (ScopeParameter)Parameters["CurrentScope"]; }
54    }
55    public IValueLookupParameter<ResultCollection> ResultsParameter {
56      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
57    }
58    public IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
59      get { return (IConstrainedValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
60    }
61    public IValueParameter<BoolValue> StoreHistoryParameter {
62      get { return (IValueParameter<BoolValue>)Parameters["StoreHistory"]; }
63    }
64    public IValueParameter<IntValue> UpdateIntervalParameter {
65      get { return (IValueParameter<IntValue>)Parameters["UpdateInterval"]; }
66    }
67    public ILookupParameter<IntValue> UpdateCounterParameter {
68      get { return (ILookupParameter<IntValue>)Parameters["UpdateCounter"]; }
69    }
70    public IFixedValueParameter<StringValue> DiversityResultNameParameter {
71      get { return (FixedValueParameter<StringValue>)Parameters[DiversityResultNameParameterName]; }
72    }
73
74    public string DiversityResultName {
75      get { return DiversityResultNameParameter.Value.Value; }
76      set { DiversityResultNameParameter.Value.Value = value; }
77    }
78
79    [StorableConstructor]
80    protected PopulationSimilarityAnalyzer(bool deserializing) : base(deserializing) { }
81    protected PopulationSimilarityAnalyzer(PopulationSimilarityAnalyzer original, Cloner cloner) : base(original, cloner) { }
82    public PopulationSimilarityAnalyzer(IEnumerable<ISolutionSimilarityCalculator> validSimilarityCalculators)
83      : base() {
84      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that contains the solutions which should be analyzed."));
85      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the population diversity analysis results should be stored."));
86      Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate population similarity."));
87      Parameters.Add(new ValueParameter<BoolValue>("StoreHistory", "True if the history of the population diversity analysis should be stored.", new BoolValue(false)));
88      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", "The interval in which the population diversity analysis should be applied.", new IntValue(1)));
89      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the operator was called since the last update.", "PopulationDiversityAnalyzerUpdateCounter"));
90      Parameters.Add(new FixedValueParameter<StringValue>(DiversityResultNameParameterName, "Specifies how the diversity results should be named.", new StringValue("PopulationDiversity")));
91
92      var similarityCalculators = SimilarityCalculatorParameter.ValidValues;
93      foreach (var sc in validSimilarityCalculators)
94        similarityCalculators.Add(sc);
95
96
97      ResultsParameter.Hidden = true;
98      UpdateCounterParameter.Hidden = true;
99    }
100
101    public override IDeepCloneable Clone(Cloner cloner) {
102      return new PopulationSimilarityAnalyzer(this, cloner);
103    }
104
105    [StorableHook(HookType.AfterDeserialization)]
106    private void AfterDeserialization() {
107      // BackwardsCompatibility3.3
108      #region Backwards compatible code, remove with 3.4
109      if (!Parameters.ContainsKey(DiversityResultNameParameterName))
110        Parameters.Add(new FixedValueParameter<StringValue>(DiversityResultNameParameterName, "Specifies how the diversity results should be named.", new StringValue("PopulationDiversity")));
111
112      if (!Parameters.ContainsKey("SimilarityCalculator"))
113        Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
114
115      SimilarityCalculatorParameter.ValidValues.Add(oldSimilarityCalculator);
116      #endregion
117    }
118
119    public override IOperation Apply() {
120      int updateInterval = UpdateIntervalParameter.Value.Value;
121      IntValue updateCounter = UpdateCounterParameter.ActualValue;
122      // if counter does not yet exist then initialize it with update interval
123      // to make sure the solutions are analyzed on the first application of this operator
124      if (updateCounter == null) {
125        updateCounter = new IntValue(updateInterval);
126        UpdateCounterParameter.ActualValue = updateCounter;
127      }
128      //analyze solutions only every 'updateInterval' times
129      if (updateCounter.Value != updateInterval) {
130        updateCounter.Value++;
131        return base.Apply();
132      }
133      updateCounter.Value = 1;
134
135      bool storeHistory = StoreHistoryParameter.Value.Value;
136      int count = CurrentScopeParameter.ActualValue.SubScopes.Count;
137
138      if (count > 1) {
139        var similarityCalculator = SimilarityCalculatorParameter.Value;
140        // calculate solution similarities
141        var similarityMatrix = similarityCalculator.CalculateSolutionCrowdSimilarity(CurrentScopeParameter.ActualValue);
142        double[,] similarities = new double[similarityMatrix.Length, similarityMatrix[0].Length];
143        for (int i = 0; i < similarityMatrix.Length; i++)
144          for (int j = 0; j < similarityMatrix[0].Length; j++)
145            similarities[i, j] = similarityMatrix[i][j];
146
147        // calculate minimum, average and maximum similarities
148        double similarity;
149        double[] minSimilarities = new double[count];
150        double[] avgSimilarities = new double[count];
151        double[] maxSimilarities = new double[count];
152        for (int i = 0; i < count; i++) {
153          minSimilarities[i] = 1;
154          avgSimilarities[i] = 0;
155          maxSimilarities[i] = 0;
156          for (int j = 0; j < count; j++) {
157            if (i != j) {
158              similarity = similarities[i, j];
159
160              if ((similarity < 0) || (similarity > 1))
161                throw new InvalidOperationException("Solution similarities have to be in the interval [0;1].");
162
163              if (minSimilarities[i] > similarity) minSimilarities[i] = similarity;
164              avgSimilarities[i] += similarity;
165              if (maxSimilarities[i] < similarity) maxSimilarities[i] = similarity;
166            }
167          }
168          avgSimilarities[i] = avgSimilarities[i] / (count - 1);
169        }
170        double avgMinSimilarity = minSimilarities.Average();
171        double avgAvgSimilarity = avgSimilarities.Average();
172        double avgMaxSimilarity = maxSimilarities.Average();
173
174        // fetch results collection
175        ResultCollection results;
176        if (!ResultsParameter.ActualValue.ContainsKey(DiversityResultName)) {
177          results = new ResultCollection();
178          ResultsParameter.ActualValue.Add(new Result(DiversityResultName, results));
179        } else {
180          results = (ResultCollection)ResultsParameter.ActualValue[DiversityResultName].Value;
181        }
182
183        // store similarities
184        HeatMap similaritiesHeatMap = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
185        if (!results.ContainsKey("Solution Similarities"))
186          results.Add(new Result("Solution Similarities", similaritiesHeatMap));
187        else
188          results["Solution Similarities"].Value = similaritiesHeatMap;
189
190        // store similarities history
191        if (storeHistory) {
192          if (!results.ContainsKey("Solution Similarities History")) {
193            HeatMapHistory history = new HeatMapHistory();
194            history.Add(similaritiesHeatMap);
195            results.Add(new Result("Solution Similarities History", history));
196          } else {
197            ((HeatMapHistory)results["Solution Similarities History"].Value).Add(similaritiesHeatMap);
198          }
199        }
200
201        // store average minimum, average and maximum similarity
202        if (!results.ContainsKey("Average Minimum Solution Similarity"))
203          results.Add(new Result("Average Minimum Solution Similarity", new DoubleValue(avgMinSimilarity)));
204        else
205          ((DoubleValue)results["Average Minimum Solution Similarity"].Value).Value = avgMinSimilarity;
206
207        if (!results.ContainsKey("Average Average Solution Similarity"))
208          results.Add(new Result("Average Average Solution Similarity", new DoubleValue(avgAvgSimilarity)));
209        else
210          ((DoubleValue)results["Average Average Solution Similarity"].Value).Value = avgAvgSimilarity;
211
212        if (!results.ContainsKey("Average Maximum Solution Similarity"))
213          results.Add(new Result("Average Maximum Solution Similarity", new DoubleValue(avgMaxSimilarity)));
214        else
215          ((DoubleValue)results["Average Maximum Solution Similarity"].Value).Value = avgMaxSimilarity;
216
217        // store average minimum, average and maximum solution similarity data table
218        DataTable minAvgMaxSimilarityDataTable;
219        if (!results.ContainsKey("Average Minimum/Average/Maximum Solution Similarity")) {
220          minAvgMaxSimilarityDataTable = new DataTable("Average Minimum/Average/Maximum Solution Similarity");
221          minAvgMaxSimilarityDataTable.VisualProperties.XAxisTitle = "Iteration";
222          minAvgMaxSimilarityDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
223          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Minimum Solution Similarity", null));
224          minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].VisualProperties.StartIndexZero = true;
225          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Average Solution Similarity", null));
226          minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].VisualProperties.StartIndexZero = true;
227          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Maximum Solution Similarity", null));
228          minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].VisualProperties.StartIndexZero = true;
229          results.Add(new Result("Average Minimum/Average/Maximum Solution Similarity", minAvgMaxSimilarityDataTable));
230        } else {
231          minAvgMaxSimilarityDataTable = (DataTable)results["Average Minimum/Average/Maximum Solution Similarity"].Value;
232        }
233        minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].Values.Add(avgMinSimilarity);
234        minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].Values.Add(avgAvgSimilarity);
235        minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].Values.Add(avgMaxSimilarity);
236
237        // store minimum, average, maximum similarities data table
238        DataTable minAvgMaxSimilaritiesDataTable = new DataTable("Minimum/Average/Maximum Solution Similarities");
239        minAvgMaxSimilaritiesDataTable.VisualProperties.XAxisTitle = "Solution Index";
240        minAvgMaxSimilaritiesDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
241        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Minimum Solution Similarity", null, minSimilarities));
242        minAvgMaxSimilaritiesDataTable.Rows["Minimum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
243        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Average Solution Similarity", null, avgSimilarities));
244        minAvgMaxSimilaritiesDataTable.Rows["Average Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
245        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Maximum Solution Similarity", null, maxSimilarities));
246        minAvgMaxSimilaritiesDataTable.Rows["Maximum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
247        if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities")) {
248          results.Add(new Result("Minimum/Average/Maximum Solution Similarities", minAvgMaxSimilaritiesDataTable));
249        } else {
250          results["Minimum/Average/Maximum Solution Similarities"].Value = minAvgMaxSimilaritiesDataTable;
251        }
252
253        // store minimum, average, maximum similarities history
254        if (storeHistory) {
255          if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities History")) {
256            DataTableHistory history = new DataTableHistory();
257            history.Add(minAvgMaxSimilaritiesDataTable);
258            results.Add(new Result("Minimum/Average/Maximum Solution Similarities History", history));
259          } else {
260            ((DataTableHistory)results["Minimum/Average/Maximum Solution Similarities History"].Value).Add(minAvgMaxSimilaritiesDataTable);
261          }
262        }
263      }
264      return base.Apply();
265    }
266  }
267}
Note: See TracBrowser for help on using the repository browser.