Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBoxPlotView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBoxPlotView.cs	(revision 12956)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBoxPlotView.cs	(revision 13475)
@@ -248,6 +248,6 @@
         matrix[5, i] = seriesValues.StandardDeviation();
         matrix[6, i] = seriesValues.Variance();
-        matrix[7, i] = seriesValues.Percentile(0.25);
-        matrix[8, i] = seriesValues.Percentile(0.75);
+        matrix[7, i] = seriesValues.Quantile(0.25);
+        matrix[8, i] = seriesValues.Quantile(0.75);
       }
       statisticsMatrixView.Content = matrix;
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionChartAggregationView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionChartAggregationView.cs	(revision 12956)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionChartAggregationView.cs	(revision 13475)
@@ -80,28 +80,27 @@
         return;
       }
+      UpdateDataTableComboBox(); // will trigger AddRuns
+    }
+    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      if (suppressUpdates) return;
+      if (InvokeRequired) {
+        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved), sender, e);
+        return;
+      }
+      RemoveRuns(e.Items);
       UpdateDataTableComboBox();
       UpdateDataRowComboBox();
-      AddRuns(e.Items);
-    }
-    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      if (suppressUpdates) return;
-      if (InvokeRequired) {
-        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved), sender, e);
-        return;
-      }
+      RebuildCombinedDataTable();
+    }
+    private void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      if (suppressUpdates) return;
+      if (InvokeRequired) {
+        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset), sender, e);
+        return;
+      }
+      RemoveRuns(e.OldItems);
       UpdateDataTableComboBox();
       UpdateDataRowComboBox();
-      RemoveRuns(e.Items);
-    }
-    private void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      if (suppressUpdates) return;
-      if (InvokeRequired) {
-        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset), sender, e);
-        return;
-      }
-      UpdateDataTableComboBox();
-      UpdateDataRowComboBox();
-      RemoveRuns(e.OldItems);
-      AddRuns(e.Items);
+      RebuildCombinedDataTable();
     }
     private void Content_AlgorithmNameChanged(object sender, EventArgs e) {
@@ -117,7 +116,9 @@
       suppressUpdates = Content.UpdateOfRunsInProgress;
       if (!suppressUpdates) {
+        foreach (var run in runMapping)
+          DeregisterRunEvents(run.Key);
+        runMapping.Clear();
+        combinedDataTable.Rows.Clear();
         UpdateDataTableComboBox();
-        UpdateDataRowComboBox();
-        UpdateRuns(Content);
       }
     }
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.Designer.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.Designer.cs	(revision 13475)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.Designer.cs	(revision 13475)
@@ -0,0 +1,275 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Optimization.Views.RunCollectionViews {
+  partial class RunCollectionIteratedSamplingView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+      System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+      System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
+      System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
+      this.dataLabel = new System.Windows.Forms.Label();
+      this.dataTableComboBox = new System.Windows.Forms.ComboBox();
+      this.targetTextBox = new System.Windows.Forms.TextBox();
+      this.targetLabel = new System.Windows.Forms.Label();
+      this.enhancedChart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+      this.groupComboBox = new System.Windows.Forms.ComboBox();
+      this.groupLabel = new System.Windows.Forms.Label();
+      this.problemLabel = new System.Windows.Forms.Label();
+      this.problemComboBox = new System.Windows.Forms.ComboBox();
+      this.groupInstanceComboBox = new System.Windows.Forms.ComboBox();
+      this.optimalCutOffDescriptionLabel = new System.Windows.Forms.Label();
+      this.optimalCutOffTextBox = new System.Windows.Forms.TextBox();
+      this.label1 = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.enhancedChart)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // dataLabel
+      // 
+      this.dataLabel.AutoSize = true;
+      this.dataLabel.Location = new System.Drawing.Point(9, 60);
+      this.dataLabel.Name = "dataLabel";
+      this.dataLabel.Size = new System.Drawing.Size(60, 13);
+      this.dataLabel.TabIndex = 0;
+      this.dataLabel.Text = "DataTable:";
+      // 
+      // dataTableComboBox
+      // 
+      this.dataTableComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.dataTableComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.dataTableComboBox.FormattingEnabled = true;
+      this.dataTableComboBox.Location = new System.Drawing.Point(75, 57);
+      this.dataTableComboBox.Name = "dataTableComboBox";
+      this.dataTableComboBox.Size = new System.Drawing.Size(827, 21);
+      this.dataTableComboBox.TabIndex = 1;
+      this.dataTableComboBox.SelectedIndexChanged += new System.EventHandler(this.dataTableComboBox_SelectedIndexChanged);
+      // 
+      // targetTextBox
+      // 
+      this.targetTextBox.Location = new System.Drawing.Point(75, 84);
+      this.targetTextBox.Name = "targetTextBox";
+      this.targetTextBox.Size = new System.Drawing.Size(827, 20);
+      this.targetTextBox.TabIndex = 2;
+      this.targetTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.targetTextBox_Validating);
+      // 
+      // targetLabel
+      // 
+      this.targetLabel.AutoSize = true;
+      this.targetLabel.Location = new System.Drawing.Point(9, 87);
+      this.targetLabel.Name = "targetLabel";
+      this.targetLabel.Size = new System.Drawing.Size(41, 13);
+      this.targetLabel.TabIndex = 0;
+      this.targetLabel.Text = "Target:";
+      // 
+      // enhancedChart
+      // 
+      this.enhancedChart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      chartArea1.AxisY.Maximum = 1D;
+      chartArea1.AxisY.Minimum = 0D;
+      chartArea1.AxisY.Title = "Probability of achieving the target";
+      chartArea1.Name = "ChartArea1";
+      this.enhancedChart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Legend1";
+      this.enhancedChart.Legends.Add(legend1);
+      this.enhancedChart.Location = new System.Drawing.Point(3, 136);
+      this.enhancedChart.Name = "enhancedChart";
+      series1.BorderWidth = 2;
+      series1.ChartArea = "ChartArea1";
+      series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+      series1.Legend = "Legend1";
+      series1.LegendText = "Observed Run-Length Distribution";
+      series1.Name = "rldSeries";
+      series1.YValuesPerPoint = 2;
+      series2.BorderWidth = 2;
+      series2.ChartArea = "ChartArea1";
+      series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
+      series2.Legend = "Legend1";
+      series2.LegendText = "Exponential Approximation";
+      series2.Name = "rldApproximationSeries";
+      series3.BorderWidth = 2;
+      series3.ChartArea = "ChartArea1";
+      series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
+      series3.Legend = "Legend1";
+      series3.LegendText = "Optimal Cut-Off Approximation";
+      series3.Name = "optimalSeries";
+      this.enhancedChart.Series.Add(series1);
+      this.enhancedChart.Series.Add(series2);
+      this.enhancedChart.Series.Add(series3);
+      this.enhancedChart.Size = new System.Drawing.Size(899, 526);
+      this.enhancedChart.TabIndex = 3;
+      // 
+      // errorProvider
+      // 
+      this.errorProvider.ContainerControl = this;
+      // 
+      // groupComboBox
+      // 
+      this.groupComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.groupComboBox.FormattingEnabled = true;
+      this.groupComboBox.Location = new System.Drawing.Point(75, 3);
+      this.groupComboBox.Name = "groupComboBox";
+      this.groupComboBox.Size = new System.Drawing.Size(379, 21);
+      this.groupComboBox.TabIndex = 5;
+      this.groupComboBox.SelectedIndexChanged += new System.EventHandler(this.groupComboBox_SelectedIndexChanged);
+      // 
+      // groupLabel
+      // 
+      this.groupLabel.AutoSize = true;
+      this.groupLabel.Location = new System.Drawing.Point(9, 6);
+      this.groupLabel.Name = "groupLabel";
+      this.groupLabel.Size = new System.Drawing.Size(39, 13);
+      this.groupLabel.TabIndex = 4;
+      this.groupLabel.Text = "Group:";
+      // 
+      // problemLabel
+      // 
+      this.problemLabel.AutoSize = true;
+      this.problemLabel.Location = new System.Drawing.Point(9, 33);
+      this.problemLabel.Name = "problemLabel";
+      this.problemLabel.Size = new System.Drawing.Size(48, 13);
+      this.problemLabel.TabIndex = 6;
+      this.problemLabel.Text = "Problem:";
+      // 
+      // problemComboBox
+      // 
+      this.problemComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.problemComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.problemComboBox.FormattingEnabled = true;
+      this.problemComboBox.Location = new System.Drawing.Point(75, 30);
+      this.problemComboBox.Name = "problemComboBox";
+      this.problemComboBox.Size = new System.Drawing.Size(827, 21);
+      this.problemComboBox.TabIndex = 7;
+      this.problemComboBox.SelectedIndexChanged += new System.EventHandler(this.problemComboBox_SelectedIndexChanged);
+      // 
+      // groupInstanceComboBox
+      // 
+      this.groupInstanceComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.groupInstanceComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.groupInstanceComboBox.FormattingEnabled = true;
+      this.groupInstanceComboBox.Location = new System.Drawing.Point(460, 3);
+      this.groupInstanceComboBox.Name = "groupInstanceComboBox";
+      this.groupInstanceComboBox.Size = new System.Drawing.Size(442, 21);
+      this.groupInstanceComboBox.TabIndex = 5;
+      this.groupInstanceComboBox.SelectedIndexChanged += new System.EventHandler(this.groupInstanceComboBox_SelectedIndexChanged);
+      // 
+      // optimalCutOffDescriptionLabel
+      // 
+      this.optimalCutOffDescriptionLabel.AutoSize = true;
+      this.optimalCutOffDescriptionLabel.Location = new System.Drawing.Point(9, 113);
+      this.optimalCutOffDescriptionLabel.Name = "optimalCutOffDescriptionLabel";
+      this.optimalCutOffDescriptionLabel.Size = new System.Drawing.Size(308, 13);
+      this.optimalCutOffDescriptionLabel.TabIndex = 8;
+      this.optimalCutOffDescriptionLabel.Text = "The optimal cut-off point for this group on this problem would be:";
+      // 
+      // optimalCutOffTextBox
+      // 
+      this.optimalCutOffTextBox.Location = new System.Drawing.Point(323, 110);
+      this.optimalCutOffTextBox.Name = "optimalCutOffTextBox";
+      this.optimalCutOffTextBox.ReadOnly = true;
+      this.optimalCutOffTextBox.Size = new System.Drawing.Size(131, 20);
+      this.optimalCutOffTextBox.TabIndex = 9;
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(460, 113);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(180, 13);
+      this.label1.TabIndex = 8;
+      this.label1.Text = "(assuming exponential convergence)";
+      // 
+      // RunCollectionIteratedSamplingView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.optimalCutOffTextBox);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.optimalCutOffDescriptionLabel);
+      this.Controls.Add(this.groupInstanceComboBox);
+      this.Controls.Add(this.groupComboBox);
+      this.Controls.Add(this.groupLabel);
+      this.Controls.Add(this.problemLabel);
+      this.Controls.Add(this.problemComboBox);
+      this.Controls.Add(this.enhancedChart);
+      this.Controls.Add(this.targetTextBox);
+      this.Controls.Add(this.dataTableComboBox);
+      this.Controls.Add(this.targetLabel);
+      this.Controls.Add(this.dataLabel);
+      this.Name = "RunCollectionIteratedSamplingView";
+      this.Size = new System.Drawing.Size(905, 665);
+      ((System.ComponentModel.ISupportInitialize)(this.enhancedChart)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label dataLabel;
+    private System.Windows.Forms.ComboBox dataTableComboBox;
+    private System.Windows.Forms.TextBox targetTextBox;
+    private System.Windows.Forms.Label targetLabel;
+    private Visualization.ChartControlsExtensions.EnhancedChart enhancedChart;
+    private System.Windows.Forms.ErrorProvider errorProvider;
+    private System.Windows.Forms.ComboBox groupComboBox;
+    private System.Windows.Forms.Label groupLabel;
+    private System.Windows.Forms.Label problemLabel;
+    private System.Windows.Forms.ComboBox problemComboBox;
+    private System.Windows.Forms.ComboBox groupInstanceComboBox;
+    private System.Windows.Forms.TextBox optimalCutOffTextBox;
+    private System.Windows.Forms.Label optimalCutOffDescriptionLabel;
+    private System.Windows.Forms.Label label1;
+  }
+}
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.cs	(revision 13475)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.cs	(revision 13475)
@@ -0,0 +1,461 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.MainForm.WindowsForms;
+using HeuristicLab.MainForm;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization.Views.RunCollectionViews {
+  [View("Run-length Cut-off Estimation View")]
+  [Content(typeof(RunCollection), IsDefaultView = false)]
+  public sealed partial class RunCollectionIteratedSamplingView : AsynchronousContentView {
+    private bool suppressEvents;
+
+    public new RunCollection Content {
+      get { return (RunCollection)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public RunCollectionIteratedSamplingView() {
+      InitializeComponent();
+    }
+
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      suppressEvents = true;
+      try {
+        UpdateGroupComboBox();
+        RecalculateTarget();
+      } finally { suppressEvents = false; }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      groupComboBox.Enabled = Content != null;
+      groupInstanceComboBox.Enabled = Content != null && groupInstanceComboBox.Items.Count > 1;
+      problemComboBox.Enabled = Content != null && problemComboBox.Items.Count > 1;
+      dataTableComboBox.Enabled = Content != null && dataTableComboBox.Items.Count > 1;
+    }
+
+    private void UpdateGroupComboBox() {
+      try {
+
+        var selectedGroupItem = (string)groupComboBox.SelectedItem;
+        groupComboBox.Items.Clear();
+        groupComboBox.SelectedItem = null;
+
+        var paramNames = Content.ParameterNames.OrderBy(x => x, new NaturalStringComparer());
+        foreach (var name in paramNames) {
+          groupComboBox.Items.Add(name);
+          if (selectedGroupItem == name) groupComboBox.SelectedItem = name;
+        }
+        if (groupComboBox.SelectedItem == null && groupComboBox.Items.Count > 0)
+          groupComboBox.SelectedItem = groupComboBox.Items[0];
+
+      } finally { UpdateGroupInstanceComboBox(); }
+    }
+
+    private void UpdateGroupInstanceComboBox() {
+      try {
+
+        var selectedGroupInstanceItem = (string)groupInstanceComboBox.SelectedItem;
+        groupInstanceComboBox.Items.Clear();
+        groupInstanceComboBox.SelectedItem = null;
+
+        var selectedGroupItem = (string)groupComboBox.SelectedItem;
+        if (selectedGroupItem == null) return;
+
+        var paramValues = GetRunsFiltered()
+                              .Select(x => x.Parameters[selectedGroupItem].ToString())
+                              .Distinct()
+                              .OrderBy(x => x, new NaturalStringComparer());
+        foreach (var value in paramValues) {
+          groupInstanceComboBox.Items.Add(value);
+          if (selectedGroupInstanceItem == value) groupInstanceComboBox.SelectedItem = value;
+        }
+        if (groupInstanceComboBox.SelectedItem == null && groupInstanceComboBox.Items.Count > 0)
+          groupInstanceComboBox.SelectedItem = groupInstanceComboBox.Items[0];
+
+      } finally { UpdateProblemCombobBox(); }
+    }
+
+    private void UpdateProblemCombobBox() {
+      try {
+
+        var selectedProblemItem = (ProblemDescription)problemComboBox.SelectedItem;
+        problemComboBox.Items.Clear();
+        problemComboBox.SelectedItem = null;
+
+        var problems = new HashSet<ProblemDescription>();
+        foreach (var run in GetRunsFiltered()) {
+          problems.Add(new ProblemDescription(run));
+        }
+
+        var problemTypesDifferent = problems.Select(x => x.ProblemType).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
+        var problemNamesDifferent = problems.Select(x => x.ProblemName).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
+        var evaluatorDifferent = problems.Select(x => x.Evaluator).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
+        var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent;
+
+        foreach (var prob in problems.OrderBy(x => x.ToString()).ToList()) {
+          prob.DisplayProblemType = problemTypesDifferent;
+          prob.DisplayProblemName = problemNamesDifferent || allEqual;
+          prob.DisplayEvaluator = evaluatorDifferent;
+          problemComboBox.Items.Add(prob);
+          if (prob.Equals(selectedProblemItem)) problemComboBox.SelectedItem = prob;
+        }
+
+        if (problemComboBox.SelectedItem == null && problemComboBox.Items.Count > 0) {
+          problemComboBox.SelectedItem = problemComboBox.Items[0];
+          RecalculateTarget();
+        }
+
+      } finally { UpdateDataTableComboBox(); }
+    }
+
+    private void UpdateDataTableComboBox() {
+      var selectedItem = (string)dataTableComboBox.SelectedItem;
+      dataTableComboBox.Items.Clear();
+      dataTableComboBox.SelectedItem = null;
+
+      var dataTables = (from run in GetRunsFiltered()
+                        from result in run.Results
+                        where result.Value is IndexedDataTable<double>
+                        select result.Key).Distinct().OrderBy(x => x, new NaturalStringComparer());
+
+      foreach (var dt in dataTables) {
+        dataTableComboBox.Items.Add(dt);
+        if (selectedItem == dt) dataTableComboBox.SelectedItem = dt;
+      }
+      if (dataTableComboBox.SelectedItem == null && dataTableComboBox.Items.Count > 0)
+        dataTableComboBox.SelectedItem = dataTableComboBox.Items[0];
+    }
+
+    private IEnumerable<IRun> GetRunsFiltered() {
+      var result = Content.Where(x => x.Visible);
+
+      var selectedGroup = (string)groupComboBox.SelectedItem;
+      if (!string.IsNullOrEmpty(selectedGroup)) {
+        result = result.Where(x => x.Parameters.ContainsKey(selectedGroup));
+
+        var selectedGroupInstance = (string)groupInstanceComboBox.SelectedItem;
+        if (!string.IsNullOrEmpty(selectedGroupInstance))
+          result = result.Where(x => x.Parameters[selectedGroup].ToString() == selectedGroupInstance);
+      }
+      var selectedProblem = (ProblemDescription)problemComboBox.SelectedItem;
+      if (selectedProblem != null)
+        result = result.Where(x => selectedProblem.Match(x));
+
+      return result;
+    }
+
+    private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      if (suppressEvents) return;
+      suppressEvents = true;
+      try {
+        UpdateGroupInstanceComboBox();
+      } finally { suppressEvents = false; }
+
+      UpdateOptimalCutoff();
+    }
+
+    private void groupInstanceComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      if (suppressEvents) return;
+      suppressEvents = true;
+      try {
+        UpdateProblemCombobBox();
+      } finally { suppressEvents = false; }
+
+      UpdateOptimalCutoff();
+    }
+
+    private void problemComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      if (suppressEvents) return;
+      suppressEvents = true;
+      try {
+        UpdateDataTableComboBox();
+        RecalculateTarget();
+      } finally { suppressEvents = false; }
+
+      UpdateOptimalCutoff();
+    }
+
+    private void dataTableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      if (suppressEvents) return;
+
+      UpdateOptimalCutoff();
+    }
+
+    private void RecalculateTarget() {
+      var problemDesc = (ProblemDescription)problemComboBox.SelectedItem;
+      var dataTable = (string)dataTableComboBox.SelectedItem;
+      if (problemDesc == null || dataTable == null) return;
+      var target = CalculateBestTarget(problemDesc, dataTable, IsMaximization());
+      targetTextBox.Text = target.ToString(CultureInfo.CurrentCulture.NumberFormat);
+    }
+
+    private void targetTextBox_Validating(object sender, CancelEventArgs e) {
+      if (InvokeRequired)
+        if (suppressEvents) return;
+      double target;
+      if (!double.TryParse(targetTextBox.Text, out target)) {
+        e.Cancel = true;
+        errorProvider.SetError(targetTextBox, "Please enter a valid fitness value.");
+        return;
+      }
+      errorProvider.SetError(targetTextBox, null);
+
+      UpdateOptimalCutoff();
+    }
+
+    private void UpdateOptimalCutoff() {
+      double target;
+      if (!double.TryParse(targetTextBox.Text, NumberStyles.Float, CultureInfo.CurrentCulture.NumberFormat, out target)) return;
+
+      var resultName = (string)dataTableComboBox.SelectedItem;
+      if (resultName == null) return;
+
+      var pool = GetRunsFiltered()
+                  .Where(x => x.Results.ContainsKey(resultName) && x.Results[resultName] is IndexedDataTable<double>)
+                  .Select(x => (IndexedDataTable<double>)x.Results[resultName]).ToList();
+      if (pool.Count == 0) return;
+
+      var maximization = IsMaximization();
+
+      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 */
+                                  ?? Tuple.Create(x.Rows.First().Values.Last().Item1, double.NaN) /* otherwise note the maximum effort */)
+                     .Where(x => !x.Equals(default(Tuple<double, double>))).OrderBy(x => x.Item1).ToList();
+      double prob;
+      var cutoff = CalculateOptimalCutoff(data, maximization, target, out prob);
+      optimalCutOffTextBox.Text = cutoff.ToString(CultureInfo.CurrentCulture.NumberFormat);
+      UpdateGraph(cutoff, prob, target, maximization);
+    }
+
+    private double CalculateOptimalCutoff(List<Tuple<double, double>> data, bool maximization, double target, out double bestProbability) {
+      bestProbability = 1.0;
+      var bestProbabilityEffort = 0.0;
+      foreach (var d in data) {
+        if (double.IsNaN(d.Item2)) continue;
+        double succ = 0.0, unsucc = 0.0;
+        foreach (var e in data) {
+          if (e.Item1 <= d.Item1 && HasAchievedTarget(maximization, e, target)) succ++;
+          else if (e.Item1 >= d.Item1) unsucc++;
+        }
+        // probability of having no successful run with effort d.Item1
+        var prob = (1.0 - succ / (succ + unsucc));
+        // normalizing probability to effort 1 (assuming exponential convergence)
+        prob = Math.Pow(prob, 1.0 / d.Item1);
+        if (prob < bestProbability) {
+          bestProbability = prob;
+          bestProbabilityEffort = d.Item1;
+        }
+      }
+      return bestProbabilityEffort;
+    }
+
+    private bool HasAchievedTarget(bool maximization, Tuple<double, double> y, double target) {
+      return maximization ? y.Item2 >= target : y.Item2 <= target;
+    }
+
+    private void UpdateGraph(double cutoff, double bestProbability, double target, bool maximization) {
+      var table = (string)dataTableComboBox.SelectedItem;
+      var result = ExpectedRuntimeHelper.CalculateErt(GetRunsFiltered().ToList(), table, target, maximization);
+      var lambda = 1.0 / result.ExpectedRuntime;
+      var runs = GetRunsFiltered().Select(x => (IndexedDataTable<double>)x.Results[table]).ToList();
+      var evaluations = runs.SelectMany(x => x.Rows.First().Values.Select(y => y.Item1)).Distinct().OrderBy(x => x).ToList();
+      var totalRuns = evaluations.ToDictionary(x => x, x => 0);
+      var hits = evaluations.ToDictionary(x => x, x => 0.0);
+      foreach (var r in runs) {
+        var evalIter = evaluations.GetEnumerator();
+        evalIter.MoveNext();
+        var eff = evalIter.Current;
+        var evalIterAbort = false;
+        var targetFirstReached = double.MaxValue;
+        foreach (var v in r.Rows.First().Values) {
+          if (targetFirstReached == double.MaxValue && (maximization && v.Item2 >= target || !maximization && v.Item2 <= target))
+            targetFirstReached = v.Item1;
+          while (eff <= v.Item1) {
+            totalRuns[eff]++;
+            if (eff >= targetFirstReached) hits[eff]++;
+            if (evalIter.MoveNext())
+              eff = evalIter.Current;
+            else {
+              evalIterAbort = true;
+              break;
+            }
+          }
+        }
+        if (!evalIterAbort) {
+          do {
+            eff = evalIter.Current;
+            totalRuns[eff]++;
+            if (eff >= targetFirstReached) hits[eff]++;
+          } while (evalIter.MoveNext());
+        }
+      }
+
+      foreach (var e in evaluations) {
+        hits[e] /= totalRuns[e];
+      }
+
+      var minimum = hits.First(x => x.Value > 0).Key;
+
+      enhancedChart.SuspendRepaint();
+
+      var cutOffIdx = -1;
+      var series = enhancedChart.Series["rldSeries"];
+      series.Points.Clear();
+      foreach (var h in hits) {
+        series.Points.AddXY(h.Key, h.Value);
+        if (h.Key <= cutoff) cutOffIdx++;
+      }
+
+      var series2 = enhancedChart.Series["rldApproximationSeries"];
+      series2.Points.Clear();
+      foreach (var e in Enumerable.Range(0, (int)Math.Ceiling(evaluations.Max()))) {
+        series2.Points.AddXY(e, Math.Max(0, 1.0 - Math.Exp(-lambda * (e - minimum))));
+      }
+      var series3 = enhancedChart.Series["optimalSeries"];
+      series3.Points.Clear();
+      lambda = -Math.Log(bestProbability);
+      foreach (var e in Enumerable.Range(0, (int)Math.Ceiling(evaluations.Max())))
+        series3.Points.AddXY(e, Math.Max(0, 1.0 - Math.Exp(-lambda * (e - minimum))));
+
+      enhancedChart.Annotations.Clear();
+      if (cutOffIdx >= 0) {
+        var annotation = new VerticalLineAnnotation();
+        annotation.AnchorDataPoint = series.Points[cutOffIdx];
+        annotation.Height = -20;
+        annotation.LineWidth = 2;
+        annotation.StartCap = LineAnchorCapStyle.Arrow;
+        enhancedChart.Annotations.Add(annotation);
+      }
+      enhancedChart.ResumeRepaint(true);
+    }
+
+    #region Helpers
+    // Determines if the RunCollection contains maximization or minimization runs
+    private bool IsMaximization() {
+      if (Content == null) return false;
+      foreach (var run in GetRunsFiltered().Where(x => x.Parameters.ContainsKey("Maximization"))) {
+        var maximization = run.Parameters["Maximization"] as BoolValue;
+        if (maximization == null) continue;
+        return maximization.Value;
+      }
+      var selectedTable = (string)dataTableComboBox.SelectedItem;
+      if (selectedTable != null) {
+        foreach (var run in GetRunsFiltered().Where(x => x.Results.ContainsKey(selectedTable))) {
+          var table = run.Results[selectedTable] as IndexedDataTable<double>;
+          if (table == null) continue;
+          var firstRowValues = table.Rows.First().Values;
+          if (firstRowValues.Count < 2) continue;
+          return firstRowValues[0].Item2 < firstRowValues[firstRowValues.Count - 1].Item2;
+        }
+      }
+      // assume minimization by default
+      return false;
+    }
+
+    private double CalculateBestTarget(ProblemDescription pd, string dataTableResult, bool maximization) {
+      var targets = (from r in Content
+                     where r.Visible && pd.Match(r)
+                     let target = r.Parameters.ContainsKey("BestKnownQuality")
+                                  && r.Parameters["BestKnownQuality"] is DoubleValue
+                       ? ((DoubleValue)r.Parameters["BestKnownQuality"]).Value
+                       : ((IndexedDataTable<double>)r.Results[dataTableResult]).Rows.First().Values.Last().Item2
+                     select target);
+      return maximization ? targets.Max() : targets.Min();
+    }
+    #endregion
+
+    private class ProblemDescription {
+
+      private ProblemDescription() {
+        ProblemType = string.Empty;
+        ProblemName = string.Empty;
+        Evaluator = string.Empty;
+        DisplayProblemType = false;
+        DisplayProblemName = false;
+        DisplayEvaluator = false;
+      }
+
+      public ProblemDescription(IRun run) {
+        ProblemType = GetStringValueOrEmpty(run, "Problem Type");
+        ProblemName = GetStringValueOrEmpty(run, "Problem Name");
+        Evaluator = GetStringValueOrEmpty(run, "Evaluator");
+        DisplayProblemType = !string.IsNullOrEmpty(ProblemType);
+        DisplayProblemName = !string.IsNullOrEmpty(ProblemName);
+        DisplayEvaluator = !string.IsNullOrEmpty(Evaluator);
+      }
+
+      public bool DisplayProblemType { get; set; }
+      public string ProblemType { get; set; }
+      public bool DisplayProblemName { get; set; }
+      public string ProblemName { get; set; }
+      public bool DisplayEvaluator { get; set; }
+      public string Evaluator { get; set; }
+
+      public bool Match(IRun run) {
+        return GetStringValueOrEmpty(run, "Problem Type") == ProblemType
+               && GetStringValueOrEmpty(run, "Problem Name") == ProblemName
+               && GetStringValueOrEmpty(run, "Evaluator") == Evaluator;
+      }
+
+      private string GetStringValueOrEmpty(IRun run, string key) {
+        return run.Parameters.ContainsKey(key) ? ((StringValue)run.Parameters[key]).Value : string.Empty;
+      }
+
+      public override bool Equals(object obj) {
+        var other = obj as RunCollectionIteratedSamplingView.ProblemDescription;
+        if (other == null) return false;
+        return ProblemType == other.ProblemType
+               && ProblemName == other.ProblemName
+               && Evaluator == other.Evaluator;
+      }
+
+      public override int GetHashCode() {
+        return ProblemType.GetHashCode() ^ ProblemName.GetHashCode() ^ Evaluator.GetHashCode();
+      }
+
+      public override string ToString() {
+        return string.Join("  --  ", new[] {
+          (DisplayProblemType ? ProblemType : string.Empty),
+          (DisplayProblemName ? ProblemName : string.Empty),
+          (DisplayEvaluator ? Evaluator : string.Empty) }.Where(x => !string.IsNullOrEmpty(x)));
+      }
+    }
+  }
+}
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.resx
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.resx	(revision 13475)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionIteratedSamplingView.resx	(revision 13475)
@@ -0,0 +1,123 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 12956)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 13475)
@@ -463,6 +463,4 @@
       ertTableView.DataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
     }
-
-
     #endregion
 
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionTableView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionTableView.cs	(revision 12956)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionTableView.cs	(revision 13475)
@@ -25,4 +25,5 @@
 using System.Linq;
 using System.Windows.Forms;
+using HeuristicLab.Collections;
 using HeuristicLab.Core;
 using HeuristicLab.Data.Views;
@@ -122,14 +123,38 @@
 
     protected override void UpdateColumnHeaders() {
-      HashSet<string> visibleColumnNames = new HashSet<string>(dataGridView.Columns.OfType<DataGridViewColumn>()
-       .Where(c => c.Visible && !string.IsNullOrEmpty(c.HeaderText)).Select(c => c.HeaderText));
-
+      string[] colNames = base.Content.ColumnNames.ToArray();
+      int colCount = colNames.Length;
       for (int i = 0; i < dataGridView.ColumnCount; i++) {
-        if (i < base.Content.ColumnNames.Count())
-          dataGridView.Columns[i].HeaderText = base.Content.ColumnNames.ElementAt(i);
+        if (i < colCount)
+          dataGridView.Columns[i].HeaderText = colNames[i];
         else
           dataGridView.Columns[i].HeaderText = "Column " + (i + 1);
+      }
+
+      HashSet<string> visibleColumnNames = new HashSet<string>(
+        dataGridView.Columns.OfType<DataGridViewColumn>()
+       .Where(c => c.Visible)
+       .Where(c => !string.IsNullOrEmpty(c.HeaderText))
+       .Where(c => !IsConstant(c.HeaderText))
+       .Select(c => c.HeaderText));
+
+      for (int i = 0; i < dataGridView.ColumnCount; i++) {
         dataGridView.Columns[i].Visible = visibleColumnNames.Count == 0 || visibleColumnNames.Contains(dataGridView.Columns[i].HeaderText);
       }
+    }
+
+    // returns true when all values in the column are the same (missing values are included in the count)
+    private bool IsConstant(string columnName) {
+      Func<IRun, string, string> GetStringValue = (IRun r, string colName) => {
+        // also include missing values in the count
+        IItem v = null;
+        if (r.Parameters.TryGetValue(colName, out v)) return v.ToString();
+        if (r.Results.TryGetValue(colName, out v)) return v.ToString();
+        return string.Empty;
+      };
+
+      var firstRun = Content.First();
+      string firstValue = GetStringValue(firstRun, columnName);
+      return Content.Skip(1).All(run => firstValue == GetStringValue(run, columnName));
     }
 
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionView.cs	(revision 12956)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionView.cs	(revision 13475)
@@ -389,8 +389,11 @@
         return;
       ReadOnly = true;
+
       try {
+        RunCollection.UpdateOfRunsInProgress = true;
         RunCollection.Modify();
       } finally {
         ReadOnly = false;
+        RunCollection.UpdateOfRunsInProgress = false;
       }
     }
