Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs @ 12813

Last change on this file since 12813 was 12808, checked in by abeham, 9 years ago

#2431:

  • added ability to plot curves for multiple targets at once
  • fixed bug in IndexedDataTableView regarding log-scaling
  • added result that counts restarts
  • fixed bugs in IRRestarter
  • Set LineWidth = 2 in analyzers for chart
  • fixed bugs in RLD view
File size: 18.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.Core.Views;
30using HeuristicLab.Data;
31using HeuristicLab.MainForm;
32using HeuristicLab.MainForm.WindowsForms;
33
34namespace HeuristicLab.Optimization.Views {
35  [View("Run-length Distribution View")]
36  [Content(typeof(RunCollection), false)]
37  public partial class RunCollectionRLDView : ItemView {
38    private const string AllRuns = "All Runs";
39
40    public new RunCollection Content {
41      get { return (RunCollection)base.Content; }
42      set { base.Content = value; }
43    }
44
45    private double[] levels;
46
47    private bool suppressUpdates;
48    private readonly IndexedDataTable<double> combinedDataTable;
49    public IndexedDataTable<double> CombinedDataTable {
50      get { return combinedDataTable; }
51    }
52
53    public RunCollectionRLDView() {
54      InitializeComponent();
55      combinedDataTable = new IndexedDataTable<double>("Combined DataTable", "A data table containing the ECDF of each of a number of groups.") {
56        VisualProperties = {
57          YAxisTitle = "Proportion of reached targets",
58          YAxisMinimumFixedValue = 0, YAxisMinimumAuto = false,
59          YAxisMaximumFixedValue = 1, YAxisMaximumAuto = false
60        }
61      };
62      viewHost.Content = combinedDataTable;
63      suppressUpdates = false;
64    }
65
66    #region Content events
67    protected override void RegisterContentEvents() {
68      base.RegisterContentEvents();
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    }
75    protected override void DeregisterContentEvents() {
76      Content.ItemsAdded -= Content_ItemsAdded;
77      Content.ItemsRemoved -= Content_ItemsRemoved;
78      Content.CollectionReset -= Content_CollectionReset;
79      Content.UpdateOfRunsInProgressChanged -= Content_UpdateOfRunsInProgressChanged;
80      Content.OptimizerNameChanged -= Content_AlgorithmNameChanged;
81      base.DeregisterContentEvents();
82    }
83
84    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
85      if (suppressUpdates) return;
86      if (InvokeRequired) {
87        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded), sender, e);
88        return;
89      }
90      UpdateGroupComboBox();
91      UpdateDataTableComboBox();
92      foreach (var run in e.Items)
93        RegisterRunEvents(run);
94    }
95    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
96      if (suppressUpdates) return;
97      if (InvokeRequired) {
98        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved), sender, e);
99        return;
100      }
101      UpdateGroupComboBox();
102      UpdateDataTableComboBox();
103      foreach (var run in e.Items)
104        DeregisterRunEvents(run);
105    }
106    private void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
107      if (suppressUpdates) return;
108      if (InvokeRequired) {
109        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset), sender, e);
110        return;
111      }
112      UpdateGroupComboBox();
113      UpdateDataTableComboBox();
114      foreach (var run in e.OldItems)
115        DeregisterRunEvents(run);
116    }
117    private void Content_AlgorithmNameChanged(object sender, EventArgs e) {
118      if (InvokeRequired)
119        Invoke(new EventHandler(Content_AlgorithmNameChanged), sender, e);
120      else UpdateCaption();
121    }
122    private void Content_UpdateOfRunsInProgressChanged(object sender, EventArgs e) {
123      if (InvokeRequired) {
124        Invoke(new EventHandler(Content_UpdateOfRunsInProgressChanged), sender, e);
125        return;
126      }
127      suppressUpdates = Content.UpdateOfRunsInProgress;
128      if (!suppressUpdates) {
129        UpdateDataTableComboBox();
130        UpdateGroupComboBox();
131        UpdateRuns();
132      }
133    }
134
135    private void RegisterRunEvents(IRun run) {
136      run.PropertyChanged += run_PropertyChanged;
137    }
138    private void DeregisterRunEvents(IRun run) {
139      run.PropertyChanged -= run_PropertyChanged;
140    }
141    private void run_PropertyChanged(object sender, PropertyChangedEventArgs e) {
142      if (suppressUpdates) return;
143      if (InvokeRequired) {
144        Invoke((Action<object, PropertyChangedEventArgs>)run_PropertyChanged, sender, e);
145      } else {
146        if (e.PropertyName == "Visible")
147          UpdateRuns();
148      }
149    }
150    #endregion
151
152    protected override void OnContentChanged() {
153      base.OnContentChanged();
154      dataTableComboBox.Items.Clear();
155      groupComboBox.Items.Clear();
156      combinedDataTable.Rows.Clear();
157
158      UpdateCaption();
159      if (Content != null) {
160        UpdateGroupComboBox();
161        UpdateDataTableComboBox();
162      }
163    }
164
165    protected override void SetEnabledStateOfControls() {
166      base.SetEnabledStateOfControls();
167      groupComboBox.Enabled = Content != null;
168      dataTableComboBox.Enabled = Content != null;
169      fixedTargetButton.Enabled = Content != null && levels != null && dataTableComboBox.SelectedIndex >= 0;
170    }
171
172    private void UpdateRuns() {
173      if (InvokeRequired) {
174        Invoke((Action)UpdateRuns);
175        return;
176      }
177      SuspendRepaint();
178      try {
179        combinedDataTable.VisualProperties.XAxisLogScale = false;
180        combinedDataTable.Rows.Clear();
181        var table = (string)dataTableComboBox.SelectedItem;
182        if (string.IsNullOrEmpty(table)) return;
183        if (levels == null) {
184          var worstMin = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.First().Item2).Min();
185          var worstMax = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.First().Item2).Max();
186          var bestMin = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Last().Item2).Min();
187          var bestMax = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Last().Item2).Max();
188          double worst, best;
189          if (Math.Abs(bestMax - worstMin) > Math.Abs(bestMin - worstMax)) {
190            worst = worstMin;
191            best = bestMax;
192          } else {
193            worst = worstMax;
194            best = bestMin;
195          }
196          levels = Enumerable.Range(0, 11).Select(x => worst + (x / 10.0) * (best - worst)).ToArray();
197          suppressTargetsEvents = true;
198          targetsTextBox.Text = string.Join(" ; ", levels);
199          suppressTargetsEvents = false;
200        }
201        var selectedGroup = (string)groupComboBox.SelectedItem;
202        if (string.IsNullOrEmpty(selectedGroup)) return;
203        List<Tuple<string, List<IRun>>> groupedRuns;
204        if (selectedGroup == AllRuns)
205          groupedRuns = new List<Tuple<string, List<IRun>>> { Tuple.Create(AllRuns, Content.ToList()) };
206        else groupedRuns = (from r in Content
207                            group r by r.Parameters[selectedGroup].ToString() into g
208                            select Tuple.Create(g.Key, g.ToList())).ToList();
209        var xAxisTitles = new HashSet<string>();
210        foreach (var group in groupedRuns) {
211          var hits = new Dictionary<string, SortedList<double, double>>();
212          foreach (var run in group.Item2) {
213            if (!run.Results.ContainsKey(table)) continue;
214            var resultsTable = (IndexedDataTable<double>)run.Results[table];
215            xAxisTitles.Add(resultsTable.VisualProperties.XAxisTitle);
216            var values = resultsTable.Rows.First().Values;
217            var maximization = values.First().Item2 < values.Last().Item2;
218            if (allOrEachTargetCheckBox.Checked) {
219              // each
220              foreach (double l in levels) {
221                var key = "-" + l.ToString();
222                if (!hits.ContainsKey(key)) hits.Add(key, new SortedList<double, double>());
223                foreach (var v in values) {
224                  if (maximization && v.Item2 >= l || !maximization && v.Item2 <= l) {
225                    if (hits[key].ContainsKey(v.Item1))
226                      hits[key][v.Item1] += 1.0 / group.Item2.Count;
227                    else hits[key][v.Item1] = 1.0 / group.Item2.Count;
228                    break;
229                  }
230                }
231              }
232            } else {
233              if (!hits.ContainsKey("all")) hits.Add("all", new SortedList<double, double>());
234              // all
235              var i = 0;
236              var j = 0;
237              var current = values[j];
238              var prev = Tuple.Create(-1.0, double.NaN);
239              while (i < levels.Length) {
240                if ((double.IsNaN(prev.Item2) || prev.Item2 != current.Item2)
241                    && (maximization && current.Item2 >= levels[i]
242                        || !maximization && current.Item2 <= levels[i])) {
243                  if (hits["all"].ContainsKey(current.Item1))
244                    hits["all"][current.Item1] += 1.0 / (group.Item2.Count * levels.Length);
245                  else hits["all"][current.Item1] = 1.0 / (group.Item2.Count * levels.Length);
246                  i++;
247                } else {
248                  j++;
249                  if (j >= values.Count) break;
250                  prev = current;
251                  current = values[j];
252                }
253              }
254            }
255          }
256          foreach (var list in hits) {
257            var row = new IndexedDataRow<double>(group.Item1 + (list.Key != "all" ? list.Key : string.Empty)) {
258              VisualProperties = {
259                ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
260                LineWidth = 2
261              }
262            };
263            var total = 0.0;
264            foreach (var h in list.Value) {
265              total += h.Value;
266              row.Values.Add(Tuple.Create(h.Key, total));
267            }
268            combinedDataTable.Rows.Add(row);
269          }
270        }
271        combinedDataTable.VisualProperties.XAxisTitle = string.Join(" / ", xAxisTitles);
272        combinedDataTable.VisualProperties.XAxisLogScale = combinedDataTable.Rows.Count > 0 && logScalingCheckBox.Checked;
273      } finally { ResumeRepaint(true); }
274    }
275
276    private void UpdateGroupComboBox() {
277      string selectedItem = (string)groupComboBox.SelectedItem;
278
279      var groupings = Content.ParameterNames.OrderBy(x => x).ToArray();
280      groupComboBox.Items.Clear();
281      groupComboBox.Items.Add(AllRuns);
282      groupComboBox.Items.AddRange(groupings);
283      if (selectedItem != null && groupComboBox.Items.Contains(selectedItem)) {
284        groupComboBox.SelectedItem = selectedItem;
285      } else if (groupComboBox.Items.Count > 0) {
286        groupComboBox.SelectedItem = groupComboBox.Items[0];
287      }
288    }
289
290    private void UpdateDataTableComboBox() {
291      string selectedItem = (string)dataTableComboBox.SelectedItem;
292
293      dataTableComboBox.Items.Clear();
294      var dataTables = (from run in Content
295                        from result in run.Results
296                        where result.Value is IndexedDataTable<double>
297                        select result.Key).Distinct().ToArray();
298
299      dataTableComboBox.Items.AddRange(dataTables);
300      if (selectedItem != null && dataTableComboBox.Items.Contains(selectedItem)) {
301        dataTableComboBox.SelectedItem = selectedItem;
302      } else if (dataTableComboBox.Items.Count > 0) {
303        dataTableComboBox.SelectedItem = dataTableComboBox.Items[0];
304      }
305    }
306
307    private void UpdateCaption() {
308      Caption = Content != null ? Content.OptimizerName + " RLD View" : ViewAttribute.GetViewName(GetType());
309    }
310
311    private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
312      UpdateRuns();
313      SetEnabledStateOfControls();
314    }
315    private void dataTableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
316      UpdateRuns();
317      SetEnabledStateOfControls();
318    }
319
320    private void logScalingCheckBox_CheckedChanged(object sender, EventArgs e) {
321      combinedDataTable.VisualProperties.XAxisLogScale = logScalingCheckBox.Checked;
322    }
323
324    private bool suppressTargetsEvents;
325    private void targetsTextBox_Validating(object sender, CancelEventArgs e) {
326      if (suppressTargetsEvents) return;
327      var targetStrings = targetsTextBox.Text.Split(new[] { ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
328      var targetList = new List<double>();
329      foreach (var ts in targetStrings) {
330        double t;
331        if (!double.TryParse(ts, out t)) {
332          errorProvider.SetError(targetsTextBox, "Not all targets can be parsed: " + ts);
333          e.Cancel = true;
334          return;
335        }
336        targetList.Add(t);
337      }
338      if (targetList.Count == 0) {
339        errorProvider.SetError(targetsTextBox, "Give at least one target value!");
340        e.Cancel = true;
341        return;
342      }
343      e.Cancel = false;
344      errorProvider.SetError(targetsTextBox, null);
345      levels = targetList.ToArray();
346      UpdateRuns();
347      SetEnabledStateOfControls();
348    }
349
350    private void generateTargetsButton_Click(object sender, EventArgs e) {
351      decimal max = 1, min = 0, count = 10;
352      if (levels != null) {
353        max = (decimal)Math.Max(levels.First(), levels.Last());
354        min = (decimal)Math.Min(levels.First(), levels.Last());
355        count = levels.Length;
356      } else if (Content.Count > 0 && dataTableComboBox.SelectedIndex >= 0) {
357        var table = (string)dataTableComboBox.SelectedItem;
358        var worst = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Max(y => y.Item2)).First();
359        var best = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Min(y => y.Item2)).Last();
360        max = (decimal)Math.Max(best, worst);
361        min = (decimal)Math.Min(best, worst);
362        count = 10;
363      }
364      using (var dialog = new DefineArithmeticProgressionDialog(false, min, max, (max - min) / count)) {
365        if (dialog.ShowDialog() == DialogResult.OK) {
366          if (dialog.Values.Any()) {
367            var maximization = true;
368            if (Content.Count > 0 && Content.First().Parameters.ContainsKey("Maximization"))
369              maximization = ((BoolValue)Content.First().Parameters["Maximization"]).Value;
370
371            levels = maximization ? dialog.Values.Select(x => (double)x).ToArray()
372                                  : dialog.Values.Reverse().Select(x => (double)x).ToArray();
373            suppressTargetsEvents = true;
374            targetsTextBox.Text = string.Join(" ; ", levels);
375            suppressTargetsEvents = false;
376
377            UpdateRuns();
378            SetEnabledStateOfControls();
379          }
380        }
381      }
382    }
383
384    private void fixedTargetButton_Click(object sender, EventArgs e) {
385      var table = (string)dataTableComboBox.SelectedItem;
386      foreach (var run in Content) {
387        if (!run.Results.ContainsKey(table)) continue;
388        var resultsTable = (IndexedDataTable<double>)run.Results[table];
389        var values = resultsTable.Rows.First().Values;
390        var maximization = values.First().Item2 < values.Last().Item2;
391        var i = 0;
392        var j = 0;
393        var current = values[j];
394        var prev = Tuple.Create(-1.0, double.NaN);
395        while (i < levels.Length) {
396          if (prev.Item2 != current.Item2
397              && (maximization && current.Item2 >= levels[i]
398              || !maximization && current.Item2 <= levels[i])) {
399            run.Results[table + ".Target" + levels[i]] = new DoubleValue(current.Item1);
400            i++;
401          } else {
402            j++;
403            if (j >= values.Count) break;
404            prev = current;
405            current = values[j];
406          }
407        }
408      }
409    }
410
411    private void fixedCostButton_Click(object sender, EventArgs e) {
412      var table = (string)dataTableComboBox.SelectedItem;
413      var budgetStrings = budgetsTextBox.Text.Split(new[] { ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
414      if (budgetStrings.Length == 0) {
415        MessageBox.Show("Define a number of budgets.");
416        return;
417      }
418      var budgetList = new List<double>();
419      foreach (var bs in budgetStrings) {
420        double v;
421        if (!double.TryParse(bs, out v)) {
422          MessageBox.Show("Budgets must be a valid number: " + bs);
423          return;
424        }
425        budgetList.Add(v);
426      }
427      budgetList.Sort();
428
429      foreach (var run in Content) {
430        if (!run.Results.ContainsKey(table)) continue;
431        var resultsTable = (IndexedDataTable<double>)run.Results[table];
432        var values = resultsTable.Rows.First().Values;
433        var i = 0;
434        var j = 0;
435        var current = values[j];
436        var prev = Tuple.Create(-1.0, double.NaN);
437        while (i < budgetList.Count) {
438          if (prev.Item2 != current.Item2 && current.Item1 >= budgetList[i]) {
439            run.Results[table + ".Cost" + budgetList[i]] = new DoubleValue(double.IsNaN(prev.Item2) || current.Item1 == budgetList[i] ? current.Item2 : prev.Item2);
440            i++;
441          } else {
442            j++;
443            if (j >= values.Count) break;
444            prev = current;
445            current = values[j];
446          }
447        }
448      }
449    }
450
451    private void allOrEachTargetCheckBox_CheckedChanged(object sender, EventArgs e) {
452      var each = allOrEachTargetCheckBox.Checked;
453      allOrEachTargetCheckBox.Text = each ? "each" : "all";
454      UpdateRuns();
455    }
456  }
457}
Note: See TracBrowser for help on using the repository browser.