Index: /branches/1614_GeneralizedQAP/GeneralizedQAP.sln
===================================================================
--- /branches/1614_GeneralizedQAP/GeneralizedQAP.sln	(revision 15718)
+++ /branches/1614_GeneralizedQAP/GeneralizedQAP.sln	(revision 15719)
@@ -12,6 +12,4 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{68C6C157-08DA-414F-9256-CCCA13038399}"
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7275B9B0-0E8D-471E-9F64-067E1F85BB71}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Optimization-3.3", "HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj", "{14AB8D24-25BC-400C-A846-4627AA945192}"
 EndProject
@@ -28,8 +26,9 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Analysis.FitnessLandscape-3.3", "HeuristicLab.Analysis.FitnessLandscape\3.3\HeuristicLab.Analysis.FitnessLandscape-3.3.csproj", "{5FBDCD4A-3C2A-4EC6-83CE-34B29F43621A}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Analysis-3.3", "HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj", "{887425B4-4348-49ED-A457-B7D2C26DDBF9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Analysis.Views-3.3", "HeuristicLab.Analysis.Views\3.3\HeuristicLab.Analysis.Views-3.3.csproj", "{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}"
+EndProject
 Global
-	GlobalSection(Performance) = preSolution
-		HasPerformanceSessions = true
-	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -173,4 +172,28 @@
 		{5FBDCD4A-3C2A-4EC6-83CE-34B29F43621A}.Release|x86.ActiveCfg = Release|x86
 		{5FBDCD4A-3C2A-4EC6-83CE-34B29F43621A}.Release|x86.Build.0 = Release|x86
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Debug|x64.ActiveCfg = Debug|x64
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Debug|x64.Build.0 = Debug|x64
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Debug|x86.ActiveCfg = Debug|x86
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Debug|x86.Build.0 = Debug|x86
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Release|x64.ActiveCfg = Release|x64
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Release|x64.Build.0 = Release|x64
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Release|x86.ActiveCfg = Release|x86
+		{887425B4-4348-49ED-A457-B7D2C26DDBF9}.Release|x86.Build.0 = Release|x86
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Debug|x64.ActiveCfg = Debug|x64
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Debug|x64.Build.0 = Debug|x64
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Debug|x86.ActiveCfg = Debug|x86
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Debug|x86.Build.0 = Debug|x86
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Release|x64.ActiveCfg = Release|x64
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Release|x64.Build.0 = Release|x64
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Release|x86.ActiveCfg = Release|x86
+		{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
@@ -192,3 +215,6 @@
 		HasPerformanceSessions = true
 	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
 EndGlobal
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Algorithms.GRASP/3.3/HeuristicLab.Algorithms.GRASP-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Algorithms.GRASP/3.3/HeuristicLab.Algorithms.GRASP-3.3.csproj	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Algorithms.GRASP/3.3/HeuristicLab.Algorithms.GRASP-3.3.csproj	(revision 15719)
@@ -41,8 +41,4 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0">
-      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
     <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
       <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
@@ -105,4 +101,9 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
       <Project>{14ab8d24-25bc-400c-a846-4627aa945192}</Project>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.FitnessLandscape/3.3/HeuristicLab.Analysis.FitnessLandscape-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.FitnessLandscape/3.3/HeuristicLab.Analysis.FitnessLandscape-3.3.csproj	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.FitnessLandscape/3.3/HeuristicLab.Analysis.FitnessLandscape-3.3.csproj	(revision 15719)
@@ -94,8 +94,4 @@
     <Reference Include="ALGLIB-3.7.0">
       <HintPath>..\..\..\..\trunk\bin\ALGLIB-3.7.0.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="HeuristicLab.Analysis-3.3">
-      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -256,4 +252,9 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
       <Project>{14ab8d24-25bc-400c-a846-4627aa945192}</Project>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionHistoryView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionHistoryView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionHistoryView.Designer.cs	(revision 15719)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class AlleleFrequencyCollectionHistoryView {
+    /// <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) {
+        if (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() {
+      components = new System.ComponentModel.Container();
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+    }
+
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionHistoryView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionHistoryView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionHistoryView.cs	(revision 15719)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("AlleleFrequencyCollectionHistory View")]
+  [Content(typeof(AlleleFrequencyCollectionHistory), true)]
+  public partial class AlleleFrequencyCollectionHistoryView : MovieView<AlleleFrequencyCollection> {
+    public AlleleFrequencyCollectionHistoryView() {
+      InitializeComponent();
+      itemsGroupBox.Text = "Allele Frequencies";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.Designer.cs	(revision 15719)
@@ -0,0 +1,108 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class AlleleFrequencyCollectionView {
+    /// <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) {
+        if (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() {
+      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.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      this.chart.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)));
+      this.chart.BorderlineColor = System.Drawing.Color.Black;
+      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
+      chartArea1.AxisX.IntervalAutoMode = System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode.VariableCount;
+      chartArea1.AxisX.LabelAutoFitStyle = ((System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles)((System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles.IncreaseFont | System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles.DecreaseFont)));
+      chartArea1.AxisX.Title = "Allele Index";
+      chartArea1.AxisY.Maximum = 1D;
+      chartArea1.AxisY.Minimum = 0D;
+      chartArea1.AxisY.Title = "Relative Frequency";
+      chartArea1.AxisY2.Title = "Average Solution Quality";
+      chartArea1.CursorX.IsUserEnabled = true;
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
+      chartArea1.Name = "Default";
+      this.chart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Default";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(0, 0);
+      this.chart.Name = "chart";
+      this.chart.Size = new System.Drawing.Size(498, 359);
+      this.chart.TabIndex = 0;
+      this.chart.Text = "chart";
+      title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      title1.Name = "Default";
+      title1.Text = "Allele Frequencies";
+      this.chart.Titles.Add(title1);
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // AlleleFrequencyCollectionView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.chart);
+      this.Name = "AlleleFrequencyCollectionView";
+      this.Size = new System.Drawing.Size(498, 359);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.cs	(revision 15719)
@@ -0,0 +1,182 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("AlleleFrequencyCollection View")]
+  [Content(typeof(AlleleFrequencyCollection), true)]
+  public partial class AlleleFrequencyCollectionView : ItemView {
+    private List<Series> invisibleSeries;
+
+    public new AlleleFrequencyCollection Content {
+      get { return (AlleleFrequencyCollection)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public AlleleFrequencyCollectionView() {
+      InitializeComponent();
+      invisibleSeries = new List<Series>();
+      chart.CustomizeAllChartAreas();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        chart.Series.Clear();
+        invisibleSeries.Clear();
+      } else {
+        if (chart.Series.Count == 0) CreateSeries();
+        UpdateSeries();
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      chart.Enabled = Content != null;
+    }
+
+    protected virtual void CreateSeries() {
+      Series bestKnown = new Series("Alleles of Best Known Solution");
+      bestKnown.ChartType = SeriesChartType.Column;
+      bestKnown.XValueType = ChartValueType.String;
+      bestKnown.YValueType = ChartValueType.Double;
+      bestKnown.YAxisType = AxisType.Primary;
+      chart.Series.Add(bestKnown);
+
+      Series others = new Series("Other Alleles");
+      others.ChartType = SeriesChartType.Column;
+      others.XValueType = ChartValueType.String;
+      others.YValueType = ChartValueType.Double;
+      others.YAxisType = AxisType.Primary;
+      chart.Series.Add(others);
+      invisibleSeries.Add(others);
+
+      Series qualities = new Series("Average Solution Qualities");
+      qualities.ChartType = SeriesChartType.FastPoint;
+      qualities.XValueType = ChartValueType.String;
+      qualities.YValueType = ChartValueType.Double;
+      qualities.YAxisType = AxisType.Secondary;
+      chart.Series.Add(qualities);
+
+      Series impacts = new Series("Average Impact");
+      impacts.ChartType = SeriesChartType.FastPoint;
+      impacts.XValueType = ChartValueType.String;
+      impacts.YValueType = ChartValueType.Double;
+      impacts.YAxisType = AxisType.Secondary;
+      chart.Series.Add(impacts);
+    }
+
+    protected virtual void UpdateSeries() {
+      int index = 1;
+      Series bestKnown = chart.Series["Alleles of Best Known Solution"];
+      Series others = chart.Series["Other Alleles"];
+      Series qualities = chart.Series["Average Solution Qualities"];
+      Series impacts = chart.Series["Average Impact"];
+      bestKnown.Points.Clear();
+      others.Points.Clear();
+      qualities.Points.Clear();
+      impacts.Points.Clear();
+
+      if (!invisibleSeries.Contains(qualities) && !invisibleSeries.Contains(impacts))
+        chart.ChartAreas["Default"].AxisY2.Title = "Average Solution Quality / Average Impact";
+      else if (!invisibleSeries.Contains(qualities))
+        chart.ChartAreas["Default"].AxisY2.Title = "Average Solution Quality";
+      else if (!invisibleSeries.Contains(impacts))
+        chart.ChartAreas["Default"].AxisY2.Title = "Average Impact";
+
+      if (!invisibleSeries.Contains(bestKnown)) {
+        foreach (AlleleFrequency af in Content.Where(x => x.ContainedInBestKnownSolution).OrderBy(x => x.Id)) {
+          bestKnown.Points.Add(CreateDataPoint(index, af.Frequency, af));
+          if (!invisibleSeries.Contains(qualities)) qualities.Points.Add(CreateDataPoint(index, af.AverageSolutionQuality, af));
+          if (!invisibleSeries.Contains(impacts)) impacts.Points.Add(CreateDataPoint(index, af.AverageImpact, af));
+          index++;
+        }
+      }
+      if (!invisibleSeries.Contains(others)) {
+        foreach (AlleleFrequency af in Content.Where(x => !x.ContainedInBestKnownSolution).OrderBy(x => x.Id)) {
+          others.Points.Add(CreateDataPoint(index, af.Frequency, af));
+          if (!invisibleSeries.Contains(qualities)) qualities.Points.Add(CreateDataPoint(index, af.AverageSolutionQuality, af));
+          if (!invisibleSeries.Contains(impacts)) impacts.Points.Add(CreateDataPoint(index, af.AverageImpact, af));
+          index++;
+        }
+      }
+    }
+
+    protected virtual DataPoint CreateDataPoint(int index, double value, AlleleFrequency af) {
+      string nl = Environment.NewLine;
+      DataPoint p = new DataPoint(index, value);
+      p.ToolTip = string.Format("Id: {0}" + nl +
+                                "Relative Frequency: {1}" + nl +
+                                "Average Solution Quality: {2}" + nl +
+                                "Average Impact: {3}" + nl +
+                                "Contained in Best Known Solution: {4}" + nl +
+                                "Contained in Best Solution: {5}",
+                                af.Id, af.Frequency, af.AverageSolutionQuality, af.AverageImpact, af.ContainedInBestKnownSolution, af.ContainedInBestSolution);
+      p.IsEmpty = value == 0;
+      return p;
+    }
+
+    #region Chart Events
+    protected virtual void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        ToggleSeriesVisible(result.Series);
+      }
+    }
+
+    protected virtual void ToggleSeriesVisible(Series series) {
+      if (!invisibleSeries.Contains(series))
+        invisibleSeries.Add(series);
+      else
+        invisibleSeries.Remove(series);
+      UpdateSeries();
+    }
+
+    protected virtual void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+    }
+
+    protected virtual void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = invisibleSeries.Contains(series);
+          foreach (LegendCell cell in legendItem.Cells) {
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+          }
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyView.Designer.cs	(revision 15719)
@@ -0,0 +1,216 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class AlleleFrequencyView {
+    /// <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) {
+        if (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();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      this.idLabel = new System.Windows.Forms.Label();
+      this.idTextBox = new System.Windows.Forms.TextBox();
+      this.frequencyTextBox = new System.Windows.Forms.TextBox();
+      this.averageImpactTextBox = new System.Windows.Forms.TextBox();
+      this.averageSolutionQualityTextBox = new System.Windows.Forms.TextBox();
+      this.frequencyLabel = new System.Windows.Forms.Label();
+      this.averageImpactLabel = new System.Windows.Forms.Label();
+      this.averageSolutionQualityLabel = new System.Windows.Forms.Label();
+      this.containedInBestKnownSolutionLabel = new System.Windows.Forms.Label();
+      this.containedInBestSolutionLabel = new System.Windows.Forms.Label();
+      this.containedInBestKnownSolutionCheckBox = new System.Windows.Forms.CheckBox();
+      this.containedInBestSolutionCheckBox = new System.Windows.Forms.CheckBox();
+      this.SuspendLayout();
+      // 
+      // idLabel
+      // 
+      this.idLabel.AutoSize = true;
+      this.idLabel.Location = new System.Drawing.Point(3, 3);
+      this.idLabel.Name = "idLabel";
+      this.idLabel.Size = new System.Drawing.Size(19, 13);
+      this.idLabel.TabIndex = 0;
+      this.idLabel.Text = "&Id:";
+      // 
+      // idTextBox
+      // 
+      this.idTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.idTextBox.Location = new System.Drawing.Point(179, 0);
+      this.idTextBox.Name = "idTextBox";
+      this.idTextBox.ReadOnly = true;
+      this.idTextBox.Size = new System.Drawing.Size(188, 20);
+      this.idTextBox.TabIndex = 1;
+      // 
+      // frequencyTextBox
+      // 
+      this.frequencyTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.frequencyTextBox.Location = new System.Drawing.Point(179, 26);
+      this.frequencyTextBox.Name = "frequencyTextBox";
+      this.frequencyTextBox.ReadOnly = true;
+      this.frequencyTextBox.Size = new System.Drawing.Size(188, 20);
+      this.frequencyTextBox.TabIndex = 3;
+      // 
+      // averageImpactTextBox
+      // 
+      this.averageImpactTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.averageImpactTextBox.Location = new System.Drawing.Point(179, 52);
+      this.averageImpactTextBox.Name = "averageImpactTextBox";
+      this.averageImpactTextBox.ReadOnly = true;
+      this.averageImpactTextBox.Size = new System.Drawing.Size(188, 20);
+      this.averageImpactTextBox.TabIndex = 5;
+      // 
+      // averageSolutionQualityTextBox
+      // 
+      this.averageSolutionQualityTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.averageSolutionQualityTextBox.Location = new System.Drawing.Point(179, 78);
+      this.averageSolutionQualityTextBox.Name = "averageSolutionQualityTextBox";
+      this.averageSolutionQualityTextBox.ReadOnly = true;
+      this.averageSolutionQualityTextBox.Size = new System.Drawing.Size(188, 20);
+      this.averageSolutionQualityTextBox.TabIndex = 7;
+      // 
+      // frequencyLabel
+      // 
+      this.frequencyLabel.AutoSize = true;
+      this.frequencyLabel.Location = new System.Drawing.Point(3, 29);
+      this.frequencyLabel.Name = "frequencyLabel";
+      this.frequencyLabel.Size = new System.Drawing.Size(60, 13);
+      this.frequencyLabel.TabIndex = 2;
+      this.frequencyLabel.Text = "&Frequency:";
+      // 
+      // averageImpactLabel
+      // 
+      this.averageImpactLabel.AutoSize = true;
+      this.averageImpactLabel.Location = new System.Drawing.Point(3, 55);
+      this.averageImpactLabel.Name = "averageImpactLabel";
+      this.averageImpactLabel.Size = new System.Drawing.Size(85, 13);
+      this.averageImpactLabel.TabIndex = 4;
+      this.averageImpactLabel.Text = "Average &Impact:";
+      // 
+      // averageSolutionQualityLabel
+      // 
+      this.averageSolutionQualityLabel.AutoSize = true;
+      this.averageSolutionQualityLabel.Location = new System.Drawing.Point(3, 81);
+      this.averageSolutionQualityLabel.Name = "averageSolutionQualityLabel";
+      this.averageSolutionQualityLabel.Size = new System.Drawing.Size(126, 13);
+      this.averageSolutionQualityLabel.TabIndex = 6;
+      this.averageSolutionQualityLabel.Text = "Average Solution &Quality:";
+      // 
+      // containedInBestKnownSolutionLabel
+      // 
+      this.containedInBestKnownSolutionLabel.AutoSize = true;
+      this.containedInBestKnownSolutionLabel.Location = new System.Drawing.Point(3, 104);
+      this.containedInBestKnownSolutionLabel.Name = "containedInBestKnownSolutionLabel";
+      this.containedInBestKnownSolutionLabel.Size = new System.Drawing.Size(170, 13);
+      this.containedInBestKnownSolutionLabel.TabIndex = 8;
+      this.containedInBestKnownSolutionLabel.Text = "Contained in Best &Known Solution:";
+      // 
+      // containedInBestSolutionLabel
+      // 
+      this.containedInBestSolutionLabel.AutoSize = true;
+      this.containedInBestSolutionLabel.Location = new System.Drawing.Point(3, 124);
+      this.containedInBestSolutionLabel.Name = "containedInBestSolutionLabel";
+      this.containedInBestSolutionLabel.Size = new System.Drawing.Size(134, 13);
+      this.containedInBestSolutionLabel.TabIndex = 10;
+      this.containedInBestSolutionLabel.Text = "Contained in &Best Solution:";
+      // 
+      // containedInBestKnownSolutionCheckBox
+      // 
+      this.containedInBestKnownSolutionCheckBox.AutoSize = true;
+      this.containedInBestKnownSolutionCheckBox.Enabled = false;
+      this.containedInBestKnownSolutionCheckBox.Location = new System.Drawing.Point(179, 104);
+      this.containedInBestKnownSolutionCheckBox.Name = "containedInBestKnownSolutionCheckBox";
+      this.containedInBestKnownSolutionCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.containedInBestKnownSolutionCheckBox.TabIndex = 9;
+      this.containedInBestKnownSolutionCheckBox.UseVisualStyleBackColor = true;
+      // 
+      // containedInBestSolutionCheckBox
+      // 
+      this.containedInBestSolutionCheckBox.AutoSize = true;
+      this.containedInBestSolutionCheckBox.Enabled = false;
+      this.containedInBestSolutionCheckBox.Location = new System.Drawing.Point(179, 124);
+      this.containedInBestSolutionCheckBox.Name = "containedInBestSolutionCheckBox";
+      this.containedInBestSolutionCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.containedInBestSolutionCheckBox.TabIndex = 11;
+      this.containedInBestSolutionCheckBox.UseVisualStyleBackColor = true;
+      // 
+      // AlleleFrequencyView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.containedInBestSolutionCheckBox);
+      this.Controls.Add(this.containedInBestKnownSolutionCheckBox);
+      this.Controls.Add(this.averageSolutionQualityTextBox);
+      this.Controls.Add(this.averageImpactTextBox);
+      this.Controls.Add(this.frequencyTextBox);
+      this.Controls.Add(this.idTextBox);
+      this.Controls.Add(this.containedInBestSolutionLabel);
+      this.Controls.Add(this.containedInBestKnownSolutionLabel);
+      this.Controls.Add(this.averageSolutionQualityLabel);
+      this.Controls.Add(this.averageImpactLabel);
+      this.Controls.Add(this.frequencyLabel);
+      this.Controls.Add(this.idLabel);
+      this.Name = "AlleleFrequencyView";
+      this.Size = new System.Drawing.Size(367, 151);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    protected System.Windows.Forms.ToolTip toolTip;
+    protected System.Windows.Forms.Label idLabel;
+    protected System.Windows.Forms.TextBox idTextBox;
+    protected System.Windows.Forms.TextBox frequencyTextBox;
+    protected System.Windows.Forms.TextBox averageImpactTextBox;
+    protected System.Windows.Forms.TextBox averageSolutionQualityTextBox;
+    protected System.Windows.Forms.Label frequencyLabel;
+    protected System.Windows.Forms.Label averageImpactLabel;
+    protected System.Windows.Forms.Label averageSolutionQualityLabel;
+    protected System.Windows.Forms.Label containedInBestKnownSolutionLabel;
+    protected System.Windows.Forms.Label containedInBestSolutionLabel;
+    protected System.Windows.Forms.CheckBox containedInBestKnownSolutionCheckBox;
+    protected System.Windows.Forms.CheckBox containedInBestSolutionCheckBox;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyView.cs	(revision 15719)
@@ -0,0 +1,66 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("AlleleFrequency View")]
+  [Content(typeof(AlleleFrequency), true)]
+  public partial class AlleleFrequencyView : ItemView {
+    public new AlleleFrequency Content {
+      get { return (AlleleFrequency)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public AlleleFrequencyView() {
+      InitializeComponent();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        idTextBox.Text = string.Empty;
+        frequencyTextBox.Text = string.Empty;
+        averageImpactTextBox.Text = string.Empty;
+        averageSolutionQualityTextBox.Text = string.Empty;
+        containedInBestKnownSolutionCheckBox.Checked = false;
+        containedInBestSolutionCheckBox.Checked = false;
+      } else {
+        idTextBox.Text = Content.Id;
+        frequencyTextBox.Text = Content.Frequency.ToString();
+        averageImpactTextBox.Text = Content.AverageImpact.ToString();
+        averageSolutionQualityTextBox.Text = Content.AverageSolutionQuality.ToString();
+        containedInBestKnownSolutionCheckBox.Checked = Content.ContainedInBestKnownSolution;
+        containedInBestSolutionCheckBox.Checked = Content.ContainedInBestSolution;
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      idTextBox.Enabled = Content != null;
+      frequencyTextBox.Enabled = Content != null;
+      averageImpactTextBox.Enabled = Content != null;
+      averageSolutionQualityTextBox.Enabled = Content != null;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs	(revision 15719)
@@ -0,0 +1,445 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class DataRowVisualPropertiesControl {
+    /// <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.chartTypeComboBox = new System.Windows.Forms.ComboBox();
+      this.colorDialog = new System.Windows.Forms.ColorDialog();
+      this.colorButton = new System.Windows.Forms.Button();
+      this.startIndexZeroCheckBox = new System.Windows.Forms.CheckBox();
+      this.label1 = new System.Windows.Forms.Label();
+      this.label2 = new System.Windows.Forms.Label();
+      this.commonGroupBox = new System.Windows.Forms.GroupBox();
+      this.clearColorButton = new System.Windows.Forms.Button();
+      this.isVisibleInLegendCheckBox = new System.Windows.Forms.CheckBox();
+      this.label10 = new System.Windows.Forms.Label();
+      this.displayNameTextBox = new System.Windows.Forms.TextBox();
+      this.axisGroupBox = new System.Windows.Forms.GroupBox();
+      this.panel2 = new System.Windows.Forms.Panel();
+      this.yAxisSecondaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel1 = new System.Windows.Forms.Panel();
+      this.xAxisPrimaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.label5 = new System.Windows.Forms.Label();
+      this.label6 = new System.Windows.Forms.Label();
+      this.label9 = new System.Windows.Forms.Label();
+      this.lineChartGroupBox = new System.Windows.Forms.GroupBox();
+      this.lineWidthNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label4 = new System.Windows.Forms.Label();
+      this.label7 = new System.Windows.Forms.Label();
+      this.lineStyleComboBox = new System.Windows.Forms.ComboBox();
+      this.label8 = new System.Windows.Forms.Label();
+      this.commonGroupBox.SuspendLayout();
+      this.axisGroupBox.SuspendLayout();
+      this.panel2.SuspendLayout();
+      this.panel1.SuspendLayout();
+      this.lineChartGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.lineWidthNumericUpDown)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chartTypeComboBox
+      // 
+      this.chartTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.chartTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.chartTypeComboBox.FormattingEnabled = true;
+      this.chartTypeComboBox.Location = new System.Drawing.Point(102, 45);
+      this.chartTypeComboBox.Name = "chartTypeComboBox";
+      this.chartTypeComboBox.Size = new System.Drawing.Size(219, 21);
+      this.chartTypeComboBox.TabIndex = 3;
+      this.chartTypeComboBox.SelectedValueChanged += new System.EventHandler(this.chartTypeComboBox_SelectedValueChanged);
+      // 
+      // colorDialog
+      // 
+      this.colorDialog.Color = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(128)))), ((int)(((byte)(255)))));
+      // 
+      // colorButton
+      // 
+      this.colorButton.BackColor = System.Drawing.SystemColors.Control;
+      this.colorButton.Location = new System.Drawing.Point(102, 72);
+      this.colorButton.Name = "colorButton";
+      this.colorButton.Size = new System.Drawing.Size(23, 23);
+      this.colorButton.TabIndex = 5;
+      this.colorButton.UseVisualStyleBackColor = false;
+      this.colorButton.Click += new System.EventHandler(this.colorButton_Click);
+      // 
+      // startIndexZeroCheckBox
+      // 
+      this.startIndexZeroCheckBox.AutoSize = true;
+      this.startIndexZeroCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.startIndexZeroCheckBox.Location = new System.Drawing.Point(81, 46);
+      this.startIndexZeroCheckBox.Name = "startIndexZeroCheckBox";
+      this.startIndexZeroCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.startIndexZeroCheckBox.TabIndex = 3;
+      this.startIndexZeroCheckBox.UseVisualStyleBackColor = true;
+      this.startIndexZeroCheckBox.CheckedChanged += new System.EventHandler(this.startIndexZeroCheckBox_CheckedChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(6, 48);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(34, 13);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "&Type:";
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(6, 77);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(34, 13);
+      this.label2.TabIndex = 4;
+      this.label2.Text = "&Color:";
+      // 
+      // commonGroupBox
+      // 
+      this.commonGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.commonGroupBox.Controls.Add(this.clearColorButton);
+      this.commonGroupBox.Controls.Add(this.isVisibleInLegendCheckBox);
+      this.commonGroupBox.Controls.Add(this.label10);
+      this.commonGroupBox.Controls.Add(this.displayNameTextBox);
+      this.commonGroupBox.Controls.Add(this.axisGroupBox);
+      this.commonGroupBox.Controls.Add(this.colorButton);
+      this.commonGroupBox.Controls.Add(this.label9);
+      this.commonGroupBox.Controls.Add(this.label1);
+      this.commonGroupBox.Controls.Add(this.label2);
+      this.commonGroupBox.Controls.Add(this.chartTypeComboBox);
+      this.commonGroupBox.Location = new System.Drawing.Point(0, 0);
+      this.commonGroupBox.Name = "commonGroupBox";
+      this.commonGroupBox.Size = new System.Drawing.Size(327, 199);
+      this.commonGroupBox.TabIndex = 0;
+      this.commonGroupBox.TabStop = false;
+      this.commonGroupBox.Text = "Common";
+      // 
+      // clearColorButton
+      // 
+      this.clearColorButton.BackColor = System.Drawing.SystemColors.ActiveCaption;
+      this.clearColorButton.Cursor = System.Windows.Forms.Cursors.Default;
+      this.clearColorButton.FlatAppearance.BorderSize = 0;
+      this.clearColorButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+      this.clearColorButton.ForeColor = System.Drawing.Color.Transparent;
+      this.clearColorButton.Location = new System.Drawing.Point(128, 76);
+      this.clearColorButton.Margin = new System.Windows.Forms.Padding(0);
+      this.clearColorButton.Name = "clearColorButton";
+      this.clearColorButton.Size = new System.Drawing.Size(15, 16);
+      this.clearColorButton.TabIndex = 10;
+      this.clearColorButton.TabStop = false;
+      this.clearColorButton.UseVisualStyleBackColor = false;
+      this.clearColorButton.Click += new System.EventHandler(this.clearColorButton_Click);
+      // 
+      // isVisibleInLegendCheckBox
+      // 
+      this.isVisibleInLegendCheckBox.AutoSize = true;
+      this.isVisibleInLegendCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.isVisibleInLegendCheckBox.Location = new System.Drawing.Point(102, 104);
+      this.isVisibleInLegendCheckBox.Name = "isVisibleInLegendCheckBox";
+      this.isVisibleInLegendCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.isVisibleInLegendCheckBox.TabIndex = 8;
+      this.isVisibleInLegendCheckBox.UseVisualStyleBackColor = true;
+      this.isVisibleInLegendCheckBox.CheckedChanged += new System.EventHandler(this.isVisibleInLegendCheckBox_CheckedChanged);
+      // 
+      // label10
+      // 
+      this.label10.AutoSize = true;
+      this.label10.Location = new System.Drawing.Point(6, 104);
+      this.label10.Name = "label10";
+      this.label10.Size = new System.Drawing.Size(90, 13);
+      this.label10.TabIndex = 7;
+      this.label10.Text = "&Visible in Legend:";
+      // 
+      // displayNameTextBox
+      // 
+      this.displayNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.displayNameTextBox.Location = new System.Drawing.Point(102, 19);
+      this.displayNameTextBox.Name = "displayNameTextBox";
+      this.displayNameTextBox.Size = new System.Drawing.Size(219, 20);
+      this.displayNameTextBox.TabIndex = 1;
+      this.displayNameTextBox.Validated += new System.EventHandler(this.displayNameTextBox_Validated);
+      // 
+      // axisGroupBox
+      // 
+      this.axisGroupBox.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)));
+      this.axisGroupBox.Controls.Add(this.panel2);
+      this.axisGroupBox.Controls.Add(this.panel1);
+      this.axisGroupBox.Controls.Add(this.label5);
+      this.axisGroupBox.Controls.Add(this.label6);
+      this.axisGroupBox.Location = new System.Drawing.Point(6, 126);
+      this.axisGroupBox.Name = "axisGroupBox";
+      this.axisGroupBox.Size = new System.Drawing.Size(315, 67);
+      this.axisGroupBox.TabIndex = 6;
+      this.axisGroupBox.TabStop = false;
+      this.axisGroupBox.Text = "Axes";
+      // 
+      // panel2
+      // 
+      this.panel2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.panel2.Controls.Add(this.yAxisSecondaryRadioButton);
+      this.panel2.Controls.Add(this.yAxisPrimaryRadioButton);
+      this.panel2.Location = new System.Drawing.Point(51, 42);
+      this.panel2.Name = "panel2";
+      this.panel2.Size = new System.Drawing.Size(258, 17);
+      this.panel2.TabIndex = 7;
+      // 
+      // yAxisSecondaryRadioButton
+      // 
+      this.yAxisSecondaryRadioButton.AutoSize = true;
+      this.yAxisSecondaryRadioButton.Location = new System.Drawing.Point(65, 0);
+      this.yAxisSecondaryRadioButton.Name = "yAxisSecondaryRadioButton";
+      this.yAxisSecondaryRadioButton.Size = new System.Drawing.Size(76, 17);
+      this.yAxisSecondaryRadioButton.TabIndex = 5;
+      this.yAxisSecondaryRadioButton.TabStop = true;
+      this.yAxisSecondaryRadioButton.Text = "&Secondary";
+      this.yAxisSecondaryRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryRadioButton.CheckedChanged += new System.EventHandler(this.yAxisRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryRadioButton
+      // 
+      this.yAxisPrimaryRadioButton.AutoSize = true;
+      this.yAxisPrimaryRadioButton.Location = new System.Drawing.Point(0, 0);
+      this.yAxisPrimaryRadioButton.Name = "yAxisPrimaryRadioButton";
+      this.yAxisPrimaryRadioButton.Size = new System.Drawing.Size(59, 17);
+      this.yAxisPrimaryRadioButton.TabIndex = 4;
+      this.yAxisPrimaryRadioButton.TabStop = true;
+      this.yAxisPrimaryRadioButton.Text = "&Primary";
+      this.yAxisPrimaryRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryRadioButton.CheckedChanged += new System.EventHandler(this.yAxisRadioButton_CheckedChanged);
+      // 
+      // panel1
+      // 
+      this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.panel1.Controls.Add(this.xAxisPrimaryRadioButton);
+      this.panel1.Controls.Add(this.xAxisSecondaryRadioButton);
+      this.panel1.Location = new System.Drawing.Point(51, 19);
+      this.panel1.Name = "panel1";
+      this.panel1.Size = new System.Drawing.Size(258, 17);
+      this.panel1.TabIndex = 6;
+      // 
+      // xAxisPrimaryRadioButton
+      // 
+      this.xAxisPrimaryRadioButton.AutoSize = true;
+      this.xAxisPrimaryRadioButton.Location = new System.Drawing.Point(0, 0);
+      this.xAxisPrimaryRadioButton.Name = "xAxisPrimaryRadioButton";
+      this.xAxisPrimaryRadioButton.Size = new System.Drawing.Size(59, 17);
+      this.xAxisPrimaryRadioButton.TabIndex = 1;
+      this.xAxisPrimaryRadioButton.TabStop = true;
+      this.xAxisPrimaryRadioButton.Text = "&Primary";
+      this.xAxisPrimaryRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryRadioButton.CheckedChanged += new System.EventHandler(this.xAxisRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryRadioButton
+      // 
+      this.xAxisSecondaryRadioButton.AutoSize = true;
+      this.xAxisSecondaryRadioButton.Location = new System.Drawing.Point(65, 0);
+      this.xAxisSecondaryRadioButton.Name = "xAxisSecondaryRadioButton";
+      this.xAxisSecondaryRadioButton.Size = new System.Drawing.Size(76, 17);
+      this.xAxisSecondaryRadioButton.TabIndex = 2;
+      this.xAxisSecondaryRadioButton.TabStop = true;
+      this.xAxisSecondaryRadioButton.Text = "&Secondary";
+      this.xAxisSecondaryRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryRadioButton.CheckedChanged += new System.EventHandler(this.xAxisRadioButton_CheckedChanged);
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(6, 44);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(39, 13);
+      this.label5.TabIndex = 3;
+      this.label5.Text = "&Y-Axis:";
+      // 
+      // label6
+      // 
+      this.label6.AutoSize = true;
+      this.label6.Location = new System.Drawing.Point(6, 21);
+      this.label6.Name = "label6";
+      this.label6.Size = new System.Drawing.Size(39, 13);
+      this.label6.TabIndex = 0;
+      this.label6.Text = "&X-Axis:";
+      // 
+      // label9
+      // 
+      this.label9.AutoSize = true;
+      this.label9.Location = new System.Drawing.Point(6, 22);
+      this.label9.Name = "label9";
+      this.label9.Size = new System.Drawing.Size(38, 13);
+      this.label9.TabIndex = 0;
+      this.label9.Text = "&Name:";
+      // 
+      // lineChartGroupBox
+      // 
+      this.lineChartGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.lineChartGroupBox.Controls.Add(this.lineWidthNumericUpDown);
+      this.lineChartGroupBox.Controls.Add(this.label4);
+      this.lineChartGroupBox.Controls.Add(this.startIndexZeroCheckBox);
+      this.lineChartGroupBox.Controls.Add(this.label7);
+      this.lineChartGroupBox.Controls.Add(this.lineStyleComboBox);
+      this.lineChartGroupBox.Controls.Add(this.label8);
+      this.lineChartGroupBox.Location = new System.Drawing.Point(0, 205);
+      this.lineChartGroupBox.Name = "lineChartGroupBox";
+      this.lineChartGroupBox.Size = new System.Drawing.Size(327, 94);
+      this.lineChartGroupBox.TabIndex = 1;
+      this.lineChartGroupBox.TabStop = false;
+      this.lineChartGroupBox.Text = "Line Properties";
+      // 
+      // lineWidthNumericUpDown
+      // 
+      this.lineWidthNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.lineWidthNumericUpDown.Location = new System.Drawing.Point(82, 66);
+      this.lineWidthNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.lineWidthNumericUpDown.Name = "lineWidthNumericUpDown";
+      this.lineWidthNumericUpDown.Size = new System.Drawing.Size(239, 20);
+      this.lineWidthNumericUpDown.TabIndex = 5;
+      this.lineWidthNumericUpDown.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.lineWidthNumericUpDown.ValueChanged += new System.EventHandler(this.lineWidthNumericUpDown_ValueChanged);
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(6, 68);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(38, 13);
+      this.label4.TabIndex = 4;
+      this.label4.Text = "&Width:";
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(6, 46);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(70, 13);
+      this.label7.TabIndex = 2;
+      this.label7.Text = "Start &Index 0:";
+      // 
+      // lineStyleComboBox
+      // 
+      this.lineStyleComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.lineStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.lineStyleComboBox.FormattingEnabled = true;
+      this.lineStyleComboBox.Location = new System.Drawing.Point(82, 19);
+      this.lineStyleComboBox.Name = "lineStyleComboBox";
+      this.lineStyleComboBox.Size = new System.Drawing.Size(239, 21);
+      this.lineStyleComboBox.TabIndex = 1;
+      this.lineStyleComboBox.SelectedValueChanged += new System.EventHandler(this.lineStyleComboBox_SelectedValueChanged);
+      // 
+      // label8
+      // 
+      this.label8.AutoSize = true;
+      this.label8.Location = new System.Drawing.Point(6, 22);
+      this.label8.Name = "label8";
+      this.label8.Size = new System.Drawing.Size(33, 13);
+      this.label8.TabIndex = 0;
+      this.label8.Text = "&Style:";
+      // 
+      // DataRowVisualPropertiesControl
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.lineChartGroupBox);
+      this.Controls.Add(this.commonGroupBox);
+      this.Name = "DataRowVisualPropertiesControl";
+      this.Size = new System.Drawing.Size(327, 300);
+      this.commonGroupBox.ResumeLayout(false);
+      this.commonGroupBox.PerformLayout();
+      this.axisGroupBox.ResumeLayout(false);
+      this.axisGroupBox.PerformLayout();
+      this.panel2.ResumeLayout(false);
+      this.panel2.PerformLayout();
+      this.panel1.ResumeLayout(false);
+      this.panel1.PerformLayout();
+      this.lineChartGroupBox.ResumeLayout(false);
+      this.lineChartGroupBox.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.lineWidthNumericUpDown)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.ComboBox chartTypeComboBox;
+    private System.Windows.Forms.ColorDialog colorDialog;
+    private System.Windows.Forms.Button colorButton;
+    private System.Windows.Forms.CheckBox startIndexZeroCheckBox;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.GroupBox commonGroupBox;
+    private System.Windows.Forms.RadioButton xAxisSecondaryRadioButton;
+    private System.Windows.Forms.RadioButton yAxisSecondaryRadioButton;
+    private System.Windows.Forms.RadioButton xAxisPrimaryRadioButton;
+    private System.Windows.Forms.RadioButton yAxisPrimaryRadioButton;
+    private System.Windows.Forms.Label label6;
+    private System.Windows.Forms.GroupBox lineChartGroupBox;
+    private System.Windows.Forms.NumericUpDown lineWidthNumericUpDown;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.ComboBox lineStyleComboBox;
+    private System.Windows.Forms.Label label8;
+    private System.Windows.Forms.Label label5;
+    private System.Windows.Forms.GroupBox axisGroupBox;
+    private System.Windows.Forms.TextBox displayNameTextBox;
+    private System.Windows.Forms.Label label9;
+    private System.Windows.Forms.Panel panel2;
+    private System.Windows.Forms.Panel panel1;
+    private System.Windows.Forms.Label label10;
+    private System.Windows.Forms.CheckBox isVisibleInLegendCheckBox;
+    private System.Windows.Forms.Button clearColorButton;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs	(revision 15719)
@@ -0,0 +1,191 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.Common.Resources;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("DataRow Visual Properties")]
+  public partial class DataRowVisualPropertiesControl : UserControl {
+    protected bool SuppressEvents { get; set; }
+
+    private DataRowVisualProperties content;
+    public DataRowVisualProperties Content {
+      get { return content; }
+      set {
+        bool changed = (value != content);
+        content = value;
+        if (changed) OnContentChanged();
+      }
+    }
+
+    public DataRowVisualPropertiesControl() {
+      InitializeComponent();
+      chartTypeComboBox.DataSource = Enum.GetValues(typeof(DataRowVisualProperties.DataRowChartType));
+      lineStyleComboBox.DataSource = Enum.GetValues(typeof(DataRowVisualProperties.DataRowLineStyle));
+      clearColorButton.BackColor = Color.Transparent;
+      clearColorButton.BackgroundImage = VSImageLibrary.Delete;
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void OnContentChanged() {
+      SuppressEvents = true;
+      try {
+        if (Content == null) {
+          chartTypeComboBox.SelectedIndex = -1;
+          colorButton.BackColor = SystemColors.Control;
+          colorButton.Text = "?";
+          yAxisPrimaryRadioButton.Checked = false;
+          yAxisSecondaryRadioButton.Checked = false;
+          xAxisPrimaryRadioButton.Checked = false;
+          xAxisSecondaryRadioButton.Checked = false;
+          lineStyleComboBox.SelectedIndex = -1;
+          startIndexZeroCheckBox.Checked = false;
+          lineWidthNumericUpDown.Value = 1;
+          displayNameTextBox.Text = String.Empty;
+        } else {
+          chartTypeComboBox.SelectedItem = Content.ChartType;
+          if (Content.Color.IsEmpty) {
+            colorButton.BackColor = SystemColors.Control;
+            colorButton.Text = "?";
+          } else {
+            colorButton.BackColor = Content.Color;
+            colorButton.Text = String.Empty;
+          }
+          yAxisPrimaryRadioButton.Checked = !Content.SecondYAxis;
+          yAxisSecondaryRadioButton.Checked = Content.SecondYAxis;
+          xAxisPrimaryRadioButton.Checked = !Content.SecondXAxis;
+          xAxisSecondaryRadioButton.Checked = Content.SecondXAxis;
+          lineStyleComboBox.SelectedItem = Content.LineStyle;
+          startIndexZeroCheckBox.Checked = Content.StartIndexZero;
+          if (Content.LineWidth < lineWidthNumericUpDown.Minimum)
+            lineWidthNumericUpDown.Value = lineWidthNumericUpDown.Minimum;
+          else if (Content.LineWidth > lineWidthNumericUpDown.Maximum)
+            lineWidthNumericUpDown.Value = lineWidthNumericUpDown.Maximum;
+          else lineWidthNumericUpDown.Value = Content.LineWidth;
+          displayNameTextBox.Text = Content.DisplayName;
+          isVisibleInLegendCheckBox.Checked = Content.IsVisibleInLegend;
+        }
+      } finally { SuppressEvents = false; }
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void SetEnabledStateOfControls() {
+      commonGroupBox.Enabled = Content != null;
+      clearColorButton.Visible = Content != null && !Content.Color.IsEmpty;
+      lineChartGroupBox.Enabled = Content != null && Content.ChartType == DataRowVisualProperties.DataRowChartType.Line;
+      isVisibleInLegendCheckBox.Enabled = Content != null;
+    }
+
+    #region Event Handlers
+    private void chartTypeComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        DataRowVisualProperties.DataRowChartType selected = (DataRowVisualProperties.DataRowChartType)chartTypeComboBox.SelectedValue;
+        Content.ChartType = selected;
+        if (Content.ChartType != selected) {
+          MessageBox.Show("There may be incompatibilities with other series or the data is not suited to be displayed as " + selected.ToString() + ".", "Failed to set type to " + selected.ToString());
+          SuppressEvents = true;
+          try {
+            chartTypeComboBox.SelectedItem = Content.ChartType;
+          } finally { SuppressEvents = false; }
+        }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void colorButton_Click(object sender, EventArgs e) {
+      if (colorDialog.ShowDialog() == DialogResult.OK) {
+        Content.Color = colorDialog.Color;
+        colorButton.BackColor = Content.Color;
+        colorButton.Text = String.Empty;
+        clearColorButton.Visible = true;
+      }
+    }
+
+    private void clearColorButton_Click(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.Color = Color.Empty;
+          colorButton.BackColor = SystemColors.Control;
+          colorButton.Text = "?";
+          clearColorButton.Visible = false;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void yAxisRadioButton_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxis = yAxisSecondaryRadioButton.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void xAxisRadioButton_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxis = xAxisSecondaryRadioButton.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void lineStyleComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.LineStyle = (DataRowVisualProperties.DataRowLineStyle)lineStyleComboBox.SelectedValue;
+      }
+    }
+
+    private void startIndexZeroCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.StartIndexZero = startIndexZeroCheckBox.Checked;
+      }
+    }
+
+    private void lineWidthNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.LineWidth = (int)lineWidthNumericUpDown.Value;
+      }
+    }
+
+    private void displayNameTextBox_Validated(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.DisplayName = displayNameTextBox.Text;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void isVisibleInLegendCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.IsVisibleInLegend = isVisibleInLegendCheckBox.Checked;
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.Designer.cs	(revision 15719)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class DataTableHistoryView {
+    /// <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) {
+        if (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() {
+      components = new System.ComponentModel.Container();
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+    }
+
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs	(revision 15719)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("DataTableHistory View")]
+  [Content(typeof(DataTableHistory), true)]
+  public partial class DataTableHistoryView : MovieView<DataTable>, IConfigureableView {
+    public DataTableHistoryView() {
+      InitializeComponent();
+      itemsGroupBox.Text = "Data Table";
+    }
+
+    public void ShowConfiguration() {
+      DataTable current = viewHost.Content as DataTable;
+      if (current == null) return;
+      using (DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(current)) {
+        if (dialog.ShowDialog(this) != DialogResult.OK) return;
+        HashSet<string> modifiedDisplayNames = new HashSet<string>(dialog.RowsWithModifiedDisplayNames);
+        foreach (DataTable dt in Content) {
+          if (current == dt) continue;
+          dt.VisualProperties = (DataTableVisualProperties)current.VisualProperties.Clone();
+          foreach (DataRow row in current.Rows) {
+            if (!dt.Rows.ContainsKey(row.Name)) continue;
+            string oldDisplayName = dt.Rows[row.Name].VisualProperties.DisplayName;
+            dt.Rows[row.Name].VisualProperties = (DataRowVisualProperties)row.VisualProperties.Clone();
+            if (!modifiedDisplayNames.Contains(row.Name))
+              dt.Rows[row.Name].VisualProperties.DisplayName = oldDisplayName;
+          }
+        }
+      }
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableView.Designer.cs	(revision 15719)
@@ -0,0 +1,134 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class DataTableView {
+    /// <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) {
+        if (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.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.configureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Location = new System.Drawing.Point(55, 0);
+      this.nameTextBox.Size = new System.Drawing.Size(279, 20);
+      //
+      // infoLabel
+      //
+      this.infoLabel.Location = new System.Drawing.Point(340, 3);
+      // 
+      // chart
+      // 
+      this.chart.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)));
+      this.chart.BorderlineColor = System.Drawing.Color.Black;
+      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
+      chartArea1.AxisX.Minimum = 0D;
+      chartArea1.CursorX.IsUserEnabled = true;
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
+      chartArea1.Name = "Default";
+      this.chart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.LegendItemOrder = System.Windows.Forms.DataVisualization.Charting.LegendItemOrder.ReversedSeriesOrder;
+      legend1.Name = "Default";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(0, 26);
+      this.chart.Name = "chart";
+      series1.ChartArea = "Default";
+      series1.Legend = "Default";
+      series1.Name = "Default";
+      this.chart.Series.Add(series1);
+      this.chart.Size = new System.Drawing.Size(359, 248);
+      this.chart.TabIndex = 3;
+      this.chart.Text = "chart";
+      title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      title1.Name = "Default";
+      title1.Text = "Title";
+      this.chart.Titles.Add(title1);
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // configureToolStripMenuItem
+      // 
+      this.configureToolStripMenuItem.Name = "configureToolStripMenuItem";
+      this.configureToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
+      this.configureToolStripMenuItem.Text = "Configure Chart...";
+      this.configureToolStripMenuItem.Click += new System.EventHandler(this.configureToolStripMenuItem_Click);
+      // 
+      // DataTableView
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.chart);
+      this.Name = "DataTableView";
+      this.Size = new System.Drawing.Size(359, 274);
+      this.Controls.SetChildIndex(this.chart, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+    private System.Windows.Forms.ToolStripMenuItem configureToolStripMenuItem;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 15719)
@@ -0,0 +1,752 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Collections;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("DataTable View")]
+  [Content(typeof(DataTable), true)]
+  public partial class DataTableView : NamedItemView, IConfigureableView {
+    protected List<Series> invisibleSeries;
+    protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable;
+    protected bool showChartOnly = false;
+
+    public new DataTable Content {
+      get { return (DataTable)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public bool ShowChartOnly {
+      get { return showChartOnly; }
+      set {
+        if (showChartOnly != value) {
+          showChartOnly = value;
+          UpdateControlsVisibility();
+        }
+      }
+    }
+
+    public DataTableView() {
+      InitializeComponent();
+      valuesRowsTable = new Dictionary<IObservableList<double>, DataRow>();
+      invisibleSeries = new List<Series>();
+      chart.CustomizeAllChartAreas();
+      chart.ChartAreas[0].CursorX.Interval = 1;
+      chart.ContextMenuStrip.Items.Add(configureToolStripMenuItem);
+    }
+
+    #region Event Handler Registration
+    protected override void DeregisterContentEvents() {
+      foreach (DataRow row in Content.Rows)
+        DeregisterDataRowEvents(row);
+      Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);
+      Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded);
+      Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsRemoved);
+      Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced);
+      Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset);
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
+      Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded);
+      Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsRemoved);
+      Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced);
+      Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset);
+    }
+
+    protected virtual void RegisterDataRowEvents(DataRow row) {
+      row.NameChanged += new EventHandler(Row_NameChanged);
+      row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
+      valuesRowsTable.Add(row.Values, row);
+      row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
+      row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
+      row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
+      row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
+    }
+    protected virtual void DeregisterDataRowEvents(DataRow row) {
+      row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
+      row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
+      row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
+      row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
+      valuesRowsTable.Remove(row.Values);
+      row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
+      row.NameChanged -= new EventHandler(Row_NameChanged);
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      invisibleSeries.Clear();
+      chart.Titles[0].Text = string.Empty;
+      chart.ChartAreas[0].AxisX.Title = string.Empty;
+      chart.ChartAreas[0].AxisY.Title = string.Empty;
+      chart.ChartAreas[0].AxisY2.Title = string.Empty;
+      chart.Series.Clear();
+      if (Content != null) {
+        chart.Titles[0].Text = Content.Name;
+        chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.Name);
+        AddDataRows(Content.Rows);
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]);
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      chart.Enabled = Content != null;
+    }
+
+    public void ShowConfiguration() {
+      if (Content != null) {
+        using (var dialog = new DataTableVisualPropertiesDialog(Content)) {
+          dialog.ShowDialog(this);
+        }
+      } else MessageBox.Show("Nothing to configure.");
+    }
+
+    protected void UpdateControlsVisibility() {
+      if (InvokeRequired)
+        Invoke(new Action(UpdateControlsVisibility));
+      else {
+        foreach (Control c in Controls) {
+          if (c == chart) continue;
+          c.Visible = !showChartOnly;
+        }
+        chart.Dock = showChartOnly ? DockStyle.Fill : DockStyle.None;
+      }
+    }
+
+    protected virtual void AddDataRows(IEnumerable<DataRow> rows) {
+      foreach (var row in rows) {
+        RegisterDataRowEvents(row);
+        var series = new Series(row.Name) {
+          Tag = row
+        };
+        if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+        else series.LegendText = row.Name;
+        ConfigureSeries(series, row);
+        FillSeriesWithRowValues(series, row);
+        chart.Series.Add(series);
+      }
+      ConfigureChartArea(chart.ChartAreas[0]);
+      RecalculateAxesScale(chart.ChartAreas[0]);
+      UpdateYCursorInterval();
+      UpdateHistogramTransparency();
+    }
+
+    protected virtual void RemoveDataRows(IEnumerable<DataRow> rows) {
+      foreach (var row in rows) {
+        DeregisterDataRowEvents(row);
+        Series series = chart.Series[row.Name];
+        chart.Series.Remove(series);
+        if (invisibleSeries.Contains(series))
+          invisibleSeries.Remove(series);
+      }
+      RecalculateAxesScale(chart.ChartAreas[0]);
+    }
+
+    private void ConfigureSeries(Series series, DataRow row) {
+      RemoveCustomPropertyIfExists(series, "PointWidth");
+      series.BorderWidth = 1;
+      series.BorderDashStyle = ChartDashStyle.Solid;
+      series.BorderColor = Color.Empty;
+
+      if (row.VisualProperties.Color != Color.Empty)
+        series.Color = row.VisualProperties.Color;
+      else series.Color = Color.Empty;
+      series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;
+
+      switch (row.VisualProperties.ChartType) {
+        case DataRowVisualProperties.DataRowChartType.Line:
+          series.ChartType = SeriesChartType.FastLine;
+          series.BorderWidth = row.VisualProperties.LineWidth;
+          series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
+          break;
+        case DataRowVisualProperties.DataRowChartType.Bars:
+          // Bar is incompatible with anything but Bar and StackedBar*
+          if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100))
+            series.ChartType = SeriesChartType.Bar;
+          else {
+            series.ChartType = SeriesChartType.FastPoint; //default
+            row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          }
+          break;
+        case DataRowVisualProperties.DataRowChartType.Columns:
+          series.ChartType = SeriesChartType.Column;
+          break;
+        case DataRowVisualProperties.DataRowChartType.Points:
+          series.ChartType = SeriesChartType.FastPoint;
+          break;
+        case DataRowVisualProperties.DataRowChartType.Histogram:
+          bool stacked = Content.VisualProperties.HistogramAggregation == DataTableVisualProperties.DataTableHistogramAggregation.Stacked;
+          series.ChartType = stacked ? SeriesChartType.StackedColumn : SeriesChartType.Column;
+          bool sideBySide = Content.VisualProperties.HistogramAggregation == DataTableVisualProperties.DataTableHistogramAggregation.SideBySide;
+          series.SetCustomProperty("DrawSideBySide", sideBySide ? "True" : "False");
+          series.SetCustomProperty("PointWidth", "1");
+          if (!series.Color.IsEmpty && series.Color.GetBrightness() < 0.25)
+            series.BorderColor = Color.White;
+          else series.BorderColor = Color.Black;
+          break;
+        case DataRowVisualProperties.DataRowChartType.StepLine:
+          series.ChartType = SeriesChartType.StepLine;
+          series.BorderWidth = row.VisualProperties.LineWidth;
+          series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
+          break;
+        default:
+          series.ChartType = SeriesChartType.FastPoint;
+          break;
+      }
+      series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
+      series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary;
+      if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+      else series.LegendText = row.Name;
+
+      string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
+                      ? "X"
+                      : Content.VisualProperties.XAxisTitle;
+      string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
+                            ? "Y"
+                            : Content.VisualProperties.YAxisTitle;
+      series.ToolTip =
+        series.LegendText + Environment.NewLine +
+        xAxisTitle + " = " + "#INDEX," + Environment.NewLine +
+        yAxisTitle + " = " + "#VAL";
+    }
+
+    private void ConfigureChartArea(ChartArea area) {
+      if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
+      if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
+      chart.Titles[0].Text = Content.VisualProperties.Title;
+      chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.VisualProperties.Title);
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX.Title = Content.VisualProperties.XAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX2.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX2.Title = Content.VisualProperties.SecondXAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY.Title = Content.VisualProperties.YAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY2.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY2.Title = Content.VisualProperties.SecondYAxisTitle;
+
+      area.AxisX.IsLogarithmic = Content.VisualProperties.XAxisLogScale;
+      area.AxisX2.IsLogarithmic = Content.VisualProperties.SecondXAxisLogScale;
+      area.AxisY.IsLogarithmic = Content.VisualProperties.YAxisLogScale;
+      area.AxisY2.IsLogarithmic = Content.VisualProperties.SecondYAxisLogScale;
+    }
+
+    private void RecalculateAxesScale(ChartArea area) {
+      // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds
+      foreach (Axis a in area.Axes) {
+        a.Minimum = double.NaN;
+        a.Maximum = double.NaN;
+      }
+      area.RecalculateAxesScale();
+      area.AxisX.IsMarginVisible = false;
+      area.AxisX2.IsMarginVisible = false;
+
+      if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
+      if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
+      if (!Content.VisualProperties.SecondXAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMinimumFixedValue)) area.AxisX2.Minimum = Content.VisualProperties.SecondXAxisMinimumFixedValue;
+      if (!Content.VisualProperties.SecondXAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMaximumFixedValue)) area.AxisX2.Maximum = Content.VisualProperties.SecondXAxisMaximumFixedValue;
+      if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
+      if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
+      if (!Content.VisualProperties.SecondYAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMinimumFixedValue)) area.AxisY2.Minimum = Content.VisualProperties.SecondYAxisMinimumFixedValue;
+      if (!Content.VisualProperties.SecondYAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMaximumFixedValue)) area.AxisY2.Maximum = Content.VisualProperties.SecondYAxisMaximumFixedValue;
+      if (area.AxisX.Minimum >= area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1;
+      if (area.AxisX2.Minimum >= area.AxisX2.Maximum) area.AxisX2.Maximum = area.AxisX2.Minimum + 1;
+      if (area.AxisY.Minimum >= area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1;
+      if (area.AxisY2.Minimum >= area.AxisY2.Maximum) area.AxisY2.Maximum = area.AxisY2.Minimum + 1;
+    }
+
+    protected virtual void UpdateYCursorInterval() {
+      double interestingValuesRange = (
+        from series in chart.Series
+        where series.Enabled
+        let values = (from point in series.Points
+                      where !point.IsEmpty
+                      select point.YValues[0]).DefaultIfEmpty(1.0)
+        let range = values.Max() - values.Min()
+        where range > 0.0
+        select range
+        ).DefaultIfEmpty(1.0).Min();
+
+      double digits = (int)Math.Log10(interestingValuesRange) - 3;
+      double yZoomInterval = Math.Pow(10, digits);
+      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
+    }
+
+    protected void UpdateHistogramTransparency() {
+      if (Content.Rows.Any(r => RequiresTransparency(r) && r.VisualProperties.Color.IsEmpty)) {
+        foreach (var series in chart.Series) // sync colors before applying palette colors
+          series.Color = ((DataRow)series.Tag).VisualProperties.Color;
+        chart.ApplyPaletteColors();
+      }
+
+      var numTransparent = Content.Rows.Count(RequiresTransparency);
+      if (numTransparent <= 1) return;
+      foreach (var series in chart.Series) {
+        var row = (DataRow)series.Tag;
+        if (!RequiresTransparency(row))
+          continue;
+        var baseColor = row.VisualProperties.Color;
+        if (baseColor.IsEmpty) baseColor = series.Color;
+        series.Color = Color.FromArgb(180, baseColor);
+      }
+    }
+    private bool RequiresTransparency(DataRow row) {
+      return row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram
+             && Content.VisualProperties.HistogramAggregation == DataTableVisualProperties.DataTableHistogramAggregation.Overlapping;
+    }
+
+    #region Event Handlers
+    #region Content Event Handlers
+    protected override void Content_NameChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_NameChanged), sender, e);
+      else {
+        Content.VisualProperties.Title = Content.Name;
+        base.Content_NameChanged(sender, e);
+      }
+    }
+    private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
+      else {
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
+
+        chart.Update(); // side-by-side and stacked histograms are not always correctly displayed without an update
+        // (chart update is required before the series are updated, otherwise the widths of the bars are updated incorrectly)
+        foreach (var row in Content.Rows.Where(r => r.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram))
+          Row_VisualPropertiesChanged(row, EventArgs.Empty); // Histogram properties could have changed
+      }
+    }
+    #endregion
+    #region Rows Event Handlers
+    private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded), sender, e);
+      else {
+        AddDataRows(e.Items);
+      }
+    }
+    private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsRemoved), sender, e);
+      else {
+        RemoveDataRows(e.Items);
+      }
+    }
+    private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced), sender, e);
+      else {
+        RemoveDataRows(e.OldItems);
+        AddDataRows(e.Items);
+      }
+    }
+    private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset), sender, e);
+      else {
+        RemoveDataRows(e.OldItems);
+        AddDataRows(e.Items);
+      }
+    }
+    #endregion
+    #region Row Event Handlers
+    private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);
+      else {
+        DataRow row = (DataRow)sender;
+        Series series = chart.Series[row.Name];
+        ClearPoints(series.Points);
+        ConfigureSeries(series, row);
+        if (!invisibleSeries.Contains(series)) {
+          FillSeriesWithRowValues(series, row);
+          RecalculateAxesScale(chart.ChartAreas[0]);
+          UpdateHistogramTransparency();
+        }
+      }
+    }
+    private void Row_NameChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Row_NameChanged), sender, e);
+      else {
+        DataRow row = (DataRow)sender;
+        chart.Series[row.Name].Name = row.Name;
+      }
+    }
+    #endregion
+    #region Values Event Handlers
+    private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded), sender, e);
+      else {
+        DataRow row = null;
+        valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            ClearPoints(rowSeries.Points);
+            FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    private void Values_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved), sender, e);
+      else {
+        DataRow row = null;
+        valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            ClearPoints(rowSeries.Points);
+            FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    private void Values_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced), sender, e);
+      else {
+        DataRow row = null;
+        valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            if (row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram) {
+              ClearPoints(rowSeries.Points);
+              FillSeriesWithRowValues(rowSeries, row);
+            } else {
+              foreach (IndexedItem<double> item in e.Items) {
+                if (IsInvalidValue(item.Value))
+                  rowSeries.Points[item.Index].IsEmpty = true;
+                else {
+                  rowSeries.Points[item.Index].YValues = new double[] { item.Value };
+                  rowSeries.Points[item.Index].IsEmpty = false;
+                }
+              }
+            }
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    private void Values_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved), sender, e);
+      else {
+        DataRow row = null;
+        valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            ClearPoints(rowSeries.Points);
+            FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+
+    private void Values_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset), sender, e);
+      else {
+        DataRow row = null;
+        valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            ClearPoints(rowSeries.Points);
+            FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    #endregion
+    private void configureToolStripMenuItem_Click(object sender, EventArgs e) {
+      ShowConfiguration();
+    }
+    #endregion
+
+    #region Chart Event Handlers
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        ToggleSeriesVisible(result.Series);
+      }
+    }
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+    }
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = invisibleSeries.Contains(series);
+          foreach (LegendCell cell in legendItem.Cells) {
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+          }
+        }
+      }
+    }
+    #endregion
+
+    private void ToggleSeriesVisible(Series series) {
+      if (!invisibleSeries.Contains(series)) {
+        ClearPoints(series.Points);
+        invisibleSeries.Add(series);
+      } else {
+        invisibleSeries.Remove(series);
+        if (Content != null) {
+
+          var row = (from r in Content.Rows
+                     where r.Name == series.Name
+                     select r).Single();
+          FillSeriesWithRowValues(series, row);
+          this.chart.Legends[series.Legend].ForeColor = Color.Black;
+          RecalculateAxesScale(chart.ChartAreas[0]);
+          UpdateYCursorInterval();
+        }
+      }
+    }
+
+    private void FillSeriesWithRowValues(Series series, DataRow row) {
+      switch (row.VisualProperties.ChartType) {
+        case DataRowVisualProperties.DataRowChartType.Histogram:
+          // when a single histogram is updated, all histograms must be updated. otherwise the value ranges may not be equal.
+          var histograms = Content.Rows
+            .Where(r => r.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram)
+            .ToList();
+          CalculateHistogram(series, row, histograms);
+          foreach (var h in from r in histograms
+                            where r != row
+                            let s = chart.Series.FindByName(r.Name)
+                            where s != null
+                            where !invisibleSeries.Contains(s)
+                            select new { row = r, series = s }) {
+            ClearPoints(h.series.Points);
+            CalculateHistogram(h.series, h.row, histograms);
+          }
+          break;
+        default: {
+            bool yLogarithmic = series.YAxisType == AxisType.Primary
+                                  ? Content.VisualProperties.YAxisLogScale
+                                  : Content.VisualProperties.SecondYAxisLogScale;
+            bool xLogarithmic = series.XAxisType == AxisType.Primary
+                                  ? Content.VisualProperties.XAxisLogScale
+                                  : Content.VisualProperties.SecondXAxisLogScale;
+            for (int i = 0; i < row.Values.Count; i++) {
+              var value = row.Values[i];
+              var point = new DataPoint();
+              point.XValue = row.VisualProperties.StartIndexZero && !xLogarithmic ? i : i + 1;
+              if (IsInvalidValue(value) || (yLogarithmic && value <= 0))
+                point.IsEmpty = true;
+              else
+                point.YValues = new double[] { value };
+              series.Points.Add(point);
+            }
+          }
+          break;
+      }
+    }
+
+    protected virtual void CalculateHistogram(Series series, DataRow row, IEnumerable<DataRow> histogramRows) {
+      ClearPoints(series.Points);
+      if (!row.Values.Any()) return;
+
+      var validValues = histogramRows.SelectMany(r => r.Values).Where(x => !IsInvalidValue(x)).ToList();
+      if (!validValues.Any()) return;
+
+      int bins = Content.VisualProperties.HistogramBins;
+      decimal minValue = (decimal)validValues.Min();
+      decimal maxValue = (decimal)validValues.Max();
+      decimal intervalWidth = (maxValue - minValue) / bins;
+      if (intervalWidth < 0) return;
+      if (intervalWidth == 0) {
+        series.Points.AddXY(minValue, row.Values.Count);
+        return;
+      }
+
+      if (!Content.VisualProperties.HistogramExactBins) {
+        intervalWidth = (decimal)HumanRoundRange((double)intervalWidth);
+        minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
+        maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
+      }
+
+      decimal intervalCenter = intervalWidth / 2;
+
+      decimal min = 0.0m, max = 0.0m;
+      if (!Double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue) && !Content.VisualProperties.XAxisMinimumAuto)
+        min = (decimal)Content.VisualProperties.XAxisMinimumFixedValue;
+      else min = minValue;
+      if (!Double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue) && !Content.VisualProperties.XAxisMaximumAuto)
+        max = (decimal)Content.VisualProperties.XAxisMaximumFixedValue;
+      else max = maxValue + intervalWidth;
+
+      double axisInterval = (double)intervalWidth / row.VisualProperties.ScaleFactor;
+
+      var area = chart.ChartAreas[0];
+      area.AxisX.Interval = axisInterval;
+
+      series.SetCustomProperty("PointWidth", "1"); // 0.8 is the default value
+
+      // get the range or intervals which define the grouping of the frequency values
+      var range = Range(min, max, intervalWidth).Skip(1).ToList();
+
+      // aggregate the row values by unique key and frequency value
+      var valueFrequencies = (from v in row.Values
+                              where !IsInvalidValue(v)
+                              orderby v
+                              group v by v into g
+                              select new Tuple<double, double>(g.First(), g.Count())).ToList();
+
+      // ensure that each column is displayed completely on the chart by adding two dummy datapoints on the upper and lower range
+      series.Points.Add(new DataPoint((double)(min - intervalWidth), 0));
+      series.Points.Add(new DataPoint((double)(max + intervalWidth), 0));
+
+      // add data points
+      int j = 0;
+      int overallCount = row.Values.Count(x => !IsInvalidValue(x));
+      foreach (var d in range) {
+        double sum = 0.0;
+        // sum the frequency values that fall within the same interval
+        while (j < valueFrequencies.Count && (decimal)valueFrequencies[j].Item1 < d) {
+          sum += valueFrequencies[j].Item2;
+          ++j;
+        }
+        string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
+                              ? "X"
+                              : Content.VisualProperties.XAxisTitle;
+        string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
+                              ? "Y"
+                              : Content.VisualProperties.YAxisTitle;
+        series.Points.Add(new DataPoint((double)(d - intervalCenter), sum) {
+          ToolTip =
+            string.Format("{0}: [{1} - {2})", xAxisTitle, (d - intervalWidth), d) + Environment.NewLine +
+            string.Format("{0}: {1} ({2:F2}%)", yAxisTitle, sum, sum / overallCount * 100)
+        });
+      }
+    }
+
+    #region Helpers
+    public static IEnumerable<decimal> Range(decimal min, decimal max, decimal step) {
+      decimal i;
+      for (i = min; i <= max; i += step)
+        yield return i;
+
+      if (i != max + step)
+        yield return i;
+    }
+
+    protected void RemoveCustomPropertyIfExists(Series series, string property) {
+      if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property);
+    }
+
+    private double HumanRoundRange(double range) {
+      double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
+      double rounding = range / base10;
+      if (rounding <= 1.5) rounding = 1;
+      else if (rounding <= 2.25) rounding = 2;
+      else if (rounding <= 3.75) rounding = 2.5;
+      else if (rounding <= 7.5) rounding = 5;
+      else rounding = 10;
+      return rounding * base10;
+    }
+
+    private double HumanRoundMax(double max) {
+      double base10;
+      if (max > 0) base10 = Math.Pow(10.0, Math.Floor(Math.Log10(max)));
+      else base10 = Math.Pow(10.0, Math.Ceiling(Math.Log10(-max)));
+      double rounding = (max > 0) ? base10 : -base10;
+      while (rounding < max) rounding += base10;
+      return rounding;
+    }
+
+    private ChartDashStyle ConvertLineStyle(DataRowVisualProperties.DataRowLineStyle dataRowLineStyle) {
+      switch (dataRowLineStyle) {
+        case DataRowVisualProperties.DataRowLineStyle.Dash:
+          return ChartDashStyle.Dash;
+        case DataRowVisualProperties.DataRowLineStyle.DashDot:
+          return ChartDashStyle.DashDot;
+        case DataRowVisualProperties.DataRowLineStyle.DashDotDot:
+          return ChartDashStyle.DashDotDot;
+        case DataRowVisualProperties.DataRowLineStyle.Dot:
+          return ChartDashStyle.Dot;
+        case DataRowVisualProperties.DataRowLineStyle.NotSet:
+          return ChartDashStyle.NotSet;
+        case DataRowVisualProperties.DataRowLineStyle.Solid:
+          return ChartDashStyle.Solid;
+        default:
+          return ChartDashStyle.NotSet;
+      }
+    }
+
+    protected static bool IsInvalidValue(double x) {
+      return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
+    }
+
+    // workaround for performance problem as described in https://stackoverflow.com/questions/5744930/datapointcollection-clear-performance
+    public static void ClearPoints(DataPointCollection points) {
+      points.SuspendUpdates();
+      while (points.Count > 0)
+        points.RemoveAt(points.Count - 1);
+      points.ResumeUpdates();
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.Designer.cs	(revision 15719)
@@ -0,0 +1,1135 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class DataTableVisualPropertiesControl {
+    /// <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();
+      this.label1 = new System.Windows.Forms.Label();
+      this.yAxisPrimaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisSecondaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label4 = new System.Windows.Forms.Label();
+      this.xAxisPrimaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.xAxisPrimaryLogScaleCheckBox = new System.Windows.Forms.CheckBox();
+      this.panel2 = new System.Windows.Forms.Panel();
+      this.xAxisPrimaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisPrimaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel1 = new System.Windows.Forms.Panel();
+      this.xAxisPrimaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisPrimaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisPrimaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisPrimaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.label12 = new System.Windows.Forms.Label();
+      this.label9 = new System.Windows.Forms.Label();
+      this.xAxisPrimaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label11 = new System.Windows.Forms.Label();
+      this.xAxisSecondaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.xAxisSecondaryLogScaleCheckBox = new System.Windows.Forms.CheckBox();
+      this.panel4 = new System.Windows.Forms.Panel();
+      this.xAxisSecondaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel3 = new System.Windows.Forms.Panel();
+      this.xAxisSecondaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisSecondaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.label10 = new System.Windows.Forms.Label();
+      this.xAxisSecondaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label5 = new System.Windows.Forms.Label();
+      this.label6 = new System.Windows.Forms.Label();
+      this.axisTabControl = new System.Windows.Forms.TabControl();
+      this.xAxisTabPage = new System.Windows.Forms.TabPage();
+      this.yAxisTabPage = new System.Windows.Forms.TabPage();
+      this.yAxisSecondaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.yAxisSecondaryLogScaleCheckBox = new System.Windows.Forms.CheckBox();
+      this.panel8 = new System.Windows.Forms.Panel();
+      this.yAxisSecondaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisSecondaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel7 = new System.Windows.Forms.Panel();
+      this.yAxisSecondaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisSecondaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisSecondaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisSecondaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.label13 = new System.Windows.Forms.Label();
+      this.label14 = new System.Windows.Forms.Label();
+      this.yAxisPrimaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.yAxisPrimaryLogScaleCheckBox = new System.Windows.Forms.CheckBox();
+      this.panel6 = new System.Windows.Forms.Panel();
+      this.yAxisPrimaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel5 = new System.Windows.Forms.Panel();
+      this.yAxisPrimaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisPrimaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.label7 = new System.Windows.Forms.Label();
+      this.label8 = new System.Windows.Forms.Label();
+      this.histogramTabPage = new System.Windows.Forms.TabPage();
+      this.histogramGroupBox = new System.Windows.Forms.GroupBox();
+      this.histogramBinsExactRadioButton = new System.Windows.Forms.RadioButton();
+      this.histogramBinsApproximatelyRadioButton = new System.Windows.Forms.RadioButton();
+      this.histogramBinsNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label16 = new System.Windows.Forms.Label();
+      this.label17 = new System.Windows.Forms.Label();
+      this.histogramAggregationComboBox = new System.Windows.Forms.ComboBox();
+      this.titleTextBox = new System.Windows.Forms.TextBox();
+      this.label15 = new System.Windows.Forms.Label();
+      this.axisFontLabel = new System.Windows.Forms.Label();
+      this.titleFontLabel = new System.Windows.Forms.Label();
+      this.axisFontButton = new System.Windows.Forms.Button();
+      this.label3 = new System.Windows.Forms.Label();
+      this.titleFontButton = new System.Windows.Forms.Button();
+      this.label2 = new System.Windows.Forms.Label();
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+      this.titleFontDialog = new System.Windows.Forms.FontDialog();
+      this.axisFontDialog = new System.Windows.Forms.FontDialog();
+      this.xAxisPrimaryGroupBox.SuspendLayout();
+      this.panel2.SuspendLayout();
+      this.panel1.SuspendLayout();
+      this.xAxisSecondaryGroupBox.SuspendLayout();
+      this.panel4.SuspendLayout();
+      this.panel3.SuspendLayout();
+      this.axisTabControl.SuspendLayout();
+      this.xAxisTabPage.SuspendLayout();
+      this.yAxisTabPage.SuspendLayout();
+      this.yAxisSecondaryGroupBox.SuspendLayout();
+      this.panel8.SuspendLayout();
+      this.panel7.SuspendLayout();
+      this.yAxisPrimaryGroupBox.SuspendLayout();
+      this.panel6.SuspendLayout();
+      this.panel5.SuspendLayout();
+      this.histogramTabPage.SuspendLayout();
+      this.histogramGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.histogramBinsNumericUpDown)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(6, 22);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(30, 13);
+      this.label1.TabIndex = 0;
+      this.label1.Text = "&Title:";
+      // 
+      // yAxisPrimaryTitleTextBox
+      // 
+      this.yAxisPrimaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisPrimaryTitleTextBox.Location = new System.Drawing.Point(74, 19);
+      this.yAxisPrimaryTitleTextBox.Name = "yAxisPrimaryTitleTextBox";
+      this.yAxisPrimaryTitleTextBox.Size = new System.Drawing.Size(361, 20);
+      this.yAxisPrimaryTitleTextBox.TabIndex = 1;
+      this.yAxisPrimaryTitleTextBox.Validated += new System.EventHandler(this.yPrimaryTitleTextBox_Validated);
+      // 
+      // yAxisSecondaryTitleTextBox
+      // 
+      this.yAxisSecondaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisSecondaryTitleTextBox.Location = new System.Drawing.Point(74, 19);
+      this.yAxisSecondaryTitleTextBox.Name = "yAxisSecondaryTitleTextBox";
+      this.yAxisSecondaryTitleTextBox.Size = new System.Drawing.Size(361, 20);
+      this.yAxisSecondaryTitleTextBox.TabIndex = 1;
+      this.yAxisSecondaryTitleTextBox.Validated += new System.EventHandler(this.ySecondaryTitleTextBox_Validated);
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(6, 22);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(30, 13);
+      this.label4.TabIndex = 0;
+      this.label4.Text = "&Title:";
+      // 
+      // xAxisPrimaryGroupBox
+      // 
+      this.xAxisPrimaryGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryLogScaleCheckBox);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.panel2);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.panel1);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryMinimumFixedTextBox);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryMaximumFixedTextBox);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.label12);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.label9);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryTitleTextBox);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.label11);
+      this.xAxisPrimaryGroupBox.Location = new System.Drawing.Point(3, 3);
+      this.xAxisPrimaryGroupBox.Name = "xAxisPrimaryGroupBox";
+      this.xAxisPrimaryGroupBox.Size = new System.Drawing.Size(441, 126);
+      this.xAxisPrimaryGroupBox.TabIndex = 0;
+      this.xAxisPrimaryGroupBox.TabStop = false;
+      this.xAxisPrimaryGroupBox.Text = "Primary Axis";
+      // 
+      // xAxisPrimaryLogScaleCheckBox
+      // 
+      this.xAxisPrimaryLogScaleCheckBox.AutoSize = true;
+      this.xAxisPrimaryLogScaleCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.xAxisPrimaryLogScaleCheckBox.Location = new System.Drawing.Point(6, 99);
+      this.xAxisPrimaryLogScaleCheckBox.Name = "xAxisPrimaryLogScaleCheckBox";
+      this.xAxisPrimaryLogScaleCheckBox.Size = new System.Drawing.Size(83, 17);
+      this.xAxisPrimaryLogScaleCheckBox.TabIndex = 8;
+      this.xAxisPrimaryLogScaleCheckBox.Text = "Logarithmic:";
+      this.xAxisPrimaryLogScaleCheckBox.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryLogScaleCheckBox.CheckedChanged += new System.EventHandler(this.xAxisPrimaryLogScaleCheckBox_CheckedChanged);
+      // 
+      // panel2
+      // 
+      this.panel2.Controls.Add(this.xAxisPrimaryMaximumFixedRadioButton);
+      this.panel2.Controls.Add(this.xAxisPrimaryMaximumAutoRadioButton);
+      this.panel2.Location = new System.Drawing.Point(74, 71);
+      this.panel2.Name = "panel2";
+      this.panel2.Size = new System.Drawing.Size(106, 20);
+      this.panel2.TabIndex = 6;
+      // 
+      // xAxisPrimaryMaximumFixedRadioButton
+      // 
+      this.xAxisPrimaryMaximumFixedRadioButton.AutoSize = true;
+      this.xAxisPrimaryMaximumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.xAxisPrimaryMaximumFixedRadioButton.Name = "xAxisPrimaryMaximumFixedRadioButton";
+      this.xAxisPrimaryMaximumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.xAxisPrimaryMaximumFixedRadioButton.TabIndex = 1;
+      this.xAxisPrimaryMaximumFixedRadioButton.TabStop = true;
+      this.xAxisPrimaryMaximumFixedRadioButton.Text = "&Fixed:";
+      this.xAxisPrimaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMaximumAutoRadioButton
+      // 
+      this.xAxisPrimaryMaximumAutoRadioButton.AutoSize = true;
+      this.xAxisPrimaryMaximumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.xAxisPrimaryMaximumAutoRadioButton.Name = "xAxisPrimaryMaximumAutoRadioButton";
+      this.xAxisPrimaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisPrimaryMaximumAutoRadioButton.TabIndex = 0;
+      this.xAxisPrimaryMaximumAutoRadioButton.TabStop = true;
+      this.xAxisPrimaryMaximumAutoRadioButton.Text = "&Auto";
+      this.xAxisPrimaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // panel1
+      // 
+      this.panel1.Controls.Add(this.xAxisPrimaryMinimumFixedRadioButton);
+      this.panel1.Controls.Add(this.xAxisPrimaryMinimumAutoRadioButton);
+      this.panel1.Location = new System.Drawing.Point(74, 45);
+      this.panel1.Name = "panel1";
+      this.panel1.Size = new System.Drawing.Size(106, 20);
+      this.panel1.TabIndex = 3;
+      // 
+      // xAxisPrimaryMinimumFixedRadioButton
+      // 
+      this.xAxisPrimaryMinimumFixedRadioButton.AutoSize = true;
+      this.xAxisPrimaryMinimumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.xAxisPrimaryMinimumFixedRadioButton.Name = "xAxisPrimaryMinimumFixedRadioButton";
+      this.xAxisPrimaryMinimumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.xAxisPrimaryMinimumFixedRadioButton.TabIndex = 1;
+      this.xAxisPrimaryMinimumFixedRadioButton.TabStop = true;
+      this.xAxisPrimaryMinimumFixedRadioButton.Text = "&Fixed:";
+      this.xAxisPrimaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMinimumAutoRadioButton
+      // 
+      this.xAxisPrimaryMinimumAutoRadioButton.AutoSize = true;
+      this.xAxisPrimaryMinimumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.xAxisPrimaryMinimumAutoRadioButton.Name = "xAxisPrimaryMinimumAutoRadioButton";
+      this.xAxisPrimaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisPrimaryMinimumAutoRadioButton.TabIndex = 0;
+      this.xAxisPrimaryMinimumAutoRadioButton.TabStop = true;
+      this.xAxisPrimaryMinimumAutoRadioButton.Text = "&Auto";
+      this.xAxisPrimaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMinimumFixedTextBox
+      // 
+      this.xAxisPrimaryMinimumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisPrimaryMinimumFixedTextBox.Location = new System.Drawing.Point(191, 45);
+      this.xAxisPrimaryMinimumFixedTextBox.Name = "xAxisPrimaryMinimumFixedTextBox";
+      this.xAxisPrimaryMinimumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.xAxisPrimaryMinimumFixedTextBox.TabIndex = 4;
+      this.xAxisPrimaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisPrimaryMinimumFixedTextBox_Validating);
+      // 
+      // xAxisPrimaryMaximumFixedTextBox
+      // 
+      this.xAxisPrimaryMaximumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisPrimaryMaximumFixedTextBox.Location = new System.Drawing.Point(191, 71);
+      this.xAxisPrimaryMaximumFixedTextBox.Name = "xAxisPrimaryMaximumFixedTextBox";
+      this.xAxisPrimaryMaximumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.xAxisPrimaryMaximumFixedTextBox.TabIndex = 7;
+      this.xAxisPrimaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisPrimaryMaximumFixedTextBox_Validating);
+      // 
+      // label12
+      // 
+      this.label12.AutoSize = true;
+      this.label12.Location = new System.Drawing.Point(6, 74);
+      this.label12.Name = "label12";
+      this.label12.Size = new System.Drawing.Size(54, 13);
+      this.label12.TabIndex = 5;
+      this.label12.Text = "&Maximum:";
+      // 
+      // label9
+      // 
+      this.label9.AutoSize = true;
+      this.label9.Location = new System.Drawing.Point(6, 22);
+      this.label9.Name = "label9";
+      this.label9.Size = new System.Drawing.Size(30, 13);
+      this.label9.TabIndex = 0;
+      this.label9.Text = "&Title:";
+      // 
+      // xAxisPrimaryTitleTextBox
+      // 
+      this.xAxisPrimaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisPrimaryTitleTextBox.Location = new System.Drawing.Point(74, 19);
+      this.xAxisPrimaryTitleTextBox.Name = "xAxisPrimaryTitleTextBox";
+      this.xAxisPrimaryTitleTextBox.Size = new System.Drawing.Size(361, 20);
+      this.xAxisPrimaryTitleTextBox.TabIndex = 1;
+      this.xAxisPrimaryTitleTextBox.Validated += new System.EventHandler(this.xPrimaryTitleTextBox_Validated);
+      // 
+      // label11
+      // 
+      this.label11.AutoSize = true;
+      this.label11.Location = new System.Drawing.Point(6, 48);
+      this.label11.Name = "label11";
+      this.label11.Size = new System.Drawing.Size(51, 13);
+      this.label11.TabIndex = 2;
+      this.label11.Text = "&Minimum:";
+      // 
+      // xAxisSecondaryGroupBox
+      // 
+      this.xAxisSecondaryGroupBox.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)));
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryLogScaleCheckBox);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.panel4);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.panel3);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryMinimumFixedTextBox);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryMaximumFixedTextBox);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.label10);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryTitleTextBox);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.label5);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.label6);
+      this.xAxisSecondaryGroupBox.Location = new System.Drawing.Point(3, 135);
+      this.xAxisSecondaryGroupBox.Name = "xAxisSecondaryGroupBox";
+      this.xAxisSecondaryGroupBox.Size = new System.Drawing.Size(441, 125);
+      this.xAxisSecondaryGroupBox.TabIndex = 1;
+      this.xAxisSecondaryGroupBox.TabStop = false;
+      this.xAxisSecondaryGroupBox.Text = "Secondary Axis";
+      // 
+      // xAxisSecondaryLogScaleCheckBox
+      // 
+      this.xAxisSecondaryLogScaleCheckBox.AutoSize = true;
+      this.xAxisSecondaryLogScaleCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.xAxisSecondaryLogScaleCheckBox.Location = new System.Drawing.Point(6, 99);
+      this.xAxisSecondaryLogScaleCheckBox.Name = "xAxisSecondaryLogScaleCheckBox";
+      this.xAxisSecondaryLogScaleCheckBox.Size = new System.Drawing.Size(83, 17);
+      this.xAxisSecondaryLogScaleCheckBox.TabIndex = 8;
+      this.xAxisSecondaryLogScaleCheckBox.Text = "Logarithmic:";
+      this.xAxisSecondaryLogScaleCheckBox.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryLogScaleCheckBox.CheckedChanged += new System.EventHandler(this.xAxisSecondaryLogScaleCheckBox_CheckedChanged);
+      // 
+      // panel4
+      // 
+      this.panel4.Controls.Add(this.xAxisSecondaryMaximumFixedRadioButton);
+      this.panel4.Controls.Add(this.xAxisSecondaryMaximumAutoRadioButton);
+      this.panel4.Location = new System.Drawing.Point(74, 71);
+      this.panel4.Name = "panel4";
+      this.panel4.Size = new System.Drawing.Size(106, 20);
+      this.panel4.TabIndex = 6;
+      // 
+      // xAxisSecondaryMaximumFixedRadioButton
+      // 
+      this.xAxisSecondaryMaximumFixedRadioButton.AutoSize = true;
+      this.xAxisSecondaryMaximumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.xAxisSecondaryMaximumFixedRadioButton.Name = "xAxisSecondaryMaximumFixedRadioButton";
+      this.xAxisSecondaryMaximumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.xAxisSecondaryMaximumFixedRadioButton.TabIndex = 1;
+      this.xAxisSecondaryMaximumFixedRadioButton.TabStop = true;
+      this.xAxisSecondaryMaximumFixedRadioButton.Text = "&Fixed:";
+      this.xAxisSecondaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryMaximumAutoRadioButton
+      // 
+      this.xAxisSecondaryMaximumAutoRadioButton.AutoSize = true;
+      this.xAxisSecondaryMaximumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.xAxisSecondaryMaximumAutoRadioButton.Name = "xAxisSecondaryMaximumAutoRadioButton";
+      this.xAxisSecondaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisSecondaryMaximumAutoRadioButton.TabIndex = 0;
+      this.xAxisSecondaryMaximumAutoRadioButton.TabStop = true;
+      this.xAxisSecondaryMaximumAutoRadioButton.Text = "&Auto";
+      this.xAxisSecondaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // panel3
+      // 
+      this.panel3.Controls.Add(this.xAxisSecondaryMinimumFixedRadioButton);
+      this.panel3.Controls.Add(this.xAxisSecondaryMinimumAutoRadioButton);
+      this.panel3.Location = new System.Drawing.Point(74, 45);
+      this.panel3.Name = "panel3";
+      this.panel3.Size = new System.Drawing.Size(106, 20);
+      this.panel3.TabIndex = 3;
+      // 
+      // xAxisSecondaryMinimumFixedRadioButton
+      // 
+      this.xAxisSecondaryMinimumFixedRadioButton.AutoSize = true;
+      this.xAxisSecondaryMinimumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.xAxisSecondaryMinimumFixedRadioButton.Name = "xAxisSecondaryMinimumFixedRadioButton";
+      this.xAxisSecondaryMinimumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.xAxisSecondaryMinimumFixedRadioButton.TabIndex = 1;
+      this.xAxisSecondaryMinimumFixedRadioButton.TabStop = true;
+      this.xAxisSecondaryMinimumFixedRadioButton.Text = "&Fixed:";
+      this.xAxisSecondaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryMinimumAutoRadioButton
+      // 
+      this.xAxisSecondaryMinimumAutoRadioButton.AutoSize = true;
+      this.xAxisSecondaryMinimumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.xAxisSecondaryMinimumAutoRadioButton.Name = "xAxisSecondaryMinimumAutoRadioButton";
+      this.xAxisSecondaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisSecondaryMinimumAutoRadioButton.TabIndex = 0;
+      this.xAxisSecondaryMinimumAutoRadioButton.TabStop = true;
+      this.xAxisSecondaryMinimumAutoRadioButton.Text = "&Auto";
+      this.xAxisSecondaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryMinimumFixedTextBox
+      // 
+      this.xAxisSecondaryMinimumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisSecondaryMinimumFixedTextBox.Location = new System.Drawing.Point(191, 45);
+      this.xAxisSecondaryMinimumFixedTextBox.Name = "xAxisSecondaryMinimumFixedTextBox";
+      this.xAxisSecondaryMinimumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.xAxisSecondaryMinimumFixedTextBox.TabIndex = 4;
+      this.xAxisSecondaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisSecondaryMinimumFixedTextBox_Validating);
+      // 
+      // xAxisSecondaryMaximumFixedTextBox
+      // 
+      this.xAxisSecondaryMaximumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisSecondaryMaximumFixedTextBox.Location = new System.Drawing.Point(191, 71);
+      this.xAxisSecondaryMaximumFixedTextBox.Name = "xAxisSecondaryMaximumFixedTextBox";
+      this.xAxisSecondaryMaximumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.xAxisSecondaryMaximumFixedTextBox.TabIndex = 7;
+      this.xAxisSecondaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisSecondaryMaximumFixedTextBox_Validating);
+      // 
+      // label10
+      // 
+      this.label10.AutoSize = true;
+      this.label10.Location = new System.Drawing.Point(6, 22);
+      this.label10.Name = "label10";
+      this.label10.Size = new System.Drawing.Size(30, 13);
+      this.label10.TabIndex = 0;
+      this.label10.Text = "&Title:";
+      // 
+      // xAxisSecondaryTitleTextBox
+      // 
+      this.xAxisSecondaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisSecondaryTitleTextBox.Location = new System.Drawing.Point(74, 19);
+      this.xAxisSecondaryTitleTextBox.Name = "xAxisSecondaryTitleTextBox";
+      this.xAxisSecondaryTitleTextBox.Size = new System.Drawing.Size(361, 20);
+      this.xAxisSecondaryTitleTextBox.TabIndex = 1;
+      this.xAxisSecondaryTitleTextBox.Validated += new System.EventHandler(this.xSecondaryTitleTextBox_Validated);
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(6, 74);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(54, 13);
+      this.label5.TabIndex = 5;
+      this.label5.Text = "&Maximum:";
+      // 
+      // label6
+      // 
+      this.label6.AutoSize = true;
+      this.label6.Location = new System.Drawing.Point(6, 48);
+      this.label6.Name = "label6";
+      this.label6.Size = new System.Drawing.Size(51, 13);
+      this.label6.TabIndex = 2;
+      this.label6.Text = "&Minimum:";
+      // 
+      // axisTabControl
+      // 
+      this.axisTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.axisTabControl.Controls.Add(this.xAxisTabPage);
+      this.axisTabControl.Controls.Add(this.yAxisTabPage);
+      this.axisTabControl.Controls.Add(this.histogramTabPage);
+      this.axisTabControl.Location = new System.Drawing.Point(0, 84);
+      this.axisTabControl.Name = "axisTabControl";
+      this.axisTabControl.SelectedIndex = 0;
+      this.axisTabControl.Size = new System.Drawing.Size(455, 289);
+      this.axisTabControl.TabIndex = 8;
+      // 
+      // xAxisTabPage
+      // 
+      this.xAxisTabPage.Controls.Add(this.xAxisSecondaryGroupBox);
+      this.xAxisTabPage.Controls.Add(this.xAxisPrimaryGroupBox);
+      this.xAxisTabPage.Location = new System.Drawing.Point(4, 22);
+      this.xAxisTabPage.Name = "xAxisTabPage";
+      this.xAxisTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.xAxisTabPage.Size = new System.Drawing.Size(447, 263);
+      this.xAxisTabPage.TabIndex = 0;
+      this.xAxisTabPage.Text = "X-Axis";
+      this.xAxisTabPage.UseVisualStyleBackColor = true;
+      // 
+      // yAxisTabPage
+      // 
+      this.yAxisTabPage.Controls.Add(this.yAxisSecondaryGroupBox);
+      this.yAxisTabPage.Controls.Add(this.yAxisPrimaryGroupBox);
+      this.yAxisTabPage.Location = new System.Drawing.Point(4, 22);
+      this.yAxisTabPage.Name = "yAxisTabPage";
+      this.yAxisTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.yAxisTabPage.Size = new System.Drawing.Size(447, 263);
+      this.yAxisTabPage.TabIndex = 1;
+      this.yAxisTabPage.Text = "Y-Axis";
+      this.yAxisTabPage.UseVisualStyleBackColor = true;
+      // 
+      // yAxisSecondaryGroupBox
+      // 
+      this.yAxisSecondaryGroupBox.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)));
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryLogScaleCheckBox);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.panel8);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.panel7);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryMinimumFixedTextBox);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryMaximumFixedTextBox);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryTitleTextBox);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.label4);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.label13);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.label14);
+      this.yAxisSecondaryGroupBox.Location = new System.Drawing.Point(3, 135);
+      this.yAxisSecondaryGroupBox.Name = "yAxisSecondaryGroupBox";
+      this.yAxisSecondaryGroupBox.Size = new System.Drawing.Size(441, 125);
+      this.yAxisSecondaryGroupBox.TabIndex = 1;
+      this.yAxisSecondaryGroupBox.TabStop = false;
+      this.yAxisSecondaryGroupBox.Text = "Secondary Axis";
+      // 
+      // yAxisSecondaryLogScaleCheckBox
+      // 
+      this.yAxisSecondaryLogScaleCheckBox.AutoSize = true;
+      this.yAxisSecondaryLogScaleCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.yAxisSecondaryLogScaleCheckBox.Location = new System.Drawing.Point(6, 99);
+      this.yAxisSecondaryLogScaleCheckBox.Name = "yAxisSecondaryLogScaleCheckBox";
+      this.yAxisSecondaryLogScaleCheckBox.Size = new System.Drawing.Size(83, 17);
+      this.yAxisSecondaryLogScaleCheckBox.TabIndex = 9;
+      this.yAxisSecondaryLogScaleCheckBox.Text = "Logarithmic:";
+      this.yAxisSecondaryLogScaleCheckBox.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryLogScaleCheckBox.CheckedChanged += new System.EventHandler(this.yAxisSecondaryLogScaleCheckBox_CheckedChanged);
+      // 
+      // panel8
+      // 
+      this.panel8.Controls.Add(this.yAxisSecondaryMaximumFixedRadioButton);
+      this.panel8.Controls.Add(this.yAxisSecondaryMaximumAutoRadioButton);
+      this.panel8.Location = new System.Drawing.Point(74, 71);
+      this.panel8.Name = "panel8";
+      this.panel8.Size = new System.Drawing.Size(106, 20);
+      this.panel8.TabIndex = 6;
+      // 
+      // yAxisSecondaryMaximumFixedRadioButton
+      // 
+      this.yAxisSecondaryMaximumFixedRadioButton.AutoSize = true;
+      this.yAxisSecondaryMaximumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.yAxisSecondaryMaximumFixedRadioButton.Name = "yAxisSecondaryMaximumFixedRadioButton";
+      this.yAxisSecondaryMaximumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.yAxisSecondaryMaximumFixedRadioButton.TabIndex = 1;
+      this.yAxisSecondaryMaximumFixedRadioButton.TabStop = true;
+      this.yAxisSecondaryMaximumFixedRadioButton.Text = "&Fixed:";
+      this.yAxisSecondaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisSecondaryMaximumAutoRadioButton
+      // 
+      this.yAxisSecondaryMaximumAutoRadioButton.AutoSize = true;
+      this.yAxisSecondaryMaximumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.yAxisSecondaryMaximumAutoRadioButton.Name = "yAxisSecondaryMaximumAutoRadioButton";
+      this.yAxisSecondaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisSecondaryMaximumAutoRadioButton.TabIndex = 0;
+      this.yAxisSecondaryMaximumAutoRadioButton.TabStop = true;
+      this.yAxisSecondaryMaximumAutoRadioButton.Text = "&Auto";
+      this.yAxisSecondaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // panel7
+      // 
+      this.panel7.Controls.Add(this.yAxisSecondaryMinimumFixedRadioButton);
+      this.panel7.Controls.Add(this.yAxisSecondaryMinimumAutoRadioButton);
+      this.panel7.Location = new System.Drawing.Point(74, 45);
+      this.panel7.Name = "panel7";
+      this.panel7.Size = new System.Drawing.Size(106, 20);
+      this.panel7.TabIndex = 3;
+      // 
+      // yAxisSecondaryMinimumFixedRadioButton
+      // 
+      this.yAxisSecondaryMinimumFixedRadioButton.AutoSize = true;
+      this.yAxisSecondaryMinimumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.yAxisSecondaryMinimumFixedRadioButton.Name = "yAxisSecondaryMinimumFixedRadioButton";
+      this.yAxisSecondaryMinimumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.yAxisSecondaryMinimumFixedRadioButton.TabIndex = 1;
+      this.yAxisSecondaryMinimumFixedRadioButton.TabStop = true;
+      this.yAxisSecondaryMinimumFixedRadioButton.Text = "&Fixed:";
+      this.yAxisSecondaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisSecondaryMinimumAutoRadioButton
+      // 
+      this.yAxisSecondaryMinimumAutoRadioButton.AutoSize = true;
+      this.yAxisSecondaryMinimumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.yAxisSecondaryMinimumAutoRadioButton.Name = "yAxisSecondaryMinimumAutoRadioButton";
+      this.yAxisSecondaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisSecondaryMinimumAutoRadioButton.TabIndex = 0;
+      this.yAxisSecondaryMinimumAutoRadioButton.TabStop = true;
+      this.yAxisSecondaryMinimumAutoRadioButton.Text = "&Auto";
+      this.yAxisSecondaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisSecondaryMinimumFixedTextBox
+      // 
+      this.yAxisSecondaryMinimumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisSecondaryMinimumFixedTextBox.Location = new System.Drawing.Point(191, 45);
+      this.yAxisSecondaryMinimumFixedTextBox.Name = "yAxisSecondaryMinimumFixedTextBox";
+      this.yAxisSecondaryMinimumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.yAxisSecondaryMinimumFixedTextBox.TabIndex = 4;
+      this.yAxisSecondaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisSecondaryMinimumFixedTextBox_Validating);
+      // 
+      // yAxisSecondaryMaximumFixedTextBox
+      // 
+      this.yAxisSecondaryMaximumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisSecondaryMaximumFixedTextBox.Location = new System.Drawing.Point(191, 71);
+      this.yAxisSecondaryMaximumFixedTextBox.Name = "yAxisSecondaryMaximumFixedTextBox";
+      this.yAxisSecondaryMaximumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.yAxisSecondaryMaximumFixedTextBox.TabIndex = 7;
+      this.yAxisSecondaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisSecondaryMaximumFixedTextBox_Validating);
+      // 
+      // label13
+      // 
+      this.label13.AutoSize = true;
+      this.label13.Location = new System.Drawing.Point(6, 74);
+      this.label13.Name = "label13";
+      this.label13.Size = new System.Drawing.Size(54, 13);
+      this.label13.TabIndex = 5;
+      this.label13.Text = "&Maximum:";
+      // 
+      // label14
+      // 
+      this.label14.AutoSize = true;
+      this.label14.Location = new System.Drawing.Point(6, 48);
+      this.label14.Name = "label14";
+      this.label14.Size = new System.Drawing.Size(51, 13);
+      this.label14.TabIndex = 2;
+      this.label14.Text = "&Minimum:";
+      // 
+      // yAxisPrimaryGroupBox
+      // 
+      this.yAxisPrimaryGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryLogScaleCheckBox);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.panel6);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.panel5);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryMinimumFixedTextBox);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryMaximumFixedTextBox);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.label7);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryTitleTextBox);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.label8);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.label1);
+      this.yAxisPrimaryGroupBox.Location = new System.Drawing.Point(3, 3);
+      this.yAxisPrimaryGroupBox.Name = "yAxisPrimaryGroupBox";
+      this.yAxisPrimaryGroupBox.Size = new System.Drawing.Size(441, 126);
+      this.yAxisPrimaryGroupBox.TabIndex = 0;
+      this.yAxisPrimaryGroupBox.TabStop = false;
+      this.yAxisPrimaryGroupBox.Text = "Primary Axis";
+      // 
+      // yAxisPrimaryLogScaleCheckBox
+      // 
+      this.yAxisPrimaryLogScaleCheckBox.AutoSize = true;
+      this.yAxisPrimaryLogScaleCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.yAxisPrimaryLogScaleCheckBox.Location = new System.Drawing.Point(6, 99);
+      this.yAxisPrimaryLogScaleCheckBox.Name = "yAxisPrimaryLogScaleCheckBox";
+      this.yAxisPrimaryLogScaleCheckBox.Size = new System.Drawing.Size(83, 17);
+      this.yAxisPrimaryLogScaleCheckBox.TabIndex = 10;
+      this.yAxisPrimaryLogScaleCheckBox.Text = "Logarithmic:";
+      this.yAxisPrimaryLogScaleCheckBox.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryLogScaleCheckBox.CheckedChanged += new System.EventHandler(this.yAxisPrimaryLogScaleCheckBox_CheckedChanged);
+      // 
+      // panel6
+      // 
+      this.panel6.Controls.Add(this.yAxisPrimaryMaximumFixedRadioButton);
+      this.panel6.Controls.Add(this.yAxisPrimaryMaximumAutoRadioButton);
+      this.panel6.Location = new System.Drawing.Point(74, 71);
+      this.panel6.Name = "panel6";
+      this.panel6.Size = new System.Drawing.Size(106, 20);
+      this.panel6.TabIndex = 6;
+      // 
+      // yAxisPrimaryMaximumFixedRadioButton
+      // 
+      this.yAxisPrimaryMaximumFixedRadioButton.AutoSize = true;
+      this.yAxisPrimaryMaximumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.yAxisPrimaryMaximumFixedRadioButton.Name = "yAxisPrimaryMaximumFixedRadioButton";
+      this.yAxisPrimaryMaximumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.yAxisPrimaryMaximumFixedRadioButton.TabIndex = 1;
+      this.yAxisPrimaryMaximumFixedRadioButton.TabStop = true;
+      this.yAxisPrimaryMaximumFixedRadioButton.Text = "&Fixed:";
+      this.yAxisPrimaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMaximumAutoRadioButton
+      // 
+      this.yAxisPrimaryMaximumAutoRadioButton.AutoSize = true;
+      this.yAxisPrimaryMaximumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.yAxisPrimaryMaximumAutoRadioButton.Name = "yAxisPrimaryMaximumAutoRadioButton";
+      this.yAxisPrimaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisPrimaryMaximumAutoRadioButton.TabIndex = 0;
+      this.yAxisPrimaryMaximumAutoRadioButton.TabStop = true;
+      this.yAxisPrimaryMaximumAutoRadioButton.Text = "&Auto";
+      this.yAxisPrimaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // panel5
+      // 
+      this.panel5.Controls.Add(this.yAxisPrimaryMinimumAutoRadioButton);
+      this.panel5.Controls.Add(this.yAxisPrimaryMinimumFixedRadioButton);
+      this.panel5.Location = new System.Drawing.Point(74, 45);
+      this.panel5.Name = "panel5";
+      this.panel5.Size = new System.Drawing.Size(106, 20);
+      this.panel5.TabIndex = 3;
+      // 
+      // yAxisPrimaryMinimumAutoRadioButton
+      // 
+      this.yAxisPrimaryMinimumAutoRadioButton.AutoSize = true;
+      this.yAxisPrimaryMinimumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.yAxisPrimaryMinimumAutoRadioButton.Name = "yAxisPrimaryMinimumAutoRadioButton";
+      this.yAxisPrimaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisPrimaryMinimumAutoRadioButton.TabIndex = 0;
+      this.yAxisPrimaryMinimumAutoRadioButton.TabStop = true;
+      this.yAxisPrimaryMinimumAutoRadioButton.Text = "&Auto";
+      this.yAxisPrimaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMinimumFixedRadioButton
+      // 
+      this.yAxisPrimaryMinimumFixedRadioButton.AutoSize = true;
+      this.yAxisPrimaryMinimumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.yAxisPrimaryMinimumFixedRadioButton.Name = "yAxisPrimaryMinimumFixedRadioButton";
+      this.yAxisPrimaryMinimumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.yAxisPrimaryMinimumFixedRadioButton.TabIndex = 1;
+      this.yAxisPrimaryMinimumFixedRadioButton.TabStop = true;
+      this.yAxisPrimaryMinimumFixedRadioButton.Text = "&Fixed:";
+      this.yAxisPrimaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMinimumFixedTextBox
+      // 
+      this.yAxisPrimaryMinimumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisPrimaryMinimumFixedTextBox.Location = new System.Drawing.Point(191, 45);
+      this.yAxisPrimaryMinimumFixedTextBox.Name = "yAxisPrimaryMinimumFixedTextBox";
+      this.yAxisPrimaryMinimumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.yAxisPrimaryMinimumFixedTextBox.TabIndex = 4;
+      this.yAxisPrimaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisPrimaryMinimumFixedTextBox_Validating);
+      // 
+      // yAxisPrimaryMaximumFixedTextBox
+      // 
+      this.yAxisPrimaryMaximumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisPrimaryMaximumFixedTextBox.Location = new System.Drawing.Point(191, 71);
+      this.yAxisPrimaryMaximumFixedTextBox.Name = "yAxisPrimaryMaximumFixedTextBox";
+      this.yAxisPrimaryMaximumFixedTextBox.Size = new System.Drawing.Size(244, 20);
+      this.yAxisPrimaryMaximumFixedTextBox.TabIndex = 7;
+      this.yAxisPrimaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisPrimaryMaximumFixedTextBox_Validating);
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(6, 74);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(54, 13);
+      this.label7.TabIndex = 5;
+      this.label7.Text = "&Maximum:";
+      // 
+      // label8
+      // 
+      this.label8.AutoSize = true;
+      this.label8.Location = new System.Drawing.Point(6, 48);
+      this.label8.Name = "label8";
+      this.label8.Size = new System.Drawing.Size(51, 13);
+      this.label8.TabIndex = 2;
+      this.label8.Text = "&Minimum:";
+      // 
+      // histogramTabPage
+      // 
+      this.histogramTabPage.Controls.Add(this.histogramGroupBox);
+      this.histogramTabPage.Location = new System.Drawing.Point(4, 22);
+      this.histogramTabPage.Name = "histogramTabPage";
+      this.histogramTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.histogramTabPage.Size = new System.Drawing.Size(447, 263);
+      this.histogramTabPage.TabIndex = 2;
+      this.histogramTabPage.Text = "Histogram";
+      this.histogramTabPage.UseVisualStyleBackColor = true;
+      // 
+      // histogramGroupBox
+      // 
+      this.histogramGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.histogramGroupBox.Controls.Add(this.histogramBinsExactRadioButton);
+      this.histogramGroupBox.Controls.Add(this.histogramBinsApproximatelyRadioButton);
+      this.histogramGroupBox.Controls.Add(this.histogramBinsNumericUpDown);
+      this.histogramGroupBox.Controls.Add(this.label16);
+      this.histogramGroupBox.Controls.Add(this.label17);
+      this.histogramGroupBox.Controls.Add(this.histogramAggregationComboBox);
+      this.histogramGroupBox.Location = new System.Drawing.Point(3, 3);
+      this.histogramGroupBox.Name = "histogramGroupBox";
+      this.histogramGroupBox.Size = new System.Drawing.Size(441, 75);
+      this.histogramGroupBox.TabIndex = 2;
+      this.histogramGroupBox.TabStop = false;
+      this.histogramGroupBox.Text = "Histogram Properties";
+      // 
+      // histogramBinsExactRadioButton
+      // 
+      this.histogramBinsExactRadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.histogramBinsExactRadioButton.AutoSize = true;
+      this.histogramBinsExactRadioButton.Location = new System.Drawing.Point(383, 19);
+      this.histogramBinsExactRadioButton.Name = "histogramBinsExactRadioButton";
+      this.histogramBinsExactRadioButton.Size = new System.Drawing.Size(52, 17);
+      this.histogramBinsExactRadioButton.TabIndex = 3;
+      this.histogramBinsExactRadioButton.TabStop = true;
+      this.histogramBinsExactRadioButton.Text = "&Exact";
+      this.histogramBinsExactRadioButton.UseVisualStyleBackColor = true;
+      this.histogramBinsExactRadioButton.CheckedChanged += new System.EventHandler(this.histogramBinsExactRadioButton_CheckedChanged);
+      // 
+      // histogramBinsApproximatelyRadioButton
+      // 
+      this.histogramBinsApproximatelyRadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.histogramBinsApproximatelyRadioButton.AutoSize = true;
+      this.histogramBinsApproximatelyRadioButton.Location = new System.Drawing.Point(287, 19);
+      this.histogramBinsApproximatelyRadioButton.Name = "histogramBinsApproximatelyRadioButton";
+      this.histogramBinsApproximatelyRadioButton.Size = new System.Drawing.Size(90, 17);
+      this.histogramBinsApproximatelyRadioButton.TabIndex = 2;
+      this.histogramBinsApproximatelyRadioButton.TabStop = true;
+      this.histogramBinsApproximatelyRadioButton.Text = "&Approximately";
+      this.histogramBinsApproximatelyRadioButton.UseVisualStyleBackColor = true;
+      // 
+      // histogramBinsNumericUpDown
+      // 
+      this.histogramBinsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.histogramBinsNumericUpDown.Location = new System.Drawing.Point(82, 19);
+      this.histogramBinsNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.histogramBinsNumericUpDown.Name = "histogramBinsNumericUpDown";
+      this.histogramBinsNumericUpDown.Size = new System.Drawing.Size(186, 20);
+      this.histogramBinsNumericUpDown.TabIndex = 1;
+      this.histogramBinsNumericUpDown.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.histogramBinsNumericUpDown.ValueChanged += new System.EventHandler(this.histogramBinsNumericUpDown_ValueChanged);
+      // 
+      // label16
+      // 
+      this.label16.AutoSize = true;
+      this.label16.Location = new System.Drawing.Point(6, 49);
+      this.label16.Name = "label16";
+      this.label16.Size = new System.Drawing.Size(67, 13);
+      this.label16.TabIndex = 0;
+      this.label16.Text = "Aggregation:";
+      // 
+      // label17
+      // 
+      this.label17.AutoSize = true;
+      this.label17.Location = new System.Drawing.Point(6, 21);
+      this.label17.Name = "label17";
+      this.label17.Size = new System.Drawing.Size(30, 13);
+      this.label17.TabIndex = 0;
+      this.label17.Text = "&Bins:";
+      // 
+      // histogramAggregationComboBox
+      // 
+      this.histogramAggregationComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.histogramAggregationComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.histogramAggregationComboBox.FormattingEnabled = true;
+      this.histogramAggregationComboBox.Location = new System.Drawing.Point(82, 45);
+      this.histogramAggregationComboBox.Name = "histogramAggregationComboBox";
+      this.histogramAggregationComboBox.Size = new System.Drawing.Size(353, 21);
+      this.histogramAggregationComboBox.TabIndex = 3;
+      this.histogramAggregationComboBox.SelectedValueChanged += new System.EventHandler(this.histogramAggregationComboBox_SelectedValueChanged);
+      // 
+      // titleTextBox
+      // 
+      this.titleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.titleTextBox.Location = new System.Drawing.Point(66, 0);
+      this.titleTextBox.Name = "titleTextBox";
+      this.titleTextBox.Size = new System.Drawing.Size(389, 20);
+      this.titleTextBox.TabIndex = 1;
+      this.titleTextBox.Validated += new System.EventHandler(this.titleTextBox_Validated);
+      // 
+      // label15
+      // 
+      this.label15.AutoSize = true;
+      this.label15.Location = new System.Drawing.Point(3, 3);
+      this.label15.Name = "label15";
+      this.label15.Size = new System.Drawing.Size(30, 13);
+      this.label15.TabIndex = 0;
+      this.label15.Text = "&Title:";
+      // 
+      // axisFontLabel
+      // 
+      this.axisFontLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.axisFontLabel.AutoSize = true;
+      this.axisFontLabel.Location = new System.Drawing.Point(98, 60);
+      this.axisFontLabel.Name = "axisFontLabel";
+      this.axisFontLabel.Size = new System.Drawing.Size(43, 13);
+      this.axisFontLabel.TabIndex = 7;
+      this.axisFontLabel.Text = "( none )";
+      // 
+      // titleFontLabel
+      // 
+      this.titleFontLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.titleFontLabel.AutoSize = true;
+      this.titleFontLabel.Location = new System.Drawing.Point(98, 31);
+      this.titleFontLabel.Name = "titleFontLabel";
+      this.titleFontLabel.Size = new System.Drawing.Size(43, 13);
+      this.titleFontLabel.TabIndex = 4;
+      this.titleFontLabel.Text = "( none )";
+      // 
+      // axisFontButton
+      // 
+      this.axisFontButton.Location = new System.Drawing.Point(66, 55);
+      this.axisFontButton.Name = "axisFontButton";
+      this.axisFontButton.Size = new System.Drawing.Size(26, 23);
+      this.axisFontButton.TabIndex = 6;
+      this.axisFontButton.Text = "...";
+      this.axisFontButton.UseVisualStyleBackColor = true;
+      this.axisFontButton.Click += new System.EventHandler(this.axisFontButton_Click);
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(3, 60);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(57, 13);
+      this.label3.TabIndex = 5;
+      this.label3.Text = "&Axes Font:";
+      // 
+      // titleFontButton
+      // 
+      this.titleFontButton.Location = new System.Drawing.Point(66, 26);
+      this.titleFontButton.Name = "titleFontButton";
+      this.titleFontButton.Size = new System.Drawing.Size(26, 23);
+      this.titleFontButton.TabIndex = 3;
+      this.titleFontButton.Text = "...";
+      this.titleFontButton.UseVisualStyleBackColor = true;
+      this.titleFontButton.Click += new System.EventHandler(this.titleFontButton_Click);
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(3, 31);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(54, 13);
+      this.label2.TabIndex = 2;
+      this.label2.Text = "&Title Font:";
+      // 
+      // errorProvider
+      // 
+      this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
+      this.errorProvider.ContainerControl = this;
+      // 
+      // titleFontDialog
+      // 
+      this.titleFontDialog.Color = System.Drawing.SystemColors.ControlText;
+      this.titleFontDialog.FontMustExist = true;
+      this.titleFontDialog.ShowColor = true;
+      // 
+      // axisFontDialog
+      // 
+      this.axisFontDialog.Color = System.Drawing.SystemColors.ControlText;
+      // 
+      // DataTableVisualPropertiesControl
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.axisFontLabel);
+      this.Controls.Add(this.label15);
+      this.Controls.Add(this.axisFontButton);
+      this.Controls.Add(this.titleFontLabel);
+      this.Controls.Add(this.label3);
+      this.Controls.Add(this.titleTextBox);
+      this.Controls.Add(this.axisTabControl);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.titleFontButton);
+      this.Name = "DataTableVisualPropertiesControl";
+      this.Size = new System.Drawing.Size(455, 373);
+      this.xAxisPrimaryGroupBox.ResumeLayout(false);
+      this.xAxisPrimaryGroupBox.PerformLayout();
+      this.panel2.ResumeLayout(false);
+      this.panel2.PerformLayout();
+      this.panel1.ResumeLayout(false);
+      this.panel1.PerformLayout();
+      this.xAxisSecondaryGroupBox.ResumeLayout(false);
+      this.xAxisSecondaryGroupBox.PerformLayout();
+      this.panel4.ResumeLayout(false);
+      this.panel4.PerformLayout();
+      this.panel3.ResumeLayout(false);
+      this.panel3.PerformLayout();
+      this.axisTabControl.ResumeLayout(false);
+      this.xAxisTabPage.ResumeLayout(false);
+      this.yAxisTabPage.ResumeLayout(false);
+      this.yAxisSecondaryGroupBox.ResumeLayout(false);
+      this.yAxisSecondaryGroupBox.PerformLayout();
+      this.panel8.ResumeLayout(false);
+      this.panel8.PerformLayout();
+      this.panel7.ResumeLayout(false);
+      this.panel7.PerformLayout();
+      this.yAxisPrimaryGroupBox.ResumeLayout(false);
+      this.yAxisPrimaryGroupBox.PerformLayout();
+      this.panel6.ResumeLayout(false);
+      this.panel6.PerformLayout();
+      this.panel5.ResumeLayout(false);
+      this.panel5.PerformLayout();
+      this.histogramTabPage.ResumeLayout(false);
+      this.histogramGroupBox.ResumeLayout(false);
+      this.histogramGroupBox.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.histogramBinsNumericUpDown)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.TextBox yAxisPrimaryTitleTextBox;
+    private System.Windows.Forms.TextBox yAxisSecondaryTitleTextBox;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.GroupBox xAxisPrimaryGroupBox;
+    private System.Windows.Forms.Label label12;
+    private System.Windows.Forms.Label label9;
+    private System.Windows.Forms.TextBox xAxisPrimaryTitleTextBox;
+    private System.Windows.Forms.Label label11;
+    private System.Windows.Forms.TextBox xAxisPrimaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMaximumAutoRadioButton;
+    private System.Windows.Forms.TextBox xAxisPrimaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMinimumAutoRadioButton;
+    private System.Windows.Forms.GroupBox xAxisSecondaryGroupBox;
+    private System.Windows.Forms.Label label10;
+    private System.Windows.Forms.TextBox xAxisSecondaryTitleTextBox;
+    private System.Windows.Forms.Label label5;
+    private System.Windows.Forms.Label label6;
+    private System.Windows.Forms.TextBox xAxisSecondaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMaximumAutoRadioButton;
+    private System.Windows.Forms.TextBox xAxisSecondaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMinimumAutoRadioButton;
+    private System.Windows.Forms.TabControl axisTabControl;
+    private System.Windows.Forms.TabPage xAxisTabPage;
+    private System.Windows.Forms.TabPage yAxisTabPage;
+    private System.Windows.Forms.GroupBox yAxisSecondaryGroupBox;
+    private System.Windows.Forms.Label label13;
+    private System.Windows.Forms.Label label14;
+    private System.Windows.Forms.TextBox yAxisSecondaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMaximumAutoRadioButton;
+    private System.Windows.Forms.TextBox yAxisSecondaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMinimumAutoRadioButton;
+    private System.Windows.Forms.GroupBox yAxisPrimaryGroupBox;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.Label label8;
+    private System.Windows.Forms.TextBox yAxisPrimaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMaximumAutoRadioButton;
+    private System.Windows.Forms.TextBox yAxisPrimaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMinimumAutoRadioButton;
+    private System.Windows.Forms.ErrorProvider errorProvider;
+    private System.Windows.Forms.FontDialog titleFontDialog;
+    private System.Windows.Forms.Button titleFontButton;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.Button axisFontButton;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label axisFontLabel;
+    private System.Windows.Forms.Label titleFontLabel;
+    private System.Windows.Forms.FontDialog axisFontDialog;
+    private System.Windows.Forms.Label label15;
+    private System.Windows.Forms.TextBox titleTextBox;
+    private System.Windows.Forms.Panel panel1;
+    private System.Windows.Forms.Panel panel2;
+    private System.Windows.Forms.Panel panel4;
+    private System.Windows.Forms.Panel panel3;
+    private System.Windows.Forms.Panel panel6;
+    private System.Windows.Forms.Panel panel5;
+    private System.Windows.Forms.Panel panel7;
+    private System.Windows.Forms.Panel panel8;
+    private System.Windows.Forms.CheckBox xAxisPrimaryLogScaleCheckBox;
+    private System.Windows.Forms.CheckBox xAxisSecondaryLogScaleCheckBox;
+    private System.Windows.Forms.CheckBox yAxisSecondaryLogScaleCheckBox;
+    private System.Windows.Forms.CheckBox yAxisPrimaryLogScaleCheckBox;
+    private System.Windows.Forms.TabPage histogramTabPage;
+    private System.Windows.Forms.GroupBox histogramGroupBox;
+    private System.Windows.Forms.RadioButton histogramBinsExactRadioButton;
+    private System.Windows.Forms.RadioButton histogramBinsApproximatelyRadioButton;
+    private System.Windows.Forms.NumericUpDown histogramBinsNumericUpDown;
+    private System.Windows.Forms.Label label16;
+    private System.Windows.Forms.Label label17;
+    private System.Windows.Forms.ComboBox histogramAggregationComboBox;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.cs	(revision 15719)
@@ -0,0 +1,532 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("DataTable Visual Properties")]
+  public partial class DataTableVisualPropertiesControl : UserControl {
+    protected bool SuppressEvents { get; set; }
+
+    private DataTableVisualProperties content;
+    public DataTableVisualProperties Content {
+      get { return content; }
+      set {
+        bool changed = (value != content);
+        content = value;
+        if (changed) OnContentChanged();
+      }
+    }
+
+    public DataTableVisualPropertiesControl() {
+      InitializeComponent();
+      errorProvider.SetIconAlignment(xAxisPrimaryMinimumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(xAxisPrimaryMaximumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(xAxisSecondaryMinimumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(xAxisSecondaryMaximumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(yAxisPrimaryMinimumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(yAxisPrimaryMaximumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(yAxisSecondaryMinimumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(yAxisSecondaryMaximumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconPadding(xAxisPrimaryMinimumFixedTextBox, 2);
+      errorProvider.SetIconPadding(xAxisPrimaryMaximumFixedTextBox, 2);
+      errorProvider.SetIconPadding(xAxisSecondaryMinimumFixedTextBox, 2);
+      errorProvider.SetIconPadding(xAxisSecondaryMaximumFixedTextBox, 2);
+      errorProvider.SetIconPadding(yAxisPrimaryMinimumFixedTextBox, 2);
+      errorProvider.SetIconPadding(yAxisPrimaryMaximumFixedTextBox, 2);
+      errorProvider.SetIconPadding(yAxisSecondaryMinimumFixedTextBox, 2);
+      errorProvider.SetIconPadding(yAxisSecondaryMaximumFixedTextBox, 2);
+      histogramAggregationComboBox.DataSource = Enum.GetValues(typeof(DataTableVisualProperties.DataTableHistogramAggregation));
+    }
+
+    protected virtual void OnContentChanged() {
+      SuppressEvents = true;
+      try {
+        if (Content == null) {
+          titleFontLabel.Text = "( none )";
+          axisFontLabel.Text = "( none )";
+          titleTextBox.Text = string.Empty;
+
+          xAxisPrimaryTitleTextBox.Text = string.Empty;
+          xAxisPrimaryMinimumAutoRadioButton.Checked = false;
+          xAxisPrimaryMinimumFixedRadioButton.Checked = false;
+          xAxisPrimaryMinimumFixedTextBox.Text = string.Empty;
+          xAxisPrimaryMaximumAutoRadioButton.Checked = false;
+          xAxisPrimaryMaximumFixedRadioButton.Checked = false;
+          xAxisPrimaryMaximumFixedTextBox.Text = string.Empty;
+          xAxisPrimaryLogScaleCheckBox.Checked = false;
+          xAxisSecondaryTitleTextBox.Text = string.Empty;
+          xAxisSecondaryMinimumAutoRadioButton.Checked = false;
+          xAxisSecondaryMinimumFixedRadioButton.Checked = false;
+          xAxisSecondaryMinimumFixedTextBox.Text = string.Empty;
+          xAxisSecondaryMaximumAutoRadioButton.Checked = false;
+          xAxisSecondaryMaximumFixedRadioButton.Checked = false;
+          xAxisSecondaryMaximumFixedTextBox.Text = string.Empty;
+          xAxisSecondaryLogScaleCheckBox.Checked = false;
+
+          yAxisPrimaryTitleTextBox.Text = string.Empty;
+          yAxisPrimaryMinimumAutoRadioButton.Checked = false;
+          yAxisPrimaryMinimumFixedRadioButton.Checked = false;
+          yAxisPrimaryMinimumFixedTextBox.Text = string.Empty;
+          yAxisPrimaryMaximumAutoRadioButton.Checked = false;
+          yAxisPrimaryMaximumFixedRadioButton.Checked = false;
+          yAxisPrimaryMaximumFixedTextBox.Text = string.Empty;
+          yAxisPrimaryLogScaleCheckBox.Checked = false;
+          yAxisSecondaryTitleTextBox.Text = string.Empty;
+          yAxisSecondaryMinimumAutoRadioButton.Checked = false;
+          yAxisSecondaryMinimumFixedRadioButton.Checked = false;
+          yAxisSecondaryMinimumFixedTextBox.Text = string.Empty;
+          yAxisSecondaryMaximumAutoRadioButton.Checked = false;
+          yAxisSecondaryMaximumFixedRadioButton.Checked = false;
+          yAxisSecondaryMaximumFixedTextBox.Text = string.Empty;
+          yAxisSecondaryLogScaleCheckBox.Checked = false;
+
+          histogramBinsNumericUpDown.Value = 1;
+          histogramBinsApproximatelyRadioButton.Checked = false;
+          histogramBinsExactRadioButton.Checked = false;
+          histogramAggregationComboBox.SelectedIndex = -1;
+        } else {
+          titleFontLabel.Text = "( " + FormatFont(Content.TitleFont) + " )";
+          axisFontLabel.Text = "( " + FormatFont(Content.AxisTitleFont) + " )";
+          titleTextBox.Text = Content.Title;
+
+          xAxisPrimaryTitleTextBox.Text = Content.XAxisTitle;
+          xAxisPrimaryMinimumAutoRadioButton.Checked = Content.XAxisMinimumAuto;
+          xAxisPrimaryMinimumFixedRadioButton.Checked = !Content.XAxisMinimumAuto;
+          xAxisPrimaryMinimumFixedTextBox.Text = Content.XAxisMinimumFixedValue.ToString();
+          xAxisPrimaryMaximumAutoRadioButton.Checked = Content.XAxisMaximumAuto;
+          xAxisPrimaryMaximumFixedRadioButton.Checked = !Content.XAxisMaximumAuto;
+          xAxisPrimaryMaximumFixedTextBox.Text = Content.XAxisMaximumFixedValue.ToString();
+          xAxisPrimaryLogScaleCheckBox.Checked = Content.XAxisLogScale;
+          xAxisSecondaryTitleTextBox.Text = Content.SecondXAxisTitle;
+          xAxisSecondaryMinimumAutoRadioButton.Checked = Content.SecondXAxisMinimumAuto;
+          xAxisSecondaryMinimumFixedRadioButton.Checked = !Content.SecondXAxisMinimumAuto;
+          xAxisSecondaryMinimumFixedTextBox.Text = Content.SecondXAxisMinimumFixedValue.ToString();
+          xAxisSecondaryMaximumAutoRadioButton.Checked = Content.SecondXAxisMaximumAuto;
+          xAxisSecondaryMaximumFixedRadioButton.Checked = !Content.SecondXAxisMaximumAuto;
+          xAxisSecondaryMaximumFixedTextBox.Text = Content.SecondXAxisMaximumFixedValue.ToString();
+          xAxisSecondaryLogScaleCheckBox.Checked = Content.SecondXAxisLogScale;
+
+          yAxisPrimaryTitleTextBox.Text = Content.YAxisTitle;
+          yAxisPrimaryMinimumAutoRadioButton.Checked = Content.YAxisMinimumAuto;
+          yAxisPrimaryMinimumFixedRadioButton.Checked = !Content.YAxisMinimumAuto;
+          yAxisPrimaryMinimumFixedTextBox.Text = Content.YAxisMinimumFixedValue.ToString();
+          yAxisPrimaryMaximumAutoRadioButton.Checked = Content.YAxisMaximumAuto;
+          yAxisPrimaryMaximumFixedRadioButton.Checked = !Content.YAxisMaximumAuto;
+          yAxisPrimaryMaximumFixedTextBox.Text = Content.YAxisMaximumFixedValue.ToString();
+          yAxisPrimaryLogScaleCheckBox.Checked = Content.YAxisLogScale;
+          yAxisSecondaryTitleTextBox.Text = Content.SecondYAxisTitle;
+          yAxisSecondaryMinimumAutoRadioButton.Checked = Content.SecondYAxisMinimumAuto;
+          yAxisSecondaryMinimumFixedRadioButton.Checked = !Content.SecondYAxisMinimumAuto;
+          yAxisSecondaryMinimumFixedTextBox.Text = Content.SecondYAxisMinimumFixedValue.ToString();
+          yAxisSecondaryMaximumAutoRadioButton.Checked = Content.SecondYAxisMaximumAuto;
+          yAxisSecondaryMaximumFixedRadioButton.Checked = !Content.SecondYAxisMaximumAuto;
+          yAxisSecondaryMaximumFixedTextBox.Text = Content.SecondYAxisMaximumFixedValue.ToString();
+          yAxisSecondaryLogScaleCheckBox.Checked = Content.SecondYAxisLogScale;
+
+          if (Content.HistogramBins < histogramBinsNumericUpDown.Minimum)
+            histogramBinsNumericUpDown.Value = histogramBinsNumericUpDown.Minimum;
+          else if (Content.HistogramBins > histogramBinsNumericUpDown.Maximum)
+            histogramBinsNumericUpDown.Value = histogramBinsNumericUpDown.Maximum;
+          else histogramBinsNumericUpDown.Value = Content.HistogramBins;
+          histogramBinsApproximatelyRadioButton.Checked = !Content.HistogramExactBins;
+          histogramBinsExactRadioButton.Checked = Content.HistogramExactBins;
+          histogramAggregationComboBox.SelectedItem = Content.HistogramAggregation;
+        }
+      } finally { SuppressEvents = false; }
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void SetEnabledStateOfControls() {
+      axisTabControl.Enabled = Content != null;
+      xAxisPrimaryMinimumFixedTextBox.Enabled = xAxisPrimaryMinimumFixedRadioButton.Checked;
+      xAxisPrimaryMaximumFixedTextBox.Enabled = xAxisPrimaryMaximumFixedRadioButton.Checked;
+      xAxisSecondaryMinimumFixedTextBox.Enabled = xAxisSecondaryMinimumFixedRadioButton.Checked;
+      xAxisSecondaryMaximumFixedTextBox.Enabled = xAxisSecondaryMaximumFixedRadioButton.Checked;
+
+      yAxisPrimaryMinimumFixedTextBox.Enabled = yAxisPrimaryMinimumFixedRadioButton.Checked;
+      yAxisPrimaryMaximumFixedTextBox.Enabled = yAxisPrimaryMaximumFixedRadioButton.Checked;
+      yAxisSecondaryMinimumFixedTextBox.Enabled = yAxisSecondaryMinimumFixedRadioButton.Checked;
+      yAxisSecondaryMaximumFixedTextBox.Enabled = yAxisSecondaryMaximumFixedRadioButton.Checked;
+    }
+
+    #region Event Handlers
+    private void yPrimaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.YAxisTitle = yAxisPrimaryTitleTextBox.Text;
+      }
+    }
+
+    private void ySecondaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.SecondYAxisTitle = yAxisSecondaryTitleTextBox.Text;
+      }
+    }
+
+    private void xPrimaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.XAxisTitle = xAxisPrimaryTitleTextBox.Text;
+      }
+    }
+
+    private void xSecondaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.SecondXAxisTitle = xAxisSecondaryTitleTextBox.Text;
+      }
+    }
+
+    private void xAxisPrimaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.XAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.XAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisPrimaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.XAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.XAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisSecondaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.SecondXAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondXAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisSecondaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.SecondXAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondXAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisPrimaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.YAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.YAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisPrimaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.YAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.YAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisSecondaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.SecondYAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondYAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisSecondaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.SecondYAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondYAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisPrimaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisMinimumAuto = xAxisPrimaryMinimumAutoRadioButton.Checked;
+          if (Content.XAxisMinimumAuto) xAxisPrimaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisPrimaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisMaximumAuto = xAxisPrimaryMaximumAutoRadioButton.Checked;
+          if (Content.XAxisMaximumAuto) xAxisPrimaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisSecondaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxisMinimumAuto = xAxisSecondaryMinimumAutoRadioButton.Checked;
+          if (Content.SecondXAxisMinimumAuto) xAxisSecondaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisSecondaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxisMaximumAuto = xAxisSecondaryMaximumAutoRadioButton.Checked;
+          if (Content.SecondXAxisMaximumAuto) xAxisSecondaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisPrimaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisMinimumAuto = yAxisPrimaryMinimumAutoRadioButton.Checked;
+          if (Content.YAxisMinimumAuto) yAxisPrimaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisPrimaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisMaximumAuto = yAxisPrimaryMaximumAutoRadioButton.Checked;
+          if (Content.YAxisMaximumAuto) yAxisPrimaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisSecondaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxisMinimumAuto = yAxisSecondaryMinimumAutoRadioButton.Checked;
+          if (Content.SecondYAxisMinimumAuto) yAxisSecondaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisSecondaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxisMaximumAuto = yAxisSecondaryMaximumAutoRadioButton.Checked;
+          if (Content.SecondYAxisMaximumAuto) yAxisSecondaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisPrimaryLogScaleCheckBox_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisLogScale = xAxisPrimaryLogScaleCheckBox.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void xAxisSecondaryLogScaleCheckBox_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxisLogScale = xAxisSecondaryLogScaleCheckBox.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void yAxisPrimaryLogScaleCheckBox_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisLogScale = yAxisPrimaryLogScaleCheckBox.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void yAxisSecondaryLogScaleCheckBox_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxisLogScale = yAxisSecondaryLogScaleCheckBox.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void titleFontButton_Click(object sender, System.EventArgs e) {
+      titleFontDialog.Font = Content.TitleFont;
+      titleFontDialog.Color = Content.TitleColor;
+      if (titleFontDialog.ShowDialog() == DialogResult.OK) {
+        Content.TitleFont = titleFontDialog.Font;
+        Content.TitleColor = titleFontDialog.Color;
+        titleFontLabel.Text = "( " + FormatFont(Content.TitleFont) + " )";
+      }
+    }
+
+    private void axisFontButton_Click(object sender, System.EventArgs e) {
+      axisFontDialog.Font = Content.AxisTitleFont;
+      axisFontDialog.Color = Content.AxisTitleColor;
+      if (axisFontDialog.ShowDialog() == DialogResult.OK) {
+        Content.AxisTitleFont = axisFontDialog.Font;
+        Content.AxisTitleColor = axisFontDialog.Color;
+        axisFontLabel.Text = "( " + FormatFont(Content.AxisTitleFont) + " )";
+      }
+    }
+
+    private void titleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.Title = titleTextBox.Text;
+      }
+    }
+
+    private void histogramBinsNumericUpDown_ValueChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.HistogramBins = (int)histogramBinsNumericUpDown.Value;
+      }
+    }
+
+    private void histogramBinsExactRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.HistogramExactBins = histogramBinsExactRadioButton.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void histogramAggregationComboBox_SelectedValueChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.HistogramAggregation = (DataTableVisualProperties.DataTableHistogramAggregation)histogramAggregationComboBox.SelectedValue;
+        } finally { SuppressEvents = false; }
+      }
+    }
+    #endregion
+
+    private string FormatFont(Font f) {
+      if (f == null) return "default";
+      else return f.Name + ", " + f.SizeInPoints.ToString() + "pt, " + f.Style.ToString();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs	(revision 15719)
@@ -0,0 +1,252 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class DataTableVisualPropertiesDialog {
+    /// <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 Windows Form 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.okButton = new System.Windows.Forms.Button();
+      this.cancelButton = new System.Windows.Forms.Button();
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.seriesTabPage = new System.Windows.Forms.TabPage();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.downButton = new System.Windows.Forms.Button();
+      this.upButton = new System.Windows.Forms.Button();
+      this.seriesListView = new System.Windows.Forms.ListView();
+      this.dataRowVisualPropertiesControl = new HeuristicLab.Analysis.Views.DataRowVisualPropertiesControl();
+      this.chartTabPage = new System.Windows.Forms.TabPage();
+      this.dataTableVisualPropertiesControl = new HeuristicLab.Analysis.Views.DataTableVisualPropertiesControl();
+      this.tabControl.SuspendLayout();
+      this.seriesTabPage.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.chartTabPage.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // okButton
+      // 
+      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.okButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.okButton.Location = new System.Drawing.Point(325, 454);
+      this.okButton.Name = "okButton";
+      this.okButton.Size = new System.Drawing.Size(75, 23);
+      this.okButton.TabIndex = 0;
+      this.okButton.Text = "&OK";
+      this.okButton.UseVisualStyleBackColor = true;
+      this.okButton.Click += new System.EventHandler(this.okButton_Click);
+      // 
+      // cancelButton
+      // 
+      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+      this.cancelButton.Location = new System.Drawing.Point(406, 454);
+      this.cancelButton.Name = "cancelButton";
+      this.cancelButton.Size = new System.Drawing.Size(75, 23);
+      this.cancelButton.TabIndex = 1;
+      this.cancelButton.Text = "&Cancel";
+      this.cancelButton.UseVisualStyleBackColor = true;
+      this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+      // 
+      // tabControl
+      // 
+      this.tabControl.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)));
+      this.tabControl.Controls.Add(this.seriesTabPage);
+      this.tabControl.Controls.Add(this.chartTabPage);
+      this.tabControl.Location = new System.Drawing.Point(12, 12);
+      this.tabControl.Name = "tabControl";
+      this.tabControl.SelectedIndex = 0;
+      this.tabControl.Size = new System.Drawing.Size(469, 436);
+      this.tabControl.TabIndex = 2;
+      // 
+      // seriesTabPage
+      // 
+      this.seriesTabPage.Controls.Add(this.splitContainer);
+      this.seriesTabPage.Location = new System.Drawing.Point(4, 22);
+      this.seriesTabPage.Name = "seriesTabPage";
+      this.seriesTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.seriesTabPage.Size = new System.Drawing.Size(461, 410);
+      this.seriesTabPage.TabIndex = 0;
+      this.seriesTabPage.Text = "Series";
+      this.seriesTabPage.UseVisualStyleBackColor = true;
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.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)));
+      this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+      this.splitContainer.Location = new System.Drawing.Point(0, 0);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.downButton);
+      this.splitContainer.Panel1.Controls.Add(this.upButton);
+      this.splitContainer.Panel1.Controls.Add(this.seriesListView);
+      this.splitContainer.Panel1MinSize = 20;
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.dataRowVisualPropertiesControl);
+      this.splitContainer.Panel2MinSize = 50;
+      this.splitContainer.Size = new System.Drawing.Size(461, 410);
+      this.splitContainer.SplitterDistance = 125;
+      this.splitContainer.TabIndex = 0;
+      // 
+      // downButton
+      // 
+      this.downButton.Enabled = false;
+      this.downButton.Location = new System.Drawing.Point(35, 3);
+      this.downButton.Name = "downButton";
+      this.downButton.Size = new System.Drawing.Size(26, 23);
+      this.downButton.TabIndex = 1;
+      this.downButton.Text = "Down";
+      this.downButton.UseVisualStyleBackColor = true;
+      this.downButton.Click += new System.EventHandler(this.downButton_Click);
+      // 
+      // upButton
+      // 
+      this.upButton.Enabled = false;
+      this.upButton.Location = new System.Drawing.Point(3, 3);
+      this.upButton.Name = "upButton";
+      this.upButton.Size = new System.Drawing.Size(26, 23);
+      this.upButton.TabIndex = 0;
+      this.upButton.Text = "Up";
+      this.upButton.UseVisualStyleBackColor = true;
+      this.upButton.Click += new System.EventHandler(this.upButton_Click);
+      // 
+      // seriesListView
+      // 
+      this.seriesListView.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)));
+      this.seriesListView.HideSelection = false;
+      this.seriesListView.Location = new System.Drawing.Point(3, 32);
+      this.seriesListView.MultiSelect = false;
+      this.seriesListView.Name = "seriesListView";
+      this.seriesListView.ShowGroups = false;
+      this.seriesListView.Size = new System.Drawing.Size(119, 375);
+      this.seriesListView.TabIndex = 2;
+      this.seriesListView.UseCompatibleStateImageBehavior = false;
+      this.seriesListView.View = System.Windows.Forms.View.List;
+      this.seriesListView.SelectedIndexChanged += new System.EventHandler(this.seriesListView_SelectedIndexChanged);
+      // 
+      // dataRowVisualPropertiesControl
+      // 
+      this.dataRowVisualPropertiesControl.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)));
+      this.dataRowVisualPropertiesControl.Content = null;
+      this.dataRowVisualPropertiesControl.Location = new System.Drawing.Point(3, 26);
+      this.dataRowVisualPropertiesControl.Name = "dataRowVisualPropertiesControl";
+      this.dataRowVisualPropertiesControl.Size = new System.Drawing.Size(326, 381);
+      this.dataRowVisualPropertiesControl.TabIndex = 0;
+      // 
+      // chartTabPage
+      // 
+      this.chartTabPage.Controls.Add(this.dataTableVisualPropertiesControl);
+      this.chartTabPage.Location = new System.Drawing.Point(4, 22);
+      this.chartTabPage.Name = "chartTabPage";
+      this.chartTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.chartTabPage.Size = new System.Drawing.Size(461, 381);
+      this.chartTabPage.TabIndex = 1;
+      this.chartTabPage.Text = "Chart";
+      this.chartTabPage.UseVisualStyleBackColor = true;
+      // 
+      // dataTableVisualPropertiesControl
+      // 
+      this.dataTableVisualPropertiesControl.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)));
+      this.dataTableVisualPropertiesControl.Content = null;
+      this.dataTableVisualPropertiesControl.Location = new System.Drawing.Point(3, 6);
+      this.dataTableVisualPropertiesControl.Name = "dataTableVisualPropertiesControl";
+      this.dataTableVisualPropertiesControl.Size = new System.Drawing.Size(455, 372);
+      this.dataTableVisualPropertiesControl.TabIndex = 0;
+      // 
+      // DataTableVisualPropertiesDialog
+      // 
+      this.AcceptButton = this.okButton;
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.CancelButton = this.cancelButton;
+      this.ClientSize = new System.Drawing.Size(493, 489);
+      this.Controls.Add(this.tabControl);
+      this.Controls.Add(this.cancelButton);
+      this.Controls.Add(this.okButton);
+      this.MaximizeBox = false;
+      this.MinimizeBox = false;
+      this.Name = "DataTableVisualPropertiesDialog";
+      this.ShowIcon = false;
+      this.ShowInTaskbar = false;
+      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+      this.Text = "Customize Visual Properties";
+      this.TopMost = true;
+      this.tabControl.ResumeLayout(false);
+      this.seriesTabPage.ResumeLayout(false);
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+      this.splitContainer.ResumeLayout(false);
+      this.chartTabPage.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button okButton;
+    private System.Windows.Forms.Button cancelButton;
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage seriesTabPage;
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.Windows.Forms.ListView seriesListView;
+    private System.Windows.Forms.TabPage chartTabPage;
+    private DataRowVisualPropertiesControl dataRowVisualPropertiesControl;
+    private DataTableVisualPropertiesControl dataTableVisualPropertiesControl;
+    private System.Windows.Forms.Button downButton;
+    private System.Windows.Forms.Button upButton;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.cs	(revision 15719)
@@ -0,0 +1,179 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Common.Resources;
+
+namespace HeuristicLab.Analysis.Views {
+  public partial class DataTableVisualPropertiesDialog : Form {
+    protected bool SuppressEvents { get; set; }
+    protected DataTable Content { get; private set; }
+    private DataTableVisualProperties originalDataTableVPs;
+    private Dictionary<string, DataRowVisualProperties> originalDataRowVPs;
+
+    private HashSet<string> modifiedDisplayNames;
+    public IEnumerable<string> RowsWithModifiedDisplayNames { get { return modifiedDisplayNames.AsEnumerable(); } }
+
+    public DataTableVisualPropertiesDialog(DataTable dataTable) {
+      InitializeComponent();
+      #region Prepare controls
+      upButton.Text = string.Empty;
+      upButton.Image = VSImageLibrary.ArrowUp;
+      downButton.Text = string.Empty;
+      downButton.Image = VSImageLibrary.ArrowDown;
+      seriesListView.Items.Clear();
+      seriesListView.SmallImageList = new ImageList();
+      seriesListView.SmallImageList.Images.Add(VSImageLibrary.Graph);
+      #endregion
+
+      Content = dataTable;
+      originalDataTableVPs = (DataTableVisualProperties)Content.VisualProperties.Clone();
+      originalDataRowVPs = new Dictionary<string, DataRowVisualProperties>();
+      foreach (DataRow row in Content.Rows)
+        originalDataRowVPs.Add(row.Name, (DataRowVisualProperties)row.VisualProperties.Clone());
+
+      dataTableVisualPropertiesControl.Content = Content.VisualProperties;
+
+      modifiedDisplayNames = new HashSet<string>();
+      FillSeriesListView();
+      RegisterContentEvents();
+    }
+
+    private void RegisterContentEvents() {
+      foreach (DataRow row in Content.Rows) {
+        row.VisualProperties.PropertyChanged += new PropertyChangedEventHandler(Row_VisualProperties_PropertyChanged);
+      }
+    }
+
+    private void DeregisterContentEvents() {
+      foreach (DataRow row in Content.Rows) {
+        row.VisualProperties.PropertyChanged -= new PropertyChangedEventHandler(Row_VisualProperties_PropertyChanged);
+      }
+    }
+
+    protected override void OnClosing(CancelEventArgs e) {
+      DeregisterContentEvents();
+      Application.DoEvents();
+      base.OnClosing(e);
+    }
+
+    private void Row_VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      foreach (DataRow row in Content.Rows) {
+        if (e.PropertyName == "DisplayName" && row.VisualProperties == sender) {
+          modifiedDisplayNames.Add(row.Name);
+          break;
+        }
+      }
+    }
+
+    private void seriesListView_SelectedIndexChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents) {
+        if (seriesListView.SelectedItems.Count != 1) {
+          dataRowVisualPropertiesControl.Content = null;
+          upButton.Enabled = downButton.Enabled = false;
+        } else {
+          string rowName = seriesListView.SelectedItems[0].Text;
+          dataRowVisualPropertiesControl.Content = Content.Rows[rowName].VisualProperties;
+          upButton.Enabled = seriesListView.SelectedIndices[0] > 0;
+          downButton.Enabled = seriesListView.SelectedIndices[0] < seriesListView.Items.Count - 1;
+        }
+      }
+    }
+
+    private void okButton_Click(object sender, System.EventArgs e) {
+      DialogResult = DialogResult.OK;
+      Close();
+    }
+
+    private void cancelButton_Click(object sender, System.EventArgs e) {
+      DialogResult = DialogResult.Cancel;
+      foreach (DataRow row in Content.Rows) {
+        row.VisualProperties = originalDataRowVPs[row.Name];
+      }
+      modifiedDisplayNames.Clear();
+      Content.VisualProperties = originalDataTableVPs;
+      Close();
+    }
+
+    private void upButton_Click(object sender, System.EventArgs e) {
+      if (seriesListView.SelectedIndices.Count == 1 && seriesListView.SelectedIndices[0] > 0) {
+        int index = seriesListView.SelectedIndices[0];
+        SuppressEvents = true;
+        try {
+          seriesListView.BeginUpdate();
+          ListViewItem selectedSeriesItem = seriesListView.Items[index];
+          seriesListView.Items.RemoveAt(index);
+          ListViewItem temp = seriesListView.Items[index - 1];
+          seriesListView.Items.RemoveAt(index - 1);
+          seriesListView.Items.Insert(index - 1, selectedSeriesItem);
+          seriesListView.Items.Insert(index, temp);
+          seriesListView.SelectedIndices.Clear();
+          seriesListView.EndUpdate();
+        } finally { SuppressEvents = false; }
+        seriesListView.SelectedIndices.Add(index - 1);
+        UpdateAllSeriesPositions();
+      }
+    }
+
+    private void downButton_Click(object sender, System.EventArgs e) {
+      if (seriesListView.SelectedIndices.Count == 1 && seriesListView.SelectedIndices[0] < seriesListView.Items.Count - 1) {
+        int index = seriesListView.SelectedIndices[0];
+        SuppressEvents = true;
+        try {
+          seriesListView.BeginUpdate();
+          ListViewItem temp = seriesListView.Items[index + 1];
+          seriesListView.Items.RemoveAt(index + 1);
+          ListViewItem selectedSeriesItem = seriesListView.Items[index];
+          seriesListView.Items.RemoveAt(index);
+          seriesListView.Items.Insert(index, temp);
+          seriesListView.Items.Insert(index + 1, selectedSeriesItem);
+          seriesListView.SelectedIndices.Clear();
+          seriesListView.EndUpdate();
+        } finally { SuppressEvents = false; }
+        seriesListView.SelectedIndices.Add(index + 1);
+        UpdateAllSeriesPositions();
+      }
+    }
+
+    #region Helpers
+    private void FillSeriesListView() {
+      seriesListView.SelectedIndices.Clear();
+      foreach (DataRow row in Content.Rows) {
+        seriesListView.Items.Add(new ListViewItem(row.Name, 0));
+      }
+      if (seriesListView.Items.Count > 0)
+        seriesListView.SelectedIndices.Add(0);
+    }
+
+    private void UpdateAllSeriesPositions() {
+      Dictionary<string, DataRow> rows = Content.Rows.ToDictionary(x => x.Name);
+      Content.Rows.Clear();
+      for (int i = 0; i < seriesListView.Items.Count; i++) {
+        ListViewItem item = seriesListView.Items[i];
+        Content.Rows.Add(rows[item.Text]);
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/GanttDataView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/GanttDataView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/GanttDataView.Designer.cs	(revision 15719)
@@ -0,0 +1,75 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class GanttDataView {
+    /// <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.ganttChart = new HeuristicLab.Visualization.ChartControlsExtensions.GanttChart();
+      this.SuspendLayout();
+      // 
+      // ganttChart
+      // 
+      this.ganttChart.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.ganttChart.Location = new System.Drawing.Point(0, 0);
+      this.ganttChart.Name = "ganttChart";
+      this.ganttChart.Size = new System.Drawing.Size(367, 249);
+      this.ganttChart.TabIndex = 0;
+      // 
+      // GanttDataView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.ganttChart);
+      this.Name = "GanttDataView";
+      this.Size = new System.Drawing.Size(367, 249);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private Visualization.ChartControlsExtensions.GanttChart ganttChart;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/GanttDataView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/GanttDataView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/GanttDataView.cs	(revision 15719)
@@ -0,0 +1,177 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("Gantt Data View")]
+  [Content(typeof(GanttData), IsDefaultView = true)]
+  public partial class GanttDataView : ItemView {
+
+    public new GanttData Content {
+      get { return (GanttData)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public GanttDataView() {
+      InitializeComponent();
+    }
+
+    #region De/Register Content Events
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.Rows.ItemsAdded += GanttRowsOnChanged;
+      Content.Rows.ItemsRemoved += GanttRowsOnRemoved;
+      Content.Rows.ItemsReplaced += GanttRowsOnChanged;
+      Content.Rows.CollectionReset += GanttRowsOnChanged;
+      Content.CategoryColors.ItemsAdded += GanttCategoryColorsOnChanged;
+      Content.CategoryColors.ItemsRemoved += GanttCategoryColorsOnChanged;
+      Content.CategoryColors.ItemsReplaced += GanttCategoryColorsOnChanged;
+      Content.CategoryColors.CollectionReset += GanttCategoryColorsOnChanged;
+      foreach (var row in Content.Rows)
+        RegisterGanttRowEvents(row);
+    }
+
+    private void RegisterGanttRowEvents(GanttRow row) {
+      row.Items.ItemsAdded += GanttRowItemsOnChanged;
+      row.Items.ItemsReplaced += GanttRowItemsOnChanged;
+      row.Items.ItemsRemoved += GanttRowItemsOnRemoved;
+      row.Items.CollectionReset += GanttRowItemsOnChanged;
+      foreach (var item in row.Items)
+        RegisterGanttRowItemEvents(item);
+    }
+
+    private void RegisterGanttRowItemEvents(GanttItem item) {
+      item.PropertyChanged += GanttRowItemsItemOnChanged;
+    }
+
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+      Content.Rows.ItemsAdded -= GanttRowsOnChanged;
+      Content.Rows.ItemsRemoved -= GanttRowsOnRemoved;
+      Content.Rows.ItemsReplaced -= GanttRowsOnChanged;
+      Content.Rows.CollectionReset -= GanttRowsOnChanged;
+      Content.CategoryColors.ItemsAdded -= GanttCategoryColorsOnChanged;
+      Content.CategoryColors.ItemsRemoved -= GanttCategoryColorsOnChanged;
+      Content.CategoryColors.ItemsReplaced -= GanttCategoryColorsOnChanged;
+      Content.CategoryColors.CollectionReset -= GanttCategoryColorsOnChanged;
+      foreach (var row in Content.Rows)
+        DeregisterGanttRowEvents(row);
+    }
+
+    private void DeregisterGanttRowEvents(GanttRow row) {
+      row.Items.ItemsAdded -= GanttRowItemsOnChanged;
+      row.Items.ItemsReplaced -= GanttRowItemsOnChanged;
+      row.Items.ItemsRemoved -= GanttRowItemsOnRemoved;
+      row.Items.CollectionReset -= GanttRowItemsOnChanged;
+      foreach (var item in row.Items)
+        DeregisterGanttRowItemEvents(item);
+    }
+
+    private void DeregisterGanttRowItemEvents(GanttItem item) {
+      item.PropertyChanged -= GanttRowItemsItemOnChanged;
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+
+      UpdateVisualization();
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      ganttChart.Enabled = !Locked && !ReadOnly && Content != null;
+    }
+
+    private void UpdateVisualization() {
+      ganttChart.Reset();
+
+      if (Content == null) return;
+
+      var colors = (KnownColor[])Enum.GetValues(typeof(KnownColor));
+
+      var categories = Content.Rows.SelectMany(x => x.Items.Select(y => y.Category ?? string.Empty)).Distinct();
+      foreach (var cat in categories) {
+        Color color;
+        if (!Content.CategoryColors.TryGetValue(cat, out color)) {
+          // if no color is defined, a random color is chosen for each category
+          var rand = new Random(cat.GetHashCode());
+          color = Color.FromKnownColor(colors[rand.Next(colors.Length)]);
+        }
+        ganttChart.AddCategory(cat, color);
+      }
+      
+      ganttChart.Hide();
+      ganttChart.Title = string.IsNullOrWhiteSpace(Content.Name) ? null : Content.Name;
+      foreach (var row in Content.Rows) {
+        foreach (var item in row.Items) {
+          ganttChart.AddData(row.Name, item.Category ?? string.Empty, item.StartDate, item.EndDate, item.ToolTip, item.ShowLabel);
+        }
+      }
+      ganttChart.Show();
+    }
+
+    #region Content Event Handlers
+    private void GanttRowsOnChanged(object sender, CollectionItemsChangedEventArgs<GanttRow> e) {
+      foreach (var row in e.Items)
+        RegisterGanttRowEvents(row);
+      foreach (var row in e.OldItems)
+        DeregisterGanttRowEvents(row);
+
+      UpdateVisualization();
+    }
+    private void GanttRowsOnRemoved(object sender, CollectionItemsChangedEventArgs<GanttRow> e) {
+      foreach (var row in e.Items)
+        DeregisterGanttRowEvents(row);
+
+      UpdateVisualization();
+    }
+    private void GanttCategoryColorsOnChanged(object sender, EventArgs e) {
+      UpdateVisualization();
+    }
+    private void GanttRowItemsOnChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<GanttItem>> e) {
+      foreach (var item in e.Items)
+        RegisterGanttRowItemEvents(item.Value);
+      foreach (var item in e.OldItems)
+        DeregisterGanttRowItemEvents(item.Value);
+
+      UpdateVisualization();
+    }
+    private void GanttRowItemsOnRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<GanttItem>> e) {
+      foreach (var item in e.Items)
+        DeregisterGanttRowItemEvents(item.Value);
+
+      UpdateVisualization();
+    }
+    private void GanttRowItemsItemOnChanged(object sender, EventArgs e) {
+      UpdateVisualization();
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapHistoryView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapHistoryView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapHistoryView.Designer.cs	(revision 15719)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class HeatMapHistoryView {
+    /// <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) {
+        if (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() {
+      components = new System.ComponentModel.Container();
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+    }
+
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapHistoryView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapHistoryView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapHistoryView.cs	(revision 15719)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("HeatMapHistory View")]
+  [Content(typeof(HeatMapHistory), true)]
+  public partial class HeatMapHistoryView : MovieView<HeatMap> {
+    public HeatMapHistoryView() {
+      InitializeComponent();
+      itemsGroupBox.Text = "Heat Map";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.Designer.cs	(revision 15719)
@@ -0,0 +1,178 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class HeatMapView {
+    /// <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() {
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HeatMapView));
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.colorsPictureBox = new System.Windows.Forms.PictureBox();
+      this.minimumLabel = new System.Windows.Forms.Label();
+      this.maximumLabel = new System.Windows.Forms.Label();
+      this.grayscalesPictureBox = new System.Windows.Forms.PictureBox();
+      this.grayscaleCheckBox = new System.Windows.Forms.CheckBox();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.colorsPictureBox)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.grayscalesPictureBox)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      this.chart.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)));
+      this.chart.BorderlineColor = System.Drawing.Color.Black;
+      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
+      chartArea1.AxisX.IntervalAutoMode = System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode.VariableCount;
+      chartArea1.AxisX.LabelAutoFitStyle = ((System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles)((System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles.IncreaseFont | System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles.DecreaseFont)));
+      chartArea1.AxisX.Title = "Column Index";
+      chartArea1.AxisY.Title = "Row Index";
+      chartArea1.CursorX.IsUserEnabled = true;
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
+      chartArea1.Name = "Default";
+      this.chart.ChartAreas.Add(chartArea1);
+      this.chart.Location = new System.Drawing.Point(0, 0);
+      this.chart.Name = "chart";
+      this.chart.Size = new System.Drawing.Size(406, 463);
+      this.chart.TabIndex = 0;
+      this.chart.Text = "chart";
+      title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      title1.Name = "Default";
+      title1.Text = "Heat Map";
+      this.chart.Titles.Add(title1);
+      // 
+      // colorsPictureBox
+      // 
+      this.colorsPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.colorsPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+      this.colorsPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("colorsPictureBox.Image")));
+      this.colorsPictureBox.Location = new System.Drawing.Point(430, 28);
+      this.colorsPictureBox.Name = "colorsPictureBox";
+      this.colorsPictureBox.Size = new System.Drawing.Size(35, 393);
+      this.colorsPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+      this.colorsPictureBox.TabIndex = 11;
+      this.colorsPictureBox.TabStop = false;
+      // 
+      // minimumLabel
+      // 
+      this.minimumLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.minimumLabel.BackColor = System.Drawing.Color.Transparent;
+      this.minimumLabel.Location = new System.Drawing.Point(412, 424);
+      this.minimumLabel.Name = "minimumLabel";
+      this.minimumLabel.Size = new System.Drawing.Size(73, 19);
+      this.minimumLabel.TabIndex = 2;
+      this.minimumLabel.Text = "0.0";
+      this.minimumLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+      // 
+      // maximumLabel
+      // 
+      this.maximumLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.maximumLabel.BackColor = System.Drawing.Color.Transparent;
+      this.maximumLabel.Location = new System.Drawing.Point(412, 0);
+      this.maximumLabel.Name = "maximumLabel";
+      this.maximumLabel.Size = new System.Drawing.Size(73, 25);
+      this.maximumLabel.TabIndex = 1;
+      this.maximumLabel.Text = "1.0";
+      this.maximumLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
+      // 
+      // grayscalesPictureBox
+      // 
+      this.grayscalesPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.grayscalesPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+      this.grayscalesPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("grayscalesPictureBox.Image")));
+      this.grayscalesPictureBox.Location = new System.Drawing.Point(430, 28);
+      this.grayscalesPictureBox.Name = "grayscalesPictureBox";
+      this.grayscalesPictureBox.Size = new System.Drawing.Size(35, 393);
+      this.grayscalesPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+      this.grayscalesPictureBox.TabIndex = 15;
+      this.grayscalesPictureBox.TabStop = false;
+      this.grayscalesPictureBox.Visible = false;
+      // 
+      // grayscaleCheckBox
+      // 
+      this.grayscaleCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.grayscaleCheckBox.AutoSize = true;
+      this.grayscaleCheckBox.Location = new System.Drawing.Point(412, 446);
+      this.grayscaleCheckBox.Name = "grayscaleCheckBox";
+      this.grayscaleCheckBox.Size = new System.Drawing.Size(73, 17);
+      this.grayscaleCheckBox.TabIndex = 3;
+      this.grayscaleCheckBox.Text = "Grayscale";
+      this.grayscaleCheckBox.UseVisualStyleBackColor = true;
+      this.grayscaleCheckBox.CheckedChanged += new System.EventHandler(this.grayscaledImagesCheckBox_CheckedChanged);
+      // 
+      // HeatMapView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.grayscaleCheckBox);
+      this.Controls.Add(this.minimumLabel);
+      this.Controls.Add(this.maximumLabel);
+      this.Controls.Add(this.colorsPictureBox);
+      this.Controls.Add(this.chart);
+      this.Controls.Add(this.grayscalesPictureBox);
+      this.Name = "HeatMapView";
+      this.Size = new System.Drawing.Size(485, 463);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.colorsPictureBox)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.grayscalesPictureBox)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+    protected System.Windows.Forms.PictureBox colorsPictureBox;
+    protected System.Windows.Forms.Label minimumLabel;
+    protected System.Windows.Forms.Label maximumLabel;
+    protected System.Windows.Forms.PictureBox grayscalesPictureBox;
+    protected System.Windows.Forms.CheckBox grayscaleCheckBox;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.cs	(revision 15719)
@@ -0,0 +1,146 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Common;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("HeatMap View")]
+  [Content(typeof(HeatMap), true)]
+  public partial class HeatMapView : ItemView {
+    protected static Color[] colors = new Color[256];
+    public new HeatMap Content {
+      get { return (HeatMap)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public HeatMapView() {
+      InitializeComponent();
+      chart.CustomizeAllChartAreas();
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.TitleChanged -= new EventHandler(Content_TitleChanged);
+      Content.MinimumChanged -= new EventHandler(Content_MinimumChanged);
+      Content.MaximumChanged -= new EventHandler(Content_MaximumChanged);
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.TitleChanged += new EventHandler(Content_TitleChanged);
+      Content.MinimumChanged += new EventHandler(Content_MinimumChanged);
+      Content.MaximumChanged += new EventHandler(Content_MaximumChanged);
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        chart.Series.Clear();
+        chart.Titles[0].Text = "Heat Map";
+        minimumLabel.Text = "0.0";
+        maximumLabel.Text = "1.0";
+      } else {
+        chart.Titles[0].Text = Content.Title;
+        minimumLabel.Text = Content.Minimum.ToString();
+        maximumLabel.Text = Content.Maximum.ToString();
+        UpdatePoints();
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      chart.Enabled = Content != null;
+      grayscaleCheckBox.Enabled = Content != null;
+    }
+
+    protected virtual void UpdatePoints() {
+      chart.Series.Clear();
+      Series series = new Series();
+      series.ChartType = SeriesChartType.Point;
+      series.XValueType = ChartValueType.Int32;
+      series.YValueType = ChartValueType.Int32;
+      series.YAxisType = AxisType.Primary;
+      for (int i = 1; i < Content.Rows + 1; i++)
+        for (int j = 1; j < Content.Columns + 1; j++)
+          series.Points.Add(CreateDataPoint(j, i, Content[i - 1, j - 1]));
+      chart.ChartAreas[0].AxisX.Minimum = 0;
+      chart.ChartAreas[0].AxisX.Maximum = Content.Columns + 1;
+      chart.ChartAreas[0].AxisY.Minimum = 0;
+      chart.ChartAreas[0].AxisY.Maximum = Content.Rows + 1;
+      chart.Series.Add(series);
+    }
+
+    protected virtual DataPoint CreateDataPoint(int index1, int index2, double value) {
+      DataPoint p = new DataPoint(index1, index2);
+      p.Color = GetDataPointColor(value, Content.Minimum, Content.Maximum, grayscaleCheckBox.Checked);
+      p.MarkerStyle = MarkerStyle.Square;
+      return p;
+    }
+
+    protected virtual Color GetDataPointColor(double value, double min, double max, bool grayscale) {
+      IList<Color> colors = grayscale ? ColorGradient.GrayscaledColors : ColorGradient.Colors;
+      int index = (int)((colors.Count - 1) * (value - min) / (max - min));
+      if (index >= colors.Count) index = colors.Count - 1;
+      if (index < 0) index = 0;
+      return colors[index];
+    }
+
+    #region Content Events
+    protected virtual void Content_TitleChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_TitleChanged), sender, e);
+      else {
+        chart.Titles[0].Text = Content.Title;
+      }
+    }
+    protected virtual void Content_MinimumChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_MinimumChanged), sender, e);
+      else {
+        minimumLabel.Text = Content.Minimum.ToString();
+        UpdatePoints();
+      }
+    }
+    protected virtual void Content_MaximumChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_MaximumChanged), sender, e);
+      else {
+        maximumLabel.Text = Content.Maximum.ToString();
+        UpdatePoints();
+      }
+    }
+    #endregion
+
+    #region Control Events
+    protected virtual void grayscaledImagesCheckBox_CheckedChanged(object sender, EventArgs e) {
+      grayscalesPictureBox.Visible = grayscaleCheckBox.Checked;
+      colorsPictureBox.Visible = !grayscaleCheckBox.Checked;
+      UpdatePoints();
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.resx
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.resx	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeatMapView.resx	(revision 15719)
@@ -0,0 +1,1923 @@
+﻿<?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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="colorsPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        Qk0S0gAAAAAAADYAAAAoAAAAMQAAAGsBAAABABgAAAAAAAAAAADEDgAAxA4AAAAAAAAAAAAA/wAe/wAe
+        /wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe
+        /wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe/wAe
+        /wAe/wAe/wAe/wAe/wAe/wAe/wAeAP8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8A
+        G/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8A
+        G/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AG/8AGwD/ABj/ABj/ABj/
+        ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/
+        ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/ABj/
+        ABj/ABj/ABj/ABj/ABj/ABgA/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV
+        /wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV
+        /wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAV/wAVAP8AEv8AEv8AEv8AEv8A
+        Ev8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8A
+        Ev8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8AEv8A
+        Ev8AEv8AEv8AEv8AEgD/AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//
+        AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//
+        AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA//AA8A/wAM/wAM/wAM/wAM/wAM/wAM
+        /wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM
+        /wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM/wAM
+        /wAM/wAM/wAMAP8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8A
+        Cf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8A
+        Cf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACf8ACQD/AAb/AAb/AAb/AAb/AAb/AAb/AAb/
+        AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/
+        AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/AAb/
+        AAb/AAYA/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG
+        /wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG
+        /wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAGAP8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        AwD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/
+        AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/
+        AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAAA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA
+        /wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA
+        /wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMAAP8G
+        AP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8G
+        AP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8G
+        AP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAAD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/
+        CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/
+        CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQAA/wwA/wwA
+        /wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA
+        /wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA
+        /wwA/wwA/wwA/wwA/wwA/wwA/wwAAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8P
+        AP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8P
+        AP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAAD/EgD/EgD/EgD/
+        EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/
+        EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/
+        EgD/EgD/EgD/EgD/EgD/EgAA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA
+        /xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA
+        /xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUAAP8YAP8YAP8YAP8YAP8Y
+        AP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8Y
+        AP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8Y
+        AP8YAP8YAP8YAP8YAAD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/
+        GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/
+        GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwAA/x4A/x4A/x4A/x4A/x4A/x4A
+        /x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A
+        /x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A
+        /x4A/x4A/x4AAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8h
+        AP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8h
+        AP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/
+        JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/
+        JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/
+        JAD/JAAA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA
+        /ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA
+        /ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycAAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8q
+        AP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8q
+        AP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8qAP8q
+        AAD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/
+        LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/
+        LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQD/LQAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA
+        /zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA
+        /zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAA/zAAAP8z
+        AP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8z
+        AP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8z
+        AP8zAP8zAP8zAP8zAP8zAP8zAP8zAP8zAAD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/
+        NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/
+        NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgD/NgAA/zkA/zkA
+        /zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA
+        /zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA/zkA
+        /zkA/zkA/zkA/zkA/zkA/zkA/zkAAP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88
+        AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88
+        AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AP88AAD/PwD/PwD/PwD/
+        PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/
+        PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/PwD/
+        PwD/PwD/PwD/PwD/PwD/PwAA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA
+        /0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA
+        /0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IA/0IAAP9FAP9FAP9FAP9FAP9F
+        AP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9F
+        AP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9FAP9F
+        AP9FAP9FAP9FAP9FAAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/
+        SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/
+        SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAD/SAAA/0sA/0sA/0sA/0sA/0sA/0sA
+        /0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA
+        /0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA/0sA
+        /0sA/0sA/0sAAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9L
+        AP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9L
+        AP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAAD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/
+        TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/
+        TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/
+        TgD/TgAA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA
+        /1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA
+        /1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EAAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9U
+        AP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9U
+        AP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9U
+        AAD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/
+        VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/
+        VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwAA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA
+        /1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA
+        /1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oAAP9d
+        AP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9d
+        AP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9d
+        AP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/
+        YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/
+        YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAAA/2MA/2MA
+        /2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA
+        /2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA
+        /2MA/2MA/2MA/2MA/2MA/2MA/2MAAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9m
+        AP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9m
+        AP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAAD/aQD/aQD/aQD/
+        aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/
+        aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/
+        aQD/aQD/aQD/aQD/aQD/aQAA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA
+        /2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA
+        /2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wAAP9vAP9vAP9vAP9vAP9v
+        AP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9v
+        AP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9v
+        AP9vAP9vAP9vAP9vAAD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/
+        cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/
+        cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgAA/3UA/3UA/3UA/3UA/3UA/3UA
+        /3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA
+        /3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA
+        /3UA/3UA/3UAAP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94
+        AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94
+        AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AP94AAD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/
+        ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/
+        ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/ewD/
+        ewD/ewAA/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A
+        /34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34A
+        /34A/34A/34A/34A/34A/34A/34A/34A/34A/34A/34AAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+B
+        AP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+B
+        AP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+BAP+B
+        AAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/
+        hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/
+        hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAD/hAAA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA
+        /4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA
+        /4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cA/4cAAP+K
+        AP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+K
+        AP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+K
+        AP+KAP+KAP+KAP+KAP+KAP+KAP+KAP+KAAD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/
+        jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/
+        jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQD/jQAA/5AA/5AA
+        /5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA
+        /5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA/5AA
+        /5AA/5AA/5AA/5AA/5AA/5AA/5AAAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+T
+        AP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+T
+        AP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAP+TAAD/lgD/lgD/lgD/
+        lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/
+        lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/lgD/
+        lgD/lgD/lgD/lgD/lgD/lgAA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA
+        /5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA
+        /5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kA/5kAAP+ZAP+ZAP+ZAP+ZAP+Z
+        AP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+Z
+        AP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+Z
+        AP+ZAP+ZAP+ZAP+ZAAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/
+        nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/
+        nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAAA/58A/58A/58A/58A/58A/58A
+        /58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A
+        /58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A
+        /58A/58A/58AAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+i
+        AP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+i
+        AP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAAD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/
+        pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/
+        pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/
+        pQD/pQAA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA
+        /6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA
+        /6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gAAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+r
+        AP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+r
+        AP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+r
+        AAD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/
+        rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/
+        rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgAA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA
+        /7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA
+        /7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EAAP+0
+        AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0
+        AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0
+        AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AAD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/
+        twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/
+        twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twAA/7oA/7oA
+        /7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA
+        /7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA
+        /7oA/7oA/7oA/7oA/7oA/7oA/7oAAP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9
+        AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9
+        AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AAD/wAD/wAD/wAD/
+        wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/
+        wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/
+        wAD/wAD/wAD/wAD/wAD/wAAA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA
+        /8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA
+        /8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MAAP/GAP/GAP/GAP/GAP/G
+        AP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/G
+        AP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/GAP/G
+        AP/GAP/GAP/GAP/GAAD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/
+        yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/
+        yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQD/yQAA/8wA/8wA/8wA/8wA/8wA/8wA
+        /8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA
+        /8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA/8wA
+        /8wA/8wA/8wAAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/P
+        AP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/P
+        AP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAP/PAAD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/
+        0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/
+        0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/0gD/
+        0gD/0gAA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA
+        /9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA
+        /9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UA/9UAAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/Y
+        AP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/Y
+        AP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/YAP/Y
+        AAD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/
+        2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/
+        2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wD/2wAA/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A
+        /94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A
+        /94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94A/94AAP/h
+        AP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/h
+        AP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/h
+        AP/hAP/hAP/hAP/hAP/hAP/hAP/hAP/hAAD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/
+        5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/
+        5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AD/5AAA/+cA/+cA
+        /+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA
+        /+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA/+cA
+        /+cA/+cA/+cA/+cA/+cA/+cA/+cAAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/n
+        AP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/n
+        AP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAAD/6gD/6gD/6gD/
+        6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/
+        6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/
+        6gD/6gD/6gD/6gD/6gD/6gAA/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A
+        /+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A
+        /+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0AAP/wAP/wAP/wAP/wAP/w
+        AP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/w
+        AP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/w
+        AP/wAP/wAP/wAP/wAAD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/
+        8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/
+        8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wAA//YA//YA//YA//YA//YA//YA
+        //YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA
+        //YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA
+        //YA//YA//YAAP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5
+        AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5
+        AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AAD//AD//AD//AD//AD//AD//AD//AD/
+        /AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD/
+        /AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD/
+        /AD//AAA//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A
+        //8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A
+        //8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8AAPz/APz/APz/APz/APz/APz/APz/APz/APz/
+        APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/
+        APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/
+        AAD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5
+        /wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5
+        /wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wAA9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A
+        9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A
+        9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8AAPP/
+        APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/
+        APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/
+        APP/APP/APP/APP/APP/APP/APP/APP/AADw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw
+        /wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw
+        /wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wAA7f8A7f8A
+        7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A
+        7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A
+        7f8A7f8A7f8A7f8A7f8A7f8A7f8AAOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/
+        AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/
+        AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AADn/wDn/wDn/wDn
+        /wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn
+        /wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn/wDn
+        /wDn/wDn/wDn/wDn/wDn/wAA5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A
+        5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A
+        5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8A5P8AAOH/AOH/AOH/AOH/AOH/
+        AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/
+        AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/AOH/
+        AOH/AOH/AOH/AOH/AADe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe
+        /wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe
+        /wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wDe/wAA2/8A2/8A2/8A2/8A2/8A2/8A
+        2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A
+        2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A2/8A
+        2/8A2/8A2/8AANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/
+        ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/
+        ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/ANj/AADV/wDV/wDV/wDV/wDV/wDV/wDV/wDV
+        /wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV
+        /wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV/wDV
+        /wDV/wAA0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A
+        0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A
+        0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8A0v8AAM//AM//AM//AM//AM//AM//AM//AM//AM//
+        AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//
+        AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//AM//
+        AADM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM
+        /wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM
+        /wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wDM/wAAyf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8A
+        yf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8A
+        yf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8Ayf8AAMb/
+        AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/
+        AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/
+        AMb/AMb/AMb/AMb/AMb/AMb/AMb/AMb/AADG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG
+        /wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG
+        /wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wAAw/8Aw/8A
+        w/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8A
+        w/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8A
+        w/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8AAMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/
+        AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/
+        AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AAC9/wC9/wC9/wC9
+        /wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9
+        /wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9
+        /wC9/wC9/wC9/wC9/wC9/wAAuv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8A
+        uv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8A
+        uv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8AALf/ALf/ALf/ALf/ALf/
+        ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/
+        ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/
+        ALf/ALf/ALf/ALf/AAC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0
+        /wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0
+        /wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wAAsf8Asf8Asf8Asf8Asf8Asf8A
+        sf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8A
+        sf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8A
+        sf8Asf8Asf8AAK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/
+        AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/
+        AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AACr/wCr/wCr/wCr/wCr/wCr/wCr/wCr
+        /wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr
+        /wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr
+        /wCr/wAAqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8A
+        qP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8A
+        qP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AAKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/
+        AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/
+        AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/
+        AACi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi
+        /wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi
+        /wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wAAn/8An/8An/8An/8An/8An/8An/8An/8An/8An/8A
+        n/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8A
+        n/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8AAJz/
+        AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/
+        AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/
+        AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AACZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ
+        /wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ
+        /wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wCZ/wAAlv8Alv8A
+        lv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8A
+        lv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8Alv8A
+        lv8Alv8Alv8Alv8Alv8Alv8Alv8AAJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/
+        AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/
+        AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AJP/AACQ/wCQ/wCQ/wCQ
+        /wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ
+        /wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ/wCQ
+        /wCQ/wCQ/wCQ/wCQ/wCQ/wAAjf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8A
+        jf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8A
+        jf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8Ajf8AAIr/AIr/AIr/AIr/AIr/
+        AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/
+        AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/AIr/
+        AIr/AIr/AIr/AIr/AACH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH
+        /wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH
+        /wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wCH/wAAhP8AhP8AhP8AhP8AhP8AhP8A
+        hP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8A
+        hP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8AhP8A
+        hP8AhP8AhP8AAIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/
+        AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/
+        AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AIH/AAB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+
+        /wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+
+        /wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+/wB+
+        /wB+/wAAe/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8A
+        e/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8A
+        e/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8Ae/8AAHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/
+        AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/
+        AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/AHj/
+        AAB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4
+        /wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4
+        /wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wAAdf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8A
+        df8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8A
+        df8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8AAHL/
+        AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/
+        AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/
+        AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AABv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv
+        /wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv
+        /wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wAAbP8AbP8A
+        bP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8A
+        bP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8A
+        bP8AbP8AbP8AbP8AbP8AbP8AbP8AAGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/
+        AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/
+        AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AABm/wBm/wBm/wBm
+        /wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm
+        /wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm
+        /wBm/wBm/wBm/wBm/wBm/wAAY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8A
+        Y/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8A
+        Y/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AAGD/AGD/AGD/AGD/AGD/
+        AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/
+        AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/
+        AGD/AGD/AGD/AGD/AABd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd
+        /wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd
+        /wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wAAWv8AWv8AWv8AWv8AWv8AWv8A
+        Wv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8A
+        Wv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8A
+        Wv8AWv8AWv8AAFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/
+        AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/
+        AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AABU/wBU/wBU/wBU/wBU/wBU/wBU/wBU
+        /wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU
+        /wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU
+        /wBU/wAAUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8A
+        Uf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8A
+        Uf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AAE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/
+        AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/
+        AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/
+        AABL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL
+        /wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL
+        /wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wBL/wAASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8A
+        SP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8A
+        SP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8ASP8AAEX/
+        AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/
+        AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/
+        AEX/AEX/AEX/AEX/AEX/AEX/AEX/AEX/AABC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC
+        /wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC
+        /wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wBC/wAAP/8AP/8A
+        P/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8A
+        P/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8AP/8A
+        P/8AP/8AP/8AP/8AP/8AP/8AP/8AADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/
+        ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/
+        ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/ADz/AAA5/wA5/wA5/wA5
+        /wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5
+        /wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5/wA5
+        /wA5/wA5/wA5/wA5/wA5/wAANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8A
+        Nv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8A
+        Nv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8ANv8AADP/ADP/ADP/ADP/ADP/
+        ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/
+        ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/ADP/
+        ADP/ADP/ADP/ADP/AAAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw
+        /wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw
+        /wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAw/wAALf8ALf8ALf8ALf8ALf8ALf8A
+        Lf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8A
+        Lf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8ALf8A
+        Lf8ALf8ALf8AACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/
+        ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/
+        ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/ACr/AAAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq
+        /wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq
+        /wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq
+        /wAq/wAAJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8A
+        J/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8A
+        J/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/
+        ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/
+        ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/
+        AAAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh
+        /wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh
+        /wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAAHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8A
+        Hv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8A
+        Hv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AABv/
+        ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/
+        ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/
+        ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/AAAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY
+        /wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY
+        /wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAAFf8AFf8A
+        Ff8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8A
+        Ff8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8A
+        Ff8AFf8AFf8AFf8AFf8AFf8AFf8AABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/
+        ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/
+        ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/AAAP/wAP/wAP/wAP
+        /wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP
+        /wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP
+        /wAP/wAP/wAP/wAP/wAP/wAADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8A
+        DP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8A
+        DP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8AAAn/AAn/AAn/AAn/AAn/
+        AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/
+        AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/
+        AAn/AAn/AAn/AAn/AAAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG
+        /wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG
+        /wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAAA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/
+        AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/
+        AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAAA/wMA/wMA/wMA/wMA/wMA/wMA/wMA
+        /wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA
+        /wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA/wMA
+        /wMA/wMAAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8G
+        AP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8G
+        AP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAP8GAAD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/
+        CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/
+        CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/CQD/
+        CQAA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA
+        /wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA
+        /wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwA/wwAAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8P
+        AP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8P
+        AP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAP8PAAD/
+        EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/
+        EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/
+        EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgD/EgAA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA
+        /xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA
+        /xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUA/xUAAP8YAP8Y
+        AP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8Y
+        AP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8YAP8Y
+        AP8YAP8YAP8YAP8YAP8YAP8YAP8YAAD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/
+        GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/
+        GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwD/GwAA/x4A/x4A/x4A
+        /x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A
+        /x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A/x4A
+        /x4A/x4A/x4A/x4A/x4A/x4AAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8h
+        AP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8h
+        AP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAP8hAAD/JAD/JAD/JAD/JAD/
+        JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/
+        JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/JAD/
+        JAD/JAD/JAD/JAD/JAAA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA
+        /ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA
+        /ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycA/ycAAP8nAP8nAP8nAP8nAP8nAP8n
+        AP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8n
+        AP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8nAP8n
+        AP8nAP8nAP8nAAD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/
+        KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/
+        KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgD/KgAA/y0A/y0A/y0A/y0A/y0A/y0A/y0A
+        /y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A
+        /y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A/y0A
+        /y0A/y0AAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8w
+        AP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8w
+        AP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAP8wAAD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/
+        MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/
+        MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/MwD/
+        MwAA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA
+        /zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA
+        /zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYA/zYAAP85AP85AP85AP85AP85AP85AP85AP85AP85AP85
+        AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85
+        AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AP85AAD/
+        PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/
+        PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/
+        PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAD/PAAA/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A
+        /z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A
+        /z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8A/z8AAP9CAP9C
+        AP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9C
+        AP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9CAP9C
+        AP9CAP9CAP9CAP9CAP9CAP9CAP9CAAD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/
+        RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/
+        RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQD/RQAA/0gA/0gA/0gA
+        /0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA
+        /0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA/0gA
+        /0gA/0gA/0gA/0gA/0gA/0gAAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9L
+        AP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9L
+        AP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAP9LAAD/TgD/TgD/TgD/TgD/
+        TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/
+        TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/TgD/
+        TgD/TgD/TgD/TgD/TgAA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA
+        /1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA
+        /1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EA/1EAAP9UAP9UAP9UAP9UAP9UAP9U
+        AP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9U
+        AP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9UAP9U
+        AP9UAP9UAP9UAAD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/
+        VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/
+        VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwD/VwAA/1oA/1oA/1oA/1oA/1oA/1oA/1oA
+        /1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA
+        /1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA/1oA
+        /1oA/1oAAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9d
+        AP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9d
+        AP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAP9dAAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/
+        YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/
+        YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/YAD/
+        YAAA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA
+        /2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA
+        /2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MA/2MAAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9m
+        AP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9m
+        AP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAP9mAAD/
+        aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/
+        aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/
+        aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQD/aQAA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA
+        /2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA
+        /2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wA/2wAAP9vAP9v
+        AP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9v
+        AP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9vAP9v
+        AP9vAP9vAP9vAP9vAP9vAP9vAP9vAAD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/
+        cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/
+        cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgD/cgAA/3UA/3UA/3UA
+        /3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA
+        /3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA/3UA
+        /3UA/3UA/3UA/3UA/3UA/3UAAP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91
+        AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91
+        AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AP91AAD/eAD/eAD/eAD/eAD/
+        eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/
+        eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/eAD/
+        eAD/eAD/eAD/eAD/eAAA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA
+        /3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA
+        /3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sA/3sAAP9+AP9+AP9+AP9+AP9+AP9+
+        AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+
+        AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+AP9+
+        AP9+AP9+AP9+AAD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/
+        gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/
+        gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQD/gQAA/4QA/4QA/4QA/4QA/4QA/4QA/4QA
+        /4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA
+        /4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA/4QA
+        /4QA/4QAAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+H
+        AP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+H
+        AP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAP+HAAD/igD/igD/igD/igD/igD/igD/igD/igD/
+        igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/
+        igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/igD/
+        igAA/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A
+        /40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A/40A
+        /40A/40A/40A/40A/40A/40A/40A/40A/40A/40AAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+Q
+        AP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+Q
+        AP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAP+QAAD/
+        kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/
+        kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/
+        kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwD/kwAA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA
+        /5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA
+        /5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YA/5YAAP+ZAP+Z
+        AP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+Z
+        AP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+Z
+        AP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAP+ZAAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/
+        nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/
+        nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAD/nAAA/58A/58A/58A
+        /58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A
+        /58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A/58A
+        /58A/58A/58A/58A/58A/58AAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+i
+        AP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+i
+        AP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAP+iAAD/pQD/pQD/pQD/pQD/
+        pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/
+        pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/pQD/
+        pQD/pQD/pQD/pQD/pQAA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA
+        /6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA
+        /6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gA/6gAAP+rAP+rAP+rAP+rAP+rAP+r
+        AP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+r
+        AP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+rAP+r
+        AP+rAP+rAP+rAAD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/
+        rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/
+        rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgD/rgAA/7EA/7EA/7EA/7EA/7EA/7EA/7EA
+        /7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA
+        /7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA/7EA
+        /7EA/7EAAP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0
+        AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0
+        AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AP+0AAD/twD/twD/twD/twD/twD/twD/twD/twD/
+        twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/
+        twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/twD/
+        twAA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA
+        /7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA
+        /7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oA/7oAAP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9
+        AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9
+        AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AP+9AAD/
+        wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/
+        wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/
+        wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAD/wAAA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA
+        /8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA
+        /8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MA/8MAAP/DAP/D
+        AP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/D
+        AP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/DAP/D
+        AP/DAP/DAP/DAP/DAP/DAP/DAP/DAAD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/
+        xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/
+        xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgD/xgAA/8kA/8kA/8kA
+        /8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA
+        /8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA/8kA
+        /8kA/8kA/8kA/8kA/8kA/8kAAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/M
+        AP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/M
+        AP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAP/MAAD/zwD/zwD/zwD/zwD/
+        zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/
+        zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/zwD/
+        zwD/zwD/zwD/zwD/zwAA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA
+        /9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA
+        /9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IA/9IAAP/VAP/VAP/VAP/VAP/VAP/V
+        AP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/V
+        AP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/VAP/V
+        AP/VAP/VAP/VAAD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/
+        2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/
+        2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AD/2AAA/9sA/9sA/9sA/9sA/9sA/9sA/9sA
+        /9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA
+        /9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA/9sA
+        /9sA/9sAAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/e
+        AP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/e
+        AP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAP/eAAD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/
+        4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/
+        4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/4QD/
+        4QAA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA
+        /+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA
+        /+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QA/+QAAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/n
+        AP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/n
+        AP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAP/nAAD/
+        6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/
+        6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/
+        6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gD/6gAA/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A
+        /+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A
+        /+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0A/+0AAP/wAP/w
+        AP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/w
+        AP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/w
+        AP/wAP/wAP/wAP/wAP/wAP/wAP/wAAD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/
+        8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/
+        8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wD/8wAA//YA//YA//YA
+        //YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA
+        //YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA//YA
+        //YA//YA//YA//YA//YA//YAAP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5
+        AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5
+        AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AP/5AAD//AD//AD//AD//AD/
+        /AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD/
+        /AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD/
+        /AD//AD//AD//AD//AAA//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A
+        //8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A
+        //8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8A//8AAPz/APz/APz/APz/APz/APz/
+        APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/
+        APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/APz/
+        APz/APz/APz/AAD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5
+        /wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5
+        /wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wD5/wAA9v8A9v8A9v8A9v8A9v8A9v8A9v8A
+        9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A
+        9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A9v8A
+        9v8A9v8AAPP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/
+        APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/
+        APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/APP/AADw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw
+        /wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw
+        /wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw/wDw
+        /wAA7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A
+        7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A
+        7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8A7f8AAOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/
+        AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/
+        AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AOr/AADq
+        /wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq
+        /wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq
+        /wDq/wDq/wDq/wDq/wDq/wDq/wDq/wDq/wAA5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A
+        5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A
+        5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8A5/8AAOT/AOT/
+        AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/
+        AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/AOT/
+        AOT/AOT/AOT/AOT/AOT/AOT/AOT/AADh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh
+        /wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh
+        /wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wDh/wAA3v8A3v8A3v8A
+        3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A
+        3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A3v8A
+        3v8A3v8A3v8A3v8A3v8A3v8AANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/
+        ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/
+        ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/ANv/AADY/wDY/wDY/wDY/wDY
+        /wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY
+        /wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY/wDY
+        /wDY/wDY/wDY/wDY/wAA1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A
+        1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A
+        1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8A1f8AANL/ANL/ANL/ANL/ANL/ANL/
+        ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/
+        ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/ANL/
+        ANL/ANL/ANL/AADP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP
+        /wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP
+        /wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wDP/wAAzP8AzP8AzP8AzP8AzP8AzP8AzP8A
+        zP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8A
+        zP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8AzP8A
+        zP8AzP8AAMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/
+        AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/
+        AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AMn/AADG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG
+        /wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG
+        /wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG/wDG
+        /wAAw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8A
+        w/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8A
+        w/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8Aw/8AAMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/
+        AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/
+        AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AMD/AAC9
+        /wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9
+        /wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9
+        /wC9/wC9/wC9/wC9/wC9/wC9/wC9/wC9/wAAuv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8A
+        uv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8A
+        uv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8Auv8AALf/ALf/
+        ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/
+        ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/ALf/
+        ALf/ALf/ALf/ALf/ALf/ALf/ALf/AAC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0
+        /wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0
+        /wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wC0/wAAsf8Asf8Asf8A
+        sf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8A
+        sf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8Asf8A
+        sf8Asf8Asf8Asf8Asf8Asf8AAK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/
+        AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/
+        AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AK7/AACr/wCr/wCr/wCr/wCr
+        /wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr
+        /wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr/wCr
+        /wCr/wCr/wCr/wCr/wAAqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8A
+        qP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8A
+        qP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AqP8AAKX/AKX/AKX/AKX/AKX/AKX/
+        AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/
+        AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/AKX/
+        AKX/AKX/AKX/AACi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi
+        /wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi
+        /wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wCi/wAAn/8An/8An/8An/8An/8An/8An/8A
+        n/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8A
+        n/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8An/8A
+        n/8An/8AAJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/
+        AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/
+        AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AJz/AACc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc
+        /wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc
+        /wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc/wCc
+        /wAAmf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8A
+        mf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8A
+        mf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8Amf8AAJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/
+        AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/
+        AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AJb/AACT
+        /wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT
+        /wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT
+        /wCT/wCT/wCT/wCT/wCT/wCT/wCT/wCT/wAAkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8A
+        kP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8A
+        kP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AkP8AAI3/AI3/
+        AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/
+        AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/AI3/
+        AI3/AI3/AI3/AI3/AI3/AI3/AI3/AACK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK
+        /wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK
+        /wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wCK/wAAh/8Ah/8Ah/8A
+        h/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8A
+        h/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8Ah/8A
+        h/8Ah/8Ah/8Ah/8Ah/8Ah/8AAIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/
+        AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/
+        AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AIT/AACB/wCB/wCB/wCB/wCB
+        /wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB
+        /wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB/wCB
+        /wCB/wCB/wCB/wCB/wAAfv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8A
+        fv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8A
+        fv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8Afv8AAHv/AHv/AHv/AHv/AHv/AHv/
+        AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/
+        AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/AHv/
+        AHv/AHv/AHv/AAB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4
+        /wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4
+        /wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wB4/wAAdf8Adf8Adf8Adf8Adf8Adf8Adf8A
+        df8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8A
+        df8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8Adf8A
+        df8Adf8AAHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/
+        AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/
+        AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AHL/AABv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv
+        /wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv
+        /wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv/wBv
+        /wAAbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8A
+        bP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8A
+        bP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AbP8AAGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/
+        AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/
+        AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AGn/AABm
+        /wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm
+        /wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm
+        /wBm/wBm/wBm/wBm/wBm/wBm/wBm/wBm/wAAY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8A
+        Y/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8A
+        Y/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AY/8AAGD/AGD/
+        AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/
+        AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/AGD/
+        AGD/AGD/AGD/AGD/AGD/AGD/AGD/AABd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd
+        /wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd
+        /wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wBd/wAAWv8AWv8AWv8A
+        Wv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8A
+        Wv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8AWv8A
+        Wv8AWv8AWv8AWv8AWv8AWv8AAFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/
+        AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/
+        AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AFf/AABU/wBU/wBU/wBU/wBU
+        /wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU
+        /wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU/wBU
+        /wBU/wBU/wBU/wBU/wAAUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8A
+        Uf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8A
+        Uf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AUf8AAE7/AE7/AE7/AE7/AE7/AE7/
+        AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/
+        AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/AE7/
+        AE7/AE7/AE7/AABO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO
+        /wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO
+        /wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wBO/wAAS/8AS/8AS/8AS/8AS/8AS/8AS/8A
+        S/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8A
+        S/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8AS/8A
+        S/8AS/8AAEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/
+        AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/
+        AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AEj/AABF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF
+        /wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF
+        /wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF/wBF
+        /wAAQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8A
+        Qv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8A
+        Qv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AQv8AAD//AD//AD//AD//AD//AD//AD//AD//AD//AD//
+        AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//
+        AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AD//AAA8
+        /wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8
+        /wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8
+        /wA8/wA8/wA8/wA8/wA8/wA8/wA8/wA8/wAAOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8A
+        Of8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8A
+        Of8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AOf8AADb/ADb/
+        ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/
+        ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/ADb/
+        ADb/ADb/ADb/ADb/ADb/ADb/ADb/AAAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz
+        /wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz
+        /wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAz/wAAMP8AMP8AMP8A
+        MP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8A
+        MP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8AMP8A
+        MP8AMP8AMP8AMP8AMP8AMP8AAC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/
+        AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/
+        AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AC3/AAAq/wAq/wAq/wAq/wAq
+        /wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq
+        /wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq/wAq
+        /wAq/wAq/wAq/wAq/wAAJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8A
+        J/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8A
+        J/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AJ/8AACT/ACT/ACT/ACT/ACT/ACT/
+        ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/
+        ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/ACT/
+        ACT/ACT/ACT/AAAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh
+        /wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh
+        /wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAh/wAAHv8AHv8AHv8AHv8AHv8AHv8AHv8A
+        Hv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8A
+        Hv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8AHv8A
+        Hv8AHv8AABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/
+        ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/
+        ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/ABv/AAAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY
+        /wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY
+        /wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY/wAY
+        /wAAFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8A
+        Ff8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8A
+        Ff8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AFf8AABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/
+        ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/
+        ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/ABL/AAAP
+        /wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP
+        /wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP
+        /wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAP/wAADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8A
+        DP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8A
+        DP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8ADP8AAAn/AAn/
+        AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/
+        AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAn/
+        AAn/AAn/AAn/AAn/AAn/AAn/AAn/AAAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG
+        /wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG
+        /wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAG/wAAA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8AA/8A
+        A/8AA/8AA/8AA/8AA/8AA/8A
+</value>
+  </data>
+  <data name="grayscalesPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        Qk0S0gAAAAAAADYAAAAoAAAAMQAAAGsBAAABABgAAAAAAAAAAADEDgAAxA4AAAAAAAAAAAAA////////
+        ////////////////////////////////////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        ////////////////////////////AP//////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        /////////////////////////////////////////////////////////////////wD/////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        //////////////////////8A////////////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////AP//////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////////////////////////
+        /////////////////wD+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v4A/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+AP7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+
+        /v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/gD9/f39/f39/f39/f39/f39/f39/f39
+        /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
+        /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
+        /f39/f0A/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8
+        /Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8
+        /Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8APv7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7
+        +/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7
+        +/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7
+        +wD7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7
+        +/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7
+        +/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sA+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6
+        +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6
+        +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6APn5
+        +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5
+        +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5
+        +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+QD5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5
+        +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5
+        +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fkA+Pj4+Pj4
+        +Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4
+        +Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4
+        +Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4APf39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+        9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+        9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39wD29vb29vb29vb2
+        9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb2
+        9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb2
+        9vb29vb29vb29vb29vb29vYA9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb2
+        9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb2
+        9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb2APX19fX19fX19fX19fX1
+        9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX1
+        9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX1
+        9fX19fX19fX19fX19QD09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0
+        9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0
+        9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQA9PT09PT09PT09PT09PT09PT0
+        9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0
+        9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0
+        9PT09PT09PT0APPz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz
+        8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz
+        8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8wDy8vLy8vLy8vLy8vLy8vLy8vLy8vLy
+        8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy
+        8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy
+        8vLy8vIA8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx
+        8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx
+        8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHxAPHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx
+        8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx
+        8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx
+        8QDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw
+        8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw
+        8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PAA7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v
+        7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v
+        7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/vAO/v
+        7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v
+        7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v
+        7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7wDu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u
+        7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u
+        7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u4A7e3t7e3t
+        7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t
+        7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t
+        7e3t7e3t7e3t7e3t7e3t7e3t7e3tAOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs
+        7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs
+        7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ADs7Ozs7Ozs7Ozs
+        7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs
+        7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs
+        7Ozs7Ozs7Ozs7Ozs7Ozs7OwA6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr
+        6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr
+        6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vrAOrq6urq6urq6urq6urq
+        6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq
+        6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq
+        6urq6urq6urq6urq6gDq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq
+        6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq
+        6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6uoA6enp6enp6enp6enp6enp6enp
+        6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp
+        6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp
+        6enp6enp6enpAOjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo
+        6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo
+        6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6ADn5+fn5+fn5+fn5+fn5+fn5+fn5+fn
+        5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn
+        5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn
+        5+fn5+cA5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn
+        5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn
+        5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnAObm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm
+        5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm
+        5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm
+        5gDl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl
+        5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl
+        5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eUA5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl
+        5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl
+        5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXlAOTk
+        5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk
+        5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk
+        5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5ADj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj
+        4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj
+        4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+MA4+Pj4+Pj
+        4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj
+        4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj
+        4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+PjAOLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi
+        4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi
+        4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4gDh4eHh4eHh4eHh
+        4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh
+        4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh
+        4eHh4eHh4eHh4eHh4eHh4eEA4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg
+        4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg
+        4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODgAODg4ODg4ODg4ODg4ODg
+        4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg
+        4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg
+        4ODg4ODg4ODg4ODg4ADf39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f
+        39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f
+        39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f398A3t7e3t7e3t7e3t7e3t7e3t7e
+        3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e
+        3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e
+        3t7e3t7e3t7eAN7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e
+        3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e
+        3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3gDd3d3d3d3d3d3d3d3d3d3d3d3d3d3d
+        3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d
+        3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d
+        3d3d3d0A3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc
+        3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc
+        3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcANvb29vb29vb29vb29vb29vb29vb29vb29vb
+        29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb
+        29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb
+        2wDb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb
+        29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb
+        29vb29vb29vb29vb29vb29vb29vb29vb29vb29sA2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra
+        2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra
+        2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2traANnZ
+        2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ
+        2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ
+        2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2QDZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ
+        2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ
+        2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkA2NjY2NjY
+        2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY
+        2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY
+        2NjY2NjY2NjY2NjY2NjY2NjY2NjYANfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX
+        19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX
+        19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX1wDW1tbW1tbW1tbW
+        1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW
+        1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW
+        1tbW1tbW1tbW1tbW1tbW1tYA1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW
+        1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW
+        1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbWANXV1dXV1dXV1dXV1dXV
+        1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
+        1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
+        1dXV1dXV1dXV1dXV1QDU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU
+        1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU
+        1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NQA1NTU1NTU1NTU1NTU1NTU1NTU
+        1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU
+        1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU
+        1NTU1NTU1NTUANPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT
+        09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT
+        09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0wDS0tLS0tLS0tLS0tLS0tLS0tLS0tLS
+        0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS
+        0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS
+        0tLS0tIA0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR
+        0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR
+        0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHRANHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR
+        0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR
+        0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR
+        0QDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ
+        0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ
+        0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NAAz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P
+        z8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P
+        z8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/PAM/P
+        z8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P
+        z8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P
+        z8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/PzwDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O
+        zs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O
+        zs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs4Azc3Nzc3N
+        zc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N
+        zc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N
+        zc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NAMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
+        zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
+        zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzADMzMzMzMzMzMzM
+        zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
+        zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
+        zMzMzMzMzMzMzMzMzMzMzMwAy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL
+        y8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL
+        y8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLAMrKysrKysrKysrKysrK
+        ysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK
+        ysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK
+        ysrKysrKysrKysrKygDKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK
+        ysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK
+        ysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysoAycnJycnJycnJycnJycnJycnJ
+        ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJ
+        ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJ
+        ycnJycnJycnJAMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI
+        yMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI
+        yMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyADIyMjIyMjIyMjIyMjIyMjIyMjIyMjI
+        yMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI
+        yMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI
+        yMjIyMgAx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fH
+        x8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fH
+        x8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHAMbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG
+        xsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG
+        xsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG
+        xgDFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXF
+        xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXF
+        xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUAxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXF
+        xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXF
+        xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFAMTE
+        xMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTE
+        xMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTE
+        xMTExMTExMTExMTExMTExMTExMTExMTExADDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PD
+        w8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PD
+        w8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8MAw8PDw8PD
+        w8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PD
+        w8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PD
+        w8PDw8PDw8PDw8PDw8PDw8PDw8PDAMLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC
+        wsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC
+        wsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwgDBwcHBwcHBwcHB
+        wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB
+        wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB
+        wcHBwcHBwcHBwcHBwcHBwcEAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA
+        wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA
+        wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAMDAwMDAwMDAwMDAwMDA
+        wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA
+        wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA
+        wMDAwMDAwMDAwMDAwAC/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/
+        v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/
+        v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v78Avr6+vr6+vr6+vr6+vr6+vr6+
+        vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+
+        vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+
+        vr6+vr6+vr6+AL6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+
+        vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+
+        vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vgC9vb29vb29vb29vb29vb29vb29vb29
+        vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29
+        vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29
+        vb29vb0AvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8
+        vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8
+        vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8ALu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7
+        u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7
+        u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7
+        uwC7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7
+        u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7
+        u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7sAurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6
+        urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6
+        urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6ALm5
+        ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5
+        ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5
+        ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5uQC5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5
+        ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5
+        ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubkAuLi4uLi4
+        uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4
+        uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4
+        uLi4uLi4uLi4uLi4uLi4uLi4uLi4ALe3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3
+        t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3
+        t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3twC2tra2tra2tra2
+        tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2
+        tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2
+        tra2tra2tra2tra2tra2trYAtra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2
+        tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2
+        tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2ALW1tbW1tbW1tbW1tbW1
+        tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1
+        tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1
+        tbW1tbW1tbW1tbW1tQC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0
+        tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0
+        tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQAtLS0tLS0tLS0tLS0tLS0tLS0
+        tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0
+        tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0
+        tLS0tLS0tLS0ALOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz
+        s7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz
+        s7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzswCysrKysrKysrKysrKysrKysrKysrKy
+        srKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy
+        srKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy
+        srKysrIAsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx
+        sbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx
+        sbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxALGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx
+        sbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx
+        sbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx
+        sQCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCw
+        sLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCw
+        sLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLAAr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+v
+        r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+v
+        r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vAK+v
+        r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+v
+        r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+v
+        r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vrwCurq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6u
+        rq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6u
+        rq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq4Ara2tra2t
+        ra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2t
+        ra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2t
+        ra2tra2tra2tra2tra2tra2tra2tAKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKys
+        rKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKys
+        rKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrACsrKysrKysrKys
+        rKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKys
+        rKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKys
+        rKysrKysrKysrKysrKysrKwAq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6ur
+        q6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6ur
+        q6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urAKqqqqqqqqqqqqqqqqqq
+        qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+        qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+        qqqqqqqqqqqqqqqqqgCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+        qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+        qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoAqampqampqampqampqampqamp
+        qampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqamp
+        qampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqamp
+        qampqampqampAKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio
+        qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio
+        qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqACoqKioqKioqKioqKioqKioqKioqKio
+        qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio
+        qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio
+        qKioqKgAp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6en
+        p6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6en
+        p6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enAKampqampqampqampqampqampqampqampqam
+        pqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqam
+        pqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqam
+        pgClpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl
+        paWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl
+        paWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaUApaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl
+        paWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWl
+        paWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlAKSk
+        pKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSk
+        pKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSk
+        pKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpACjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj
+        o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj
+        o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6MAo6Ojo6Oj
+        o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj
+        o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj
+        o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjAKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi
+        oqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi
+        oqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogChoaGhoaGhoaGh
+        oaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGh
+        oaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGh
+        oaGhoaGhoaGhoaGhoaGhoaEAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
+        oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
+        oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgAKCgoKCgoKCgoKCgoKCg
+        oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
+        oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
+        oKCgoKCgoKCgoKCgoACfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+f
+        n5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+f
+        n5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn58Anp6enp6enp6enp6enp6enp6e
+        np6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6e
+        np6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6e
+        np6enp6enp6eAJ6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6e
+        np6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6e
+        np6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6engCdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2d
+        nZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2d
+        nZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2d
+        nZ2dnZ0AnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyc
+        nJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyc
+        nJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycAJubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ub
+        m5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ub
+        m5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ub
+        mwCbm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ub
+        m5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ub
+        m5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5sAmpqampqampqampqampqampqampqampqampqampqa
+        mpqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqa
+        mpqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqaAJmZ
+        mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ
+        mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ
+        mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmQCZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ
+        mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ
+        mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZkAmJiYmJiY
+        mJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiY
+        mJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiY
+        mJiYmJiYmJiYmJiYmJiYmJiYmJiYAJeXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eX
+        l5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eX
+        l5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXlwCWlpaWlpaWlpaW
+        lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaW
+        lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaW
+        lpaWlpaWlpaWlpaWlpaWlpYAlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaW
+        lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaW
+        lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWAJWVlZWVlZWVlZWVlZWV
+        lZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWV
+        lZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWV
+        lZWVlZWVlZWVlZWVlQCUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU
+        lJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU
+        lJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJQAlJSUlJSUlJSUlJSUlJSUlJSU
+        lJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU
+        lJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU
+        lJSUlJSUlJSUAJOTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OT
+        k5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OT
+        k5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTkwCSkpKSkpKSkpKSkpKSkpKSkpKSkpKS
+        kpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKS
+        kpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKS
+        kpKSkpIAkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGR
+        kZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGR
+        kZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRAJGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGR
+        kZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGR
+        kZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGR
+        kQCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ
+        kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQ
+        kJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJAAj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+P
+        j4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+P
+        j4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+PAI+P
+        j4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+P
+        j4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+P
+        j4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+PjwCOjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6O
+        jo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6O
+        jo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo4AjY2NjY2N
+        jY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2N
+        jY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2N
+        jY2NjY2NjY2NjY2NjY2NjY2NjY2NAI2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2N
+        jY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2N
+        jY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjQCMjIyMjIyMjIyM
+        jIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM
+        jIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM
+        jIyMjIyMjIyMjIyMjIyMjIwAi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uL
+        i4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uL
+        i4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLAIqKioqKioqKioqKioqK
+        ioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqK
+        ioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqK
+        ioqKioqKioqKioqKigCKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqK
+        ioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqK
+        ioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiooAiYmJiYmJiYmJiYmJiYmJiYmJ
+        iYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJ
+        iYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJ
+        iYmJiYmJiYmJAIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+        iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+        iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiACIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+        iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+        iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+        iIiIiIgAh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eH
+        h4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eH
+        h4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHAIaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaG
+        hoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaG
+        hoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaG
+        hgCFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF
+        hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF
+        hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUAhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF
+        hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF
+        hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFAISE
+        hISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISE
+        hISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISE
+        hISEhISEhISEhISEhISEhISEhISEhISEhACDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OD
+        g4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OD
+        g4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4MAg4ODg4OD
+        g4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OD
+        g4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OD
+        g4ODg4ODg4ODg4ODg4ODg4ODg4ODAIKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKC
+        goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKC
+        goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCggCBgYGBgYGBgYGB
+        gYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGB
+        gYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGB
+        gYGBgYGBgYGBgYGBgYGBgYEAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+        gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+        gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAICAgICAgICAgICAgICA
+        gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+        gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+        gICAgICAgICAgICAgAB/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/
+        f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/
+        f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f38Afn5+fn5+fn5+fn5+fn5+fn5+
+        fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+
+        fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+
+        fn5+fn5+fn5+AH5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+
+        fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+
+        fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fgB9fX19fX19fX19fX19fX19fX19fX19
+        fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19
+        fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19
+        fX19fX0AfHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8
+        fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8
+        fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8AHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7
+        e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7
+        e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7
+        ewB7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7
+        e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7
+        e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3sAenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6
+        enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6
+        enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6AHl5
+        eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5
+        eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5
+        eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eQB5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5
+        eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5
+        eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXkAeHh4eHh4
+        eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4
+        eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4
+        eHh4eHh4eHh4eHh4eHh4eHh4eHh4AHd3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3
+        d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3
+        d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3dwB2dnZ2dnZ2dnZ2
+        dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
+        dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
+        dnZ2dnZ2dnZ2dnZ2dnZ2dnYAdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
+        dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
+        dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2AHV1dXV1dXV1dXV1dXV1
+        dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1
+        dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1
+        dXV1dXV1dXV1dXV1dQB0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0
+        dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0
+        dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAdHR0dHR0dHR0dHR0dHR0dHR0
+        dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0
+        dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0
+        dHR0dHR0dHR0AHNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nz
+        c3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nz
+        c3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcwBycnJycnJycnJycnJycnJycnJycnJy
+        cnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJy
+        cnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJy
+        cnJycnIAcnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJy
+        cnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJy
+        cnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyAHFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFx
+        cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFx
+        cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFx
+        cQBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw
+        cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw
+        cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHAAb29vb29vb29vb29vb29vb29vb29vb29vb29vb29v
+        b29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29v
+        b29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vAG9v
+        b29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29v
+        b29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29v
+        b29vb29vb29vb29vb29vb29vb29vb29vbwBubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5u
+        bm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5u
+        bm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm4AbW1tbW1t
+        bW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1t
+        bW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1t
+        bW1tbW1tbW1tbW1tbW1tbW1tbW1tAG1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1t
+        bW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1t
+        bW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbQBsbGxsbGxsbGxs
+        bGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxs
+        bGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxs
+        bGxsbGxsbGxsbGxsbGxsbGwAa2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tr
+        a2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tr
+        a2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2trAGpqampqampqampqampq
+        ampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampq
+        ampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampq
+        ampqampqampqampqagBqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampq
+        ampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampq
+        ampqampqampqampqampqampqampqampqampqampqampqampqampqamoAaWlpaWlpaWlpaWlpaWlpaWlp
+        aWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlp
+        aWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlp
+        aWlpaWlpaWlpAGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho
+        aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho
+        aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaABoaGhoaGhoaGhoaGhoaGhoaGhoaGho
+        aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho
+        aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho
+        aGhoaGgAZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn
+        Z2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn
+        Z2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnAGZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm
+        ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm
+        ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm
+        ZgBlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVl
+        ZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVl
+        ZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWUAZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVl
+        ZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVl
+        ZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlAGRk
+        ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRk
+        ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRk
+        ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZABjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj
+        Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj
+        Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2MAY2NjY2Nj
+        Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj
+        Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj
+        Y2NjY2NjY2NjY2NjY2NjY2NjY2NjAGJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi
+        YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi
+        YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYgBhYWFhYWFhYWFh
+        YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+        YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+        YWFhYWFhYWFhYWFhYWFhYWEAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBg
+        YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBg
+        YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgAGBgYGBgYGBgYGBgYGBg
+        YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBg
+        YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBg
+        YGBgYGBgYGBgYGBgYABfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
+        X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
+        X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18AXl5eXl5eXl5eXl5eXl5eXl5e
+        Xl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5e
+        Xl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5e
+        Xl5eXl5eXl5eAF5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5e
+        Xl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5e
+        Xl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXgBdXV1dXV1dXV1dXV1dXV1dXV1dXV1d
+        XV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1d
+        XV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1d
+        XV1dXV0AXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxc
+        XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxc
+        XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcAFtbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb
+        W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb
+        W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb
+        WwBbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb
+        W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb
+        W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1sAWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpa
+        WlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpa
+        WlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaAFlZ
+        WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZ
+        WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZ
+        WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWQBZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZ
+        WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZ
+        WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVkAWFhYWFhY
+        WFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY
+        WFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY
+        WFhYWFhYWFhYWFhYWFhYWFhYWFhYAFdXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dX
+        V1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dX
+        V1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXVwBXV1dXV1dXV1dX
+        V1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dX
+        V1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dX
+        V1dXV1dXV1dXV1dXV1dXV1cAVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZW
+        VlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZW
+        VlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWAFVVVVVVVVVVVVVVVVVV
+        VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+        VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+        VVVVVVVVVVVVVVVVVQBUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU
+        VFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU
+        VFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQAVFRUVFRUVFRUVFRUVFRUVFRU
+        VFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU
+        VFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU
+        VFRUVFRUVFRUAFNTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NT
+        U1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NT
+        U1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTUwBSUlJSUlJSUlJSUlJSUlJSUlJSUlJS
+        UlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJS
+        UlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJS
+        UlJSUlIAUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJS
+        UlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJS
+        UlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSAFFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFR
+        UVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFR
+        UVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFR
+        UQBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ
+        UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ
+        UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFAAT09PT09PT09PT09PT09PT09PT09PT09PT09PT09P
+        T09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09P
+        T09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PAE9P
+        T09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09P
+        T09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09P
+        T09PT09PT09PT09PT09PT09PT09PT09PTwBOTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5O
+        Tk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5O
+        Tk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk4ATU1NTU1N
+        TU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1N
+        TU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1N
+        TU1NTU1NTU1NTU1NTU1NTU1NTU1NAE1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1N
+        TU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1N
+        TU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTQBMTExMTExMTExM
+        TExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExM
+        TExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExM
+        TExMTExMTExMTExMTExMTEwAS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tL
+        S0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tL
+        S0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLAEpKSkpKSkpKSkpKSkpK
+        SkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpK
+        SkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpK
+        SkpKSkpKSkpKSkpKSgBKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpK
+        SkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpK
+        SkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkoASUlJSUlJSUlJSUlJSUlJSUlJ
+        SUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJ
+        SUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJ
+        SUlJSUlJSUlJAEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhI
+        SEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhI
+        SEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISABISEhISEhISEhISEhISEhISEhISEhI
+        SEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhI
+        SEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhI
+        SEhISEgAR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dH
+        R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dH
+        R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAEZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZG
+        RkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZG
+        RkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZG
+        RgBFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+        RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+        RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUUARUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+        RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+        RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFAERE
+        RERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERE
+        RERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERE
+        RERERERERERERERERERERERERERERERERABDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND
+        Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND
+        Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0MAQ0NDQ0ND
+        Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND
+        Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND
+        Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDAEJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJC
+        QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJC
+        QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQgBBQUFBQUFBQUFB
+        QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
+        QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
+        QUFBQUFBQUFBQUFBQUFBQUEAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA
+        QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA
+        QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBA
+        QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA
+        QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA
+        QEBAQEBAQEBAQEBAQAA/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/
+        Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/
+        Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8APj4+Pj4+Pj4+Pj4+Pj4+Pj4+
+        Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+
+        Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+
+        Pj4+Pj4+Pj4+AD4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+
+        Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+
+        Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+PgA9PT09PT09PT09PT09PT09PT09PT09
+        PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
+        PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
+        PT09PT0APDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8
+        PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8
+        PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8ADw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8
+        PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8
+        PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8
+        PAA7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7
+        Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7
+        Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsAOjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6
+        Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6
+        Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6ADk5
+        OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5
+        OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5
+        OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OQA5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5
+        OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5
+        OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTkAODg4ODg4
+        ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4
+        ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4
+        ODg4ODg4ODg4ODg4ODg4ODg4ODg4ADc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3
+        Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3
+        Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NwA3Nzc3Nzc3Nzc3
+        Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3
+        Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3
+        Nzc3Nzc3Nzc3Nzc3Nzc3NzcANjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2
+        NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2
+        NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2ADU1NTU1NTU1NTU1NTU1
+        NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1
+        NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1
+        NTU1NTU1NTU1NTU1NQA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0
+        NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0
+        NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQANDQ0NDQ0NDQ0NDQ0NDQ0NDQ0
+        NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0
+        NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0
+        NDQ0NDQ0NDQ0ADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMz
+        MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMz
+        MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMwAyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
+        MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
+        MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
+        MjIyMjIAMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
+        MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
+        MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyADExMTExMTExMTExMTExMTExMTExMTExMTEx
+        MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx
+        MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx
+        MQAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+        MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+        MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAALy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
+        Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
+        Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vAC8v
+        Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
+        Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
+        Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
+        Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
+        Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4ALS0tLS0t
+        LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
+        LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
+        LS0tLS0tLS0tLS0tLS0tLS0tLS0tAC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
+        LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
+        LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQAsLCwsLCwsLCws
+        LCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCws
+        LCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCws
+        LCwsLCwsLCwsLCwsLCwsLCwAKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
+        KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
+        KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrACoqKioqKioqKioqKioq
+        KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+        KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+        KioqKioqKioqKioqKgAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+        KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+        KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioAKSkpKSkpKSkpKSkpKSkpKSkp
+        KSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkp
+        KSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkp
+        KSkpKSkpKSkpACgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo
+        KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo
+        KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKAAoKCgoKCgoKCgoKCgoKCgoKCgoKCgo
+        KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo
+        KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo
+        KCgoKCgAJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycn
+        JycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycn
+        JycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnACYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYm
+        JiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYm
+        JiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYm
+        JgAlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUl
+        JSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUl
+        JSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUAJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUl
+        JSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUl
+        JSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlACQk
+        JCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQk
+        JCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQk
+        JCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJAAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
+        IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
+        IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMAIyMjIyMj
+        IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
+        IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
+        IyMjIyMjIyMjIyMjIyMjIyMjIyMjACIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
+        IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
+        IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAhISEhISEhISEh
+        ISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEh
+        ISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEh
+        ISEhISEhISEhISEhISEhISEAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+        ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+        ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAgICAgICAgICAgICAg
+        ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+        ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+        ICAgICAgICAgICAgIAAfHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f
+        Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f
+        Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8AHh4eHh4eHh4eHh4eHh4eHh4e
+        Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
+        Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
+        Hh4eHh4eHh4eAB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
+        Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
+        Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHgAdHR0dHR0dHR0dHR0dHR0dHR0dHR0d
+        HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0d
+        HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0d
+        HR0dHR0AHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc
+        HBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc
+        HBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc
+        HBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc
+        HBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc
+        HAAbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb
+        GxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb
+        GxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsAGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa
+        GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa
+        GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaABkZ
+        GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ
+        GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ
+        GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQAZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ
+        GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZ
+        GRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkAGBgYGBgY
+        GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgY
+        GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgY
+        GBgYGBgYGBgYGBgYGBgYGBgYGBgYABcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcX
+        FxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcX
+        FxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwAXFxcXFxcXFxcX
+        FxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcX
+        FxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcX
+        FxcXFxcXFxcXFxcXFxcXFxcAFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW
+        FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW
+        FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWABUVFRUVFRUVFRUVFRUV
+        FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUV
+        FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUV
+        FRUVFRUVFRUVFRUVFQAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU
+        FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU
+        FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFBQUFBQUFBQUFBQUFBQUFBQU
+        FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU
+        FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU
+        FBQUFBQUFBQUABMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMT
+        ExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMT
+        ExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEwASEhISEhISEhISEhISEhISEhISEhIS
+        EhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIS
+        EhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIS
+        EhISEhIAEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIS
+        EhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIS
+        EhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISABERERERERERERERERERERERERERERERERER
+        ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERER
+        ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERER
+        EQAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ
+        EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ
+        EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAADw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8P
+        Dw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8P
+        Dw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PAA8P
+        Dw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8P
+        Dw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8P
+        Dw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDwAODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4O
+        Dg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4O
+        Dg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ADQ0NDQ0N
+        DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0N
+        DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0N
+        DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NAA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0N
+        DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0N
+        DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQAMDAwMDAwMDAwM
+        DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM
+        DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM
+        DAwMDAwMDAwMDAwMDAwMDAwACwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsL
+        CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsL
+        CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLAAoKCgoKCgoKCgoKCgoK
+        CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK
+        CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK
+        CgoKCgoKCgoKCgoKCgAKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK
+        CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK
+        CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoACQkJCQkJCQkJCQkJCQkJCQkJ
+        CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJ
+        CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJ
+        CQkJCQkJCQkJAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+        CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+        CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAICAgICAgICAgICAgICAgICAgICAgI
+        CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+        CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+        CAgICAgABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH
+        BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH
+        BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHAAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYG
+        BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYG
+        BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYG
+        BgAFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
+        BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
+        BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
+        BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
+        BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFAAQE
+        BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE
+        BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE
+        BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD
+        AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD
+        AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwMDAwMD
+        AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD
+        AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD
+        AwMDAwMDAwMDAwMDAwMDAwMDAwMDAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+        AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+        AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgABAQEBAQEBAQEB
+        AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
+        AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
+        AQEBAQEBAQEBAQEBAQEBAQEA
+</value>
+  </data>
+</root>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 15719)
@@ -0,0 +1,336 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{76945D76-CA61-4147-9DC2-0ACDCDDF87F9}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Analysis.Views</RootNamespace>
+    <AssemblyName>HeuristicLab.Analysis.Views-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\..\trunk\bin\ALGLIB-3.7.0.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common.Resources-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core.Views-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core.Views-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm.WindowsForms-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.MainForm.WindowsForms-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.MainForm-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Visualization.ChartControlsExtensions-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Visualization.ChartControlsExtensions-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Forms.DataVisualization" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DataTableView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DataTableView.Designer.cs">
+      <DependentUpon>DataTableView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="GanttDataView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GanttDataView.Designer.cs">
+      <DependentUpon>GanttDataView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="IndexedDataTableView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="IndexedDataTableView.Designer.cs">
+      <DependentUpon>IndexedDataTableView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ScatterPlotView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ScatterPlotView.Designer.cs">
+      <DependentUpon>ScatterPlotView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ScatterPlotVisualPropertiesDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="ScatterPlotVisualPropertiesDialog.Designer.cs">
+      <DependentUpon>ScatterPlotVisualPropertiesDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ScatterPlotVisualPropertiesControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ScatterPlotVisualPropertiesControl.Designer.cs">
+      <DependentUpon>ScatterPlotVisualPropertiesControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ScatterPlotDataRowVisualPropertiesControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ScatterPlotDataRowVisualPropertiesControl.Designer.cs">
+      <DependentUpon>ScatterPlotDataRowVisualPropertiesControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ScatterPlotHistoryView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ScatterPlotHistoryView.Designer.cs">
+      <DependentUpon>ScatterPlotHistoryView.cs</DependentUpon>
+    </Compile>
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="AlleleFrequencyCollectionView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="AlleleFrequencyCollectionView.Designer.cs">
+      <DependentUpon>AlleleFrequencyCollectionView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DataRowVisualPropertiesControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DataRowVisualPropertiesControl.Designer.cs">
+      <DependentUpon>DataRowVisualPropertiesControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesControl.Designer.cs">
+      <DependentUpon>DataTableVisualPropertiesControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesDialog.Designer.cs">
+      <DependentUpon>DataTableVisualPropertiesDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="HeatMapHistoryView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="HeatMapHistoryView.Designer.cs">
+      <DependentUpon>HeatMapHistoryView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DataTableHistoryView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DataTableHistoryView.Designer.cs">
+      <DependentUpon>DataTableHistoryView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="HeatMapView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="HeatMapView.Designer.cs">
+      <DependentUpon>HeatMapView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="AlleleFrequencyView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="AlleleFrequencyView.Designer.cs">
+      <DependentUpon>AlleleFrequencyView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="AlleleFrequencyCollectionHistoryView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="AlleleFrequencyCollectionHistoryView.Designer.cs">
+      <DependentUpon>AlleleFrequencyCollectionHistoryView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="HistogramControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="HistogramControl.Designer.cs">
+      <DependentUpon>HistogramControl.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="HeatMapView.resx">
+      <DependentUpon>HeatMapView.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HistogramControl.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HistogramControl.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HistogramControl.Designer.cs	(revision 15719)
@@ -0,0 +1,202 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Visualization.ChartControlsExtensions;
+
+namespace HeuristicLab.Analysis.Views {
+  partial class HistogramControl {
+    /// <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 chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend2 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+      System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.binsNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label1 = new System.Windows.Forms.Label();
+      this.exactCheckBox = new System.Windows.Forms.CheckBox();
+      this.label2 = new System.Windows.Forms.Label();
+      this.bandwidthNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.noDataLabel = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.bandwidthNumericUpDown)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      this.chart.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)));
+      chartArea2.Name = "ChartArea1";
+      this.chart.ChartAreas.Add(chartArea2);
+      legend2.Alignment = System.Drawing.StringAlignment.Center;
+      legend2.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend2.Name = "Default";
+      this.chart.Legends.Add(legend2);
+      this.chart.Location = new System.Drawing.Point(0, 27);
+      this.chart.Name = "chart";
+      series2.ChartArea = "ChartArea1";
+      series2.Legend = "Default";
+      series2.Name = "Series1";
+      this.chart.Series.Add(series2);
+      this.chart.Size = new System.Drawing.Size(465, 336);
+      this.chart.TabIndex = 0;
+      // 
+      // binsNumericUpDown
+      // 
+      this.binsNumericUpDown.Location = new System.Drawing.Point(91, 3);
+      this.binsNumericUpDown.Maximum = new decimal(new int[] {
+            100000,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.Minimum = new decimal(new int[] {
+            2,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.Name = "binsNumericUpDown";
+      this.binsNumericUpDown.Size = new System.Drawing.Size(61, 20);
+      this.binsNumericUpDown.TabIndex = 1;
+      this.binsNumericUpDown.Value = new decimal(new int[] {
+            10,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.ValueChanged += new System.EventHandler(this.binsNumericUpDown_ValueChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 5);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(82, 13);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "Number of Bins:";
+      // 
+      // exactCheckBox
+      // 
+      this.exactCheckBox.AutoSize = true;
+      this.exactCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.exactCheckBox.Location = new System.Drawing.Point(291, 4);
+      this.exactCheckBox.Name = "exactCheckBox";
+      this.exactCheckBox.Size = new System.Drawing.Size(56, 17);
+      this.exactCheckBox.TabIndex = 3;
+      this.exactCheckBox.Text = "Exact:";
+      this.exactCheckBox.UseVisualStyleBackColor = true;
+      this.exactCheckBox.CheckedChanged += new System.EventHandler(this.exactCheckBox_CheckedChanged);
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(158, 5);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(60, 13);
+      this.label2.TabIndex = 5;
+      this.label2.Text = "Bandwidth:";
+      // 
+      // bandwidthNumericUpDown
+      // 
+      this.bandwidthNumericUpDown.DecimalPlaces = 2;
+      this.bandwidthNumericUpDown.Location = new System.Drawing.Point(224, 3);
+      this.bandwidthNumericUpDown.Maximum = new decimal(new int[] {
+            100000000,
+            0,
+            0,
+            0});
+      this.bandwidthNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            851968});
+      this.bandwidthNumericUpDown.Name = "bandwidthNumericUpDown";
+      this.bandwidthNumericUpDown.Size = new System.Drawing.Size(61, 20);
+      this.bandwidthNumericUpDown.TabIndex = 4;
+      this.bandwidthNumericUpDown.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.bandwidthNumericUpDown.ValueChanged += new System.EventHandler(this.bandwidthNumericUpDown_ValueChanged);
+      // 
+      // noDataLabel
+      // 
+      this.noDataLabel.Anchor = System.Windows.Forms.AnchorStyles.None;
+      this.noDataLabel.AutoSize = true;
+      this.noDataLabel.Location = new System.Drawing.Point(163, 175);
+      this.noDataLabel.Name = "noDataLabel";
+      this.noDataLabel.Size = new System.Drawing.Size(139, 13);
+      this.noDataLabel.TabIndex = 22;
+      this.noDataLabel.Text = "No data could be displayed.";
+      // 
+      // HistogramControl
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.noDataLabel);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.bandwidthNumericUpDown);
+      this.Controls.Add(this.exactCheckBox);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.binsNumericUpDown);
+      this.Controls.Add(this.chart);
+      this.Name = "HistogramControl";
+      this.Size = new System.Drawing.Size(465, 363);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.bandwidthNumericUpDown)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private EnhancedChart chart;
+    private System.Windows.Forms.NumericUpDown binsNumericUpDown;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.CheckBox exactCheckBox;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.NumericUpDown bandwidthNumericUpDown;
+    private System.Windows.Forms.Label noDataLabel;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HistogramControl.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HistogramControl.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/HistogramControl.cs	(revision 15719)
@@ -0,0 +1,256 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Analysis.Statistics;
+
+namespace HeuristicLab.Analysis.Views {
+  public partial class HistogramControl : UserControl {
+    protected static readonly string SeriesName = "Histogram";
+    protected static readonly decimal bandwidthMin = 0.0000000000001m;
+    protected Dictionary<string, List<double>> points;
+    protected bool suppressUpdate;
+
+    public int NumberOfBins {
+      get { return (int)binsNumericUpDown.Value; }
+      set { binsNumericUpDown.Value = value; }
+    }
+
+    public int MinimumNumberOfBins {
+      get { return (int)binsNumericUpDown.Minimum; }
+      set { binsNumericUpDown.Minimum = value; }
+    }
+
+    public int MaximumNumberOfBins {
+      get { return (int)binsNumericUpDown.Maximum; }
+      set { binsNumericUpDown.Maximum = value; }
+    }
+
+    public int IncrementNumberOfBins {
+      get { return (int)binsNumericUpDown.Increment; }
+      set { binsNumericUpDown.Increment = value; }
+    }
+
+    public bool CalculateExactBins {
+      get { return exactCheckBox.Checked; }
+      set { exactCheckBox.Checked = value; }
+    }
+
+    public bool ShowExactCheckbox {
+      get { return exactCheckBox.Visible; }
+      set { exactCheckBox.Visible = value; }
+    }
+
+    public HistogramControl() {
+      InitializeComponent();
+      points = new Dictionary<string, List<double>>();
+    }
+
+    protected void InitNewRow(string name) {
+      if (!points.ContainsKey(name)) {
+        points.Add(name, new List<double>());
+      }
+    }
+
+    protected void InitSeries(string name) {
+      if (!chart.Series.Any(x => x.Name == name)) {
+        Series s = chart.Series.Add(name);
+        s.ChartType = SeriesChartType.Column;
+        s.BorderColor = Color.Black;
+        s.BorderWidth = 1;
+        s.BorderDashStyle = ChartDashStyle.Solid;
+      }
+    }
+
+    public void AddPoint(double point) {
+      InitNewRow(SeriesName);
+      InitSeries(SeriesName);
+      points[SeriesName].Add(point);
+      UpdateHistogram();
+    }
+
+    public void AddPoints(IEnumerable<double> points) {
+      InitNewRow(SeriesName);
+      InitSeries(SeriesName);
+      this.points[SeriesName].AddRange(points);
+      UpdateHistogram();
+    }
+
+    public void AddPoint(string name, double point, bool replace = false) {
+      InitNewRow(name);
+      InitSeries(name);
+      if (replace) {
+        points[name].Clear();
+      }
+      points[name].Add(point);
+      UpdateHistogram();
+    }
+
+    public void AddPoints(string name, IEnumerable<double> points, bool replace = false) {
+      InitNewRow(name);
+      InitSeries(name);
+      if (replace) {
+        this.points[name].Clear();
+      }
+      this.points[name].AddRange(points);
+      UpdateHistogram();
+    }
+
+    public void ClearPoints() {
+      points.Clear();
+      UpdateHistogram();
+    }
+
+    protected void UpdateHistogram(double bandwith = double.NaN) {
+      if (InvokeRequired) {
+        Invoke((Action<double>)UpdateHistogram, bandwith);
+        return;
+      }
+
+      double overallMin = double.MaxValue;
+      double overallMax = double.MinValue;
+      int bins = (int)binsNumericUpDown.Value;
+
+      chart.Series.Clear();
+      foreach (var point in points) {
+        if (!point.Value.Any()) continue;
+
+        double minValue = point.Value.Min();
+        double maxValue = point.Value.Max();
+        double intervalWidth = (maxValue - minValue) / bins;
+        if (intervalWidth <= 0) continue;
+
+        Series histogramSeries = new Series(point.Key);
+        chart.Series.Add(histogramSeries);
+
+        if (!exactCheckBox.Checked) {
+          intervalWidth = HumanRoundRange(intervalWidth);
+          minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
+          maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
+        }
+
+        double current = minValue, intervalCenter = intervalWidth / 2.0;
+        int count = 0;
+        foreach (double v in point.Value.OrderBy(x => x)) {
+          while (v > current + intervalWidth) {
+            histogramSeries.Points.AddXY(current + intervalCenter, count);
+            current += intervalWidth;
+            count = 0;
+          }
+          count++;
+        }
+        histogramSeries.Points.AddXY(current + intervalCenter, count);
+        histogramSeries["PointWidth"] = "1";
+
+        overallMax = Math.Max(overallMax, maxValue);
+        overallMin = Math.Min(overallMin, minValue);
+
+        chart.ApplyPaletteColors();
+        CalculateDensity(histogramSeries, point.Value, bandwith);
+      }
+
+      if (chart.Series.Any()) {
+        noDataLabel.Visible = false;
+      } else {
+        noDataLabel.Visible = true;
+      }
+
+      ChartArea chartArea = chart.ChartAreas[0];
+      // don't show grid lines for second y-axis
+      chartArea.AxisY2.MajorGrid.Enabled = false;
+      chartArea.AxisY2.MinorGrid.Enabled = false;
+      chartArea.AxisY.Title = "Frequency";
+
+      double overallIntervalWidth = (overallMax - overallMin) / bins;
+      double axisInterval = overallIntervalWidth;
+      while ((overallMax - overallMin) / axisInterval > 10.0) {
+        axisInterval *= 2.0;
+      }
+      chartArea.AxisX.Interval = axisInterval;
+    }
+
+    protected void CalculateDensity(Series series, List<double> row, double bandwidth = double.NaN) {
+      string densitySeriesName = "Density " + series.Name;
+      double stepWidth = series.Points[1].XValue - series.Points[0].XValue;
+      var rowArray = row.ToArray();
+
+      if (chart.Series.Any(x => x.Name == densitySeriesName)) {
+        var ds = chart.Series.Single(x => x.Name == densitySeriesName);
+        chart.Series.Remove(ds);
+      }
+
+      if (double.IsNaN(bandwidth)) {
+        bandwidth = KernelDensityEstimator.EstimateBandwidth(rowArray);
+        decimal bwDecimal = (decimal)bandwidth;
+        if (bwDecimal < bandwidthMin) {
+          bwDecimal = bandwidthMin;
+          bandwidth = decimal.ToDouble(bwDecimal);
+        }
+        suppressUpdate = true;
+        bandwidthNumericUpDown.Value = bwDecimal;
+      }
+      var density = KernelDensityEstimator.Density(rowArray, rowArray.Length, stepWidth, bandwidth);
+
+      Series newSeries = new Series(densitySeriesName);
+      newSeries.Color = series.Color;
+      newSeries.ChartType = SeriesChartType.FastLine;
+      newSeries.BorderWidth = 2;
+      foreach (var d in density) {
+        newSeries.Points.Add(new DataPoint(d.Item1, d.Item2));
+      }
+
+      // densities should be plotted on the second axis (different scale)
+      newSeries.YAxisType = AxisType.Secondary;
+      chart.Series.Add(newSeries);
+    }
+
+    protected double HumanRoundRange(double range) {
+      double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
+      double rounding = range / base10;
+      if (rounding <= 1.5) rounding = 1;
+      else if (rounding <= 2.25) rounding = 2;
+      else if (rounding <= 3.75) rounding = 2.5;
+      else if (rounding <= 7.5) rounding = 5;
+      else rounding = 10;
+      return rounding * base10;
+    }
+
+    private void binsNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      UpdateHistogram();
+    }
+
+    private void exactCheckBox_CheckedChanged(object sender, EventArgs e) {
+      UpdateHistogram();
+    }
+
+    private void bandwidthNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!suppressUpdate) {
+        UpdateHistogram(decimal.ToDouble(bandwidthNumericUpDown.Value));
+      }
+      suppressUpdate = false;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/IndexedDataTableView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/IndexedDataTableView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/IndexedDataTableView.Designer.cs	(revision 15719)
@@ -0,0 +1,125 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class IndexedDataTableView<T> {
+    /// <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) {
+        if (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() {
+      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.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Location = new System.Drawing.Point(55, 0);
+      this.nameTextBox.Size = new System.Drawing.Size(279, 20);
+      // 
+      // infoLabel
+      // 
+      this.infoLabel.Location = new System.Drawing.Point(340, 3);
+      // 
+      // chart
+      // 
+      this.chart.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)));
+      this.chart.BorderlineColor = System.Drawing.Color.Black;
+      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
+      chartArea1.AxisX.Minimum = 0D;
+      chartArea1.CursorX.IsUserEnabled = true;
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
+      chartArea1.Name = "Default";
+      this.chart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Default";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(0, 26);
+      this.chart.Name = "chart";
+      series1.ChartArea = "Default";
+      series1.Legend = "Default";
+      series1.Name = "Default";
+      this.chart.Series.Add(series1);
+      this.chart.Size = new System.Drawing.Size(359, 248);
+      this.chart.TabIndex = 3;
+      this.chart.Text = "chart";
+      title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      title1.Name = "Default";
+      title1.Text = "Title";
+      this.chart.Titles.Add(title1);
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // DataTableView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.chart);
+      this.Name = "DataTableView";
+      this.Size = new System.Drawing.Size(359, 274);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      this.Controls.SetChildIndex(this.chart, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/IndexedDataTableView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/IndexedDataTableView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/IndexedDataTableView.cs	(revision 15719)
@@ -0,0 +1,609 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Collections;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("IndexedDataTable View")]
+  [Content(typeof(IndexedDataTable<>), true)]
+  public partial class IndexedDataTableView<T> : NamedItemView {
+    protected List<Series> invisibleSeries;
+    protected Dictionary<IObservableList<Tuple<T, double>>, IndexedDataRow<T>> valuesRowsTable;
+
+    public new IndexedDataTable<T> Content {
+      get { return (IndexedDataTable<T>)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public IndexedDataTableView() {
+      InitializeComponent();
+      valuesRowsTable = new Dictionary<IObservableList<Tuple<T, double>>, IndexedDataRow<T>>();
+      invisibleSeries = new List<Series>();
+      chart.CustomizeAllChartAreas();
+      chart.ChartAreas[0].CursorX.Interval = 1;
+      chart.SuppressExceptions = true;
+    }
+
+    #region Event Handler Registration
+    protected override void DeregisterContentEvents() {
+      foreach (var row in Content.Rows)
+        DeregisterDataRowEvents(row);
+      Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);
+      Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsAdded);
+      Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsRemoved);
+      Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsReplaced);
+      Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_CollectionReset);
+      base.DeregisterContentEvents();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
+      Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsAdded);
+      Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsRemoved);
+      Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsReplaced);
+      Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_CollectionReset);
+      foreach (var row in Content.Rows)
+        RegisterDataRowEvents(row);
+    }
+
+    /// <summary>
+    /// Automatically called for every existing data row and whenever a data row is added
+    /// to the data table. Do not call this method directly.
+    /// </summary>
+    /// <param name="row">The DataRow that was added.</param>
+    protected virtual void RegisterDataRowEvents(IndexedDataRow<T> row) {
+      row.NameChanged += new EventHandler(Row_NameChanged);
+      row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
+      valuesRowsTable.Add(row.Values, row);
+      row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsAdded);
+      row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsReplaced);
+      row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsMoved);
+      row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_CollectionReset);
+    }
+
+    /// <summary>
+    /// Automatically called for every data row that is removed from the DataTable. Do
+    /// not directly call this method.
+    /// </summary>
+    /// <param name="row">The DataRow that was removed.</param>
+    protected virtual void DeregisterDataRowEvents(IndexedDataRow<T> row) {
+      row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsAdded);
+      row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsReplaced);
+      row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsMoved);
+      row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_CollectionReset);
+      valuesRowsTable.Remove(row.Values);
+      row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
+      row.NameChanged -= new EventHandler(Row_NameChanged);
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      invisibleSeries.Clear();
+      chart.Titles[0].Text = string.Empty;
+      chart.ChartAreas[0].AxisX.Title = string.Empty;
+      chart.ChartAreas[0].AxisY.Title = string.Empty;
+      chart.ChartAreas[0].AxisY2.Title = string.Empty;
+      chart.ChartAreas[0].AxisX.IsLogarithmic = false;
+      chart.ChartAreas[0].AxisX2.IsLogarithmic = false;
+      chart.ChartAreas[0].AxisY.IsLogarithmic = false;
+      chart.ChartAreas[0].AxisY2.IsLogarithmic = false;
+      chart.Series.Clear();
+      if (Content != null) {
+        chart.Titles[0].Text = Content.Name;
+        foreach (var row in Content.Rows)
+          AddDataRow(row);
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]);
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      chart.Enabled = Content != null;
+    }
+
+    /// <summary>
+    /// Add the DataRow as a series to the chart.
+    /// </summary>
+    /// <param name="row">DataRow to add as series to the chart.</param>
+    protected virtual void AddDataRow(IndexedDataRow<T> row) {
+      if (row.Values.Count == 0) return;
+
+      Series series = new Series(row.Name);
+      if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+      else series.LegendText = row.Name;
+      ConfigureSeries(series, row);
+      FillSeriesWithRowValues(series, row);
+
+      chart.Series.Add(series);
+      ConfigureChartArea(chart.ChartAreas[0]);
+      RecalculateAxesScale(chart.ChartAreas[0]);
+      UpdateYCursorInterval();
+    }
+
+    private void ConfigureSeries(Series series, IndexedDataRow<T> row) {
+      RemoveCustomPropertyIfExists(series, "PointWidth");
+      series.BorderWidth = 1;
+      series.BorderDashStyle = ChartDashStyle.Solid;
+      series.BorderColor = Color.Empty;
+
+      series.Color = row.VisualProperties.Color;
+      series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;
+
+      series.SmartLabelStyle.Enabled = true;
+      series.SmartLabelStyle.AllowOutsidePlotArea = LabelOutsidePlotAreaStyle.No;
+      series.SmartLabelStyle.CalloutLineAnchorCapStyle = LineAnchorCapStyle.None;
+      series.SmartLabelStyle.CalloutLineColor = series.Color;
+      series.SmartLabelStyle.CalloutLineWidth = 2;
+      series.SmartLabelStyle.CalloutStyle = LabelCalloutStyle.Underlined;
+      series.SmartLabelStyle.IsOverlappedHidden = false;
+      series.SmartLabelStyle.MaxMovingDistance = 200;
+
+      switch (row.VisualProperties.ChartType) {
+        case DataRowVisualProperties.DataRowChartType.Line:
+          series.ChartType = SeriesChartType.FastLine;
+          series.BorderWidth = row.VisualProperties.LineWidth;
+          series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
+          break;
+        case DataRowVisualProperties.DataRowChartType.Bars:
+          // Bar is incompatible with anything but Bar and StackedBar*
+          if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100)) {
+            series.ChartType = SeriesChartType.Bar;
+            chart.ChartAreas[0].AxisX.Interval = 1;
+          } else {
+            series.ChartType = SeriesChartType.FastPoint; //default
+            row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          }
+          break;
+        case DataRowVisualProperties.DataRowChartType.Columns:
+          series.ChartType = SeriesChartType.Column;
+          break;
+        case DataRowVisualProperties.DataRowChartType.Points:
+          series.ChartType = SeriesChartType.FastPoint;
+          break;
+        case DataRowVisualProperties.DataRowChartType.StepLine:
+          series.ChartType = SeriesChartType.StepLine;
+          series.BorderWidth = row.VisualProperties.LineWidth;
+          series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
+          break;
+        default:
+          series.ChartType = SeriesChartType.FastPoint;
+          break;
+      }
+      series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
+      series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary;
+      if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+      else series.LegendText = row.Name;
+      series.ToolTip = series.LegendText + " X = #VALX, Y = #VALY";
+    }
+
+    private void ConfigureChartArea(ChartArea area) {
+      if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
+      if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX.Title = Content.VisualProperties.XAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX2.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX2.Title = Content.VisualProperties.SecondXAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY.Title = Content.VisualProperties.YAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY2.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY2.Title = Content.VisualProperties.SecondYAxisTitle;
+
+      if (typeof(T).Equals(typeof(DateTime))) {
+        area.AxisX.IntervalType = DateTimeIntervalType.Hours;
+        area.AxisX.LabelStyle.Format = "dd.MM.yyyy HH:mm";
+        area.AxisX.IntervalAutoMode = IntervalAutoMode.VariableCount;
+      }
+    }
+
+    private void RecalculateAxesScale(ChartArea area) {
+      // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds
+      foreach (Axis a in area.Axes) {
+        a.Minimum = double.NaN;
+        a.Maximum = double.NaN;
+      }
+
+      if (chart.Series.Any(x => x.Enabled && x.XAxisType == AxisType.Primary && (x.Points.Count == 0 || x.Points.Any(y => y.XValue <= 0))))
+        area.AxisX.IsLogarithmic = false;
+      else area.AxisX.IsLogarithmic = Content.VisualProperties.XAxisLogScale;
+      if (chart.Series.Any(x => x.Enabled && x.XAxisType == AxisType.Secondary && (x.Points.Count == 0 || x.Points.Any(y => y.XValue <= 0))))
+        area.AxisX2.IsLogarithmic = false;
+      else area.AxisX2.IsLogarithmic = Content.VisualProperties.SecondXAxisLogScale;
+
+      if (chart.Series.Any(x => x.Enabled && x.YAxisType == AxisType.Primary && (x.Points.Count == 0 || x.Points.Any(y => y.YValues.Min() <= 0))))
+        area.AxisY.IsLogarithmic = false;
+      else area.AxisY.IsLogarithmic = Content.VisualProperties.YAxisLogScale;
+      if (chart.Series.Any(x => x.Enabled && x.YAxisType == AxisType.Secondary && (x.Points.Count == 0 || x.Points.Any(y => y.YValues.Min() <= 0))))
+        area.AxisY2.IsLogarithmic = false;
+      else area.AxisY2.IsLogarithmic = Content.VisualProperties.SecondYAxisLogScale;
+
+      area.RecalculateAxesScale();
+      area.AxisX.IsMarginVisible = false;
+      area.AxisX2.IsMarginVisible = false;
+
+      area.AxisX.IsStartedFromZero = Content.Rows.Where(x => !x.VisualProperties.SecondXAxis).Any(x => x.VisualProperties.StartIndexZero);
+      area.AxisX2.IsStartedFromZero = Content.Rows.Where(x => x.VisualProperties.SecondXAxis).Any(x => x.VisualProperties.StartIndexZero);
+
+      if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
+      if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
+      if (!Content.VisualProperties.SecondXAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMinimumFixedValue)) area.AxisX2.Minimum = Content.VisualProperties.SecondXAxisMinimumFixedValue;
+      if (!Content.VisualProperties.SecondXAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMaximumFixedValue)) area.AxisX2.Maximum = Content.VisualProperties.SecondXAxisMaximumFixedValue;
+      if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
+      if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
+      if (!Content.VisualProperties.SecondYAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMinimumFixedValue)) area.AxisY2.Minimum = Content.VisualProperties.SecondYAxisMinimumFixedValue;
+      if (!Content.VisualProperties.SecondYAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMaximumFixedValue)) area.AxisY2.Maximum = Content.VisualProperties.SecondYAxisMaximumFixedValue;
+      if (area.AxisX.Minimum >= area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1;
+      if (area.AxisX2.Minimum >= area.AxisX2.Maximum) area.AxisX2.Maximum = area.AxisX2.Minimum + 1;
+      if (area.AxisY.Minimum >= area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1;
+      if (area.AxisY2.Minimum >= area.AxisY2.Maximum) area.AxisY2.Maximum = area.AxisY2.Minimum + 1;
+    }
+
+    /// <summary>
+    /// Set the Y Cursor interval to visible points of enabled series.
+    /// </summary>
+    protected virtual void UpdateYCursorInterval() {
+      double interestingValuesRange = (
+        from series in chart.Series
+        where series.Enabled
+        let values = (from point in series.Points
+                      where !point.IsEmpty
+                      select point.YValues[0]).DefaultIfEmpty(1.0)
+        let range = values.Max() - values.Min()
+        where range > 0.0
+        select range
+        ).DefaultIfEmpty(1.0).Min();
+
+      double digits = (int)Math.Log10(interestingValuesRange) - 3;
+      double yZoomInterval = Math.Pow(10, digits);
+      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
+    }
+
+
+    /// <summary>
+    /// Remove the corresponding series for a certain DataRow.
+    /// </summary>
+    /// <param name="row">DataRow which series should be removed.</param>
+    protected virtual void RemoveDataRow(IndexedDataRow<T> row) {
+      if (chart.Series.All(x => x.Name != row.Name)) return;
+      Series series = chart.Series[row.Name];
+      chart.Series.Remove(series);
+      if (invisibleSeries.Contains(series))
+        invisibleSeries.Remove(series);
+      RecalculateAxesScale(chart.ChartAreas[0]);
+    }
+
+    #region Event Handlers
+    #region Content Event Handlers
+    protected override void Content_NameChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_NameChanged), sender, e);
+      else {
+        chart.Titles[0].Text = Content.Name;
+        base.Content_NameChanged(sender, e);
+      }
+    }
+    private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
+      else {
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
+      }
+    }
+    #endregion
+    #region Rows Event Handlers
+    private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsAdded), sender, e);
+      else {
+        foreach (var row in e.Items) {
+          AddDataRow(row);
+          RegisterDataRowEvents(row);
+        }
+      }
+    }
+    private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsRemoved), sender, e);
+      else {
+        foreach (var row in e.Items) {
+          DeregisterDataRowEvents(row);
+          RemoveDataRow(row);
+        }
+      }
+    }
+    private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_ItemsReplaced), sender, e);
+      else {
+        foreach (var row in e.OldItems) {
+          DeregisterDataRowEvents(row);
+          RemoveDataRow(row);
+        }
+        foreach (var row in e.Items) {
+          AddDataRow(row);
+          RegisterDataRowEvents(row);
+        }
+      }
+    }
+    private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(Rows_CollectionReset), sender, e);
+      else {
+        foreach (var row in e.OldItems) {
+          DeregisterDataRowEvents(row);
+          RemoveDataRow(row);
+        }
+        foreach (var row in e.Items) {
+          AddDataRow(row);
+          RegisterDataRowEvents(row);
+        }
+      }
+    }
+    #endregion
+    #region Row Event Handlers
+    private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);
+      else {
+        var row = (IndexedDataRow<T>)sender;
+        Series series = chart.Series[row.Name];
+        series.Points.Clear();
+        ConfigureSeries(series, row);
+        FillSeriesWithRowValues(series, row);
+        RecalculateAxesScale(chart.ChartAreas[0]);
+      }
+    }
+    private void Row_NameChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Row_NameChanged), sender, e);
+      else {
+        var row = (IndexedDataRow<T>)sender;
+        chart.Series[row.Name].Name = row.Name;
+      }
+    }
+    #endregion
+    #region Values Event Handlers
+    private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsAdded), sender, e);
+      else {
+        IndexedDataRow<T> row = null;
+        valuesRowsTable.TryGetValue((IObservableList<Tuple<T, double>>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            rowSeries.Points.Clear();
+            FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        } else AddDataRow((IndexedDataRow<T>)sender);
+      }
+    }
+    private void Values_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsRemoved), sender, e);
+      else {
+        IndexedDataRow<T> row = null;
+        valuesRowsTable.TryGetValue((IObservableList<Tuple<T, double>>)sender, out row);
+        if (row != null) {
+          if (row.Values.Count == 0) {
+            RemoveDataRow(row);
+          } else {
+            Series rowSeries = chart.Series[row.Name];
+            if (!invisibleSeries.Contains(rowSeries)) {
+              rowSeries.Points.Clear();
+              FillSeriesWithRowValues(rowSeries, row);
+              RecalculateAxesScale(chart.ChartAreas[0]);
+              UpdateYCursorInterval();
+            }
+          }
+        }
+      }
+    }
+    private void Values_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsReplaced), sender, e);
+      else {
+        IndexedDataRow<T> row = null;
+        valuesRowsTable.TryGetValue((IObservableList<Tuple<T, double>>)sender, out row);
+        if (row != null) {
+          if (row.Values.Count == 0) {
+            RemoveDataRow(row);
+          } else {
+            Series rowSeries = chart.Series[row.Name];
+            if (!invisibleSeries.Contains(rowSeries)) {
+              if (row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram) {
+                rowSeries.Points.Clear();
+                FillSeriesWithRowValues(rowSeries, row);
+              } else {
+                foreach (IndexedItem<Tuple<T, double>> item in e.Items) {
+                  rowSeries.Points[item.Index].SetValueXY(item.Value.Item1, item.Value.Item2);
+                }
+              }
+              RecalculateAxesScale(chart.ChartAreas[0]);
+              UpdateYCursorInterval();
+            }
+          }
+        }
+      }
+    }
+    private void Values_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_ItemsMoved), sender, e);
+      else {
+        IndexedDataRow<T> row = null;
+        valuesRowsTable.TryGetValue((IObservableList<Tuple<T, double>>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            rowSeries.Points.Clear();
+            FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+
+    private void Values_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(Values_CollectionReset), sender, e);
+      else {
+        IndexedDataRow<T> row = null;
+        valuesRowsTable.TryGetValue((IObservableList<Tuple<T, double>>)sender, out row);
+        if (row != null) {
+          if (row.Values.Count == 0) {
+            RemoveDataRow(row);
+          } else {
+            Series rowSeries = chart.Series[row.Name];
+            if (!invisibleSeries.Contains(rowSeries)) {
+              rowSeries.Points.Clear();
+              FillSeriesWithRowValues(rowSeries, row);
+              RecalculateAxesScale(chart.ChartAreas[0]);
+              UpdateYCursorInterval();
+            }
+          }
+        }
+      }
+    }
+    #endregion
+    #endregion
+
+    #region Chart Event Handlers
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        ToggleSeriesVisible(result.Series);
+      }
+    }
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+    }
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = invisibleSeries.Contains(series);
+          foreach (LegendCell cell in legendItem.Cells) {
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+          }
+        }
+      }
+    }
+    #endregion
+
+    private void ToggleSeriesVisible(Series series) {
+      if (!invisibleSeries.Contains(series)) {
+        series.Points.Clear();
+        invisibleSeries.Add(series);
+      } else {
+        invisibleSeries.Remove(series);
+        if (Content != null) {
+
+          var row = (from r in Content.Rows
+                     where r.Name == series.Name
+                     select r).Single();
+          FillSeriesWithRowValues(series, row);
+          this.chart.Legends[series.Legend].ForeColor = Color.Black;
+          RecalculateAxesScale(chart.ChartAreas[0]);
+          UpdateYCursorInterval();
+        }
+      }
+    }
+
+    private void FillSeriesWithRowValues(Series series, IndexedDataRow<T> row) {
+      for (int i = 0; i < row.Values.Count; i++) {
+        var value = row.Values[i];
+        if (IsInvalidValue(value.Item2)) continue;
+        var point = new DataPoint();
+        point.SetValueXY(value.Item1, value.Item2);
+        if (i == row.Values.Count - 1) {
+          point.Label = series.Name;
+          point.MarkerStyle = MarkerStyle.Cross;
+          point.MarkerSize = 15;
+          point.MarkerBorderWidth = 1;
+        }
+        series.Points.Add(point);
+      }
+    }
+
+    #region Helpers
+    protected void RemoveCustomPropertyIfExists(Series series, string property) {
+      if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property);
+    }
+
+    private ChartDashStyle ConvertLineStyle(DataRowVisualProperties.DataRowLineStyle dataRowLineStyle) {
+      switch (dataRowLineStyle) {
+        case DataRowVisualProperties.DataRowLineStyle.Dash:
+          return ChartDashStyle.Dash;
+        case DataRowVisualProperties.DataRowLineStyle.DashDot:
+          return ChartDashStyle.DashDot;
+        case DataRowVisualProperties.DataRowLineStyle.DashDotDot:
+          return ChartDashStyle.DashDotDot;
+        case DataRowVisualProperties.DataRowLineStyle.Dot:
+          return ChartDashStyle.Dot;
+        case DataRowVisualProperties.DataRowLineStyle.NotSet:
+          return ChartDashStyle.NotSet;
+        case DataRowVisualProperties.DataRowLineStyle.Solid:
+          return ChartDashStyle.Solid;
+        default:
+          return ChartDashStyle.NotSet;
+      }
+    }
+
+    /// <summary>
+    /// Determines whether a double value can be displayed (converted to Decimal and not an NaN).
+    /// </summary>
+    /// <param name="x">The number to check.</param>
+    /// <returns><code>true</code> if the value can be safely shwon in the chart,
+    /// <code>false</code> otherwise.</returns>
+    protected static bool IsInvalidValue(double x) {
+      return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/Plugin.cs.frame
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/Plugin.cs.frame	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/Plugin.cs.frame	(revision 15719)
@@ -0,0 +1,43 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Analysis.Views {
+  /// <summary>
+  /// Plugin class for HeuristicLab.Analysis.Views plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.Analysis.Views", "3.3.15.$WCREV$")]
+  [PluginFile("HeuristicLab.Analysis.Views-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Core.Views", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
+  [PluginDependency("HeuristicLab.Visualization.ChartControlsExtensions", "3.3")]
+  public class HeuristicLabAnalysisViewsPlugin : PluginBase {
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/Properties/AssemblyInfo.cs.frame	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/Properties/AssemblyInfo.cs.frame	(revision 15719)
@@ -0,0 +1,56 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Analysis.Views")]
+[assembly: AssemblyDescription("Views of the HeuristicLab algorithm analysis classes")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("bb4e3c6d-ba36-4bb9-a601-04d3c714c0f1")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.15.$WCREV$")]
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.Designer.cs	(revision 15719)
@@ -0,0 +1,346 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class ScatterPlotDataRowVisualPropertiesControl {
+    /// <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();
+      this.pointStyleComboBox = new System.Windows.Forms.ComboBox();
+      this.colorDialog = new System.Windows.Forms.ColorDialog();
+      this.colorButton = new System.Windows.Forms.Button();
+      this.isVisibleInLegendCheckBox = new System.Windows.Forms.CheckBox();
+      this.label1 = new System.Windows.Forms.Label();
+      this.label2 = new System.Windows.Forms.Label();
+      this.pointSizeNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label3 = new System.Windows.Forms.Label();
+      this.displayNameTextBox = new System.Windows.Forms.TextBox();
+      this.label9 = new System.Windows.Forms.Label();
+      this.label7 = new System.Windows.Forms.Label();
+      this.label4 = new System.Windows.Forms.Label();
+      this.regressionTypeComboBox = new System.Windows.Forms.ComboBox();
+      this.regressionGroupBox = new System.Windows.Forms.GroupBox();
+      this.isRegressionVisibleInLegendCheckBox = new System.Windows.Forms.CheckBox();
+      this.polynomialRegressionOrderNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.orderLabel = new System.Windows.Forms.Label();
+      this.regressionLegendTextBox = new System.Windows.Forms.TextBox();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      this.clearColorButton = new System.Windows.Forms.Button();
+      ((System.ComponentModel.ISupportInitialize)(this.pointSizeNumericUpDown)).BeginInit();
+      this.regressionGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.polynomialRegressionOrderNumericUpDown)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // pointStyleComboBox
+      // 
+      this.pointStyleComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.pointStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.pointStyleComboBox.FormattingEnabled = true;
+      this.pointStyleComboBox.Location = new System.Drawing.Point(99, 34);
+      this.pointStyleComboBox.Name = "pointStyleComboBox";
+      this.pointStyleComboBox.Size = new System.Drawing.Size(240, 21);
+      this.pointStyleComboBox.TabIndex = 3;
+      this.pointStyleComboBox.SelectedValueChanged += new System.EventHandler(this.pointStyleComboBox_SelectedValueChanged);
+      // 
+      // colorDialog
+      // 
+      this.colorDialog.Color = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(128)))), ((int)(((byte)(255)))));
+      // 
+      // colorButton
+      // 
+      this.colorButton.BackColor = System.Drawing.SystemColors.Control;
+      this.colorButton.Location = new System.Drawing.Point(99, 61);
+      this.colorButton.Name = "colorButton";
+      this.colorButton.Size = new System.Drawing.Size(23, 23);
+      this.colorButton.TabIndex = 5;
+      this.colorButton.UseVisualStyleBackColor = false;
+      this.colorButton.Click += new System.EventHandler(this.colorButton_Click);
+      // 
+      // isVisibleInLegendCheckBox
+      // 
+      this.isVisibleInLegendCheckBox.AutoSize = true;
+      this.isVisibleInLegendCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.isVisibleInLegendCheckBox.Location = new System.Drawing.Point(99, 116);
+      this.isVisibleInLegendCheckBox.Name = "isVisibleInLegendCheckBox";
+      this.isVisibleInLegendCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.isVisibleInLegendCheckBox.TabIndex = 3;
+      this.isVisibleInLegendCheckBox.UseVisualStyleBackColor = true;
+      this.isVisibleInLegendCheckBox.CheckedChanged += new System.EventHandler(this.isVisibleInLegendCheckBox_CheckedChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 37);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(60, 13);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "&Point Style:";
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(3, 66);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(61, 13);
+      this.label2.TabIndex = 4;
+      this.label2.Text = "Point &Color:";
+      // 
+      // pointSizeNumericUpDown
+      // 
+      this.pointSizeNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.pointSizeNumericUpDown.Location = new System.Drawing.Point(99, 90);
+      this.pointSizeNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.pointSizeNumericUpDown.Name = "pointSizeNumericUpDown";
+      this.pointSizeNumericUpDown.Size = new System.Drawing.Size(240, 20);
+      this.pointSizeNumericUpDown.TabIndex = 5;
+      this.pointSizeNumericUpDown.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.pointSizeNumericUpDown.ValueChanged += new System.EventHandler(this.pointSizeNumericUpDown_ValueChanged);
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(3, 92);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(57, 13);
+      this.label3.TabIndex = 6;
+      this.label3.Text = "Point &Size:";
+      // 
+      // displayNameTextBox
+      // 
+      this.displayNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.displayNameTextBox.Location = new System.Drawing.Point(99, 8);
+      this.displayNameTextBox.Name = "displayNameTextBox";
+      this.displayNameTextBox.Size = new System.Drawing.Size(240, 20);
+      this.displayNameTextBox.TabIndex = 1;
+      this.displayNameTextBox.Validated += new System.EventHandler(this.displayNameTextBox_Validated);
+      // 
+      // label9
+      // 
+      this.label9.AutoSize = true;
+      this.label9.Location = new System.Drawing.Point(3, 11);
+      this.label9.Name = "label9";
+      this.label9.Size = new System.Drawing.Size(38, 13);
+      this.label9.TabIndex = 0;
+      this.label9.Text = "&Name:";
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(3, 116);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(90, 13);
+      this.label7.TabIndex = 2;
+      this.label7.Text = "&Visible in Legend:";
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(6, 22);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(34, 13);
+      this.label4.TabIndex = 7;
+      this.label4.Text = "Type:";
+      // 
+      // regressionTypeComboBox
+      // 
+      this.regressionTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regressionTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.regressionTypeComboBox.FormattingEnabled = true;
+      this.regressionTypeComboBox.Location = new System.Drawing.Point(93, 19);
+      this.regressionTypeComboBox.Name = "regressionTypeComboBox";
+      this.regressionTypeComboBox.Size = new System.Drawing.Size(147, 21);
+      this.regressionTypeComboBox.TabIndex = 8;
+      this.regressionTypeComboBox.SelectedValueChanged += new System.EventHandler(this.regressionTypeComboBox_SelectedValueChanged);
+      // 
+      // regressionGroupBox
+      // 
+      this.regressionGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regressionGroupBox.Controls.Add(this.isRegressionVisibleInLegendCheckBox);
+      this.regressionGroupBox.Controls.Add(this.regressionTypeComboBox);
+      this.regressionGroupBox.Controls.Add(this.polynomialRegressionOrderNumericUpDown);
+      this.regressionGroupBox.Controls.Add(this.orderLabel);
+      this.regressionGroupBox.Controls.Add(this.regressionLegendTextBox);
+      this.regressionGroupBox.Controls.Add(this.label4);
+      this.regressionGroupBox.Location = new System.Drawing.Point(3, 136);
+      this.regressionGroupBox.Name = "regressionGroupBox";
+      this.regressionGroupBox.Size = new System.Drawing.Size(336, 74);
+      this.regressionGroupBox.TabIndex = 9;
+      this.regressionGroupBox.TabStop = false;
+      this.regressionGroupBox.Text = "&Regression";
+      // 
+      // isRegressionVisibleInLegendCheckBox
+      // 
+      this.isRegressionVisibleInLegendCheckBox.AutoSize = true;
+      this.isRegressionVisibleInLegendCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.isRegressionVisibleInLegendCheckBox.Location = new System.Drawing.Point(6, 48);
+      this.isRegressionVisibleInLegendCheckBox.Name = "isRegressionVisibleInLegendCheckBox";
+      this.isRegressionVisibleInLegendCheckBox.Size = new System.Drawing.Size(68, 17);
+      this.isRegressionVisibleInLegendCheckBox.TabIndex = 13;
+      this.isRegressionVisibleInLegendCheckBox.Text = "Legend: ";
+      this.isRegressionVisibleInLegendCheckBox.UseVisualStyleBackColor = true;
+      this.isRegressionVisibleInLegendCheckBox.CheckedChanged += new System.EventHandler(this.isRegressionVisibleInLegendCheckBox_CheckedChanged);
+      // 
+      // polynomialRegressionOrderNumericUpDown
+      // 
+      this.polynomialRegressionOrderNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.polynomialRegressionOrderNumericUpDown.Location = new System.Drawing.Point(285, 20);
+      this.polynomialRegressionOrderNumericUpDown.Margin = new System.Windows.Forms.Padding(9, 3, 3, 3);
+      this.polynomialRegressionOrderNumericUpDown.Maximum = new decimal(new int[] {
+            6,
+            0,
+            0,
+            0});
+      this.polynomialRegressionOrderNumericUpDown.Minimum = new decimal(new int[] {
+            2,
+            0,
+            0,
+            0});
+      this.polynomialRegressionOrderNumericUpDown.Name = "polynomialRegressionOrderNumericUpDown";
+      this.polynomialRegressionOrderNumericUpDown.Size = new System.Drawing.Size(45, 20);
+      this.polynomialRegressionOrderNumericUpDown.TabIndex = 11;
+      this.toolTip.SetToolTip(this.polynomialRegressionOrderNumericUpDown, "Order only available for Polynomial");
+      this.polynomialRegressionOrderNumericUpDown.Value = new decimal(new int[] {
+            2,
+            0,
+            0,
+            0});
+      this.polynomialRegressionOrderNumericUpDown.ValueChanged += new System.EventHandler(this.polynomialRegressionOrderNumericUpDown_ValueChanged);
+      // 
+      // orderLabel
+      // 
+      this.orderLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.orderLabel.AutoSize = true;
+      this.orderLabel.Location = new System.Drawing.Point(246, 22);
+      this.orderLabel.Name = "orderLabel";
+      this.orderLabel.Size = new System.Drawing.Size(36, 13);
+      this.orderLabel.TabIndex = 12;
+      this.orderLabel.Text = "Order:";
+      // 
+      // regressionLegendTextBox
+      // 
+      this.regressionLegendTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regressionLegendTextBox.Location = new System.Drawing.Point(93, 46);
+      this.regressionLegendTextBox.Name = "regressionLegendTextBox";
+      this.regressionLegendTextBox.Size = new System.Drawing.Size(237, 20);
+      this.regressionLegendTextBox.TabIndex = 10;
+      this.regressionLegendTextBox.Validated += new System.EventHandler(this.regressionLegendTextBox_Validated);
+      // 
+      // clearColorButton
+      // 
+      this.clearColorButton.BackColor = System.Drawing.SystemColors.ActiveCaption;
+      this.clearColorButton.Cursor = System.Windows.Forms.Cursors.Default;
+      this.clearColorButton.FlatAppearance.BorderSize = 0;
+      this.clearColorButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+      this.clearColorButton.ForeColor = System.Drawing.Color.Transparent;
+      this.clearColorButton.Location = new System.Drawing.Point(125, 65);
+      this.clearColorButton.Margin = new System.Windows.Forms.Padding(0);
+      this.clearColorButton.Name = "clearColorButton";
+      this.clearColorButton.Size = new System.Drawing.Size(15, 16);
+      this.clearColorButton.TabIndex = 11;
+      this.clearColorButton.TabStop = false;
+      this.clearColorButton.UseVisualStyleBackColor = false;
+      this.clearColorButton.Click += new System.EventHandler(this.clearColorButton_Click);
+      // 
+      // ScatterPlotDataRowVisualPropertiesControl
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.clearColorButton);
+      this.Controls.Add(this.regressionGroupBox);
+      this.Controls.Add(this.pointSizeNumericUpDown);
+      this.Controls.Add(this.isVisibleInLegendCheckBox);
+      this.Controls.Add(this.label9);
+      this.Controls.Add(this.label3);
+      this.Controls.Add(this.pointStyleComboBox);
+      this.Controls.Add(this.label7);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.displayNameTextBox);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.colorButton);
+      this.Name = "ScatterPlotDataRowVisualPropertiesControl";
+      this.Size = new System.Drawing.Size(342, 215);
+      ((System.ComponentModel.ISupportInitialize)(this.pointSizeNumericUpDown)).EndInit();
+      this.regressionGroupBox.ResumeLayout(false);
+      this.regressionGroupBox.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.polynomialRegressionOrderNumericUpDown)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.ComboBox pointStyleComboBox;
+    private System.Windows.Forms.ColorDialog colorDialog;
+    private System.Windows.Forms.Button colorButton;
+    private System.Windows.Forms.CheckBox isVisibleInLegendCheckBox;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.NumericUpDown pointSizeNumericUpDown;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.TextBox displayNameTextBox;
+    private System.Windows.Forms.Label label9;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.ComboBox regressionTypeComboBox;
+    private System.Windows.Forms.GroupBox regressionGroupBox;
+    private System.Windows.Forms.TextBox regressionLegendTextBox;
+    private System.Windows.Forms.NumericUpDown polynomialRegressionOrderNumericUpDown;
+    private System.Windows.Forms.Label orderLabel;
+    private System.Windows.Forms.ToolTip toolTip;
+    private System.Windows.Forms.CheckBox isRegressionVisibleInLegendCheckBox;
+    private System.Windows.Forms.Button clearColorButton;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.cs	(revision 15719)
@@ -0,0 +1,178 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.Common.Resources;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("ScatterPlot DataRow Visual Properties")]
+  public partial class ScatterPlotDataRowVisualPropertiesControl : UserControl {
+    protected bool SuppressEvents { get; set; }
+
+    private ScatterPlotDataRowVisualProperties content;
+    public ScatterPlotDataRowVisualProperties Content {
+      get { return content; }
+      set {
+        bool changed = (value != content);
+        content = value;
+        if (changed) OnContentChanged();
+      }
+    }
+
+    public ScatterPlotDataRowVisualPropertiesControl() {
+      InitializeComponent();
+      pointStyleComboBox.DataSource = Enum.GetValues(typeof(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle));
+      regressionTypeComboBox.DataSource = Enum.GetValues(typeof(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType));
+      clearColorButton.BackColor = Color.Transparent;
+      clearColorButton.BackgroundImage = VSImageLibrary.Delete;
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void OnContentChanged() {
+      SuppressEvents = true;
+      try {
+        if (Content == null) {
+          pointStyleComboBox.SelectedIndex = -1;
+          colorButton.BackColor = SystemColors.Control;
+          colorButton.Text = "?";
+          isVisibleInLegendCheckBox.Checked = false;
+          pointSizeNumericUpDown.Value = 1;
+          displayNameTextBox.Text = String.Empty;
+          regressionTypeComboBox.SelectedIndex = -1;
+          polynomialRegressionOrderNumericUpDown.Value = 2;
+          isRegressionVisibleInLegendCheckBox.Checked = false;
+          regressionLegendTextBox.Text = string.Empty;
+        } else {
+          displayNameTextBox.Text = Content.DisplayName;
+          pointStyleComboBox.SelectedItem = Content.PointStyle;
+          if (Content.Color.IsEmpty) {
+            colorButton.BackColor = SystemColors.Control;
+            colorButton.Text = "?";
+          } else {
+            colorButton.BackColor = Content.Color;
+            colorButton.Text = String.Empty;
+          }
+          pointSizeNumericUpDown.Value = Content.PointSize;
+          isVisibleInLegendCheckBox.Checked = Content.IsVisibleInLegend;
+          regressionTypeComboBox.SelectedItem = Content.RegressionType;
+          polynomialRegressionOrderNumericUpDown.Value = Content.PolynomialRegressionOrder;
+          isRegressionVisibleInLegendCheckBox.Checked = Content.IsRegressionVisibleInLegend;
+          regressionLegendTextBox.Text = content.RegressionDisplayName;
+        }
+      }
+      finally { SuppressEvents = false; }
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void SetEnabledStateOfControls() {
+      pointStyleComboBox.Enabled = Content != null;
+      colorButton.Enabled = Content != null;
+      clearColorButton.Visible = Content != null && !Content.Color.IsEmpty;
+      isVisibleInLegendCheckBox.Enabled = Content != null;
+      pointSizeNumericUpDown.Enabled = Content != null;
+      displayNameTextBox.Enabled = Content != null;
+      regressionTypeComboBox.Enabled = Content != null;
+      polynomialRegressionOrderNumericUpDown.Enabled = Content != null && Content.RegressionType == ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial;
+      orderLabel.Enabled = polynomialRegressionOrderNumericUpDown.Enabled;
+      isRegressionVisibleInLegendCheckBox.Enabled = Content != null && Content.RegressionType != ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None;
+      regressionLegendTextBox.Enabled = Content != null && Content.RegressionType != ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None;
+    }
+
+    #region Event Handlers
+    private void pointStyleComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        var selected = (ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle)pointStyleComboBox.SelectedValue;
+        Content.PointStyle = selected;
+      }
+    }
+
+    private void colorButton_Click(object sender, EventArgs e) {
+      if (colorDialog.ShowDialog() == DialogResult.OK) {
+        Content.Color = colorDialog.Color;
+        colorButton.BackColor = Content.Color;
+        colorButton.Text = String.Empty;
+        clearColorButton.Visible = true;
+      }
+    }
+
+    private void clearColorButton_Click(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.Color = Color.Empty;
+        colorButton.BackColor = SystemColors.Control;
+        colorButton.Text = "?";
+        clearColorButton.Visible = false;
+      }
+    }
+
+    private void displayNameTextBox_Validated(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.DisplayName = displayNameTextBox.Text;
+        }
+        finally { SuppressEvents = false; }
+      }
+    }
+
+    private void pointSizeNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.PointSize = (int)pointSizeNumericUpDown.Value;
+      }
+    }
+
+    private void isVisibleInLegendCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.IsVisibleInLegend = isVisibleInLegendCheckBox.Checked;
+      }
+    }
+
+    private void regressionTypeComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        var selected = (ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType)regressionTypeComboBox.SelectedValue;
+        Content.RegressionType = selected;
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void polynomialRegressionOrderNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.PolynomialRegressionOrder = (int)polynomialRegressionOrderNumericUpDown.Value;
+      }
+    }
+
+    private void isRegressionVisibleInLegendCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.IsRegressionVisibleInLegend = isRegressionVisibleInLegendCheckBox.Checked;
+      }
+    }
+
+    private void regressionLegendTextBox_Validated(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.RegressionDisplayName = regressionLegendTextBox.Text;
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotHistoryView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotHistoryView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotHistoryView.Designer.cs	(revision 15719)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class ScatterPlotHistoryView {
+    /// <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) {
+        if (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() {
+      components = new System.ComponentModel.Container();
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+    }
+
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotHistoryView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotHistoryView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotHistoryView.cs	(revision 15719)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("ScatterPlotHistory View")]
+  [Content(typeof(ScatterPlotHistory), true)]
+  public partial class ScatterPlotHistoryView : MovieView<ScatterPlot> {
+    public ScatterPlotHistoryView() {
+      InitializeComponent();
+      itemsGroupBox.Text = "Scatter Plots";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs	(revision 15719)
@@ -0,0 +1,133 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class ScatterPlotView {
+    /// <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) {
+        if (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.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.configureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Location = new System.Drawing.Point(55, 0);
+      this.nameTextBox.Size = new System.Drawing.Size(279, 20);
+      // 
+      // infoLabel
+      // 
+      this.infoLabel.Location = new System.Drawing.Point(340, 3);
+      // 
+      // chart
+      // 
+      this.chart.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)));
+      this.chart.BorderlineColor = System.Drawing.Color.Black;
+      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
+      chartArea1.AxisX.Minimum = 0D;
+      chartArea1.CursorX.IsUserEnabled = true;
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
+      chartArea1.Name = "Default";
+      this.chart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Default";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(0, 26);
+      this.chart.Name = "chart";
+      series1.ChartArea = "Default";
+      series1.Legend = "Default";
+      series1.Name = "Default";
+      this.chart.Series.Add(series1);
+      this.chart.Size = new System.Drawing.Size(359, 248);
+      this.chart.TabIndex = 3;
+      this.chart.Text = "chart";
+      title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      title1.Name = "Default";
+      title1.Text = "Title";
+      this.chart.Titles.Add(title1);
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDoubleClick);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // configureToolStripMenuItem
+      // 
+      this.configureToolStripMenuItem.Name = "configureToolStripMenuItem";
+      this.configureToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
+      this.configureToolStripMenuItem.Text = "Configure Chart...";
+      this.configureToolStripMenuItem.Click += new System.EventHandler(this.configureToolStripMenuItem_Click);
+      // 
+      // ScatterPlotView
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.chart);
+      this.Name = "ScatterPlotView";
+      this.Size = new System.Drawing.Size(359, 274);
+      this.Controls.SetChildIndex(this.chart, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+    #endregion
+
+    protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+    private System.Windows.Forms.ToolStripMenuItem configureToolStripMenuItem;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs	(revision 15719)
@@ -0,0 +1,829 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("ScatterPlot View")]
+  [Content(typeof(ScatterPlot), true)]
+  public partial class ScatterPlotView : NamedItemView, IConfigureableView {
+    protected List<Series> invisibleSeries;
+    protected Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow> pointsRowsTable;
+    protected Dictionary<Series, Series> seriesToRegressionSeriesTable;
+    private double xMin, xMax, yMin, yMax;
+
+    public new ScatterPlot Content {
+      get { return (ScatterPlot)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public bool ShowName {
+      get { return nameTextBox.Visible; }
+      set {
+        if (nameTextBox.Visible != value) {
+          foreach (Control c in Controls) {
+            if (c == chart) continue;
+            c.Visible = value;
+          }
+          chart.Dock = value ? DockStyle.None : DockStyle.Fill;
+        }
+      }
+    }
+
+    public ScatterPlotView() {
+      InitializeComponent();
+      pointsRowsTable = new Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow>();
+      seriesToRegressionSeriesTable = new Dictionary<Series, Series>();
+      invisibleSeries = new List<Series>();
+      chart.CustomizeAllChartAreas();
+      chart.ChartAreas[0].CursorX.Interval = 1;
+      chart.ContextMenuStrip.Items.Add(configureToolStripMenuItem);
+    }
+
+    #region Event Handler Registration
+    protected override void DeregisterContentEvents() {
+      foreach (ScatterPlotDataRow row in Content.Rows)
+        DeregisterScatterPlotDataRowEvents(row);
+      Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);
+      Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
+      Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);
+      Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
+      Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
+      Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
+      Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);
+      Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
+      Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
+    }
+
+    protected virtual void RegisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {
+      row.NameChanged += new EventHandler(Row_NameChanged);
+      row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
+      pointsRowsTable.Add(row.Points, row);
+      row.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
+      row.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
+      row.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
+      row.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
+    }
+    protected virtual void DeregisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {
+      row.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
+      row.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
+      row.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
+      row.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
+      pointsRowsTable.Remove(row.Points);
+      row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
+      row.NameChanged -= new EventHandler(Row_NameChanged);
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      invisibleSeries.Clear();
+      chart.Titles[0].Text = string.Empty;
+      chart.ChartAreas[0].AxisX.Title = string.Empty;
+      chart.ChartAreas[0].AxisY.Title = string.Empty;
+      chart.Series.Clear();
+      if (Content != null) {
+        chart.Titles[0].Text = Content.Name;
+        chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.Name);
+        AddScatterPlotDataRows(Content.Rows);
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateMinMaxPointValues();
+        RecalculateAxesScale(chart.ChartAreas[0]);
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      chart.Enabled = Content != null;
+    }
+
+    public void ShowConfiguration() {
+      if (Content != null) {
+        using (ScatterPlotVisualPropertiesDialog dialog = new ScatterPlotVisualPropertiesDialog(Content)) {
+          dialog.ShowDialog(this);
+        }
+      } else MessageBox.Show("Nothing to configure.");
+    }
+
+    protected virtual void AddScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {
+      foreach (var row in rows) {
+        RegisterScatterPlotDataRowEvents(row);
+        Series series = new Series(row.Name) { Tag = row };
+
+        if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+        else series.LegendText = row.Name;
+
+        var regressionSeries = new Series(row.Name + "_Regression") {
+          Tag = row,
+          ChartType = SeriesChartType.Line,
+          BorderDashStyle = ChartDashStyle.Dot,
+          IsVisibleInLegend = false,
+          Color = Color.Transparent // to avoid auto color assignment via color palette 
+        };
+
+        seriesToRegressionSeriesTable.Add(series, regressionSeries);
+        ConfigureSeries(series, regressionSeries, row);
+        FillSeriesWithRowValues(series, row);
+
+        chart.Series.Add(series);
+        chart.Series.Add(regressionSeries);
+        FillRegressionSeries(regressionSeries, row);
+      }
+      ConfigureChartArea(chart.ChartAreas[0]);
+      RecalculateMinMaxPointValues();
+      RecalculateAxesScale(chart.ChartAreas[0]);
+      UpdateYCursorInterval();
+      UpdateRegressionSeriesColors();
+    }
+
+    protected virtual void RemoveScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {
+      foreach (var row in rows) {
+        DeregisterScatterPlotDataRowEvents(row);
+        Series series = chart.Series[row.Name];
+        chart.Series.Remove(series);
+        if (invisibleSeries.Contains(series))
+          invisibleSeries.Remove(series);
+        chart.Series.Remove(seriesToRegressionSeriesTable[series]);
+        seriesToRegressionSeriesTable.Remove(series);
+      }
+      RecalculateMinMaxPointValues();
+      RecalculateAxesScale(chart.ChartAreas[0]);
+    }
+
+    private void ConfigureSeries(Series series, Series regressionSeries, ScatterPlotDataRow row) {
+      series.BorderWidth = 1;
+      series.BorderDashStyle = ChartDashStyle.Solid;
+      series.BorderColor = Color.Empty;
+
+      if (row.VisualProperties.Color != Color.Empty)
+        series.Color = row.VisualProperties.Color;
+      else series.Color = Color.Empty;
+      series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;
+      series.ChartType = SeriesChartType.FastPoint;
+      series.MarkerSize = row.VisualProperties.PointSize;
+      series.MarkerStyle = ConvertPointStyle(row.VisualProperties.PointStyle);
+      series.XAxisType = AxisType.Primary;
+      series.YAxisType = AxisType.Primary;
+
+      if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+      else series.LegendText = row.Name;
+
+      string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
+                      ? "X"
+                      : Content.VisualProperties.XAxisTitle;
+      string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
+                            ? "Y"
+                            : Content.VisualProperties.YAxisTitle;
+      series.ToolTip =
+        series.LegendText + Environment.NewLine +
+        xAxisTitle + " = " + "#VALX," + Environment.NewLine +
+        yAxisTitle + " = " + "#VAL";
+
+      regressionSeries.BorderWidth = Math.Max(1, row.VisualProperties.PointSize / 2);
+      regressionSeries.IsVisibleInLegend = row.VisualProperties.IsRegressionVisibleInLegend &&
+        row.VisualProperties.RegressionType != ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None;
+      regressionSeries.LegendText = string.IsNullOrEmpty(row.VisualProperties.RegressionDisplayName)
+        ? string.Format("{0}({1})", row.VisualProperties.RegressionType, row.Name)
+        : row.VisualProperties.RegressionDisplayName;
+    }
+
+    private void ConfigureChartArea(ChartArea area) {
+      if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
+      if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
+      chart.Titles[0].Text = Content.VisualProperties.Title;
+      chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.VisualProperties.Title);
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX.Title = Content.VisualProperties.XAxisTitle;
+      area.AxisX.MajorGrid.Enabled = Content.VisualProperties.XAxisGrid;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY.Title = Content.VisualProperties.YAxisTitle;
+      area.AxisY.MajorGrid.Enabled = Content.VisualProperties.YAxisGrid;
+    }
+
+    private void RecalculateAxesScale(ChartArea area) {
+      area.AxisX.Minimum = CalculateMinBound(xMin);
+      area.AxisX.Maximum = CalculateMaxBound(xMax);
+      if (area.AxisX.Minimum == area.AxisX.Maximum) {
+        area.AxisX.Minimum = xMin - 0.5;
+        area.AxisX.Maximum = xMax + 0.5;
+      }
+      area.AxisY.Minimum = CalculateMinBound(yMin);
+      area.AxisY.Maximum = CalculateMaxBound(yMax);
+      if (area.AxisY.Minimum == area.AxisY.Maximum) {
+        area.AxisY.Minimum = yMin - 0.5;
+        area.AxisY.Maximum = yMax + 0.5;
+      }
+      if (xMax - xMin > 0) area.CursorX.Interval = Math.Pow(10, Math.Floor(Math.Log10(area.AxisX.Maximum - area.AxisX.Minimum) - 3));
+      else area.CursorX.Interval = 1;
+      area.AxisX.IsMarginVisible = false;
+
+      if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
+      if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
+      if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
+      if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
+    }
+
+    private static double CalculateMinBound(double min) {
+      if (min == 0) return 0;
+      var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(min))));
+      return scale * (Math.Floor(min / scale));
+    }
+
+    private static double CalculateMaxBound(double max) {
+      if (max == 0) return 0;
+      var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(max))));
+      return scale * (Math.Ceiling(max / scale));
+    }
+
+    protected virtual void UpdateYCursorInterval() {
+      double interestingValuesRange = (
+        from series in chart.Series
+        where series.Enabled
+        let values = (from point in series.Points
+                      where !point.IsEmpty
+                      select point.YValues[0]).DefaultIfEmpty(1.0)
+        let range = values.Max() - values.Min()
+        where range > 0.0
+        select range
+        ).DefaultIfEmpty(1.0).Min();
+
+      double digits = (int)Math.Log10(interestingValuesRange) - 3;
+      double yZoomInterval = Math.Pow(10, digits);
+      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
+    }
+
+    protected void UpdateRegressionSeriesColors() {
+      chart.ApplyPaletteColors();
+      foreach (var row in Content.Rows) {
+        var series = chart.Series[row.Name];
+        var regressionSeries = seriesToRegressionSeriesTable[series];
+        regressionSeries.Color = series.Color;
+      }
+    }
+
+    #region Event Handlers
+    #region Content Event Handlers
+    protected override void Content_NameChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_NameChanged), sender, e);
+      else {
+        Content.VisualProperties.Title = Content.Name;
+        base.Content_NameChanged(sender, e);
+      }
+    }
+    private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
+      else {
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
+      }
+    }
+    #endregion
+    #region Rows Event Handlers
+    private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded), sender, e);
+      else {
+        AddScatterPlotDataRows(e.Items);
+      }
+    }
+    private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved), sender, e);
+      else {
+        RemoveScatterPlotDataRows(e.Items);
+      }
+    }
+    private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced), sender, e);
+      else {
+        RemoveScatterPlotDataRows(e.OldItems);
+        AddScatterPlotDataRows(e.Items);
+      }
+    }
+    private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset), sender, e);
+      else {
+        RemoveScatterPlotDataRows(e.OldItems);
+        AddScatterPlotDataRows(e.Items);
+      }
+    }
+    #endregion
+    #region Row Event Handlers
+    private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);
+      else {
+        ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
+        Series series = chart.Series[row.Name];
+        Series regressionSeries = seriesToRegressionSeriesTable[series];
+        series.Points.Clear();
+        regressionSeries.Points.Clear();
+        ConfigureSeries(series, regressionSeries, row);
+        FillSeriesWithRowValues(series, row);
+        FillRegressionSeries(regressionSeries, row);
+        RecalculateMinMaxPointValues();
+        RecalculateAxesScale(chart.ChartAreas[0]);
+        UpdateRegressionSeriesColors();
+      }
+    }
+    private void Row_NameChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Row_NameChanged), sender, e);
+      else {
+        ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
+        chart.Series[row.Name].Name = row.Name;
+      }
+    }
+    #endregion
+    #region Points Event Handlers
+    private void Points_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded), sender, e);
+      else {
+        ScatterPlotDataRow row = null;
+        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
+            FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
+            RecalculateMinMaxPointValues();
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    private void Points_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved), sender, e);
+      else {
+        ScatterPlotDataRow row = null;
+        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
+            FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
+            RecalculateMinMaxPointValues();
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    private void Points_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced), sender, e);
+      else {
+        ScatterPlotDataRow row = null;
+        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
+            FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
+            RecalculateMinMaxPointValues();
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    private void Points_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset), sender, e);
+      else {
+        ScatterPlotDataRow row = null;
+        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
+        if (row != null) {
+          Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
+          if (!invisibleSeries.Contains(rowSeries)) {
+            rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
+            FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
+            RecalculateMinMaxPointValues();
+            RecalculateAxesScale(chart.ChartAreas[0]);
+            UpdateYCursorInterval();
+          }
+        }
+      }
+    }
+    #endregion
+    private void configureToolStripMenuItem_Click(object sender, System.EventArgs e) {
+      ShowConfiguration();
+    }
+    #endregion
+
+    #region Chart Event Handlers
+    private void chart_MouseDoubleClick(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y, ChartElementType.DataPoint);
+      if (result.ChartElementType != ChartElementType.DataPoint) return;
+
+      var series = result.Series;
+      var dataPoint = series.Points[result.PointIndex];
+      var tag = dataPoint.Tag;
+      var content = tag as IContent;
+
+      if (tag == null) return;
+      if (content == null) return;
+
+      MainFormManager.MainForm.ShowContent(content);
+    }
+
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        ToggleSeriesVisible(result.Series);
+      }
+    }
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+    }
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = invisibleSeries.Contains(series);
+          foreach (LegendCell cell in legendItem.Cells) {
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+          }
+        }
+      }
+    }
+    #endregion
+
+    private void ToggleSeriesVisible(Series series) {
+      if (!invisibleSeries.Contains(series)) {
+        series.Points.Clear();
+        invisibleSeries.Add(series);
+        RecalculateMinMaxPointValues();
+      } else {
+        invisibleSeries.Remove(series);
+        if (Content != null) {
+          var row = (ScatterPlotDataRow)series.Tag;
+          if (seriesToRegressionSeriesTable.ContainsKey(series))
+            FillSeriesWithRowValues(series, row);
+          else
+            FillRegressionSeries(series, row);
+          RecalculateMinMaxPointValues();
+          this.chart.Legends[series.Legend].ForeColor = Color.Black;
+          RecalculateAxesScale(chart.ChartAreas[0]);
+          UpdateYCursorInterval();
+        }
+      }
+    }
+
+    private void RecalculateMinMaxPointValues() {
+      yMin = xMin = double.MaxValue;
+      yMax = xMax = double.MinValue;
+      foreach (var s in chart.Series.Where(x => x.Enabled)) {
+        foreach (var p in s.Points) {
+          double x = p.XValue, y = p.YValues[0];
+          if (xMin > x) xMin = x;
+          if (xMax < x) xMax = x;
+          if (yMin > y) yMin = y;
+          if (yMax < y) yMax = y;
+        }
+      }
+    }
+
+    private void FillSeriesWithRowValues(Series series, ScatterPlotDataRow row) {
+      bool zerosOnly = true;
+      for (int i = 0; i < row.Points.Count; i++) {
+        var value = row.Points[i];
+        DataPoint point = new DataPoint();
+        if (IsInvalidValue(value.X) || IsInvalidValue(value.Y))
+          point.IsEmpty = true;
+        else {
+          point.XValue = value.X;
+          point.YValues = new double[] { value.Y };
+        }
+        point.Tag = value.Tag;
+        series.Points.Add(point);
+        if (value.X != 0.0f)
+          zerosOnly = false;
+      }
+      if (zerosOnly) // if all x-values are zero, the x-values are interpreted as 1, 2, 3, ...
+        series.Points.Add(new DataPoint(1, 1) { IsEmpty = true });
+      double correlation = Correlation(row.Points);
+      series.LegendToolTip = string.Format("Correlation (R²) = {0:G4}", correlation * correlation);
+    }
+
+    private void FillRegressionSeries(Series regressionSeries, ScatterPlotDataRow row) {
+      if (row.VisualProperties.RegressionType == ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None
+        || invisibleSeries.Contains(regressionSeries))
+        return;
+
+      double[] coefficients;
+      if (!Fitting(row, out coefficients)) {
+        regressionSeries.LegendToolTip = "Could not calculate regression.";
+        return;
+      }
+
+      // Fill regrssion series
+      double min = row.Points.Min(p => p.X), max = row.Points.Max(p => p.X);
+      double range = max - min, delta = range / Math.Max(row.Points.Count - 1, 50);
+      if (range > double.Epsilon) {
+        for (double x = min; x <= max; x += delta) {
+          regressionSeries.Points.AddXY(x, Estimate(x, row, coefficients));
+        }
+      }
+
+      // Correlation
+      var data = row.Points.Select(p => new Point2D<double>(p.Y, Estimate(p.X, row, coefficients)));
+      double correlation = Correlation(data.ToList());
+      regressionSeries.LegendToolTip = GetStringFormula(row, coefficients) + Environment.NewLine +
+                                       string.Format("Correlation (R²) = {0:G4}", correlation * correlation);
+      regressionSeries.ToolTip = GetStringFormula(row, coefficients);
+    }
+
+    #region Helpers
+    private MarkerStyle ConvertPointStyle(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle pointStyle) {
+      switch (pointStyle) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Circle:
+          return MarkerStyle.Circle;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Cross:
+          return MarkerStyle.Cross;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Diamond:
+          return MarkerStyle.Diamond;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Square:
+          return MarkerStyle.Square;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star4:
+          return MarkerStyle.Star4;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star5:
+          return MarkerStyle.Star5;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star6:
+          return MarkerStyle.Star6;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star10:
+          return MarkerStyle.Star10;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Triangle:
+          return MarkerStyle.Triangle;
+        default:
+          return MarkerStyle.None;
+      }
+    }
+
+    protected static bool IsInvalidValue(double x) {
+      return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
+    }
+    #endregion
+
+    #region Correlation and Fitting Helper
+    protected static double Correlation(IList<Point2D<double>> values) {
+      // sums of x, y, x squared etc.
+      double sx = 0.0;
+      double sy = 0.0;
+      double sxx = 0.0;
+      double syy = 0.0;
+      double sxy = 0.0;
+
+      int n = 0;
+      for (int i = 0; i < values.Count; i++) {
+        double x = values[i].X;
+        double y = values[i].Y;
+        if (IsInvalidValue(x) || IsInvalidValue(y))
+          continue;
+
+        sx += x;
+        sy += y;
+        sxx += x * x;
+        syy += y * y;
+        sxy += x * y;
+        n++;
+      }
+
+      // covariation
+      double cov = sxy / n - sx * sy / n / n;
+      // standard error of x
+      double sigmaX = Math.Sqrt(sxx / n - sx * sx / n / n);
+      // standard error of y
+      double sigmaY = Math.Sqrt(syy / n - sy * sy / n / n);
+
+      // correlation
+      return cov / sigmaX / sigmaY;
+    }
+
+    protected static bool Fitting(ScatterPlotDataRow row, out double[] coefficients) {
+      if (!IsValidRegressionData(row)) {
+        coefficients = new double[0];
+        return false;
+      }
+
+      var xs = row.Points.Select(p => p.X).ToList();
+      var ys = row.Points.Select(p => p.Y).ToList();
+
+      // Input transformations
+      double[,] matrix;
+      int nRows;
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Linear:
+          matrix = CreateMatrix(out nRows, ys, xs);
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial:
+          var xss = Enumerable.Range(1, row.VisualProperties.PolynomialRegressionOrder)
+            .Select(o => xs.Select(x => Math.Pow(x, o)).ToList())
+            .Reverse(); // higher order first
+          matrix = CreateMatrix(out nRows, ys, xss.ToArray());
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          matrix = CreateMatrix(out nRows, ys.Select(y => Math.Log(y)).ToList(), xs);
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          matrix = CreateMatrix(out nRows, ys.Select(y => Math.Log(y)).ToList(), xs.Select(x => Math.Log(x)).ToList());
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          matrix = CreateMatrix(out nRows, ys, xs.Select(x => Math.Log(x)).ToList());
+          break;
+        default:
+          throw new ArgumentException("Unknown RegressionType: " + row.VisualProperties.RegressionType);
+      }
+
+      // Linear fitting
+      bool success = LinearFitting(matrix, nRows, out coefficients);
+      if (!success) return false;
+
+      // Output transformation
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          coefficients[1] = Math.Exp(coefficients[1]);
+          break;
+      }
+
+      return true;
+    }
+    protected static bool IsValidRegressionData(ScatterPlotDataRow row) {
+      // No invalid values allowed
+      for (int i = 0; i < row.Points.Count; i++) {
+        if (IsInvalidValue(row.Points[i].X) || IsInvalidValue(row.Points[i].Y))
+          return false;
+      }
+      // Exp, Power and Log Regression do not work with negative values
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          for (int i = 0; i < row.Points.Count; i++) {
+            if (row.Points[i].Y <= 0)
+              return false;
+          }
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          for (int i = 0; i < row.Points.Count; i++) {
+            if (row.Points[i].X <= 0 || row.Points[i].Y <= 0)
+              return false;
+          }
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          for (int i = 0; i < row.Points.Count; i++) {
+            if (row.Points[i].X <= 0)
+              return false;
+          }
+          break;
+      }
+      return true;
+    }
+    protected static double[,] CreateMatrix(out int nRows, IList<double> ys, params IList<double>[] xss) {
+      var matrix = new double[ys.Count, xss.Length + 1];
+      int rowIdx = 0;
+      for (int i = 0; i < ys.Count; i++) {
+        if (IsInvalidValue(ys[i]) || xss.Any(xs => IsInvalidValue(xs[i])))
+          continue;
+        for (int j = 0; j < xss.Length; j++) {
+          matrix[rowIdx, j] = xss[j][i];
+        }
+        matrix[rowIdx, xss.Length] = ys[i];
+        rowIdx++;
+      }
+      nRows = rowIdx;
+      return matrix;
+    }
+
+    protected static bool LinearFitting(double[,] xsy, int nRows, out double[] coefficients) {
+      int nFeatures = xsy.GetLength(1) - 1;
+
+      alglib.linearmodel lm;
+      alglib.lrreport ar;
+      int retVal;
+      alglib.lrbuild(xsy, nRows, nFeatures, out retVal, out lm, out ar);
+      if (retVal != 1) {
+        coefficients = new double[0];
+        return false;
+      }
+
+      alglib.lrunpack(lm, out coefficients, out nFeatures);
+      return true;
+    }
+
+    protected static double Estimate(double x, ScatterPlotDataRow row, double[] coefficients) {
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Linear:
+          return coefficients[0] * x + coefficients[1];
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial:
+          return coefficients
+            .Reverse() // to match index and order
+            .Select((c, o) => c * Math.Pow(x, o))
+            .Sum();
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          return coefficients[1] * Math.Exp(coefficients[0] * x);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          return coefficients[1] * Math.Pow(x, coefficients[0]);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          return coefficients[0] * Math.Log(x) + coefficients[1];
+        default:
+          throw new ArgumentException("Unknown RegressionType: " + row.VisualProperties.RegressionType);
+      }
+    }
+
+    protected static string GetStringFormula(ScatterPlotDataRow row, double[] coefficients) {
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Linear:
+          return string.Format("{0:G4} x {1} {2:G4}", coefficients[0], Sign(coefficients[1]), Math.Abs(coefficients[1]));
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial:
+          var sb = new StringBuilder();
+          sb.AppendFormat("{0:G4}{1}", coefficients[0], PolyFactor(coefficients.Length - 1));
+          foreach (var x in coefficients
+            .Reverse() // match index and order
+            .Select((c, o) => new { c, o })
+            .Reverse() // higher order first
+            .Skip(1)) // highest order poly already added
+            sb.AppendFormat(" {0} {1:G4}{2}", Sign(x.c), Math.Abs(x.c), PolyFactor(x.o));
+          return sb.ToString();
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          return string.Format("{0:G4} e^({1:G4} x)", coefficients[1], coefficients[0]);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          return string.Format("{0:G4} x^({1:G4})", coefficients[1], coefficients[0]);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          return string.Format("{0:G4} ln(x) {1} {2:G4}", coefficients[0], Sign(coefficients[1]), Math.Abs(coefficients[1]));
+        default:
+          throw new ArgumentException("Unknown RegressionType: " + row.VisualProperties.RegressionType);
+      }
+    }
+    private static string Sign(double value) {
+      return value >= 0 ? "+" : "-";
+    }
+    private static string PolyFactor(int order) {
+      if (order == 0) return "";
+      if (order == 1) return " x";
+      if (order == 2) return " x²";
+      if (order == 3) return " x³";
+      return " x^" + order;
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesControl.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesControl.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesControl.Designer.cs	(revision 15719)
@@ -0,0 +1,609 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class ScatterPlotVisualPropertiesControl {
+    /// <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();
+      this.label1 = new System.Windows.Forms.Label();
+      this.yAxisTitleTextBox = new System.Windows.Forms.TextBox();
+      this.panel2 = new System.Windows.Forms.Panel();
+      this.xAxisMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel1 = new System.Windows.Forms.Panel();
+      this.xAxisMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.label12 = new System.Windows.Forms.Label();
+      this.label9 = new System.Windows.Forms.Label();
+      this.xAxisTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label11 = new System.Windows.Forms.Label();
+      this.axisTabControl = new System.Windows.Forms.TabControl();
+      this.xAxisTabPage = new System.Windows.Forms.TabPage();
+      this.xAxisGridCheckBox = new System.Windows.Forms.CheckBox();
+      this.label4 = new System.Windows.Forms.Label();
+      this.yAxisTabPage = new System.Windows.Forms.TabPage();
+      this.yAxisGridCheckBox = new System.Windows.Forms.CheckBox();
+      this.label5 = new System.Windows.Forms.Label();
+      this.panel6 = new System.Windows.Forms.Panel();
+      this.yAxisMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel5 = new System.Windows.Forms.Panel();
+      this.yAxisMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.label8 = new System.Windows.Forms.Label();
+      this.label7 = new System.Windows.Forms.Label();
+      this.titleTextBox = new System.Windows.Forms.TextBox();
+      this.label15 = new System.Windows.Forms.Label();
+      this.axisFontLabel = new System.Windows.Forms.Label();
+      this.titleFontLabel = new System.Windows.Forms.Label();
+      this.axisFontButton = new System.Windows.Forms.Button();
+      this.label3 = new System.Windows.Forms.Label();
+      this.titleFontButton = new System.Windows.Forms.Button();
+      this.label2 = new System.Windows.Forms.Label();
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+      this.titleFontDialog = new System.Windows.Forms.FontDialog();
+      this.axisFontDialog = new System.Windows.Forms.FontDialog();
+      this.panel2.SuspendLayout();
+      this.panel1.SuspendLayout();
+      this.axisTabControl.SuspendLayout();
+      this.xAxisTabPage.SuspendLayout();
+      this.yAxisTabPage.SuspendLayout();
+      this.panel6.SuspendLayout();
+      this.panel5.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(6, 12);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(30, 13);
+      this.label1.TabIndex = 0;
+      this.label1.Text = "&Title:";
+      // 
+      // yAxisPrimaryTitleTextBox
+      // 
+      this.yAxisTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisTitleTextBox.Location = new System.Drawing.Point(71, 9);
+      this.yAxisTitleTextBox.Name = "yAxisPrimaryTitleTextBox";
+      this.yAxisTitleTextBox.Size = new System.Drawing.Size(370, 20);
+      this.yAxisTitleTextBox.TabIndex = 1;
+      this.yAxisTitleTextBox.Validated += new System.EventHandler(this.yTitleTextBox_Validated);
+      // 
+      // panel2
+      // 
+      this.panel2.Controls.Add(this.xAxisMaximumFixedRadioButton);
+      this.panel2.Controls.Add(this.xAxisMaximumAutoRadioButton);
+      this.panel2.Location = new System.Drawing.Point(71, 61);
+      this.panel2.Name = "panel2";
+      this.panel2.Size = new System.Drawing.Size(106, 16);
+      this.panel2.TabIndex = 6;
+      // 
+      // xAxisPrimaryMaximumFixedRadioButton
+      // 
+      this.xAxisMaximumFixedRadioButton.AutoSize = true;
+      this.xAxisMaximumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.xAxisMaximumFixedRadioButton.Name = "xAxisPrimaryMaximumFixedRadioButton";
+      this.xAxisMaximumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.xAxisMaximumFixedRadioButton.TabIndex = 1;
+      this.xAxisMaximumFixedRadioButton.TabStop = true;
+      this.xAxisMaximumFixedRadioButton.Text = "&Fixed:";
+      this.xAxisMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMaximumAutoRadioButton
+      // 
+      this.xAxisMaximumAutoRadioButton.AutoSize = true;
+      this.xAxisMaximumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.xAxisMaximumAutoRadioButton.Name = "xAxisPrimaryMaximumAutoRadioButton";
+      this.xAxisMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisMaximumAutoRadioButton.TabIndex = 0;
+      this.xAxisMaximumAutoRadioButton.TabStop = true;
+      this.xAxisMaximumAutoRadioButton.Text = "&Auto";
+      this.xAxisMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisMaximumRadioButton_CheckedChanged);
+      // 
+      // panel1
+      // 
+      this.panel1.Controls.Add(this.xAxisMinimumFixedRadioButton);
+      this.panel1.Controls.Add(this.xAxisMinimumAutoRadioButton);
+      this.panel1.Location = new System.Drawing.Point(71, 35);
+      this.panel1.Name = "panel1";
+      this.panel1.Size = new System.Drawing.Size(106, 16);
+      this.panel1.TabIndex = 3;
+      // 
+      // xAxisPrimaryMinimumFixedRadioButton
+      // 
+      this.xAxisMinimumFixedRadioButton.AutoSize = true;
+      this.xAxisMinimumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.xAxisMinimumFixedRadioButton.Name = "xAxisPrimaryMinimumFixedRadioButton";
+      this.xAxisMinimumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.xAxisMinimumFixedRadioButton.TabIndex = 1;
+      this.xAxisMinimumFixedRadioButton.TabStop = true;
+      this.xAxisMinimumFixedRadioButton.Text = "&Fixed:";
+      this.xAxisMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMinimumAutoRadioButton
+      // 
+      this.xAxisMinimumAutoRadioButton.AutoSize = true;
+      this.xAxisMinimumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.xAxisMinimumAutoRadioButton.Name = "xAxisPrimaryMinimumAutoRadioButton";
+      this.xAxisMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisMinimumAutoRadioButton.TabIndex = 0;
+      this.xAxisMinimumAutoRadioButton.TabStop = true;
+      this.xAxisMinimumAutoRadioButton.Text = "&Auto";
+      this.xAxisMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMinimumFixedTextBox
+      // 
+      this.xAxisMinimumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisMinimumFixedTextBox.Location = new System.Drawing.Point(196, 35);
+      this.xAxisMinimumFixedTextBox.Name = "xAxisPrimaryMinimumFixedTextBox";
+      this.xAxisMinimumFixedTextBox.Size = new System.Drawing.Size(245, 20);
+      this.xAxisMinimumFixedTextBox.TabIndex = 4;
+      this.xAxisMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisMinimumFixedTextBox_Validating);
+      // 
+      // xAxisPrimaryMaximumFixedTextBox
+      // 
+      this.xAxisMaximumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisMaximumFixedTextBox.Location = new System.Drawing.Point(196, 61);
+      this.xAxisMaximumFixedTextBox.Name = "xAxisPrimaryMaximumFixedTextBox";
+      this.xAxisMaximumFixedTextBox.Size = new System.Drawing.Size(245, 20);
+      this.xAxisMaximumFixedTextBox.TabIndex = 7;
+      this.xAxisMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisMaximumFixedTextBox_Validating);
+      // 
+      // label12
+      // 
+      this.label12.AutoSize = true;
+      this.label12.Location = new System.Drawing.Point(6, 64);
+      this.label12.Name = "label12";
+      this.label12.Size = new System.Drawing.Size(54, 13);
+      this.label12.TabIndex = 5;
+      this.label12.Text = "&Maximum:";
+      // 
+      // label9
+      // 
+      this.label9.AutoSize = true;
+      this.label9.Location = new System.Drawing.Point(6, 12);
+      this.label9.Name = "label9";
+      this.label9.Size = new System.Drawing.Size(30, 13);
+      this.label9.TabIndex = 0;
+      this.label9.Text = "&Title:";
+      // 
+      // xAxisPrimaryTitleTextBox
+      // 
+      this.xAxisTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisTitleTextBox.Location = new System.Drawing.Point(71, 9);
+      this.xAxisTitleTextBox.Name = "xAxisPrimaryTitleTextBox";
+      this.xAxisTitleTextBox.Size = new System.Drawing.Size(370, 20);
+      this.xAxisTitleTextBox.TabIndex = 1;
+      this.xAxisTitleTextBox.Validated += new System.EventHandler(this.xTitleTextBox_Validated);
+      // 
+      // label11
+      // 
+      this.label11.AutoSize = true;
+      this.label11.Location = new System.Drawing.Point(6, 38);
+      this.label11.Name = "label11";
+      this.label11.Size = new System.Drawing.Size(51, 13);
+      this.label11.TabIndex = 2;
+      this.label11.Text = "&Minimum:";
+      // 
+      // axisTabControl
+      // 
+      this.axisTabControl.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)));
+      this.axisTabControl.Controls.Add(this.xAxisTabPage);
+      this.axisTabControl.Controls.Add(this.yAxisTabPage);
+      this.axisTabControl.Location = new System.Drawing.Point(0, 84);
+      this.axisTabControl.Name = "axisTabControl";
+      this.axisTabControl.SelectedIndex = 0;
+      this.axisTabControl.Size = new System.Drawing.Size(455, 134);
+      this.axisTabControl.TabIndex = 8;
+      // 
+      // xAxisTabPage
+      // 
+      this.xAxisTabPage.Controls.Add(this.xAxisGridCheckBox);
+      this.xAxisTabPage.Controls.Add(this.label4);
+      this.xAxisTabPage.Controls.Add(this.panel2);
+      this.xAxisTabPage.Controls.Add(this.panel1);
+      this.xAxisTabPage.Controls.Add(this.xAxisTitleTextBox);
+      this.xAxisTabPage.Controls.Add(this.xAxisMinimumFixedTextBox);
+      this.xAxisTabPage.Controls.Add(this.label11);
+      this.xAxisTabPage.Controls.Add(this.xAxisMaximumFixedTextBox);
+      this.xAxisTabPage.Controls.Add(this.label9);
+      this.xAxisTabPage.Controls.Add(this.label12);
+      this.xAxisTabPage.Location = new System.Drawing.Point(4, 22);
+      this.xAxisTabPage.Name = "xAxisTabPage";
+      this.xAxisTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.xAxisTabPage.Size = new System.Drawing.Size(447, 108);
+      this.xAxisTabPage.TabIndex = 0;
+      this.xAxisTabPage.Text = "X-Axis";
+      this.xAxisTabPage.UseVisualStyleBackColor = true;
+      // 
+      // xAxisGridCheckBox
+      // 
+      this.xAxisGridCheckBox.AutoSize = true;
+      this.xAxisGridCheckBox.Location = new System.Drawing.Point(71, 85);
+      this.xAxisGridCheckBox.Name = "xAxisGridCheckBox";
+      this.xAxisGridCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.xAxisGridCheckBox.TabIndex = 9;
+      this.xAxisGridCheckBox.UseVisualStyleBackColor = true;
+      this.xAxisGridCheckBox.CheckedChanged += new System.EventHandler(this.xAxisGridCheckBox_CheckedChanged);
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(6, 85);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(59, 13);
+      this.label4.TabIndex = 8;
+      this.label4.Text = "Show &Grid:";
+      // 
+      // yAxisTabPage
+      // 
+      this.yAxisTabPage.Controls.Add(this.yAxisGridCheckBox);
+      this.yAxisTabPage.Controls.Add(this.label5);
+      this.yAxisTabPage.Controls.Add(this.panel6);
+      this.yAxisTabPage.Controls.Add(this.panel5);
+      this.yAxisTabPage.Controls.Add(this.yAxisTitleTextBox);
+      this.yAxisTabPage.Controls.Add(this.yAxisMinimumFixedTextBox);
+      this.yAxisTabPage.Controls.Add(this.label1);
+      this.yAxisTabPage.Controls.Add(this.yAxisMaximumFixedTextBox);
+      this.yAxisTabPage.Controls.Add(this.label8);
+      this.yAxisTabPage.Controls.Add(this.label7);
+      this.yAxisTabPage.Location = new System.Drawing.Point(4, 22);
+      this.yAxisTabPage.Name = "yAxisTabPage";
+      this.yAxisTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.yAxisTabPage.Size = new System.Drawing.Size(447, 108);
+      this.yAxisTabPage.TabIndex = 1;
+      this.yAxisTabPage.Text = "Y-Axis";
+      this.yAxisTabPage.UseVisualStyleBackColor = true;
+      // 
+      // yAxisGridCheckBox
+      // 
+      this.yAxisGridCheckBox.AutoSize = true;
+      this.yAxisGridCheckBox.Location = new System.Drawing.Point(71, 85);
+      this.yAxisGridCheckBox.Name = "yAxisGridCheckBox";
+      this.yAxisGridCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.yAxisGridCheckBox.TabIndex = 10;
+      this.yAxisGridCheckBox.UseVisualStyleBackColor = true;
+      this.yAxisGridCheckBox.CheckedChanged += new System.EventHandler(this.yAxisGridCheckBox_CheckedChanged);
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(6, 85);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(59, 13);
+      this.label5.TabIndex = 9;
+      this.label5.Text = "Show &Grid:";
+      // 
+      // panel6
+      // 
+      this.panel6.Controls.Add(this.yAxisMaximumFixedRadioButton);
+      this.panel6.Controls.Add(this.yAxisMaximumAutoRadioButton);
+      this.panel6.Location = new System.Drawing.Point(71, 61);
+      this.panel6.Name = "panel6";
+      this.panel6.Size = new System.Drawing.Size(106, 20);
+      this.panel6.TabIndex = 6;
+      // 
+      // yAxisPrimaryMaximumFixedRadioButton
+      // 
+      this.yAxisMaximumFixedRadioButton.AutoSize = true;
+      this.yAxisMaximumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.yAxisMaximumFixedRadioButton.Name = "yAxisPrimaryMaximumFixedRadioButton";
+      this.yAxisMaximumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.yAxisMaximumFixedRadioButton.TabIndex = 1;
+      this.yAxisMaximumFixedRadioButton.TabStop = true;
+      this.yAxisMaximumFixedRadioButton.Text = "&Fixed:";
+      this.yAxisMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMaximumAutoRadioButton
+      // 
+      this.yAxisMaximumAutoRadioButton.AutoSize = true;
+      this.yAxisMaximumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.yAxisMaximumAutoRadioButton.Name = "yAxisPrimaryMaximumAutoRadioButton";
+      this.yAxisMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisMaximumAutoRadioButton.TabIndex = 0;
+      this.yAxisMaximumAutoRadioButton.TabStop = true;
+      this.yAxisMaximumAutoRadioButton.Text = "&Auto";
+      this.yAxisMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisMaximumRadioButton_CheckedChanged);
+      // 
+      // panel5
+      // 
+      this.panel5.Controls.Add(this.yAxisMinimumAutoRadioButton);
+      this.panel5.Controls.Add(this.yAxisMinimumFixedRadioButton);
+      this.panel5.Location = new System.Drawing.Point(71, 35);
+      this.panel5.Name = "panel5";
+      this.panel5.Size = new System.Drawing.Size(106, 20);
+      this.panel5.TabIndex = 3;
+      // 
+      // yAxisPrimaryMinimumAutoRadioButton
+      // 
+      this.yAxisMinimumAutoRadioButton.AutoSize = true;
+      this.yAxisMinimumAutoRadioButton.Location = new System.Drawing.Point(0, 1);
+      this.yAxisMinimumAutoRadioButton.Name = "yAxisPrimaryMinimumAutoRadioButton";
+      this.yAxisMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisMinimumAutoRadioButton.TabIndex = 0;
+      this.yAxisMinimumAutoRadioButton.TabStop = true;
+      this.yAxisMinimumAutoRadioButton.Text = "&Auto";
+      this.yAxisMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMinimumFixedRadioButton
+      // 
+      this.yAxisMinimumFixedRadioButton.AutoSize = true;
+      this.yAxisMinimumFixedRadioButton.Location = new System.Drawing.Point(53, 1);
+      this.yAxisMinimumFixedRadioButton.Name = "yAxisPrimaryMinimumFixedRadioButton";
+      this.yAxisMinimumFixedRadioButton.Size = new System.Drawing.Size(53, 17);
+      this.yAxisMinimumFixedRadioButton.TabIndex = 1;
+      this.yAxisMinimumFixedRadioButton.TabStop = true;
+      this.yAxisMinimumFixedRadioButton.Text = "&Fixed:";
+      this.yAxisMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMinimumFixedTextBox
+      // 
+      this.yAxisMinimumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisMinimumFixedTextBox.Location = new System.Drawing.Point(196, 35);
+      this.yAxisMinimumFixedTextBox.Name = "yAxisPrimaryMinimumFixedTextBox";
+      this.yAxisMinimumFixedTextBox.Size = new System.Drawing.Size(245, 20);
+      this.yAxisMinimumFixedTextBox.TabIndex = 4;
+      this.yAxisMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisMinimumFixedTextBox_Validating);
+      // 
+      // yAxisPrimaryMaximumFixedTextBox
+      // 
+      this.yAxisMaximumFixedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisMaximumFixedTextBox.Location = new System.Drawing.Point(196, 61);
+      this.yAxisMaximumFixedTextBox.Name = "yAxisPrimaryMaximumFixedTextBox";
+      this.yAxisMaximumFixedTextBox.Size = new System.Drawing.Size(245, 20);
+      this.yAxisMaximumFixedTextBox.TabIndex = 7;
+      this.yAxisMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisMaximumFixedTextBox_Validating);
+      // 
+      // label8
+      // 
+      this.label8.AutoSize = true;
+      this.label8.Location = new System.Drawing.Point(6, 38);
+      this.label8.Name = "label8";
+      this.label8.Size = new System.Drawing.Size(51, 13);
+      this.label8.TabIndex = 2;
+      this.label8.Text = "&Minimum:";
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(6, 64);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(54, 13);
+      this.label7.TabIndex = 5;
+      this.label7.Text = "&Maximum:";
+      // 
+      // titleTextBox
+      // 
+      this.titleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.titleTextBox.Location = new System.Drawing.Point(66, 0);
+      this.titleTextBox.Name = "titleTextBox";
+      this.titleTextBox.Size = new System.Drawing.Size(389, 20);
+      this.titleTextBox.TabIndex = 1;
+      this.titleTextBox.Validated += new System.EventHandler(this.titleTextBox_Validated);
+      // 
+      // label15
+      // 
+      this.label15.AutoSize = true;
+      this.label15.Location = new System.Drawing.Point(3, 3);
+      this.label15.Name = "label15";
+      this.label15.Size = new System.Drawing.Size(30, 13);
+      this.label15.TabIndex = 0;
+      this.label15.Text = "&Title:";
+      // 
+      // axisFontLabel
+      // 
+      this.axisFontLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.axisFontLabel.AutoSize = true;
+      this.axisFontLabel.Location = new System.Drawing.Point(98, 60);
+      this.axisFontLabel.Name = "axisFontLabel";
+      this.axisFontLabel.Size = new System.Drawing.Size(43, 13);
+      this.axisFontLabel.TabIndex = 7;
+      this.axisFontLabel.Text = "( none )";
+      // 
+      // titleFontLabel
+      // 
+      this.titleFontLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.titleFontLabel.AutoSize = true;
+      this.titleFontLabel.Location = new System.Drawing.Point(98, 31);
+      this.titleFontLabel.Name = "titleFontLabel";
+      this.titleFontLabel.Size = new System.Drawing.Size(43, 13);
+      this.titleFontLabel.TabIndex = 4;
+      this.titleFontLabel.Text = "( none )";
+      // 
+      // axisFontButton
+      // 
+      this.axisFontButton.Location = new System.Drawing.Point(66, 55);
+      this.axisFontButton.Name = "axisFontButton";
+      this.axisFontButton.Size = new System.Drawing.Size(26, 23);
+      this.axisFontButton.TabIndex = 6;
+      this.axisFontButton.Text = "...";
+      this.axisFontButton.UseVisualStyleBackColor = true;
+      this.axisFontButton.Click += new System.EventHandler(this.axisFontButton_Click);
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(3, 60);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(57, 13);
+      this.label3.TabIndex = 5;
+      this.label3.Text = "&Axes Font:";
+      // 
+      // titleFontButton
+      // 
+      this.titleFontButton.Location = new System.Drawing.Point(66, 26);
+      this.titleFontButton.Name = "titleFontButton";
+      this.titleFontButton.Size = new System.Drawing.Size(26, 23);
+      this.titleFontButton.TabIndex = 3;
+      this.titleFontButton.Text = "...";
+      this.titleFontButton.UseVisualStyleBackColor = true;
+      this.titleFontButton.Click += new System.EventHandler(this.titleFontButton_Click);
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(3, 31);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(54, 13);
+      this.label2.TabIndex = 2;
+      this.label2.Text = "&Title Font:";
+      // 
+      // errorProvider
+      // 
+      this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
+      this.errorProvider.ContainerControl = this;
+      // 
+      // titleFontDialog
+      // 
+      this.titleFontDialog.Color = System.Drawing.SystemColors.ControlText;
+      this.titleFontDialog.FontMustExist = true;
+      this.titleFontDialog.ShowColor = true;
+      // 
+      // axisFontDialog
+      // 
+      this.axisFontDialog.Color = System.Drawing.SystemColors.ControlText;
+      // 
+      // ScatterPlotVisualPropertiesControl
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.axisFontLabel);
+      this.Controls.Add(this.label15);
+      this.Controls.Add(this.axisFontButton);
+      this.Controls.Add(this.titleFontLabel);
+      this.Controls.Add(this.label3);
+      this.Controls.Add(this.titleTextBox);
+      this.Controls.Add(this.axisTabControl);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.titleFontButton);
+      this.Name = "ScatterPlotVisualPropertiesControl";
+      this.Size = new System.Drawing.Size(455, 220);
+      this.panel2.ResumeLayout(false);
+      this.panel2.PerformLayout();
+      this.panel1.ResumeLayout(false);
+      this.panel1.PerformLayout();
+      this.axisTabControl.ResumeLayout(false);
+      this.xAxisTabPage.ResumeLayout(false);
+      this.xAxisTabPage.PerformLayout();
+      this.yAxisTabPage.ResumeLayout(false);
+      this.yAxisTabPage.PerformLayout();
+      this.panel6.ResumeLayout(false);
+      this.panel6.PerformLayout();
+      this.panel5.ResumeLayout(false);
+      this.panel5.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.TextBox yAxisTitleTextBox;
+    private System.Windows.Forms.Label label12;
+    private System.Windows.Forms.Label label9;
+    private System.Windows.Forms.TextBox xAxisTitleTextBox;
+    private System.Windows.Forms.Label label11;
+    private System.Windows.Forms.TextBox xAxisMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisMaximumAutoRadioButton;
+    private System.Windows.Forms.TextBox xAxisMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisMinimumAutoRadioButton;
+    private System.Windows.Forms.TabControl axisTabControl;
+    private System.Windows.Forms.TabPage xAxisTabPage;
+    private System.Windows.Forms.TabPage yAxisTabPage;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.Label label8;
+    private System.Windows.Forms.TextBox yAxisMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisMaximumAutoRadioButton;
+    private System.Windows.Forms.TextBox yAxisMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisMinimumAutoRadioButton;
+    private System.Windows.Forms.ErrorProvider errorProvider;
+    private System.Windows.Forms.FontDialog titleFontDialog;
+    private System.Windows.Forms.Button titleFontButton;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.Button axisFontButton;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label axisFontLabel;
+    private System.Windows.Forms.Label titleFontLabel;
+    private System.Windows.Forms.FontDialog axisFontDialog;
+    private System.Windows.Forms.Label label15;
+    private System.Windows.Forms.TextBox titleTextBox;
+    private System.Windows.Forms.Panel panel1;
+    private System.Windows.Forms.Panel panel2;
+    private System.Windows.Forms.Panel panel6;
+    private System.Windows.Forms.Panel panel5;
+    private System.Windows.Forms.CheckBox xAxisGridCheckBox;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.CheckBox yAxisGridCheckBox;
+    private System.Windows.Forms.Label label5;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesControl.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesControl.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesControl.cs	(revision 15719)
@@ -0,0 +1,297 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("Scatter Plot Visual Properties")]
+  public partial class ScatterPlotVisualPropertiesControl : UserControl {
+    protected bool SuppressEvents { get; set; }
+
+    private ScatterPlotVisualProperties content;
+    public ScatterPlotVisualProperties Content {
+      get { return content; }
+      set {
+        bool changed = (value != content);
+        content = value;
+        if (changed) OnContentChanged();
+      }
+    }
+
+    public ScatterPlotVisualPropertiesControl() {
+      InitializeComponent();
+      errorProvider.SetIconAlignment(xAxisMinimumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(xAxisMaximumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(yAxisMinimumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconAlignment(yAxisMaximumFixedTextBox, ErrorIconAlignment.MiddleLeft);
+      errorProvider.SetIconPadding(xAxisMinimumFixedTextBox, 2);
+      errorProvider.SetIconPadding(xAxisMaximumFixedTextBox, 2);
+      errorProvider.SetIconPadding(yAxisMinimumFixedTextBox, 2);
+      errorProvider.SetIconPadding(yAxisMaximumFixedTextBox, 2);
+    }
+
+    protected virtual void OnContentChanged() {
+      SuppressEvents = true;
+      try {
+        if (Content == null) {
+          titleFontLabel.Text = "( none )";
+          axisFontLabel.Text = "( none )";
+          titleTextBox.Text = string.Empty;
+
+          xAxisTitleTextBox.Text = string.Empty;
+          xAxisMinimumAutoRadioButton.Checked = false;
+          xAxisMinimumFixedRadioButton.Checked = false;
+          xAxisMinimumFixedTextBox.Text = string.Empty;
+          xAxisMaximumAutoRadioButton.Checked = false;
+          xAxisMaximumFixedRadioButton.Checked = false;
+          xAxisMaximumFixedTextBox.Text = string.Empty;
+          xAxisGridCheckBox.Checked = false;
+
+          yAxisTitleTextBox.Text = string.Empty;
+          yAxisMinimumAutoRadioButton.Checked = false;
+          yAxisMinimumFixedRadioButton.Checked = false;
+          yAxisMinimumFixedTextBox.Text = string.Empty;
+          yAxisMaximumAutoRadioButton.Checked = false;
+          yAxisMaximumFixedRadioButton.Checked = false;
+          yAxisMaximumFixedTextBox.Text = string.Empty;
+          yAxisGridCheckBox.Checked = false;
+        } else {
+          titleFontLabel.Text = "( " + FormatFont(Content.TitleFont) + " )";
+          axisFontLabel.Text = "( " + FormatFont(Content.AxisTitleFont) + " )";
+          titleTextBox.Text = Content.Title;
+
+          xAxisTitleTextBox.Text = Content.XAxisTitle;
+          xAxisMinimumAutoRadioButton.Checked = Content.XAxisMinimumAuto;
+          xAxisMinimumFixedRadioButton.Checked = !Content.XAxisMinimumAuto;
+          xAxisMinimumFixedTextBox.Text = Content.XAxisMinimumFixedValue.ToString();
+          xAxisMaximumAutoRadioButton.Checked = Content.XAxisMaximumAuto;
+          xAxisMaximumFixedRadioButton.Checked = !Content.XAxisMaximumAuto;
+          xAxisMaximumFixedTextBox.Text = Content.XAxisMaximumFixedValue.ToString();
+          xAxisGridCheckBox.Checked = Content.XAxisGrid;
+
+          yAxisTitleTextBox.Text = Content.YAxisTitle;
+          yAxisMinimumAutoRadioButton.Checked = Content.YAxisMinimumAuto;
+          yAxisMinimumFixedRadioButton.Checked = !Content.YAxisMinimumAuto;
+          yAxisMinimumFixedTextBox.Text = Content.YAxisMinimumFixedValue.ToString();
+          yAxisMaximumAutoRadioButton.Checked = Content.YAxisMaximumAuto;
+          yAxisMaximumFixedRadioButton.Checked = !Content.YAxisMaximumAuto;
+          yAxisMaximumFixedTextBox.Text = Content.YAxisMaximumFixedValue.ToString();
+          yAxisGridCheckBox.Checked = Content.YAxisGrid;
+        }
+      }
+      finally { SuppressEvents = false; }
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void SetEnabledStateOfControls() {
+      axisTabControl.Enabled = Content != null;
+      xAxisMinimumFixedTextBox.Enabled = xAxisMinimumFixedRadioButton.Checked;
+      xAxisMaximumFixedTextBox.Enabled = xAxisMaximumFixedRadioButton.Checked;
+
+      yAxisMinimumFixedTextBox.Enabled = yAxisMinimumFixedRadioButton.Checked;
+      yAxisMaximumFixedTextBox.Enabled = yAxisMaximumFixedRadioButton.Checked;
+    }
+
+    #region Event Handlers
+    private void yTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.YAxisTitle = yAxisTitleTextBox.Text;
+      }
+    }
+
+    private void xTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.XAxisTitle = xAxisTitleTextBox.Text;
+      }
+    }
+
+    private void xAxisMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.XAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.XAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.XAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.XAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.YAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.YAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.YAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.YAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisMinimumAuto = xAxisMinimumAutoRadioButton.Checked;
+          if (Content.XAxisMinimumAuto) xAxisMinimumFixedTextBox.Text = double.NaN.ToString();
+        }
+        finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisMaximumAuto = xAxisMaximumAutoRadioButton.Checked;
+          if (Content.XAxisMaximumAuto) xAxisMaximumFixedTextBox.Text = double.NaN.ToString();
+        }
+        finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisMinimumAuto = yAxisMinimumAutoRadioButton.Checked;
+          if (Content.YAxisMinimumAuto) yAxisMinimumFixedTextBox.Text = double.NaN.ToString();
+        }
+        finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisMaximumAuto = yAxisMaximumAutoRadioButton.Checked;
+          if (Content.YAxisMaximumAuto) yAxisMaximumFixedTextBox.Text = double.NaN.ToString();
+        }
+        finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void titleFontButton_Click(object sender, System.EventArgs e) {
+      titleFontDialog.Font = Content.TitleFont;
+      titleFontDialog.Color = Content.TitleColor;
+      if (titleFontDialog.ShowDialog() == DialogResult.OK) {
+        Content.TitleFont = titleFontDialog.Font;
+        Content.TitleColor = titleFontDialog.Color;
+        titleFontLabel.Text = "( " + FormatFont(Content.TitleFont) + " )";
+      }
+    }
+
+    private void axisFontButton_Click(object sender, System.EventArgs e) {
+      axisFontDialog.Font = Content.AxisTitleFont;
+      axisFontDialog.Color = Content.AxisTitleColor;
+      if (axisFontDialog.ShowDialog() == DialogResult.OK) {
+        Content.AxisTitleFont = axisFontDialog.Font;
+        Content.AxisTitleColor = axisFontDialog.Color;
+        axisFontLabel.Text = "( " + FormatFont(Content.AxisTitleFont) + " )";
+      }
+    }
+
+    private void titleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.Title = titleTextBox.Text;
+      }
+    }
+
+    private void yAxisGridCheckBox_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.YAxisGrid = yAxisGridCheckBox.Checked;
+      }
+    }
+
+    private void xAxisGridCheckBox_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.XAxisGrid = xAxisGridCheckBox.Checked;
+      }
+    }
+    #endregion
+
+    private string FormatFont(Font f) {
+      if (f == null) return "default";
+      else return f.Name + ", " + f.SizeInPoints.ToString() + "pt, " + f.Style.ToString();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesDialog.Designer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesDialog.Designer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesDialog.Designer.cs	(revision 15719)
@@ -0,0 +1,252 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Views {
+  partial class ScatterPlotVisualPropertiesDialog {
+    /// <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 Windows Form 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.okButton = new System.Windows.Forms.Button();
+      this.cancelButton = new System.Windows.Forms.Button();
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.seriesTabPage = new System.Windows.Forms.TabPage();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.downButton = new System.Windows.Forms.Button();
+      this.upButton = new System.Windows.Forms.Button();
+      this.seriesListView = new System.Windows.Forms.ListView();
+      this.dataRowVisualPropertiesControl = new HeuristicLab.Analysis.Views.ScatterPlotDataRowVisualPropertiesControl();
+      this.chartTabPage = new System.Windows.Forms.TabPage();
+      this.dataTableVisualPropertiesControl = new HeuristicLab.Analysis.Views.ScatterPlotVisualPropertiesControl();
+      this.tabControl.SuspendLayout();
+      this.seriesTabPage.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.chartTabPage.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // okButton
+      // 
+      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.okButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.okButton.Location = new System.Drawing.Point(325, 400);
+      this.okButton.Name = "okButton";
+      this.okButton.Size = new System.Drawing.Size(75, 23);
+      this.okButton.TabIndex = 0;
+      this.okButton.Text = "&OK";
+      this.okButton.UseVisualStyleBackColor = true;
+      this.okButton.Click += new System.EventHandler(this.okButton_Click);
+      // 
+      // cancelButton
+      // 
+      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+      this.cancelButton.Location = new System.Drawing.Point(406, 400);
+      this.cancelButton.Name = "cancelButton";
+      this.cancelButton.Size = new System.Drawing.Size(75, 23);
+      this.cancelButton.TabIndex = 1;
+      this.cancelButton.Text = "&Cancel";
+      this.cancelButton.UseVisualStyleBackColor = true;
+      this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+      // 
+      // tabControl
+      // 
+      this.tabControl.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)));
+      this.tabControl.Controls.Add(this.seriesTabPage);
+      this.tabControl.Controls.Add(this.chartTabPage);
+      this.tabControl.Location = new System.Drawing.Point(12, 12);
+      this.tabControl.Name = "tabControl";
+      this.tabControl.SelectedIndex = 0;
+      this.tabControl.Size = new System.Drawing.Size(469, 382);
+      this.tabControl.TabIndex = 2;
+      // 
+      // seriesTabPage
+      // 
+      this.seriesTabPage.Controls.Add(this.splitContainer);
+      this.seriesTabPage.Location = new System.Drawing.Point(4, 22);
+      this.seriesTabPage.Name = "seriesTabPage";
+      this.seriesTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.seriesTabPage.Size = new System.Drawing.Size(461, 356);
+      this.seriesTabPage.TabIndex = 0;
+      this.seriesTabPage.Text = "Series";
+      this.seriesTabPage.UseVisualStyleBackColor = true;
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.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)));
+      this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+      this.splitContainer.Location = new System.Drawing.Point(0, 0);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.downButton);
+      this.splitContainer.Panel1.Controls.Add(this.upButton);
+      this.splitContainer.Panel1.Controls.Add(this.seriesListView);
+      this.splitContainer.Panel1MinSize = 20;
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.dataRowVisualPropertiesControl);
+      this.splitContainer.Panel2MinSize = 50;
+      this.splitContainer.Size = new System.Drawing.Size(461, 356);
+      this.splitContainer.SplitterDistance = 125;
+      this.splitContainer.TabIndex = 0;
+      // 
+      // downButton
+      // 
+      this.downButton.Enabled = false;
+      this.downButton.Location = new System.Drawing.Point(35, 3);
+      this.downButton.Name = "downButton";
+      this.downButton.Size = new System.Drawing.Size(26, 23);
+      this.downButton.TabIndex = 1;
+      this.downButton.Text = "Down";
+      this.downButton.UseVisualStyleBackColor = true;
+      this.downButton.Click += new System.EventHandler(this.downButton_Click);
+      // 
+      // upButton
+      // 
+      this.upButton.Enabled = false;
+      this.upButton.Location = new System.Drawing.Point(3, 3);
+      this.upButton.Name = "upButton";
+      this.upButton.Size = new System.Drawing.Size(26, 23);
+      this.upButton.TabIndex = 0;
+      this.upButton.Text = "Up";
+      this.upButton.UseVisualStyleBackColor = true;
+      this.upButton.Click += new System.EventHandler(this.upButton_Click);
+      // 
+      // seriesListView
+      // 
+      this.seriesListView.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)));
+      this.seriesListView.HideSelection = false;
+      this.seriesListView.Location = new System.Drawing.Point(3, 32);
+      this.seriesListView.MultiSelect = false;
+      this.seriesListView.Name = "seriesListView";
+      this.seriesListView.ShowGroups = false;
+      this.seriesListView.Size = new System.Drawing.Size(119, 321);
+      this.seriesListView.TabIndex = 2;
+      this.seriesListView.UseCompatibleStateImageBehavior = false;
+      this.seriesListView.View = System.Windows.Forms.View.List;
+      this.seriesListView.SelectedIndexChanged += new System.EventHandler(this.seriesListView_SelectedIndexChanged);
+      // 
+      // dataRowVisualPropertiesControl
+      // 
+      this.dataRowVisualPropertiesControl.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)));
+      this.dataRowVisualPropertiesControl.Content = null;
+      this.dataRowVisualPropertiesControl.Location = new System.Drawing.Point(3, 26);
+      this.dataRowVisualPropertiesControl.Name = "dataRowVisualPropertiesControl";
+      this.dataRowVisualPropertiesControl.Size = new System.Drawing.Size(326, 327);
+      this.dataRowVisualPropertiesControl.TabIndex = 0;
+      // 
+      // chartTabPage
+      // 
+      this.chartTabPage.Controls.Add(this.dataTableVisualPropertiesControl);
+      this.chartTabPage.Location = new System.Drawing.Point(4, 22);
+      this.chartTabPage.Name = "chartTabPage";
+      this.chartTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.chartTabPage.Size = new System.Drawing.Size(461, 356);
+      this.chartTabPage.TabIndex = 1;
+      this.chartTabPage.Text = "Chart";
+      this.chartTabPage.UseVisualStyleBackColor = true;
+      // 
+      // dataTableVisualPropertiesControl
+      // 
+      this.dataTableVisualPropertiesControl.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)));
+      this.dataTableVisualPropertiesControl.Content = null;
+      this.dataTableVisualPropertiesControl.Location = new System.Drawing.Point(3, 6);
+      this.dataTableVisualPropertiesControl.Name = "dataTableVisualPropertiesControl";
+      this.dataTableVisualPropertiesControl.Size = new System.Drawing.Size(455, 347);
+      this.dataTableVisualPropertiesControl.TabIndex = 0;
+      // 
+      // DataTableVisualPropertiesDialog
+      // 
+      this.AcceptButton = this.okButton;
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.CancelButton = this.cancelButton;
+      this.ClientSize = new System.Drawing.Size(493, 435);
+      this.Controls.Add(this.tabControl);
+      this.Controls.Add(this.cancelButton);
+      this.Controls.Add(this.okButton);
+      this.MaximizeBox = false;
+      this.MinimizeBox = false;
+      this.Name = "DataTableVisualPropertiesDialog";
+      this.ShowIcon = false;
+      this.ShowInTaskbar = false;
+      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+      this.Text = "Customize Visual Properties";
+      this.TopMost = true;
+      this.tabControl.ResumeLayout(false);
+      this.seriesTabPage.ResumeLayout(false);
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+      this.splitContainer.ResumeLayout(false);
+      this.chartTabPage.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button okButton;
+    private System.Windows.Forms.Button cancelButton;
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage seriesTabPage;
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.Windows.Forms.ListView seriesListView;
+    private System.Windows.Forms.TabPage chartTabPage;
+    private ScatterPlotDataRowVisualPropertiesControl dataRowVisualPropertiesControl;
+    private ScatterPlotVisualPropertiesControl dataTableVisualPropertiesControl;
+    private System.Windows.Forms.Button downButton;
+    private System.Windows.Forms.Button upButton;
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesDialog.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesDialog.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis.Views/3.3/ScatterPlotVisualPropertiesDialog.cs	(revision 15719)
@@ -0,0 +1,181 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Common.Resources;
+
+namespace HeuristicLab.Analysis.Views {
+  public partial class ScatterPlotVisualPropertiesDialog : Form {
+    protected bool SuppressEvents { get; set; }
+    protected ScatterPlot Content { get; private set; }
+    private ScatterPlotVisualProperties originalScatterPlotVPs;
+    private Dictionary<string, ScatterPlotDataRowVisualProperties> originalScatterPlotDataRowVPs;
+
+    private HashSet<string> modifiedDisplayNames;
+    public IEnumerable<string> RowsWithModifiedDisplayNames { get { return modifiedDisplayNames.AsEnumerable(); } }
+
+    public ScatterPlotVisualPropertiesDialog(ScatterPlot scatterPlot) {
+      InitializeComponent();
+      #region Prepare controls
+      upButton.Text = string.Empty;
+      upButton.Image = VSImageLibrary.ArrowUp;
+      downButton.Text = string.Empty;
+      downButton.Image = VSImageLibrary.ArrowDown;
+      seriesListView.Items.Clear();
+      seriesListView.SmallImageList = new ImageList();
+      seriesListView.SmallImageList.Images.Add(VSImageLibrary.Graph);
+      #endregion
+
+      Content = scatterPlot;
+      originalScatterPlotVPs = (ScatterPlotVisualProperties)Content.VisualProperties.Clone();
+      originalScatterPlotDataRowVPs = new Dictionary<string, ScatterPlotDataRowVisualProperties>();
+      foreach (ScatterPlotDataRow row in Content.Rows)
+        originalScatterPlotDataRowVPs.Add(row.Name, (ScatterPlotDataRowVisualProperties)row.VisualProperties.Clone());
+
+      dataTableVisualPropertiesControl.Content = Content.VisualProperties;
+
+      modifiedDisplayNames = new HashSet<string>();
+      FillSeriesListView();
+      RegisterContentEvents();
+    }
+
+    private void RegisterContentEvents() {
+      foreach (ScatterPlotDataRow row in Content.Rows) {
+        row.VisualProperties.PropertyChanged += new PropertyChangedEventHandler(Row_VisualProperties_PropertyChanged);
+      }
+    }
+
+    private void DeregisterContentEvents() {
+      foreach (ScatterPlotDataRow row in Content.Rows) {
+        row.VisualProperties.PropertyChanged -= new PropertyChangedEventHandler(Row_VisualProperties_PropertyChanged);
+      }
+    }
+
+    protected override void OnClosing(CancelEventArgs e) {
+      DeregisterContentEvents();
+      Application.DoEvents();
+      base.OnClosing(e);
+    }
+
+    private void Row_VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      foreach (ScatterPlotDataRow row in Content.Rows) {
+        if (e.PropertyName == "DisplayName" && row.VisualProperties == sender) {
+          modifiedDisplayNames.Add(row.Name);
+          break;
+        }
+      }
+    }
+
+    private void seriesListView_SelectedIndexChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents) {
+        if (seriesListView.SelectedItems.Count != 1) {
+          dataRowVisualPropertiesControl.Content = null;
+          upButton.Enabled = downButton.Enabled = false;
+        } else {
+          string rowName = seriesListView.SelectedItems[0].Text;
+          dataRowVisualPropertiesControl.Content = Content.Rows[rowName].VisualProperties;
+          upButton.Enabled = seriesListView.SelectedIndices[0] > 0;
+          downButton.Enabled = seriesListView.SelectedIndices[0] < seriesListView.Items.Count - 1;
+        }
+      }
+    }
+
+    private void okButton_Click(object sender, System.EventArgs e) {
+      DialogResult = DialogResult.OK;
+      Close();
+    }
+
+    private void cancelButton_Click(object sender, System.EventArgs e) {
+      DialogResult = DialogResult.Cancel;
+      foreach (ScatterPlotDataRow row in Content.Rows) {
+        row.VisualProperties = originalScatterPlotDataRowVPs[row.Name];
+      }
+      modifiedDisplayNames.Clear();
+      Content.VisualProperties = originalScatterPlotVPs;
+      Close();
+    }
+
+    private void upButton_Click(object sender, System.EventArgs e) {
+      if (seriesListView.SelectedIndices.Count == 1 && seriesListView.SelectedIndices[0] > 0) {
+        int index = seriesListView.SelectedIndices[0];
+        SuppressEvents = true;
+        try {
+          seriesListView.BeginUpdate();
+          ListViewItem selectedSeriesItem = seriesListView.Items[index];
+          seriesListView.Items.RemoveAt(index);
+          ListViewItem temp = seriesListView.Items[index - 1];
+          seriesListView.Items.RemoveAt(index - 1);
+          seriesListView.Items.Insert(index - 1, selectedSeriesItem);
+          seriesListView.Items.Insert(index, temp);
+          seriesListView.SelectedIndices.Clear();
+          seriesListView.EndUpdate();
+        }
+        finally { SuppressEvents = false; }
+        seriesListView.SelectedIndices.Add(index - 1);
+        UpdateAllSeriesPositions();
+      }
+    }
+
+    private void downButton_Click(object sender, System.EventArgs e) {
+      if (seriesListView.SelectedIndices.Count == 1 && seriesListView.SelectedIndices[0] < seriesListView.Items.Count - 1) {
+        int index = seriesListView.SelectedIndices[0];
+        SuppressEvents = true;
+        try {
+          seriesListView.BeginUpdate();
+          ListViewItem temp = seriesListView.Items[index + 1];
+          seriesListView.Items.RemoveAt(index + 1);
+          ListViewItem selectedSeriesItem = seriesListView.Items[index];
+          seriesListView.Items.RemoveAt(index);
+          seriesListView.Items.Insert(index, temp);
+          seriesListView.Items.Insert(index + 1, selectedSeriesItem);
+          seriesListView.SelectedIndices.Clear();
+          seriesListView.EndUpdate();
+        }
+        finally { SuppressEvents = false; }
+        seriesListView.SelectedIndices.Add(index + 1);
+        UpdateAllSeriesPositions();
+      }
+    }
+
+    #region Helpers
+    private void FillSeriesListView() {
+      seriesListView.SelectedIndices.Clear();
+      foreach (ScatterPlotDataRow row in Content.Rows) {
+        seriesListView.Items.Add(new ListViewItem(row.Name, 0));
+      }
+      if (seriesListView.Items.Count > 0)
+        seriesListView.SelectedIndices.Add(0);
+    }
+
+    private void UpdateAllSeriesPositions() {
+      Dictionary<string, ScatterPlotDataRow> rows = Content.Rows.ToDictionary(x => x.Name);
+      Content.Rows.Clear();
+      for (int i = 0; i < seriesListView.Items.Count; i++) {
+        ListViewItem item = seriesListView.Items[i];
+        Content.Rows.Add(rows[item.Text]);
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/Allele.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/Allele.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/Allele.cs	(revision 15719)
@@ -0,0 +1,87 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents an allele of a solution which is used for allele analysis.
+  /// </summary>
+  [Item("Allele", "Represents an allele of a solution which is used for allele analysis.")]
+  [StorableClass]
+  public class Allele : Item {
+    private string id;
+    public string Id {
+      get { return id; }
+    }
+    private double impact;
+    public double Impact {
+      get { return impact; }
+    }
+
+    #region Storable Properties
+    [Storable(Name = "Id")]
+    private string StorableId {
+      get { return id; }
+      set { id = value; }
+    }
+    [Storable(Name = "Impact")]
+    private double StorableImpact {
+      get { return impact; }
+      set { impact = value; }
+    }
+    #endregion
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected Allele(bool deserializing) : base(deserializing) { }
+    protected Allele(Allele original, Cloner cloner)
+      : base(original, cloner) {
+      this.id = original.id;
+      this.impact = original.impact;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Allele(this, cloner);
+    }
+    #endregion
+    public Allele()
+      : base() {
+      this.id = string.Empty;
+      this.impact = 0;
+    }
+    public Allele(string id)
+      : base() {
+      this.id = id;
+      this.impact = 0;
+    }
+    public Allele(string id, double impact)
+      : base() {
+      this.id = id;
+      this.impact = impact;
+    }
+
+    public override string ToString() {
+      return id + " (" + impact + ")";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequency.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequency.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequency.cs	(revision 15719)
@@ -0,0 +1,130 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents the frequency of an allele.
+  /// </summary>
+  [Item("AlleleFrequency", "Represents the frequency of an allele.")]
+  [StorableClass]
+  public class AlleleFrequency : Item {
+    private string id;
+    public string Id {
+      get { return id; }
+    }
+    private double frequency;
+    public double Frequency {
+      get { return frequency; }
+    }
+    private double averageImpact;
+    public double AverageImpact {
+      get { return averageImpact; }
+    }
+    private double averageSolutionQuality;
+    public double AverageSolutionQuality {
+      get { return averageSolutionQuality; }
+    }
+    private bool containedInBestKnownSolution;
+    public bool ContainedInBestKnownSolution {
+      get { return containedInBestKnownSolution; }
+    }
+    private bool containedInBestSolution;
+    public bool ContainedInBestSolution {
+      get { return containedInBestSolution; }
+    }
+
+    #region Storable Properties
+    [Storable(Name = "Id")]
+    private string StorableId {
+      get { return id; }
+      set { id = value; }
+    }
+    [Storable(Name = "Frequency")]
+    private double StorableFrequency {
+      get { return frequency; }
+      set { frequency = value; }
+    }
+    [Storable(Name = "AverageImpact")]
+    private double StorableAverageImpact {
+      get { return averageImpact; }
+      set { averageImpact = value; }
+    }
+    [Storable(Name = "AverageSolutionQuality")]
+    private double StorableAverageSolutionQuality {
+      get { return averageSolutionQuality; }
+      set { averageSolutionQuality = value; }
+    }
+    [Storable(Name = "ContainedInBestKnownSolution")]
+    private bool StorableContainedInBestKnownSolution {
+      get { return containedInBestKnownSolution; }
+      set { containedInBestKnownSolution = value; }
+    }
+    [Storable(Name = "ContainedInBestSolution")]
+    private bool StorableContainedInBestSolution {
+      get { return containedInBestSolution; }
+      set { containedInBestSolution = value; }
+    }
+    #endregion
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected AlleleFrequency(bool deserializing) : base(deserializing) { }
+    protected AlleleFrequency(AlleleFrequency original, Cloner cloner)
+      : base(original, cloner) {
+      this.id = original.id;
+      this.frequency = original.frequency;
+      this.averageImpact = original.averageImpact;
+      this.averageSolutionQuality = original.averageSolutionQuality;
+      this.containedInBestKnownSolution = original.containedInBestKnownSolution;
+      this.containedInBestSolution = original.containedInBestSolution;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlleleFrequency(this, cloner);
+    }
+    #endregion
+    public AlleleFrequency()
+      : base() {
+      id = string.Empty;
+      frequency = 0;
+      averageImpact = 0;
+      averageSolutionQuality = 0;
+      containedInBestKnownSolution = false;
+      containedInBestSolution = false;
+    }
+    public AlleleFrequency(string id, double frequency, double averageImpact, double averageSolutionQuality, bool containedInBestKnownSolution, bool containedInBestSolution)
+      : base() {
+      this.id = id;
+      this.frequency = frequency;
+      this.averageImpact = averageImpact;
+      this.averageSolutionQuality = averageSolutionQuality;
+      this.containedInBestKnownSolution = containedInBestKnownSolution;
+      this.containedInBestSolution = containedInBestSolution;
+    }
+
+    public override string ToString() {
+      return id;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 15719)
@@ -0,0 +1,312 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator for analyzing the frequency of alleles.
+  /// </summary>
+  [Item("AlleleFrequencyAnalyzer", "An operator for analyzing the frequency of alleles.")]
+  [StorableClass]
+  public abstract class AlleleFrequencyAnalyzer<T> : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator where T : class, IItem {
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<T> SolutionParameter {
+      get { return (ScopeTreeLookupParameter<T>)Parameters["Solution"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public LookupParameter<T> BestKnownSolutionParameter {
+      get { return (LookupParameter<T>)Parameters["BestKnownSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public ValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public ValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (ValueParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public LookupParameter<IntValue> UpdateCounterParameter {
+      get { return (LookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+
+    [StorableConstructor]
+    protected AlleleFrequencyAnalyzer(bool deserializing) : base(deserializing) { }
+    protected AlleleFrequencyAnalyzer(AlleleFrequencyAnalyzer<T> original, Cloner cloner) : base(original, cloner) { }
+    public AlleleFrequencyAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
+      Parameters.Add(new ScopeTreeLookupParameter<T>("Solution", "The solutions whose alleles should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the solutions which should be analyzed."));
+      Parameters.Add(new LookupParameter<T>("BestKnownSolution", "The best known solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the allele frequency analysis results should be stored."));
+      Parameters.Add(new ValueParameter<BoolValue>("StoreHistory", "True if the history of the allele frequency analysis should be stored.", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", "The interval in which the allele frequency analysis should be applied.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the operator was called since the last update.", "AlleleFrequencyAnalyzerUpdateCounter"));
+
+      MaximizationParameter.Hidden = true;
+      SolutionParameter.Hidden = true;
+      QualityParameter.Hidden = true;
+      BestKnownSolutionParameter.Hidden = true;
+      ResultsParameter.Hidden = true;
+      UpdateCounterParameter.Hidden = true;
+    }
+
+    #region Equality Comparers
+    private class AlleleIdEqualityComparer : IEqualityComparer<Allele> {
+      public bool Equals(Allele x, Allele y) {
+        return x.Id == y.Id;
+      }
+      public int GetHashCode(Allele obj) {
+        return obj.Id.GetHashCode();
+      }
+    }
+    private class AlleleFrequencyIdEqualityComparer : IEqualityComparer<AlleleFrequency> {
+      public bool Equals(AlleleFrequency x, AlleleFrequency y) {
+        return x.Id == y.Id;
+      }
+      public int GetHashCode(AlleleFrequency obj) {
+        return obj.Id.GetHashCode();
+      }
+    }
+    #endregion
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      } else updateCounter.Value++;
+
+      if (updateCounter.Value == updateInterval) {
+        updateCounter.Value = 0;
+
+        bool max = MaximizationParameter.ActualValue.Value;
+        ItemArray<T> solutions = SolutionParameter.ActualValue;
+        double[] qualities = QualityParameter.ActualValue.Select(x => x.Value).ToArray();
+        T bestKnownSolution = BestKnownSolutionParameter.ActualValue;
+        bool storeHistory = StoreHistoryParameter.Value.Value;
+
+        // calculate index of current best solution
+        int bestIndex = -1;
+        if (!max) {
+          bestIndex = qualities
+            .Select((x, i) => new { Index = i, Value = x })
+            .OrderBy(x => x.Value)
+            .First().Index;
+        } else {
+          bestIndex = qualities
+            .Select((x, i) => new { Index = i, Value = x })
+            .OrderByDescending(x => x.Value)
+            .First().Index;
+        }
+
+        // calculate allels of current best and (if available) best known solution
+        Allele[] bestAlleles = CalculateAlleles(solutions[bestIndex]);
+        Allele[] bestKnownAlleles = null;
+        if (bestKnownSolution != null)
+          bestKnownAlleles = CalculateAlleles(bestKnownSolution);
+
+        // calculate allele frequencies
+        var frequencies = solutions.SelectMany((s, index) => CalculateAlleles(s).Select(a => new { Allele = a, Quality = qualities[index] })).
+                          GroupBy(x => x.Allele.Id).
+                          Select(x => new AlleleFrequency(x.Key,
+                                                          x.Count() / ((double)solutions.Length),
+                                                          x.Average(a => a.Allele.Impact),
+                                                          x.Average(a => a.Quality),
+                                                          bestKnownAlleles == null ? false : bestKnownAlleles.Any(a => a.Id == x.Key),
+                                                          bestAlleles.Any(a => a.Id == x.Key)));
+
+        // calculate dummy allele frequencies of alleles of best known solution which did not occur
+        if (bestKnownAlleles != null) {
+          var bestKnownFrequencies = bestKnownAlleles.Select(x => new AlleleFrequency(x.Id, 0, x.Impact, 0, true, false)).Except(frequencies, new AlleleFrequencyIdEqualityComparer());
+          frequencies = frequencies.Concat(bestKnownFrequencies);
+        }
+
+        // fetch results collection
+        ResultCollection results;
+        if (!ResultsParameter.ActualValue.ContainsKey(Name + " Results")) {
+          results = new ResultCollection();
+          ResultsParameter.ActualValue.Add(new Result(Name + " Results", results));
+        } else {
+          results = (ResultCollection)ResultsParameter.ActualValue[Name + " Results"].Value;
+        }
+
+        // store allele frequencies
+        AlleleFrequencyCollection frequenciesCollection = new AlleleFrequencyCollection(frequencies);
+        if (!results.ContainsKey("Allele Frequencies"))
+          results.Add(new Result("Allele Frequencies", frequenciesCollection));
+        else
+          results["Allele Frequencies"].Value = frequenciesCollection;
+
+        // store allele frequencies history
+        if (storeHistory) {
+          if (!results.ContainsKey("Allele Frequencies History")) {
+            AlleleFrequencyCollectionHistory history = new AlleleFrequencyCollectionHistory();
+            history.Add(frequenciesCollection);
+            results.Add(new Result("Allele Frequencies History", history));
+          } else {
+            ((AlleleFrequencyCollectionHistory)results["Allele Frequencies History"].Value).Add(frequenciesCollection);
+          }
+        }
+
+        // store alleles data table
+        DataTable allelesTable;
+        if (!results.ContainsKey("Alleles")) {
+          allelesTable = new DataTable("Alleles");
+          allelesTable.VisualProperties.XAxisTitle = "Iteration";
+          allelesTable.VisualProperties.YAxisTitle = "Number of Alleles";
+          allelesTable.VisualProperties.SecondYAxisTitle = "Number of Alleles";
+
+          allelesTable.Rows.Add(new DataRow("Unique Alleles"));
+          allelesTable.Rows["Unique Alleles"].VisualProperties.StartIndexZero = true;
+
+          allelesTable.Rows.Add(new DataRow("Unique Alleles of Best Known Solution", null));
+          allelesTable.Rows["Unique Alleles of Best Known Solution"].VisualProperties.SecondYAxis = true;
+          allelesTable.Rows["Unique Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
+
+          allelesTable.Rows.Add(new DataRow("Fixed Alleles", null));
+          allelesTable.Rows["Fixed Alleles"].VisualProperties.SecondYAxis = true;
+          allelesTable.Rows["Fixed Alleles"].VisualProperties.StartIndexZero = true;
+
+          allelesTable.Rows.Add(new DataRow("Fixed Alleles of Best Known Solution", null));
+          allelesTable.Rows["Fixed Alleles of Best Known Solution"].VisualProperties.SecondYAxis = true;
+          allelesTable.Rows["Fixed Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
+
+          allelesTable.Rows.Add(new DataRow("Lost Alleles of Best Known Solution", null));
+          allelesTable.Rows["Lost Alleles of Best Known Solution"].VisualProperties.SecondYAxis = true;
+          allelesTable.Rows["Lost Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
+
+          results.Add(new Result("Alleles", allelesTable));
+        } else {
+          allelesTable = (DataTable)results["Alleles"].Value;
+        }
+
+        int fixedAllelesCount = frequenciesCollection.Where(x => x.Frequency == 1).Count();
+        var relevantAlleles = frequenciesCollection.Where(x => x.ContainedInBestKnownSolution);
+        int relevantAllelesCount = relevantAlleles.Count();
+        int fixedRelevantAllelesCount = relevantAlleles.Where(x => x.Frequency == 1).Count();
+        int lostRelevantAllelesCount = relevantAlleles.Where(x => x.Frequency == 0).Count();
+        int uniqueRelevantAllelesCount = relevantAllelesCount - lostRelevantAllelesCount;
+        allelesTable.Rows["Unique Alleles"].Values.Add(frequenciesCollection.Count);
+        allelesTable.Rows["Unique Alleles of Best Known Solution"].Values.Add(uniqueRelevantAllelesCount);
+        allelesTable.Rows["Fixed Alleles"].Values.Add(fixedAllelesCount);
+        allelesTable.Rows["Fixed Alleles of Best Known Solution"].Values.Add(fixedRelevantAllelesCount);
+        allelesTable.Rows["Lost Alleles of Best Known Solution"].Values.Add(lostRelevantAllelesCount);
+
+        // store alleles values
+        if (!results.ContainsKey("Unique Alleles"))
+          results.Add(new Result("Unique Alleles", new DoubleValue(frequenciesCollection.Count)));
+        else
+          ((DoubleValue)results["Unique Alleles"].Value).Value = frequenciesCollection.Count;
+
+        if (!results.ContainsKey("Unique Alleles of Best Known Solution"))
+          results.Add(new Result("Unique Alleles of Best Known Solution", new DoubleValue(uniqueRelevantAllelesCount)));
+        else
+          ((DoubleValue)results["Unique Alleles of Best Known Solution"].Value).Value = uniqueRelevantAllelesCount;
+
+        if (!results.ContainsKey("Fixed Alleles"))
+          results.Add(new Result("Fixed Alleles", new DoubleValue(fixedAllelesCount)));
+        else
+          ((DoubleValue)results["Fixed Alleles"].Value).Value = fixedAllelesCount;
+
+        if (!results.ContainsKey("Fixed Alleles of Best Known Solution"))
+          results.Add(new Result("Fixed Alleles of Best Known Solution", new DoubleValue(fixedRelevantAllelesCount)));
+        else
+          ((DoubleValue)results["Fixed Alleles of Best Known Solution"].Value).Value = fixedRelevantAllelesCount;
+
+        if (!results.ContainsKey("Lost Alleles of Best Known Solution"))
+          results.Add(new Result("Lost Alleles of Best Known Solution", new DoubleValue(lostRelevantAllelesCount)));
+        else
+          ((DoubleValue)results["Lost Alleles of Best Known Solution"].Value).Value = lostRelevantAllelesCount;
+
+        // calculate contained alleles of best known solution and relative quality
+        if (bestKnownAlleles != null) {
+          double qualityRange = Math.Abs(qualities.Max() - qualities.Min());
+          var points = solutions.Select((s, index) => new Point2D<double>(CalculateAlleles(s).Intersect(bestKnownAlleles, new AlleleIdEqualityComparer()).Count(),
+                                                                          Math.Abs(qualities[index] - qualities[bestIndex]) / qualityRange));
+          var avgContainedReleventAlleles = points.Select(x => x.X).Average();
+
+          var plot = new ScatterPlot("Contained Alleles of Best Known Solution and Relative Solution Qualtiy", null);
+          plot.VisualProperties.XAxisTitle = "Contained Alleles of Best Known Solution";
+          plot.VisualProperties.YAxisTitle = "Relative Solution Quality";
+          plot.VisualProperties.XAxisMinimumAuto = false;
+          plot.VisualProperties.XAxisMinimumFixedValue = 0.0;
+          plot.VisualProperties.XAxisMaximumAuto = false;
+          plot.VisualProperties.XAxisMaximumFixedValue = bestKnownAlleles.Length;
+          plot.VisualProperties.YAxisMinimumAuto = false;
+          plot.VisualProperties.YAxisMinimumFixedValue = 0.0;
+          plot.VisualProperties.YAxisMaximumAuto = false;
+          plot.VisualProperties.YAxisMaximumFixedValue = 1.0;
+          var row = new ScatterPlotDataRow("Solutions of Current Generation", null, points);
+          row.VisualProperties.PointStyle = ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Circle;
+          row.VisualProperties.PointSize = 5;
+          plot.Rows.Add(row);
+
+          if (!results.ContainsKey("Scatter Plot"))
+            results.Add(new Result("Scatter Plot", plot));
+          else
+            results["Scatter Plot"].Value = plot;
+          if (storeHistory) {
+            if (!results.ContainsKey("Scatter Plot History")) {
+              results.Add(new Result("Scatter Plot History", new ScatterPlotHistory()));
+            }
+            ((ScatterPlotHistory)results["Scatter Plot History"].Value).Add(plot);
+          }
+
+          if (!allelesTable.Rows.ContainsKey("Average Contained Alleles of Best Known Solution")) {
+            allelesTable.Rows.Add(new DataRow("Average Contained Alleles of Best Known Solution", null));
+            allelesTable.Rows["Average Contained Alleles of Best Known Solution"].VisualProperties.SecondYAxis = true;
+            allelesTable.Rows["Average Contained Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
+          }
+          allelesTable.Rows["Average Contained Alleles of Best Known Solution"].Values.Add(avgContainedReleventAlleles);
+
+          if (!results.ContainsKey("Average Contained Alleles of Best Known Solution"))
+            results.Add(new Result("Average Contained Alleles of Best Known Solution", new DoubleValue(avgContainedReleventAlleles)));
+          else
+            ((DoubleValue)results["Average Contained Alleles of Best Known Solution"].Value).Value = avgContainedReleventAlleles;
+        }
+      }
+      return base.Apply();
+    }
+
+    protected abstract Allele[] CalculateAlleles(T solution);
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyCollection.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyCollection.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyCollection.cs	(revision 15719)
@@ -0,0 +1,49 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents a collection of allele frequencies.
+  /// </summary>
+  [Item("AlleleFrequencyCollection", "Represents a collection of allele frequencies.")]
+  [StorableClass]
+  public class AlleleFrequencyCollection : ReadOnlyItemCollection<AlleleFrequency> {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Statistics; }
+    }
+
+    [StorableConstructor]
+    protected AlleleFrequencyCollection(bool deserializing) : base(deserializing) { }
+    protected AlleleFrequencyCollection(AlleleFrequencyCollection original, Cloner cloner) : base(original, cloner) { }
+    public AlleleFrequencyCollection() : base() { }
+    public AlleleFrequencyCollection(IEnumerable<AlleleFrequency> frequencies) : base(new ItemCollection<AlleleFrequency>(frequencies)) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlleleFrequencyCollection(this, cloner);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyCollectionHistory.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyCollectionHistory.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyCollectionHistory.cs	(revision 15719)
@@ -0,0 +1,49 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents history values of allele frequencies collections.
+  /// </summary>
+  [Item("AlleleFrequencyCollectionHistory", "Represents history values of allele frequencies collections.")]
+  [StorableClass]
+  public class AlleleFrequencyCollectionHistory : ItemCollection<AlleleFrequencyCollection> {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Cab; }
+    }
+
+    [StorableConstructor]
+    protected AlleleFrequencyCollectionHistory(bool deserializing) : base(deserializing) { }
+    protected AlleleFrequencyCollectionHistory(AlleleFrequencyCollectionHistory original, Cloner cloner) : base(original, cloner) { }
+    public AlleleFrequencyCollectionHistory() : base() { }
+    public AlleleFrequencyCollectionHistory(IEnumerable<AlleleFrequencyCollection> collections) : base(new ItemCollection<AlleleFrequencyCollection>(collections)) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlleleFrequencyCollectionHistory(this, cloner);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/BestScopeSolutionAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/BestScopeSolutionAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/BestScopeSolutionAnalyzer.cs	(revision 15719)
@@ -0,0 +1,147 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator that extracts (clones) the scope containing the best quality.
+  /// </summary>
+  [Item("BestScopeSolutionAnalyzer", "An operator that extracts the scope containing the best quality.")]
+  [StorableClass]
+  public class BestScopeSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator {
+
+    public virtual bool EnabledByDefault {
+      get { return true; }
+    }
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IFixedValueParameter<StringValue> BestSolutionResultNameParameter {
+      get { return (IFixedValueParameter<StringValue>)Parameters["BestSolution ResultName"]; }
+    }
+    public ILookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public string BestSolutionResultName {
+      get { return BestSolutionResultNameParameter.Value.Value; }
+      set { BestSolutionResultNameParameter.Value.Value = value; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected BestScopeSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+    protected BestScopeSolutionAnalyzer(BestScopeSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestScopeSolutionAnalyzer(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("BestSolution ResultName"))
+        Parameters.Add(new FixedValueParameter<StringValue>("BestSolution ResultName", "The name of the result for storing the best solution.", new StringValue("Best Solution")));
+      if (Parameters.ContainsKey("BestSolution")) Parameters.Remove("BestSolution");
+      if (Parameters.ContainsKey("BestKnownSolution")) Parameters.Remove("BestKnownSolution");
+      #endregion
+    }
+    #endregion
+    public BestScopeSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the solutions."));
+      Parameters.Add(new FixedValueParameter<StringValue>("BestSolution ResultName", "The name of the result for storing the best solution.", new StringValue("Best Solution")));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the solution should be stored."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      bool max = MaximizationParameter.ActualValue.Value;
+      DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
+
+      if (results.ContainsKey(BestSolutionResultName) && !typeof(IScope).IsAssignableFrom(results[BestSolutionResultName].DataType)) {
+        throw new InvalidOperationException(string.Format("Could not add best solution result, because there is already a result with the name \"{0}\" present in the result collection.", BestSolutionResultName));
+      }
+
+      int i = -1;
+      if (!max)
+        i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      else i = qualities.Select((x, index) => new { index, x.Value }).OrderByDescending(x => x.Value).First().index;
+
+      IEnumerable<IScope> scopes = new IScope[] { ExecutionContext.Scope };
+      for (int j = 0; j < QualityParameter.Depth; j++)
+        scopes = scopes.SelectMany(x => x.SubScopes);
+      IScope currentBestScope = scopes.ToList()[i];
+
+      if (bestKnownQuality == null ||
+          max && qualities[i].Value > bestKnownQuality.Value
+          || !max && qualities[i].Value < bestKnownQuality.Value) {
+        BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value);
+      }
+
+      if (!results.ContainsKey(BestSolutionResultName)) {
+        var cloner = new Cloner();
+        //avoid cloning of subscopes and the results collection that the solution is put in
+        cloner.RegisterClonedObject(results, new ResultCollection());
+        cloner.RegisterClonedObject(currentBestScope.SubScopes, new ScopeList());
+        var solution = cloner.Clone(currentBestScope);
+
+        results.Add(new Result(BestSolutionResultName, solution));
+      } else {
+        var bestSolution = (IScope)results[BestSolutionResultName].Value;
+        string qualityName = QualityParameter.TranslatedName;
+        if (bestSolution.Variables.ContainsKey(qualityName)) {
+          double bestQuality = ((DoubleValue)bestSolution.Variables[qualityName].Value).Value;
+          if (max && qualities[i].Value > bestQuality
+              || !max && qualities[i].Value < bestQuality) {
+            var cloner = new Cloner();
+            //avoid cloning of subscopes and the results collection that the solution is put in
+            cloner.RegisterClonedObject(results, new ResultCollection());
+            cloner.RegisterClonedObject(currentBestScope.SubScopes, new ScopeList());
+            var solution = cloner.Clone(currentBestScope);
+
+            results[BestSolutionResultName].Value = solution;
+          }
+        }
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataRow.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataRow.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataRow.cs	(revision 15719)
@@ -0,0 +1,124 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// A row of data values.
+  /// </summary>
+  [Item("DataRow", "A row of data values.")]
+  [StorableClass]
+  public class DataRow : NamedItem {
+    private DataRowVisualProperties visualProperties;
+    public DataRowVisualProperties VisualProperties {
+      get { return visualProperties; }
+      set {
+        if (visualProperties != value) {
+          if (value == null) throw new ArgumentNullException("VisualProperties");
+          if (visualProperties != null) visualProperties.PropertyChanged -= new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          visualProperties = value;
+          visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          OnVisualPropertiesChanged();
+        }
+      }
+    }
+    private ObservableList<double> values;
+    public ObservableList<double> Values {
+      get { return values; }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "VisualProperties")]
+    private DataRowVisualProperties StorableVisualProperties {
+      get { return visualProperties; }
+      set {
+        visualProperties = value;
+        visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+      }
+    }
+    [Storable(Name = "values")]
+    private IEnumerable<double> StorableValues {
+      get { return values; }
+      set { values = new ObservableList<double>(value); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected DataRow(bool deserializing) : base(deserializing) { }
+    protected DataRow(DataRow original, Cloner cloner)
+      : base(original, cloner) {
+      this.VisualProperties = (DataRowVisualProperties)cloner.Clone(original.visualProperties);
+      this.values = new ObservableList<double>(original.values);
+    }
+    public DataRow() : this("DataRow") { }
+    public DataRow(string name)
+      : base(name) {
+      if (string.IsNullOrEmpty(name)) throw new ArgumentException("Name of a DataRow cannot be empty", name);
+      VisualProperties = new DataRowVisualProperties(name);
+      values = new ObservableList<double>();
+    }
+    public DataRow(string name, string description)
+      : base(name, description) {
+      if (string.IsNullOrEmpty(name)) throw new ArgumentException("Name of a DataRow cannot be empty", name);
+      VisualProperties = new DataRowVisualProperties(name);
+      values = new ObservableList<double>();
+    }
+    public DataRow(string name, string description, IEnumerable<double> values)
+      : base(name, description) {
+      if (string.IsNullOrEmpty(name)) throw new ArgumentException("Name of a DataRow cannot be empty", name);
+      VisualProperties = new DataRowVisualProperties(name);
+      this.values = new ObservableList<double>(values);
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (VisualProperties == null) VisualProperties = new DataRowVisualProperties();
+    }
+    #endregion
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataRow(this, cloner);
+    }
+
+    public event EventHandler VisualPropertiesChanged;
+    protected virtual void OnVisualPropertiesChanged() {
+      EventHandler handler = VisualPropertiesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnVisualPropertiesChanged();
+    }
+    protected override void OnNameChanged() {
+      base.OnNameChanged();
+      VisualProperties.DisplayName = Name;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 15719)
@@ -0,0 +1,291 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.ComponentModel;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Visual properties of a DataRow.
+  /// </summary>
+  [StorableClass]
+  public class DataRowVisualProperties : DeepCloneable, INotifyPropertyChanged {
+    #region ChartType
+    public enum DataRowChartType {
+      Line,
+      Columns,
+      Points,
+      Bars,
+      Histogram,
+      StepLine
+    }
+    #endregion
+    #region LineStyle
+    public enum DataRowLineStyle {
+      Dash,
+      DashDot,
+      DashDotDot,
+      Dot,
+      NotSet,
+      Solid
+    }
+    #endregion
+
+    private DataRowChartType chartType;
+    public DataRowChartType ChartType {
+      get { return chartType; }
+      set {
+        if (chartType != value) {
+          chartType = value;
+          OnPropertyChanged("ChartType");
+        }
+      }
+    }
+    private bool secondYAxis;
+    public bool SecondYAxis {
+      get { return secondYAxis; }
+      set {
+        if (secondYAxis != value) {
+          secondYAxis = value;
+          OnPropertyChanged("SecondYAxis");
+        }
+      }
+    }
+    private bool secondXAxis;
+    public bool SecondXAxis {
+      get { return secondXAxis; }
+      set {
+        if (secondXAxis != value) {
+          secondXAxis = value;
+          OnPropertyChanged("SecondXAxis");
+        }
+      }
+    }
+    private Color color;
+    public Color Color {
+      get { return color; }
+      set {
+        if (color != value) {
+          color = value;
+          OnPropertyChanged("Color");
+        }
+      }
+    }
+    private DataRowLineStyle lineStyle;
+    public DataRowLineStyle LineStyle {
+      get { return lineStyle; }
+      set {
+        if (lineStyle != value) {
+          lineStyle = value;
+          OnPropertyChanged("LineStyle");
+        }
+      }
+    }
+    private bool startIndexZero;
+    public bool StartIndexZero {
+      get { return startIndexZero; }
+      set {
+        if (startIndexZero != value) {
+          startIndexZero = value;
+          OnPropertyChanged("StartIndexZero");
+        }
+      }
+    }
+    private int lineWidth;
+    public int LineWidth {
+      get { return lineWidth; }
+      set {
+        if (lineWidth != value) {
+          lineWidth = value;
+          OnPropertyChanged("LineWidth");
+        }
+      }
+    }
+
+    private double scaleFactor;
+    public double ScaleFactor {
+      get { return scaleFactor; }
+      set {
+        if (scaleFactor != value) {
+          scaleFactor = value;
+          OnPropertyChanged("ScaleFactor");
+        }
+      }
+    }
+    private bool isVisibleInLegend;
+    public bool IsVisibleInLegend {
+      get { return isVisibleInLegend; }
+      set {
+        if (isVisibleInLegend != value) {
+          isVisibleInLegend = value;
+          OnPropertyChanged("IsVisibleInLegend");
+        }
+      }
+    }
+    private string displayName;
+    public string DisplayName {
+      get { return displayName == null ? String.Empty : displayName; }
+      set {
+        if (displayName != value) {
+          if (value == null && displayName != String.Empty) {
+            displayName = String.Empty;
+            OnPropertyChanged("DisplayName");
+          } else if (value != null) {
+            displayName = value;
+            OnPropertyChanged("DisplayName");
+          }
+        }
+      }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "ChartType")]
+    private DataRowChartType StorableChartType {
+      get { return chartType; }
+      set { chartType = value; }
+    }
+    [Storable(Name = "SecondYAxis")]
+    private bool StorableSecondYAxis {
+      get { return secondYAxis; }
+      set { secondYAxis = value; }
+    }
+    [Storable(Name = "SecondXAxis")]
+    private bool StorableSecondXAxis {
+      get { return secondXAxis; }
+      set { secondXAxis = value; }
+    }
+    [Storable(Name = "Color")]
+    private Color StorableColor {
+      get { return color; }
+      set { color = value; }
+    }
+    [Storable(Name = "LineStyle")]
+    private DataRowLineStyle StorableLineStyle {
+      get { return lineStyle; }
+      set { lineStyle = value; }
+    }
+    [Storable(Name = "StartIndexZero")]
+    private bool StorableStartIndexZero {
+      get { return startIndexZero; }
+      set { startIndexZero = value; }
+    }
+    [Storable(Name = "LineWidth")]
+    private int StorableLineWidth {
+      get { return lineWidth; }
+      set { lineWidth = value; }
+    }
+    [Storable(Name = "ScaleFactor")]
+    private double StorableScaleFactor {
+      get { return scaleFactor; }
+      set { scaleFactor = value; }
+    }
+    [Storable(Name = "IsVisibleInLegend", DefaultValue = true)]
+    private bool StorableIsVisibleInLegend {
+      get { return isVisibleInLegend; }
+      set { isVisibleInLegend = value; }
+    }
+    [Storable(Name = "DisplayName")]
+    private string StorableDisplayName {
+      get { return displayName; }
+      set { displayName = value; }
+    }
+    #endregion
+
+    #region Histogram Properties - Backwards Compatability
+    internal enum DataRowHistogramAggregation {
+      Overlapping,
+      SideBySide,
+      Stacked
+    }
+
+    internal int? Bins { get; private set; }
+    internal bool? ExactBins { get; private set; }
+    internal DataRowHistogramAggregation? Aggregation { get; private set; }
+
+    [Storable(Name = "Bins", AllowOneWay = true)]
+    private int StorableBins { set { Bins = value; } }
+    [Storable(Name = "ExactBins", AllowOneWay = true)]
+    private bool StorableExactBins { set { ExactBins = value; } }
+    [Storable(Name = "Aggregation", AllowOneWay = true)]
+    private DataRowHistogramAggregation StorableAggregation { set { Aggregation = value; } }
+    #endregion
+
+    [StorableConstructor]
+    protected DataRowVisualProperties(bool deserializing) : base() { }
+    protected DataRowVisualProperties(DataRowVisualProperties original, Cloner cloner)
+      : base(original, cloner) {
+      this.chartType = original.chartType;
+      this.secondYAxis = original.secondYAxis;
+      this.secondXAxis = original.secondXAxis;
+      this.color = original.color;
+      this.lineStyle = original.lineStyle;
+      this.startIndexZero = original.startIndexZero;
+      this.lineWidth = original.lineWidth;
+      this.scaleFactor = original.scaleFactor;
+      this.displayName = original.displayName;
+      this.isVisibleInLegend = original.isVisibleInLegend;
+    }
+    public DataRowVisualProperties() {
+      chartType = DataRowChartType.Line;
+      secondYAxis = false;
+      secondXAxis = false;
+      color = Color.Empty;
+      lineStyle = DataRowLineStyle.Solid;
+      startIndexZero = false;
+      lineWidth = 1;
+      scaleFactor = 1.0;
+      displayName = String.Empty;
+      isVisibleInLegend = true;
+    }
+    public DataRowVisualProperties(string displayName)
+      : this() {
+      this.displayName = displayName;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataRowVisualProperties(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      PropertyChangedEventHandler handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (secondXAxis == default(bool)
+        && lineStyle == default(DataRowLineStyle)
+        && displayName == default(string)) {
+        secondXAxis = false;
+        lineStyle = DataRowLineStyle.Solid;
+        lineWidth = 1;
+        displayName = String.Empty;
+      }
+      #endregion
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTable.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTable.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTable.cs	(revision 15719)
@@ -0,0 +1,302 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// A table of data values.
+  /// </summary>
+  [Item("DataTable", "A table of data values.")]
+  [StorableClass]
+  public class DataTable : NamedItem, IStringConvertibleMatrix {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
+    }
+
+    private DataTableVisualProperties visualProperties;
+    public DataTableVisualProperties VisualProperties {
+      get { return visualProperties; }
+      set {
+        if (visualProperties != value) {
+          if (value == null) throw new ArgumentNullException("VisualProperties");
+          if (visualProperties != null) visualProperties.PropertyChanged -= new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          visualProperties = value;
+          visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          OnVisualPropertiesChanged();
+        }
+      }
+    }
+
+    private NamedItemCollection<DataRow> rows;
+    public NamedItemCollection<DataRow> Rows {
+      get { return rows; }
+      private set {
+        if (rows != null) throw new InvalidOperationException("Rows already set");
+        rows = value;
+        if (rows != null) RegisterRowsEvents();
+      }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "VisualProperties")]
+    private DataTableVisualProperties StorableVisualProperties {
+      get { return visualProperties; }
+      set {
+        visualProperties = value;
+        visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+      }
+    }
+    [Storable(Name = "rows")]
+    private IEnumerable<DataRow> StorableRows {
+      get { return rows; }
+      set { Rows = new NamedItemCollection<DataRow>(value); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected DataTable(bool deserializing) : base(deserializing) { }
+    protected DataTable(DataTable original, Cloner cloner)
+      : base(original, cloner) {
+      VisualProperties = (DataTableVisualProperties)cloner.Clone(original.visualProperties);
+      Rows = cloner.Clone(original.rows);
+    }
+    public DataTable()
+      : base() {
+      Name = "DataTable";
+      VisualProperties = new DataTableVisualProperties();
+      Rows = new NamedItemCollection<DataRow>();
+    }
+    public DataTable(string name)
+      : base(name) {
+      VisualProperties = new DataTableVisualProperties(name);
+      Rows = new NamedItemCollection<DataRow>();
+    }
+    public DataTable(string name, string description)
+      : base(name, description) {
+      VisualProperties = new DataTableVisualProperties(name);
+      Rows = new NamedItemCollection<DataRow>();
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (VisualProperties == null) VisualProperties = new DataTableVisualProperties(name);
+      if (VisualProperties.Title == null) VisualProperties.Title = name;
+
+      #region Backwards Compatability Histogram Visual Properties 
+      var rowProperties = Rows.Select(r => r.VisualProperties).ToList();
+      if (rowProperties.Any(r => r.Bins.HasValue))
+        VisualProperties.HistogramBins = rowProperties.Where(r => r.Bins.HasValue).Max(r => r.Bins.Value);
+      if (rowProperties.Any(r => r.ExactBins.HasValue))
+        VisualProperties.HistogramExactBins = rowProperties.Where(r => r.ExactBins.HasValue).Any(r => r.ExactBins.Value);
+      if (rowProperties.Any(r => r.Aggregation.HasValue)) {
+        var maxOccurrence = rowProperties
+          .Where(r => r.Aggregation.HasValue).Select(r => r.Aggregation.Value)
+          .GroupBy(x => x).OrderByDescending(x => x.Count())
+          .First().Key;
+        VisualProperties.HistogramAggregation = (DataTableVisualProperties.DataTableHistogramAggregation)maxOccurrence;
+      }
+      #endregion
+    }
+    #endregion
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataTable(this, cloner);
+    }
+
+    public event EventHandler VisualPropertiesChanged;
+    protected virtual void OnVisualPropertiesChanged() {
+      EventHandler handler = VisualPropertiesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnVisualPropertiesChanged();
+    }
+
+    protected virtual void RegisterRowsEvents() {
+      rows.ItemsAdded += new CollectionItemsChangedEventHandler<DataRow>(rows_ItemsAdded);
+      rows.ItemsRemoved += new CollectionItemsChangedEventHandler<DataRow>(rows_ItemsRemoved);
+      rows.ItemsReplaced += new CollectionItemsChangedEventHandler<DataRow>(rows_ItemsReplaced);
+      rows.CollectionReset += new CollectionItemsChangedEventHandler<DataRow>(rows_CollectionReset);
+    }
+    private void rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      foreach (DataRow row in e.Items)
+        this.RegisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    private void rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      foreach (DataRow row in e.Items)
+        this.DeregisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    private void rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      foreach (DataRow row in e.OldItems)
+        this.DeregisterRowEvents(row);
+      foreach (DataRow row in e.Items)
+        this.RegisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    private void rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
+      foreach (DataRow row in e.OldItems)
+        this.DeregisterRowEvents(row);
+      foreach (DataRow row in e.Items)
+        this.RegisterRowEvents(row);
+
+      if (e.OldItems.Count() != e.Items.Count())
+        this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+
+    protected virtual void RegisterRowEvents(DataRow row) {
+      row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
+      row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
+      row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
+      row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
+    }
+    protected virtual void DeregisterRowEvents(DataRow row) {
+      row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
+      row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
+      row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
+      row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
+    }
+
+    private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      this.OnReset();
+    }
+    private void Values_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      this.OnReset();
+    }
+    private void Values_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      this.OnReset();
+    }
+    private void Values_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      this.OnReset();
+    }
+    private void Values_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
+      this.OnReset();
+    }
+
+    #region IStringConvertibleMatrix Members
+
+    int IStringConvertibleMatrix.Rows {
+      get { return rows.Count == 0 ? 0 : rows.Max(r => r.Values.Count); }
+      set { throw new NotSupportedException(); }
+    }
+    int IStringConvertibleMatrix.Columns {
+      get { return rows.Count; }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
+      get { return rows.Select(r => r.Name); }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.RowNames {
+      get { return Enumerable.Empty<string>(); }
+      set { throw new NotSupportedException(); }
+    }
+
+    bool IStringConvertibleMatrix.SortableView {
+      get { return true; }
+      set { throw new NotSupportedException(); }
+    }
+    bool IStringConvertibleMatrix.ReadOnly {
+      get { return true; }
+    }
+
+    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
+      if (columnIndex < rows.Count) {
+        string columnName = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
+        if (rows.ContainsKey(columnName) && rowIndex < rows[columnName].Values.Count)
+          return rows[columnName].Values[rowIndex].ToString();
+      }
+      return string.Empty;
+    }
+
+    bool IStringConvertibleMatrix.Validate(string value, out string errorMessage) {
+      throw new NotSupportedException();
+    }
+    bool IStringConvertibleMatrix.SetValue(string value, int rowIndex, int columnIndex) {
+      throw new NotSupportedException();
+    }
+
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
+      var handler = ItemChanged;
+      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      OnToStringChanged();
+    }
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      var handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnsChanged;
+    protected virtual void OnColumnsChanged() {
+      var handler = ColumnsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowsChanged;
+    protected virtual void OnRowsChanged() {
+      var handler = RowsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnNamesChanged;
+    protected virtual void OnColumnNamesChanged() {
+      var handler = ColumnNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowNamesChanged;
+    protected virtual void OnRowNamesChanged() {
+      var handler = RowNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler SortableViewChanged;
+    protected virtual void OnSortableViewChanged() {
+      var handler = SortableViewChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableHistory.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableHistory.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableHistory.cs	(revision 15719)
@@ -0,0 +1,49 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents history values of data tables.
+  /// </summary>
+  [Item("DataTableHistory", "Represents history values of data tables.")]
+  [StorableClass]
+  public class DataTableHistory : ItemCollection<DataTable> {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Cab; }
+    }
+
+    [StorableConstructor]
+    protected DataTableHistory(bool deserializing) : base(deserializing) { }
+    protected DataTableHistory(DataTableHistory original, Cloner cloner) : base(original, cloner) { }
+    public DataTableHistory() : base() { }
+    public DataTableHistory(IEnumerable<DataTable> collection) : base(new ItemCollection<DataTable>(collection)) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataTableHistory(this, cloner);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableValuesCollector.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableValuesCollector.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableValuesCollector.cs	(revision 15719)
@@ -0,0 +1,135 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which collects the actual values of parameters and adds them to a table of data values.
+  /// </summary>
+  [Item("DataTableValuesCollector", "An operator which collects the actual values of parameters and adds them to a table of data values.")]
+  [StorableClass]
+  public class DataTableValuesCollector : ValuesCollector {
+    public ValueLookupParameter<DataTable> DataTableParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["DataTable"]; }
+    }
+    private IFixedValueParameter<BoolValue> StartIndexZeroParameter {
+      get { return (FixedValueParameter<BoolValue>)Parameters["StartIndexZero"]; }
+    }
+
+    public bool StartIndexZero {
+      get { return StartIndexZeroParameter.Value.Value; }
+      set { StartIndexZeroParameter.Value.Value = value; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected DataTableValuesCollector(bool deserializing) : base(deserializing) { }
+    protected DataTableValuesCollector(DataTableValuesCollector original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataTableValuesCollector(this, cloner);
+    }
+    #endregion
+    public DataTableValuesCollector()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DataTable>("DataTable", "The table of data values where the collected values should be stored."));
+      Parameters.Add(new FixedValueParameter<BoolValue>("StartIndexZero", "True, if the collected data values should start with index 0, otherwise false.", new BoolValue(true), false));
+      StartIndexZeroParameter.Hidden = true;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code (remove with 3.4)
+      if (!Parameters.ContainsKey("StartIndexZero")) {
+        Parameters.Add(new FixedValueParameter<BoolValue>("StartIndexZero", "True, if the collected data values should start with index 0, otherwise false.", new BoolValue(true), false));
+        StartIndexZeroParameter.Hidden = true;
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      DataTable table = DataTableParameter.ActualValue;
+      if (table == null) {
+        table = new DataTable(DataTableParameter.ActualName);
+        DataTableParameter.ActualValue = table;
+      }
+
+      foreach (IParameter param in CollectedValues) {
+        ILookupParameter lookupParam = param as ILookupParameter;
+        string name = lookupParam != null ? lookupParam.TranslatedName : param.Name;
+
+        if (param.ActualValue is DoubleValue) {
+          AddValue(table, (param.ActualValue as DoubleValue).Value, name, param.Description);
+        } else if (param.ActualValue is IntValue) {
+          AddValue(table, (param.ActualValue as IntValue).Value, name, param.Description);
+        } else if (param.ActualValue is IEnumerable<DoubleValue>) {
+          IEnumerable<DoubleValue> values = (IEnumerable<DoubleValue>)param.ActualValue;
+          if (values.Count() <= 1) {
+            foreach (DoubleValue data in values)
+              AddValue(table, data != null ? data.Value : double.NaN, name, param.Description);
+          } else {
+            int counter = 1;
+            foreach (DoubleValue data in values) {
+              AddValue(table, data != null ? data.Value : double.NaN, name + " " + counter.ToString(), param.Description);
+              counter++;
+            }
+          }
+        } else if (param.ActualValue is IEnumerable<IntValue>) {
+          IEnumerable<IntValue> values = (IEnumerable<IntValue>)param.ActualValue;
+          if (values.Count() <= 1) {
+            foreach (IntValue data in values)
+              AddValue(table, data != null ? data.Value : double.NaN, name, param.Description);
+          } else {
+            int counter = 1;
+            foreach (IntValue data in values) {
+              AddValue(table, data != null ? data.Value : double.NaN, name + " " + counter.ToString(), param.Description);
+              counter++;
+            }
+          }
+        } else {
+          AddValue(table, double.NaN, name, param.Description);
+        }
+      }
+      return base.Apply();
+    }
+
+    private void AddValue(DataTable table, double data, string name, string description) {
+      DataRow row;
+      table.Rows.TryGetValue(name, out row);
+      if (row == null) {
+        row = new DataRow(name, description);
+        row.VisualProperties.StartIndexZero = StartIndexZero;
+        row.Values.Add(data);
+        table.Rows.Add(row);
+      } else {
+        row.Values.Add(data);
+      }
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs	(revision 15719)
@@ -0,0 +1,685 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.ComponentModel;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Visual properties of a DataTable.
+  /// </summary>
+  [StorableClass]
+  public class DataTableVisualProperties : DeepCloneable, INotifyPropertyChanged {
+
+    #region Histogram Aggregation
+    public enum DataTableHistogramAggregation {
+      Overlapping,
+      SideBySide,
+      Stacked
+    }
+    #endregion
+
+    private Font titleFont;
+    public Font TitleFont {
+      get { return titleFont; }
+      set {
+        if (titleFont == null || value == null
+          || titleFont.Name != value.Name || titleFont.Size != value.Size || titleFont.Style != value.Style) {
+          titleFont = value;
+          OnPropertyChanged("TitleFont");
+        }
+      }
+    }
+    private Color titleColor;
+    public Color TitleColor {
+      get { return titleColor; }
+      set {
+        if (titleColor != value) {
+          titleColor = value;
+          OnPropertyChanged("TitleFontColor");
+        }
+      }
+    }
+    private string title;
+    public string Title {
+      get { return title; }
+      set {
+        if (title != value) {
+          title = value;
+          OnPropertyChanged("Title");
+        }
+      }
+    }
+    private Font axisTitleFont;
+    public Font AxisTitleFont {
+      get { return axisTitleFont; }
+      set {
+        if (axisTitleFont == null || axisTitleFont == null
+          || axisTitleFont.Name != value.Name || axisTitleFont.Size != value.Size || axisTitleFont.Style != value.Style) {
+          axisTitleFont = value;
+          OnPropertyChanged("AxisTitleFont");
+        }
+      }
+    }
+    private Color axisTitleColor;
+    public Color AxisTitleColor {
+      get { return axisTitleColor; }
+      set {
+        if (axisTitleColor != value) {
+          axisTitleColor = value;
+          OnPropertyChanged("AxisTitleColor");
+        }
+      }
+    }
+    private string xAxisTitle;
+    public string XAxisTitle {
+      get { return xAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (xAxisTitle != value) {
+          xAxisTitle = value;
+          OnPropertyChanged("XAxisTitle");
+        }
+      }
+    }
+
+    private string yAxisTitle;
+    public string YAxisTitle {
+      get { return yAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (yAxisTitle != value) {
+          yAxisTitle = value;
+          OnPropertyChanged("YAxisTitle");
+        }
+      }
+    }
+
+    private string secondXAxisTitle;
+    public string SecondXAxisTitle {
+      get { return secondXAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (secondXAxisTitle != value) {
+          secondXAxisTitle = value;
+          OnPropertyChanged("SecondXAxisTitle");
+        }
+      }
+    }
+
+    private string secondYAxisTitle;
+    public string SecondYAxisTitle {
+      get { return secondYAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (secondYAxisTitle != value) {
+          secondYAxisTitle = value;
+          OnPropertyChanged("SecondYAxisTitle");
+        }
+      }
+    }
+
+    private bool xAxisMinimumAuto;
+    public bool XAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set {
+        if (xAxisMinimumAuto != value) {
+          xAxisMinimumAuto = value;
+          if (value) xAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool xAxisMaximumAuto;
+    public bool XAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set {
+        if (xAxisMaximumAuto != value) {
+          xAxisMaximumAuto = value;
+          if (value) xAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double xAxisMinimumFixedValue;
+    public double XAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set {
+        if (xAxisMinimumFixedValue != value) {
+          xAxisMinimumFixedValue = value;
+          OnPropertyChanged("XAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double xAxisMaximumFixedValue;
+    public double XAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set {
+        if (xAxisMaximumFixedValue != value) {
+          xAxisMaximumFixedValue = value;
+          OnPropertyChanged("XAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool secondXAxisMinimumAuto;
+    public bool SecondXAxisMinimumAuto {
+      get { return secondXAxisMinimumAuto; }
+      set {
+        if (secondXAxisMinimumAuto != value) {
+          secondXAxisMinimumAuto = value;
+          if (value) secondXAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("SecondXAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool secondXAxisMaximumAuto;
+    public bool SecondXAxisMaximumAuto {
+      get { return secondXAxisMaximumAuto; }
+      set {
+        if (secondXAxisMaximumAuto != value) {
+          secondXAxisMaximumAuto = value;
+          if (value) secondXAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("SecondXAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double secondXAxisMinimumFixedValue;
+    public double SecondXAxisMinimumFixedValue {
+      get { return secondXAxisMinimumFixedValue; }
+      set {
+        if (secondXAxisMinimumFixedValue != value) {
+          secondXAxisMinimumFixedValue = value;
+          OnPropertyChanged("SecondXAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double secondXAxisMaximumFixedValue;
+    public double SecondXAxisMaximumFixedValue {
+      get { return secondXAxisMaximumFixedValue; }
+      set {
+        if (secondXAxisMaximumFixedValue != value) {
+          secondXAxisMaximumFixedValue = value;
+          OnPropertyChanged("SecondXAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool yAxisMinimumAuto;
+    public bool YAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set {
+        if (yAxisMinimumAuto != value) {
+          yAxisMinimumAuto = value;
+          if (value) yAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool yAxisMaximumAuto;
+    public bool YAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set {
+        if (yAxisMaximumAuto != value) {
+          yAxisMaximumAuto = value;
+          if (value) yAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double yAxisMinimumFixedValue;
+    public double YAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set {
+        if (yAxisMinimumFixedValue != value) {
+          yAxisMinimumFixedValue = value;
+          OnPropertyChanged("YAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double yAxisMaximumFixedValue;
+    public double YAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set {
+        if (yAxisMaximumFixedValue != value) {
+          yAxisMaximumFixedValue = value;
+          OnPropertyChanged("YAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool secondYAxisMinimumAuto;
+    public bool SecondYAxisMinimumAuto {
+      get { return secondYAxisMinimumAuto; }
+      set {
+        if (secondYAxisMinimumAuto != value) {
+          secondYAxisMinimumAuto = value;
+          if (value) secondYAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("SecondYAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool secondYAxisMaximumAuto;
+    public bool SecondYAxisMaximumAuto {
+      get { return secondYAxisMaximumAuto; }
+      set {
+        if (secondYAxisMaximumAuto != value) {
+          secondYAxisMaximumAuto = value;
+          if (value) secondYAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("SecondYAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double secondYAxisMinimumFixedValue;
+    public double SecondYAxisMinimumFixedValue {
+      get { return secondYAxisMinimumFixedValue; }
+      set {
+        if (secondYAxisMinimumFixedValue != value) {
+          secondYAxisMinimumFixedValue = value;
+          OnPropertyChanged("SecondYAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double secondYAxisMaximumFixedValue;
+    public double SecondYAxisMaximumFixedValue {
+      get { return secondYAxisMaximumFixedValue; }
+      set {
+        if (secondYAxisMaximumFixedValue != value) {
+          secondYAxisMaximumFixedValue = value;
+          OnPropertyChanged("SecondYAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool xAxisLogScale;
+    public bool XAxisLogScale {
+      get { return xAxisLogScale; }
+      set {
+        if (xAxisLogScale == value) return;
+        xAxisLogScale = value;
+        OnPropertyChanged("XAxisLogScale");
+      }
+    }
+
+    private bool secondXAxisLogScale;
+    public bool SecondXAxisLogScale {
+      get { return secondXAxisLogScale; }
+      set {
+        if (secondXAxisLogScale == value) return;
+        secondXAxisLogScale = value;
+        OnPropertyChanged("SecondXAxisLogScale");
+      }
+    }
+
+    private bool yAxisLogScale;
+    public bool YAxisLogScale {
+      get { return yAxisLogScale; }
+      set {
+        if (yAxisLogScale == value) return;
+        yAxisLogScale = value;
+        OnPropertyChanged("YAxisLogScale");
+      }
+    }
+
+    private bool secondYAxisLogScale;
+    public bool SecondYAxisLogScale {
+      get { return secondYAxisLogScale; }
+      set {
+        if (secondYAxisLogScale == value) return;
+        secondYAxisLogScale = value;
+        OnPropertyChanged("SecondYAxisLogScale");
+      }
+    }
+
+    private int histogramBins;
+    public int HistogramBins {
+      get { return histogramBins; }
+      set {
+        if (histogramBins != value) {
+          histogramBins = value;
+          OnPropertyChanged("HistogramBins");
+        }
+      }
+    }
+
+    private bool histogramExactBins;
+    public bool HistogramExactBins {
+      get { return histogramExactBins; }
+      set {
+        if (histogramExactBins != value) {
+          histogramExactBins = value;
+          OnPropertyChanged("HistogramExactBins");
+        }
+      }
+    }
+
+    private DataTableHistogramAggregation histogramAggregation;
+    public DataTableHistogramAggregation HistogramAggregation {
+      get { return histogramAggregation; }
+      set {
+        if (histogramAggregation != value) {
+          histogramAggregation = value;
+          OnPropertyChanged("HistogramAggregation");
+        }
+      }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "TitleFont")]
+    private Font StorableTitleFont {
+      get { return titleFont; }
+      set { titleFont = value; }
+    }
+    [Storable(Name = "TitleColor")]
+    private Color StorableTitleColor {
+      get { return titleColor; }
+      set { titleColor = value; }
+    }
+    [Storable(Name = "Title")]
+    private string StorableTitle {
+      get { return title; }
+      set { title = value; }
+    }
+    [Storable(Name = "AxisTitleFont")]
+    private Font StorableAxisTitleFont {
+      get { return axisTitleFont; }
+      set { axisTitleFont = value; }
+    }
+    [Storable(Name = "AxisTitleColor")]
+    private Color StorableAxisTitleColor {
+      get { return axisTitleColor; }
+      set { axisTitleColor = value; }
+    }
+    [Storable(Name = "XAxisTitle")]
+    private string StorableXAxisTitle {
+      get { return xAxisTitle; }
+      set { xAxisTitle = value; }
+    }
+    [Storable(Name = "YAxisTitle")]
+    private string StorableYAxisTitle {
+      get { return yAxisTitle; }
+      set { yAxisTitle = value; }
+    }
+    [Storable(Name = "SecondXAxisTitle")]
+    private string StorableSecondXAxisTitle {
+      get { return secondXAxisTitle; }
+      set { secondXAxisTitle = value; }
+    }
+    [Storable(Name = "SecondYAxisTitle")]
+    private string StorableSecondYAxisTitle {
+      get { return secondYAxisTitle; }
+      set { secondYAxisTitle = value; }
+    }
+    [Storable(Name = "XAxisMinimumAuto")]
+    private bool StorableXAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set { xAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "XAxisMaximumAuto")]
+    private bool StorableXAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set { xAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "XAxisMinimumFixedValue")]
+    private double StorableXAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set { xAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "XAxisMaximumFixedValue")]
+    private double StorableXAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set { xAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "SecondXAxisMinimumAuto")]
+    private bool StorableSecondXAxisMinimumAuto {
+      get { return secondXAxisMinimumAuto; }
+      set { secondXAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "SecondXAxisMaximumAuto")]
+    private bool StorableSecondXAxisMaximumAuto {
+      get { return secondXAxisMaximumAuto; }
+      set { secondXAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "SecondXAxisMinimumFixedValue")]
+    private double StorableSecondXAxisMinimumFixedValue {
+      get { return secondXAxisMinimumFixedValue; }
+      set { secondXAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "SecondXAxisMaximumFixedValue")]
+    private double StorableSecondXAxisMaximumFixedValue {
+      get { return secondXAxisMaximumFixedValue; }
+      set { secondXAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMinimumAuto")]
+    private bool StorableYAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set { yAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "YAxisMaximumAuto")]
+    private bool StorableYAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set { yAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "YAxisMinimumFixedValue")]
+    private double StorableYAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set { yAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMaximumFixedValue")]
+    private double StorableYAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set { yAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "SecondYAxisMinimumAuto")]
+    private bool StorableSecondYAxisMinimumAuto {
+      get { return secondYAxisMinimumAuto; }
+      set { secondYAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "SecondYAxisMaximumAuto")]
+    private bool StorableSecondYAxisMaximumAuto {
+      get { return secondYAxisMaximumAuto; }
+      set { secondYAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "SecondYAxisMinimumFixedValue")]
+    private double StorableSecondYAxisMinimumFixedValue {
+      get { return secondYAxisMinimumFixedValue; }
+      set { secondYAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "SecondYAxisMaximumFixedValue")]
+    private double StorableSecondYAxisMaximumFixedValue {
+      get { return secondYAxisMaximumFixedValue; }
+      set { secondYAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "XAxisLogScale")]
+    private bool StorableXAxisLogScale {
+      get { return xAxisLogScale; }
+      set { xAxisLogScale = value; }
+    }
+    [Storable(Name = "SecondXAxisLogScale")]
+    private bool StorableSecondXAxisLogScale {
+      get { return secondXAxisLogScale; }
+      set { secondXAxisLogScale = value; }
+    }
+    [Storable(Name = "YAxisLogScale")]
+    private bool StorableYAxisLogScale {
+      get { return yAxisLogScale; }
+      set { yAxisLogScale = value; }
+    }
+    [Storable(Name = "SecondYAxisLogScale")]
+    private bool StorableSecondYAxisLogScale {
+      get { return secondYAxisLogScale; }
+      set { secondYAxisLogScale = value; }
+    }
+    [Storable(Name = "HistogramBins", DefaultValue = 10)]
+    private int StorableHistogramBins {
+      get { return histogramBins; }
+      set { histogramBins = value; }
+    }
+    [Storable(Name = "HistogramExactBins", DefaultValue = false)]
+    private bool StorableHistogramExactBins {
+      get { return histogramExactBins; }
+      set { histogramExactBins = value; }
+    }
+    [Storable(Name = "HistogramAggregation", DefaultValue = DataTableHistogramAggregation.Overlapping)]
+    private DataTableHistogramAggregation StorableHistogramAggregation {
+      get { return histogramAggregation; }
+      set { histogramAggregation = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected DataTableVisualProperties(bool deserializing) : base() { }
+    protected DataTableVisualProperties(DataTableVisualProperties original, Cloner cloner)
+      : base(original, cloner) {
+      if (original.titleFont != null)
+        this.titleFont = (Font)original.titleFont.Clone();
+      if (original.axisTitleFont != null)
+        this.axisTitleFont = (Font)original.axisTitleFont.Clone();
+      this.title = original.title;
+      this.xAxisTitle = original.xAxisTitle;
+      this.yAxisTitle = original.yAxisTitle;
+      this.secondXAxisTitle = original.secondXAxisTitle;
+      this.secondYAxisTitle = original.secondYAxisTitle;
+      this.xAxisMinimumAuto = original.xAxisMinimumAuto;
+      this.xAxisMinimumFixedValue = original.xAxisMinimumFixedValue;
+      this.xAxisMaximumAuto = original.xAxisMaximumAuto;
+      this.xAxisMaximumFixedValue = original.xAxisMaximumFixedValue;
+      this.secondXAxisMinimumAuto = original.secondXAxisMinimumAuto;
+      this.secondXAxisMinimumFixedValue = original.secondXAxisMinimumFixedValue;
+      this.secondXAxisMaximumAuto = original.secondXAxisMaximumAuto;
+      this.secondXAxisMaximumFixedValue = original.secondXAxisMaximumFixedValue;
+      this.yAxisMinimumAuto = original.yAxisMinimumAuto;
+      this.yAxisMinimumFixedValue = original.yAxisMinimumFixedValue;
+      this.yAxisMaximumAuto = original.yAxisMaximumAuto;
+      this.yAxisMaximumFixedValue = original.yAxisMaximumFixedValue;
+      this.secondYAxisMinimumAuto = original.secondYAxisMinimumAuto;
+      this.secondYAxisMinimumFixedValue = original.secondYAxisMinimumFixedValue;
+      this.secondYAxisMaximumAuto = original.secondYAxisMaximumAuto;
+      this.secondYAxisMaximumFixedValue = original.secondYAxisMaximumFixedValue;
+      this.xAxisLogScale = original.xAxisLogScale;
+      this.secondXAxisLogScale = original.secondXAxisLogScale;
+      this.yAxisLogScale = original.yAxisLogScale;
+      this.secondYAxisLogScale = original.secondYAxisLogScale;
+      this.histogramBins = original.histogramBins;
+      this.histogramExactBins = original.histogramExactBins;
+      this.histogramAggregation = original.histogramAggregation;
+    }
+    public DataTableVisualProperties() {
+      this.titleColor = Color.Black;
+      this.axisTitleColor = Color.Black;
+      this.title = string.Empty;
+      this.xAxisTitle = string.Empty;
+      this.yAxisTitle = string.Empty;
+      this.secondXAxisTitle = string.Empty;
+      this.secondYAxisTitle = string.Empty;
+      this.xAxisMinimumAuto = true;
+      this.xAxisMinimumFixedValue = double.NaN;
+      this.xAxisMaximumAuto = true;
+      this.xAxisMaximumFixedValue = double.NaN;
+      this.secondXAxisMinimumAuto = true;
+      this.secondXAxisMinimumFixedValue = double.NaN;
+      this.secondXAxisMaximumAuto = true;
+      this.secondXAxisMaximumFixedValue = double.NaN;
+      this.yAxisMinimumAuto = true;
+      this.yAxisMinimumFixedValue = double.NaN;
+      this.yAxisMaximumAuto = true;
+      this.yAxisMaximumFixedValue = double.NaN;
+      this.secondYAxisMinimumAuto = true;
+      this.secondYAxisMinimumFixedValue = double.NaN;
+      this.secondYAxisMaximumAuto = true;
+      this.secondYAxisMaximumFixedValue = double.NaN;
+      this.xAxisLogScale = false;
+      this.secondXAxisLogScale = false;
+      this.yAxisLogScale = false;
+      this.secondYAxisLogScale = false;
+      histogramBins = 10;
+      histogramExactBins = false;
+      histogramAggregation = DataTableHistogramAggregation.Overlapping;
+    }
+    public DataTableVisualProperties(string title)
+      : this() {
+      this.title = title;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataTableVisualProperties(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      // check if most of the properties that were added in Mai'11 were set to their default values, then we want to reset them to our default values
+      if (xAxisMinimumAuto == default(bool) && xAxisMaximumAuto == default(bool)
+        && yAxisMinimumAuto == default(bool) && yAxisMaximumAuto == default(bool)
+        && secondXAxisMinimumAuto == default(bool) && secondXAxisMaximumAuto == default(bool)
+        && secondYAxisMinimumAuto == default(bool) && secondYAxisMaximumAuto == default(bool)
+        && titleColor == default(Color) && axisTitleColor == default(Color)
+        && secondXAxisTitle == default(string)
+        && xAxisMinimumFixedValue == default(double) && xAxisMaximumFixedValue == default(double)
+        && yAxisMinimumFixedValue == default(double) && yAxisMaximumFixedValue == default(double)
+        && secondXAxisMinimumFixedValue == default(double) && secondXAxisMaximumFixedValue == default(double)
+        && secondYAxisMinimumFixedValue == default(double) && secondYAxisMaximumFixedValue == default(double)) {
+        titleColor = Color.Black;
+        axisTitleColor = Color.Black;
+        this.secondXAxisTitle = string.Empty;
+        this.xAxisMinimumAuto = true;
+        this.xAxisMinimumFixedValue = double.NaN;
+        this.xAxisMaximumAuto = true;
+        this.xAxisMaximumFixedValue = double.NaN;
+        this.secondXAxisMinimumAuto = true;
+        this.secondXAxisMinimumFixedValue = double.NaN;
+        this.secondXAxisMaximumAuto = true;
+        this.secondXAxisMaximumFixedValue = double.NaN;
+        this.yAxisMinimumAuto = true;
+        this.yAxisMinimumFixedValue = double.NaN;
+        this.yAxisMaximumAuto = true;
+        this.yAxisMaximumFixedValue = double.NaN;
+        this.secondYAxisMinimumAuto = true;
+        this.secondYAxisMinimumFixedValue = double.NaN;
+        this.secondYAxisMaximumAuto = true;
+        this.secondYAxisMaximumFixedValue = double.NaN;
+      }
+      #endregion
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/GanttData.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/GanttData.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/GanttData.cs	(revision 15719)
@@ -0,0 +1,188 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("Gantt Data", "Data of a Gantt visualization")]
+  [StorableClass]
+  public class GanttData : NamedItem {
+
+    [Storable]
+    private NamedItemCollection<GanttRow> rows;
+    public NamedItemCollection<GanttRow> Rows { get { return rows; } }
+
+    [Storable]
+    private ObservableDictionary<string, Color> categoryColors;
+    public ObservableDictionary<string, Color> CategoryColors { get { return categoryColors; } }
+
+    [StorableConstructor]
+    protected GanttData(bool deserializing) : base(deserializing) {}
+    protected GanttData(GanttData original, Cloner cloner)
+      : base(original, cloner) {
+      rows = cloner.Clone(original.rows);
+      categoryColors = new ObservableDictionary<string, Color>(original.categoryColors);
+    }
+    public GanttData() : this("Gantt Data", "Data of a Gantt visualization") { }
+    public GanttData(string name) : this(name, string.Empty) { }
+    public GanttData(string name, string description) : base(name, description) {
+      rows = new NamedItemCollection<GanttRow>();
+      categoryColors = new ObservableDictionary<string, Color>();
+    }
+    public GanttData(IEnumerable<GanttRow> rows) : this("Gantt Data", rows) { }
+    public GanttData(string name, IEnumerable<GanttRow> rows) : this(name, string.Empty, rows) { }
+    public GanttData(string name, string description, IEnumerable<GanttRow> rows) : base(name, description) {
+      this.rows = new NamedItemCollection<GanttRow>(rows);
+      categoryColors = new ObservableDictionary<string, Color>();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GanttData(this, cloner);
+    }
+  }
+
+  [Item("Gantt Row", "Row of a Gantt chart")]
+  [StorableClass]
+  public class GanttRow : NamedItem {
+    [Storable]
+    private ItemList<GanttItem> items;
+    public ItemList<GanttItem> Items { get { return items; } }
+
+    [StorableConstructor]
+    protected GanttRow(bool deserializing) : base(deserializing) {}
+    protected GanttRow(GanttRow original, Cloner cloner)
+      : base(original, cloner) {
+      items = cloner.Clone(original.items);
+    }
+    public GanttRow() : this("Gantt Row", "Row of a Gantt chart") { }
+    public GanttRow(string name) : this(name, string.Empty) { }
+    public GanttRow(string name, string description) : base(name, description) {
+      items = new ItemList<GanttItem>();
+    }
+    public GanttRow(IEnumerable<GanttItem> items) : this("Gantt Row", items) { }
+    public GanttRow(string name, IEnumerable<GanttItem> items) : this(name, string.Empty, items) { }
+    public GanttRow(string name, string description, IEnumerable<GanttItem> items) : base(name, description) {
+      this.items = new ItemList<GanttItem>(items);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GanttRow(this, cloner);
+    }
+  }
+
+  [Item("Gantt Item", "Item of a Gantt chart row")]
+  [StorableClass]
+  public class GanttItem : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private DateTime startDate;
+    public DateTime StartDate {
+      get { return startDate; }
+      set {
+        if (startDate == value) return;
+        startDate = value;
+        OnPropertyChanged("StartDate");
+      }
+    }
+
+    [Storable]
+    private DateTime endDate;
+    public DateTime EndDate {
+      get { return endDate; }
+      set {
+        if (endDate == value) return;
+        endDate = value;
+        OnPropertyChanged("EndDate");
+      }
+    }
+
+    [Storable]
+    private string toolTip;
+    public string ToolTip {
+      get { return toolTip; }
+      set {
+        if (toolTip == value) return;
+        toolTip = value;
+        OnPropertyChanged("ToolTip");
+      }
+    }
+
+    [Storable]
+    private string category;
+    public string Category {
+      get { return category; }
+      set {
+        if (category == value) return;
+        category = value;
+        OnPropertyChanged("Category");
+      }
+    }
+
+    [Storable]
+    private bool showLabel;
+    public bool ShowLabel {
+      get { return showLabel; }
+      set {
+        if (showLabel == value) return;
+        showLabel = value;
+        OnPropertyChanged("ShowLabel");
+      }
+    }
+
+    [StorableConstructor]
+    protected GanttItem(bool deserializing) : base(deserializing) { }
+    protected GanttItem(GanttItem original, Cloner cloner)
+      : base(original, cloner) {
+      startDate = original.startDate;
+      endDate = original.endDate;
+      toolTip = original.toolTip;
+      category = original.category;
+      showLabel = original.showLabel;
+    }
+    public GanttItem() : this(DateTime.Now, DateTime.Now) { }
+    public GanttItem(DateTime start, DateTime end) {
+      startDate = start;
+      endDate = end;
+      toolTip = string.Empty;
+      category = string.Empty;
+      showLabel = false;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GanttItem(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/HeatMap.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/HeatMap.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/HeatMap.cs	(revision 15719)
@@ -0,0 +1,159 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("HeatMap", "Represents a heat map of double values.")]
+  [StorableClass]
+  public class HeatMap : DoubleMatrix {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Gradient; }
+    }
+
+    private string title;
+    public string Title {
+      get { return title; }
+      set {
+        if (value == null) value = string.Empty;
+        if (title != value) {
+          title = value;
+          OnTitleChanged();
+        }
+      }
+    }
+    private double minimum;
+    public double Minimum {
+      get { return minimum; }
+      set {
+        if (minimum != value) {
+          minimum = value;
+          if (minimum >= maximum) Maximum = minimum + 1.0;
+          OnMinimumChanged();
+        }
+      }
+    }
+    private double maximum;
+    public double Maximum {
+      get { return maximum; }
+      set {
+        if (maximum != value) {
+          maximum = value;
+          if (maximum <= minimum) Minimum = maximum - 1.0;
+          OnMaximumChanged();
+        }
+      }
+    }
+
+    #region Storable Properties
+    [Storable(Name = "Title")]
+    private string StorableTitle {
+      get { return title; }
+      set { title = value; }
+    }
+    [Storable(Name = "Minimum")]
+    private double StorableMinimum {
+      get { return minimum; }
+      set { minimum = value; }
+    }
+    [Storable(Name = "Maximum")]
+    private double StorableMaximum {
+      get { return maximum; }
+      set { maximum = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected HeatMap(bool deserializing) : base(deserializing) { }
+    protected HeatMap(HeatMap original, Cloner cloner)
+      : base(original, cloner) {
+      this.title = original.title;
+      this.minimum = original.minimum;
+      this.maximum = original.maximum;
+    }
+    public HeatMap()
+      : base() {
+      this.title = "Heat Map";
+      this.minimum = 0.0;
+      this.maximum = 1.0;
+    }
+    public HeatMap(int rows, int columns)
+      : base(rows, columns) {
+      this.title = "Heat Map";
+      this.minimum = 0.0;
+      this.maximum = 1.0;
+    }
+    public HeatMap(int rows, int columns, string title)
+      : base(rows, columns) {
+      this.title = title == null ? string.Empty : title;
+      this.minimum = 0.0;
+      this.maximum = 1.0;
+    }
+    public HeatMap(double[,] elements)
+      : base(elements) {
+      this.title = "Heat Map";
+      this.minimum = 0.0;
+      this.maximum = 1.0;
+    }
+    public HeatMap(double[,] elements, string title)
+      : base(elements) {
+      this.title = title == null ? string.Empty : title;
+      this.minimum = 0.0;
+      this.maximum = 1.0;
+    }
+    public HeatMap(double[,] elements, string title, double minimum, double maximum)
+      : base(elements) {
+      this.title = title == null ? string.Empty : title;
+      if (minimum >= maximum) throw new ArgumentException("Minimum is larger than or equal to maximum");
+      this.minimum = minimum;
+      this.maximum = maximum;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HeatMap(this, cloner);
+    }
+
+    public override string ToString() {
+      return Title;
+    }
+
+    public event EventHandler TitleChanged;
+    protected virtual void OnTitleChanged() {
+      var handler = TitleChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler MinimumChanged;
+    protected virtual void OnMinimumChanged() {
+      var handler = MinimumChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler MaximumChanged;
+    protected virtual void OnMaximumChanged() {
+      var handler = MaximumChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/HeatMapHistory.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/HeatMapHistory.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/HeatMapHistory.cs	(revision 15719)
@@ -0,0 +1,49 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents history values of heat maps.
+  /// </summary>
+  [Item("HeatMapHistory", "Represents history values of heat maps.")]
+  [StorableClass]
+  public class HeatMapHistory : ItemCollection<HeatMap> {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Cab; }
+    }
+
+    [StorableConstructor]
+    protected HeatMapHistory(bool deserializing) : base(deserializing) { }
+    protected HeatMapHistory(HeatMapHistory original, Cloner cloner) : base(original, cloner) { }
+    public HeatMapHistory() : base() { }
+    public HeatMapHistory(IEnumerable<HeatMap> collection) : base(new ItemCollection<HeatMap>(collection)) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HeatMapHistory(this, cloner);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataRow.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataRow.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataRow.cs	(revision 15719)
@@ -0,0 +1,112 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+
+namespace HeuristicLab.Analysis {
+  [Item("IndexedDataRow", "A data row that contains a series of points.")]
+  [StorableClass]
+  public class IndexedDataRow<T> : NamedItem {
+
+    private DataRowVisualProperties visualProperties;
+    public DataRowVisualProperties VisualProperties {
+      get { return visualProperties; }
+      set {
+        if (visualProperties != value) {
+          if (value == null) throw new ArgumentNullException("VisualProperties");
+          if (visualProperties != null) visualProperties.PropertyChanged -= new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          visualProperties = value;
+          visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          OnVisualPropertiesChanged();
+        }
+      }
+    }
+    private ObservableList<Tuple<T, double>> values;
+    public ObservableList<Tuple<T, double>> Values {
+      get { return values; }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "visualProperties")]
+    private DataRowVisualProperties StorableVisualProperties {
+      get { return visualProperties; }
+      set { visualProperties = value; }
+    }
+    [Storable(Name = "values")]
+    private IEnumerable<Tuple<T, double>> StorableValues {
+      get { return values; }
+      set { values = new ObservableList<Tuple<T, double>>(value); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected IndexedDataRow(bool deserializing) : base(deserializing) { }
+    protected IndexedDataRow(IndexedDataRow<T> original, Cloner cloner)
+      : base(original, cloner) {
+      values = new ObservableList<Tuple<T, double>>(original.values.Select(x => Tuple.Create<T, double>(x.Item1, x.Item2)).ToList());
+      VisualProperties = cloner.Clone(original.visualProperties);
+    }
+    public IndexedDataRow() {
+      values = new ObservableList<Tuple<T, double>>();
+      VisualProperties = new DataRowVisualProperties();
+    }
+    public IndexedDataRow(string name)
+      : base(name) {
+      values = new ObservableList<Tuple<T, double>>();
+      VisualProperties = new DataRowVisualProperties(name);
+    }
+    public IndexedDataRow(string name, string description)
+      : base(name, description) {
+      values = new ObservableList<Tuple<T, double>>();
+      VisualProperties = new DataRowVisualProperties(name);
+    }
+    public IndexedDataRow(string name, string description, IEnumerable<Tuple<T, double>> values)
+      : base(name, description) {
+      this.values = new ObservableList<Tuple<T, double>>(values);
+      VisualProperties = new DataRowVisualProperties(name);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IndexedDataRow<T>(this, cloner);
+    }
+
+    public event EventHandler VisualPropertiesChanged;
+    protected virtual void OnVisualPropertiesChanged() {
+      EventHandler handler = VisualPropertiesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnVisualPropertiesChanged();
+    }
+    protected override void OnNameChanged() {
+      base.OnNameChanged();
+      VisualProperties.DisplayName = Name;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataTable.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataTable.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataTable.cs	(revision 15719)
@@ -0,0 +1,279 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("IndexedDataTable", "A data table where the points are also given with a certain index.")]
+  [StorableClass]
+  public class IndexedDataTable<T> : NamedItem, IStringConvertibleMatrix {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
+    }
+
+    private DataTableVisualProperties visualProperties;
+    public DataTableVisualProperties VisualProperties {
+      get { return visualProperties; }
+      set {
+        if (visualProperties != value) {
+          if (value == null) throw new ArgumentNullException("VisualProperties");
+          if (visualProperties != null) visualProperties.PropertyChanged -= new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          visualProperties = value;
+          visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          OnVisualPropertiesChanged();
+        }
+      }
+    }
+
+    private NamedItemCollection<IndexedDataRow<T>> rows;
+    public NamedItemCollection<IndexedDataRow<T>> Rows {
+      get { return rows; }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "VisualProperties")]
+    private DataTableVisualProperties StorableVisualProperties {
+      get { return visualProperties; }
+      set {
+        visualProperties = value;
+        visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+      }
+    }
+    [Storable(Name = "rows")]
+    private IEnumerable<IndexedDataRow<T>> StorableRows {
+      get { return rows; }
+      set { rows = new NamedItemCollection<IndexedDataRow<T>>(value); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected IndexedDataTable(bool deserializing) : base(deserializing) { }
+    protected IndexedDataTable(IndexedDataTable<T> original, Cloner cloner)
+      : base(original, cloner) {
+      VisualProperties = (DataTableVisualProperties)cloner.Clone(original.visualProperties);
+      rows = cloner.Clone(original.rows);
+      this.RegisterRowsEvents();
+    }
+    public IndexedDataTable()
+      : base() {
+      VisualProperties = new DataTableVisualProperties();
+      rows = new NamedItemCollection<IndexedDataRow<T>>();
+      this.RegisterRowsEvents();
+    }
+    public IndexedDataTable(string name)
+      : base(name) {
+      VisualProperties = new DataTableVisualProperties();
+      rows = new NamedItemCollection<IndexedDataRow<T>>();
+      this.RegisterRowsEvents();
+    }
+    public IndexedDataTable(string name, string description)
+      : base(name, description) {
+      VisualProperties = new DataTableVisualProperties();
+      rows = new NamedItemCollection<IndexedDataRow<T>>();
+      this.RegisterRowsEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IndexedDataTable<T>(this, cloner);
+    }
+
+    public event EventHandler VisualPropertiesChanged;
+    protected virtual void OnVisualPropertiesChanged() {
+      var handler = VisualPropertiesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnVisualPropertiesChanged();
+    }
+
+    private void RegisterRowsEvents() {
+      rows.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(RowsOnItemsAdded);
+      rows.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(RowsOnItemsRemoved);
+      rows.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(RowsOnItemsReplaced);
+      rows.CollectionReset += new CollectionItemsChangedEventHandler<IndexedDataRow<T>>(RowsOnCollectionReset);
+      foreach (var row in Rows) RegisterRowEvents(row);
+    }
+    protected virtual void RowsOnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      foreach (var row in e.Items)
+        this.RegisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    protected virtual void RowsOnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      foreach (var row in e.Items)
+        this.DeregisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    protected virtual void RowsOnItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      foreach (var row in e.OldItems)
+        this.DeregisterRowEvents(row);
+      foreach (var row in e.Items)
+        this.RegisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    protected virtual void RowsOnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedDataRow<T>> e) {
+      foreach (var row in e.OldItems)
+        this.DeregisterRowEvents(row);
+      foreach (var row in e.Items)
+        this.RegisterRowEvents(row);
+
+      if (e.OldItems.Count() != e.Items.Count())
+        this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+
+    private void RegisterRowEvents(IndexedDataRow<T> row) {
+      row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsAdded);
+      row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsMoved);
+      row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsRemoved);
+      row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsReplaced);
+      row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnCollectionReset);
+    }
+    private void DeregisterRowEvents(IndexedDataRow<T> row) {
+      row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsAdded);
+      row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsMoved);
+      row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsRemoved);
+      row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnItemsReplaced);
+      row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Tuple<T, double>>>(ValuesOnCollectionReset);
+    }
+
+    protected virtual void ValuesOnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      this.OnReset();
+    }
+    protected virtual void ValuesOnItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      this.OnReset();
+    }
+    protected virtual void ValuesOnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      this.OnReset();
+    }
+    protected virtual void ValuesOnItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      this.OnReset();
+    }
+    protected virtual void ValuesOnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Tuple<T, double>>> e) {
+      this.OnReset();
+    }
+
+    #region IStringConvertibleMatrix Members
+
+    int IStringConvertibleMatrix.Rows {
+      get { return rows.Count == 0 ? 0 : rows.Max(r => r.Values.Count); }
+      set { throw new NotSupportedException(); }
+    }
+    int IStringConvertibleMatrix.Columns {
+      get { return rows.Count * 2; }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
+      get { return rows.Select(r => new string[] { r.Name + " Index", r.Name }).SelectMany(x => x); }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.RowNames {
+      get { return new List<string>(); }
+      set { throw new NotSupportedException(); }
+    }
+
+    bool IStringConvertibleMatrix.SortableView {
+      get { return true; }
+      set { throw new NotSupportedException(); }
+    }
+    bool IStringConvertibleMatrix.ReadOnly {
+      get { return true; }
+    }
+
+    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
+      if (columnIndex < rows.Count * 2) {
+        string columnName = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
+        if (!rows.ContainsKey(columnName) && columnName.Length > " Index".Length) {
+          columnName = columnName.Substring(0, columnName.Length - " Index".Length);
+          if (rows.ContainsKey(columnName) && rowIndex < rows[columnName].Values.Count)
+            return rows[columnName].Values[rowIndex].Item1.ToString();
+          else return string.Empty;
+        } else if (rows.ContainsKey(columnName) && rowIndex < rows[columnName].Values.Count)
+          return rows[columnName].Values[rowIndex].Item2.ToString();
+      }
+      return string.Empty;
+    }
+
+    bool IStringConvertibleMatrix.Validate(string value, out string errorMessage) {
+      throw new NotSupportedException();
+    }
+    bool IStringConvertibleMatrix.SetValue(string value, int rowIndex, int columnIndex) {
+      throw new NotSupportedException();
+    }
+
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
+      var handler = ItemChanged;
+      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      OnToStringChanged();
+    }
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      var handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnsChanged;
+    protected virtual void OnColumnsChanged() {
+      var handler = ColumnsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowsChanged;
+    protected virtual void OnRowsChanged() {
+      var handler = RowsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnNamesChanged;
+    protected virtual void OnColumnNamesChanged() {
+      var handler = ColumnNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowNamesChanged;
+    protected virtual void OnRowNamesChanged() {
+      var handler = RowNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler SortableViewChanged;
+    protected virtual void OnSortableViewChanged() {
+      var handler = SortableViewChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs	(revision 15719)
@@ -0,0 +1,304 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("ScatterPlot", "A scatter plot of 2D data")]
+  [StorableClass]
+  public class ScatterPlot : NamedItem, IStringConvertibleMatrix {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
+    }
+
+    private ScatterPlotVisualProperties visualProperties;
+    public ScatterPlotVisualProperties VisualProperties {
+      get { return visualProperties; }
+      set {
+        if (visualProperties != value) {
+          if (value == null) throw new ArgumentNullException("VisualProperties");
+          if (visualProperties != null) visualProperties.PropertyChanged -= new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          visualProperties = value;
+          visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          OnVisualPropertiesChanged();
+        }
+      }
+    }
+
+    private NamedItemCollection<ScatterPlotDataRow> rows;
+    public NamedItemCollection<ScatterPlotDataRow> Rows {
+      get { return rows; }
+      private set {
+        if (rows != null) throw new InvalidOperationException("Rows already set");
+        rows = value;
+        if (rows != null) RegisterRowsEvents();
+      }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "VisualProperties")]
+    private ScatterPlotVisualProperties StorableVisualProperties {
+      get { return visualProperties; }
+      set {
+        visualProperties = value;
+        visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+      }
+    }
+    [Storable(Name = "Rows")]
+    private IEnumerable<ScatterPlotDataRow> StorableRows {
+      get { return rows; }
+      set { Rows = new NamedItemCollection<ScatterPlotDataRow>(value); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ScatterPlot(bool deserializing) : base(deserializing) { }
+    protected ScatterPlot(ScatterPlot original, Cloner cloner)
+      : base(original, cloner) {
+      VisualProperties = cloner.Clone(original.visualProperties);
+      Rows = cloner.Clone(original.rows);
+    }
+    public ScatterPlot()
+      : base() {
+      this.Name = ItemName;
+      this.Description = ItemDescription;
+      VisualProperties = new ScatterPlotVisualProperties();
+      Rows = new NamedItemCollection<ScatterPlotDataRow>();
+    }
+    public ScatterPlot(string name, string description)
+      : base(name, description) {
+      VisualProperties = new ScatterPlotVisualProperties(name);
+      Rows = new NamedItemCollection<ScatterPlotDataRow>();
+    }
+    public ScatterPlot(string name, string description, ScatterPlotVisualProperties visualProperties)
+      : base(name, description) {
+      VisualProperties = visualProperties;
+      Rows = new NamedItemCollection<ScatterPlotDataRow>();
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    private ObservableList<PointF> points;
+    [Storable(Name = "points", AllowOneWay = true)]
+    private ObservableList<PointF> StorablePoints {
+      set { points = value; }
+    }
+    private string xAxisName;
+    [Storable(Name = "xAxisName", AllowOneWay = true)]
+    private string StorableXAxisName {
+      set { xAxisName = value; }
+    }
+    private string yAxisName;
+    [Storable(Name = "yAxisName", AllowOneWay = true)]
+    private string StorableYAxisName {
+      set { yAxisName = value; }
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (VisualProperties == null) VisualProperties = new ScatterPlotVisualProperties(name);
+      if (string.IsNullOrEmpty(VisualProperties.XAxisTitle) && !string.IsNullOrEmpty(xAxisName)) VisualProperties.XAxisTitle = xAxisName;
+      if (string.IsNullOrEmpty(VisualProperties.YAxisTitle) && !string.IsNullOrEmpty(yAxisName)) VisualProperties.YAxisTitle = yAxisName;
+      if (rows == null) Rows = new NamedItemCollection<ScatterPlotDataRow>();
+      if ((Rows.Count == 0) && (points != null)) Rows.Add(new ScatterPlotDataRow(name, null, points.Select(p => new Point2D<double>(p.X, p.Y))));
+      if (string.IsNullOrEmpty(this.name)) this.name = ItemName;
+      if (string.IsNullOrEmpty(this.description)) this.description = ItemDescription;
+    }
+    #endregion
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlot(this, cloner);
+    }
+
+    public event EventHandler VisualPropertiesChanged;
+    protected virtual void OnVisualPropertiesChanged() {
+      EventHandler handler = VisualPropertiesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnVisualPropertiesChanged();
+    }
+
+    protected virtual void RegisterRowsEvents() {
+      rows.ItemsAdded += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(rows_ItemsAdded);
+      rows.ItemsRemoved += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(rows_ItemsRemoved);
+      rows.ItemsReplaced += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(rows_ItemsReplaced);
+      rows.CollectionReset += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(rows_CollectionReset);
+    }
+    private void rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      foreach (ScatterPlotDataRow row in e.Items)
+        this.RegisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    private void rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      foreach (ScatterPlotDataRow row in e.Items)
+        this.DeregisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    private void rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      foreach (ScatterPlotDataRow row in e.OldItems)
+        this.DeregisterRowEvents(row);
+      foreach (ScatterPlotDataRow row in e.Items)
+        this.RegisterRowEvents(row);
+
+      this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+    private void rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
+      foreach (ScatterPlotDataRow row in e.OldItems)
+        this.DeregisterRowEvents(row);
+      foreach (ScatterPlotDataRow row in e.Items)
+        this.RegisterRowEvents(row);
+
+      if (e.OldItems.Count() != e.Items.Count())
+        this.OnColumnsChanged();
+      this.OnColumnNamesChanged();
+      this.OnReset();
+    }
+
+    protected virtual void RegisterRowEvents(ScatterPlotDataRow row) {
+      row.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
+      row.Points.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsMoved);
+      row.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
+      row.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
+      row.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
+    }
+    protected virtual void DeregisterRowEvents(ScatterPlotDataRow row) {
+      row.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
+      row.Points.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsMoved);
+      row.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
+      row.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
+      row.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
+    }
+
+    private void Points_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      this.OnReset();
+    }
+    private void Points_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      this.OnReset();
+    }
+    private void Points_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      this.OnReset();
+    }
+    private void Points_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      this.OnReset();
+    }
+    private void Points_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
+      this.OnReset();
+    }
+
+    #region IStringConvertibleMatrix Members
+    int IStringConvertibleMatrix.Rows {
+      get { return rows.Count == 0 ? 0 : rows.Max(r => r.Points.Count); }
+      set { throw new NotSupportedException(); }
+    }
+    int IStringConvertibleMatrix.Columns {
+      get { return rows.Count; }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
+      get { return rows.Select(r => r.Name); }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.RowNames {
+      get { return Enumerable.Empty<string>(); }
+      set { throw new NotSupportedException(); }
+    }
+
+    bool IStringConvertibleMatrix.SortableView {
+      get { return true; }
+      set { throw new NotSupportedException(); }
+    }
+    bool IStringConvertibleMatrix.ReadOnly {
+      get { return true; }
+    }
+
+    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
+      if (columnIndex < rows.Count) {
+        string columnName = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
+        if (rows.ContainsKey(columnName) && rowIndex < rows[columnName].Points.Count)
+          return string.Format("{0};{1}", rows[columnName].Points[rowIndex].X, rows[columnName].Points[rowIndex].Y);
+      }
+      return string.Empty;
+    }
+
+    bool IStringConvertibleMatrix.Validate(string value, out string errorMessage) {
+      throw new NotSupportedException();
+    }
+    bool IStringConvertibleMatrix.SetValue(string value, int rowIndex, int columnIndex) {
+      throw new NotSupportedException();
+    }
+
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
+      var handler = ItemChanged;
+      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      OnToStringChanged();
+    }
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      var handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnsChanged;
+    protected virtual void OnColumnsChanged() {
+      var handler = ColumnsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowsChanged;
+    protected virtual void OnRowsChanged() {
+      var handler = RowsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnNamesChanged;
+    protected virtual void OnColumnNamesChanged() {
+      var handler = ColumnNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowNamesChanged;
+    protected virtual void OnRowNamesChanged() {
+      var handler = RowNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler SortableViewChanged;
+    protected virtual void OnSortableViewChanged() {
+      var handler = SortableViewChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRow.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRow.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRow.cs	(revision 15719)
@@ -0,0 +1,109 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// A row of data values for a scatter plot.
+  /// </summary>
+  [Item("ScatterPlotDataRow", "A row of data values for a scatter plot.")]
+  [StorableClass]
+  public class ScatterPlotDataRow : NamedItem {
+    private ScatterPlotDataRowVisualProperties visualProperties;
+    public ScatterPlotDataRowVisualProperties VisualProperties {
+      get { return visualProperties; }
+      set {
+        if (visualProperties != value) {
+          if (value == null) throw new ArgumentNullException("VisualProperties");
+          if (visualProperties != null) visualProperties.PropertyChanged -= new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          visualProperties = value;
+          visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+          OnVisualPropertiesChanged();
+        }
+      }
+    }
+    private ObservableList<Point2D<double>> points;
+    public ObservableList<Point2D<double>> Points {
+      get { return points; }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "VisualProperties")]
+    private ScatterPlotDataRowVisualProperties StorableVisualProperties {
+      get { return visualProperties; }
+      set {
+        visualProperties = value;
+        visualProperties.PropertyChanged += new PropertyChangedEventHandler(VisualProperties_PropertyChanged);
+      }
+    }
+    [Storable(Name = "Points")]
+    private IEnumerable<Point2D<double>> StorablePoints {
+      get { return points; }
+      set { points = new ObservableList<Point2D<double>>(value); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ScatterPlotDataRow(bool deserializing) : base(deserializing) { }
+    protected ScatterPlotDataRow(ScatterPlotDataRow original, Cloner cloner)
+      : base(original, cloner) {
+      VisualProperties = cloner.Clone(original.visualProperties);
+      points = new ObservableList<Point2D<double>>(original.points);
+    }
+    public ScatterPlotDataRow()
+      : base() {
+      Name = "ScatterPlotDataRow";
+      VisualProperties = new ScatterPlotDataRowVisualProperties();
+      points = new ObservableList<Point2D<double>>();
+    }
+    public ScatterPlotDataRow(string name, string description, IEnumerable<Point2D<double>> points)
+      : base(name, description) {
+      VisualProperties = new ScatterPlotDataRowVisualProperties(name);
+      this.points = new ObservableList<Point2D<double>>(points);
+    }
+    public ScatterPlotDataRow(string name, string description, IEnumerable<Point2D<double>> points, ScatterPlotDataRowVisualProperties visualProperties)
+      : base(name, description) {
+      VisualProperties = visualProperties;
+      this.points = new ObservableList<Point2D<double>>(points);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlotDataRow(this, cloner);
+    }
+
+    public event EventHandler VisualPropertiesChanged;
+    protected virtual void OnVisualPropertiesChanged() {
+      EventHandler handler = VisualPropertiesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void VisualProperties_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnVisualPropertiesChanged();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRowVisualProperties.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRowVisualProperties.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRowVisualProperties.cs	(revision 15719)
@@ -0,0 +1,247 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.ComponentModel;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Visual properties of a ScatterPlotDataRow.
+  /// </summary>
+  [StorableClass]
+  public class ScatterPlotDataRowVisualProperties : DeepCloneable, INotifyPropertyChanged {
+    #region PointStyle
+    public enum ScatterPlotDataRowPointStyle {
+      Circle,
+      Cross,
+      Diamond,
+      Square,
+      Star4,
+      Star5,
+      Star6,
+      Star10,
+      Triangle
+    }
+    #endregion
+    #region
+    public enum ScatterPlotDataRowRegressionType {
+      None,
+      Linear,
+      Polynomial,
+      Exponential,
+      Logarithmic,
+      Power
+    }
+    #endregion
+
+    private Color color;
+    public Color Color {
+      get { return color; }
+      set {
+        if (color != value) {
+          color = value;
+          OnPropertyChanged("Color");
+        }
+      }
+    }
+    private ScatterPlotDataRowPointStyle pointStyle;
+    public ScatterPlotDataRowPointStyle PointStyle {
+      get { return pointStyle; }
+      set {
+        if (pointStyle != value) {
+          pointStyle = value;
+          OnPropertyChanged("PointStyle");
+        }
+      }
+    }
+    private int pointSize;
+    public int PointSize {
+      get { return pointSize; }
+      set {
+        if (pointSize != value) {
+          pointSize = value;
+          OnPropertyChanged("PointSize");
+        }
+      }
+    }
+    private bool isVisibleInLegend;
+    public bool IsVisibleInLegend {
+      get { return isVisibleInLegend; }
+      set {
+        if (isVisibleInLegend != value) {
+          isVisibleInLegend = value;
+          OnPropertyChanged("IsVisibleInLegend");
+        }
+      }
+    }
+    private string displayName;
+    public string DisplayName {
+      get { return displayName == null ? String.Empty : displayName; }
+      set {
+        if (displayName != value) {
+          if (value == null && displayName != String.Empty) {
+            displayName = String.Empty;
+            OnPropertyChanged("DisplayName");
+          } else if (value != null) {
+            displayName = value;
+            OnPropertyChanged("DisplayName");
+          }
+        }
+      }
+    }
+    private ScatterPlotDataRowRegressionType regressionType;
+    public ScatterPlotDataRowRegressionType RegressionType {
+      get { return regressionType; }
+      set {
+        if (regressionType != value) {
+          regressionType = value;
+          OnPropertyChanged("RegressionType");
+        }
+      }
+    }
+    private int polynomialRegressionOrder;
+    public int PolynomialRegressionOrder {
+      get { return polynomialRegressionOrder; }
+      set {
+        if (polynomialRegressionOrder != value) {
+          polynomialRegressionOrder = value;
+          OnPropertyChanged("PolynomialRegressionOrder");
+        }
+      }
+    }
+    private bool isRegressionVisibleInLegend;
+    public bool IsRegressionVisibleInLegend {
+      get { return isRegressionVisibleInLegend; }
+      set {
+        if (isRegressionVisibleInLegend != value) {
+          isRegressionVisibleInLegend = value;
+          OnPropertyChanged("IsRegressionVisibleInLegend");
+        }
+      }
+    }
+    private string regressionDisplayName;
+    public string RegressionDisplayName {
+      get { return regressionDisplayName ?? string.Empty; }
+      set {
+        if (regressionDisplayName != value) {
+          if (value == null && regressionDisplayName != string.Empty) {
+            regressionDisplayName = string.Empty;
+            OnPropertyChanged("RegressionDisplayName");
+          } else if (value != null) {
+            regressionDisplayName = value;
+            OnPropertyChanged("RegressionDisplayName");
+          }
+        }
+      }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "Color")]
+    private Color StorableColor {
+      get { return color; }
+      set { color = value; }
+    }
+    [Storable(Name = "PointStyle")]
+    private ScatterPlotDataRowPointStyle StorablePointStyle {
+      get { return pointStyle; }
+      set { pointStyle = value; }
+    }
+    [Storable(Name = "PointSize")]
+    private int StorablePointSize {
+      get { return pointSize; }
+      set { pointSize = value; }
+    }
+    [Storable(Name = "IsVisibleInLegend")]
+    private bool StorableIsVisibleInLegend {
+      get { return isVisibleInLegend; }
+      set { isVisibleInLegend = value; }
+    }
+    [Storable(Name = "DisplayName")]
+    private string StorableDisplayName {
+      get { return displayName; }
+      set { displayName = value; }
+    }
+    [Storable(Name = "RegressionType")]
+    private ScatterPlotDataRowRegressionType StorableRegressionType {
+      get { return regressionType; }
+      set { regressionType = value; }
+    }
+    [Storable(Name = "PolynomialRegressionOrder", DefaultValue = 2)]
+    private int StorablePolynomialRegressionOrder {
+      get { return polynomialRegressionOrder; }
+      set { polynomialRegressionOrder = value; }
+    }
+    [Storable(Name = "IsRegressionVisibleInLegend", DefaultValue = true)]
+    private bool StorableIsRegressionVisibleInLegend {
+      get { return isRegressionVisibleInLegend; }
+      set { isRegressionVisibleInLegend = value; }
+    }
+    [Storable(Name = "RegressionDisplayName")]
+    private string StorableRegressionDisplayName {
+      get { return regressionDisplayName; }
+      set { regressionDisplayName = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ScatterPlotDataRowVisualProperties(bool deserializing) : base() { }
+    protected ScatterPlotDataRowVisualProperties(ScatterPlotDataRowVisualProperties original, Cloner cloner)
+      : base(original, cloner) {
+      this.color = original.color;
+      this.pointStyle = original.pointStyle;
+      this.pointSize = original.pointSize;
+      this.displayName = original.displayName;
+      this.isVisibleInLegend = original.isVisibleInLegend;
+      this.regressionType = original.regressionType;
+      this.polynomialRegressionOrder = original.polynomialRegressionOrder;
+      this.isRegressionVisibleInLegend = original.isRegressionVisibleInLegend;
+      this.regressionDisplayName = original.regressionDisplayName;
+    }
+    public ScatterPlotDataRowVisualProperties() {
+      color = Color.Empty;
+      pointStyle = ScatterPlotDataRowPointStyle.Circle;
+      pointSize = 3;
+      displayName = String.Empty;
+      isVisibleInLegend = true;
+      regressionType = ScatterPlotDataRowRegressionType.None;
+      polynomialRegressionOrder = 2;
+      isRegressionVisibleInLegend = true;
+      regressionDisplayName = string.Empty;
+    }
+    public ScatterPlotDataRowVisualProperties(string displayName)
+      : this() {
+      this.displayName = displayName;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlotDataRowVisualProperties(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      PropertyChangedEventHandler handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotHistory.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotHistory.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotHistory.cs	(revision 15719)
@@ -0,0 +1,49 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Represents history values of scatter plots.
+  /// </summary>
+  [Item("ScatterPlotHistory", "Represents history values of scatter plots.")]
+  [StorableClass]
+  public class ScatterPlotHistory : ItemCollection<ScatterPlot> {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Cab; }
+    }
+
+    [StorableConstructor]
+    protected ScatterPlotHistory(bool deserializing) : base(deserializing) { }
+    protected ScatterPlotHistory(ScatterPlotHistory original, Cloner cloner) : base(original, cloner) { }
+    public ScatterPlotHistory() : base() { }
+    public ScatterPlotHistory(IEnumerable<ScatterPlot> scatterPlots) : base(new ItemCollection<ScatterPlot>(scatterPlots)) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlotHistory(this, cloner);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotVisualProperties.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotVisualProperties.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotVisualProperties.cs	(revision 15719)
@@ -0,0 +1,365 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.ComponentModel;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Visual properties of a ScatterPlot.
+  /// </summary>
+  [StorableClass]
+  public class ScatterPlotVisualProperties : DeepCloneable, INotifyPropertyChanged {
+    private Font titleFont;
+    public Font TitleFont {
+      get { return titleFont; }
+      set {
+        if (titleFont == null || value == null
+          || titleFont.Name != value.Name || titleFont.Size != value.Size || titleFont.Style != value.Style) {
+          titleFont = value;
+          OnPropertyChanged("TitleFont");
+        }
+      }
+    }
+    private Color titleColor;
+    public Color TitleColor {
+      get { return titleColor; }
+      set {
+        if (titleColor != value) {
+          titleColor = value;
+          OnPropertyChanged("TitleFontColor");
+        }
+      }
+    }
+    private string title;
+    public string Title {
+      get { return title; }
+      set {
+        if (title != value) {
+          title = value;
+          OnPropertyChanged("Title");
+        }
+      }
+    }
+    private Font axisTitleFont;
+    public Font AxisTitleFont {
+      get { return axisTitleFont; }
+      set {
+        if (axisTitleFont == null || axisTitleFont == null
+          || axisTitleFont.Name != value.Name || axisTitleFont.Size != value.Size || axisTitleFont.Style != value.Style) {
+          axisTitleFont = value;
+          OnPropertyChanged("AxisTitleFont");
+        }
+      }
+    }
+    private Color axisTitleColor;
+    public Color AxisTitleColor {
+      get { return axisTitleColor; }
+      set {
+        if (axisTitleColor != value) {
+          axisTitleColor = value;
+          OnPropertyChanged("AxisTitleColor");
+        }
+      }
+    }
+    private string xAxisTitle;
+    public string XAxisTitle {
+      get { return xAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (xAxisTitle != value) {
+          xAxisTitle = value;
+          OnPropertyChanged("XAxisTitle");
+        }
+      }
+    }
+
+    private string yAxisTitle;
+    public string YAxisTitle {
+      get { return yAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (yAxisTitle != value) {
+          yAxisTitle = value;
+          OnPropertyChanged("YAxisTitle");
+        }
+      }
+    }
+
+    private bool xAxisGrid;
+    public bool XAxisGrid {
+      get { return xAxisGrid; }
+      set {
+        if (xAxisGrid != value) {
+          xAxisGrid = value;
+          OnPropertyChanged("XAxisGrid");
+        }
+      }
+    }
+
+    private bool yAxisGrid;
+    public bool YAxisGrid {
+      get { return yAxisGrid; }
+      set {
+        if (yAxisGrid != value) {
+          yAxisGrid = value;
+          OnPropertyChanged("YAxisGrid");
+        }
+      }
+    }
+
+    private bool xAxisMinimumAuto;
+    public bool XAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set {
+        if (xAxisMinimumAuto != value) {
+          xAxisMinimumAuto = value;
+          if (value) xAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool xAxisMaximumAuto;
+    public bool XAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set {
+        if (xAxisMaximumAuto != value) {
+          xAxisMaximumAuto = value;
+          if (value) xAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double xAxisMinimumFixedValue;
+    public double XAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set {
+        if (xAxisMinimumFixedValue != value) {
+          xAxisMinimumFixedValue = value;
+          OnPropertyChanged("XAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double xAxisMaximumFixedValue;
+    public double XAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set {
+        if (xAxisMaximumFixedValue != value) {
+          xAxisMaximumFixedValue = value;
+          OnPropertyChanged("XAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool yAxisMinimumAuto;
+    public bool YAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set {
+        if (yAxisMinimumAuto != value) {
+          yAxisMinimumAuto = value;
+          if (value) yAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool yAxisMaximumAuto;
+    public bool YAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set {
+        if (yAxisMaximumAuto != value) {
+          yAxisMaximumAuto = value;
+          if (value) yAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double yAxisMinimumFixedValue;
+    public double YAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set {
+        if (yAxisMinimumFixedValue != value) {
+          yAxisMinimumFixedValue = value;
+          OnPropertyChanged("YAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double yAxisMaximumFixedValue;
+    public double YAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set {
+        if (yAxisMaximumFixedValue != value) {
+          yAxisMaximumFixedValue = value;
+          OnPropertyChanged("YAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "TitleFont")]
+    private Font StorableTitleFont {
+      get { return titleFont; }
+      set { titleFont = value; }
+    }
+    [Storable(Name = "TitleColor")]
+    private Color StorableTitleColor {
+      get { return titleColor; }
+      set { titleColor = value; }
+    }
+    [Storable(Name = "Title")]
+    private string StorableTitle {
+      get { return title; }
+      set { title = value; }
+    }
+    [Storable(Name = "AxisTitleFont")]
+    private Font StorableAxisTitleFont {
+      get { return axisTitleFont; }
+      set { axisTitleFont = value; }
+    }
+    [Storable(Name = "AxisTitleColor")]
+    private Color StorableAxisTitleColor {
+      get { return axisTitleColor; }
+      set { axisTitleColor = value; }
+    }
+    [Storable(Name = "XAxisTitle")]
+    private string StorableXAxisTitle {
+      get { return xAxisTitle; }
+      set { xAxisTitle = value; }
+    }
+    [Storable(Name = "YAxisTitle")]
+    private string StorableYAxisTitle {
+      get { return yAxisTitle; }
+      set { yAxisTitle = value; }
+    }
+    [Storable(Name = "XAxisGrid")]
+    private bool StorableXAxisGrid {
+      get { return xAxisGrid; }
+      set { xAxisGrid = value; }
+    }
+    [Storable(Name = "YAxisGrid")]
+    private bool StorableYAxisGrid {
+      get { return yAxisGrid; }
+      set { yAxisGrid = value; }
+    }
+    [Storable(Name = "XAxisMinimumAuto")]
+    private bool StorableXAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set { xAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "XAxisMaximumAuto")]
+    private bool StorableXAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set { xAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "XAxisMinimumFixedValue")]
+    private double StorableXAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set { xAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "XAxisMaximumFixedValue")]
+    private double StorableXAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set { xAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMinimumAuto")]
+    private bool StorableYAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set { yAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "YAxisMaximumAuto")]
+    private bool StorableYAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set { yAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "YAxisMinimumFixedValue")]
+    private double StorableYAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set { yAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMaximumFixedValue")]
+    private double StorableYAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set { yAxisMaximumFixedValue = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ScatterPlotVisualProperties(bool deserializing) : base() { }
+    protected ScatterPlotVisualProperties(ScatterPlotVisualProperties original, Cloner cloner)
+      : base(original, cloner) {
+      if (original.titleFont != null)
+        this.titleFont = (Font)original.titleFont.Clone();
+      if (original.axisTitleFont != null)
+        this.axisTitleFont = (Font)original.axisTitleFont.Clone();
+      this.title = original.title;
+      this.xAxisTitle = original.xAxisTitle;
+      this.yAxisTitle = original.yAxisTitle;
+      this.xAxisGrid = original.xAxisGrid;
+      this.yAxisGrid = original.yAxisGrid;
+      this.xAxisMinimumAuto = original.xAxisMinimumAuto;
+      this.xAxisMinimumFixedValue = original.xAxisMinimumFixedValue;
+      this.xAxisMaximumAuto = original.xAxisMaximumAuto;
+      this.xAxisMaximumFixedValue = original.xAxisMaximumFixedValue;
+      this.yAxisMinimumAuto = original.yAxisMinimumAuto;
+      this.yAxisMinimumFixedValue = original.yAxisMinimumFixedValue;
+      this.yAxisMaximumAuto = original.yAxisMaximumAuto;
+      this.yAxisMaximumFixedValue = original.yAxisMaximumFixedValue;
+    }
+    public ScatterPlotVisualProperties() {
+      this.titleColor = Color.Black;
+      this.axisTitleColor = Color.Black;
+      this.title = string.Empty;
+      this.xAxisTitle = string.Empty;
+      this.yAxisTitle = string.Empty;
+      this.xAxisGrid = true;
+      this.yAxisGrid = true;
+      this.xAxisMinimumAuto = true;
+      this.xAxisMinimumFixedValue = double.NaN;
+      this.xAxisMaximumAuto = true;
+      this.xAxisMaximumFixedValue = double.NaN;
+      this.yAxisMinimumAuto = true;
+      this.yAxisMinimumFixedValue = double.NaN;
+      this.yAxisMaximumAuto = true;
+      this.yAxisMaximumFixedValue = double.NaN;
+    }
+    public ScatterPlotVisualProperties(string title)
+      : this() {
+      this.title = title;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlotVisualProperties(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      PropertyChangedEventHandler handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 15719)
@@ -0,0 +1,274 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Analysis</RootNamespace>
+    <AssemblyName>HeuristicLab.Analysis-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\..\trunk\bin\ALGLIB-3.7.0.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common.Resources-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="AlleleFrequencyAnalysis\Allele.cs" />
+    <Compile Include="AlleleFrequencyAnalysis\AlleleFrequency.cs" />
+    <Compile Include="AlleleFrequencyAnalysis\AlleleFrequencyAnalyzer.cs" />
+    <Compile Include="AlleleFrequencyAnalysis\AlleleFrequencyCollection.cs" />
+    <Compile Include="AlleleFrequencyAnalysis\AlleleFrequencyCollectionHistory.cs" />
+    <Compile Include="BestScopeSolutionAnalyzer.cs" />
+    <Compile Include="DataVisualization\GanttData.cs" />
+    <Compile Include="DataVisualization\IndexedDataRow.cs" />
+    <Compile Include="DataVisualization\IndexedDataTable.cs" />
+    <Compile Include="DataVisualization\ScatterPlotDataRowVisualProperties.cs" />
+    <Compile Include="DataVisualization\ScatterPlotDataRow.cs" />
+    <Compile Include="DataVisualization\ScatterPlotVisualProperties.cs" />
+    <Compile Include="DataVisualization\ScatterPlotHistory.cs" />
+    <Compile Include="DataVisualization\DataRow.cs" />
+    <Compile Include="DataVisualization\DataRowVisualProperties.cs" />
+    <Compile Include="DataVisualization\DataTable.cs" />
+    <Compile Include="DataVisualization\DataTableHistory.cs" />
+    <Compile Include="DataVisualization\DataTableValuesCollector.cs" />
+    <Compile Include="DataVisualization\DataTableVisualProperties.cs" />
+    <Compile Include="DataVisualization\HeatMap.cs" />
+    <Compile Include="DataVisualization\HeatMapHistory.cs" />
+    <Compile Include="DataVisualization\ScatterPlot.cs" />
+    <Compile Include="MultidimensionalScaling\MultidimensionalScaling.cs" />
+    <Compile Include="MultiObjective\RankBasedParetoFrontAnalyzer.cs" />
+    <Compile Include="MultiObjective\ParetoFrontAnalyzer.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="PopulationSimilarityAnalysis\PopulationDiversityAnalyzer.cs" />
+    <Compile Include="PopulationSimilarityAnalysis\PopulationSimilarityAnalyzer.cs" />
+    <Compile Include="PopulationSimilarityAnalysis\SingleObjectivePopulationDiversityAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\BestAverageWorstQualityAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\BestAverageWorstQualityCalculator.cs" />
+    <Compile Include="QualityAnalysis\BestQualityMemorizer.cs" />
+    <Compile Include="QualityAnalysis\ExpectedRuntimeHelper.cs" />
+    <Compile Include="QualityAnalysis\QualityAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\QualityDifferenceCalculator.cs" />
+    <Compile Include="MultiAnalyzer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="QualityAnalysis\QualityDistributionAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\QualityPerClockAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\QualityPerEvaluationsAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\ScaledQualityDifferenceAnalyzer.cs" />
+    <Compile Include="Statistics\BonferroniHolm.cs" />
+    <Compile Include="Statistics\EnumerableStatisticsExtension.cs" />
+    <Compile Include="Statistics\Fitting\ExpFitting.cs" />
+    <Compile Include="Statistics\Fitting\IFitting.cs" />
+    <Compile Include="Statistics\KruskalWallisTest.cs" />
+    <Compile Include="Statistics\Fitting\LinearLeastSquaresFitting.cs" />
+    <Compile Include="Statistics\Fitting\LogFitting.cs" />
+    <Compile Include="Statistics\KernelDensityEstimator.cs" />
+    <Compile Include="Statistics\PairwiseTest.cs" />
+    <Compile Include="Statistics\SampleSizeDetermination.cs" />
+    <Compile Include="ValueAnalysis\SingleValueAnalyzer.cs" />
+    <Compile Include="ValueAnalysis\MinAverageMaxValueAnalyzer.cs" />
+    <Compile Include="ValueAnalysis\MinAverageMaxValueCalculator.cs" />
+    <Compile Include="ValueAnalysis\ValueAnalyzer.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14ab8d24-25bc-400c-a846-4627aa945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiAnalyzer.cs	(revision 15719)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An analyzer which applies arbitrary many other analyzers.
+  /// </summary>
+  [Item("MultiAnalyzer", "An analyzer which applies arbitrary many other analyzers.")]
+  [StorableClass]
+  public class MultiAnalyzer : CheckedMultiOperator<IAnalyzer>, IMultiAnalyzer {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public virtual bool EnabledByDefault {
+      get { return true; }
+    }
+
+    public ValueLookupParameter<IntValue> UpdateIntervalParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public LookupParameter<IntValue> UpdateCounterParameter {
+      get { return (LookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+
+    public IntValue UpdateInterval {
+      get { return UpdateIntervalParameter.Value; }
+      set { UpdateIntervalParameter.Value = value; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected MultiAnalyzer(bool deserializing) : base(deserializing) { }
+    protected MultiAnalyzer(MultiAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiAnalyzer(this, cloner);
+    }
+    #endregion
+    public MultiAnalyzer()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("UpdateInterval", "The interval in which the contained analyzers should be applied.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the MultiAnalyzer was called since the last update.", "MultiAnalyzerUpdateCounter"));
+    }
+
+    public override IOperation InstrumentedApply() {
+      IntValue interval = UpdateIntervalParameter.ActualValue;
+      if (interval == null) interval = new IntValue(1);
+
+      IntValue counter = UpdateCounterParameter.ActualValue;
+      if (counter == null) {
+        counter = new IntValue(interval.Value);
+        UpdateCounterParameter.ActualValue = counter;
+      } else counter.Value++;
+
+      if (counter.Value == interval.Value) {
+        counter.Value = 0;
+        OperationCollection next = new OperationCollection();
+        foreach (IndexedItem<IAnalyzer> item in Operators.CheckedItems)
+          next.Add(ExecutionContext.CreateOperation(item.Value));
+        next.Add(base.InstrumentedApply());
+        return next;
+      } else {
+        return base.InstrumentedApply();
+      }
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiObjective/ParetoFrontAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiObjective/ParetoFrontAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiObjective/ParetoFrontAnalyzer.cs	(revision 15719)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("ParetoFrontAnalyzer", "Analyzer for multiobjective problems that collects and presents the current Pareto front as double matrix as well as the solution scopes that lie on the current front.")]
+  [StorableClass]
+  public abstract class ParetoFrontAnalyzer : SingleSuccessorOperator, IAnalyzer, IMultiObjectiveOperator {
+    public virtual bool EnabledByDefault {
+      get { return true; }
+    }
+
+    public IScopeTreeLookupParameter<DoubleArray> QualitiesParameter {
+      get { return (IScopeTreeLookupParameter<DoubleArray>)Parameters["Qualities"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    [StorableConstructor]
+    protected ParetoFrontAnalyzer(bool deserializing) : base(deserializing) { }
+    protected ParetoFrontAnalyzer(ParetoFrontAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public ParetoFrontAnalyzer() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("Qualities", "The vector of qualities of each solution."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The result collection to store the front to."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleArray> qualities = QualitiesParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      Analyze(qualities, results);
+      return base.Apply();
+    }
+
+    protected abstract void Analyze(ItemArray<DoubleArray> qualities, ResultCollection results);
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiObjective/RankBasedParetoFrontAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiObjective/RankBasedParetoFrontAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultiObjective/RankBasedParetoFrontAnalyzer.cs	(revision 15719)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("RankBasedParetoFrontAnalyzer", "Uses the rank value that is computed by e.g. the NSGA2's fast non dominated sort operator to collect all solutions and their qualities of front 0 (the current Pareto front).")]
+  [StorableClass]
+  public class RankBasedParetoFrontAnalyzer : ParetoFrontAnalyzer {
+    public IScopeTreeLookupParameter<IntValue> RankParameter {
+      get { return (IScopeTreeLookupParameter<IntValue>)Parameters["Rank"]; }
+    }
+
+    [StorableConstructor]
+    protected RankBasedParetoFrontAnalyzer(bool deserializing) : base(deserializing) { }
+    protected RankBasedParetoFrontAnalyzer(RankBasedParetoFrontAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public RankBasedParetoFrontAnalyzer() {
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("Rank", "The rank of solution [0..N] describes to which front it belongs."));
+    }
+
+    protected override void Analyze(ItemArray<DoubleArray> qualities, ResultCollection results) {
+      ItemArray<IntValue> ranks = RankParameter.ActualValue;
+
+      bool populationLevel = RankParameter.Depth == 1;
+
+      int objectives = qualities[0].Length;
+      int frontSize = ranks.Count(x => x.Value == 0);
+      ItemArray<IScope> paretoArchive = null;
+      if (populationLevel) paretoArchive = new ItemArray<IScope>(frontSize);
+
+      DoubleMatrix front = new DoubleMatrix(frontSize, objectives);
+      int counter = 0;
+      for (int i = 0; i < ranks.Length; i++) {
+        if (ranks[i].Value == 0) {
+          for (int k = 0; k < objectives; k++)
+            front[counter, k] = qualities[i][k];
+          if (populationLevel) {
+            paretoArchive[counter] = (IScope)ExecutionContext.Scope.SubScopes[i].Clone();
+          }
+          counter++;
+        }
+      }
+
+      front.RowNames = GetRowNames(front);
+      front.ColumnNames = GetColumnNames(front);
+
+      if (results.ContainsKey("Pareto Front"))
+        results["Pareto Front"].Value = front;
+      else results.Add(new Result("Pareto Front", front));
+
+      if (populationLevel) {
+        if (results.ContainsKey("Pareto Archive"))
+          results["Pareto Archive"].Value = paretoArchive;
+        else results.Add(new Result("Pareto Archive", paretoArchive));
+      }
+    }
+
+    private IEnumerable<string> GetRowNames(DoubleMatrix front) {
+      for (int i = 1; i <= front.Rows; i++)
+        yield return "Solution " + i.ToString();
+    }
+
+    private IEnumerable<string> GetColumnNames(DoubleMatrix front) {
+      for (int i = 1; i <= front.Columns; i++)
+        yield return "Objective " + i.ToString();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RankBasedParetoFrontAnalyzer(this, cloner);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 15719)
@@ -0,0 +1,182 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Analysis {
+  public static class MultidimensionalScaling {
+
+    /// <summary>
+    /// Performs the Kruskal-Shepard algorithm and applies a gradient descent method
+    /// to fit the coordinates such that the difference between the fit distances
+    /// and the dissimilarities becomes minimal.
+    /// </summary>
+    /// <remarks>
+    /// It will initialize the coordinates in a deterministic fashion such that all initial points are equally spaced on a circle.
+    /// </remarks>
+    /// <param name="dissimilarities">A symmetric NxN matrix that specifies the dissimilarities between each element i and j. Diagonal elements are ignored.</param>
+    /// 
+    /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns>
+    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities) {
+      if (dissimilarities == null) throw new ArgumentNullException("dissimilarities");
+      if (dissimilarities.Rows != dissimilarities.Columns) throw new ArgumentException("Dissimilarities must be a square matrix.", "dissimilarities");
+
+      int dimension = dissimilarities.Rows;
+      if (dimension == 1) return new DoubleMatrix(new double[,] { { 0, 0 } });
+      else if (dimension == 2) return new DoubleMatrix(new double[,] { { 0, 0 }, { 0, dissimilarities[0, 1] } });
+
+      DoubleMatrix coordinates = new DoubleMatrix(dimension, 2);
+      double rad = (2 * Math.PI) / coordinates.Rows;
+      for (int i = 0; i < dimension; i++) {
+        coordinates[i, 0] = 10 * Math.Cos(rad * i);
+        coordinates[i, 1] = 10 * Math.Sin(rad * i);
+      }
+
+      return KruskalShepard(dissimilarities, coordinates);
+    }
+
+    /// <summary>
+    /// Performs the Kruskal-Shepard algorithm and applies a gradient descent method
+    /// to fit the coordinates such that the difference between the fit distances
+    /// and the dissimilarities is minimal.
+    /// </summary>
+    /// <remarks>
+    /// It will use a pre-initialized x,y-coordinates matrix as a starting point of the gradient descent.
+    /// </remarks>
+    /// <param name="dissimilarities">A symmetric NxN matrix that specifies the dissimilarities between each element i and j. Diagonal elements are ignored.</param>
+    /// <param name="coordinates">The Nx2 matrix of initial coordinates.</param>
+    /// <param name="maximumIterations">The number of iterations for which the algorithm should run.
+    /// In every iteration it tries to find the best location for every item.</param>
+    /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns>
+    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities, DoubleMatrix coordinates, int maximumIterations = 10) {
+      int dimension = dissimilarities.Rows;
+      if (dimension != dissimilarities.Columns || coordinates.Rows != dimension) throw new ArgumentException("The number of coordinates and the number of rows and columns in the dissimilarities matrix do not match.");
+
+      double epsg = 1e-7;
+      double epsf = 0;
+      double epsx = 0;
+      int maxits = 0;
+
+      alglib.minlmstate state;
+      alglib.minlmreport rep;
+      for (int iterations = 0; iterations < maximumIterations; iterations++) {
+        bool changed = false;
+        for (int i = 0; i < dimension; i++) {
+          double[] c = new double[] { coordinates[i, 0], coordinates[i, 1] };
+
+          try {
+            alglib.minlmcreatevj(dimension - 1, c, out state);
+            alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
+            alglib.minlmoptimize(state, StressFitness, StressJacobian, null, new Info(coordinates, dissimilarities, i));
+            alglib.minlmresults(state, out c, out rep);
+          } catch (alglib.alglibexception) { }
+          if (!double.IsNaN(c[0]) && !double.IsNaN(c[1])) {
+            changed = changed || (coordinates[i, 0] != c[0]) || (coordinates[i, 1] != c[1]);
+            coordinates[i, 0] = c[0];
+            coordinates[i, 1] = c[1];
+          }
+        }
+        if (!changed) break;
+      }
+      return coordinates;
+    }
+
+    private static void StressFitness(double[] x, double[] fi, object obj) {
+      Info info = (obj as Info);
+      int idx = 0;
+      for (int i = 0; i < info.Coordinates.Rows; i++) {
+        if (i == info.Row) continue;
+        if (!double.IsNaN(info.Dissimilarities[info.Row, i]))
+          fi[idx++] = Stress(x, info.Dissimilarities[info.Row, i], info.Coordinates[i, 0], info.Coordinates[i, 1]);
+        else fi[idx++] = 0.0;
+      }
+    }
+
+    private static void StressJacobian(double[] x, double[] fi, double[,] jac, object obj) {
+      Info info = (obj as Info);
+      int idx = 0;
+      for (int i = 0; i < info.Coordinates.Rows; i++) {
+        if (i == info.Row) continue;
+        double c = info.Dissimilarities[info.Row, i];
+        double a = info.Coordinates[i, 0];
+        double b = info.Coordinates[i, 1];
+        if (!double.IsNaN(c)) {
+          fi[idx] = Stress(x, c, a, b); ;
+          jac[idx, 0] = 2 * (x[0] - a) * (Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1])) - c) / Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1]));
+          jac[idx, 1] = 2 * (x[1] - b) * (Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1])) - c) / Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1]));
+        } else {
+          fi[idx] = jac[idx, 0] = jac[idx, 1] = 0;
+        }
+        idx++;
+      }
+    }
+
+    private static double Stress(double[] x, double distance, double xCoord, double yCoord) {
+      return Stress(x[0], x[1], distance, xCoord, yCoord);
+    }
+
+    private static double Stress(double x, double y, double distance, double otherX, double otherY) {
+      double d = Math.Sqrt((x - otherX) * (x - otherX)
+                         + (y - otherY) * (y - otherY));
+      return (d - distance) * (d - distance);
+    }
+
+    /// <summary>
+    /// This method computes the normalized raw-stress value according to Groenen and van de Velden 2004. "Multidimensional Scaling". Technical report EI 2004-15.
+    /// </summary>
+    /// <remarks>
+    /// Throws an ArgumentException when the <paramref name="dissimilarities"/> matrix is not symmetric.
+    /// </remarks>
+    /// 
+    /// <param name="dissimilarities">The matrix with the dissimilarities.</param>
+    /// <param name="coordinates">The actual location of the points.</param>
+    /// <returns>The normalized raw-stress value that describes the goodness-of-fit between the distances in the points and the size of the dissimilarities. If the value is &lt; 0.1 the fit is generally considered good. If between 0.1 and 0.2 it is considered acceptable, but the usefulness of the scaling with higher values is doubtful.</returns>
+    public static double CalculateNormalizedStress(DoubleMatrix dissimilarities, DoubleMatrix coordinates) {
+      int dimension = dissimilarities.Rows;
+      if (dimension != dissimilarities.Columns || dimension != coordinates.Rows) throw new ArgumentException("The number of coordinates and the number of rows and columns in the dissimilarities matrix do not match.");
+      double stress = 0, normalization = 0;
+      for (int i = 0; i < dimension - 1; i++) {
+        for (int j = i + 1; j < dimension; j++) {
+          if (dissimilarities[i, j] != dissimilarities[j, i] && !(double.IsNaN(dissimilarities[i, j]) && double.IsNaN(dissimilarities[j, i])))
+            throw new ArgumentException("Dissimilarities is not a symmetric matrix.", "dissimilarities");
+          if (!double.IsNaN(dissimilarities[i, j])) {
+            stress += Stress(coordinates[i, 0], coordinates[i, 1], dissimilarities[i, j], coordinates[j, 0], coordinates[j, 1]);
+            normalization += (dissimilarities[i, j] * dissimilarities[i, j]);
+          }
+        }
+      }
+      return stress / normalization;
+    }
+
+    private class Info {
+      public DoubleMatrix Coordinates { get; set; }
+      public DoubleMatrix Dissimilarities { get; set; }
+      public int Row { get; set; }
+
+      public Info(DoubleMatrix c, DoubleMatrix d, int r) {
+        Coordinates = c;
+        Dissimilarities = d;
+        Row = r;
+      }
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Plugin.cs.frame
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Plugin.cs.frame	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Plugin.cs.frame	(revision 15719)
@@ -0,0 +1,43 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// Plugin class for HeuristicLab.Analysis plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.Analysis", "3.3.15.$WCREV$")]
+  [PluginFile("HeuristicLab.Analysis-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  public class HeuristicLabAnalysisPlugin : PluginBase {
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationDiversityAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationDiversityAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationDiversityAnalyzer.cs	(revision 15719)
@@ -0,0 +1,252 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  // use HeuristicLab.Analysis.SingleObjectivePopulationDiversityAnalyzer instead
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
+  /// <summary>
+  /// An operator for analyzing the solution diversity in a population.
+  /// </summary>
+  [Obsolete]
+  [Item("PopulationDiversityAnalyzer", "An operator for analyzing the solution diversity in a population.")]
+  [StorableClass]
+  public abstract class PopulationDiversityAnalyzer<T> : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator where T : class, IItem {
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<T> SolutionParameter {
+      get { return (ScopeTreeLookupParameter<T>)Parameters["Solution"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public ValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public ValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (ValueParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public LookupParameter<IntValue> UpdateCounterParameter {
+      get { return (LookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+
+    [StorableConstructor]
+    protected PopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    protected PopulationDiversityAnalyzer(PopulationDiversityAnalyzer<T> original, Cloner cloner) : base(original, cloner) { }
+    public PopulationDiversityAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
+      Parameters.Add(new ScopeTreeLookupParameter<T>("Solution", "The solutions whose diversity should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the population diversity analysis results should be stored."));
+      Parameters.Add(new ValueParameter<BoolValue>("StoreHistory", "True if the history of the population diversity analysis should be stored.", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", "The interval in which the population diversity analysis should be applied.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the operator was called since the last update.", "PopulationDiversityAnalyzerUpdateCounter"));
+
+      MaximizationParameter.Hidden = true;
+      SolutionParameter.Hidden = true;
+      QualityParameter.Hidden = true;
+      ResultsParameter.Hidden = true;
+      UpdateCounterParameter.Hidden = true;
+    }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval 
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      } else updateCounter.Value++;
+
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value == updateInterval) {
+        updateCounter.Value = 0;
+
+        bool max = MaximizationParameter.ActualValue.Value;
+        ItemArray<T> solutions = SolutionParameter.ActualValue;
+        ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+        bool storeHistory = StoreHistoryParameter.Value.Value;
+        int count = solutions.Length;
+
+        if (count > 1) {
+          // sort solutions by quality
+          T[] sortedSolutions = null;
+          if (max)
+            sortedSolutions = solutions
+              .Select((x, index) => new { Solution = x, Quality = qualities[index] })
+              .OrderByDescending(x => x.Quality)
+              .Select(x => x.Solution)
+              .ToArray();
+          else
+            sortedSolutions = solutions
+              .Select((x, index) => new { Solution = x, Quality = qualities[index] })
+              .OrderBy(x => x.Quality)
+              .Select(x => x.Solution)
+              .ToArray();
+
+          // calculate solution similarities
+          double[,] similarities = CalculateSimilarities(sortedSolutions);
+
+          // calculate minimum, average and maximum similarities
+          double similarity;
+          double[] minSimilarities = new double[count];
+          double[] avgSimilarities = new double[count];
+          double[] maxSimilarities = new double[count];
+          for (int i = 0; i < count; i++) {
+            minSimilarities[i] = 1;
+            avgSimilarities[i] = 0;
+            maxSimilarities[i] = 0;
+            for (int j = 0; j < count; j++) {
+              if (i != j) {
+                similarity = similarities[i, j];
+
+                if ((similarity < 0) || (similarity > 1))
+                  throw new InvalidOperationException("Solution similarities have to be in the interval [0;1].");
+
+                if (minSimilarities[i] > similarity) minSimilarities[i] = similarity;
+                avgSimilarities[i] += similarity;
+                if (maxSimilarities[i] < similarity) maxSimilarities[i] = similarity;
+              }
+            }
+            avgSimilarities[i] = avgSimilarities[i] / (count - 1);
+          }
+          double avgMinSimilarity = minSimilarities.Average();
+          double avgAvgSimilarity = avgSimilarities.Average();
+          double avgMaxSimilarity = maxSimilarities.Average();
+
+          // fetch results collection
+          ResultCollection results;
+          if (!ResultsParameter.ActualValue.ContainsKey(Name + " Results")) {
+            results = new ResultCollection();
+            ResultsParameter.ActualValue.Add(new Result(Name + " Results", results));
+          } else {
+            results = (ResultCollection)ResultsParameter.ActualValue[Name + " Results"].Value;
+          }
+
+          // store similarities
+          HeatMap similaritiesHeatMap = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
+          if (!results.ContainsKey("Solution Similarities"))
+            results.Add(new Result("Solution Similarities", similaritiesHeatMap));
+          else
+            results["Solution Similarities"].Value = similaritiesHeatMap;
+
+          // store similarities history
+          if (storeHistory) {
+            if (!results.ContainsKey("Solution Similarities History")) {
+              HeatMapHistory history = new HeatMapHistory();
+              history.Add(similaritiesHeatMap);
+              results.Add(new Result("Solution Similarities History", history));
+            } else {
+              ((HeatMapHistory)results["Solution Similarities History"].Value).Add(similaritiesHeatMap);
+            }
+          }
+
+          // store average minimum, average and maximum similarity
+          if (!results.ContainsKey("Average Minimum Solution Similarity"))
+            results.Add(new Result("Average Minimum Solution Similarity", new DoubleValue(avgMinSimilarity)));
+          else
+            ((DoubleValue)results["Average Minimum Solution Similarity"].Value).Value = avgMinSimilarity;
+
+          if (!results.ContainsKey("Average Average Solution Similarity"))
+            results.Add(new Result("Average Average Solution Similarity", new DoubleValue(avgAvgSimilarity)));
+          else
+            ((DoubleValue)results["Average Average Solution Similarity"].Value).Value = avgAvgSimilarity;
+
+          if (!results.ContainsKey("Average Maximum Solution Similarity"))
+            results.Add(new Result("Average Maximum Solution Similarity", new DoubleValue(avgMaxSimilarity)));
+          else
+            ((DoubleValue)results["Average Maximum Solution Similarity"].Value).Value = avgMaxSimilarity;
+
+          // store average minimum, average and maximum solution similarity data table
+          DataTable minAvgMaxSimilarityDataTable;
+          if (!results.ContainsKey("Average Minimum/Average/Maximum Solution Similarity")) {
+            minAvgMaxSimilarityDataTable = new DataTable("Average Minimum/Average/Maximum Solution Similarity");
+            minAvgMaxSimilarityDataTable.VisualProperties.XAxisTitle = "Iteration";
+            minAvgMaxSimilarityDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Minimum Solution Similarity", null));
+            minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].VisualProperties.StartIndexZero = true;
+            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Average Solution Similarity", null));
+            minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].VisualProperties.StartIndexZero = true;
+            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Maximum Solution Similarity", null));
+            minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].VisualProperties.StartIndexZero = true;
+            results.Add(new Result("Average Minimum/Average/Maximum Solution Similarity", minAvgMaxSimilarityDataTable));
+          } else {
+            minAvgMaxSimilarityDataTable = (DataTable)results["Average Minimum/Average/Maximum Solution Similarity"].Value;
+          }
+          minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].Values.Add(avgMinSimilarity);
+          minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].Values.Add(avgAvgSimilarity);
+          minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].Values.Add(avgMaxSimilarity);
+
+          // store minimum, average, maximum similarities data table
+          DataTable minAvgMaxSimilaritiesDataTable = new DataTable("Minimum/Average/Maximum Solution Similarities");
+          minAvgMaxSimilaritiesDataTable.VisualProperties.XAxisTitle = "Solution Index";
+          minAvgMaxSimilaritiesDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Minimum Solution Similarity", null, minSimilarities));
+          minAvgMaxSimilaritiesDataTable.Rows["Minimum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Average Solution Similarity", null, avgSimilarities));
+          minAvgMaxSimilaritiesDataTable.Rows["Average Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Maximum Solution Similarity", null, maxSimilarities));
+          minAvgMaxSimilaritiesDataTable.Rows["Maximum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities")) {
+            results.Add(new Result("Minimum/Average/Maximum Solution Similarities", minAvgMaxSimilaritiesDataTable));
+          } else {
+            results["Minimum/Average/Maximum Solution Similarities"].Value = minAvgMaxSimilaritiesDataTable;
+          }
+
+          // store minimum, average, maximum similarities history
+          if (storeHistory) {
+            if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities History")) {
+              DataTableHistory history = new DataTableHistory();
+              history.Add(minAvgMaxSimilaritiesDataTable);
+              results.Add(new Result("Minimum/Average/Maximum Solution Similarities History", history));
+            } else {
+              ((DataTableHistory)results["Minimum/Average/Maximum Solution Similarities History"].Value).Add(minAvgMaxSimilaritiesDataTable);
+            }
+          }
+        }
+      }
+      return base.Apply();
+    }
+
+    protected abstract double[,] CalculateSimilarities(T[] solutions);
+  }
+  #endregion
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs	(revision 15719)
@@ -0,0 +1,323 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator for analyzing the solution similarity in a population.
+  /// </summary>
+  [Item("PopulationSimilarityAnalyzer", "An operator for analyzing the solution similarity in a population.")]
+  [StorableClass]
+  public class PopulationSimilarityAnalyzer : SingleSuccessorOperator, IAnalyzer, ISimilarityBasedOperator {
+    private const string DiversityResultNameParameterName = "DiversityResultsName";
+    private const string ExecuteInParallelParameterName = "ExecuteInParallel";
+    private const string MaxDegreeOfParallelismParameterName = "MaxDegreeOfParallelism";
+
+    #region Backwards compatible code, remove with 3.4
+    private ISolutionSimilarityCalculator oldSimilarityCalculator;
+    [Storable(AllowOneWay = true, Name = "SimilarityCalculator")]
+    [Obsolete]
+    private ISolutionSimilarityCalculator SimilarityCalculator { set { oldSimilarityCalculator = value; } }
+    #endregion
+
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+    public ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IConstrainedValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    }
+    public IValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public IValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (IValueParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public ILookupParameter<IntValue> UpdateCounterParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+    public IFixedValueParameter<StringValue> DiversityResultNameParameter {
+      get { return (FixedValueParameter<StringValue>)Parameters[DiversityResultNameParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> ExecuteInParallelParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[ExecuteInParallelParameterName]; }
+    }
+    public IFixedValueParameter<IntValue> MaxDegreeOfParallelismParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[MaxDegreeOfParallelismParameterName]; }
+    }
+
+    public string DiversityResultName {
+      get { return DiversityResultNameParameter.Value.Value; }
+      set { DiversityResultNameParameter.Value.Value = value; }
+    }
+
+    public bool ExecuteInParallel {
+      get { return ExecuteInParallelParameter.Value.Value; }
+      set { ExecuteInParallelParameter.Value.Value = value; }
+    }
+
+    public int MaxDegreeOfParallelism {
+      get { return MaxDegreeOfParallelismParameter.Value.Value; }
+      set { MaxDegreeOfParallelismParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected PopulationSimilarityAnalyzer(bool deserializing) : base(deserializing) { }
+
+    protected PopulationSimilarityAnalyzer(PopulationSimilarityAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterParametersEventHandlers();
+    }
+
+    public PopulationSimilarityAnalyzer(IEnumerable<ISolutionSimilarityCalculator> validSimilarityCalculators)
+      : base() {
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that contains the solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the population diversity analysis results should be stored."));
+      Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate population similarity."));
+      Parameters.Add(new ValueParameter<BoolValue>("StoreHistory", "True if the history of the population diversity analysis should be stored.", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", "The interval in which the population diversity analysis should be applied.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the operator was called since the last update.", "PopulationDiversityAnalyzerUpdateCounter"));
+      Parameters.Add(new FixedValueParameter<StringValue>(DiversityResultNameParameterName, "Specifies how the diversity results should be named.", new StringValue("PopulationDiversity")));
+      Parameters.Add(new FixedValueParameter<BoolValue>(ExecuteInParallelParameterName, "Specifies whether similarity calculations should be parallelized.", new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(MaxDegreeOfParallelismParameterName, "Specifies the maximum number of threads when calculating similarities in parallel.", new IntValue(-1)));
+
+      var similarityCalculators = SimilarityCalculatorParameter.ValidValues;
+      foreach (var sc in validSimilarityCalculators) {
+        similarityCalculators.Add(sc);
+      }
+
+      ResultsParameter.Hidden = true;
+      UpdateCounterParameter.Hidden = true;
+      ExecuteInParallelParameter.Hidden = true;
+      MaxDegreeOfParallelismParameter.Hidden = true;
+
+      RegisterParametersEventHandlers();
+    }
+
+    private void RegisterParametersEventHandlers() {
+      ExecuteInParallelParameter.Value.ValueChanged += Value_ValueChanged;
+      MaxDegreeOfParallelismParameter.Value.ValueChanged += Value_ValueChanged;
+    }
+
+    private void Value_ValueChanged(object sender, EventArgs e) {
+      var similarityCalculators = SimilarityCalculatorParameter.ValidValues;
+      foreach (var similarityCalculator in similarityCalculators) {
+        similarityCalculator.ExecuteInParallel = ExecuteInParallel;
+        similarityCalculator.MaxDegreeOfParallelism = MaxDegreeOfParallelism;
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PopulationSimilarityAnalyzer(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey(DiversityResultNameParameterName))
+        Parameters.Add(new FixedValueParameter<StringValue>(DiversityResultNameParameterName, "Specifies how the diversity results should be named.", new StringValue("PopulationDiversity")));
+
+      if (!Parameters.ContainsKey("SimilarityCalculator"))
+        Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+
+      if (oldSimilarityCalculator != null)
+        SimilarityCalculatorParameter.ValidValues.Add(oldSimilarityCalculator);
+
+      if (!Parameters.ContainsKey(ExecuteInParallelParameterName)) {
+        Parameters.Add(new FixedValueParameter<BoolValue>(ExecuteInParallelParameterName,
+          "Specifies whether similarity calculations should be parallelized.", new BoolValue(false)));
+        ExecuteInParallelParameter.Hidden = true;
+      }
+      if (!Parameters.ContainsKey(MaxDegreeOfParallelismParameterName)) {
+        Parameters.Add(new FixedValueParameter<IntValue>(MaxDegreeOfParallelismParameterName,
+          "Specifies the maximum number of threads when calculating similarities in parallel.", new IntValue(-1)));
+        MaxDegreeOfParallelismParameter.Hidden = true;
+      }
+
+      RegisterParametersEventHandlers();
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      }
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value != updateInterval) {
+        updateCounter.Value++;
+        return base.Apply();
+      }
+      updateCounter.Value = 1;
+
+      bool storeHistory = StoreHistoryParameter.Value.Value;
+      int count = CurrentScopeParameter.ActualValue.SubScopes.Count;
+
+      if (count > 1) {
+        var similarityCalculator = SimilarityCalculatorParameter.Value;
+        // calculate solution similarities
+        var similarityMatrix = similarityCalculator.CalculateSolutionCrowdSimilarity(CurrentScopeParameter.ActualValue);
+        double[,] similarities = new double[similarityMatrix.Length, similarityMatrix[0].Length];
+        for (int i = 0; i < similarityMatrix.Length; i++)
+          for (int j = 0; j < similarityMatrix[0].Length; j++)
+            similarities[i, j] = similarityMatrix[i][j];
+
+        // calculate minimum, average and maximum similarities
+        double similarity;
+        double[] minSimilarities = new double[count];
+        double[] avgSimilarities = new double[count];
+        double[] maxSimilarities = new double[count];
+        for (int i = 0; i < count; i++) {
+          minSimilarities[i] = 1;
+          avgSimilarities[i] = 0;
+          maxSimilarities[i] = 0;
+          for (int j = 0; j < count; j++) {
+            if (i != j) {
+              similarity = similarities[i, j];
+
+              if ((similarity < 0) || (similarity > 1))
+                throw new InvalidOperationException("Solution similarities have to be in the interval [0;1].");
+
+              if (minSimilarities[i] > similarity) minSimilarities[i] = similarity;
+              avgSimilarities[i] += similarity;
+              if (maxSimilarities[i] < similarity) maxSimilarities[i] = similarity;
+            }
+          }
+          avgSimilarities[i] = avgSimilarities[i] / (count - 1);
+        }
+        double avgMinSimilarity = minSimilarities.Average();
+        double avgAvgSimilarity = avgSimilarities.Average();
+        double avgMaxSimilarity = maxSimilarities.Average();
+
+        // fetch results collection
+        ResultCollection results;
+        if (!ResultsParameter.ActualValue.ContainsKey(DiversityResultName)) {
+          results = new ResultCollection();
+          ResultsParameter.ActualValue.Add(new Result(DiversityResultName, results));
+        } else {
+          results = (ResultCollection)ResultsParameter.ActualValue[DiversityResultName].Value;
+        }
+
+        // store similarities
+        HeatMap similaritiesHeatMap = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
+        if (!results.ContainsKey("Solution Similarities"))
+          results.Add(new Result("Solution Similarities", similaritiesHeatMap));
+        else
+          results["Solution Similarities"].Value = similaritiesHeatMap;
+
+        // store similarities history
+        if (storeHistory) {
+          if (!results.ContainsKey("Solution Similarities History")) {
+            HeatMapHistory history = new HeatMapHistory();
+            history.Add(similaritiesHeatMap);
+            results.Add(new Result("Solution Similarities History", history));
+          } else {
+            ((HeatMapHistory)results["Solution Similarities History"].Value).Add(similaritiesHeatMap);
+          }
+        }
+
+        // store average minimum, average and maximum similarity
+        if (!results.ContainsKey("Average Minimum Solution Similarity"))
+          results.Add(new Result("Average Minimum Solution Similarity", new DoubleValue(avgMinSimilarity)));
+        else
+          ((DoubleValue)results["Average Minimum Solution Similarity"].Value).Value = avgMinSimilarity;
+
+        if (!results.ContainsKey("Average Average Solution Similarity"))
+          results.Add(new Result("Average Average Solution Similarity", new DoubleValue(avgAvgSimilarity)));
+        else
+          ((DoubleValue)results["Average Average Solution Similarity"].Value).Value = avgAvgSimilarity;
+
+        if (!results.ContainsKey("Average Maximum Solution Similarity"))
+          results.Add(new Result("Average Maximum Solution Similarity", new DoubleValue(avgMaxSimilarity)));
+        else
+          ((DoubleValue)results["Average Maximum Solution Similarity"].Value).Value = avgMaxSimilarity;
+
+        // store average minimum, average and maximum solution similarity data table
+        DataTable minAvgMaxSimilarityDataTable;
+        if (!results.ContainsKey("Average Minimum/Average/Maximum Solution Similarity")) {
+          minAvgMaxSimilarityDataTable = new DataTable("Average Minimum/Average/Maximum Solution Similarity");
+          minAvgMaxSimilarityDataTable.VisualProperties.XAxisTitle = "Iteration";
+          minAvgMaxSimilarityDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Minimum Solution Similarity", null));
+          minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].VisualProperties.StartIndexZero = true;
+          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Average Solution Similarity", null));
+          minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].VisualProperties.StartIndexZero = true;
+          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Maximum Solution Similarity", null));
+          minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].VisualProperties.StartIndexZero = true;
+          results.Add(new Result("Average Minimum/Average/Maximum Solution Similarity", minAvgMaxSimilarityDataTable));
+        } else {
+          minAvgMaxSimilarityDataTable = (DataTable)results["Average Minimum/Average/Maximum Solution Similarity"].Value;
+        }
+        minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].Values.Add(avgMinSimilarity);
+        minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].Values.Add(avgAvgSimilarity);
+        minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].Values.Add(avgMaxSimilarity);
+
+        // store minimum, average, maximum similarities data table
+        DataTable minAvgMaxSimilaritiesDataTable = new DataTable("Minimum/Average/Maximum Solution Similarities");
+        minAvgMaxSimilaritiesDataTable.VisualProperties.XAxisTitle = "Solution Index";
+        minAvgMaxSimilaritiesDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Minimum Solution Similarity", null, minSimilarities));
+        minAvgMaxSimilaritiesDataTable.Rows["Minimum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Average Solution Similarity", null, avgSimilarities));
+        minAvgMaxSimilaritiesDataTable.Rows["Average Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Maximum Solution Similarity", null, maxSimilarities));
+        minAvgMaxSimilaritiesDataTable.Rows["Maximum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities")) {
+          results.Add(new Result("Minimum/Average/Maximum Solution Similarities", minAvgMaxSimilaritiesDataTable));
+        } else {
+          results["Minimum/Average/Maximum Solution Similarities"].Value = minAvgMaxSimilaritiesDataTable;
+        }
+
+        // store minimum, average, maximum similarities history
+        if (storeHistory) {
+          if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities History")) {
+            DataTableHistory history = new DataTableHistory();
+            history.Add(minAvgMaxSimilaritiesDataTable);
+            results.Add(new Result("Minimum/Average/Maximum Solution Similarities History", history));
+          } else {
+            ((DataTableHistory)results["Minimum/Average/Maximum Solution Similarities History"].Value).Add(minAvgMaxSimilaritiesDataTable);
+          }
+        }
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/SingleObjectivePopulationDiversityAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/SingleObjectivePopulationDiversityAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/SingleObjectivePopulationDiversityAnalyzer.cs	(revision 15719)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Analysis {
+  // use HeuristicLab.Analysis.PopulationSimilarityAnalyzer instead
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
+  /// <summary>
+  /// An operator for analyzing the solution diversity in a population.
+  /// </summary>
+  [Obsolete]
+  [NonDiscoverableType]
+  [Item("SingleObjectivePopulationDiversityAnalyzer", "An operator for analyzing the solution diversity in a population.")]
+  [StorableClass]
+  public class SingleObjectivePopulationDiversityAnalyzer : PopulationSimilarityAnalyzer {
+    [StorableConstructor]
+    protected SingleObjectivePopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    protected SingleObjectivePopulationDiversityAnalyzer(SingleObjectivePopulationDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectivePopulationDiversityAnalyzer(this, cloner);
+    }
+  }
+  #endregion
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Properties/AssemblyInfo.cs.frame	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Properties/AssemblyInfo.cs.frame	(revision 15719)
@@ -0,0 +1,56 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Analysis")]
+[assembly: AssemblyDescription("HeuristicLab algorithm analysis classes")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b987398b-693f-41e6-8a90-10374e9464ba")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.15.$WCREV$")]
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestAverageWorstQualityAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestAverageWorstQualityAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestAverageWorstQualityAnalyzer.cs	(revision 15719)
@@ -0,0 +1,197 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes the best, average and worst quality of solutions in the scope tree.
+  /// </summary>
+  [Item("BestAverageWorstQualityAnalyzer", "An operator which analyzes the best, average and worst quality of solutions in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstQualityAnalyzer : AlgorithmOperator, IAnalyzer, ISingleObjectiveOperator {
+    #region Parameter properties
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentBestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentBestQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAverageQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAverageQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentWorstQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstQuality"]; }
+    }
+    public ValueLookupParameter<DataTable> QualitiesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Qualities"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AbsoluteDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AbsoluteDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<PercentValue> RelativeDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<PercentValue>)Parameters["RelativeDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private BestQualityMemorizer BestQualityMemorizer {
+      get { return (BestQualityMemorizer)OperatorGraph.InitialOperator; }
+    }
+    private BestAverageWorstQualityCalculator BestAverageWorstQualityCalculator {
+      get { return (BestAverageWorstQualityCalculator)BestQualityMemorizer.Successor; }
+    }
+    #endregion
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private BestAverageWorstQualityAnalyzer(bool deserializing) : base(deserializing) { }
+    private BestAverageWorstQualityAnalyzer(BestAverageWorstQualityAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      Initialize();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstQualityAnalyzer(this, cloner);
+    }
+    #endregion
+    public BestAverageWorstQualityAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestKnownQuality", "The best known quality value found so far."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestQuality", "The best quality value found in the current run."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentBestQuality", "The best quality value found in the current population."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageQuality", "The average quality value of all solutions in the current population."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstQuality", "The worst quality value found in the current population."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Qualities", "The data table to store the current best, current average, current worst, best and best known quality value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", "The absolute difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", "The relative difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The results collection where the analysis values should be stored."));
+
+      BestQualityParameter.Hidden = true;
+      CurrentBestQualityParameter.Hidden = true;
+      CurrentAverageQualityParameter.Hidden = true;
+      CurrentWorstQualityParameter.Hidden = true;
+      QualitiesParameter.Hidden = true;
+      AbsoluteDifferenceBestKnownToBestParameter.Hidden = true;
+      RelativeDifferenceBestKnownToBestParameter.Hidden = true;
+      #endregion
+
+      #region Create operators
+      BestQualityMemorizer bestQualityMemorizer = new BestQualityMemorizer();
+      BestAverageWorstQualityCalculator bestAverageWorstQualityCalculator = new BestAverageWorstQualityCalculator();
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      QualityDifferenceCalculator qualityDifferenceCalculator = new QualityDifferenceCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      bestQualityMemorizer.BestQualityParameter.ActualName = BestQualityParameter.Name;
+      bestQualityMemorizer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      bestQualityMemorizer.QualityParameter.ActualName = QualityParameter.Name;
+      bestQualityMemorizer.QualityParameter.Depth = QualityParameter.Depth;
+
+      bestAverageWorstQualityCalculator.AverageQualityParameter.ActualName = CurrentAverageQualityParameter.Name;
+      bestAverageWorstQualityCalculator.BestQualityParameter.ActualName = CurrentBestQualityParameter.Name;
+      bestAverageWorstQualityCalculator.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      bestAverageWorstQualityCalculator.QualityParameter.ActualName = QualityParameter.Name;
+      bestAverageWorstQualityCalculator.QualityParameter.Depth = QualityParameter.Depth;
+      bestAverageWorstQualityCalculator.WorstQualityParameter.ActualName = CurrentWorstQualityParameter.Name;
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestQuality", null, CurrentBestQualityParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageQuality", null, CurrentAverageQualityParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstQuality", null, CurrentWorstQualityParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestQuality", null, BestQualityParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestKnownQuality", null, BestKnownQualityParameter.Name));
+      dataTableValuesCollector.DataTableParameter.ActualName = QualitiesParameter.Name;
+
+      qualityDifferenceCalculator.AbsoluteDifferenceParameter.ActualName = AbsoluteDifferenceBestKnownToBestParameter.Name;
+      qualityDifferenceCalculator.FirstQualityParameter.ActualName = BestKnownQualityParameter.Name;
+      qualityDifferenceCalculator.RelativeDifferenceParameter.ActualName = RelativeDifferenceBestKnownToBestParameter.Name;
+      qualityDifferenceCalculator.SecondQualityParameter.ActualName = BestQualityParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestQuality", null, CurrentBestQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageQuality", null, CurrentAverageQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstQuality", null, CurrentWorstQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestQuality", null, BestQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestKnownQuality", null, BestKnownQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", null, AbsoluteDifferenceBestKnownToBestParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", null, RelativeDifferenceBestKnownToBestParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(QualitiesParameter.Name));
+      resultsCollector.ResultsParameter.ActualName = ResultsParameter.Name;
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestQualityMemorizer;
+      bestQualityMemorizer.Successor = bestAverageWorstQualityCalculator;
+      bestAverageWorstQualityCalculator.Successor = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = qualityDifferenceCalculator;
+      qualityDifferenceCalculator.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (Parameters["Results"] is ValueLookupParameter<VariableCollection>) {
+        Parameters.Remove("Results");
+        Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The results collection where the analysis values should be stored."));
+      }
+      #endregion
+    }
+
+    private void Initialize() {
+      QualityParameter.DepthChanged += new EventHandler(QualityParameter_DepthChanged);
+    }
+
+    private void QualityParameter_DepthChanged(object sender, System.EventArgs e) {
+      BestQualityMemorizer.QualityParameter.Depth = QualityParameter.Depth;
+      BestAverageWorstQualityCalculator.QualityParameter.Depth = QualityParameter.Depth;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestAverageWorstQualityCalculator.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestAverageWorstQualityCalculator.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestAverageWorstQualityCalculator.cs	(revision 15719)
@@ -0,0 +1,105 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which calculates the best, average and worst quality of solutions in the scope tree.
+  /// </summary>
+  [Item("BestAverageWorstQualityCalculator", "An operator which calculates the best, average and worst quality of solutions in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstQualityCalculator : SingleSuccessorOperator, ISingleObjectiveOperator {
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> WorstQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["WorstQuality"]; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private BestAverageWorstQualityCalculator(bool deserializing) : base(deserializing) { }
+    private BestAverageWorstQualityCalculator(BestAverageWorstQualityCalculator original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstQualityCalculator(this, cloner);
+    }
+    #endregion
+    public BestAverageWorstQualityCalculator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the current problem is a maximization problem, otherwise false."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value contained in the scope tree which represents the solution quality."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestQuality", "The quality value of the best solution."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageQuality", "The average quality of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("WorstQuality", "The quality value of the worst solution."));
+
+      BestQualityParameter.Hidden = true;
+      AverageQualityParameter.Hidden = true;
+      WorstQualityParameter.Hidden = true;
+    }
+
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+
+      if (qualities.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < qualities.Length; i++) {
+          if (qualities[i].Value < min) min = qualities[i].Value;
+          if (qualities[i].Value > max) max = qualities[i].Value;
+          sum += qualities[i].Value;
+        }
+        if (!maximization) {
+          double temp = min;
+          min = max;
+          max = temp;
+        }
+
+        DoubleValue best = BestQualityParameter.ActualValue;
+        if (best == null) BestQualityParameter.ActualValue = new DoubleValue(max);
+        else best.Value = max;
+        DoubleValue average = AverageQualityParameter.ActualValue;
+        if (average == null) AverageQualityParameter.ActualValue = new DoubleValue(sum / qualities.Length);
+        else average.Value = sum / qualities.Length;
+        DoubleValue worst = WorstQualityParameter.ActualValue;
+        if (worst == null) WorstQualityParameter.ActualValue = new DoubleValue(min);
+        else worst.Value = min;
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestQualityMemorizer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestQualityMemorizer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/BestQualityMemorizer.cs	(revision 15719)
@@ -0,0 +1,80 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator that updates the best quality found so far with those qualities contained in the scope tree.
+  /// </summary>
+  [Item("BestQualityMemorizer", "An operator that updates the best quality found so far with those qualities contained in the scope tree.")]
+  [StorableClass]
+  public class BestQualityMemorizer : SingleSuccessorOperator, ISingleObjectiveOperator {
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected BestQualityMemorizer(bool deserializing) : base(deserializing) { }
+    protected BestQualityMemorizer(BestQualityMemorizer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestQualityMemorizer(this, cloner);
+    }
+    #endregion
+    public BestQualityMemorizer()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the current problem is a maximization problem, otherwise false."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value contained in the scope tree which represents the solution quality."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestQuality", "The quality value of the best solution."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      DoubleValue best = BestQualityParameter.ActualValue;
+      double max = (best != null) ? (best.Value) : ((maximization) ? (double.MinValue) : (double.MaxValue));
+
+      foreach (DoubleValue quality in qualities)
+        if (IsBetter(maximization, quality.Value, max)) max = quality.Value;
+
+      if (best == null) BestQualityParameter.ActualValue = new DoubleValue(max);
+      else best.Value = max;
+      return base.Apply();
+    }
+
+    private bool IsBetter(bool maximization, double quality, double max) {
+      return (maximization && quality > max || !maximization && quality < max);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/ExpectedRuntimeHelper.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/ExpectedRuntimeHelper.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/ExpectedRuntimeHelper.cs	(revision 15719)
@@ -0,0 +1,62 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Optimization;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace HeuristicLab.Analysis {
+  public static class ExpectedRuntimeHelper {
+    public static ErtCalculationResult CalculateErt(IEnumerable<IEnumerable<Tuple<double, double>>> convGraphs, double target, bool maximization) {
+      var successful = new List<double>();
+      var unsuccessful = new List<double>();
+      foreach (var graph in convGraphs) {
+        var targetAchieved = false;
+        var lastEffort = double.MaxValue;
+        foreach (var v in graph) {
+          if (maximization && v.Item2 >= target || !maximization && v.Item2 <= target) {
+            successful.Add(v.Item1);
+            targetAchieved = true;
+            break;
+          }
+          lastEffort = v.Item1;
+        }
+        if (!targetAchieved) unsuccessful.Add(lastEffort);
+      }
+
+      var ert = double.PositiveInfinity;
+
+      var nRuns = successful.Count + unsuccessful.Count;
+      if (successful.Count > 0) {
+        var succAvg = successful.Average();
+        var succDev = successful.StandardDeviation() + 1e-7;
+        successful.RemoveAll(x => x < succAvg - 2 * succDev);
+        unsuccessful.RemoveAll(x => x < succAvg - 2 * succDev);
+        nRuns = successful.Count + unsuccessful.Count;
+
+        ert = successful.Average() / (successful.Count / (double)nRuns);
+      }
+      return new ErtCalculationResult(successful.Count, nRuns, ert);
+    }
+
+    public static ErtCalculationResult CalculateErt(List<IRun> runs, string indexedDataTableName, double target, bool maximization) {
+      return CalculateErt(runs.Select(r => ((IndexedDataTable<double>)r.Results[indexedDataTableName]).Rows.First().Values), target, maximization);
+    }
+  }
+
+  public struct ErtCalculationResult {
+    public readonly int SuccessfulRuns;
+    public readonly int TotalRuns;
+    public readonly double ExpectedRuntime;
+
+    public ErtCalculationResult(int successful, int total, double ert) {
+      SuccessfulRuns = successful;
+      TotalRuns = total;
+      ExpectedRuntime = ert;
+    }
+
+    public override string ToString() {
+      return ExpectedRuntime.ToString("##,0.0", CultureInfo.CurrentCulture.NumberFormat);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityAnalyzer.cs	(revision 15719)
@@ -0,0 +1,174 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes the quality of solutions in the scope tree.
+  /// </summary>
+  [Item("QualityAnalyzer", "An operator which analyzes the quality of solutions in the scope tree.")]
+  [StorableClass]
+  public sealed class QualityAnalyzer : AlgorithmOperator, IAnalyzer, ISingleObjectiveOperator {
+    #region Parameter properties
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ValueLookupParameter<DataTable> QualitiesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Qualities"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AbsoluteDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AbsoluteDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<PercentValue> RelativeDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<PercentValue>)Parameters["RelativeDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private BestQualityMemorizer BestQualityMemorizer {
+      get { return (BestQualityMemorizer)OperatorGraph.InitialOperator; }
+    }
+    private BestQualityMemorizer BestKnownQualityMemorizer {
+      get { return (BestQualityMemorizer)BestQualityMemorizer.Successor; }
+    }
+    private DataTableValuesCollector DataTableValuesCollector {
+      get { return (DataTableValuesCollector)BestKnownQualityMemorizer.Successor; }
+    }
+    private ResultsCollector ResultsCollector {
+      get { return (ResultsCollector)((QualityDifferenceCalculator)DataTableValuesCollector.Successor).Successor; }
+    }
+    #endregion
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private QualityAnalyzer(bool deserializing) : base(deserializing) { }
+    private QualityAnalyzer(QualityAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      Initialize();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityAnalyzer(this, cloner);
+    }
+    #endregion
+    public QualityAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestKnownQuality", "The best known quality value found so far."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestQuality", "The best quality value found in the current run."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Qualities", "The data table to store the current best, current average, current worst, best and best known quality value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", "The absolute difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", "The relative difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestQualityMemorizer bestQualityMemorizer = new BestQualityMemorizer();
+      BestQualityMemorizer bestKnownQualityMemorizer = new BestQualityMemorizer();
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      QualityDifferenceCalculator qualityDifferenceCalculator = new QualityDifferenceCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      bestQualityMemorizer.BestQualityParameter.ActualName = BestQualityParameter.Name;
+      bestQualityMemorizer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      bestQualityMemorizer.QualityParameter.ActualName = QualityParameter.Name;
+      bestQualityMemorizer.QualityParameter.Depth = QualityParameter.Depth;
+
+      bestKnownQualityMemorizer.BestQualityParameter.ActualName = BestKnownQualityParameter.Name;
+      bestKnownQualityMemorizer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      bestKnownQualityMemorizer.QualityParameter.ActualName = QualityParameter.Name;
+      bestKnownQualityMemorizer.QualityParameter.Depth = QualityParameter.Depth;
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestQuality", null, BestQualityParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestKnownQuality", null, BestKnownQualityParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", null, QualityParameter.Name));
+      ((ScopeTreeLookupParameter<DoubleValue>)dataTableValuesCollector.CollectedValues["Quality"]).Depth = QualityParameter.Depth;
+      dataTableValuesCollector.DataTableParameter.ActualName = QualitiesParameter.Name;
+
+      qualityDifferenceCalculator.AbsoluteDifferenceParameter.ActualName = AbsoluteDifferenceBestKnownToBestParameter.Name;
+      qualityDifferenceCalculator.FirstQualityParameter.ActualName = BestKnownQualityParameter.Name;
+      qualityDifferenceCalculator.RelativeDifferenceParameter.ActualName = RelativeDifferenceBestKnownToBestParameter.Name;
+      qualityDifferenceCalculator.SecondQualityParameter.ActualName = BestQualityParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestQuality", null, BestQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestKnownQuality", null, BestKnownQualityParameter.Name));
+      resultsCollector.CollectedValues.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", null, QualityParameter.Name));
+      ((ScopeTreeLookupParameter<DoubleValue>)resultsCollector.CollectedValues["Quality"]).Depth = QualityParameter.Depth;
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", null, AbsoluteDifferenceBestKnownToBestParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", null, RelativeDifferenceBestKnownToBestParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(QualitiesParameter.Name));
+      resultsCollector.ResultsParameter.ActualName = ResultsParameter.Name;
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestQualityMemorizer;
+      bestQualityMemorizer.Successor = bestKnownQualityMemorizer;
+      bestKnownQualityMemorizer.Successor = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = qualityDifferenceCalculator;
+      qualityDifferenceCalculator.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      QualityParameter.DepthChanged += new EventHandler(QualityParameter_DepthChanged);
+    }
+
+    private void QualityParameter_DepthChanged(object sender, System.EventArgs e) {
+      BestQualityMemorizer.QualityParameter.Depth = QualityParameter.Depth;
+      BestKnownQualityMemorizer.QualityParameter.Depth = QualityParameter.Depth;
+      ((ScopeTreeLookupParameter<DoubleValue>)DataTableValuesCollector.CollectedValues["Quality"]).Depth = QualityParameter.Depth;
+      ((ScopeTreeLookupParameter<DoubleValue>)ResultsCollector.CollectedValues["Quality"]).Depth = QualityParameter.Depth;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDifferenceCalculator.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDifferenceCalculator.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDifferenceCalculator.cs	(revision 15719)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which calculates the absolute and relative difference of two quality values.
+  /// </summary>
+  [Item("QualityDifferenceCalculator", "An operator which calculates the absolute and relative difference of two quality values.")]
+  [StorableClass]
+  public class QualityDifferenceCalculator : SingleSuccessorOperator {
+    public IValueLookupParameter<DoubleValue> FirstQualityParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["FirstQuality"]; }
+    }
+    public IValueLookupParameter<DoubleValue> SecondQualityParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["SecondQuality"]; }
+    }
+    public IValueLookupParameter<DoubleValue> AbsoluteDifferenceParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["AbsoluteDifference"]; }
+    }
+    public IValueLookupParameter<PercentValue> RelativeDifferenceParameter {
+      get { return (IValueLookupParameter<PercentValue>)Parameters["RelativeDifference"]; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    protected QualityDifferenceCalculator(bool deserializing) : base(deserializing) { }
+    protected QualityDifferenceCalculator(QualityDifferenceCalculator original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityDifferenceCalculator(this, cloner);
+    }
+    #endregion
+    public QualityDifferenceCalculator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("FirstQuality", "The first quality value from which the difference to the second quality value is calculated."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("SecondQuality", "The second quality value from which the difference from the first quality value is calculated."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AbsoluteDifference", "The absolute difference of the first and second quality value."));
+      Parameters.Add(new ValueLookupParameter<PercentValue>("RelativeDifference", "The relative difference of the first and second quality value."));
+    }
+
+    public override IOperation Apply() {
+      DoubleValue first = FirstQualityParameter.ActualValue;
+      DoubleValue second = SecondQualityParameter.ActualValue;
+
+      if ((first != null) && (second != null)) {
+        double absolute = second.Value - first.Value;
+        double relative = first.Value == 0 ? double.NaN : absolute / first.Value;
+
+        if (AbsoluteDifferenceParameter.ActualValue == null) AbsoluteDifferenceParameter.ActualValue = new DoubleValue(absolute);
+        else AbsoluteDifferenceParameter.ActualValue.Value = absolute;
+        if (RelativeDifferenceParameter.ActualValue == null) RelativeDifferenceParameter.ActualValue = new PercentValue(relative);
+        else RelativeDifferenceParameter.ActualValue.Value = relative;
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 15719)
@@ -0,0 +1,139 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis.QualityAnalysis {
+  [Item("QualityDistributionAnalyzer", "Analyzes the distribution of the quality values in that it adds a Histogram of them into the result collection.")]
+  [StorableClass]
+  public class QualityDistributionAnalyzer : SingleSuccessorOperator, IAnalyzer, IIterationBasedOperator, ISingleObjectiveOperator {
+
+    #region Parameter properties
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    private ValueParameter<StringValue> HistogramNameParameter {
+      get { return (ValueParameter<StringValue>)Parameters["HistogramName"]; }
+    }
+    private ValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    #endregion
+
+    public virtual bool EnabledByDefault {
+      get { return true; }
+    }
+
+    public string HistogramName {
+      get { return HistogramNameParameter.Value.Value; }
+      set { HistogramNameParameter.Value.Value = value; }
+    }
+
+    public bool StoreHistory {
+      get { return StoreHistoryParameter.Value.Value; }
+      set { StoreHistoryParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected QualityDistributionAnalyzer(bool deserializing) : base(deserializing) { }
+    protected QualityDistributionAnalyzer(QualityDistributionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QualityDistributionAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The results collection where the analysis values should be stored."));
+      Parameters.Add(new FixedValueParameter<StringValue>("HistogramName", "The name of the histogram that gets injected in to the results collection.", new StringValue("Quality Distribution")));
+      Parameters.Add(new FixedValueParameter<BoolValue>("StoreHistory", "True if the history should be stored in addition to the current distribution", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<IntValue>("Iterations", "Optional: A value indicating the current iteration."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "Unused", new IntValue(-1)));
+
+      QualityParameter.Hidden = true;
+      ResultsParameter.Hidden = true;
+      IterationsParameter.Hidden = true;
+      MaximumIterationsParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityDistributionAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      DataTable qualityDistribution = null;
+      ResultCollection results = ResultsParameter.ActualValue;
+      string description = "Shows the quality distributions in the current population.";
+      if (results.ContainsKey(HistogramName)) {
+        qualityDistribution = results[HistogramName].Value as DataTable;
+      } else {
+        qualityDistribution = new DataTable("Population Quality Distribution", description);
+        qualityDistribution.VisualProperties.XAxisTitle = QualityParameter.ActualName;
+        qualityDistribution.VisualProperties.YAxisTitle = "Frequency";
+        results.Add(new Result(HistogramName, description, qualityDistribution));
+      }
+      DataRow row;
+      if (!qualityDistribution.Rows.TryGetValue("QualityDistribution", out row)) {
+        row = new DataRow("QualityDistribution");
+        row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
+        qualityDistribution.Rows.Add(row);
+      }
+      var qualities = QualityParameter.ActualValue;
+      row.Values.Replace(qualities.Select(x => x.Value));
+
+      if (StoreHistory) {
+        string historyResultName = HistogramName + " History";
+        DataTableHistory qdHistory = null;
+        if (results.ContainsKey(historyResultName)) {
+          qdHistory = results[historyResultName].Value as DataTableHistory;
+        } else {
+          qdHistory = new DataTableHistory();
+          results.Add(new Result(historyResultName, qdHistory));
+        }
+        DataTable table = (DataTable)qualityDistribution.Clone();
+        IntValue iteration = IterationsParameter.ActualValue;
+        if (iteration != null) {
+          string iterationName = IterationsParameter.ActualName;
+          if (iterationName.EndsWith("s")) iterationName = iterationName.Remove(iterationName.Length - 1);
+          string appendix = " at " + iterationName + " " + iteration.Value.ToString();
+          table.Name += appendix;
+          table.Rows["QualityDistribution"].VisualProperties.DisplayName += appendix;
+        }
+        qdHistory.Add(table);
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityPerClockAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityPerClockAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityPerClockAnalyzer.cs	(revision 15719)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("QualityPerClockAnalyzer", @"Creates a plot of the solution quality with respect to the elapsed wall-clock time.")]
+  [StorableClass]
+  public class QualityPerClockAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator {
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+
+    public ILookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+
+    public ILookupParameter<DateTimeValue> LastUpdateTimeParameter {
+      get { return (ILookupParameter<DateTimeValue>)Parameters["LastUpdateTime"]; }
+    }
+
+    public IResultParameter<IndexedDataTable<double>> QualityPerClockParameter {
+      get { return (IResultParameter<IndexedDataTable<double>>)Parameters["QualityPerClock"]; }
+    }
+
+    [StorableConstructor]
+    protected QualityPerClockAnalyzer(bool deserializing) : base(deserializing) { }
+    protected QualityPerClockAnalyzer(QualityPerClockAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public QualityPerClockAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("BestQuality", "The quality value that should be compared."));
+      Parameters.Add(new LookupParameter<DateTimeValue>("LastUpdateTime", "The time the analyzer was last run."));
+      Parameters.Add(new ResultParameter<IndexedDataTable<double>>("QualityPerClock", "Data table containing the first hitting graph with elapsed wall clock time (in seconds) as the x-axis."));
+      QualityPerClockParameter.DefaultValue = new IndexedDataTable<double>("Quality per Clock") {
+        VisualProperties = {
+          XAxisTitle = "Elapsed time [s]",
+          YAxisTitle = "Quality"
+        },
+        Rows = { new IndexedDataRow<double>("First-hit Graph") { VisualProperties = {
+          ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
+          LineWidth = 2
+        } } }
+      };
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityPerClockAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var bestQuality = BestQualityParameter.ActualValue.Value;
+      var dataTable = QualityPerClockParameter.ActualValue;
+      var values = dataTable.Rows["First-hit Graph"].Values;
+
+      var lastUpdateTime = LastUpdateTimeParameter.ActualValue;
+      if (lastUpdateTime == null) {
+        lastUpdateTime = new DateTimeValue(DateTime.UtcNow.AddMilliseconds(-1));
+        LastUpdateTimeParameter.ActualValue = lastUpdateTime;
+      }
+
+      var now = DateTime.UtcNow;
+      var runtimeSoFar = (now - lastUpdateTime.Value).TotalSeconds + (values.Count > 0 ? values.Last().Item1 : 0);
+      lastUpdateTime.Value = now;
+      var newEntry = Tuple.Create(runtimeSoFar, bestQuality);
+
+      if (values.Count == 0) {
+        values.Add(newEntry); // record the first data
+        values.Add(Tuple.Create(runtimeSoFar, bestQuality)); // last entry records max number of evaluations
+        return base.Apply();
+      }
+
+      var improvement = values.Last().Item2 != bestQuality;
+      if (improvement) {
+        values[values.Count - 1] = newEntry; // record the improvement
+        values.Add(Tuple.Create(runtimeSoFar, bestQuality)); // last entry records max number of evaluations
+      } else {
+        values[values.Count - 1] = Tuple.Create(runtimeSoFar, bestQuality);
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityPerEvaluationsAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityPerEvaluationsAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityPerEvaluationsAnalyzer.cs	(revision 15719)
@@ -0,0 +1,113 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("QualityPerEvaluationsAnalyzer", @"Creates a plot of the solution quality with respect to the number of evaluated solutions.")]
+  [StorableClass]
+  public class QualityPerEvaluationsAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator {
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+
+    public ILookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+    public ILookupParameter<IntValue> EvaluatedMovesParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedMoves"]; }
+    }
+    public IValueLookupParameter<DoubleValue> MoveCostPerSolutionParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["MoveCostPerSolution"]; }
+    }
+    public IResultParameter<IndexedDataTable<double>> QualityPerEvaluationsParameter {
+      get { return (IResultParameter<IndexedDataTable<double>>)Parameters["QualityPerEvaluations"]; }
+    }
+
+    [StorableConstructor]
+    protected QualityPerEvaluationsAnalyzer(bool deserializing) : base(deserializing) { }
+    protected QualityPerEvaluationsAnalyzer(QualityPerEvaluationsAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public QualityPerEvaluationsAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("BestQuality", "The quality value that should be compared."));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated solutions."));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedMoves", "The number of evaluated moves."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MoveCostPerSolution", "The cost to evaluate a move as a ratio to the cost of evaluating a solution.", new DoubleValue(1)));
+      Parameters.Add(new ResultParameter<IndexedDataTable<double>>("QualityPerEvaluations", "Data table containing the first hitting graph with evaluations as the x-axis."));
+      QualityPerEvaluationsParameter.DefaultValue = new IndexedDataTable<double>("Quality per Evaluations") {
+        VisualProperties = {
+          XAxisTitle = "Evaluations",
+          YAxisTitle = "Quality"
+        },
+        Rows = { new IndexedDataRow<double>("First-hit Graph") { VisualProperties = {
+          ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
+          LineWidth = 2
+        } } }
+      };
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityPerEvaluationsAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var bestQuality = BestQualityParameter.ActualValue.Value;
+      var evalSols = EvaluatedSolutionsParameter.ActualValue;
+      var evalMoves = EvaluatedMovesParameter.ActualValue;
+      var evaluations = 0.0;
+      if (evalSols != null) evaluations += evalSols.Value;
+      if (evalMoves != null) evaluations += evalMoves.Value * MoveCostPerSolutionParameter.ActualValue.Value;
+
+      if (evaluations > 0) {
+        var dataTable = QualityPerEvaluationsParameter.ActualValue;
+        var values = dataTable.Rows["First-hit Graph"].Values;
+
+        var newEntry = Tuple.Create(evaluations, bestQuality);
+
+        if (values.Count == 0) {
+          values.Add(newEntry); // record the first data
+          values.Add(Tuple.Create(evaluations, bestQuality)); // last entry records max number of evaluations
+          return base.Apply();
+        }
+
+        var improvement = values.Last().Item2 != bestQuality;
+        if (improvement) {
+          values[values.Count - 1] = newEntry; // record the improvement
+          values.Add(Tuple.Create(evaluations, bestQuality)); // last entry records max number of evaluations
+        } else {
+          values[values.Count - 1] = Tuple.Create(evaluations, bestQuality); // the last entry is updated
+        }
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/ScaledQualityDifferenceAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/ScaledQualityDifferenceAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/QualityAnalysis/ScaledQualityDifferenceAnalyzer.cs	(revision 15719)
@@ -0,0 +1,102 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis.QualityAnalysis {
+  [Item("ScaledQualityDifferenceAnalyzer", @"Calculates the quality value relative to a certain range given with a minimum and a maximum value.
+The difference lies in the interval [0;1] if the range [min;max] is as large as the observed quality values, otherwise the difference will become < 0 or > 1.
+A value towards 0 always means that it's closer to the better fitness value, while a value towards 1 means that it's closer to the worse fitness value.")]
+  [StorableClass]
+  public class ScaledQualityDifferenceAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator {
+    public virtual bool EnabledByDefault {
+      get { return true; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<DoubleValue> ScaledDifferenceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["ScaledDifference"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public IValueLookupParameter<DoubleValue> MinimumQualityParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["MinimumQuality"]; }
+    }
+    public IValueLookupParameter<DoubleValue> MaximumQualityParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["MaximumQuality"]; }
+    }
+
+    [StorableConstructor]
+    protected ScaledQualityDifferenceAnalyzer(bool deserializing) : base(deserializing) { }
+    protected ScaledQualityDifferenceAnalyzer(ScaledQualityDifferenceAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public ScaledQualityDifferenceAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value that should be compared."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, false otherwise."));
+      Parameters.Add(new LookupParameter<DoubleValue>("ScaledDifference", "The value that describes whether the quality value lies towards the better quality in the range (<=0.5) or more towards the worse quality (> 0.5)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The result collection where the difference will be stored (in addition to the scope)."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MinimumQuality", "The lower bound of the quality range to which the quality is compared."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaximumQuality", "The upper bound of the quality range to which the quality is compared."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScaledQualityDifferenceAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      double quality = QualityParameter.ActualValue.Value, max = MaximumQualityParameter.ActualValue.Value, min = MinimumQualityParameter.ActualValue.Value;
+      double difference;
+
+      difference = ((quality - min) / (max - min));
+      if (maximization) difference = 1.0 - difference;
+
+      DoubleValue differenceValue = ScaledDifferenceParameter.ActualValue;
+      if (differenceValue == null) {
+        differenceValue = new DoubleValue(difference);
+        ScaledDifferenceParameter.ActualValue = differenceValue;
+      } else differenceValue.Value = difference;
+
+      ResultCollection results = ResultsParameter.ActualValue;
+      if (results != null) {
+        IResult r;
+        if (!results.TryGetValue(ScaledDifferenceParameter.TranslatedName, out r)) {
+          r = new Result(ScaledDifferenceParameter.TranslatedName, differenceValue);
+          results.Add(r);
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/BonferroniHolm.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/BonferroniHolm.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/BonferroniHolm.cs	(revision 15719)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public static class BonferroniHolm {
+    /// <summary>
+    /// Based on David Groppe's MATLAB implementation 
+    /// (BSD licensed, see 
+    /// http://www.mathworks.com/matlabcentral/fileexchange/28303-bonferroni-holm-correction-for-multiple-comparisons)
+    /// </summary>
+    public static double[] Calculate(double globalAlpha, double[] pValues, out bool[] h) {
+      int k = pValues.Length;
+      double[] alphaNiveau = new double[k];
+      double[] adjustedPValues = new double[k];
+      bool[] decision = new bool[k];
+      Dictionary<int, double> pValuesIndizes = new Dictionary<int, double>();
+
+      for (int i = 0; i < k; i++) {
+        pValuesIndizes.Add(i, pValues[i]);
+      }
+      var sortedPValues = pValuesIndizes.OrderBy(x => x.Value).ToArray();
+
+      for (int i = 1; i < k + 1; i++) {
+        alphaNiveau[i - 1] = globalAlpha / (k - i + 1);
+        int idx = sortedPValues[i - 1].Key;
+
+        if (i == 1) {
+          //true means reject
+          decision[idx] = sortedPValues[i - 1].Value < alphaNiveau[i - 1];
+          adjustedPValues[idx] = sortedPValues[i - 1].Value * (k - i + 1);
+        } else {
+          decision[idx] = decision[sortedPValues[i - 2].Key] && (sortedPValues[i - 1].Value < alphaNiveau[i - 1]);
+          adjustedPValues[idx] = Math.Max(adjustedPValues[sortedPValues[i - 2].Key], sortedPValues[i - 1].Value * (k - i + 1));
+        }
+        if (adjustedPValues[idx] > 1.0) {
+          adjustedPValues[idx] = 1.0;
+        }
+      }
+
+      h = decision;
+      return adjustedPValues;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/EnumerableStatisticsExtension.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/EnumerableStatisticsExtension.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/EnumerableStatisticsExtension.cs	(revision 15719)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public static class EnumerableStatisticExtensions {
+    public static Tuple<double, double> ConfidenceIntervals(this IEnumerable<double> values, double alpha) {
+      return ConfidenceIntervals(values.ToArray(), alpha);
+    }
+
+    public static Tuple<double, double> ConfidenceIntervals(this double[] values, double alpha) {
+      double lower, upper;
+      int n = values.Length;
+      if (n <= 1) return new Tuple<double, double>(double.NaN, double.NaN);
+
+      double s = values.StandardDeviation();
+      double x = values.Average();
+      double t = alglib.invstudenttdistribution(n - 1, (1.0 - alpha) / 2.0);
+
+      lower = x + t * (s / Math.Sqrt(n));
+      upper = x - t * (s / Math.Sqrt(n));
+
+      return new Tuple<double, double>(lower, upper);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/ExpFitting.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/ExpFitting.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/ExpFitting.cs	(revision 15719)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public class ExpFitting : IFitting {
+    private void ExpFunc(double[] c, double[] x, ref double func, object obj) {
+      func = Math.Exp(-c[0] * Math.Pow(x[0], 2));
+    }
+
+    private double[] GetDefaultXValues(int n) {
+      var stdX = Enumerable.Range(1, n).Select(x => (double)x).ToArray();
+      return stdX;
+    }
+
+    public void Calculate(double[] dataPoints, out double p0) {
+      var stdX = GetDefaultXValues(dataPoints.Count());
+      Calculate(dataPoints, stdX, out p0);
+    }
+
+    public void Calculate(double[] y, double[] x, out double p0) {
+      if (y.Count() != x.Count()) {
+        throw new ArgumentException("The lenght of x and y needs do be equal. ");
+      }
+
+      double[] c = new double[] { 0.3 };
+      double epsf = 0;
+      double epsx = 0.000001;
+      int maxits = 0;
+      int info;
+      alglib.lsfitstate state;
+      alglib.lsfitreport rep;
+      double diffstep = 0.0001;
+      double[,] xx = new double[x.Count(), 1];
+
+      for (int i = 0; i < x.Count(); i++) {
+        xx[i, 0] = x[i];
+      }
+
+      alglib.lsfitcreatef(xx, y, c, diffstep, out state);
+      alglib.lsfitsetcond(state, epsf, epsx, maxits);
+      alglib.lsfitfit(state, ExpFunc, null, null);
+      alglib.lsfitresults(state, out info, out c, out rep);
+
+      p0 = c[0];
+    }
+
+    public DataRow CalculateFittedLine(double[] dataPoints) {
+      DataRow newRow = new DataRow();
+      double c0;
+      Calculate(dataPoints, out c0);
+      var stdX = GetDefaultXValues(dataPoints.Count());
+
+      for (int i = 0; i < stdX.Count(); i++) {
+        newRow.Values.Add(Math.Exp(-c0 * Math.Pow(stdX[i], 2)));
+      }
+
+      return newRow;
+    }
+
+    public DataRow CalculateFittedLine(double[] y, double[] x) {
+      DataRow newRow = new DataRow();
+      double c0;
+      Calculate(y, x, out c0);
+
+      for (int i = 0; i < x.Count(); i++) {
+        newRow.Values.Add(Math.Exp(-c0 * Math.Pow(x[i], 2)));
+      }
+
+      return newRow;
+    }
+
+    public override string ToString() {
+      return "Exponential Fitting";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/IFitting.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/IFitting.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/IFitting.cs	(revision 15719)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Statistics {
+  public interface IFitting {
+    DataRow CalculateFittedLine(double[] dataPoints);
+    DataRow CalculateFittedLine(double[] y, double[] x);
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/LinearLeastSquaresFitting.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/LinearLeastSquaresFitting.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/LinearLeastSquaresFitting.cs	(revision 15719)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public class LinearLeastSquaresFitting : IFitting {
+    public void Calculate(double[] dataPoints, out double slope, out double intercept) {
+      var stdX = Enumerable.Range(0, dataPoints.Count()).Select(x => (double)x).ToArray();
+      Calculate(dataPoints, stdX, out slope, out intercept);
+    }
+
+    public void Calculate(double[] y, double[] x, out double slope, out double intercept) {
+      if (y.Count() != x.Count()) {
+        throw new ArgumentException("The lenght of x and y needs do be equal. ");
+      }
+
+      double sxy = 0.0;
+      double sxx = 0.0;
+      int n = y.Count();
+      double sy = y.Sum();
+      double sx = ((n - 1) * n) / 2.0;
+      double avgy = sy / n;
+      double avgx = sx / n;
+
+      for (int i = 0; i < n; i++) {
+        sxy += x[i] * y[i];
+        sxx += x[i] * x[i];
+      }
+
+      slope = (sxy - (n * avgx * avgy)) / (sxx - (n * avgx * avgx));
+      intercept = avgy - slope * avgx;
+    }
+
+    public double CalculateError(double[] dataPoints, double slope, double intercept) {
+      double r;
+      double avgy = dataPoints.Average();
+      double sstot = 0.0;
+      double sserr = 0.0;
+
+      for (int i = 0; i < dataPoints.Count(); i++) {
+        double y = slope * i + intercept;
+        sstot += Math.Pow(dataPoints[i] - avgy, 2);
+        sserr += Math.Pow(dataPoints[i] - y, 2);
+      }
+
+      r = 1.0 - (sserr / sstot);
+      return r;
+    }
+
+    public DataRow CalculateFittedLine(double[] y, double[] x) {
+      double slope, intercept;
+      Calculate(y, x, out slope, out intercept);
+
+      DataRow newRow = new DataRow();
+      for (int i = 0; i < x.Count(); i++) {
+        newRow.Values.Add(slope * x[i] + intercept);
+      }
+      return newRow;
+    }
+
+    public DataRow CalculateFittedLine(double[] dataPoints) {
+      DataRow newRow = new DataRow();
+      double slope, intercept;
+      Calculate(dataPoints, out slope, out intercept);
+      var stdX = Enumerable.Range(0, dataPoints.Count()).Select(x => (double)x).ToArray();
+
+      for (int i = 0; i < stdX.Count(); i++) {
+        newRow.Values.Add(slope * stdX[i] + intercept);
+      }
+
+      return newRow;
+    }
+
+    public override string ToString() {
+      return "Linear Fitting";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/LogFitting.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/LogFitting.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/Fitting/LogFitting.cs	(revision 15719)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public class LogFitting : IFitting {
+    private void LogFunc(double[] c, double[] x, ref double func, object obj) {
+      func = c[0] * Math.Exp(c[1] / x[0]);
+    }
+
+    private double[] GetDefaultXValues(int n) {
+      var stdX = Enumerable.Range(1, n).Select(x => (double)x).ToArray();
+      return stdX;
+    }
+
+    public void Calculate(double[] dataPoints, out double p0, out double p1) {
+      var stdX = GetDefaultXValues(dataPoints.Count());
+      Calculate(dataPoints, stdX, out p0, out p1);
+    }
+
+    public void Calculate(double[] y, double[] x, out double p0, out double p1) {
+      if (y.Count() != x.Count()) {
+        throw new ArgumentException("The lenght of x and y needs do be equal. ");
+      }
+
+      double[] c = new double[] { 0.3, 0.3 };
+      double epsf = 0;
+      double epsx = 0.000001;
+      int maxits = 0;
+      int info;
+      alglib.lsfitstate state;
+      alglib.lsfitreport rep;
+      double diffstep = 0.0001;
+      double[,] xx = new double[x.Count(), 1];
+
+      for (int i = 0; i < x.Count(); i++) {
+        xx[i, 0] = x[i];
+      }
+
+      alglib.lsfitcreatef(xx, y, c, diffstep, out state);
+      alglib.lsfitsetcond(state, epsf, epsx, maxits);
+      alglib.lsfitfit(state, LogFunc, null, null);
+      alglib.lsfitresults(state, out info, out c, out rep);
+
+      p0 = c[0];
+      p1 = c[1];
+    }
+
+    public DataRow CalculateFittedLine(double[] dataPoints) {
+      DataRow newRow = new DataRow();
+      double c0, c1;
+      Calculate(dataPoints, out c0, out c1);
+      var stdX = GetDefaultXValues(dataPoints.Count());
+
+      for (int i = 0; i < stdX.Count(); i++) {
+        newRow.Values.Add(c0 * Math.Exp(c1 / stdX[i]));
+      }
+
+      return newRow;
+    }
+
+    public DataRow CalculateFittedLine(double[] y, double[] x) {
+      DataRow newRow = new DataRow();
+      double c0, c1;
+      Calculate(y, x, out c0, out c1);
+
+      for (int i = 0; i < x.Count(); i++) {
+        newRow.Values.Add(c0 * Math.Exp(c1 / x[i]));
+      }
+
+      return newRow;
+    }
+
+    public override string ToString() {
+      return "Logarithmic Fitting";
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/KernelDensityEstimator.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/KernelDensityEstimator.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/KernelDensityEstimator.cs	(revision 15719)
@@ -0,0 +1,69 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public static class KernelDensityEstimator {
+    public static double[] Density(double[] x, double mean, double stdDev) {
+      return x.Select(xi => Density(xi, mean, stdDev)).ToArray();
+    }
+
+    public static double Density(double x, double mean, double stdDev) {
+      return (1.0 / (stdDev * Math.Sqrt(2.0 * Math.PI))) *
+                  Math.Exp(-((Math.Pow(x - mean, 2.0)) /
+                             (2.0 * Math.Pow(stdDev, 2.0))));
+    }
+
+    // the scale (sigma) of the kernel is a parameter
+    public static List<Tuple<double, double>> Density(double[] x, int nrOfPoints, double stepWidth, double sigma = 1.0) {
+      // calculate grid for which to estimate the density
+      double[] newX = new double[nrOfPoints];
+      double margin = stepWidth * 2;
+
+      double dataMin = x.Min() - margin;
+      double dataMax = x.Max() + margin;
+      double diff = (dataMax - dataMin) / nrOfPoints;
+      double cur = dataMin;
+      newX[0] = cur;
+      for (int i = 1; i < nrOfPoints; i++) {
+        cur += diff;
+        newX[i] = cur;
+      }
+
+      // for each of the points for which we want to calculate the density
+      // we sum up all the densities of the observed points assuming they are at the center of a normal distribution
+      var y = from xi in newX
+              select (from obsX in x
+                      select Density(xi, obsX, sigma)).Sum();
+
+      return newX.Zip(y, Tuple.Create).ToList();
+    }
+
+    //Silverman's rule of thumb for bandwidth estimation (sigma)
+    public static double EstimateBandwidth(double[] x) {
+      return 1.06 * x.StandardDeviation() * Math.Pow(x.Length, -0.2);
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/KruskalWallisTest.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/KruskalWallisTest.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/KruskalWallisTest.cs	(revision 15719)
@@ -0,0 +1,151 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public static class KruskalWallisTest {
+    /// <summary>
+    /// Performs the Kruskal-Wallis test and returns the p-Value. 
+    /// (source based on R's kruskal.test(), GNU GPL)
+    /// </summary>
+    public static double Test(double[][] data) {
+      double[] g;
+      double[] x = FlattenArray(data, out g);
+      int n = x.Length;
+      int parameter = data.Length - 1;
+
+      int[] r = Rank(x);
+      double[][] ties = CountDuplicates(x);
+      double statistic = CalculateStatistic(r, g);
+      double tiesCorrection = CalculateTiesCorrection(ties);
+      statistic = ((12 * statistic / (n * (n + 1)) - 3 * (n + 1)) /
+                  (1 - tiesCorrection / (Math.Pow(n, 3) - n)));
+
+      return alglib.chisquarecdistribution(parameter, statistic);
+    }
+
+    private static double CalculateStatistic(int[] r, double[] g) {
+      double result = 0.0;
+      double lastG = g[0];
+      double curSum = 0.0;
+      int cnt = 0;
+      for (int i = 0; i < r.Length; i++) {
+        if (lastG.IsAlmost(g[i])) {
+          curSum += r[i];
+          cnt++;
+        } else {
+          double sum = Math.Pow(curSum, 2);
+          sum /= cnt;
+          result += sum;
+
+          lastG = g[i];
+          curSum = r[i];
+          cnt = 1;
+        }
+      }
+
+      double lastSum = Math.Pow(curSum, 2);
+      lastSum /= cnt;
+      result += lastSum;
+
+      return result;
+    }
+
+    private static double CalculateTiesCorrection(double[][] ties) {
+      double sum = 0.0;
+      for (int i = 0; i < ties[1].Length; i++) {
+        double tic = Math.Pow(ties[1][i], 3) - ties[1][i];
+        sum += tic;
+      }
+      return sum;
+    }
+
+    private static double[] FlattenArray(double[][] x, out double[] indizes) {
+      int compLenght = 0;
+      for (int i = 0; i < x.Length; i++) {
+        compLenght += x[i].Length;
+      }
+
+      double[] result = new double[compLenght];
+      indizes = new double[compLenght];
+
+      int resultPos = 0;
+      for (int i = 0; i < x.Length; i++) {
+        Array.Copy(x[i], 0, result, resultPos, x[i].Length);
+
+        for (int j = resultPos; j < resultPos + x[i].Length; j++) {
+          indizes[j] = i;
+        }
+        resultPos += x[i].Length;
+      }
+
+      return result;
+    }
+
+    private static double[][] CountDuplicates(double[] x) {
+      List<double> number = new List<double>();
+      List<double> cnt = new List<double>();
+      double[] sortedX = new double[x.Length];
+
+      Array.Copy(x, sortedX, x.Length);
+      Array.Sort(sortedX);
+
+      double last = x[0];
+      number.Add(x[0]);
+      cnt.Add(1);
+
+      for (int i = 1; i < x.Length; i++) {
+        if (!last.IsAlmost(x[i])) {
+          number.Add(x[i]);
+          last = x[i];
+          cnt.Add(1);
+        } else {
+          cnt[cnt.Count - 1] += 1;
+        }
+      }
+
+      double[][] result = new double[2][];
+      result[0] = number.ToArray();
+      result[1] = cnt.ToArray();
+
+      return result;
+    }
+
+    private static int[] Rank(double[] x) {
+      double[] keys = new double[x.Length];
+      int[] items = new int[x.Length];
+      int[] ranks = new int[x.Length];
+
+      Array.Copy(x, keys, x.Length);
+      for (int i = 0; i < x.Length; i++) items[i] = i;
+
+      Array.Sort(keys, items);
+
+      for (int i = 0; i < x.Length; i++) {
+        ranks[items[i]] = i + 1;
+      }
+      return ranks;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/PairwiseTest.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/PairwiseTest.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/PairwiseTest.cs	(revision 15719)
@@ -0,0 +1,37 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Analysis.Statistics {
+  public class PairwiseTest {
+    public static double TTest(double[] group1, double[] group2) {
+      double left, right, both;
+      alglib.unequalvariancettest(group1, group1.Length, group2, group2.Length, out both, out left, out right);
+      return both;
+    }
+
+    public static double MannWhitneyUTest(double[] group1, double[] group2) {
+      double mwuBothtails, mwuLefttail, mwuRighttail;
+      alglib.mannwhitneyutest(group1, group1.Length, group2, group2.Length, out mwuBothtails, out mwuLefttail, out mwuRighttail);
+      return mwuBothtails;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/SampleSizeDetermination.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/SampleSizeDetermination.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/Statistics/SampleSizeDetermination.cs	(revision 15719)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Analysis.Statistics {
+  public static class SampleSizeDetermination {
+    /// <summary>
+    /// Determines for a given sample the required sample size as described in 
+    /// Göran Kauermann, Helmut Küchenhoff: Stichproben: Methoden und praktische Umsetzung mit R, section 2.27. 
+    /// </summary>
+    /// <param name="samples">The pilot sample.</param>
+    /// <param name="conf">Confidence Interval.</param>
+    /// <returns>Number of required samples for the given confidence interval. </returns>
+    public static int DetermineSampleSizeByEstimatingMean(double[] samples, double conf = 0.95) {
+      if (conf < 0.0 || conf > 1.0) throw new ArgumentException("The confidence interval must be between zero and one.");
+
+      var confInterval = samples.ConfidenceIntervals(conf);
+      double e = (confInterval.Item2 - confInterval.Item1) / 2;
+      double s = samples.StandardDeviation();
+      double z = alglib.invnormaldistribution((conf + 1) / 2);
+      double n = samples.Count();
+
+      double result = Math.Pow(s, 2) / ((Math.Pow(e, 2) / Math.Pow(z, 2)) + (Math.Pow(s, 2) / n));
+
+      result = Math.Ceiling(result);
+      if (result > int.MaxValue)
+        return int.MaxValue;
+      else
+        return (int)result;
+    }
+
+    /// <summary>
+    /// Calculates Cohen's d.
+    /// </summary>
+    /// <returns>Cohen's d. 
+    /// d = 0.2 means small effect
+    /// d = 0.5 means medium effect
+    /// d = 0.8 means big effect
+    /// According to Wikipedia this means: "A lower Cohen's d indicates a necessity of larger sample sizes, and vice versa."
+    /// </returns>
+    public static double CalculateCohensD(double[] d1, double[] d2) {
+      double x1, x2, s1, s2;
+
+      x1 = d1.Average();
+      x2 = d2.Average();
+      s1 = d1.Variance();
+      s2 = d2.Variance();
+
+      return Math.Abs(x1 - x2) / Math.Sqrt((s1 + s2) / 2);
+    }
+
+    /// <summary>
+    /// Calculates Hedges' g. 
+    /// Hedges' g works like Cohen's d but corrects for bias. 
+    /// </summary>
+    /// <returns>Hedges' g</returns>
+    public static double CalculateHedgesG(double[] d1, double[] d2) {
+      double x1, x2, s1, s2, n1, n2, s, g, c;
+
+      x1 = d1.Average();
+      x2 = d2.Average();
+      s1 = d1.Variance();
+      s2 = d2.Variance();
+      n1 = d1.Count();
+      n2 = d2.Count();
+
+      s = Math.Sqrt(((n1 - 1) * s1 + (n2 - 1) * s2) / (n1 + n2 - 2));
+      g = Math.Abs(x1 - x2) / s;
+      c = (1 - (3 / (4 * (n1 + n2) - 9))) * g;
+
+      return c;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/MinAverageMaxValueAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/MinAverageMaxValueAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/MinAverageMaxValueAnalyzer.cs	(revision 15719)
@@ -0,0 +1,228 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes the minimum, average and maximum of a value in the scope tree.
+  /// </summary>
+  [Item("MinAverageMaxValueAnalyzer", "An operator which analyzes the minimum, average and maximum of a value in the scope tree.")]
+  [StorableClass]
+  public sealed class MinAverageMaxValueAnalyzer : AlgorithmOperator, IAnalyzer {
+    #region Parameter properties
+    public ScopeTreeLookupParameter<DoubleValue> ValueParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public ValueLookupParameter<DoubleValue> MinValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["MinValue"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageValue"]; }
+    }
+    public ValueLookupParameter<DoubleValue> MaxValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["MaxValue"]; }
+    }
+    public ValueLookupParameter<DataTable> ValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Values"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    public ValueParameter<BoolValue> CollectMinValueInResultsParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["CollectMinValueInResults"]; }
+    }
+    public ValueParameter<BoolValue> CollectMaxValueInResultsParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["CollectMaxValueInResults"]; }
+    }
+    public ValueParameter<BoolValue> CollectAverageValueInResultsParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["CollectAverageValueInResults"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private MinAverageMaxValueCalculator MinAverageMaxValueCalculator {
+      get { return (MinAverageMaxValueCalculator)OperatorGraph.InitialOperator; }
+    }
+    private BoolValue CollectMinValueInResults {
+      get { return CollectMinValueInResultsParameter.Value; }
+    }
+    private BoolValue CollectMaxValueInResults {
+      get { return CollectMaxValueInResultsParameter.Value; }
+    }
+    private BoolValue CollectAverageValueInResults {
+      get { return CollectAverageValueInResultsParameter.Value; }
+    }
+    #endregion
+
+    [Storable]
+    private ResultsCollector resultsCollector;
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private MinAverageMaxValueAnalyzer(bool deserializing) : base(deserializing) { }
+    private MinAverageMaxValueAnalyzer(MinAverageMaxValueAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      resultsCollector = cloner.Clone(original.resultsCollector);
+      RegisterEventHandlers();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MinAverageMaxValueAnalyzer(this, cloner);
+    }
+    #endregion
+    public MinAverageMaxValueAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Value", "The value contained in the scope tree which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MinValue", "The minimum of the value."));
+      Parameters.Add(new ValueParameter<BoolValue>("CollectMinValueInResults", "Determines if the minimum of the value should also be stored in the results.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageValue", "The average of the value."));
+      Parameters.Add(new ValueParameter<BoolValue>("CollectAverageValueInResults", "Determines if the average of the value should also be stored in the results.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaxValue", "The maximum of the value."));
+      Parameters.Add(new ValueParameter<BoolValue>("CollectMaxValueInResults", "Determines if the maximum of the value should also be stored in the results.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Values", "The data table to store the minimum, average and maximum of the value."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      MinAverageMaxValueCalculator minAverageMaxValueCalculator = new MinAverageMaxValueCalculator();
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      resultsCollector = new ResultsCollector();
+
+      minAverageMaxValueCalculator.AverageValueParameter.ActualName = AverageValueParameter.Name;
+      minAverageMaxValueCalculator.MaxValueParameter.ActualName = MaxValueParameter.Name;
+      minAverageMaxValueCalculator.MinValueParameter.ActualName = MinValueParameter.Name;
+      minAverageMaxValueCalculator.ValueParameter.ActualName = ValueParameter.Name;
+      minAverageMaxValueCalculator.ValueParameter.Depth = ValueParameter.Depth;
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MinValue", null, MinValueParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("AverageValue", null, AverageValueParameter.Name));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MaxValue", null, MaxValueParameter.Name));
+      dataTableValuesCollector.DataTableParameter.ActualName = ValuesParameter.Name;
+
+      if (CollectMinValueInResults.Value)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MinValue", null, MinValueParameter.Name));
+      if (CollectAverageValueInResults.Value)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("AverageValue", null, AverageValueParameter.Name));
+      if (CollectMaxValueInResults.Value)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MaxValue", null, MaxValueParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(ValuesParameter.Name));
+      resultsCollector.ResultsParameter.ActualName = ResultsParameter.Name;
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = minAverageMaxValueCalculator;
+      minAverageMaxValueCalculator.Successor = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      RegisterEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      ValueParameter.DepthChanged += new EventHandler(ValueParameter_DepthChanged);
+      CollectMinValueInResultsParameter.ValueChanged += new EventHandler(CollectMinValueInResultsParameter_ValueChanged);
+      CollectMinValueInResultsParameter.Value.ValueChanged += new EventHandler(CollectMinValueInResultsParameter_Value_ValueChanged);
+      CollectMaxValueInResultsParameter.ValueChanged += new EventHandler(CollectMaxValueInResultsParameter_ValueChanged);
+      CollectMaxValueInResultsParameter.Value.ValueChanged += new EventHandler(CollectMaxValueInResultsParameter_Value_ValueChanged);
+      CollectAverageValueInResultsParameter.ValueChanged += new EventHandler(CollectAverageValueInResultsParameter_ValueChanged);
+      CollectAverageValueInResultsParameter.Value.ValueChanged += new EventHandler(CollectAverageValueInResultsParameter_Value_ValueChanged);
+    }
+
+    private void CollectAverageValueInResultsParameter_ValueChanged(object sender, EventArgs e) {
+      IParameter avgValueParameter;
+      resultsCollector.CollectedValues.TryGetValue("AverageValue", out avgValueParameter);
+      if (CollectAverageValueInResults.Value && avgValueParameter == null)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("AverageValue", null, AverageValueParameter.Name));
+      else if (!CollectAverageValueInResults.Value && avgValueParameter != null)
+        resultsCollector.CollectedValues.Remove(avgValueParameter);
+      CollectAverageValueInResultsParameter.Value.ValueChanged += new EventHandler(CollectAverageValueInResultsParameter_Value_ValueChanged);
+    }
+
+    private void CollectAverageValueInResultsParameter_Value_ValueChanged(object sender, EventArgs e) {
+      IParameter avgValueParameter;
+      resultsCollector.CollectedValues.TryGetValue("AverageValue", out avgValueParameter);
+      if (CollectAverageValueInResults.Value && avgValueParameter == null)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("AverageValue", null, AverageValueParameter.Name));
+      else if (!CollectAverageValueInResults.Value && avgValueParameter != null)
+        resultsCollector.CollectedValues.Remove(avgValueParameter);
+    }
+
+    private void CollectMaxValueInResultsParameter_ValueChanged(object sender, EventArgs e) {
+      IParameter maxValueParameter;
+      resultsCollector.CollectedValues.TryGetValue("MaxValue", out maxValueParameter);
+      if (CollectMaxValueInResults.Value && maxValueParameter == null)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MaxValue", null, MaxValueParameter.Name));
+      else if (!CollectMaxValueInResults.Value && maxValueParameter != null)
+        resultsCollector.CollectedValues.Remove(maxValueParameter);
+      CollectMaxValueInResultsParameter.Value.ValueChanged += new EventHandler(CollectMaxValueInResultsParameter_Value_ValueChanged);
+    }
+
+    private void CollectMaxValueInResultsParameter_Value_ValueChanged(object sender, EventArgs e) {
+      IParameter maxValueParameter;
+      resultsCollector.CollectedValues.TryGetValue("MaxValue", out maxValueParameter);
+      if (CollectMaxValueInResults.Value && maxValueParameter == null)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MaxValue", null, MaxValueParameter.Name));
+      else if (!CollectMaxValueInResults.Value && maxValueParameter != null)
+        resultsCollector.CollectedValues.Remove(maxValueParameter);
+    }
+
+    private void CollectMinValueInResultsParameter_ValueChanged(object sender, EventArgs e) {
+      IParameter minValueParameter;
+      resultsCollector.CollectedValues.TryGetValue("MinValue", out minValueParameter);
+      if (CollectMinValueInResults.Value && minValueParameter == null)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MinValue", null, MinValueParameter.Name));
+      else if (!CollectMinValueInResults.Value && minValueParameter != null)
+        resultsCollector.CollectedValues.Remove(minValueParameter);
+      CollectMinValueInResultsParameter.Value.ValueChanged += new EventHandler(CollectMinValueInResultsParameter_Value_ValueChanged);
+    }
+
+    private void CollectMinValueInResultsParameter_Value_ValueChanged(object sender, EventArgs e) {
+      IParameter minValueParameter;
+      resultsCollector.CollectedValues.TryGetValue("MinValue", out minValueParameter);
+      if (CollectMinValueInResults.Value && minValueParameter == null)
+        resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("MinValue", null, MinValueParameter.Name));
+      else if (!CollectMinValueInResults.Value && minValueParameter != null)
+        resultsCollector.CollectedValues.Remove(minValueParameter);
+    }
+
+    private void ValueParameter_DepthChanged(object sender, System.EventArgs e) {
+      MinAverageMaxValueCalculator.ValueParameter.Depth = ValueParameter.Depth;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/MinAverageMaxValueCalculator.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/MinAverageMaxValueCalculator.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/MinAverageMaxValueCalculator.cs	(revision 15719)
@@ -0,0 +1,89 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which calculates the minimum, average and maximum of a value in the scope tree.
+  /// </summary>
+  [Item("MinAverageMaxValueCalculator", "An operator which calculates the minimum, average and maximum of a value in the scope tree.")]
+  [StorableClass]
+  public sealed class MinAverageMaxValueCalculator : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> ValueParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public ValueLookupParameter<DoubleValue> MinValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["MinValue"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageValue"]; }
+    }
+    public ValueLookupParameter<DoubleValue> MaxValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["MaxValue"]; }
+    }
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private MinAverageMaxValueCalculator(bool deserializing) : base(deserializing) { }
+    private MinAverageMaxValueCalculator(MinAverageMaxValueCalculator original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MinAverageMaxValueCalculator(this, cloner);
+    }
+    #endregion
+    public MinAverageMaxValueCalculator()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Value", "The value contained in the scope tree for which the minimum, average and maximum should be calculated."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MinValue", "The minimum of the value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageValue", "The average of the value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaxValue", "The maximum of the value."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> values = ValueParameter.ActualValue;
+
+      if (values.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < values.Length; i++) {
+          if (values[i].Value < min) min = values[i].Value;
+          if (values[i].Value > max) max = values[i].Value;
+          sum += values[i].Value;
+        }
+
+        DoubleValue minValue = MinValueParameter.ActualValue;
+        if (minValue == null) MinValueParameter.ActualValue = new DoubleValue(min);
+        else minValue.Value = min;
+        DoubleValue averageValue = AverageValueParameter.ActualValue;
+        if (averageValue == null) AverageValueParameter.ActualValue = new DoubleValue(sum / values.Length);
+        else averageValue.Value = sum / values.Length;
+        DoubleValue maxValue = MaxValueParameter.ActualValue;
+        if (maxValue == null) MaxValueParameter.ActualValue = new DoubleValue(max);
+        else maxValue.Value = max;
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/SingleValueAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/SingleValueAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/SingleValueAnalyzer.cs	(revision 15719)
@@ -0,0 +1,97 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes a value in the scope tree (current scope and parents).
+  /// </summary>
+  [Item("SingleValueAnalyzer", "An operator which analyzes a value in the scope tree (current scope and parents).")]
+  [StorableClass]
+  public sealed class SingleValueAnalyzer : AlgorithmOperator, IAnalyzer {
+    #region Parameter properties
+    public ILookupParameter<DoubleValue> ValueParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public IValueLookupParameter<DataTable> ValuesParameter {
+      get { return (IValueLookupParameter<DataTable>)Parameters["Values"]; }
+    }
+    public IValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (IValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private DataTableValuesCollector DataTableValuesCollector {
+      get { return (DataTableValuesCollector)OperatorGraph.InitialOperator; }
+    }
+    private ResultsCollector ResultsCollector {
+      get { return (ResultsCollector)DataTableValuesCollector.Successor; }
+    }
+    #endregion
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private SingleValueAnalyzer(bool deserializing) : base(deserializing) { }
+    private SingleValueAnalyzer(SingleValueAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleValueAnalyzer(this, cloner);
+    }
+    #endregion
+    public SingleValueAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<DoubleValue>("Value", "The value contained in the scope tree which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Values", "The data table to store the values."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Value", null, ValueParameter.Name));
+      dataTableValuesCollector.DataTableParameter.ActualName = ValuesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Value", null, ValueParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(ValuesParameter.Name));
+      resultsCollector.ResultsParameter.ActualName = ResultsParameter.Name;
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/ValueAnalyzer.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/ValueAnalyzer.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Analysis/3.3/ValueAnalysis/ValueAnalyzer.cs	(revision 15719)
@@ -0,0 +1,119 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes a value in the scope tree.
+  /// </summary>
+  [Item("ValueAnalyzer", "An operator which analyzes a value in the scope tree (current scope and children).")]
+  [StorableClass]
+  public sealed class ValueAnalyzer : AlgorithmOperator, IAnalyzer {
+    #region Parameter properties
+    public ScopeTreeLookupParameter<DoubleValue> ValueParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public ValueLookupParameter<DataTable> ValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Values"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private DataTableValuesCollector DataTableValuesCollector {
+      get { return (DataTableValuesCollector)OperatorGraph.InitialOperator; }
+    }
+    private ResultsCollector ResultsCollector {
+      get { return (ResultsCollector)DataTableValuesCollector.Successor; }
+    }
+    #endregion
+
+    #region Storing & Cloning
+    [StorableConstructor]
+    private ValueAnalyzer(bool deserializing) : base(deserializing) { }
+    private ValueAnalyzer(ValueAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      Initialize();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ValueAnalyzer(this, cloner);
+    }
+    #endregion
+    public ValueAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Value", "The value contained in the scope tree which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Values", "The data table to store the values."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      dataTableValuesCollector.CollectedValues.Add(new ScopeTreeLookupParameter<DoubleValue>("Value", null, ValueParameter.Name));
+      ((ScopeTreeLookupParameter<DoubleValue>)dataTableValuesCollector.CollectedValues["Value"]).Depth = ValueParameter.Depth;
+      dataTableValuesCollector.DataTableParameter.ActualName = ValuesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new ScopeTreeLookupParameter<DoubleValue>("Value", null, ValueParameter.Name));
+      ((ScopeTreeLookupParameter<DoubleValue>)resultsCollector.CollectedValues["Value"]).Depth = ValueParameter.Depth;
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(ValuesParameter.Name));
+      resultsCollector.ResultsParameter.ActualName = ResultsParameter.Name;
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      ValueParameter.DepthChanged += new EventHandler(ValueParameter_DepthChanged);
+    }
+
+    private void ValueParameter_DepthChanged(object sender, System.EventArgs e) {
+      ((ScopeTreeLookupParameter<DoubleValue>)DataTableValuesCollector.CollectedValues["Value"]).Depth = ValueParameter.Depth;
+      ((ScopeTreeLookupParameter<DoubleValue>)ResultsCollector.CollectedValues["Value"]).Depth = ValueParameter.Depth;
+    }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 15719)
@@ -391,8 +391,4 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Analysis.Views-3.3, Version=3.3.0.0">
-      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis.Views-3.3.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
     <Reference Include="HeuristicLab.Core.Views-3.3, Version=3.3.0.0">
       <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core.Views-3.3.dll</HintPath>
@@ -427,10 +423,16 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0">
-      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-  </ItemGroup>
-  <ItemGroup>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis.Views\3.3\HeuristicLab.Analysis.Views-3.3.csproj">
+      <Project>{76945d76-ca61-4147-9dc2-0acdcddf87f9}</Project>
+      <Name>HeuristicLab.Analysis.Views-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
       <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/RunView.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/RunView.cs	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/RunView.cs	(revision 15719)
@@ -97,4 +97,8 @@
 
     private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      if (InvokeRequired) {
+        Invoke((Action<object, PropertyChangedEventArgs>)Content_PropertyChanged, sender, e);
+        return;
+      }
       if (e.PropertyName == "Color") {
         if (InvokeRequired) this.Invoke((Action)UpdateColor, null);
@@ -112,4 +116,8 @@
 
     private void ParametersOnItemsChanged(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      if (InvokeRequired) {
+        Invoke((Action<object, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>>>)ParametersOnItemsChanged, sender, e);
+        return;
+      }
       foreach (var item in e.OldItems) {
         listView.Items.Remove(parametersItemToListViewItem[item.Key]);
@@ -124,4 +132,8 @@
 
     private void ParametersOnItemsRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      if (InvokeRequired) {
+        Invoke((Action<object, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>>>)ParametersOnItemsRemoved, sender, e);
+        return;
+      }
       foreach (var item in e.Items) {
         listView.Items.Remove(parametersItemToListViewItem[item.Key]);
@@ -131,4 +143,8 @@
 
     private void ResultsOnItemsChanged(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      if (InvokeRequired) {
+        Invoke((Action<object, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>>>)ResultsOnItemsChanged, sender, e);
+        return;
+      }
       foreach (var item in e.OldItems) {
         listView.Items.Remove(resultsItemToListViewItem[item.Key]);
@@ -143,4 +159,8 @@
 
     private void ResultsOnItemsRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      if (InvokeRequired) {
+        Invoke((Action<object, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>>>)ResultsOnItemsRemoved, sender, e);
+        return;
+      }
       foreach (var item in e.Items) {
         listView.Items.Remove(resultsItemToListViewItem[item.Key]);
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Algorithms/Algorithm.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Algorithms/Algorithm.cs	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Algorithms/Algorithm.cs	(revision 15719)
@@ -221,5 +221,6 @@
     }
     public virtual void CollectResultValues(IDictionary<string, IItem> values) {
-      values.Add("Execution Time", new TimeSpanValue(ExecutionTime));
+      if (!Results.ContainsKey("Execution Time"))
+        values.Add("Execution Time", new TimeSpanValue(ExecutionTime));
       Results.CollectResultValues(values);
     }
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Algorithms/EngineAlgorithm.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Algorithms/EngineAlgorithm.cs	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Algorithms/EngineAlgorithm.cs	(revision 15719)
@@ -170,4 +170,5 @@
         context = new ExecutionContext(context, operatorGraph.InitialOperator, globalScope);
         engine.Prepare(context);
+        engine.Log.Clear();
       }
     }
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 15719)
@@ -158,4 +158,6 @@
     <Compile Include="Interfaces\IPopulationReducer.cs" />
     <Compile Include="MultiObjective\DominationCalculator.cs" />
+    <Compile Include="Interfaces\IPreexistingSolutionCreator.cs" />
+    <Compile Include="Interfaces\ISolutionModel.cs" />
     <Compile Include="Results\IResultParameter.cs" />
     <Compile Include="Interfaces\ISingleObjectiveOperator.cs" />
@@ -173,4 +175,7 @@
     <Compile Include="MetaOptimizers\TimeLimitRun.cs" />
     <Compile Include="Results\ResultParameter.cs" />
+    <Compile Include="RunCollection.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="RunCollectionModification\RunCollectionRunRemover.cs" />
     <Compile Include="Plugin.cs" />
@@ -230,5 +235,4 @@
     <Compile Include="OptimizerList.cs" />
     <Compile Include="Interfaces\IOptimizer.cs" />
-    <Compile Include="RunCollection.cs" />
     <Compile Include="Run.cs" />
     <Compile Include="Results\IResult.cs" />
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Interfaces/IPreexistingSolutionCreator.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Interfaces/IPreexistingSolutionCreator.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Interfaces/IPreexistingSolutionCreator.cs	(revision 15719)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IPreexistingSolutionCreator : ISolutionCreator {
+    IValueLookupParameter<ScopeList> PreexistingSolutionsParameter { get; }
+    IValueLookupParameter<BoolValue> SampleFromPreexistingParameter { get; }
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Interfaces/ISolutionModel.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Interfaces/ISolutionModel.cs	(revision 15719)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Interfaces/ISolutionModel.cs	(revision 15719)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface ISolutionModel<TSolution> : IItem {
+    TSolution Sample();
+  }
+}
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Results/ResultParameter.cs
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Results/ResultParameter.cs	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/Results/ResultParameter.cs	(revision 15719)
@@ -40,4 +40,5 @@
       get { return resultCollectionName; }
       set {
+        if (value == null) throw new ArgumentNullException();
         if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException();
         else if (!value.Equals(resultCollectionName)) {
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 15719)
@@ -42,8 +42,4 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0">
-      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
     <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
       <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
@@ -146,4 +142,9 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Encodings.IntegerVectorEncoding\3.3\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj">
       <Project>{ddfb14dd-2a85-493c-a52d-e69729bbaeb0}</Project>
Index: /branches/1614_GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj
===================================================================
--- /branches/1614_GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 15718)
+++ /branches/1614_GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 15719)
@@ -41,8 +41,4 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0">
-      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
     <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
       <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
@@ -162,4 +158,9 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Encodings.IntegerVectorEncoding\3.3\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj">
       <Project>{ddfb14dd-2a85-493c-a52d-e69729bbaeb0}</Project>
