Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingSolutionsView.cs @ 16300

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

#2457: updated branch to trunk

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