Index: /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem.Common/3.3/KnowledgeCenter.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem.Common/3.3/KnowledgeCenter.cs	(revision 13751)
+++ /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem.Common/3.3/KnowledgeCenter.cs	(revision 13752)
@@ -46,4 +46,5 @@
   [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 119)]
   public sealed class KnowledgeCenter : IContent {
+    private bool SuppressEvents { get; set; }
 
     public string Filename { get; set; }
@@ -90,6 +91,7 @@
 
     private readonly CheckedItemList<StringValue> problemCharacteristics;
-    public CheckedItemList<StringValue> ProblemCharacteristics {
-      get { return problemCharacteristics; }
+    private readonly ReadOnlyCheckedItemList<StringValue> readonlyProblemCharacteristics; 
+    public ReadOnlyCheckedItemList<StringValue> ProblemCharacteristics {
+      get { return readonlyProblemCharacteristics; }
     } 
 
@@ -121,4 +123,5 @@
       problemInstances = new RunCollection();
       problemCharacteristics = new CheckedItemList<StringValue>();
+      readonlyProblemCharacteristics = problemCharacteristics.AsReadOnly();
       problem = new SingleObjectiveOKBProblem();
       algorithmId2RunMapping = new BidirectionalLookup<long, IRun>();
@@ -149,4 +152,9 @@
       knowledgeBase.ItemsAdded += InformationChanged;
       knowledgeBase.ItemsRemoved += InformationChanged;
+      problemCharacteristics.ItemsAdded += CharacteristicChanged;
+      problemCharacteristics.ItemsReplaced += CharacteristicChanged;
+      problemCharacteristics.ItemsRemoved += CharacteristicChanged;
+      problemCharacteristics.CollectionReset += CharacteristicChanged;
+      problemCharacteristics.CheckedItemsChanged += CharacteristicChanged;
     }
 
@@ -168,4 +176,9 @@
     }
 
+    private void CharacteristicChanged(object sender, EventArgs e) {
+      if (SuppressEvents) return;
+      UpdateInstanceProjection();
+    }
+
     public bool IsCurrentInstance(IRun run) {
       if (!problemId2ProblemInstanceMapping.ContainsSecond(run)) return false;
@@ -177,19 +190,27 @@
 
       var instances = new Dictionary<IRun, double[]>();
+      var values = new List<double>[ProblemCharacteristics.CheckedItems.Count()];
       foreach (var run in ProblemInstances) {
         var f = 0;
         instances[run] = new double[ProblemCharacteristics.CheckedItems.Count()];
         foreach (var c in ProblemCharacteristics.CheckedItems.Select(x => x.Value.Value)) {
+          if (values[f] == null) values[f] = new List<double>(ProblemInstances.Count);
           IItem item;
           if (run.Results.TryGetValue(c, out item)) {
-            instances[run][f] = (double)((dynamic)item).Value;
-          } else instances[run][f] = 0; // TODO: handle missing values
+            var val = (double)((dynamic)item).Value;
+            if (!double.IsNaN(val)) values[f].Add(val);
+            instances[run][f] = val;
+          } else instances[run][f] = double.NaN;
           f++;
         }
       }
-
-      var allValues = instances.SelectMany(x => x.Value).ToList();
-      var avg = allValues.Average();
-      var stdev = allValues.StandardDeviation();
+      var median = values.Select(x => x.Count == 0 ? 0.0 : x.Median()).ToList();
+
+      var allValues = instances.Values.Select(x => x.Select((f, i) => new { Idx = i, Val = double.IsNaN(f) ? median[i] : f }).ToList())
+                                      .SelectMany(x => x)
+                                      .GroupBy(x => x.Idx, x => x.Val)
+                                      .OrderBy(x => x.Key).ToList();
+      var avg = allValues.Select(x => x.Average()).ToList();
+      var stdev = allValues.Select(x => x.StandardDeviation()).ToList();
 
       // normalize characteristic values by transforming them to their z-score
@@ -197,5 +218,6 @@
         var arr = instances[key];
         for (var i = 0; i < arr.Length; i++) {
-          arr[i] = (arr[i] - avg) / stdev;
+          if (double.IsNaN(arr[i])) arr[i] = median[i];
+          if (stdev[i] > 0) arr[i] = (arr[i] - avg[i]) / stdev[i];
         }
       }
@@ -396,5 +418,5 @@
       var adminClient = Clients.OKB.Administration.AdministrationClient.Instance;
       try {
-        progress.Status = "Downloading run information...";
+        progress.Status = "Connecting to OKB...";
         progress.ProgressValue = 0;
         // FIXME: How to tell if refresh is necessary?
@@ -414,83 +436,90 @@
         progress.Status = "Downloading problem instances...";
         progress.ProgressValue = 0;
-        var p = 0;
+        int[] p = { 0 };
         ProblemInstances.UpdateOfRunsInProgress = true;
         ProblemInstances.Clear();
         var characteristics = new HashSet<string>();
         var totalProblems = adminClient.Problems.Count(x => x.ProblemClassId == probClassId);
-        foreach (var problInst in adminClient.Problems.Where(x => x.ProblemClassId == probClassId)) {
-          progress.Status = string.Format("Downloading problem {0} (okb-id: {1})....", problInst.Name, problInst.Id);
-          var data = Clients.OKB.Administration.AdministrationClient.GetProblemData(problInst.Id);
+        Parallel.ForEach(adminClient.Problems.Where(x => x.ProblemClassId == probClassId), (pInst) => { 
+          var charas = new List<string>();
+          IRun probRun = null;
+          var data = Clients.OKB.Administration.AdministrationClient.GetProblemData(pInst.Id);
           if (data != null) {
             using (var stream = new MemoryStream(data)) {
               try {
                 var prob = (IProblem)XmlParser.Deserialize<IContent>(stream);
-                var probRun = new Run() { Name = prob.Name };
+                probRun = new Run() { Name = prob.Name };
                 prob.CollectParameterValues(probRun.Parameters);
                 probRun.Parameters["Problem Name"] = new StringValue(prob.Name);
                 probRun.Parameters["Problem Type"] = new StringValue(prob.GetType().Name);
-                progress.Status += Environment.NewLine + "Downloading characteristics...";
-                foreach (var v in RunCreationClient.Instance.GetCharacteristicValues(problInst.Id)) {
+                foreach (var v in RunCreationClient.Instance.GetCharacteristicValues(pInst.Id)) {
                   probRun.Results.Add("Characteristic." + v.Name, RunCreationClient.Instance.ConvertToItem(v));
-                  characteristics.Add(v.Name);
+                  charas.Add("Characteristic." + v.Name);
                 }
-                ProblemInstances.Add(probRun);
-                problemId2ProblemInstanceMapping.Add(problInst.Id, probRun);
               } catch { }
               stream.Close();
             }
-          }
-          p++;
-          progress.ProgressValue = p / (double)totalProblems;
-        }
+            if (probRun != null) {
+              lock (characteristics) {
+                problemId2ProblemInstanceMapping.Add(pInst.Id, probRun);
+                ProblemInstances.Add(probRun);
+                progress.Status = string.Format("Downloaded problem {0} (okb-id: {1})....", pInst.Name, pInst.Id);
+                p[0]++;
+                progress.ProgressValue = p[0] / (double)totalProblems;
+                foreach (var c in charas) characteristics.Add(c);
+              }
+            }
+          }
+        });
 
         algorithmId2AlgorithmInstanceMapping.Clear();
         progress.Status = "Downloading algorithm instances...";
         progress.ProgressValue = 0;
-        p = 0;
-        foreach (var algInst in adminClient.Algorithms) {
-          progress.Status = string.Format("Downloading algorithm {0} (okb-id: {1})...", algInst.Name, algInst.Id);
+        p[0] = 0;
+        Parallel.ForEach(adminClient.Algorithms, (algInst) => {
+          IAlgorithm alg = null;
           var data = Clients.OKB.Administration.AdministrationClient.GetAlgorithmData(algInst.Id);
           if (data != null) {
             using (var stream = new MemoryStream(data)) {
               try {
-                var alg = (IAlgorithm)XmlParser.Deserialize<IContent>(stream);
-                algorithmId2AlgorithmInstanceMapping.Add(algInst.Id, alg);
+                alg = (IAlgorithm)XmlParser.Deserialize<IContent>(stream);
               } catch { }
               stream.Close();
             }
-          }
-          p++;
-          progress.ProgressValue = p / (double)adminClient.Algorithms.Count;
-        }
+            if (alg != null) {
+              lock (algorithmId2AlgorithmInstanceMapping) {
+                algorithmId2AlgorithmInstanceMapping.Add(algInst.Id, alg);
+                progress.Status = string.Format("Downloaded algorithm {0} (okb-id: {1})...", algInst.Name, algInst.Id);
+                p[0]++;
+                progress.ProgressValue = p[0] / (double)adminClient.Algorithms.Count;
+              }
+            }
+          }
+        });
 
         var interestingValues = queryClient.ValueNames.Where(x => InterestingValueNames.Contains(x.Name)).ToList();
 
-        progress.Status = "Obtaining number of runs...";
+        progress.Status = "Downloading runs...";
         progress.ProgressValue = 0;
-        p = 0;
+        p[0] = 0;
         var count = queryClient.GetNumberOfRuns(problemClassFilter);
         if (count == 0) return;
         
+        var runList = new List<IRun>();
         var runIds = queryClient.GetRunIds(problemClassFilter).ToList();
-        var conversions = new List<Task>();
-        var runList = new List<IRun>();
-        while (p < count) {
-          var nextIds = runIds.Skip(p).Take(500).ToList();
-          progress.Status = string.Format("Downloading runs {0} to {1} of {2}...", p, p + nextIds.Count, count);
-          var okbRuns = queryClient.GetRunsWithValues(nextIds, true, interestingValues);
-          conversions.Add(Task.Factory.StartNew(() => {
-            var hlRuns = okbRuns.AsParallel().Select(x => new { AlgorithmId = x.Algorithm.Id, Run = queryClient.ConvertToOptimizationRun(x) }).ToList();
-            lock (runList) {
-              foreach (var r in hlRuns) {
-                algorithmId2RunMapping.Add(r.AlgorithmId, r.Run);
-                runList.Add(r.Run);
-              }
-            }
-          }));
-          p += nextIds.Count;
-          progress.ProgressValue = p / (double)count;
-        }
-        Task.WaitAll(conversions.ToArray());
+        var batches = runIds.Select((v, i) => new { Idx = i, Val = v }).GroupBy(x => x.Idx / 500, x => x.Val);
+        Parallel.ForEach(batches.Select(x => x.ToList()), (batch) => {
+          var okbRuns = queryClient.GetRunsWithValues(batch, true, interestingValues);
+          var hlRuns = okbRuns.AsParallel().Select(x => new { AlgorithmId = x.Algorithm.Id, Run = queryClient.ConvertToOptimizationRun(x) }).ToList();
+          lock (runList) {
+            foreach (var r in hlRuns) {
+              algorithmId2RunMapping.Add(r.AlgorithmId, r.Run);
+              runList.Add(r.Run);
+            }
+            progress.Status = string.Format("Downloaded runs {0} to {1} of {2}...", p[0], p[0] + batch.Count, count);
+            p[0] += batch.Count;
+            progress.ProgressValue = p[0] / (double)count;
+          }
+        });
 
         progress.Status = "Finishing...";
@@ -534,5 +563,10 @@
           }
         }
-        ProblemCharacteristics.Replace(characteristics.Select(x => new StringValue(x)));
+        try {
+          SuppressEvents = true;
+          problemCharacteristics.Replace(characteristics.Select(x => new StringValue(x)));
+          foreach (var pc in problemCharacteristics.Where(x => !x.Value.StartsWith("Characteristic.")))
+            problemCharacteristics.SetItemCheckedState(pc, false);
+        } finally { SuppressEvents = false; }
         try {
           KnowledgeBase.UpdateOfRunsInProgress = true;
Index: /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/KnowledgeCenterViewBase.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/KnowledgeCenterViewBase.cs	(revision 13751)
+++ /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/KnowledgeCenterViewBase.cs	(revision 13752)
@@ -50,4 +50,5 @@
       RegisterContentProblemEvents();
       RegisterContentProblemInstancesEvents();
+      RegisterContentProblemCharacteristicsEvents();
       RegisterContentSolutionSeedingPoolEvents();
       RegisterContentSuggestedInstancesEvents();
@@ -70,4 +71,12 @@
     }
 
+    private void RegisterContentProblemCharacteristicsEvents() {
+      Content.ProblemCharacteristics.ItemsAdded += ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.ItemsReplaced += ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.ItemsRemoved += ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.CheckedItemsChanged += ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.CollectionReset += ContentOnProblemCharacteristicsChanged;
+    }
+
     private void RegisterContentSolutionSeedingPoolEvents() {
       Content.SolutionSeedingPool.CheckedItemsChanged += ContentOnSolutionSeedingPoolChanged;
@@ -92,4 +101,5 @@
       DeregisterContentProblemEvents();
       DeregisterContentProblemInstancesEvents();
+      DeregisterContentProblemCharacteristicsEvents();
       DeregisterContentSolutionSeedingPoolEvents();
       DeregisterContentSuggestedInstancesEvents();
@@ -110,4 +120,12 @@
       Content.ProblemInstances.CollectionReset -= ContentOnProblemInstancesChanged;
       Content.ProblemInstances.ItemChanged -= ContentOnProblemInstancesChanged;
+    }
+
+    private void DeregisterContentProblemCharacteristicsEvents() {
+      Content.ProblemCharacteristics.ItemsAdded -= ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.ItemsReplaced -= ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.ItemsRemoved -= ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.CheckedItemsChanged -= ContentOnProblemCharacteristicsChanged;
+      Content.ProblemCharacteristics.CollectionReset -= ContentOnProblemCharacteristicsChanged;
     }
 
@@ -136,4 +154,5 @@
     protected virtual void OnProblemSolutionsChanged() { }
     protected virtual void OnProblemInstancesChanged() { }
+    protected virtual void OnProblemCharacteristicsChanged() { }
     protected virtual void OnSolutionSeedingPoolChanged() { }
     protected virtual void OnSuggestedInstancesChanged() { }
@@ -175,4 +194,9 @@
     }
 
+    private void ContentOnProblemCharacteristicsChanged(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action)OnProblemCharacteristicsChanged);
+      else OnProblemCharacteristicsChanged();
+    }
+
     private void ContentOnSolutionSeedingPoolChanged(object sender, EventArgs e) {
       if (InvokeRequired) Invoke((Action)OnSolutionSeedingPoolChanged);
Index: /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingProblemInstanceView.Designer.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingProblemInstanceView.Designer.cs	(revision 13751)
+++ /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingProblemInstanceView.Designer.cs	(revision 13752)
@@ -52,7 +52,6 @@
       this.problemInstancesTabControl = new HeuristicLab.MainForm.WindowsForms.DragOverTabControl();
       this.mapTabPage = new System.Windows.Forms.TabPage();
-      this.instancesTabPage = new System.Windows.Forms.TabPage();
-      this.problemInstancesView = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       this.mapSplitContainer = new System.Windows.Forms.SplitContainer();
+      this.showCharacteristicsCheckBox = new System.Windows.Forms.CheckBox();
       this.invPropCheckBox = new System.Windows.Forms.CheckBox();
       this.sizeLabel = new System.Windows.Forms.Label();
@@ -61,12 +60,13 @@
       this.sizeComboBox = new System.Windows.Forms.ComboBox();
       this.projectionComboBox = new System.Windows.Forms.ComboBox();
-      this.showCharacteristicsCheckBox = new System.Windows.Forms.CheckBox();
+      this.instancesTabPage = new System.Windows.Forms.TabPage();
+      this.problemInstancesView = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       this.problemInstancesTabControl.SuspendLayout();
       this.mapTabPage.SuspendLayout();
-      this.instancesTabPage.SuspendLayout();
       ((System.ComponentModel.ISupportInitialize)(this.mapSplitContainer)).BeginInit();
       this.mapSplitContainer.Panel1.SuspendLayout();
       this.mapSplitContainer.SuspendLayout();
       ((System.ComponentModel.ISupportInitialize)(this.instanceMapChart)).BeginInit();
+      this.instancesTabPage.SuspendLayout();
       this.SuspendLayout();
       // 
@@ -96,29 +96,4 @@
       this.mapTabPage.UseVisualStyleBackColor = true;
       // 
-      // instancesTabPage
-      // 
-      this.instancesTabPage.Controls.Add(this.problemInstancesView);
-      this.instancesTabPage.Location = new System.Drawing.Point(4, 22);
-      this.instancesTabPage.Name = "instancesTabPage";
-      this.instancesTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.instancesTabPage.Size = new System.Drawing.Size(992, 734);
-      this.instancesTabPage.TabIndex = 0;
-      this.instancesTabPage.Text = "Instances";
-      this.instancesTabPage.UseVisualStyleBackColor = true;
-      // 
-      // problemInstancesView
-      // 
-      this.problemInstancesView.Caption = "View";
-      this.problemInstancesView.Content = null;
-      this.problemInstancesView.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.problemInstancesView.Enabled = false;
-      this.problemInstancesView.Location = new System.Drawing.Point(3, 3);
-      this.problemInstancesView.Name = "problemInstancesView";
-      this.problemInstancesView.ReadOnly = false;
-      this.problemInstancesView.Size = new System.Drawing.Size(986, 728);
-      this.problemInstancesView.TabIndex = 0;
-      this.problemInstancesView.ViewsLabelVisible = true;
-      this.problemInstancesView.ViewType = null;
-      // 
       // mapSplitContainer
       // 
@@ -138,7 +113,20 @@
       this.mapSplitContainer.Panel1.Controls.Add(this.projectionComboBox);
       this.mapSplitContainer.Panel1.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0);
+      this.mapSplitContainer.Panel2Collapsed = true;
       this.mapSplitContainer.Size = new System.Drawing.Size(986, 728);
       this.mapSplitContainer.SplitterDistance = 847;
       this.mapSplitContainer.TabIndex = 12;
+      // 
+      // showCharacteristicsCheckBox
+      // 
+      this.showCharacteristicsCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.showCharacteristicsCheckBox.Appearance = System.Windows.Forms.Appearance.Button;
+      this.showCharacteristicsCheckBox.Location = new System.Drawing.Point(957, 4);
+      this.showCharacteristicsCheckBox.Name = "showCharacteristicsCheckBox";
+      this.showCharacteristicsCheckBox.Size = new System.Drawing.Size(26, 23);
+      this.showCharacteristicsCheckBox.TabIndex = 18;
+      this.showCharacteristicsCheckBox.Text = "Detail";
+      this.showCharacteristicsCheckBox.UseVisualStyleBackColor = true;
+      this.showCharacteristicsCheckBox.CheckedChanged += new System.EventHandler(this.showCharacteristicsCheckBox_CheckedChanged);
       // 
       // invPropCheckBox
@@ -153,4 +141,5 @@
       this.invPropCheckBox.Text = "inverse proportional";
       this.invPropCheckBox.UseVisualStyleBackColor = true;
+      this.invPropCheckBox.CheckedChanged += new System.EventHandler(this.InvPropCheckBoxOnCheckedChanged);
       // 
       // sizeLabel
@@ -203,5 +192,5 @@
       this.instanceMapChart.Series.Add(series1);
       this.instanceMapChart.Series.Add(series2);
-      this.instanceMapChart.Size = new System.Drawing.Size(841, 692);
+      this.instanceMapChart.Size = new System.Drawing.Size(980, 692);
       this.instanceMapChart.TabIndex = 12;
       // 
@@ -214,4 +203,5 @@
       this.sizeComboBox.Size = new System.Drawing.Size(273, 21);
       this.sizeComboBox.TabIndex = 13;
+      this.sizeComboBox.SelectedIndexChanged += new System.EventHandler(this.SizeComboBoxOnSelectedIndexChanged);
       // 
       // projectionComboBox
@@ -223,15 +213,30 @@
       this.projectionComboBox.Size = new System.Drawing.Size(158, 21);
       this.projectionComboBox.TabIndex = 14;
-      // 
-      // showCharacteristicsCheckBox
-      // 
-      this.showCharacteristicsCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
-      this.showCharacteristicsCheckBox.Appearance = System.Windows.Forms.Appearance.Button;
-      this.showCharacteristicsCheckBox.Location = new System.Drawing.Point(818, 4);
-      this.showCharacteristicsCheckBox.Name = "showCharacteristicsCheckBox";
-      this.showCharacteristicsCheckBox.Size = new System.Drawing.Size(26, 23);
-      this.showCharacteristicsCheckBox.TabIndex = 18;
-      this.showCharacteristicsCheckBox.Text = "Detail";
-      this.showCharacteristicsCheckBox.UseVisualStyleBackColor = true;
+      this.projectionComboBox.SelectedIndexChanged += new System.EventHandler(this.ProjectionComboBoxOnSelectedIndexChanged);
+      // 
+      // instancesTabPage
+      // 
+      this.instancesTabPage.Controls.Add(this.problemInstancesView);
+      this.instancesTabPage.Location = new System.Drawing.Point(4, 22);
+      this.instancesTabPage.Name = "instancesTabPage";
+      this.instancesTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.instancesTabPage.Size = new System.Drawing.Size(992, 734);
+      this.instancesTabPage.TabIndex = 0;
+      this.instancesTabPage.Text = "Instances";
+      this.instancesTabPage.UseVisualStyleBackColor = true;
+      // 
+      // problemInstancesView
+      // 
+      this.problemInstancesView.Caption = "View";
+      this.problemInstancesView.Content = null;
+      this.problemInstancesView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.problemInstancesView.Enabled = false;
+      this.problemInstancesView.Location = new System.Drawing.Point(3, 3);
+      this.problemInstancesView.Name = "problemInstancesView";
+      this.problemInstancesView.ReadOnly = false;
+      this.problemInstancesView.Size = new System.Drawing.Size(986, 728);
+      this.problemInstancesView.TabIndex = 0;
+      this.problemInstancesView.ViewsLabelVisible = true;
+      this.problemInstancesView.ViewType = null;
       // 
       // UnderstandingProblemInstanceView
@@ -244,5 +249,4 @@
       this.problemInstancesTabControl.ResumeLayout(false);
       this.mapTabPage.ResumeLayout(false);
-      this.instancesTabPage.ResumeLayout(false);
       this.mapSplitContainer.Panel1.ResumeLayout(false);
       this.mapSplitContainer.Panel1.PerformLayout();
@@ -250,4 +254,5 @@
       this.mapSplitContainer.ResumeLayout(false);
       ((System.ComponentModel.ISupportInitialize)(this.instanceMapChart)).EndInit();
+      this.instancesTabPage.ResumeLayout(false);
       this.ResumeLayout(false);
 
Index: /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingProblemInstanceView.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingProblemInstanceView.cs	(revision 13751)
+++ /branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/UnderstandingProblemInstanceView.cs	(revision 13752)
@@ -20,5 +20,8 @@
 #endregion
 
+using HeuristicLab.Common.Resources;
 using HeuristicLab.Core;
+using HeuristicLab.Core.Views;
+using HeuristicLab.Data;
 using HeuristicLab.MainForm;
 using HeuristicLab.OptimizationExpertSystem.Common;
@@ -27,4 +30,5 @@
 using System.Linq;
 using System.Text.RegularExpressions;
+using System.Windows.Forms;
 using System.Windows.Forms.DataVisualization.Charting;
 
@@ -34,7 +38,14 @@
   public sealed partial class UnderstandingProblemInstanceView : KnowledgeCenterViewBase {
     private bool SuppressEvents { get; set; }
-
+    private readonly CheckedItemListView<StringValue> characteristicsView;
+ 
     public UnderstandingProblemInstanceView() {
       InitializeComponent();
+      showCharacteristicsCheckBox.Text = string.Empty;
+      showCharacteristicsCheckBox.Image = VSImageLibrary.Properties;
+      characteristicsView = new CheckedItemListView<StringValue>() {
+        Dock = DockStyle.Fill
+      };
+      mapSplitContainer.Panel2.Controls.Add(characteristicsView);
     }
 
@@ -43,8 +54,10 @@
       if (Content == null) {
         problemInstancesView.Content = null;
+        characteristicsView.Content = null;
         instanceMapChart.Series["InstancesSeries"].Points.Clear();
         instanceMapChart.Series["CurrentInstanceSeries"].Points.Clear();
       } else {
         problemInstancesView.Content = Content.ProblemInstances;
+        characteristicsView.Content = Content.ProblemCharacteristics;
         UpdateProjectionComboBox();
         UpdateSizeComboBox();
@@ -175,4 +188,8 @@
       UpdateProjection();
     }
+
+    private void showCharacteristicsCheckBox_CheckedChanged(object sender, EventArgs e) {
+      mapSplitContainer.Panel2Collapsed = !showCharacteristicsCheckBox.Checked;
+    }
     #endregion
   }
