Index: /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs	(revision 12840)
+++ /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs	(revision 12841)
@@ -64,10 +64,12 @@
       this.byTargetViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       this.byCostTabPage = new System.Windows.Forms.TabPage();
+      this.budgetLogScalingCheckBox = new System.Windows.Forms.CheckBox();
       this.eachOrAllBudgetsCheckBox = new System.Windows.Forms.CheckBox();
       this.generateBudgetsButton = new System.Windows.Forms.Button();
       this.byCostViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       this.byTableTabPage = new System.Windows.Forms.TabPage();
-      this.dataGridView1 = new System.Windows.Forms.DataGridView();
-      this.budgetLogScalingCheckBox = new System.Windows.Forms.CheckBox();
+      this.ertViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.problemComboBox = new System.Windows.Forms.ComboBox();
+      this.problemLabel = new System.Windows.Forms.Label();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
@@ -75,5 +77,4 @@
       this.byCostTabPage.SuspendLayout();
       this.byTableTabPage.SuspendLayout();
-      ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
       this.SuspendLayout();
       // 
@@ -84,8 +85,8 @@
       this.dataTableComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.dataTableComboBox.FormattingEnabled = true;
-      this.dataTableComboBox.Location = new System.Drawing.Point(69, 30);
+      this.dataTableComboBox.Location = new System.Drawing.Point(69, 57);
       this.dataTableComboBox.Name = "dataTableComboBox";
       this.dataTableComboBox.Size = new System.Drawing.Size(582, 21);
-      this.dataTableComboBox.TabIndex = 0;
+      this.dataTableComboBox.TabIndex = 5;
       this.dataTableComboBox.SelectedIndexChanged += new System.EventHandler(this.dataTableComboBox_SelectedIndexChanged);
       // 
@@ -93,8 +94,8 @@
       // 
       this.dataTableLabel.AutoSize = true;
-      this.dataTableLabel.Location = new System.Drawing.Point(3, 33);
+      this.dataTableLabel.Location = new System.Drawing.Point(3, 60);
       this.dataTableLabel.Name = "dataTableLabel";
       this.dataTableLabel.Size = new System.Drawing.Size(60, 13);
-      this.dataTableLabel.TabIndex = 1;
+      this.dataTableLabel.TabIndex = 4;
       this.dataTableLabel.Text = "DataTable:";
       // 
@@ -105,5 +106,5 @@
       this.groupLabel.Name = "groupLabel";
       this.groupLabel.Size = new System.Drawing.Size(39, 13);
-      this.groupLabel.TabIndex = 3;
+      this.groupLabel.TabIndex = 0;
       this.groupLabel.Text = "Group:";
       // 
@@ -117,5 +118,5 @@
       this.groupComboBox.Name = "groupComboBox";
       this.groupComboBox.Size = new System.Drawing.Size(582, 21);
-      this.groupComboBox.TabIndex = 4;
+      this.groupComboBox.TabIndex = 1;
       this.groupComboBox.SelectedIndexChanged += new System.EventHandler(this.groupComboBox_SelectedIndexChanged);
       // 
@@ -124,8 +125,8 @@
       this.targetLogScalingCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
       this.targetLogScalingCheckBox.AutoSize = true;
-      this.targetLogScalingCheckBox.Location = new System.Drawing.Point(9, 391);
+      this.targetLogScalingCheckBox.Location = new System.Drawing.Point(9, 364);
       this.targetLogScalingCheckBox.Name = "targetLogScalingCheckBox";
       this.targetLogScalingCheckBox.Size = new System.Drawing.Size(112, 17);
-      this.targetLogScalingCheckBox.TabIndex = 5;
+      this.targetLogScalingCheckBox.TabIndex = 6;
       this.targetLogScalingCheckBox.Text = "logarithmic scaling";
       this.targetLogScalingCheckBox.UseVisualStyleBackColor = true;
@@ -139,5 +140,5 @@
       this.targetsTextBox.Name = "targetsTextBox";
       this.targetsTextBox.Size = new System.Drawing.Size(320, 20);
-      this.targetsTextBox.TabIndex = 6;
+      this.targetsTextBox.TabIndex = 1;
       this.toolTip.SetToolTip(this.targetsTextBox, "The order of the targets is important, first to-hit targets\r\nshould be given firs" +
         "t. The sequence should be monotonous.\r\n\r\nTargets should be separated by semicolo" +
@@ -151,5 +152,5 @@
       this.targetsLabel.Name = "targetsLabel";
       this.targetsLabel.Size = new System.Drawing.Size(46, 13);
-      this.targetsLabel.TabIndex = 1;
+      this.targetsLabel.TabIndex = 0;
       this.targetsLabel.Text = "Targets:";
       // 
@@ -164,5 +165,5 @@
       this.addTargetsAsResultButton.Name = "addTargetsAsResultButton";
       this.addTargetsAsResultButton.Size = new System.Drawing.Size(89, 23);
-      this.addTargetsAsResultButton.TabIndex = 7;
+      this.addTargetsAsResultButton.TabIndex = 4;
       this.addTargetsAsResultButton.Text = "Add as Result";
       this.addTargetsAsResultButton.UseVisualStyleBackColor = true;
@@ -175,5 +176,5 @@
       this.generateTargetsButton.Name = "generateTargetsButton";
       this.generateTargetsButton.Size = new System.Drawing.Size(89, 23);
-      this.generateTargetsButton.TabIndex = 7;
+      this.generateTargetsButton.TabIndex = 3;
       this.generateTargetsButton.Text = "Generate...";
       this.generateTargetsButton.UseVisualStyleBackColor = true;
@@ -217,5 +218,5 @@
       this.eachOrAllTargetCheckBox.Name = "eachOrAllTargetCheckBox";
       this.eachOrAllTargetCheckBox.Size = new System.Drawing.Size(36, 17);
-      this.eachOrAllTargetCheckBox.TabIndex = 8;
+      this.eachOrAllTargetCheckBox.TabIndex = 2;
       this.eachOrAllTargetCheckBox.Text = "all";
       this.eachOrAllTargetCheckBox.UseVisualStyleBackColor = true;
@@ -230,9 +231,9 @@
       this.tabControl.Controls.Add(this.byCostTabPage);
       this.tabControl.Controls.Add(this.byTableTabPage);
-      this.tabControl.Location = new System.Drawing.Point(0, 57);
+      this.tabControl.Location = new System.Drawing.Point(0, 84);
       this.tabControl.Name = "tabControl";
       this.tabControl.SelectedIndex = 0;
-      this.tabControl.Size = new System.Drawing.Size(654, 440);
-      this.tabControl.TabIndex = 9;
+      this.tabControl.Size = new System.Drawing.Size(654, 413);
+      this.tabControl.TabIndex = 6;
       // 
       // byTargetTabPage
@@ -248,5 +249,5 @@
       this.byTargetTabPage.Name = "byTargetTabPage";
       this.byTargetTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.byTargetTabPage.Size = new System.Drawing.Size(646, 414);
+      this.byTargetTabPage.Size = new System.Drawing.Size(646, 387);
       this.byTargetTabPage.TabIndex = 0;
       this.byTargetTabPage.Text = "Performance by Target";
@@ -264,6 +265,6 @@
       this.byTargetViewHost.Name = "byTargetViewHost";
       this.byTargetViewHost.ReadOnly = false;
-      this.byTargetViewHost.Size = new System.Drawing.Size(640, 351);
-      this.byTargetViewHost.TabIndex = 9;
+      this.byTargetViewHost.Size = new System.Drawing.Size(640, 324);
+      this.byTargetViewHost.TabIndex = 5;
       this.byTargetViewHost.ViewsLabelVisible = true;
       this.byTargetViewHost.ViewType = null;
@@ -281,8 +282,20 @@
       this.byCostTabPage.Name = "byCostTabPage";
       this.byCostTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.byCostTabPage.Size = new System.Drawing.Size(646, 414);
+      this.byCostTabPage.Size = new System.Drawing.Size(646, 387);
       this.byCostTabPage.TabIndex = 1;
       this.byCostTabPage.Text = "Performance by Cost";
       this.byCostTabPage.UseVisualStyleBackColor = true;
+      // 
+      // budgetLogScalingCheckBox
+      // 
+      this.budgetLogScalingCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+      this.budgetLogScalingCheckBox.AutoSize = true;
+      this.budgetLogScalingCheckBox.Location = new System.Drawing.Point(9, 364);
+      this.budgetLogScalingCheckBox.Name = "budgetLogScalingCheckBox";
+      this.budgetLogScalingCheckBox.Size = new System.Drawing.Size(112, 17);
+      this.budgetLogScalingCheckBox.TabIndex = 11;
+      this.budgetLogScalingCheckBox.Text = "logarithmic scaling";
+      this.budgetLogScalingCheckBox.UseVisualStyleBackColor = true;
+      this.budgetLogScalingCheckBox.CheckedChanged += new System.EventHandler(this.logScalingCheckBox_CheckedChanged);
       // 
       // eachOrAllBudgetsCheckBox
@@ -320,5 +333,5 @@
       this.byCostViewHost.Name = "byCostViewHost";
       this.byCostViewHost.ReadOnly = false;
-      this.byCostViewHost.Size = new System.Drawing.Size(640, 351);
+      this.byCostViewHost.Size = new System.Drawing.Size(640, 324);
       this.byCostViewHost.TabIndex = 8;
       this.byCostViewHost.ViewsLabelVisible = true;
@@ -327,32 +340,47 @@
       // byTableTabPage
       // 
-      this.byTableTabPage.Controls.Add(this.dataGridView1);
+      this.byTableTabPage.Controls.Add(this.ertViewHost);
       this.byTableTabPage.Location = new System.Drawing.Point(4, 22);
       this.byTableTabPage.Name = "byTableTabPage";
       this.byTableTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.byTableTabPage.Size = new System.Drawing.Size(646, 388);
+      this.byTableTabPage.Size = new System.Drawing.Size(646, 387);
       this.byTableTabPage.TabIndex = 2;
       this.byTableTabPage.Text = "Expected Runtime Tables";
       this.byTableTabPage.UseVisualStyleBackColor = true;
       // 
-      // dataGridView1
-      // 
-      this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-      this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.dataGridView1.Location = new System.Drawing.Point(3, 3);
-      this.dataGridView1.Name = "dataGridView1";
-      this.dataGridView1.Size = new System.Drawing.Size(640, 382);
-      this.dataGridView1.TabIndex = 0;
-      // 
-      // budgetLogScalingCheckBox
-      // 
-      this.budgetLogScalingCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-      this.budgetLogScalingCheckBox.AutoSize = true;
-      this.budgetLogScalingCheckBox.Location = new System.Drawing.Point(9, 391);
-      this.budgetLogScalingCheckBox.Name = "budgetLogScalingCheckBox";
-      this.budgetLogScalingCheckBox.Size = new System.Drawing.Size(112, 17);
-      this.budgetLogScalingCheckBox.TabIndex = 11;
-      this.budgetLogScalingCheckBox.Text = "logarithmic scaling";
-      this.budgetLogScalingCheckBox.UseVisualStyleBackColor = true;
+      // ertViewHost
+      // 
+      this.ertViewHost.Caption = "View";
+      this.ertViewHost.Content = null;
+      this.ertViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.ertViewHost.Enabled = false;
+      this.ertViewHost.Location = new System.Drawing.Point(3, 3);
+      this.ertViewHost.Name = "ertViewHost";
+      this.ertViewHost.ReadOnly = false;
+      this.ertViewHost.Size = new System.Drawing.Size(640, 381);
+      this.ertViewHost.TabIndex = 0;
+      this.ertViewHost.ViewsLabelVisible = true;
+      this.ertViewHost.ViewType = null;
+      // 
+      // 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(69, 30);
+      this.problemComboBox.Name = "problemComboBox";
+      this.problemComboBox.Size = new System.Drawing.Size(582, 21);
+      this.problemComboBox.TabIndex = 3;
+      this.problemComboBox.SelectedIndexChanged += new System.EventHandler(this.problemComboBox_SelectedIndexChanged);
+      // 
+      // problemLabel
+      // 
+      this.problemLabel.AutoSize = true;
+      this.problemLabel.Location = new System.Drawing.Point(3, 33);
+      this.problemLabel.Name = "problemLabel";
+      this.problemLabel.Size = new System.Drawing.Size(48, 13);
+      this.problemLabel.TabIndex = 2;
+      this.problemLabel.Text = "Problem:";
       // 
       // RunCollectionRLDView
@@ -362,5 +390,7 @@
       this.Controls.Add(this.groupComboBox);
       this.Controls.Add(this.groupLabel);
+      this.Controls.Add(this.problemLabel);
       this.Controls.Add(this.dataTableLabel);
+      this.Controls.Add(this.problemComboBox);
       this.Controls.Add(this.dataTableComboBox);
       this.Name = "RunCollectionRLDView";
@@ -373,5 +403,4 @@
       this.byCostTabPage.PerformLayout();
       this.byTableTabPage.ResumeLayout(false);
-      ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -401,9 +430,11 @@
     private System.Windows.Forms.TabPage byCostTabPage;
     private System.Windows.Forms.TabPage byTableTabPage;
-    private System.Windows.Forms.DataGridView dataGridView1;
     private MainForm.WindowsForms.ViewHost byCostViewHost;
     private System.Windows.Forms.CheckBox eachOrAllBudgetsCheckBox;
     private System.Windows.Forms.Button generateBudgetsButton;
     private System.Windows.Forms.CheckBox budgetLogScalingCheckBox;
+    private MainForm.WindowsForms.ViewHost ertViewHost;
+    private System.Windows.Forms.Label problemLabel;
+    private System.Windows.Forms.ComboBox problemComboBox;
   }
 }
Index: /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 12840)
+++ /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 12841)
@@ -24,4 +24,5 @@
 using System.ComponentModel;
 using System.Drawing;
+using System.Globalization;
 using System.Linq;
 using System.Windows.Forms;
@@ -125,5 +126,5 @@
         return;
       }
-      UpdateGroupComboBox();
+      UpdateGroupAndProblemComboBox();
       UpdateDataTableComboBox();
       foreach (var run in e.Items)
@@ -136,5 +137,5 @@
         return;
       }
-      UpdateGroupComboBox();
+      UpdateGroupAndProblemComboBox();
       UpdateDataTableComboBox();
       foreach (var run in e.Items)
@@ -147,5 +148,5 @@
         return;
       }
-      UpdateGroupComboBox();
+      UpdateGroupAndProblemComboBox();
       UpdateDataTableComboBox();
       foreach (var run in e.OldItems)
@@ -165,5 +166,5 @@
       if (!suppressUpdates) {
         UpdateDataTableComboBox();
-        UpdateGroupComboBox();
+        UpdateGroupAndProblemComboBox();
         UpdateRuns();
       }
@@ -195,5 +196,5 @@
       UpdateCaption();
       if (Content != null) {
-        UpdateGroupComboBox();
+        UpdateGroupAndProblemComboBox();
         UpdateDataTableComboBox();
       }
@@ -201,6 +202,6 @@
 
 
-    private void UpdateGroupComboBox() {
-      string selectedItem = (string)groupComboBox.SelectedItem;
+    private void UpdateGroupAndProblemComboBox() {
+      var selectedGroupItem = (string)groupComboBox.SelectedItem;
 
       var groupings = Content.ParameterNames.OrderBy(x => x).ToArray();
@@ -208,9 +209,30 @@
       groupComboBox.Items.Add(AllRuns);
       groupComboBox.Items.AddRange(groupings);
-      if (selectedItem != null && groupComboBox.Items.Contains(selectedItem)) {
-        groupComboBox.SelectedItem = selectedItem;
+      if (selectedGroupItem != null && groupComboBox.Items.Contains(selectedGroupItem)) {
+        groupComboBox.SelectedItem = selectedGroupItem;
       } else if (groupComboBox.Items.Count > 0) {
         groupComboBox.SelectedItem = groupComboBox.Items[0];
       }
+
+      var problems = new HashSet<ProblemDescription>();
+      foreach (var run in Content) {
+        problems.Add(new ProblemDescription(run));
+      }
+
+      var problemTypesDifferent = problems.Select(x => x.ProblemType).Distinct().Count() > 1;
+      var problemNamesDifferent = problems.Select(x => x.ProblemName).Distinct().Count() > 1;
+      var evaluatorDifferent = problems.Select(x => x.Evaluator).Distinct().Count() > 1;
+      var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent;
+
+      var selectedProblemItem = (ProblemDescription)problemComboBox.SelectedItem;
+      problemComboBox.Items.Clear();
+      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;
+      }
+      SetEnabledStateOfControls();
     }
 
@@ -235,7 +257,37 @@
       base.SetEnabledStateOfControls();
       groupComboBox.Enabled = Content != null;
-      dataTableComboBox.Enabled = Content != null;
+      problemComboBox.Enabled = Content != null && problemComboBox.Items.Count > 1;
+      dataTableComboBox.Enabled = Content != null && dataTableComboBox.Items.Count > 1;
       addTargetsAsResultButton.Enabled = Content != null && targets != null && dataTableComboBox.SelectedIndex >= 0;
       addBudgetsAsResultButton.Enabled = Content != null && budgets != null && dataTableComboBox.SelectedIndex >= 0;
+    }
+
+    private List<Tuple<string, List<IRun>>> GroupRuns() {
+      var groupedRuns = new List<Tuple<string, List<IRun>>>();
+
+      var table = (string)dataTableComboBox.SelectedItem;
+      if (string.IsNullOrEmpty(table)) return groupedRuns;
+
+      var selectedGroup = (string)groupComboBox.SelectedItem;
+      if (string.IsNullOrEmpty(selectedGroup)) return groupedRuns;
+
+      var selectedProblem = (ProblemDescription)problemComboBox.SelectedItem;
+      if (selectedProblem == null) selectedProblem = ProblemDescription.MatchAll;
+
+      if (selectedGroup == AllRuns)
+        groupedRuns = new List<Tuple<string, List<IRun>>> {
+          Tuple.Create(AllRuns, Content.Where(r => selectedProblem.Match(r) && r.Results.ContainsKey(table) && r.Visible).ToList())
+        };
+      else
+        groupedRuns = (from r in Content
+                       where r.Parameters.ContainsKey(selectedGroup)
+                             && selectedProblem.Match(r)
+                             && r.Results.ContainsKey(table)
+                             && r.Visible
+                       group r by r.Parameters[selectedGroup].ToString()
+                         into g
+                         select Tuple.Create(g.Key, g.ToList())).ToList();
+
+      return groupedRuns;
     }
 
@@ -261,18 +313,8 @@
       if (string.IsNullOrEmpty(table)) return;
 
-      var selectedGroup = (string)groupComboBox.SelectedItem;
-      if (string.IsNullOrEmpty(selectedGroup)) return;
-
       if (targets == null) GenerateDefaultTargets(table);
 
-      List<Tuple<string, List<IRun>>> groupedRuns;
-      if (selectedGroup == AllRuns)
-        groupedRuns = new List<Tuple<string, List<IRun>>> {
-          Tuple.Create(AllRuns, Content.Where(r => r.Results.ContainsKey(table) && r.Visible).ToList())
-        };
-      else groupedRuns = (from r in Content
-                          where r.Results.ContainsKey(table) && r.Visible
-                          group r by r.Parameters[selectedGroup].ToString() into g
-                          select Tuple.Create(g.Key, g.ToList())).ToList();
+      var groupedRuns = GroupRuns();
+      if (groupedRuns.Count == 0) return;
 
       var xAxisTitles = new HashSet<string>();
@@ -323,9 +365,12 @@
       byTargetDataTable.VisualProperties.XAxisTitle = string.Join(" / ", xAxisTitles);
       byTargetDataTable.VisualProperties.XAxisLogScale = byTargetDataTable.Rows.Count > 0 && targetLogScalingCheckBox.Checked;
+
+      UpdateErtTables(groupedRuns);
     }
 
     private void GenerateDefaultTargets(string table) {
-      var worst = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item2).Min()).Min();
-      var best = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item2).Max()).Max();
+      var runs = GroupRuns().SelectMany(x => x.Item2).ToList();
+      var worst = runs.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item2).Min()).Min();
+      var best = runs.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item2).Max()).Max();
       var maximization = IsMaximization();
       if (!maximization) {
@@ -380,4 +425,61 @@
       return values[j].Item1;
     }
+
+    private void UpdateErtTables(List<Tuple<string, List<IRun>>> groupedRuns) {
+      ertViewHost.Content = null;
+      var columns = 1 + targets.Length + 1;
+      var matrix = new string[groupedRuns.Count + 1, columns];
+      var rowCount = 0;
+      var maximization = IsMaximization();
+
+      var colNames = new string[columns];
+      colNames[0] = colNames[colNames.Length - 1] = string.Empty;
+      for (var i = 0; i < targets.Length; i++) {
+        colNames[i + 1] = maximization ? (targets[targets.Length - 1] / targets[i] - 1).ToString("0.0%")
+                                       : (targets[i] / targets[targets.Length - 1] - 1).ToString("0.0%");
+        matrix[rowCount, i + 1] = targets[i].ToString(CultureInfo.CurrentCulture.NumberFormat);
+      }
+      matrix[rowCount, columns - 1] = "#succ";
+      rowCount++;
+
+      foreach (var group in groupedRuns) {
+        matrix[rowCount, 0] = group.Item1;
+        var bestSucc = string.Empty;
+        for (var i = 0; i < targets.Length; i++) {
+          string succ;
+          matrix[rowCount, i + 1] = CalculateExpectedRunTime(group.Item2, targets[i], maximization, out succ);
+          if (i == targets.Length - 1) bestSucc = succ;
+        }
+        matrix[rowCount, columns - 1] = bestSucc;
+        rowCount++;
+      }
+      ertViewHost.Content = new StringMatrix(matrix) { ColumnNames = colNames };
+    }
+
+    private string CalculateExpectedRunTime(List<IRun> group, double target, bool maximization, out string successProb) {
+      var table = (string)dataTableComboBox.SelectedItem;
+      successProb = "-";
+      if (string.IsNullOrEmpty(table)) return "N/A";
+      var successful = new List<double>();
+      var unsuccessful = new List<double>();
+      foreach (var r in group) {
+        var targetAchieved = false;
+        var row = ((IndexedDataTable<double>)r.Results[table]).Rows.First();
+        foreach (var v in row.Values) {
+          if (maximization && v.Item2 >= target || !maximization && v.Item2 <= target) {
+            successful.Add(v.Item1);
+            targetAchieved = true;
+            break;
+          }
+        }
+        if (!targetAchieved) unsuccessful.Add(row.Values.Last().Item1);
+      }
+      successProb = successful.Count + "/" + (successful.Count + unsuccessful.Count);
+      if (successful.Count == 0) return "\u221e"; // infinity symbol
+      if (unsuccessful.Count == 0) return successful.Average().ToString("##,0.0", CultureInfo.CurrentCulture.NumberFormat);
+
+      var ps = successful.Count / (double)(successful.Count + unsuccessful.Count);
+      return (successful.Average() + ((1.0 - ps) / ps) * unsuccessful.Average()).ToString("##,0.0", CultureInfo.CurrentCulture.NumberFormat);
+    }
     #endregion
 
@@ -391,18 +493,8 @@
       if (string.IsNullOrEmpty(table)) return;
 
-      var selectedGroup = (string)groupComboBox.SelectedItem;
-      if (string.IsNullOrEmpty(selectedGroup)) return;
-
       if (budgets == null) GenerateDefaultBudgets(table);
 
-      List<Tuple<string, List<IRun>>> groupedRuns;
-      if (selectedGroup == AllRuns)
-        groupedRuns = new List<Tuple<string, List<IRun>>> {
-          Tuple.Create(AllRuns, Content.Where(r => r.Results.ContainsKey(table) && r.Visible).ToList())
-        };
-      else groupedRuns = (from r in Content
-                          where r.Results.ContainsKey(table) && r.Visible
-                          group r by r.Parameters[selectedGroup].ToString() into g
-                          select Tuple.Create(g.Key, g.ToList())).ToList();
+      var groupedRuns = GroupRuns();
+      if (groupedRuns.Count == 0) return;
 
       var colorCount = 0;
@@ -450,6 +542,7 @@
 
     private void GenerateDefaultBudgets(string table) {
-      var min = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item1).Min()).Min();
-      var max = Content.Where(x => x.Results.ContainsKey(table)).Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item1).Max()).Max();
+      var runs = GroupRuns().SelectMany(x => x.Item2).ToList();
+      var min = runs.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item1).Min()).Min();
+      var max = runs.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item1).Max()).Max();
 
       var maxMagnitude = (int)Math.Ceiling(Math.Log10(max));
@@ -525,4 +618,10 @@
 
     private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      UpdateRuns();
+      SetEnabledStateOfControls();
+    }
+    private void problemComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      if (dataTableComboBox.SelectedIndex >= 0)
+        GenerateDefaultTargets((string)dataTableComboBox.SelectedItem);
       UpdateRuns();
       SetEnabledStateOfControls();
@@ -762,4 +861,67 @@
     }
     #endregion
+
+
+    private class ProblemDescription {
+      private readonly bool matchAll;
+      public static readonly ProblemDescription MatchAll = new ProblemDescription();
+
+      private ProblemDescription() {
+        ProblemType = string.Empty;
+        ProblemName = string.Empty;
+        Evaluator = string.Empty;
+        DisplayProblemType = false;
+        DisplayProblemName = false;
+        DisplayEvaluator = false;
+        matchAll = true;
+      }
+
+      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);
+        matchAll = false;
+      }
+
+      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 matchAll ||
+               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 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)));
+      }
+    }
   }
 }
