Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingSolutionsView.cs @ 13750

Last change on this file since 13750 was 13750, checked in by abeham, 8 years ago

#2457: Added SOM projection for problem instances, fixed a bug (learningRadius was not used)

File size: 19.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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 HeuristicLab.Analysis;
23using HeuristicLab.Analysis.QualityAnalysis;
24using HeuristicLab.Analysis.SelfOrganizingMaps;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.MainForm;
29using HeuristicLab.Optimization;
30using HeuristicLab.OptimizationExpertSystem.Common;
31using HeuristicLab.Random;
32using System;
33using System.Collections.Generic;
34using System.Drawing;
35using System.Linq;
36using System.Windows.Forms;
37using System.Windows.Forms.DataVisualization.Charting;
38
39namespace HeuristicLab.OptimizationExpertSystem {
40  [View("Understanding Solutions")]
41  [Content(typeof(KnowledgeCenter), IsDefaultView = false)]
42  public partial class UnderstandingSolutionsView : KnowledgeCenterViewBase {
43    protected virtual bool SuppressEvents { get; set; }
44
45    public UnderstandingSolutionsView() {
46      InitializeComponent();
47      solutionNetworkProjectionComboBox.SelectedIndex = 0;
48    }
49
50    protected override void OnContentChanged() {
51      base.OnContentChanged();
52      UpdateSimilarityCalculators();
53      UpdateNamesComboboxes();
54      UpdateSolutionVisualization();
55    }
56
57    protected override void OnProblemChanged() {
58      base.OnProblemInstancesChanged();
59      UpdateSimilarityCalculators();
60      UpdateNamesComboboxes();
61      UpdateSolutionVisualization();
62    }
63
64    protected override void OnProblemSolutionsChanged() {
65      base.OnProblemSolutionsChanged();
66      UpdateNamesComboboxes();
67      UpdateSolutionVisualization();
68    }
69
70    protected override void OnSolutionSeedingPoolChanged() {
71      base.OnSolutionSeedingPoolChanged();
72      UpdateSolutionNetworkAnalysis(similarityComboBox.SelectedItem as ISolutionSimilarityCalculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
73    }
74
75    private void UpdateSimilarityCalculators() {
76      var selected = (ISolutionSimilarityCalculator)(similarityComboBox.SelectedIndex >= 0 ? similarityComboBox.SelectedItem : null);
77      similarityComboBox.Items.Clear();
78
79      if (Content == null || Content.Problem == null) return;
80
81      foreach (var calc in Content.Problem.Operators.OfType<ISolutionSimilarityCalculator>()) {
82        similarityComboBox.Items.Add(calc);
83        if (selected != null && calc.ItemName == selected.ItemName) similarityComboBox.SelectedItem = calc;
84      }
85      if (selected == null && similarityComboBox.Items.Count > 0)
86        similarityComboBox.SelectedIndex = 0;
87    }
88
89    private void UpdateNamesComboboxes() {
90      var selectedSolutionName = solutionNameComboBox.SelectedIndex >= 0 ? (string)solutionNameComboBox.SelectedItem : string.Empty;
91
92      solutionNameComboBox.Items.Clear();
93      if (Content == null) return;
94      var solutionNames = Content.Problem.Solutions.Select(x => x.Solution).OfType<IScope>().SelectMany(x => x.Variables);
95
96      foreach (var sn in solutionNames.GroupBy(x => x.Name).OrderBy(x => x.Key)) {
97        solutionNameComboBox.Items.Add(sn.Key);
98        // either it was previously selected, or the variable value is defined in the HeuristicLab.Encodings sub-namespace
99        if (sn.Key == selectedSolutionName || (string.IsNullOrEmpty(selectedSolutionName) && sn.All(x => x.Value != null && x.Value.GetType().FullName.StartsWith("HeuristicLab.Encodings."))))
100          solutionNameComboBox.SelectedItem = sn.Key;
101      }
102    }
103   
104    public void UpdateSolutionVisualization() {
105      if (InvokeRequired) { Invoke((Action)UpdateSolutionVisualization); return;  }
106      var qualityName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
107      UpdateSolutionQualityAnalysis(qualityName);
108      if (similarityComboBox.SelectedIndex >= 0) {
109        var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
110        UpdateSolutionDiversityAnalysis(calculator);
111        UpdateSolutionFdcAnalysis(calculator, fdcBetweenBestCheckBox.Checked);
112        UpdateSolutionLengthScaleAnalysis(calculator);
113        UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
114      } else {
115        solutionsDiversityViewHost.Content = null;
116        solutionsFdcViewHost.Content = null;
117        solutionsLengthScaleViewHost.Content = null;
118        solutionsNetworkChart.Series.First().Points.Clear();
119      }
120    }
121
122    private void UpdateSolutionQualityAnalysis(string qualityName) {
123      var dt = solutionsQualityViewHost.Content as DataTable;
124      if (dt == null) {
125        dt = QualityDistributionAnalyzer.PrepareTable(qualityName);
126        dt.VisualProperties.Title = "Quality Distribution";
127        solutionsQualityViewHost.Content = dt;
128      }
129      QualityDistributionAnalyzer.UpdateTable(dt, GetSolutionScopes().Select(x => GetQuality(x, qualityName) ?? double.NaN).Where(x => !double.IsNaN(x)));
130    }
131
132    private void UpdateSolutionDiversityAnalysis(ISolutionSimilarityCalculator calculator) {
133      try {
134        solutionsDiversityViewHost.Content = null;
135        var solutionScopes = GetSolutionScopes();
136        var similarities = new double[solutionScopes.Count, solutionScopes.Count];
137        for (var i = 0; i < solutionScopes.Count; i++) {
138          for (var j = 0; j < solutionScopes.Count; j++)
139            similarities[i, j] = calculator.CalculateSolutionSimilarity(solutionScopes[i], solutionScopes[j]);
140        }
141        var hm = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
142        solutionsDiversityViewHost.Content = hm;
143      } catch { }
144    }
145
146    private void UpdateSolutionFdcAnalysis(ISolutionSimilarityCalculator calculator, bool distanceToBest) {
147      try {
148        solutionsFdcViewHost.Content = null;
149        fdcSpearmanLabel.Text = "-";
150        fdcPearsonLabel.Text = "-";
151        var solutionScopes = GetSolutionScopes();
152        var points = new List<Point2D<double>>();
153        if (distanceToBest) {
154          var maximization = ((IValueParameter<BoolValue>)Content.Problem.MaximizationParameter).Value.Value;
155          var bestSolutions = (maximization ? solutionScopes.MaxItems(x => GetQuality(x, calculator.QualityVariableName) ?? double.NegativeInfinity)
156                                            : solutionScopes.MinItems(x => GetQuality(x, calculator.QualityVariableName) ?? double.PositiveInfinity)).ToList();
157          foreach (var solScope in solutionScopes.Except(bestSolutions)) {
158            var maxSimilarity = bestSolutions.Max(x => calculator.CalculateSolutionSimilarity(solScope, x));
159            var qDiff = (GetQuality(solScope, calculator.QualityVariableName) ?? double.NaN)
160                      - (GetQuality(bestSolutions[0], calculator.QualityVariableName) ?? double.NaN);
161            points.Add(new Point2D<double>(Math.Abs(qDiff), 1.0 - maxSimilarity));
162          }
163        } else {
164          for (int i = 0; i < solutionScopes.Count; i++) {
165            for (int j = 0; j < solutionScopes.Count; j++) {
166              if (i == j) continue;
167              var qDiff = (GetQuality(solutionScopes[i], calculator.QualityVariableName) ?? double.NaN)
168                          - (GetQuality(solutionScopes[j], calculator.QualityVariableName) ?? double.NaN);
169              if (double.IsNaN(qDiff)) continue;
170              points.Add(new Point2D<double>(Math.Abs(qDiff), 1.0 - calculator.CalculateSolutionSimilarity(solutionScopes[i], solutionScopes[j])));
171            }
172          }
173        }
174        var xs = points.Select(p => p.X).ToArray();
175        var ys = points.Select(p => p.Y).ToArray();
176        var scorr = alglib.spearmancorr2(xs, ys);
177        var pcorr = alglib.pearsoncorr2(xs, ys);
178        pcorr = pcorr * pcorr;
179        fdcSpearmanLabel.Text = scorr.ToString("F2");
180        fdcPearsonLabel.Text = pcorr.ToString("F2");
181
182        var splot = new ScatterPlot("Fitness-Distance", "");
183        splot.VisualProperties.XAxisTitle = "Absolute Fitness Difference";
184        splot.VisualProperties.XAxisMinimumAuto = false;
185        splot.VisualProperties.XAxisMinimumFixedValue = 0.0;
186        splot.VisualProperties.YAxisTitle = "Solution Distance";
187        splot.VisualProperties.YAxisMinimumAuto = false;
188        splot.VisualProperties.YAxisMinimumFixedValue = 0.0;
189        splot.VisualProperties.YAxisMaximumAuto = false;
190        splot.VisualProperties.YAxisMaximumFixedValue = 1.0;
191        var row = new ScatterPlotDataRow("Fdc", "", points);
192        row.VisualProperties.PointSize = 10;
193        row.VisualProperties.ShowRegressionLine = true;
194        splot.Rows.Add(row);
195        solutionsFdcViewHost.Content = splot;
196      } catch { }
197    }
198
199    private void UpdateSolutionLengthScaleAnalysis(ISolutionSimilarityCalculator calculator) {
200      try {
201        solutionsLengthScaleViewHost.Content = null;
202        var dt = solutionsLengthScaleViewHost.Content as DataTable;
203        if (dt == null) {
204          dt = QualityDistributionAnalyzer.PrepareTable("Length Scale");
205          solutionsLengthScaleViewHost.Content = dt;
206        }
207        QualityDistributionAnalyzer.UpdateTable(dt, CalculateLengthScale(calculator));
208      } catch {
209        solutionsLengthScaleViewHost.Content = null;
210      }
211    }
212
213    private IEnumerable<double> CalculateLengthScale(ISolutionSimilarityCalculator calculator) {
214      var solutionScopes = GetSolutionScopes();
215      for (var i = 0; i < solutionScopes.Count; i++) {
216        for (var j = 0; j < solutionScopes.Count; j++) {
217          if (i == j) continue;
218          var sim = calculator.CalculateSolutionSimilarity(solutionScopes[i], solutionScopes[j]);
219          if (sim.IsAlmost(0)) continue;
220          var qDiff = (GetQuality(solutionScopes[i], calculator.QualityVariableName) ?? double.NaN)
221                    - (GetQuality(solutionScopes[j], calculator.QualityVariableName) ?? double.NaN);
222          if (!double.IsNaN(qDiff)) yield return Math.Abs(qDiff) / sim;
223        }
224      }
225    }
226
227    private void UpdateSolutionNetworkAnalysis(ISolutionSimilarityCalculator calculator, string projection, bool lines, double contrast, double minimum) {
228      var series = solutionsNetworkChart.Series["SolutionSeries"];
229      var seedingSeries = solutionsNetworkChart.Series["SeedingSolutionSeries"];
230      try {
231        solutionsNetworkChart.Annotations.Clear();
232        series.Points.Clear();
233        seedingSeries.Points.Clear();
234        var solutionScopes = GetSolutionScopes();
235        var dissimilarities = new DoubleMatrix(solutionScopes.Count, solutionScopes.Count);
236        for (var i = 0; i < solutionScopes.Count; i++) {
237          for (var j = 0; j < solutionScopes.Count; j++) {
238            if (i == j) continue;
239            dissimilarities[i, j] = 1.0 - calculator.CalculateSolutionSimilarity(solutionScopes[i], solutionScopes[j]);
240          }
241        }
242        DoubleMatrix coords = null;
243        if (projection == "SOM")
244          coords = RelationalSOM.Map(dissimilarities, new MersenneTwister(42), jittering: true);
245        else coords = MultidimensionalScaling.KruskalShepard(dissimilarities);
246        var dataPoints = new List<DataPoint>();
247        for (var i = 0; i < coords.Rows; i++) {
248          var quality = GetQuality(solutionScopes[i], calculator.QualityVariableName) ?? double.NaN;
249          var dataPoint = new DataPoint() {
250            Name = (i + 1).ToString(),
251            XValue = coords[i, 0],
252            YValues = new[] {coords[i, 1], quality},
253            Label = (i + 1) + ": " + quality,
254            Tag = solutionScopes[i]
255          };
256          dataPoints.Add(dataPoint);
257          if (Content.SolutionSeedingPool.Contains(solutionScopes[i]) && Content.SolutionSeedingPool.ItemChecked(solutionScopes[i]))
258            seedingSeries.Points.Add(dataPoint);
259          else series.Points.Add(dataPoint);
260        }
261        if (lines) {
262          for (var i = 0; i < dataPoints.Count - 1; i++) {
263            for (var j = i + 1; j < dataPoints.Count; j++) {
264              if (dissimilarities[i, j].IsAlmost(1.0)) continue;
265              // s-shaped curve for mapping dissimilarities to alpha values
266              var alpha = (int)Math.Round(255.0 / (1.0 + Math.Exp(-contrast * ((1.0 - dissimilarities[i, j]) - (minimum / 100.0)))));
267              var lw = (int)Math.Round((1 - dissimilarities[i, j]) * 3.0 + 1.0); // linewidth of 1 to 4
268              var an = new LineAnnotation();
269              an.SetAnchor(dataPoints[i], dataPoints[j]);
270              an.LineColor = Color.FromArgb(alpha, Color.DarkGray);
271              an.LineWidth = lw;
272              solutionsNetworkChart.Annotations.Add(an);
273            }
274          }
275        }
276      } catch {
277        // problems in calculating the similarity
278        series.Points.Clear();
279        seedingSeries.Points.Clear();
280      }
281    }
282
283    private void SimilarityComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
284      if (InvokeRequired) { Invoke((Action<object, EventArgs>)SimilarityComboBoxOnSelectedIndexChanged, sender, e); return; }
285      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
286      if (calculator != null) {
287        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
288        calculator.QualityVariableName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
289      }
290      UpdateSolutionDiversityAnalysis(calculator);
291      UpdateSolutionFdcAnalysis(calculator, fdcBetweenBestCheckBox.Checked);
292      UpdateSolutionLengthScaleAnalysis(calculator);
293      UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
294    }
295
296    private void SolutionNameComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
297      if (InvokeRequired) { Invoke((Action<object, EventArgs>)SolutionNameComboBoxOnSelectedIndexChanged, sender, e); return; }
298      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
299      if (calculator != null) {
300        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
301        calculator.QualityVariableName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
302      }
303      UpdateSolutionDiversityAnalysis(calculator);
304      UpdateSolutionFdcAnalysis(calculator, fdcBetweenBestCheckBox.Checked);
305      UpdateSolutionLengthScaleAnalysis(calculator);
306      UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
307    }
308
309    private void FdcBetweenBestCheckBoxOnCheckedChanged(object sender, EventArgs e) {
310      if (InvokeRequired) { Invoke((Action<object, EventArgs>)FdcBetweenBestCheckBoxOnCheckedChanged, sender, e); return; }
311      UpdateSolutionFdcAnalysis((ISolutionSimilarityCalculator)similarityComboBox.SelectedItem, fdcBetweenBestCheckBox.Checked);
312    }
313
314    private void SolutionNetworkProjectionComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
315      if (InvokeRequired) { Invoke((Action<object, EventArgs>)SolutionNetworkProjectionComboBoxOnSelectedIndexChanged, sender, e); return; }
316      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
317      if (calculator != null) {
318        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
319        calculator.QualityVariableName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
320      }
321      UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
322    }
323
324    private void LinesCheckBoxOnCheckedChanged(object sender, EventArgs e) {
325      if (InvokeRequired) { Invoke((Action<object, EventArgs>)LinesCheckBoxOnCheckedChanged, sender, e); return; }
326      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
327      if (calculator != null) {
328        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
329        calculator.QualityVariableName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
330      }
331      UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
332    }
333
334    private void ContrastTrackBarOnScroll(object sender, EventArgs e) {
335      if (InvokeRequired) { Invoke((Action<object, EventArgs>)ContrastTrackBarOnScroll, sender, e); return; }
336      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
337      if (calculator != null) {
338        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
339        calculator.QualityVariableName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
340      }
341      UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
342    }
343
344    private void MinimumTrackBarOnScroll(object sender, EventArgs e) {
345      if (InvokeRequired) { Invoke((Action<object, EventArgs>)MinimumTrackBarOnScroll, sender, e); return; }
346      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
347      if (calculator != null) {
348        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
349        calculator.QualityVariableName = Content.Problem.Problem.Evaluator.QualityParameter.ActualName;
350      }
351      UpdateSolutionNetworkAnalysis(calculator, (string)solutionNetworkProjectionComboBox.SelectedItem, linesCheckBox.Checked, contrastTrackBar.Value, minimumTrackBar.Value);
352    }
353
354    private void SolutionsNetworkChartOnMouseClick(object sender, MouseEventArgs e) {
355      var result = solutionsNetworkChart.HitTest(e.X, e.Y);
356      if (result.ChartElementType == ChartElementType.DataPoint) {
357        var point = (DataPoint)result.Object;
358        var solutionScope = (IScope)point.Tag;
359        if (!Content.SolutionSeedingPool.Contains(solutionScope)) return;
360        Content.SolutionSeedingPool.SetItemCheckedState(solutionScope, !Content.SolutionSeedingPool.ItemChecked(solutionScope));
361      }
362    }
363
364    private void SolutionsNetworkChartOnMouseDoubleClick(object sender, MouseEventArgs e) {
365      var result = solutionsNetworkChart.HitTest(e.X, e.Y);
366      if (result.ChartElementType == ChartElementType.DataPoint) {
367        var point = (DataPoint)result.Object;
368        var solutionScope = (IScope)point.Tag;
369        MainForm.ShowContent(solutionScope, true);
370      }
371    }
372
373    #region Helpers
374    private List<IScope> GetSolutionScopes() {
375      return Content.Problem.Solutions.Select(x => x.Solution).OfType<IScope>().ToList();
376    }
377
378    private double? GetQuality(IScope scope, string qualityName) {
379      IVariable v;
380      if (!scope.Variables.TryGetValue(qualityName, out v)) return null;
381      var dval = v.Value as DoubleValue;
382      if (dval == null) return null;
383      return dval.Value;
384    }
385    #endregion
386  }
387}
Note: See TracBrowser for help on using the repository browser.