source: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionECDFView.cs @ 12774

Last change on this file since 12774 was 12774, checked in by abeham, 6 years ago

#2431: minor improvements

File size: 10.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.ComponentModel;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Analysis;
28using HeuristicLab.Collections;
29using HeuristicLab.Common;
30using HeuristicLab.Core.Views;
31using HeuristicLab.MainForm;
32
33namespace HeuristicLab.Optimization.Views {
34  [View("ECDF Performance Comparison")]
35  [Content(typeof(RunCollection), false)]
36  public partial class RunCollectionECDFView : ItemView {
37    private const string AllRuns = "All Runs";
38
39    public new RunCollection Content {
40      get { return (RunCollection)base.Content; }
41      set { base.Content = value; }
42    }
43
44    private bool suppressUpdates;
45    private readonly IndexedDataTable<double> combinedDataTable;
46    public IndexedDataTable<double> CombinedDataTable {
47      get { return combinedDataTable; }
48    }
49
50    public RunCollectionECDFView() {
51      InitializeComponent();
52      combinedDataTable = new IndexedDataTable<double>("Combined DataTable", "A data table containing the ECDF of each of a number of groups.") {
53        VisualProperties = { YAxisTitle = "Proportion of reached targets" }
54      };
55      viewHost.Content = combinedDataTable;
56      suppressUpdates = false;
57    }
58
59    #region Content events
60    protected override void RegisterContentEvents() {
61      base.RegisterContentEvents();
62      Content.ItemsAdded += Content_ItemsAdded;
63      Content.ItemsRemoved += Content_ItemsRemoved;
64      Content.CollectionReset += Content_CollectionReset;
65      Content.UpdateOfRunsInProgressChanged += Content_UpdateOfRunsInProgressChanged;
66      Content.OptimizerNameChanged += Content_AlgorithmNameChanged;
67    }
68    protected override void DeregisterContentEvents() {
69      Content.ItemsAdded -= Content_ItemsAdded;
70      Content.ItemsRemoved -= Content_ItemsRemoved;
71      Content.CollectionReset -= Content_CollectionReset;
72      Content.UpdateOfRunsInProgressChanged -= Content_UpdateOfRunsInProgressChanged;
73      Content.OptimizerNameChanged -= Content_AlgorithmNameChanged;
74      base.DeregisterContentEvents();
75    }
76
77    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
78      if (suppressUpdates) return;
79      if (InvokeRequired) {
80        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded), sender, e);
81        return;
82      }
83      UpdateGroupComboBox();
84      UpdateDataTableComboBox();
85      foreach (var run in e.Items)
86        RegisterRunEvents(run);
87    }
88    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
89      if (suppressUpdates) return;
90      if (InvokeRequired) {
91        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved), sender, e);
92        return;
93      }
94      UpdateGroupComboBox();
95      UpdateDataTableComboBox();
96      foreach (var run in e.Items)
97        DeregisterRunEvents(run);
98    }
99    private void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
100      if (suppressUpdates) return;
101      if (InvokeRequired) {
102        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset), sender, e);
103        return;
104      }
105      UpdateGroupComboBox();
106      UpdateDataTableComboBox();
107      foreach (var run in e.OldItems)
108        DeregisterRunEvents(run);
109    }
110    private void Content_AlgorithmNameChanged(object sender, EventArgs e) {
111      if (InvokeRequired)
112        Invoke(new EventHandler(Content_AlgorithmNameChanged), sender, e);
113      else UpdateCaption();
114    }
115    private void Content_UpdateOfRunsInProgressChanged(object sender, EventArgs e) {
116      if (InvokeRequired) {
117        Invoke(new EventHandler(Content_UpdateOfRunsInProgressChanged), sender, e);
118        return;
119      }
120      suppressUpdates = Content.UpdateOfRunsInProgress;
121      if (!suppressUpdates) {
122        UpdateDataTableComboBox();
123        UpdateGroupComboBox();
124        UpdateRuns();
125      }
126    }
127
128    private void RegisterRunEvents(IRun run) {
129      run.PropertyChanged += run_PropertyChanged;
130    }
131    private void DeregisterRunEvents(IRun run) {
132      run.PropertyChanged -= run_PropertyChanged;
133    }
134    private void run_PropertyChanged(object sender, PropertyChangedEventArgs e) {
135      if (suppressUpdates) return;
136      if (InvokeRequired) {
137        Invoke((Action<object, PropertyChangedEventArgs>)run_PropertyChanged, sender, e);
138      } else {
139        if (e.PropertyName == "Visible")
140          UpdateRuns();
141      }
142    }
143    #endregion
144
145    protected override void OnContentChanged() {
146      base.OnContentChanged();
147      dataTableComboBox.Items.Clear();
148      groupComboBox.Items.Clear();
149      combinedDataTable.Rows.Clear();
150
151      UpdateCaption();
152      if (Content != null) {
153        UpdateGroupComboBox();
154        UpdateDataTableComboBox();
155      }
156    }
157
158    private void UpdateRuns() {
159      if (InvokeRequired) {
160        Invoke((Action)UpdateRuns);
161        return;
162      }
163      SuspendRepaint();
164      try {
165        combinedDataTable.VisualProperties.XAxisLogScale = false;
166        combinedDataTable.Rows.Clear();
167        var table = (string)dataTableComboBox.SelectedItem;
168        if (string.IsNullOrEmpty(table)) return;
169        var maximum = Content.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Max(y => y.Item2)).Max();
170        var minimum = Content.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Min(y => y.Item2)).Min();
171        var levels = Enumerable.Range(0, 51).Select(x => maximum - (x / 50.0) * (maximum - minimum)).ToArray();
172        var selectedGroup = (string)groupComboBox.SelectedItem;
173        if (string.IsNullOrEmpty(selectedGroup)) return;
174        List<Tuple<string, List<IRun>>> groupedRuns;
175        if (selectedGroup == AllRuns)
176          groupedRuns = new List<Tuple<string, List<IRun>>> { Tuple.Create(AllRuns, Content.ToList()) };
177        else groupedRuns = (from r in Content
178                            group r by r.Parameters[selectedGroup].ToString() into g
179                            select Tuple.Create(g.Key, g.ToList())).ToList();
180        var xAxisTitles = new HashSet<string>();
181        foreach (var group in groupedRuns) {
182          var hits = new SortedList<double, int>();
183          foreach (var run in group.Item2) {
184            var resultsTable = (IndexedDataTable<double>)run.Results[table];
185            xAxisTitles.Add(resultsTable.VisualProperties.XAxisTitle);
186            var graph = new LinkedList<Tuple<double, double>>(resultsTable.Rows.First().Values);
187            var current = graph.First.Next;
188            // prune convergence graph to obtain first hit times only
189            while (current != null) {
190              if (current.Value.Item2.IsAlmost(current.Previous.Value.Item2)) {
191                var h = current;
192                current = current.Previous;
193                graph.Remove(h);
194              }
195              current = current.Next;
196            }
197            var i = 0;
198            current = graph.First;
199            while (i < levels.Length && current != null) {
200              if (current.Value.Item2 < levels[i]) {
201                if (hits.ContainsKey(current.Value.Item1))
202                  hits[current.Value.Item1]++;
203                else hits[current.Value.Item1] = 1;
204                i++;
205              } else {
206                current = current.Next;
207              }
208            }
209          }
210          var row = new IndexedDataRow<double>(group.Item1) { VisualProperties = { ChartType = DataRowVisualProperties.DataRowChartType.StepLine } };
211          var total = 0.0;
212          foreach (var h in hits) {
213            total += h.Value;
214            row.Values.Add(Tuple.Create(h.Key, total / (group.Item2.Count * levels.Length)));
215          }
216          combinedDataTable.Rows.Add(row);
217        }
218        combinedDataTable.VisualProperties.XAxisTitle = string.Join(" / ", xAxisTitles);
219        combinedDataTable.VisualProperties.XAxisLogScale = logScalingCheckBox.Checked;
220      } finally { ResumeRepaint(true); }
221    }
222
223    private void UpdateGroupComboBox() {
224      string selectedItem = (string)groupComboBox.SelectedItem;
225
226      var groupings = Content.ParameterNames.OrderBy(x => x).ToArray();
227      groupComboBox.Items.Clear();
228      groupComboBox.Items.Add(AllRuns);
229      groupComboBox.Items.AddRange(groupings);
230      if (selectedItem != null && groupComboBox.Items.Contains(selectedItem)) {
231        groupComboBox.SelectedItem = selectedItem;
232      } else if (groupComboBox.Items.Count > 0) {
233        groupComboBox.SelectedItem = groupComboBox.Items[0];
234      }
235    }
236
237    private void UpdateDataTableComboBox() {
238      string selectedItem = (string)dataTableComboBox.SelectedItem;
239
240      dataTableComboBox.Items.Clear();
241      var dataTables = (from run in Content
242                        from result in run.Results
243                        where result.Value is IndexedDataTable<double>
244                        select result.Key).Distinct().ToArray();
245
246      dataTableComboBox.Items.AddRange(dataTables);
247      if (selectedItem != null && dataTableComboBox.Items.Contains(selectedItem)) {
248        dataTableComboBox.SelectedItem = selectedItem;
249      } else if (dataTableComboBox.Items.Count > 0) {
250        dataTableComboBox.SelectedItem = dataTableComboBox.Items[0];
251      }
252    }
253
254    private void UpdateCaption() {
255      Caption = Content != null ? Content.OptimizerName + " ECDF Comparison" : ViewAttribute.GetViewName(GetType());
256    }
257
258    private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
259      UpdateRuns();
260    }
261    private void dataTableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
262      UpdateRuns();
263    }
264
265    private void logScalingCheckBox_CheckedChanged(object sender, EventArgs e) {
266      combinedDataTable.VisualProperties.XAxisLogScale = logScalingCheckBox.Checked;
267    }
268  }
269}
Note: See TracBrowser for help on using the repository browser.