source: branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/ExpertSystemView.cs @ 13667

Last change on this file since 13667 was 13667, checked in by abeham, 5 years ago

#2457: worked on expert system, created new application, merged trunk change of r13666

File size: 20.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Common;
25using HeuristicLab.Common.Resources;
26using HeuristicLab.Core.Views;
27using HeuristicLab.Data;
28using HeuristicLab.MainForm;
29using HeuristicLab.Optimization;
30using HeuristicLab.Optimization.Views;
31using HeuristicLab.OptimizationExpertSystem.Common;
32using System;
33using System.Collections.Generic;
34using System.ComponentModel;
35using System.Linq;
36using System.Text.RegularExpressions;
37using System.Windows.Forms;
38using System.Windows.Forms.DataVisualization.Charting;
39
40namespace HeuristicLab.OptimizationExpertSystem {
41  [View("Expert-system Optimizer View")]
42  [Content(typeof(ExpertSystem), IsDefaultView = true)]
43  public partial class ExpertSystemView : NamedItemView {
44    protected TypeSelectorDialog problemTypeSelectorDialog;
45    protected virtual bool SuppressEvents { get; set; }
46    private bool okbDownloadInProgress;
47
48    public new ExpertSystem Content {
49      get { return (ExpertSystem)base.Content; }
50      set { base.Content = value; }
51    }
52
53    public ExpertSystemView() {
54      InitializeComponent();
55      // brings progress panel to front (it is not visible by default, but obstructs other elements in designer)
56      this.Controls.SetChildIndex(this.progressPanel, 0);
57      algorithmStartButton.Text = string.Empty;
58      algorithmStartButton.Image = VSImageLibrary.Play;
59      refreshMapButton.Text = string.Empty;
60      refreshMapButton.Image = VSImageLibrary.Refresh;
61    }
62
63    protected override void Dispose(bool disposing) {
64      if (disposing) {
65        if (problemTypeSelectorDialog != null) problemTypeSelectorDialog.Dispose();
66        if (components != null) components.Dispose();
67      }
68      base.Dispose(disposing);
69    }
70
71    protected override void DeregisterContentEvents() {
72      Content.PropertyChanged -= ContentOnPropertyChanged;
73      Content.SuggestedInstances.CollectionReset -= SuggestedInstancesOnChanged;
74      Content.SuggestedInstances.ItemsAdded -= SuggestedInstancesOnChanged;
75      Content.SuggestedInstances.ItemsMoved -= SuggestedInstancesOnChanged;
76      Content.SuggestedInstances.ItemsRemoved -= SuggestedInstancesOnChanged;
77      Content.SuggestedInstances.ItemsReplaced -= SuggestedInstancesOnChanged;
78      Content.SolutionPool.ItemsAdded -= SolutionPoolOnChanged;
79      Content.SolutionPool.ItemsRemoved -= SolutionPoolOnChanged;
80      Content.SolutionPool.ItemsReplaced -= SolutionPoolOnChanged;
81      Content.SolutionPool.CollectionReset -= SolutionPoolOnChanged;
82      if (Content.Problem != null) Content.Problem.ProblemChanged -= ContentOnProblemChanged;
83      base.DeregisterContentEvents();
84    }
85    protected override void RegisterContentEvents() {
86      base.RegisterContentEvents();
87      Content.PropertyChanged += ContentOnPropertyChanged;
88      Content.SuggestedInstances.CollectionReset += SuggestedInstancesOnChanged;
89      Content.SuggestedInstances.ItemsAdded += SuggestedInstancesOnChanged;
90      Content.SuggestedInstances.ItemsMoved += SuggestedInstancesOnChanged;
91      Content.SuggestedInstances.ItemsRemoved += SuggestedInstancesOnChanged;
92      Content.SuggestedInstances.ItemsReplaced += SuggestedInstancesOnChanged;
93      Content.SolutionPool.ItemsAdded += SolutionPoolOnChanged;
94      Content.SolutionPool.ItemsRemoved += SolutionPoolOnChanged;
95      Content.SolutionPool.ItemsReplaced += SolutionPoolOnChanged;
96      Content.SolutionPool.CollectionReset += SolutionPoolOnChanged;
97      if (Content.Problem != null) Content.Problem.ProblemChanged += ContentOnProblemChanged;
98    }
99
100    protected override void OnContentChanged() {
101      base.OnContentChanged();
102      SuppressEvents = true;
103      okbDownloadInProgress = false;
104      try {
105        if (Content == null) {
106          maxEvaluationsTextBox.Text = String.Empty;
107
108          problemViewHost.Content = null;
109          algorithmViewHost.Content = null;
110          runsView.Content = null;
111          solutionsViewHost.Content = null;
112          kbViewHost.Content = null;
113          problemInstancesView.Content = null;
114        } else {
115          maxEvaluationsTextBox.Text = Content.MaximumEvaluations.ToString();
116          problemViewHost.Content = Content.Problem;
117          runsView.Content = Content.Runs;
118          solutionsViewHost.Content = Content.SolutionPool;
119          kbViewHost.ViewType = typeof(RunCollectionRLDView);
120          kbViewHost.Content = Content.KnowledgeBase;
121          problemInstancesView.Content = Content.ProblemInstances;
122          algorithmViewHost.Content = Content.CurrentResult;
123        }
124      } finally { SuppressEvents = false; }
125      UpdateSuggestedInstancesCombobox();
126      UpdateNamesComboboxes();
127      UpdateSimilarityCalculators();
128    }
129
130    protected override void SetEnabledStateOfControls() {
131      base.SetEnabledStateOfControls();
132      maxEvaluationsTextBox.Enabled = Content != null && !ReadOnly && !Locked;
133      problemViewHost.Enabled = Content != null && !ReadOnly && !Locked && !okbDownloadInProgress;
134      suggestedInstancesComboBox.Enabled = Content != null && !ReadOnly && !Locked && !okbDownloadInProgress;
135      algorithmStartButton.Enabled = Content != null && !ReadOnly && !Locked && suggestedInstancesComboBox.SelectedIndex >= 0;
136      algorithmViewHost.Enabled = Content != null && !ReadOnly && !Locked;
137      runsView.Enabled = Content != null;
138      kbViewHost.Enabled = Content != null && !okbDownloadInProgress;
139      problemInstancesView.Enabled = Content != null && !okbDownloadInProgress;
140      refreshMapButton.Enabled = Content != null;
141      okbDownloadButton.Enabled = Content != null && Content.Problem != null && Content.Problem.ProblemId >= 0 && !ReadOnly && !Locked && !okbDownloadInProgress;
142    }
143
144    private void UpdateSuggestedInstancesCombobox() {
145      var prevSelection = (IAlgorithm)suggestedInstancesComboBox.SelectedItem;
146      var prevNewIndex = -1;
147      suggestedInstancesComboBox.Items.Clear();
148      if (Content == null) return;
149
150      for (var i = 0; i < Content.SuggestedInstances.Count; i++) {
151        suggestedInstancesComboBox.Items.Add(Content.SuggestedInstances[i]);
152        if (prevSelection == null || Content.SuggestedInstances[i].Name == prevSelection.Name)
153          prevNewIndex = prevSelection == null ? 0 : i;
154      }
155      if (prevNewIndex >= 0) {
156        suggestedInstancesComboBox.SelectedIndex = prevNewIndex;
157      }
158    }
159
160    private void UpdateNamesComboboxes() {
161      var selectedSolutionName = solutionNameComboBox.SelectedIndex >= 0 ? (string)solutionNameComboBox.SelectedItem : string.Empty;
162      var selectedQualityName = qualityNameComboBox.SelectedIndex >= 0 ? (string)qualityNameComboBox.SelectedItem : string.Empty;
163
164      solutionNameComboBox.Items.Clear();
165      qualityNameComboBox.Items.Clear();
166      if (Content == null) return;
167      var qualityNames = new HashSet<string>(Content.SolutionPool.SelectMany(x => x.Variables).Where(x => x.Value is DoubleValue).Select(x => x.Name));
168      var solutionNames = Content.SolutionPool.SelectMany(x => x.Variables).Where(x => !qualityNames.Contains(x.Name));
169
170      foreach (var sn in solutionNames.GroupBy(x => x.Name).OrderBy(x => x.Key)) {
171        solutionNameComboBox.Items.Add(sn.Key);
172        // either it was previously selected, or the variable value is defined in the HeuristicLab.Encodings sub-namespace
173        if (sn.Key == selectedSolutionName || (string.IsNullOrEmpty(selectedSolutionName) && sn.All(x => x.Value != null && x.Value.GetType().FullName.StartsWith("HeuristicLab.Encodings."))))
174          solutionNameComboBox.SelectedItem = sn.Key;
175      }
176      foreach (var qn in qualityNames.OrderBy(x => x)) {
177        qualityNameComboBox.Items.Add(qn);
178        if (qn == selectedQualityName || string.IsNullOrEmpty(selectedQualityName)) qualityNameComboBox.SelectedItem = qn;
179      }
180    }
181
182    private void UpdateSimilarityCalculators() {
183      var selected = (ISolutionSimilarityCalculator)(similarityComboBox.SelectedIndex >= 0 ? similarityComboBox.SelectedItem : null);
184      similarityComboBox.Items.Clear();
185     
186      if (Content == null || Content.Problem == null) return;
187
188      foreach (var calc in Content.Problem.Operators.OfType<ISolutionSimilarityCalculator>()) {
189        similarityComboBox.Items.Add(calc);
190        if (selected != null && calc.ItemName == selected.ItemName) similarityComboBox.SelectedItem = calc;
191      }
192      if (selected == null && similarityComboBox.Items.Count > 0)
193        similarityComboBox.SelectedIndex = 0;
194    }
195
196    #region Event Handlers
197    #region Content events
198    private void ContentOnProblemChanged(object sender, EventArgs eventArgs) {
199      UpdateSuggestedInstancesCombobox();
200      UpdateSimilarityCalculators();
201      SetEnabledStateOfControls();
202    }
203
204    private void ContentOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
205      if (InvokeRequired) {
206        Invoke((Action<object, PropertyChangedEventArgs>)ContentOnPropertyChanged, sender, e);
207        return;
208      }
209      SuppressEvents = true;
210      try {
211        switch (e.PropertyName) {
212          case "KnowledgeBase": kbViewHost.Content = Content.KnowledgeBase; break;
213          case "MaximumEvaluations": maxEvaluationsTextBox.Text = Content.MaximumEvaluations.ToString(); break;
214          case "Problem":
215            problemViewHost.Content = Content.Problem;
216            Content.Problem.ProblemChanged += ContentOnProblemChanged;
217            break;
218          case "ProblemInstances": problemInstancesView.Content = Content.ProblemInstances; break;
219          case "CurrentResult": algorithmViewHost.Content = Content.CurrentResult; break;
220        }
221      } finally { SuppressEvents = false; }
222      SetEnabledStateOfControls();
223    }
224
225    private void SuggestedInstancesOnChanged(object sender, EventArgs e) {
226      UpdateSuggestedInstancesCombobox();
227    }
228
229    private void SolutionPoolOnChanged(object sender, EventArgs e) {
230      UpdateNamesComboboxes();
231      if (qualityNameComboBox.SelectedIndex >= 0) {
232        var qualityName = (string)qualityNameComboBox.SelectedItem;
233        UpdateSolutionQualityAnalysis(qualityName);
234      }
235      if (similarityComboBox.SelectedIndex >= 0) {
236        var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
237        UpdateSolutionDiversityAnalysis(calculator);
238        UpdateSolutionFdcAnalysis(calculator);
239        UpdateSolutionLengthScaleAnalysis(calculator);
240      } else solutionsDiversityViewHost.Content = null;
241    }
242    #endregion
243
244    #region Control events
245    private void MaxEvaluationsTextBoxOnValidating(object sender, CancelEventArgs e) {
246      if (SuppressEvents) return;
247      if (InvokeRequired) {
248        Invoke((Action<object, CancelEventArgs>)MaxEvaluationsTextBoxOnValidating, sender, e);
249        return;
250      }
251      int value;
252      if (!int.TryParse(maxEvaluationsTextBox.Text, out value)) {
253        e.Cancel = !maxEvaluationsTextBox.ReadOnly && maxEvaluationsTextBox.Enabled;
254        errorProvider.SetError(maxEvaluationsTextBox, "Please enter a valid integer number.");
255      } else {
256        Content.MaximumEvaluations = value;
257        e.Cancel = false;
258        errorProvider.SetError(maxEvaluationsTextBox, null);
259      }
260    }
261    #endregion
262    #endregion
263
264    private void RefreshMapButtonOnClick(object sender, EventArgs e) {
265      Content.UpdateInstanceProjection();
266      UpdateProjectionComboBox();
267    }
268
269    private void UpdateProjectionComboBox() {
270      projectionComboBox.Items.Clear();
271      var projStrings = Content.ProblemInstances
272        .SelectMany(x => x.Results.Where(y => Regex.IsMatch(y.Key, "^Projection[.].*[.][XY]$")))
273        .Select(x => Regex.Match(x.Key, "Projection[.](?<g>.*)[.][XY]").Groups["g"].Value)
274        .Distinct();
275      foreach (var str in projStrings) {
276        projectionComboBox.Items.Add(str);
277      }
278    }
279
280    private void OkbDownloadButtonOnClick(object sender, EventArgs e) {
281      if (Content.Problem.ProblemId == -1) {
282        MessageBox.Show("Please select a problem instance first.");
283        return;
284      }
285      var progress = new Progress();
286      progress.ProgressStateChanged += OkbDownloadProgressOnStateChanged;
287      Content.UpdateKnowledgeBaseAsync(progress);
288      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(progressPanel, progress);
289      progressPanel.Visible = true;
290      SetEnabledStateOfControls();
291    }
292
293    private void OkbDownloadProgressOnStateChanged(object sender, EventArgs eventArgs) {
294      var progress = (IProgress)sender;
295      okbDownloadInProgress = progress.ProgressState == ProgressState.Started;
296      SetEnabledStateOfControls();
297      if (!okbDownloadInProgress) {
298        progressPanel.Visible = false;
299        progress.ProgressStateChanged -= OkbDownloadProgressOnStateChanged;
300      }
301    }
302
303    private void AlgorithmStartButtonOnClick(object sender, EventArgs e) {
304      if (suggestedInstancesComboBox.SelectedIndex >= 0)
305        Content.StartAlgorithmAsync(suggestedInstancesComboBox.SelectedIndex);
306    }
307
308    private void ProjectionComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
309      if (projectionComboBox.SelectedIndex < 0) return;
310      var projection = (string)projectionComboBox.SelectedItem;
311      var instancesSeries = instanceMapChart.Series["InstancesSeries"];
312      var currentInstanceSeries = instanceMapChart.Series["CurrentInstanceSeries"];
313
314      instancesSeries.Points.Clear();
315      currentInstanceSeries.Points.Clear();
316
317      foreach (var run in Content.ProblemInstances) {
318        var xKey = "Projection." + projection + ".X";
319        var yKey = "Projection." + projection + ".Y";
320        if (!run.Results.ContainsKey(xKey) || !run.Results.ContainsKey(yKey)
321          || !(run.Results[xKey] is Data.DoubleValue) || !(run.Results[yKey] is Data.DoubleValue)) continue;
322        var x = ((Data.DoubleValue)run.Results[xKey]).Value;
323        var y = ((Data.DoubleValue)run.Results[yKey]).Value;
324        var dataPoint = new DataPoint(x, y) {
325          Label = run.Name
326        };
327        instancesSeries.Points.Add(dataPoint);
328      }
329
330      var curPoint = Content.ProjectCurrentInstance(projection);
331      if (curPoint != null) {
332        var dp = new DataPoint(curPoint.Item1, curPoint.Item2) {
333          Label = Content.Problem.Problem.Name
334        };
335        currentInstanceSeries.Points.Add(dp);
336      }
337    }
338
339    private void UpdateSolutionQualityAnalysis(string qualityName) {
340      var dt = solutionsQualityViewHost.Content as DataTable;
341      if (dt == null) {
342        dt = QualityDistributionAnalyzer.PrepareTable(qualityName);
343        solutionsQualityViewHost.Content = dt;
344      }
345      QualityDistributionAnalyzer.UpdateTable(dt, Content.SolutionPool.Where(x => x.Variables.ContainsKey(qualityName)).Select(x => x.Variables[qualityName].Value).OfType<DoubleValue>().Select(x => x.Value));
346    }
347
348    private void UpdateSolutionDiversityAnalysis(ISolutionSimilarityCalculator calculator) {
349      try {
350        solutionsDiversityViewHost.Content = null;
351        if (Content.SolutionPool == null) return;
352        var similarities = new double[Content.SolutionPool.Count, Content.SolutionPool.Count];
353        for (int i = 0; i < Content.SolutionPool.Count; i++) {
354          for (int j = 0; j < Content.SolutionPool.Count; j++)
355            similarities[i, j] = calculator.CalculateSolutionSimilarity(Content.SolutionPool[i], Content.SolutionPool[j]);
356        }
357        var hm = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
358        solutionsDiversityViewHost.Content = hm;
359      } catch { }
360    }
361
362    private void UpdateSolutionFdcAnalysis(ISolutionSimilarityCalculator calculator) {
363      try {
364        solutionsFdcViewHost.Content = null;
365        if (Content.SolutionPool == null) return;
366        var points = new List<Point2D<double>>();
367        for (int i = 0; i < Content.SolutionPool.Count; i++) {
368          for (int j = 0; j < Content.SolutionPool.Count; j++) {
369            if (i == j) continue;
370            var qDiff = Math.Abs(((DoubleValue)Content.SolutionPool[i].Variables[calculator.QualityVariableName].Value).Value - ((DoubleValue)Content.SolutionPool[j].Variables[calculator.QualityVariableName].Value).Value);
371            points.Add(new Point2D<double>(qDiff, 1.0 - calculator.CalculateSolutionSimilarity(Content.SolutionPool[i], Content.SolutionPool[j])));
372          }
373        }
374        var splot = new ScatterPlot("Fitness-Distance", "");
375        var row = new ScatterPlotDataRow("Fdc", "", points);
376        row.VisualProperties.PointSize = 7;
377        splot.Rows.Add(row);
378        solutionsFdcViewHost.Content = splot;
379      } catch { }
380    }
381
382    private void UpdateSolutionLengthScaleAnalysis(ISolutionSimilarityCalculator calculator) {
383      try {
384        solutionsLengthScaleViewHost.Content = null;
385        if (Content.SolutionPool == null) return;
386        var dt = solutionsLengthScaleViewHost.Content as DataTable;
387        if (dt == null) {
388          dt = QualityDistributionAnalyzer.PrepareTable("Length Scale");
389          solutionsLengthScaleViewHost.Content = dt;
390        }
391
392        QualityDistributionAnalyzer.UpdateTable(dt, CalculateLengthScale(calculator));
393      } catch { }
394    }
395
396    private IEnumerable<double> CalculateLengthScale(ISolutionSimilarityCalculator calculator) {
397      for (int i = 0; i < Content.SolutionPool.Count; i++) {
398        for (int j = 0; j < Content.SolutionPool.Count; j++) {
399          if (i == j) continue;
400          var sim = calculator.CalculateSolutionSimilarity(Content.SolutionPool[i], Content.SolutionPool[j]);
401          if (sim.IsAlmost(0)) continue;
402          var qDiff = Math.Abs(((DoubleValue)Content.SolutionPool[i].Variables[calculator.QualityVariableName].Value).Value - ((DoubleValue)Content.SolutionPool[j].Variables[calculator.QualityVariableName].Value).Value);
403          yield return qDiff / sim;
404        }
405      }
406    }
407
408    private void SuggestedInstancesComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
409      SetEnabledStateOfControls();
410    }
411
412    private void qualityNameComboBox_SelectedIndexChanged(object sender, EventArgs e) {
413      if (qualityNameComboBox.SelectedIndex < 0) return;
414      solutionsQualityViewHost.Content = null;
415      solutionsDiversityViewHost.Content = null;
416      var qualityName = (string)qualityNameComboBox.SelectedItem;
417      UpdateSolutionQualityAnalysis(qualityName);
418      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
419      if (calculator != null) calculator.QualityVariableName = qualityName;
420      UpdateSolutionDiversityAnalysis(calculator);
421      UpdateSolutionFdcAnalysis(calculator);
422      UpdateSolutionLengthScaleAnalysis(calculator);
423    }
424
425    private void solutionNameComboBox_SelectedIndexChanged(object sender, EventArgs e) {
426      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
427      if (calculator != null) calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
428      UpdateSolutionDiversityAnalysis(calculator);
429      UpdateSolutionFdcAnalysis(calculator);
430      UpdateSolutionLengthScaleAnalysis(calculator);
431    }
432
433    private void similarityComboBox_SelectedIndexChanged(object sender, EventArgs e) {
434      var calculator = (ISolutionSimilarityCalculator)similarityComboBox.SelectedItem;
435      if (calculator != null) {
436        calculator.SolutionVariableName = (string)solutionNameComboBox.SelectedItem;
437        calculator.QualityVariableName = (string)qualityNameComboBox.SelectedItem;
438      }
439      UpdateSolutionDiversityAnalysis(calculator);
440      UpdateSolutionFdcAnalysis(calculator);
441      UpdateSolutionLengthScaleAnalysis(calculator);
442    }
443  }
444}
Note: See TracBrowser for help on using the repository browser.