Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.cs @ 13485

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

#2457:

  • fixed bugs in iterated sampling view
  • worked on download runs from okb feature
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.Globalization;
26using System.Linq;
27using System.Windows.Forms.DataVisualization.Charting;
28using HeuristicLab.Analysis;
29using HeuristicLab.Common;
30using HeuristicLab.Data;
31using HeuristicLab.MainForm;
32using HeuristicLab.MainForm.WindowsForms;
33
34namespace HeuristicLab.Optimization.Views.RunCollectionViews {
35  [View("Run-length Cut-off Estimation View")]
36  [Content(typeof(RunCollection), IsDefaultView = false)]
37  public sealed partial class RunCollectionIteratedSamplingView : AsynchronousContentView {
38    private bool suppressEvents;
39
40    public new RunCollection Content {
41      get { return (RunCollection)base.Content; }
42      set { base.Content = value; }
43    }
44
45    public RunCollectionIteratedSamplingView() {
46      InitializeComponent();
47    }
48
49    protected override void DeregisterContentEvents() {
50      base.DeregisterContentEvents();
51    }
52
53    protected override void RegisterContentEvents() {
54      base.RegisterContentEvents();
55    }
56
57    protected override void OnContentChanged() {
58      base.OnContentChanged();
59      suppressEvents = true;
60      try {
61        UpdateGroupComboBox();
62        RecalculateTarget();
63      } finally { suppressEvents = false; }
64    }
65
66    protected override void SetEnabledStateOfControls() {
67      base.SetEnabledStateOfControls();
68      groupComboBox.Enabled = Content != null;
69      groupInstanceComboBox.Enabled = Content != null && groupInstanceComboBox.Items.Count > 1;
70      problemComboBox.Enabled = Content != null && problemComboBox.Items.Count > 1;
71      dataTableComboBox.Enabled = Content != null && dataTableComboBox.Items.Count > 1;
72    }
73
74    private void UpdateGroupComboBox() {
75      try {
76
77        var selectedGroupItem = (string)groupComboBox.SelectedItem;
78        groupComboBox.Items.Clear();
79        groupComboBox.SelectedItem = null;
80
81        var paramNames = Content.ParameterNames.OrderBy(x => x, new NaturalStringComparer());
82        foreach (var name in paramNames) {
83          groupComboBox.Items.Add(name);
84          if (selectedGroupItem == name) groupComboBox.SelectedItem = name;
85        }
86        if (groupComboBox.SelectedItem == null && groupComboBox.Items.Count > 0)
87          groupComboBox.SelectedItem = groupComboBox.Items[0];
88
89      } finally { UpdateGroupInstanceComboBox(); }
90    }
91
92    private void UpdateGroupInstanceComboBox() {
93      try {
94
95        var selectedGroupInstanceItem = (string)groupInstanceComboBox.SelectedItem;
96        groupInstanceComboBox.Items.Clear();
97        groupInstanceComboBox.SelectedItem = null;
98
99        var selectedGroupItem = (string)groupComboBox.SelectedItem;
100        if (selectedGroupItem == null) return;
101
102        var paramValues = GetRunsFiltered()
103                              .Select(x => x.Parameters[selectedGroupItem].ToString())
104                              .Distinct()
105                              .OrderBy(x => x, new NaturalStringComparer());
106        foreach (var value in paramValues) {
107          groupInstanceComboBox.Items.Add(value);
108          if (selectedGroupInstanceItem == value) groupInstanceComboBox.SelectedItem = value;
109        }
110        if (groupInstanceComboBox.SelectedItem == null && groupInstanceComboBox.Items.Count > 0)
111          groupInstanceComboBox.SelectedItem = groupInstanceComboBox.Items[0];
112
113      } finally { UpdateProblemCombobBox(); }
114    }
115
116    private void UpdateProblemCombobBox() {
117      try {
118
119        var selectedProblemItem = (ProblemDescription)problemComboBox.SelectedItem;
120        problemComboBox.Items.Clear();
121        problemComboBox.SelectedItem = null;
122
123        var problems = new HashSet<ProblemDescription>();
124        foreach (var run in GetRunsFiltered()) {
125          problems.Add(new ProblemDescription(run));
126        }
127
128        var problemTypesDifferent = problems.Select(x => x.ProblemType).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
129        var problemNamesDifferent = problems.Select(x => x.ProblemName).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
130        var evaluatorDifferent = problems.Select(x => x.Evaluator).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
131        var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent;
132
133        foreach (var prob in problems.OrderBy(x => x.ToString()).ToList()) {
134          prob.DisplayProblemType = problemTypesDifferent;
135          prob.DisplayProblemName = problemNamesDifferent || allEqual;
136          prob.DisplayEvaluator = evaluatorDifferent;
137          problemComboBox.Items.Add(prob);
138          if (prob.Equals(selectedProblemItem)) problemComboBox.SelectedItem = prob;
139        }
140
141        if (problemComboBox.SelectedItem == null && problemComboBox.Items.Count > 0) {
142          problemComboBox.SelectedItem = problemComboBox.Items[0];
143          RecalculateTarget();
144        }
145
146      } finally { UpdateDataTableComboBox(); }
147    }
148
149    private void UpdateDataTableComboBox() {
150      var selectedItem = (string)dataTableComboBox.SelectedItem;
151      dataTableComboBox.Items.Clear();
152      dataTableComboBox.SelectedItem = null;
153
154      var dataTables = (from run in GetRunsFiltered()
155                        from result in run.Results
156                        where result.Value is IndexedDataTable<double>
157                        select result.Key).Distinct().OrderBy(x => x, new NaturalStringComparer());
158
159      foreach (var dt in dataTables) {
160        dataTableComboBox.Items.Add(dt);
161        if (selectedItem == dt) dataTableComboBox.SelectedItem = dt;
162      }
163      if (dataTableComboBox.SelectedItem == null && dataTableComboBox.Items.Count > 0)
164        dataTableComboBox.SelectedItem = dataTableComboBox.Items[0];
165    }
166
167    private IEnumerable<IRun> GetRunsFiltered() {
168      var result = Content.Where(x => x.Visible);
169
170      var selectedGroup = (string)groupComboBox.SelectedItem;
171      if (!string.IsNullOrEmpty(selectedGroup)) {
172        result = result.Where(x => x.Parameters.ContainsKey(selectedGroup));
173
174        var selectedGroupInstance = (string)groupInstanceComboBox.SelectedItem;
175        if (!string.IsNullOrEmpty(selectedGroupInstance))
176          result = result.Where(x => x.Parameters[selectedGroup].ToString() == selectedGroupInstance);
177      }
178      var selectedProblem = (ProblemDescription)problemComboBox.SelectedItem;
179      if (selectedProblem != null)
180        result = result.Where(x => selectedProblem.Match(x));
181
182      return result;
183    }
184
185    private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
186      if (suppressEvents) return;
187      suppressEvents = true;
188      try {
189        UpdateGroupInstanceComboBox();
190      } finally { suppressEvents = false; }
191
192      UpdateOptimalCutoff();
193    }
194
195    private void groupInstanceComboBox_SelectedIndexChanged(object sender, EventArgs e) {
196      if (suppressEvents) return;
197      suppressEvents = true;
198      try {
199        UpdateProblemCombobBox();
200      } finally { suppressEvents = false; }
201
202      UpdateOptimalCutoff();
203    }
204
205    private void problemComboBox_SelectedIndexChanged(object sender, EventArgs e) {
206      if (suppressEvents) return;
207      suppressEvents = true;
208      try {
209        UpdateDataTableComboBox();
210        RecalculateTarget();
211      } finally { suppressEvents = false; }
212
213      UpdateOptimalCutoff();
214    }
215
216    private void dataTableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
217      if (suppressEvents) return;
218
219      UpdateOptimalCutoff();
220    }
221
222    private void RecalculateTarget() {
223      var problemDesc = (ProblemDescription)problemComboBox.SelectedItem;
224      var dataTable = (string)dataTableComboBox.SelectedItem;
225      if (problemDesc == null || dataTable == null) return;
226      var target = CalculateBestTarget(problemDesc, dataTable, IsMaximization());
227      targetTextBox.Text = target.ToString(CultureInfo.CurrentCulture.NumberFormat);
228    }
229
230    private void targetTextBox_Validating(object sender, CancelEventArgs e) {
231      if (InvokeRequired)
232        if (suppressEvents) return;
233      double target;
234      if (!double.TryParse(targetTextBox.Text, out target)) {
235        e.Cancel = true;
236        errorProvider.SetError(targetTextBox, "Please enter a valid fitness value.");
237        return;
238      }
239      errorProvider.SetError(targetTextBox, null);
240
241      UpdateOptimalCutoff();
242    }
243
244    private void UpdateOptimalCutoff() {
245      double target;
246      if (!double.TryParse(targetTextBox.Text, NumberStyles.Float, CultureInfo.CurrentCulture.NumberFormat, out target)) return;
247
248      var resultName = (string)dataTableComboBox.SelectedItem;
249      if (resultName == null) return;
250
251      var pool = GetRunsFiltered()
252                  .Where(x => x.Results.ContainsKey(resultName) && x.Results[resultName] is IndexedDataTable<double>)
253                  .Select(x => (IndexedDataTable<double>)x.Results[resultName]).ToList();
254      if (pool.Count == 0) return;
255
256      var maximization = IsMaximization();
257
258      var data = pool.Select(x => x.Rows.First().Values.SkipWhile(y => !HasAchievedTarget(maximization, y, target)).FirstOrDefault() /* get the entry where the run reached the target */
259                                  ?? Tuple.Create(x.Rows.First().Values.Last().Item1, double.NaN) /* otherwise note the maximum effort */)
260                     .Where(x => !x.Equals(default(Tuple<double, double>))).OrderBy(x => x.Item1).ToList();
261      double prob;
262      var cutoff = CalculateOptimalCutoff(data, maximization, target, out prob);
263      optimalCutOffTextBox.Text = cutoff.ToString(CultureInfo.CurrentCulture.NumberFormat);
264      UpdateGraph(cutoff, prob, target, maximization);
265    }
266
267    private double CalculateOptimalCutoff(List<Tuple<double, double>> data, bool maximization, double target, out double bestProbability) {
268      bestProbability = 1.0;
269      var bestProbabilityEffort = 0.0;
270      var succ = 0;
271      foreach (var d in data) {
272        if (double.IsNaN(d.Item2)) continue;
273        if (HasAchievedTarget(maximization, d, target)) succ++;
274        // probability of having no successful run with effort d.Item1
275        var prob = (1.0 - succ / (double)data.Count);
276        // normalizing probability to effort 1 (assuming exponential convergence)
277        prob = Math.Pow(prob, 1.0 / d.Item1);
278        if (prob < bestProbability) {
279          bestProbability = prob;
280          bestProbabilityEffort = d.Item1;
281        }
282      }
283      return bestProbabilityEffort;
284    }
285
286    private bool HasAchievedTarget(bool maximization, Tuple<double, double> y, double target) {
287      return maximization ? y.Item2 >= target : y.Item2 <= target;
288    }
289
290    private void UpdateGraph(double cutoff, double bestProbability, double target, bool maximization) {
291      var table = (string)dataTableComboBox.SelectedItem;
292      var runs = GetRunsFiltered().Select(x => (IndexedDataTable<double>)x.Results[table]).ToList();
293      var evaluations = runs.SelectMany(x => x.Rows.First().Values.Select(y => y.Item1)).Distinct().OrderBy(x => x).ToList();
294      var totalRuns = evaluations.ToDictionary(x => x, x => 0);
295      var hits = evaluations.ToDictionary(x => x, x => 0.0);
296      foreach (var r in runs) {
297        var evalIter = evaluations.GetEnumerator();
298        evalIter.MoveNext();
299        var eff = evalIter.Current;
300        var evalIterAbort = false;
301        var targetFirstReached = double.MaxValue;
302        foreach (var v in r.Rows.First().Values) {
303          if (targetFirstReached == double.MaxValue && (maximization && v.Item2 >= target || !maximization && v.Item2 <= target))
304            targetFirstReached = v.Item1;
305          while (eff <= v.Item1) {
306            totalRuns[eff]++;
307            if (eff >= targetFirstReached) hits[eff]++;
308            if (evalIter.MoveNext())
309              eff = evalIter.Current;
310            else {
311              evalIterAbort = true;
312              break;
313            }
314          }
315        }
316        if (!evalIterAbort) {
317          do {
318            eff = evalIter.Current;
319            totalRuns[eff]++;
320            if (eff >= targetFirstReached) hits[eff]++;
321          } while (evalIter.MoveNext());
322        }
323      }
324
325      foreach (var e in evaluations) {
326        hits[e] /= totalRuns[e];
327      }
328
329      enhancedChart.SuspendRepaint();
330
331      var cutOffIdx = -1;
332      var series = enhancedChart.Series["rldSeries"];
333      series.Points.Clear();
334      foreach (var h in hits) {
335        series.Points.AddXY(h.Key, h.Value);
336        if (h.Key <= cutoff) cutOffIdx++;
337      }
338
339      var series2 = enhancedChart.Series["rldApproximationSeries"];
340      series2.Points.Clear();
341      var evalMax = evaluations.Max();
342      var steps = evalMax / 100.0;
343
344      var result = ExpectedRuntimeHelper.CalculateErt(GetRunsFiltered().ToList(), table, target, maximization);
345      var lambda = 1.0 / result.ExpectedRuntime;
346      foreach (var e in Enumerable.Range(0, 100)) {
347        var x = e * steps;
348        series2.Points.AddXY(x, Math.Max(0, 1.0 - Math.Exp(-lambda * x)));
349      }
350      var series3 = enhancedChart.Series["optimalSeries"];
351      series3.Points.Clear();
352      if (bestProbability <= 0) bestProbability = 1 - lambda;
353      foreach (var e in Enumerable.Range(0, 100)) {
354        var x = e * steps;
355        series3.Points.AddXY(x, Math.Max(0, 1.0 - Math.Pow(bestProbability, x)));
356      }
357
358      enhancedChart.Annotations.Clear();
359      if (cutOffIdx >= 0) {
360        var annotation = new VerticalLineAnnotation();
361        annotation.AnchorDataPoint = series.Points[cutOffIdx];
362        annotation.Height = series.Points[cutOffIdx].YValues[0] > enhancedChart.ChartAreas[series.ChartArea].AxisY.Maximum / 2.0 ? 10 : -10;
363        annotation.LineWidth = 2;
364        annotation.StartCap = LineAnchorCapStyle.Arrow;
365        enhancedChart.Annotations.Add(annotation);
366      }
367      enhancedChart.ResumeRepaint(true);
368    }
369
370    #region Helpers
371    // Determines if the RunCollection contains maximization or minimization runs
372    private bool IsMaximization() {
373      if (Content == null) return false;
374      foreach (var run in GetRunsFiltered().Where(x => x.Parameters.ContainsKey("Maximization"))) {
375        var maximization = run.Parameters["Maximization"] as BoolValue;
376        if (maximization == null) continue;
377        return maximization.Value;
378      }
379      var selectedTable = (string)dataTableComboBox.SelectedItem;
380      if (selectedTable != null) {
381        foreach (var run in GetRunsFiltered().Where(x => x.Results.ContainsKey(selectedTable))) {
382          var table = run.Results[selectedTable] as IndexedDataTable<double>;
383          if (table == null) continue;
384          var firstRowValues = table.Rows.First().Values;
385          if (firstRowValues.Count < 2) continue;
386          return firstRowValues[0].Item2 < firstRowValues[firstRowValues.Count - 1].Item2;
387        }
388      }
389      // assume minimization by default
390      return false;
391    }
392
393    private double CalculateBestTarget(ProblemDescription pd, string dataTableResult, bool maximization) {
394      var targets = (from r in Content
395                     where r.Visible && pd.Match(r)
396                     let target = r.Parameters.ContainsKey("BestKnownQuality")
397                                  && r.Parameters["BestKnownQuality"] is DoubleValue
398                       ? ((DoubleValue)r.Parameters["BestKnownQuality"]).Value
399                       : ((IndexedDataTable<double>)r.Results[dataTableResult]).Rows.First().Values.Last().Item2
400                     select target);
401      return maximization ? targets.Max() : targets.Min();
402    }
403    #endregion
404
405    private class ProblemDescription {
406
407      private ProblemDescription() {
408        ProblemType = string.Empty;
409        ProblemName = string.Empty;
410        Evaluator = string.Empty;
411        DisplayProblemType = false;
412        DisplayProblemName = false;
413        DisplayEvaluator = false;
414      }
415
416      public ProblemDescription(IRun run) {
417        ProblemType = GetStringValueOrEmpty(run, "Problem Type");
418        ProblemName = GetStringValueOrEmpty(run, "Problem Name");
419        Evaluator = GetStringValueOrEmpty(run, "Evaluator");
420        DisplayProblemType = !string.IsNullOrEmpty(ProblemType);
421        DisplayProblemName = !string.IsNullOrEmpty(ProblemName);
422        DisplayEvaluator = !string.IsNullOrEmpty(Evaluator);
423      }
424
425      public bool DisplayProblemType { get; set; }
426      public string ProblemType { get; set; }
427      public bool DisplayProblemName { get; set; }
428      public string ProblemName { get; set; }
429      public bool DisplayEvaluator { get; set; }
430      public string Evaluator { get; set; }
431
432      public bool Match(IRun run) {
433        return GetStringValueOrEmpty(run, "Problem Type") == ProblemType
434               && GetStringValueOrEmpty(run, "Problem Name") == ProblemName
435               && GetStringValueOrEmpty(run, "Evaluator") == Evaluator;
436      }
437
438      private string GetStringValueOrEmpty(IRun run, string key) {
439        return run.Parameters.ContainsKey(key) ? ((StringValue)run.Parameters[key]).Value : string.Empty;
440      }
441
442      public override bool Equals(object obj) {
443        var other = obj as RunCollectionIteratedSamplingView.ProblemDescription;
444        if (other == null) return false;
445        return ProblemType == other.ProblemType
446               && ProblemName == other.ProblemName
447               && Evaluator == other.Evaluator;
448      }
449
450      public override int GetHashCode() {
451        return ProblemType.GetHashCode() ^ ProblemName.GetHashCode() ^ Evaluator.GetHashCode();
452      }
453
454      public override string ToString() {
455        return string.Join("  --  ", new[] {
456          (DisplayProblemType ? ProblemType : string.Empty),
457          (DisplayProblemName ? ProblemName : string.Empty),
458          (DisplayEvaluator ? Evaluator : string.Empty) }.Where(x => !string.IsNullOrEmpty(x)));
459      }
460    }
461  }
462}
Note: See TracBrowser for help on using the repository browser.