Index: trunk/sources/HeuristicLab 3.3.sln
===================================================================
--- trunk/sources/HeuristicLab 3.3.sln	(revision 6614)
+++ trunk/sources/HeuristicLab 3.3.sln	(revision 6628)
@@ -407,4 +407,6 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.PluginInfrastructure-3.3.Tests", "HeuristicLab.PluginInfrastructure\3.3\Tests\HeuristicLab.PluginInfrastructure-3.3.Tests.csproj", "{04840E7E-F7DB-4CE4-B308-EE805DD94E73}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3", "HeuristicLab.Problems.QuadraticAssignment.Algorithms\3.3\HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj", "{5B9B9E8C-2706-43C2-80B8-A08341E431F7}"
 EndProject
 Global
@@ -1873,4 +1875,16 @@
 		{04840E7E-F7DB-4CE4-B308-EE805DD94E73}.Release|x86.ActiveCfg = Release|x86
 		{04840E7E-F7DB-4CE4-B308-EE805DD94E73}.Release|x86.Build.0 = Release|x86
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Debug|x64.ActiveCfg = Debug|x64
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Debug|x64.Build.0 = Debug|x64
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Debug|x86.ActiveCfg = Debug|x86
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Debug|x86.Build.0 = Debug|x86
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Release|x64.ActiveCfg = Release|x64
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Release|x64.Build.0 = Release|x64
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Release|x86.ActiveCfg = Release|x86
+		{5B9B9E8C-2706-43C2-80B8-A08341E431F7}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs	(revision 6628)
@@ -73,4 +73,6 @@
       this.lineStyleComboBox = new System.Windows.Forms.ComboBox();
       this.label8 = new System.Windows.Forms.Label();
+      this.label9 = new System.Windows.Forms.Label();
+      this.displayNameTextBox = new System.Windows.Forms.TextBox();
       ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).BeginInit();
       this.commonGroupBox.SuspendLayout();
@@ -88,7 +90,7 @@
       this.chartTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.chartTypeComboBox.FormattingEnabled = true;
-      this.chartTypeComboBox.Location = new System.Drawing.Point(76, 19);
+      this.chartTypeComboBox.Location = new System.Drawing.Point(89, 45);
       this.chartTypeComboBox.Name = "chartTypeComboBox";
-      this.chartTypeComboBox.Size = new System.Drawing.Size(224, 21);
+      this.chartTypeComboBox.Size = new System.Drawing.Size(211, 21);
       this.chartTypeComboBox.TabIndex = 1;
       this.chartTypeComboBox.SelectedValueChanged += new System.EventHandler(this.chartTypeComboBox_SelectedValueChanged);
@@ -101,5 +103,5 @@
       // 
       this.colorButton.BackColor = System.Drawing.SystemColors.Control;
-      this.colorButton.Location = new System.Drawing.Point(76, 46);
+      this.colorButton.Location = new System.Drawing.Point(89, 72);
       this.colorButton.Name = "colorButton";
       this.colorButton.Size = new System.Drawing.Size(23, 23);
@@ -140,14 +142,14 @@
       // 
       this.label1.AutoSize = true;
-      this.label1.Location = new System.Drawing.Point(8, 22);
+      this.label1.Location = new System.Drawing.Point(8, 48);
       this.label1.Name = "label1";
-      this.label1.Size = new System.Drawing.Size(62, 13);
+      this.label1.Size = new System.Drawing.Size(58, 13);
       this.label1.TabIndex = 0;
-      this.label1.Text = "Chart Type:";
+      this.label1.Text = "Chart type:";
       // 
       // label2
       // 
       this.label2.AutoSize = true;
-      this.label2.Location = new System.Drawing.Point(8, 51);
+      this.label2.Location = new System.Drawing.Point(8, 77);
       this.label2.Name = "label2";
       this.label2.Size = new System.Drawing.Size(34, 13);
@@ -168,6 +170,8 @@
       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.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);
@@ -175,5 +179,5 @@
       this.commonGroupBox.Location = new System.Drawing.Point(3, 3);
       this.commonGroupBox.Name = "commonGroupBox";
-      this.commonGroupBox.Size = new System.Drawing.Size(313, 158);
+      this.commonGroupBox.Size = new System.Drawing.Size(313, 181);
       this.commonGroupBox.TabIndex = 0;
       this.commonGroupBox.TabStop = false;
@@ -186,10 +190,10 @@
       this.axisGroupBox.Controls.Add(this.panel1);
       this.axisGroupBox.Controls.Add(this.panel2);
-      this.axisGroupBox.Location = new System.Drawing.Point(6, 75);
+      this.axisGroupBox.Location = new System.Drawing.Point(6, 101);
       this.axisGroupBox.Name = "axisGroupBox";
       this.axisGroupBox.Size = new System.Drawing.Size(299, 75);
       this.axisGroupBox.TabIndex = 9;
       this.axisGroupBox.TabStop = false;
-      this.axisGroupBox.Text = "Display Data on";
+      this.axisGroupBox.Text = "Display data on";
       // 
       // label5
@@ -200,5 +204,5 @@
       this.label5.Size = new System.Drawing.Size(39, 13);
       this.label5.TabIndex = 6;
-      this.label5.Text = "Y Axis:";
+      this.label5.Text = "Y-Axis:";
       // 
       // label6
@@ -209,5 +213,5 @@
       this.label6.Size = new System.Drawing.Size(39, 13);
       this.label6.TabIndex = 6;
-      this.label6.Text = "X Axis:";
+      this.label6.Text = "X-Axis:";
       // 
       // panel1
@@ -284,5 +288,5 @@
       this.histoGramGroupBox.Controls.Add(this.binsNumericUpDown);
       this.histoGramGroupBox.Controls.Add(this.label3);
-      this.histoGramGroupBox.Location = new System.Drawing.Point(3, 269);
+      this.histoGramGroupBox.Location = new System.Drawing.Point(3, 292);
       this.histoGramGroupBox.Name = "histoGramGroupBox";
       this.histoGramGroupBox.Size = new System.Drawing.Size(313, 49);
@@ -334,10 +338,10 @@
       this.lineChartGroupBox.Controls.Add(this.lineStyleComboBox);
       this.lineChartGroupBox.Controls.Add(this.label8);
-      this.lineChartGroupBox.Location = new System.Drawing.Point(3, 167);
+      this.lineChartGroupBox.Location = new System.Drawing.Point(3, 190);
       this.lineChartGroupBox.Name = "lineChartGroupBox";
       this.lineChartGroupBox.Size = new System.Drawing.Size(313, 96);
       this.lineChartGroupBox.TabIndex = 1;
       this.lineChartGroupBox.TabStop = false;
-      this.lineChartGroupBox.Text = "Line Chart";
+      this.lineChartGroupBox.Text = "Line chart";
       // 
       // lineWidthNumericUpDown
@@ -364,7 +368,7 @@
       this.label4.Location = new System.Drawing.Point(8, 68);
       this.label4.Name = "label4";
-      this.label4.Size = new System.Drawing.Size(61, 13);
+      this.label4.Size = new System.Drawing.Size(58, 13);
       this.label4.TabIndex = 4;
-      this.label4.Text = "Line Width:";
+      this.label4.Text = "Line width:";
       // 
       // label7
@@ -373,7 +377,7 @@
       this.label7.Location = new System.Drawing.Point(8, 46);
       this.label7.Name = "label7";
-      this.label7.Size = new System.Drawing.Size(82, 13);
+      this.label7.Size = new System.Drawing.Size(81, 13);
       this.label7.TabIndex = 2;
-      this.label7.Text = "Start Index at 0:";
+      this.label7.Text = "Start index at 0:";
       // 
       // lineStyleComboBox
@@ -392,7 +396,24 @@
       this.label8.Location = new System.Drawing.Point(8, 22);
       this.label8.Name = "label8";
-      this.label8.Size = new System.Drawing.Size(56, 13);
+      this.label8.Size = new System.Drawing.Size(54, 13);
       this.label8.TabIndex = 0;
-      this.label8.Text = "Line Style:";
+      this.label8.Text = "Line style:";
+      // 
+      // label9
+      // 
+      this.label9.AutoSize = true;
+      this.label9.Location = new System.Drawing.Point(8, 22);
+      this.label9.Name = "label9";
+      this.label9.Size = new System.Drawing.Size(75, 13);
+      this.label9.TabIndex = 0;
+      this.label9.Text = "Display Name:";
+      // 
+      // displayNameTextBox
+      // 
+      this.displayNameTextBox.Location = new System.Drawing.Point(89, 19);
+      this.displayNameTextBox.Name = "displayNameTextBox";
+      this.displayNameTextBox.Size = new System.Drawing.Size(211, 20);
+      this.displayNameTextBox.TabIndex = 10;
+      this.displayNameTextBox.Validated += new System.EventHandler(this.displayNameTextBox_Validated);
       // 
       // DataRowVisualPropertiesControl
@@ -404,5 +425,5 @@
       this.Controls.Add(this.commonGroupBox);
       this.Name = "DataRowVisualPropertiesControl";
-      this.Size = new System.Drawing.Size(319, 323);
+      this.Size = new System.Drawing.Size(319, 347);
       ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).EndInit();
       this.commonGroupBox.ResumeLayout(false);
@@ -455,4 +476,6 @@
     private System.Windows.Forms.Label label5;
     private System.Windows.Forms.GroupBox axisGroupBox;
+    private System.Windows.Forms.TextBox displayNameTextBox;
+    private System.Windows.Forms.Label label9;
   }
 }
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs	(revision 6628)
@@ -64,4 +64,5 @@
           binsApproximatelyRadioButton.Checked = false;
           binsExactRadioButton.Checked = false;
+          displayNameTextBox.Text = String.Empty;
         } else {
           chartTypeComboBox.SelectedItem = Content.ChartType;
@@ -83,4 +84,5 @@
           binsApproximatelyRadioButton.Checked = !Content.ExactBins;
           binsExactRadioButton.Checked = Content.ExactBins;
+          displayNameTextBox.Text = Content.DisplayName;
         }
       } finally { SuppressEvents = false; }
@@ -168,4 +170,13 @@
       }
     }
+
+    private void displayNameTextBox_Validated(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.DisplayName = displayNameTextBox.Text;
+        } finally { SuppressEvents = false; }
+      }
+    }
     #endregion
   }
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs	(revision 6628)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Collections.Generic;
 using System.Windows.Forms;
 using HeuristicLab.Core.Views;
@@ -38,9 +39,19 @@
       using (DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(current)) {
         if (dialog.ShowDialog() != DialogResult.OK) return;
+        Dictionary<string, bool> changeDisplayName = new Dictionary<string, bool>();
+        foreach (DataRow row in current.Rows) {
+          var answer = MessageBox.Show("Change display name for series " + row.Name + " to " + row.VisualProperties.DisplayName + " for all frames?", "Confirm change", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
+          if (answer == DialogResult.Cancel) return;
+          changeDisplayName[row.Name] = (answer == DialogResult.Yes);
+        }
         foreach (DataTable dt in Content) {
-          if (current != dt) {
-            dt.VisualProperties = (DataTableVisualProperties)current.VisualProperties.Clone();
-            foreach (DataRow row in current.Rows)
-              dt.Rows[row.Name].VisualProperties = (DataRowVisualProperties)row.VisualProperties.Clone();
+          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;
+            var props = (DataRowVisualProperties)row.VisualProperties.Clone();
+            if (!changeDisplayName[row.Name]) props.DisplayName = oldDisplayName;
+            dt.Rows[row.Name].VisualProperties = props;
           }
         }
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 6628)
@@ -159,4 +159,6 @@
     protected virtual void AddDataRow(DataRow row) {
       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);
@@ -212,5 +214,7 @@
       series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
       series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary;
-      series.ToolTip = row.Name + " X = #INDEX, Y = #VAL";
+      if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
+      else series.LegendText = row.Name;
+      series.ToolTip = series.LegendText + " X = #INDEX, Y = #VAL";
     }
 
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs	(revision 6628)
@@ -69,5 +69,5 @@
       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.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-      this.okButton.Location = new System.Drawing.Point(307, 357);
+      this.okButton.Location = new System.Drawing.Point(307, 381);
       this.okButton.Name = "okButton";
       this.okButton.Size = new System.Drawing.Size(75, 23);
@@ -81,5 +81,5 @@
       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(388, 357);
+      this.cancelButton.Location = new System.Drawing.Point(388, 381);
       this.cancelButton.Name = "cancelButton";
       this.cancelButton.Size = new System.Drawing.Size(75, 23);
@@ -99,5 +99,5 @@
       this.tabControl.Name = "tabControl";
       this.tabControl.SelectedIndex = 0;
-      this.tabControl.Size = new System.Drawing.Size(474, 350);
+      this.tabControl.Size = new System.Drawing.Size(474, 374);
       this.tabControl.TabIndex = 2;
       // 
@@ -108,5 +108,5 @@
       this.seriesTabPage.Name = "seriesTabPage";
       this.seriesTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.seriesTabPage.Size = new System.Drawing.Size(466, 324);
+      this.seriesTabPage.Size = new System.Drawing.Size(466, 348);
       this.seriesTabPage.TabIndex = 0;
       this.seriesTabPage.Text = "Series";
@@ -131,5 +131,5 @@
       this.splitContainer.Panel2.Controls.Add(this.dataRowVisualPropertiesControl);
       this.splitContainer.Panel2MinSize = 50;
-      this.splitContainer.Size = new System.Drawing.Size(460, 318);
+      this.splitContainer.Size = new System.Drawing.Size(460, 342);
       this.splitContainer.SplitterDistance = 125;
       this.splitContainer.TabIndex = 0;
@@ -165,5 +165,5 @@
       this.seriesListView.Name = "seriesListView";
       this.seriesListView.ShowGroups = false;
-      this.seriesListView.Size = new System.Drawing.Size(125, 289);
+      this.seriesListView.Size = new System.Drawing.Size(125, 313);
       this.seriesListView.TabIndex = 0;
       this.seriesListView.UseCompatibleStateImageBehavior = false;
@@ -177,5 +177,5 @@
       this.dataRowVisualPropertiesControl.Location = new System.Drawing.Point(0, 0);
       this.dataRowVisualPropertiesControl.Name = "dataRowVisualPropertiesControl";
-      this.dataRowVisualPropertiesControl.Size = new System.Drawing.Size(331, 318);
+      this.dataRowVisualPropertiesControl.Size = new System.Drawing.Size(331, 342);
       this.dataRowVisualPropertiesControl.TabIndex = 0;
       // 
@@ -206,5 +206,5 @@
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
       this.CancelButton = this.cancelButton;
-      this.ClientSize = new System.Drawing.Size(475, 392);
+      this.ClientSize = new System.Drawing.Size(475, 416);
       this.Controls.Add(this.tabControl);
       this.Controls.Add(this.cancelButton);
Index: trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRow.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRow.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRow.cs	(revision 6628)
@@ -83,15 +83,15 @@
     public DataRow(string name)
       : base(name) {
-      VisualProperties = new DataRowVisualProperties();
+      VisualProperties = new DataRowVisualProperties(name);
       values = new ObservableList<double>();
     }
     public DataRow(string name, string description)
       : base(name, description) {
-      VisualProperties = new DataRowVisualProperties();
+      VisualProperties = new DataRowVisualProperties(name);
       values = new ObservableList<double>();
     }
     public DataRow(string name, string description, IEnumerable<double> values)
       : base(name, description) {
-      VisualProperties = new DataRowVisualProperties();
+      VisualProperties = new DataRowVisualProperties(name);
       this.values = new ObservableList<double>(values);
     }
Index: trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 6628)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.ComponentModel;
 using System.Drawing;
@@ -141,4 +142,19 @@
       }
     }
+    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
@@ -187,4 +203,9 @@
       get { return exactBins; }
       set { exactBins = value; }
+    }
+    [Storable(Name = "DisplayName")]
+    private string StorableDisplayName {
+      get { return displayName; }
+      set { displayName = value; }
     }
     #endregion
@@ -203,4 +224,5 @@
       this.bins = original.bins;
       this.exactBins = original.exactBins;
+      this.displayName = original.displayName;
     }
     public DataRowVisualProperties() {
@@ -214,4 +236,9 @@
       bins = 10;
       exactBins = false;
+      displayName = String.Empty;
+    }
+    public DataRowVisualProperties(string displayName)
+      : this() {
+      this.displayName = displayName;
     }
 
Index: trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 6628)
@@ -139,4 +139,5 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="QualityAnalysis\QualityDistributionAnalyzer.cs" />
+    <Compile Include="QualityAnalysis\ScaledQualityDifferenceAnalyzer.cs" />
     <Compile Include="ValueAnalysis\MinAverageMaxValueAnalyzer.cs" />
     <Compile Include="ValueAnalysis\MinAverageMaxValueCalculator.cs" />
Index: trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 6628)
@@ -126,5 +126,5 @@
           string appendix = " at " + iterationName + " " + iteration.Value.ToString();
           table.Name += appendix;
-          table.Rows["QualityDistribution"].Name += appendix;
+          table.Rows["QualityDistribution"].VisualProperties.DisplayName += appendix;
         }
         qdHistory.Add(table);
Index: trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/ScaledQualityDifferenceAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/ScaledQualityDifferenceAnalyzer.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/ScaledQualityDifferenceAnalyzer.cs	(revision 6628)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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 {
+    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.ActualName, out r)) {
+          r = new Result(ScaledDifferenceParameter.ActualName, differenceValue);
+          results.Add(r);
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleArrayView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleArrayView.Designer.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleArrayView.Designer.cs	(revision 6628)
@@ -116,8 +116,8 @@
     #endregion
 
-    private System.Windows.Forms.Label lengthLabel;
-    private System.Windows.Forms.TextBox lengthTextBox;
-    private System.Windows.Forms.DataGridView dataGridView;
-    private System.Windows.Forms.ErrorProvider errorProvider;
+    protected System.Windows.Forms.DataGridView dataGridView;
+    protected System.Windows.Forms.Label lengthLabel;
+    protected System.Windows.Forms.TextBox lengthTextBox;
+    protected System.Windows.Forms.ErrorProvider errorProvider;
 
   }
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/HeuristicLab.Encodings.PermutationEncoding.Views-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/HeuristicLab.Encodings.PermutationEncoding.Views-3.3.csproj	(revision 6614)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/HeuristicLab.Encodings.PermutationEncoding.Views-3.3.csproj	(revision 6628)
@@ -12,5 +12,6 @@
     <AssemblyName>HeuristicLab.Encodings.PermutationEncoding.Views-3.3</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
-    <TargetFrameworkProfile></TargetFrameworkProfile>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
     <FileAlignment>512</FileAlignment>
     <SignAssembly>true</SignAssembly>
@@ -92,4 +93,8 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86" />
+    <Reference Include="HeuristicLab.Common.Resources-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86" />
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86" />
+    <Reference Include="HeuristicLab.Visualization.ChartControlsExtensions-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86" />
     <Reference Include="System" />
     <Reference Include="System.Core">
@@ -98,4 +103,5 @@
     <Reference Include="System.Drawing" />
     <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Forms.DataVisualization" />
     <Reference Include="System.Xml.Linq">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -115,4 +121,10 @@
     </Compile>
     <Compile Include="HeuristicLabEncodingsPermutationEncodingViewsPlugin.cs" />
+    <Compile Include="PermutationView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="PermutationView.Designer.cs">
+      <DependentUpon>PermutationView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
@@ -135,4 +147,8 @@
       <Name>HeuristicLab.Core-3.3</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data.Views\3.3\HeuristicLab.Data.Views-3.3.csproj">
+      <Project>{72104A0B-90E7-42F3-9ABE-9BBBADD4B943}</Project>
+      <Name>HeuristicLab.Data.Views-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
       <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
@@ -150,4 +166,8 @@
       <Project>{3BD61258-31DA-4B09-89C0-4F71FEF5F05A}</Project>
       <Name>HeuristicLab.MainForm-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Views\3.3\HeuristicLab.Optimization.Views-3.3.csproj">
+      <Project>{662B4B15-8F4D-4AE5-B3EB-D91C215F5AF2}</Project>
+      <Name>HeuristicLab.Optimization.Views-3.3</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/HeuristicLabEncodingsPermutationEncodingViewsPlugin.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/HeuristicLabEncodingsPermutationEncodingViewsPlugin.cs.frame	(revision 6614)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/HeuristicLabEncodingsPermutationEncodingViewsPlugin.cs.frame	(revision 6628)
@@ -31,7 +31,9 @@
   [PluginDependency("HeuristicLab.Core.Views", "3.3")]
   [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Data.Views", "3.3")]
   [PluginDependency("HeuristicLab.Encodings.PermutationEncoding", "3.3")]
   [PluginDependency("HeuristicLab.MainForm", "3.3")]
   [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Views", "3.3")]
   public class HeuristicLabEncodingsPermutationEncodingViewsPlugin : PluginBase {
   }
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/PermutationView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/PermutationView.Designer.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/PermutationView.Designer.cs	(revision 6628)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Encodings.PermutationEncoding.Views {
+  partial class PermutationView {
+    /// <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.permutationTypeView = new HeuristicLab.Encodings.PermutationEncoding.Views.PermutationTypeView();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // lengthTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.lengthTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.lengthTextBox, 2);
+      // 
+      // permutationTypeView
+      // 
+      this.permutationTypeView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.permutationTypeView.Caption = "PermutationType View";
+      this.permutationTypeView.Content = null;
+      this.permutationTypeView.Location = new System.Drawing.Point(6, 26);
+      this.permutationTypeView.Name = "permutationTypeView";
+      this.permutationTypeView.ReadOnly = false;
+      this.permutationTypeView.Size = new System.Drawing.Size(418, 29);
+      this.permutationTypeView.TabIndex = 3;
+      // 
+      // PermutationView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.permutationTypeView);
+      this.Name = "PermutationView";
+      this.Controls.SetChildIndex(this.permutationTypeView, 0);
+      this.Controls.SetChildIndex(this.lengthLabel, 0);
+      this.Controls.SetChildIndex(this.lengthTextBox, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private PermutationTypeView permutationTypeView;
+
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/PermutationView.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/PermutationView.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding.Views/3.3/PermutationView.cs	(revision 6628)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Data.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Encodings.PermutationEncoding.Views {
+  [View("Permutation View")]
+  [Content(typeof(Permutation), IsDefaultView = true)]
+  public partial class PermutationView : StringConvertibleArrayView {
+    public new Permutation Content {
+      get { return (Permutation)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public PermutationView() {
+      InitializeComponent();
+      dataGridView.Top = permutationTypeView.Bottom + permutationTypeView.Margin.Bottom + dataGridView.Margin.Top;
+    }
+
+    #region Register Content Events
+    protected override void DeregisterContentEvents() {
+      Content.PermutationTypeChanged -= new System.EventHandler(Content_PermutationTypeChanged);
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.PermutationTypeChanged += new System.EventHandler(Content_PermutationTypeChanged);
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        if (permutationTypeView.Content != null)
+          permutationTypeView.Content.ValueChanged -= new System.EventHandler(PermutationTypeView_ValueChanged);
+        permutationTypeView.Content = null;
+      } else {
+        permutationTypeView.Content = new PermutationType(Content.PermutationType);
+        permutationTypeView.Content.ValueChanged += new System.EventHandler(PermutationTypeView_ValueChanged);
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+    }
+
+    #region Event Handlers
+
+    private void Content_PermutationTypeChanged(object sender, System.EventArgs e) {
+      if (permutationTypeView.Content.Value != Content.PermutationType)
+        permutationTypeView.Content.Value = Content.PermutationType;
+    }
+
+    private void PermutationTypeView_ValueChanged(object sender, System.EventArgs e) {
+      if (permutationTypeView.Content.Value != Content.PermutationType)
+        Content.PermutationType = permutationTypeView.Content.Value;
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Permutation.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Permutation.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Permutation.cs	(revision 6628)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -36,4 +37,9 @@
     public PermutationTypes PermutationType {
       get { return permutationType; }
+      set {
+        bool changed = (permutationType != value);
+        permutationType = value;
+        if (changed) OnPermutationTypeChanged();
+      }
     }
 
@@ -45,5 +51,6 @@
     }
     public Permutation() : this(PermutationTypes.RelativeUndirected) { }
-    public Permutation(PermutationTypes type) : base() {
+    public Permutation(PermutationTypes type)
+      : base() {
       permutationType = type;
     }
@@ -58,8 +65,10 @@
       Randomize(random);
     }
-    public Permutation(PermutationTypes type, int[] elements) : base(elements) {
+    public Permutation(PermutationTypes type, int[] elements)
+      : base(elements) {
       permutationType = type;
     }
-    public Permutation(PermutationTypes type, IntArray elements) : this(type, elements.Length) {
+    public Permutation(PermutationTypes type, IntArray elements)
+      : this(type, elements.Length) {
       for (int i = 0; i < array.Length; i++)
         array[i] = elements[i];
@@ -111,4 +120,11 @@
       return this[position];
     }
+
+    public event EventHandler PermutationTypeChanged;
+
+    protected virtual void OnPermutationTypeChanged() {
+      var handler = PermutationTypeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentTreeView.cs
===================================================================
--- trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentTreeView.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentTreeView.cs	(revision 6628)
@@ -576,5 +576,5 @@
     private void treeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
       if (rightClickOccured) return;
-      if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return;
+      if (e.X < e.Node.Bounds.Left - treeView.ImageList.Images[e.Node.ImageIndex].Width || e.X > e.Node.Bounds.Right) return;
       e.Node.Toggle();
       IContent optimizer = (IContent)e.Node.Tag;
@@ -582,5 +582,5 @@
     }
     private void treeview_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
-      if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return;
+      if (e.X < e.Node.Bounds.Left - treeView.ImageList.Images[e.Node.ImageIndex].Width || e.X > e.Node.Bounds.Right) return;
       treeView.SelectedNode = e.Node;
       detailsViewHost.Content = (IContent)e.Node.Tag;
@@ -593,5 +593,5 @@
       Point coordinates = new Point(e.X, e.Y);
       TreeNode node = treeView.GetNodeAt(coordinates);
-      if (node == null || coordinates.X < node.Bounds.Left || coordinates.X > node.Bounds.Right) {
+      if (node == null || coordinates.X < node.Bounds.Left - treeView.ImageList.Images[node.ImageIndex].Width || coordinates.X > node.Bounds.Right) {
         treeView.SelectedNode = null;
         detailsViewHost.Content = null;
@@ -723,6 +723,5 @@
             algorithm.Problem = problem;
           }
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
           ErrorHandling.ShowErrorDialog(this, ex);
         }
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj	(revision 6628)
@@ -0,0 +1,202 @@
+﻿<?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>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5B9B9E8C-2706-43C2-80B8-A08341E431F7}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.QuadraticAssignment.Algorithms</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Plugin.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\Plugin.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Plugin.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\Plugin.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+    <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="RobustTabooSeachOperator.cs" />
+    <Compile Include="RobustTabooSearch.cs" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </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>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.PermutationEncoding\3.3\HeuristicLab.Encodings.PermutationEncoding-3.3.csproj">
+      <Project>{DBECB8B0-B166-4133-BAF1-ED67C3FD7FCA}</Project>
+      <Name>HeuristicLab.Encodings.PermutationEncoding-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
+      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
+      <Name>HeuristicLab.Operators-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
+      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
+      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
+      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
+      <Name>HeuristicLab.Parameters-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
+      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
+      <Name>HeuristicLab.Persistence-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.QuadraticAssignment\3.3\HeuristicLab.Problems.QuadraticAssignment-3.3.csproj">
+      <Project>{79271BC8-4446-40E2-BB89-9BE4E17174FE}</Project>
+      <Name>HeuristicLab.Problems.QuadraticAssignment-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{F4539FB6-4708-40C9-BE64-0A1390AEA197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+SubWCRev "%25ProjectDir%25\" "%25ProjectDir%25\Plugin.cs.frame" "%25ProjectDir%25\Plugin.cs"</PreBuildEvent>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <!-- 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>
+  -->
+</Project>
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/Plugin.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/Plugin.cs.frame	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/Plugin.cs.frame	(revision 6628)
@@ -0,0 +1,43 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Problems.QuadraticAssignment.Algorithms {
+  [Plugin("HeuristicLab.Problems.QuadraticAssignment.Algorithms", "3.3.4.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.dll", PluginFileType.Assembly)]
+  [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.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.PermutationEncoding", "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")]
+  [PluginDependency("HeuristicLab.Problems.QuadraticAssignment", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabProblemsQuadraticAssignmentAlgorithmsPlugin : PluginBase {
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.frame
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.frame	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.frame	(revision 6628)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Problems.QuadraticAssignment.Algorithms")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2011 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("7c14407e-6980-465b-ba3a-4a916d48989b")]
+
+// 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 Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.4.$WCREV$")]
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/QAPRandomizedRobustTabooSeachOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/QAPRandomizedRobustTabooSeachOperator.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/QAPRandomizedRobustTabooSeachOperator.cs	(revision 6628)
@@ -0,0 +1,259 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
+  [Item("QAPRandomizedRobustTabooSeachOperator", "Performs an iteration of a modified robust taboo search algorithm based on Taillard 1991.")]
+  public sealed class QAPRandomizedRobustTabooSeachOperator : SingleSuccessorOperator, IIterationBasedOperator, IStochasticOperator {
+
+    #region Parameter Properties
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public ILookupParameter<IntValue> TabuTenureParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["TabuTenure"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public ILookupParameter<IntMatrix> ShortTermMemoryParameter {
+      get { return (ILookupParameter<IntMatrix>)Parameters["ShortTermMemory"]; }
+    }
+    public ILookupParameter<DoubleMatrix> ShortTermMemory2Parameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["ShortTermMemory2"]; }
+    }
+    public ILookupParameter<IntMatrix> LongTermMemoryParameter {
+      get { return (ILookupParameter<IntMatrix>)Parameters["LongTermMemory"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public ILookupParameter<IntValue> LastGlobalImprovementParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LastGlobalImprovement"]; }
+    }
+    public ILookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    public IValueLookupParameter<IntValue> MinimumTabuTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MinimumTabuTenure"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumTabuTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
+    }
+    public IValueLookupParameter<IntValue> TabuTenureAdaptionIntervalParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["TabuTenureAdaptionInterval"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private QAPRandomizedRobustTabooSeachOperator(bool deserializing) : base(deserializing) { }
+    private QAPRandomizedRobustTabooSeachOperator(QAPRandomizedRobustTabooSeachOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QAPRandomizedRobustTabooSeachOperator() {
+      Parameters.Add(new LookupParameter<IntValue>("Iterations", "The current iteration."));
+      Parameters.Add(new LookupParameter<IntValue>("TabuTenure", "The current tabu tenure."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation solution."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+      Parameters.Add(new LookupParameter<IntMatrix>("ShortTermMemory", "The table that stores the iteration at which a certain facility has been assigned to a certain location."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("ShortTermMemory2", "The table that stores the quality at which a certain facility has been assigned to a certain location."));
+      Parameters.Add(new LookupParameter<IntMatrix>("LongTermMemory", "Same as the tabu table, but constantly updates the information given the current solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestQuality", "The best quality value."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("TabuTenureAdaptionInterval", "The amount of iterations that have to pass before the tabu tenure is adapted."));
+      Parameters.Add(new LookupParameter<IntValue>("LastGlobalImprovement", "The iteration at which the best solution so far has been improved."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The best known quality is just used to store the iteration at which it was found."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection to store results to."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPRandomizedRobustTabooSeachOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ResultCollection results = ResultsParameter.ActualValue;
+      IRandom random = RandomParameter.ActualValue;
+      int iteration = IterationsParameter.ActualValue.Value;
+
+      IntMatrix longTermMemory = LongTermMemoryParameter.ActualValue;
+      IntMatrix shortTermMemory = ShortTermMemoryParameter.ActualValue;
+      DoubleMatrix shortTermMemory2 = ShortTermMemory2Parameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+
+      DoubleValue quality = QualityParameter.ActualValue;
+      DoubleValue bestQuality = BestQualityParameter.ActualValue;
+      if (bestQuality == null) {
+        BestQualityParameter.ActualValue = (DoubleValue)quality.Clone();
+        bestQuality = BestQualityParameter.ActualValue;
+      }
+
+      Permutation solution = PermutationParameter.ActualValue;
+
+      for (int i = 0; i < solution.Length; i++)
+        longTermMemory[i, solution[i]] = iteration;
+
+      double minQuality = double.MaxValue, maxQuality = double.MinValue,
+        minImprovement = double.MaxValue, maxImprovement = double.MinValue,
+        minRevist = double.MaxValue, maxRevist = double.MinValue;
+      Swap2Move[] moves = ExhaustiveSwap2MoveGenerator.Apply(solution);
+      double[] moveQualities = new double[moves.Length];
+      for (int i = 0; i < moves.Length; i++) {
+        Swap2Move move = moves[i];
+        double moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances);
+        moveQualities[i] = moveQuality;
+        if (moveQuality < minQuality) minQuality = moveQuality;
+        if (moveQuality > maxQuality) maxQuality = moveQuality;
+
+        double improvement = 0;
+        if (shortTermMemory[move.Index1, solution[move.Index2]] > 0)
+          improvement += Math.Max(0, shortTermMemory2[move.Index1, solution[move.Index2]] - quality.Value + moveQuality);
+        if (shortTermMemory[move.Index2, solution[move.Index1]] > 0)
+          improvement += Math.Max(0, shortTermMemory2[move.Index2, solution[move.Index1]] - quality.Value + moveQuality);
+        if (improvement > 0) {
+          if (improvement < minImprovement) minImprovement = improvement;
+          if (improvement > maxImprovement) maxImprovement = improvement;
+        }
+
+        double revisit = 0;
+        revisit += Math.Max(0, quality.Value - shortTermMemory2[move.Index1, solution[move.Index2]]);
+        revisit += Math.Max(0, quality.Value - shortTermMemory2[move.Index2, solution[move.Index1]]);
+        if (revisit > 0) {
+          if (revisit < minRevist) minRevist = revisit;
+          if (revisit > maxRevist) maxRevist = revisit;
+        }
+      }
+
+      Swap2Move selectedMove = null;
+      double bestInterestingness = double.MinValue, selectedMoveQuality = 0;
+      int equalInterestingCount = 0;
+      for (int i = 0; i < moves.Length; i++) {
+        Swap2Move move = moves[i];
+
+        double interestingness = 0;
+
+        if (maxQuality > minQuality)
+          interestingness += 4 * (maxQuality - moveQualities[i]) / (maxQuality - minQuality);
+
+        if (maxImprovement > minImprovement) {
+          double improvement = 0;
+          if (shortTermMemory[move.Index1, solution[move.Index2]] > 0)
+            improvement += Math.Max(0, shortTermMemory2[move.Index1, solution[move.Index2]] - quality.Value + moveQualities[i]);
+          if (shortTermMemory[move.Index2, solution[move.Index1]] > 0)
+            improvement += Math.Max(0, shortTermMemory2[move.Index2, solution[move.Index1]] - quality.Value + moveQualities[i]);
+          if (improvement > 0)
+            interestingness += 2 * (improvement - minImprovement) / (maxImprovement - minImprovement);
+        }
+
+        if (iteration > 0) {
+          interestingness += ((double)(iteration - longTermMemory[move.Index1, solution[move.Index2]]) / (double)iteration)
+            + ((double)(iteration - longTermMemory[move.Index2, solution[move.Index1]]) / (double)iteration);
+        }
+
+        if (maxRevist > minRevist) {
+          double revisit = 0;
+          revisit += Math.Max(0, quality.Value - shortTermMemory2[move.Index1, solution[move.Index2]]);
+          revisit += Math.Max(0, quality.Value - shortTermMemory2[move.Index2, solution[move.Index1]]);
+          if (revisit > 0)
+            interestingness += (revisit - minRevist) / (maxRevist - minRevist);
+        }
+
+        if (quality.Value + moveQualities[i] < bestQuality.Value) interestingness = double.MaxValue;
+        if (interestingness > bestInterestingness) {
+          bestInterestingness = interestingness;
+          selectedMove = moves[i];
+          selectedMoveQuality = moveQualities[i];
+          equalInterestingCount = 1;
+        } else if (interestingness == bestInterestingness) {
+          equalInterestingCount++;
+          if (random.NextDouble() < 1.0 / equalInterestingCount) {
+            selectedMove = moves[i];
+            selectedMoveQuality = moveQualities[i];
+          }
+        }
+      }
+
+      shortTermMemory[selectedMove.Index1, solution[selectedMove.Index1]] = iteration;
+      shortTermMemory[selectedMove.Index2, solution[selectedMove.Index2]] = iteration;
+      if (shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index2]] > 0)
+        shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index2]] = Math.Min(quality.Value + selectedMoveQuality, shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index2]]);
+      else shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index2]] = quality.Value + selectedMoveQuality;
+      if (shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index1]] > 0)
+        shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index1]] = Math.Min(quality.Value, shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index1]]);
+      else shortTermMemory2[selectedMove.Index1, solution[selectedMove.Index1]] = quality.Value;
+      if (shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index1]] > 0)
+        shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index1]] = Math.Min(quality.Value + selectedMoveQuality, shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index1]]);
+      else shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index1]] = quality.Value + selectedMoveQuality;
+      if (shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index2]] > 0)
+        shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index2]] = Math.Min(quality.Value, shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index2]]);
+      else shortTermMemory2[selectedMove.Index2, solution[selectedMove.Index2]] = quality.Value;
+
+      Swap2Manipulator.Apply(solution, selectedMove.Index1, selectedMove.Index2);
+      quality.Value += selectedMoveQuality;
+
+      if (quality.Value < bestQuality.Value) {
+        bestQuality.Value = quality.Value;
+        if (LastGlobalImprovementParameter.ActualValue == null)
+          LastGlobalImprovementParameter.ActualValue = new IntValue(iteration);
+        else LastGlobalImprovementParameter.ActualValue.Value = iteration;
+      }
+      if (!results.ContainsKey("GlobalBestFound")) results.Add(new Result("GlobalBestFound", new IntValue(-1)));
+      if (BestKnownQualityParameter.ActualValue.Value == bestQuality.Value
+        && ((IntValue)results["GlobalBestFound"].Value).Value < 0) {
+        ((IntValue)results["GlobalBestFound"].Value).Value = iteration;
+      }
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RandomizedRobustTabooSearch.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RandomizedRobustTabooSearch.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RandomizedRobustTabooSearch.cs	(revision 6628)
@@ -0,0 +1,286 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
+  [Item("Randomized Robust Taboo Search (QAP)", "This algorithm is based on Taillard, E. 1991. Robust Taboo Search for the Quadratic Assignment Problem. Parallel Computing 17, pp. 443-455.")]
+  [Creatable("Algorithms")]
+  [StorableClass]
+  public sealed class RandomizedRobustTabooSearchQAP : HeuristicOptimizationEngineAlgorithm, IStorableContent {
+    public string Filename { get; set; }
+
+    #region Problem Properties
+    public override Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+    public new QuadraticAssignmentProblem Problem {
+      get { return (QuadraticAssignmentProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+    #endregion
+
+    #region Parameter Properties
+    private FixedValueParameter<MultiAnalyzer> AnalyzerParameter {
+      get { return (FixedValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
+    }
+    private FixedValueParameter<IntValue> SeedParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["Seed"]; }
+    }
+    private FixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return (FixedValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
+    }
+    private FixedValueParameter<IntValue> MaximumIterationsParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    private FixedValueParameter<IntValue> MinimumTabuTenureParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["MinimumTabuTenure"]; }
+    }
+    private FixedValueParameter<IntValue> MaximumTabuTenureParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
+    }
+    private FixedValueParameter<IntValue> TabuTenureAdaptionIntervalParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["TabuTenureAdaptionInterval"]; }
+    }
+    #endregion
+
+    #region Properties
+    public int Seed {
+      get { return SeedParameter.Value.Value; }
+      set { SeedParameter.Value.Value = value; }
+    }
+    public bool SetSeedRandomly {
+      get { return SetSeedRandomlyParameter.Value.Value; }
+      set { SetSeedRandomlyParameter.Value.Value = value; }
+    }
+    public int MaximumIterations {
+      get { return MaximumIterationsParameter.Value.Value; }
+      set { MaximumIterationsParameter.Value.Value = value; }
+    }
+    public int MinimumTabuTenure {
+      get { return MinimumTabuTenureParameter.Value.Value; }
+      set { MinimumTabuTenureParameter.Value.Value = value; }
+    }
+    public int MaximumTabuTenure {
+      get { return MaximumTabuTenureParameter.Value.Value; }
+      set { MaximumTabuTenureParameter.Value.Value = value; }
+    }
+    public int TabuTenureAdaptionInterval {
+      get { return TabuTenureAdaptionIntervalParameter.Value.Value; }
+      set { TabuTenureAdaptionIntervalParameter.Value.Value = value; }
+    }
+    #endregion
+
+    [Storable]
+    private SolutionsCreator solutionsCreator;
+    [Storable]
+    private QAPRandomizedRobustTabooSeachOperator mainOperator;
+    [Storable]
+    private BestAverageWorstQualityAnalyzer qualityAnalyzer;
+
+    [StorableConstructor]
+    private RandomizedRobustTabooSearchQAP(bool deserializing) : base(deserializing) { }
+    private RandomizedRobustTabooSearchQAP(RandomizedRobustTabooSearchQAP original, Cloner cloner)
+      : base(original, cloner) {
+      solutionsCreator = cloner.Clone(original.solutionsCreator);
+      mainOperator = cloner.Clone(original.mainOperator);
+      qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
+    }
+    public RandomizedRobustTabooSearchQAP() {
+      Parameters.Add(new FixedValueParameter<MultiAnalyzer>("Analyzer", "The analyzers that are applied after each iteration.", new MultiAnalyzer()));
+      Parameters.Add(new FixedValueParameter<IntValue>("Seed", "The seed value of the random number generator.", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("SetSeedRandomly", "True whether the seed should be set randomly for each run, false if it should be fixed.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run.", new IntValue(10000)));
+      Parameters.Add(new FixedValueParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure.", new IntValue(20)));
+      Parameters.Add(new FixedValueParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure.", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<IntValue>("TabuTenureAdaptionInterval", "The amount of iterations that have to pass before the tabu tenure is adapted.", new IntValue(60)));
+
+      qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
+      qualityAnalyzer.ResultsParameter.ActualName = "Results";
+      AnalyzerParameter.Value.Operators.Add(qualityAnalyzer);
+
+      RandomCreator randomCreator = new RandomCreator();
+      randomCreator.RandomParameter.ActualName = "Random";
+      randomCreator.SeedParameter.Value = null;
+      randomCreator.SeedParameter.ActualName = SeedParameter.Name;
+      randomCreator.SetSeedRandomlyParameter.Value = null;
+      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
+
+      OperatorGraph.InitialOperator = randomCreator;
+
+      VariableCreator variableCreator = new VariableCreator();
+      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Iterations", new IntValue(0)));
+      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("TabuTenure", new IntValue(0)));
+      randomCreator.Successor = variableCreator;
+
+      ResultsCollector resultsCollector = new ResultsCollector();
+      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Iterations", "The actual iteration."));
+      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("TabuTenure", "The actual tabu tenure."));
+      variableCreator.Successor = resultsCollector;
+
+      solutionsCreator = new SolutionsCreator();
+      solutionsCreator.NumberOfSolutions = new IntValue(1);
+      resultsCollector.Successor = solutionsCreator;
+
+      Placeholder analyzer = new Placeholder();
+      analyzer.Name = "(Analyzer)";
+      analyzer.OperatorParameter.ActualName = AnalyzerParameter.Name;
+      solutionsCreator.Successor = analyzer;
+
+      UniformSubScopesProcessor ussp = new UniformSubScopesProcessor();
+      analyzer.Successor = ussp;
+
+      mainOperator = new QAPRandomizedRobustTabooSeachOperator();
+      mainOperator.BestQualityParameter.ActualName = "BestSoFarQuality";
+      mainOperator.IterationsParameter.ActualName = "Iterations";
+      mainOperator.LongTermMemoryParameter.ActualName = "LongTermMemory";
+      mainOperator.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
+      mainOperator.MaximumTabuTenureParameter.ActualName = MaximumTabuTenureParameter.Name;
+      mainOperator.MinimumTabuTenureParameter.ActualName = MinimumTabuTenureParameter.Name;
+      mainOperator.RandomParameter.ActualName = "Random";
+      mainOperator.ShortTermMemoryParameter.ActualName = "ShortTermMemory";
+      mainOperator.TabuTenureAdaptionIntervalParameter.ActualName = TabuTenureAdaptionIntervalParameter.Name;
+      mainOperator.TabuTenureParameter.ActualName = "TabuTenure";
+      mainOperator.ResultsParameter.ActualName = "Results";
+      ussp.Operator = mainOperator;
+
+      IntCounter iterationsCounter = new IntCounter();
+      iterationsCounter.ValueParameter.ActualName = "Iterations";
+      iterationsCounter.Increment = new IntValue(1);
+      ussp.Successor = iterationsCounter;
+
+      Comparator comparator = new Comparator();
+      comparator.Name = "Iterations < MaximumIterations ?";
+      comparator.LeftSideParameter.ActualName = "Iterations";
+      comparator.RightSideParameter.ActualName = MaximumIterationsParameter.Name;
+      comparator.Comparison = new Comparison(ComparisonType.Less);
+      comparator.ResultParameter.ActualName = "ContinueByIteration";
+      iterationsCounter.Successor = comparator;
+
+      ConditionalBranch branch = new ConditionalBranch();
+      branch.ConditionParameter.ActualName = "ContinueByIteration";
+      branch.TrueBranch = analyzer;
+      comparator.Successor = branch;
+
+      RegisterEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomizedRobustTabooSearchQAP(this, cloner);
+    }
+
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      UpdateProblemSpecificParameters();
+      ParameterizeOperators();
+      UpdateAnalyzers();
+    }
+
+    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
+      base.Problem_EvaluatorChanged(sender, e);
+      ParameterizeOperators();
+      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+    }
+
+    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
+      base.Problem_OperatorsChanged(sender, e);
+      UpdateAnalyzers();
+    }
+
+    protected override void Problem_Reset(object sender, EventArgs e) {
+      base.Problem_Reset(sender, e);
+      UpdateProblemSpecificParameters();
+      ParameterizeOperators();
+      UpdateAnalyzers();
+    }
+
+    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
+      ParameterizeOperators();
+    }
+
+    private void RegisterEventHandlers() {
+      if (Problem != null) {
+        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      }
+    }
+
+    public override void Start() {
+      if (ExecutionState == ExecutionState.Prepared) {
+        IntMatrix shortTermMemory = new IntMatrix(Problem.Weights.Rows, Problem.Weights.Rows);
+        DoubleMatrix shortTermMemory2 = new DoubleMatrix(Problem.Weights.Rows, Problem.Weights.Rows);
+        IntMatrix longTermMemory = new IntMatrix(Problem.Weights.Rows, Problem.Weights.Rows);
+        for (int i = 0; i < shortTermMemory.Rows; i++)
+          for (int j = 0; j < shortTermMemory.Rows; j++) {
+            shortTermMemory[i, j] = -1;
+            shortTermMemory2[i, j] = double.MinValue;
+            longTermMemory[i, j] = -1;
+          }
+
+        GlobalScope.Variables.Add(new Variable("ShortTermMemory", shortTermMemory));
+        GlobalScope.Variables.Add(new Variable("ShortTermMemory2", shortTermMemory2));
+        GlobalScope.Variables.Add(new Variable("LongTermMemory", longTermMemory));
+      }
+      base.Start();
+    }
+
+    private void UpdateProblemSpecificParameters() {
+      MinimumTabuTenure = (int)(0.9 * Problem.Weights.Rows);
+      MaximumTabuTenure = (int)(1.1 * Problem.Weights.Rows);
+      TabuTenureAdaptionInterval = 2 * MaximumTabuTenure;
+    }
+
+    private void UpdateAnalyzers() {
+      AnalyzerParameter.Value.Operators.Clear();
+      if (Problem != null) {
+        foreach (IAnalyzer analyzer in ((IProblem)Problem).Operators.OfType<IAnalyzer>())
+          if (!(analyzer is AlleleFrequencyAnalyzer<Permutation>) && !(analyzer is PopulationDiversityAnalyzer<Permutation>))
+            AnalyzerParameter.Value.Operators.Add(analyzer);
+      }
+      AnalyzerParameter.Value.Operators.Add(qualityAnalyzer);
+    }
+
+    private void ParameterizeOperators() {
+      if (Problem != null) {
+        solutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
+        solutionsCreator.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
+
+        qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.Name;
+
+        mainOperator.DistancesParameter.ActualName = Problem.DistancesParameter.Name;
+        mainOperator.PermutationParameter.ActualName = Problem.SolutionCreator.PermutationParameter.ActualName;
+        mainOperator.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
+        mainOperator.WeightsParameter.ActualName = Problem.WeightsParameter.Name;
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSeachOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSeachOperator.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSeachOperator.cs	(revision 6628)
@@ -0,0 +1,206 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
+  [Item("RobustTabooSearchOperator", "Performs an iteration of the robust taboo search algorithm as descrbied in Taillard 1991.")]
+  public sealed class RobustTabooSeachOperator : SingleSuccessorOperator, IIterationBasedOperator, IStochasticOperator {
+
+    #region Parameter Properties
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public ILookupParameter<IntMatrix> ShortTermMemoryParameter {
+      get { return (ILookupParameter<IntMatrix>)Parameters["ShortTermMemory"]; }
+    }
+    public ILookupParameter<DoubleMatrix> MoveQualityMatrixParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["MoveQualityMatrix"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ILookupParameter<Swap2Move> LastMoveParameter {
+      get { return (ILookupParameter<Swap2Move>)Parameters["LastMove"]; }
+    }
+    public ILookupParameter<BoolValue> UseNewTabuTenureAdaptionSchemeParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["UseNewTabuTenureAdaptionScheme"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    public IValueLookupParameter<IntValue> MinimumTabuTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MinimumTabuTenure"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumTabuTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
+    }
+    public IValueLookupParameter<BoolValue> UseAlternativeAspirationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["UseAlternativeAspiration"]; }
+    }
+    public IValueLookupParameter<IntValue> AlternativeAspirationTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["AlternativeAspirationTenure"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private RobustTabooSeachOperator(bool deserializing) : base(deserializing) { }
+    private RobustTabooSeachOperator(RobustTabooSeachOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public RobustTabooSeachOperator() {
+      Parameters.Add(new LookupParameter<IntValue>("Iterations", "The current iteration."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation solution."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+      Parameters.Add(new LookupParameter<IntMatrix>("ShortTermMemory", "The table that stores the iteration at which a certain facility has been assigned to a certain location."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("MoveQualityMatrix", "The quality of all swap moves as evaluated on the current permutation."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestQuality", "The best quality value."));
+      Parameters.Add(new LookupParameter<Swap2Move>("LastMove", "The last move that was applied."));
+      Parameters.Add(new LookupParameter<BoolValue>("UseNewTabuTenureAdaptionScheme", "True if the new tabu tenure adaption should be used or false otherwise."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "Collection that houses the results of the algorithm."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("UseAlternativeAspiration", "True if the alternative aspiration condition should be used that takes moves that have not been made for some time above others."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("AlternativeAspirationTenure", "The time t that a move will be remembered for the alternative aspiration condition."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RobustTabooSeachOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      IRandom random = RandomParameter.ActualValue;
+      int iteration = IterationsParameter.ActualValue.Value;
+      IntMatrix shortTermMemory = ShortTermMemoryParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix moveQualityMatrix = MoveQualityMatrixParameter.ActualValue;
+
+      DoubleValue quality = QualityParameter.ActualValue;
+      DoubleValue bestQuality = BestQualityParameter.ActualValue;
+      if (bestQuality == null) {
+        BestQualityParameter.ActualValue = (DoubleValue)quality.Clone();
+        bestQuality = BestQualityParameter.ActualValue;
+      }
+
+      int minTenure = MinimumTabuTenureParameter.ActualValue.Value;
+      int maxTenure = MaximumTabuTenureParameter.ActualValue.Value;
+      int alternativeAspirationTenure = AlternativeAspirationTenureParameter.ActualValue.Value;
+      bool useAlternativeAspiration = UseAlternativeAspirationParameter.ActualValue.Value;
+      Permutation solution = PermutationParameter.ActualValue;
+      Swap2Move lastMove = LastMoveParameter.ActualValue;
+
+      double bestMoveQuality = double.MaxValue;
+      Swap2Move bestMove = null;
+      bool already_aspired = false;
+
+      foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(solution)) {
+        double moveQuality;
+        if (lastMove == null)
+          moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances);
+        else moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, moveQualityMatrix[move.Index1, move.Index2], weights, distances, lastMove);
+
+        moveQualityMatrix[move.Index1, move.Index2] = moveQuality;
+        moveQualityMatrix[move.Index2, move.Index1] = moveQuality;
+
+        bool autorized = shortTermMemory[move.Index1, solution[move.Index2]] < iteration
+                      || shortTermMemory[move.Index2, solution[move.Index1]] < iteration;
+
+        bool aspired = (shortTermMemory[move.Index1, solution[move.Index2]] < iteration - alternativeAspirationTenure
+                     && shortTermMemory[move.Index2, solution[move.Index1]] < iteration - alternativeAspirationTenure)
+                  || quality.Value + moveQuality < bestQuality.Value;
+
+        if ((aspired && !already_aspired) // the first alternative move is aspired
+          || (aspired && already_aspired && moveQuality < bestMoveQuality) // an alternative move was already aspired, but this is better
+          || (autorized && !aspired && !already_aspired && moveQuality < bestMoveQuality)) { // a regular better move is found
+          bestMove = move;
+          bestMoveQuality = moveQuality;
+          if (aspired) already_aspired = true;
+        }
+      }
+
+      ResultCollection results = ResultsParameter.ActualValue;
+      if (results != null) {
+        IntValue aspiredMoves = null;
+        if (!results.ContainsKey("AspiredMoves")) {
+          aspiredMoves = new IntValue(already_aspired ? 1 : 0);
+          results.Add(new Result("AspiredMoves", "Counts the number of moves that were selected because of the aspiration criteria.", aspiredMoves));
+        } else if (already_aspired) {
+          aspiredMoves = (IntValue)results["AspiredMoves"].Value;
+          aspiredMoves.Value++;
+        }
+      }
+
+      LastMoveParameter.ActualValue = bestMove;
+
+      if (bestMove == null) return base.Apply();
+
+      bool useNewAdaptionScheme = UseNewTabuTenureAdaptionSchemeParameter.ActualValue.Value;
+      if (useNewAdaptionScheme) {
+        double r = random.NextDouble();
+        if (r == 0) r = 1; // transform to (0;1]
+        shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = (int)(iteration + r * r * r * maxTenure);
+        r = random.NextDouble();
+        if (r == 0) r = 1; // transform to (0;1]
+        shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = (int)(iteration + r * r * r * maxTenure);
+      } else {
+        shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = iteration + random.Next(minTenure, maxTenure);
+        shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = iteration + random.Next(minTenure, maxTenure);
+      }
+      Swap2Manipulator.Apply(solution, bestMove.Index1, bestMove.Index2);
+      quality.Value += bestMoveQuality;
+
+      if (quality.Value < bestQuality.Value) bestQuality.Value = quality.Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSearch.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSearch.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSearch.cs	(revision 6628)
@@ -0,0 +1,395 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Analysis;
+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;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
+  [Item("Robust Taboo Search", "The algorithm is described in Taillard, E. 1991. Robust Taboo Search for the Quadratic Assignment Problem. Parallel Computing 17, pp. 443-455.")]
+  [Creatable("Algorithms")]
+  [StorableClass]
+  public sealed class RobustTabooSearch : HeuristicOptimizationEngineAlgorithm, IStorableContent {
+    public string Filename { get; set; }
+
+    #region Problem Properties
+    public override Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+    public new QuadraticAssignmentProblem Problem {
+      get { return (QuadraticAssignmentProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+    #endregion
+
+    #region Parameter Properties
+    private FixedValueParameter<MultiAnalyzer> AnalyzerParameter {
+      get { return (FixedValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
+    }
+    private FixedValueParameter<IntValue> SeedParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["Seed"]; }
+    }
+    private FixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return (FixedValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
+    }
+    private FixedValueParameter<IntValue> MaximumIterationsParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    private FixedValueParameter<IntValue> MinimumTabuTenureParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["MinimumTabuTenure"]; }
+    }
+    private FixedValueParameter<IntValue> MaximumTabuTenureParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
+    }
+    private FixedValueParameter<BoolValue> UseAlternativeAspirationParameter {
+      get { return (FixedValueParameter<BoolValue>)Parameters["UseAlternativeAspiration"]; }
+    }
+    private FixedValueParameter<IntValue> AlternativeAspirationTenureParameter {
+      get { return (FixedValueParameter<IntValue>)Parameters["AlternativeAspirationTenure"]; }
+    }
+    private FixedValueParameter<BoolValue> UseNewTabuTenureAdaptionSchemeParameter {
+      get { return (FixedValueParameter<BoolValue>)Parameters["UseNewTabuTenureAdaptionScheme"]; }
+    }
+    #endregion
+
+    #region Properties
+    public int Seed {
+      get { return SeedParameter.Value.Value; }
+      set { SeedParameter.Value.Value = value; }
+    }
+    public bool SetSeedRandomly {
+      get { return SetSeedRandomlyParameter.Value.Value; }
+      set { SetSeedRandomlyParameter.Value.Value = value; }
+    }
+    public int MaximumIterations {
+      get { return MaximumIterationsParameter.Value.Value; }
+      set { MaximumIterationsParameter.Value.Value = value; }
+    }
+    public int MinimumTabuTenure {
+      get { return MinimumTabuTenureParameter.Value.Value; }
+      set { MinimumTabuTenureParameter.Value.Value = value; }
+    }
+    public int MaximumTabuTenure {
+      get { return MaximumTabuTenureParameter.Value.Value; }
+      set { MaximumTabuTenureParameter.Value.Value = value; }
+    }
+    public bool UseAlternativeAspiration {
+      get { return UseAlternativeAspirationParameter.Value.Value; }
+      set { UseAlternativeAspirationParameter.Value.Value = value; }
+    }
+    public int AlternativeAspirationTenure {
+      get { return AlternativeAspirationTenureParameter.Value.Value; }
+      set { AlternativeAspirationTenureParameter.Value.Value = value; }
+    }
+    public bool UseNewTabuTenureAdaptionScheme {
+      get { return UseNewTabuTenureAdaptionSchemeParameter.Value.Value; }
+      set { UseNewTabuTenureAdaptionSchemeParameter.Value.Value = value; }
+    }
+    #endregion
+
+    [Storable]
+    private SolutionsCreator solutionsCreator;
+    [Storable]
+    private RobustTabooSeachOperator mainOperator;
+    [Storable]
+    private BestAverageWorstQualityAnalyzer qualityAnalyzer;
+
+    [StorableConstructor]
+    private RobustTabooSearch(bool deserializing) : base(deserializing) { }
+    private RobustTabooSearch(RobustTabooSearch original, Cloner cloner)
+      : base(original, cloner) {
+      solutionsCreator = cloner.Clone(original.solutionsCreator);
+      mainOperator = cloner.Clone(original.mainOperator);
+      qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
+      RegisterEventHandlers();
+    }
+    public RobustTabooSearch() {
+      Parameters.Add(new FixedValueParameter<MultiAnalyzer>("Analyzer", "The analyzers that are applied after each iteration.", new MultiAnalyzer()));
+      Parameters.Add(new FixedValueParameter<IntValue>("Seed", "The seed value of the random number generator.", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("SetSeedRandomly", "True whether the seed should be set randomly for each run, false if it should be fixed.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run.", new IntValue(10000)));
+      Parameters.Add(new FixedValueParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure.", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure.", new IntValue(20)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("UseAlternativeAspiration", "True if the alternative aspiration condition should be used that takes moves that have not been made for some time above others.", new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>("AlternativeAspirationTenure", "The time t that a move will be remembered for the alternative aspiration condition.", new IntValue(int.MaxValue)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("TerminateOnOptimalSolution", "True when the algorithm should stop if it reached a quality equal or smaller to the BestKnownQuality.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("UseNewTabuTenureAdaptionScheme", @"In an updated version of his implementation, Eric Taillard introduced a different way to change the tabu tenure.
+Instead of setting it uniformly between min and max, it will be set between 0 and max according to a right-skewed distribution.
+Set this option to false if you want to optimize using the earlier 1991 version, and set to true if you want to optimize using the newer version.
+Please note that the MinimumTabuTenure parameter has no effect in the new version.", new BoolValue(true)));
+
+      qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
+      qualityAnalyzer.ResultsParameter.ActualName = "Results";
+      AnalyzerParameter.Value.Operators.Add(qualityAnalyzer);
+
+      RandomCreator randomCreator = new RandomCreator();
+      randomCreator.RandomParameter.ActualName = "Random";
+      randomCreator.SeedParameter.Value = null;
+      randomCreator.SeedParameter.ActualName = SeedParameter.Name;
+      randomCreator.SetSeedRandomlyParameter.Value = null;
+      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
+
+      VariableCreator variableCreator = new VariableCreator();
+      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Iterations", new IntValue(0)));
+
+      ResultsCollector resultsCollector = new ResultsCollector();
+      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Iterations", "The actual iteration."));
+
+      solutionsCreator = new SolutionsCreator();
+      solutionsCreator.NumberOfSolutions = new IntValue(1);
+
+      Placeholder analyzer = new Placeholder();
+      analyzer.Name = "(Analyzer)";
+      analyzer.OperatorParameter.ActualName = AnalyzerParameter.Name;
+
+      UniformSubScopesProcessor ussp = new UniformSubScopesProcessor();
+
+      mainOperator = new RobustTabooSeachOperator();
+      mainOperator.AlternativeAspirationTenureParameter.ActualName = AlternativeAspirationTenureParameter.Name;
+      mainOperator.BestQualityParameter.ActualName = "BestSoFarQuality";
+      mainOperator.IterationsParameter.ActualName = "Iterations";
+      mainOperator.LastMoveParameter.ActualName = "LastMove";
+      mainOperator.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
+      mainOperator.MaximumTabuTenureParameter.ActualName = MaximumTabuTenureParameter.Name;
+      mainOperator.MinimumTabuTenureParameter.ActualName = MinimumTabuTenureParameter.Name;
+      mainOperator.MoveQualityMatrixParameter.ActualName = "MoveQualityMatrix";
+      mainOperator.RandomParameter.ActualName = "Random";
+      mainOperator.ResultsParameter.ActualName = "Results";
+      mainOperator.ShortTermMemoryParameter.ActualName = "ShortTermMemory";
+      mainOperator.UseAlternativeAspirationParameter.ActualName = UseAlternativeAspirationParameter.Name;
+
+      ConditionalBranch qualityStopBranch = new ConditionalBranch();
+      qualityStopBranch.Name = "Terminate on optimal quality?";
+      qualityStopBranch.ConditionParameter.ActualName = "TerminateOnOptimalSolution";
+
+      Comparator qualityComparator = new Comparator();
+      qualityComparator.Comparison = new Comparison(ComparisonType.Greater);
+      qualityComparator.LeftSideParameter.ActualName = "BestQuality";
+      qualityComparator.RightSideParameter.ActualName = "BestKnownQuality";
+      qualityComparator.ResultParameter.ActualName = "ContinueByQuality";
+
+      ConditionalBranch continueByQualityBranch = new ConditionalBranch();
+      continueByQualityBranch.ConditionParameter.ActualName = "ContinueByQuality";
+
+      IntCounter iterationsCounter = new IntCounter();
+      iterationsCounter.ValueParameter.ActualName = "Iterations";
+      iterationsCounter.Increment = new IntValue(1);
+
+      Comparator comparator = new Comparator();
+      comparator.Name = "Iterations < MaximumIterations ?";
+      comparator.LeftSideParameter.ActualName = "Iterations";
+      comparator.RightSideParameter.ActualName = MaximumIterationsParameter.Name;
+      comparator.Comparison = new Comparison(ComparisonType.Less);
+      comparator.ResultParameter.ActualName = "ContinueByIteration";
+
+      ConditionalBranch continueByIterationBranch = new ConditionalBranch();
+      continueByIterationBranch.ConditionParameter.ActualName = "ContinueByIteration";
+
+      OperatorGraph.InitialOperator = randomCreator;
+      randomCreator.Successor = variableCreator;
+      variableCreator.Successor = resultsCollector;
+      resultsCollector.Successor = solutionsCreator;
+      solutionsCreator.Successor = analyzer;
+      analyzer.Successor = ussp;
+      ussp.Operator = mainOperator;
+      ussp.Successor = qualityStopBranch;
+      qualityStopBranch.FalseBranch = iterationsCounter;
+      qualityStopBranch.TrueBranch = qualityComparator;
+      qualityStopBranch.Successor = null;
+      qualityComparator.Successor = continueByQualityBranch;
+      continueByQualityBranch.TrueBranch = iterationsCounter;
+      continueByQualityBranch.FalseBranch = null;
+      continueByQualityBranch.Successor = null;
+      iterationsCounter.Successor = comparator;
+      comparator.Successor = continueByIterationBranch;
+      continueByIterationBranch.TrueBranch = analyzer;
+      continueByIterationBranch.FalseBranch = null;
+      continueByIterationBranch.Successor = null;
+
+      RegisterEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RobustTabooSearch(this, cloner);
+    }
+
+    #region Event Handlers
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      UpdateProblemSpecificParameters();
+      ParameterizeOperators();
+      UpdateAnalyzers();
+    }
+
+    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
+      base.Problem_EvaluatorChanged(sender, e);
+      ParameterizeOperators();
+      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+    }
+
+    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
+      base.Problem_OperatorsChanged(sender, e);
+      UpdateAnalyzers();
+    }
+
+    protected override void Problem_Reset(object sender, EventArgs e) {
+      base.Problem_Reset(sender, e);
+      UpdateProblemSpecificParameters();
+      ParameterizeOperators();
+      UpdateAnalyzers();
+    }
+
+    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
+      ParameterizeOperators();
+    }
+
+    private void UseAlternativeAspirationParameter_ValueChanged(object sender, EventArgs e) {
+      UpdateAlternativeAspirationTenure();
+    }
+
+    private void AlternativeAspirationTenureParameter_ValueChanged(object sender, EventArgs e) {
+      if (AlternativeAspirationTenure < MaximumIterations && !UseAlternativeAspiration) {
+        SetSilentlyUseAlternativeAspirationParameter(true);
+      } else if (AlternativeAspirationTenure >= MaximumIterations && UseAlternativeAspiration) {
+        SetSilentlyUseAlternativeAspirationParameter(false);
+      }
+    }
+
+    private void MaximumIterationsParameter_ValueChanged(object sender, EventArgs e) {
+      if (MaximumIterations < AlternativeAspirationTenure && UseAlternativeAspiration) {
+        SetSilentlyUseAlternativeAspirationParameter(false);
+      } else if (MaximumIterations >= AlternativeAspirationTenure && !UseAlternativeAspiration) {
+        SetSilentlyUseAlternativeAspirationParameter(true);
+      }
+    }
+
+    private void UseNewTabuTenureAdaptionSchemeParameter_ValueChanged(object sender, EventArgs e) {
+      UpdateProblemSpecificParameters();
+    }
+    #endregion
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      UseAlternativeAspirationParameter.Value.ValueChanged += new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+      AlternativeAspirationTenureParameter.Value.ValueChanged += new EventHandler(AlternativeAspirationTenureParameter_ValueChanged);
+      MaximumIterationsParameter.Value.ValueChanged += new EventHandler(MaximumIterationsParameter_ValueChanged);
+      UseNewTabuTenureAdaptionSchemeParameter.Value.ValueChanged += new EventHandler(UseNewTabuTenureAdaptionSchemeParameter_ValueChanged);
+    }
+
+    protected override void RegisterProblemEvents() {
+      base.RegisterProblemEvents();
+      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+    }
+
+    protected override void DeregisterProblemEvents() {
+      Problem.Evaluator.QualityParameter.ActualNameChanged -= new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      base.DeregisterProblemEvents();
+    }
+
+    public override void Start() {
+      if (ExecutionState == ExecutionState.Prepared) {
+        int dim = Problem.Weights.Rows;
+        IntMatrix shortTermMemory = new IntMatrix(dim, dim);
+        for (int i = 0; i < dim; i++)
+          for (int j = 0; j < dim; j++) {
+            shortTermMemory[i, j] = -(dim * (i + 1) + j + 1);
+          }
+
+        GlobalScope.Variables.Add(new Variable("ShortTermMemory", shortTermMemory));
+        GlobalScope.Variables.Add(new Variable("MoveQualityMatrix", new DoubleMatrix(dim, dim)));
+      }
+      base.Start();
+    }
+
+    private void UpdateProblemSpecificParameters() {
+      UpdateTabuTenure();
+      UpdateAlternativeAspirationTenure();
+    }
+
+    private void UpdateTabuTenure() {
+      if (UseNewTabuTenureAdaptionScheme) {
+        MinimumTabuTenure = 0;
+        MaximumTabuTenure = 8 * Problem.Weights.Rows;
+      } else {
+        MinimumTabuTenure = (int)(0.9 * Problem.Weights.Rows);
+        MaximumTabuTenure = (int)(1.1 * Problem.Weights.Rows);
+      }
+    }
+
+    private void UpdateAlternativeAspirationTenure() {
+      if (UseAlternativeAspiration) {
+        int n = Problem.Weights.Rows;
+        // Taillard has given two formulas for calculating default values: n^2 / 2 and later n^2 * 5
+        // However these do not really model the values he used in his original publication though
+        // The following formula is a linear regression model on the problem size and parameters
+        // given in Table 3 in Taillard1991 and was lower-bounded artificially by 100
+        AlternativeAspirationTenure = Math.Max(203 * n - 2274, 100);
+      } else {
+        AlternativeAspirationTenure = int.MaxValue;
+      }
+    }
+
+    private void UpdateAnalyzers() {
+      AnalyzerParameter.Value.Operators.Clear();
+      if (Problem != null) {
+        foreach (IAnalyzer analyzer in ((IProblem)Problem).Operators.OfType<IAnalyzer>()) {
+          AnalyzerParameter.Value.Operators.Add(analyzer);
+          if (!(analyzer is BestQAPSolutionAnalyzer))
+            AnalyzerParameter.Value.Operators.SetItemCheckedState(analyzer, false);
+        }
+      }
+      AnalyzerParameter.Value.Operators.Add(qualityAnalyzer);
+    }
+
+    private void ParameterizeOperators() {
+      if (Problem != null) {
+        solutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
+        solutionsCreator.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
+
+        qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.Name;
+
+        mainOperator.DistancesParameter.ActualName = Problem.DistancesParameter.Name;
+        mainOperator.PermutationParameter.ActualName = Problem.SolutionCreator.PermutationParameter.ActualName;
+        mainOperator.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
+        mainOperator.WeightsParameter.ActualName = Problem.WeightsParameter.Name;
+      }
+    }
+
+    private void SetSilentlyUseAlternativeAspirationParameter(bool value) {
+      UseAlternativeAspirationParameter.Value.ValueChanged -= new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+      UseAlternativeAspiration = value;
+      UseAlternativeAspirationParameter.Value.ValueChanged += new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs	(revision 6628)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Collections.Generic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
@@ -56,17 +57,19 @@
 
     protected override Allele[] CalculateAlleles(Permutation solution) {
-      Allele[] alleles = new Allele[solution.Length];
+      Allele[] alleles = new Allele[solution.Length * solution.Length];
+      Dictionary<string, int> allelesDict = new Dictionary<string, int>();
       DoubleMatrix weights = WeightsParameter.ActualValue;
       DoubleMatrix distances = DistancesParameter.ActualValue;
-      int source, target;
       double impact;
 
-      for (int i = 0; i < solution.Length; i++) {
-        source = i;
-        target = solution[i];
-        impact = 0;
-        for (int j = 0; j < solution.Length; j++)
-          impact += weights[source, j] * distances[target, solution[j]];
-        alleles[i] = new Allele(source.ToString() + "->" + target.ToString(), impact);
+      for (int x = 0; x < solution.Length; x++) {
+        for (int y = 0; y < solution.Length; y++) {
+          string allele = weights[x, y].ToString() + ">" + distances[solution[x], solution[y]].ToString();
+          int repetition = 1;
+          if (allelesDict.ContainsKey(allele)) repetition += allelesDict[allele];
+          allelesDict[allele] = repetition;
+          impact = weights[x, y] * distances[solution[x], solution[y]];
+          alleles[x * solution.Length + y] = new Allele(allele + "/" + repetition, impact);
+        }
       }
 
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs	(revision 6628)
@@ -23,5 +23,7 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -33,8 +35,23 @@
   [StorableClass]
   public sealed class QAPPopulationDiversityAnalyzer : PopulationDiversityAnalyzer<Permutation> {
+    public IValueParameter<BoolValue> UsePhenotypeSimilarityParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["UsePhenotypeSimilarity"]; }
+    }
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
     [StorableConstructor]
     private QAPPopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
     private QAPPopulationDiversityAnalyzer(QAPPopulationDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { }
-    public QAPPopulationDiversityAnalyzer() : base() { }
+    public QAPPopulationDiversityAnalyzer()
+      : base() {
+      Parameters.Add(new ValueParameter<BoolValue>("UsePhenotypeSimilarity", "True if the similarity should be measured a level closer to the phenotype (the number of similar assignments of individual weights to distances). Set to false if the number of equal assignments (facility to location) should be counted.", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -42,5 +59,20 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("UsePhenotypeSimilarity"))
+        Parameters.Add(new ValueParameter<BoolValue>("UsePhenotypeSimilarity", "True if the similarity should be measured a level closer to the phenotype (the number of similar assignments of individual weights to distances). Set to false if the number of equal assignments (facility to location) should be counted.", new BoolValue(false)));
+      if (!Parameters.ContainsKey("Weights"))
+        Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      if (!Parameters.ContainsKey("Distances"))
+        Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+      #endregion
+    }
+
     protected override double[,] CalculateSimilarities(Permutation[] solutions) {
+      DoubleMatrix weights = WeightsParameter.ActualValue, distances = DistancesParameter.ActualValue;
+      bool phenotypeSimilarity = UsePhenotypeSimilarityParameter.Value.Value;
       int count = solutions.Length;
       double[,] similarities = new double[count, count];
@@ -49,5 +81,7 @@
         similarities[i, i] = 1;
         for (int j = i + 1; j < count; j++) {
-          similarities[i, j] = CalculateSimilarity(solutions[i], solutions[j]);
+          if (phenotypeSimilarity)
+            similarities[i, j] = QAPPermutationProximityCalculator.CalculatePhenotypeSimilarity(solutions[i], solutions[j], weights, distances);
+          else similarities[i, j] = QAPPermutationProximityCalculator.CalculateGenotypeSimilarity(solutions[i], solutions[j]);
           similarities[j, i] = similarities[i, j];
         }
@@ -55,13 +89,4 @@
       return similarities;
     }
-
-    private double CalculateSimilarity(Permutation assignment1, Permutation assignment2) {
-      int identicalAssignments = 0;
-      for (int i = 0; i < assignment1.Length; i++) {
-        if (assignment1[i] == assignment2[i])
-          identicalAssignments++;
-      }
-      return ((double)identicalAssignments) / assignment1.Length;
-    }
   }
 }
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs	(revision 6628)
@@ -49,4 +49,13 @@
     }
 
+    /// <summary>
+    /// Calculates the quality of the move <paramref name="move"/> by evaluating the changes.
+    /// The runtime complexity of this method is O(N) with N being the size of the permutation.
+    /// </summary>
+    /// <param name="assignment">The current permutation.</param>
+    /// <param name="move">The move that is to be evaluated if it was applied to the current permutation.</param>
+    /// <param name="weights">The weights matrix.</param>
+    /// <param name="distances">The distances matrix.</param>
+    /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
     public static double Apply(Permutation assignment, Swap2Move move, DoubleMatrix weights, DoubleMatrix distances) {
       if (move.Index1 == move.Index2) return 0;
@@ -73,4 +82,42 @@
     }
 
+    /// <summary>
+    /// Is able to compute the move qualities faster O(1) in some cases if it knows the quality of
+    /// performing the move <paramref name="move"/> previously. In other cases it performs a
+    /// standard move quality calculation with runtime complexity O(N).
+    /// </summary>
+    /// <remarks>
+    /// The number of cases that the calculation can be performed faster grows with N^2
+    /// while the number of cases which require a larger recalculation grows linearly with N.
+    /// Larger problem instances thus benefit from this faster method to a larger degree.
+    /// </remarks>
+    /// <param name="assignment">The current permutation.</param>
+    /// <param name="move">The current move that is to be evaluated.</param>
+    /// <param name="previousQuality">The quality of that move as evaluated for the previous permutation.</param>
+    /// <param name="weights">The weigths matrix.</param>
+    /// <param name="distances">The distances matrix.</param>
+    /// <param name="lastMove">The move that was applied to transform the permutation from the previous to the current one.</param>
+    /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
+    public static double Apply(Permutation assignment, Swap2Move move, double previousQuality,
+      DoubleMatrix weights, DoubleMatrix distances, Swap2Move lastMove) {
+      bool overlapsLastMove = move.Index1 == lastMove.Index1
+                           || move.Index2 == lastMove.Index1
+                           || move.Index1 == lastMove.Index2
+                           || move.Index2 == lastMove.Index2;
+
+      if (!overlapsLastMove) {
+        int r = lastMove.Index1, u = move.Index1, s = lastMove.Index2, v = move.Index2;
+        int pR = assignment[lastMove.Index1], pU = assignment[move.Index1], pS = assignment[lastMove.Index2], pV = assignment[move.Index2];
+
+        return previousQuality
+          + (weights[r, u] - weights[r, v] + weights[s, v] - weights[s, u])
+            * (distances[pS, pU] - distances[pS, pV] + distances[pR, pV] - distances[pR, pU])
+          + (weights[u, r] - weights[v, r] + weights[v, s] - weights[u, s])
+            * (distances[pU, pS] - distances[pV, pS] + distances[pV, pR] - distances[pU, pR]);
+      } else {
+        return Apply(assignment, move, weights, distances);
+      }
+    }
+
     public override IOperation Apply() {
       Swap2Move move = Swap2MoveParameter.ActualValue;
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj	(revision 6614)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj	(revision 6628)
@@ -124,4 +124,5 @@
     <Compile Include="Parsers\QAPLIBParser.cs" />
     <Compile Include="QAPAssignment.cs" />
+    <Compile Include="QAPPermutationProximityCalculator.cs" />
     <Compile Include="QuadraticAssignmentProblem.cs" />
     <EmbeddedResource Include="Data\bur26a.dat" />
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPPermutationProximityCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPPermutationProximityCalculator.cs	(revision 6628)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPPermutationProximityCalculator.cs	(revision 6628)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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 HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  public static class QAPPermutationProximityCalculator {
+
+    public static double CalculateGenotypeSimilarity(Permutation a, Permutation b) {
+      int similar = 0;
+      for (int i = 0; i < a.Length; i++) {
+        if (a[i] == b[i]) similar++;
+      }
+      return similar / (double)a.Length;
+    }
+
+    public static double CalculateGenotypeDistance(Permutation a, Permutation b) {
+      return 1.0 - CalculateGenotypeSimilarity(a, b);
+    }
+
+    public static double CalculatePhenotypeSimilarity(Permutation a, Permutation b, DoubleMatrix weights, DoubleMatrix distances) {
+      return 1.0 - CalculatePhenotypeDistance(a, b, weights, distances);
+    }
+
+    public static double CalculatePhenotypeDistance(Permutation a, Permutation b, DoubleMatrix weights, DoubleMatrix distances) {
+      Dictionary<double, Dictionary<double, int>> alleles = new Dictionary<double, Dictionary<double, int>>();
+      int distance = 0, len = a.Length;
+      for (int x = 0; x < len; x++) {
+        for (int y = 0; y < len; y++) {
+          // there's a limited universe of double values as they're all drawn from the same matrix
+          double dA = distances[a[x], a[y]], dB = distances[b[x], b[y]];
+          if (dA == dB) continue;
+
+          Dictionary<double, int> dAlleles;
+          if (!alleles.ContainsKey(weights[x, y])) {
+            dAlleles = new Dictionary<double, int>();
+            alleles.Add(weights[x, y], dAlleles);
+          } else dAlleles = alleles[weights[x, y]];
+
+          int countA = 1, countB = -1;
+
+          if (dAlleles.ContainsKey(dA)) countA += dAlleles[dA];
+          if (dAlleles.ContainsKey(dB)) countB += dAlleles[dB];
+
+          if (countA <= 0) distance--; // we've found in A an allele that was present in B
+          else distance++; // we've found in A a new allele
+          dAlleles[dA] = countA;
+
+          if (countB >= 0) distance--; // we've found in B an allele that was present in A
+          else distance++; // we've found in B a new allele
+          dAlleles[dB] = countB;
+        }
+      }
+      return distance / (double)(2 * len * len);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs	(revision 6628)
@@ -385,6 +385,6 @@
         Distances = new DoubleMatrix(parser.Distances);
         Weights = new DoubleMatrix(parser.Weights);
-        Name = "Quadratic Assignment Problem (loaded instance " + instance + ")";
-        Description = "Loaded embedded problem data of instance " + instance + ".";
+        Name = instance;
+        Description = "Loaded embedded QAPLIB problem data of instance " + instance + ".";
         OnReset();
       }
Index: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs	(revision 6614)
+++ trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs	(revision 6628)
@@ -60,27 +60,67 @@
       for (int i = 0; i < ProblemSize - 1; i++) {
         for (int j = i + 1; j < ProblemSize; j++) {
-          symmetricDistances[i, j] = random.Next(ProblemSize);
+          symmetricDistances[i, j] = random.Next(ProblemSize * 100);
           symmetricDistances[j, i] = symmetricDistances[i, j];
-          symmetricWeights[i, j] = random.Next(ProblemSize);
+          symmetricWeights[i, j] = random.Next(ProblemSize * 100);
           symmetricWeights[j, i] = symmetricWeights[i, j];
-          asymmetricDistances[i, j] = random.Next(ProblemSize);
-          asymmetricDistances[j, i] = random.Next(ProblemSize);
-          asymmetricWeights[i, j] = random.Next(ProblemSize);
-          asymmetricWeights[j, i] = random.Next(ProblemSize);
-          nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize);
-          nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize);
-          nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize);
-          nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize);
+          asymmetricDistances[i, j] = random.Next(ProblemSize * 100);
+          asymmetricDistances[j, i] = random.Next(ProblemSize * 100);
+          asymmetricWeights[i, j] = random.Next(ProblemSize * 100);
+          asymmetricWeights[j, i] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize * 100);
         }
-        nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize);
-        nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize);
+        nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize * 100);
+        nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize * 100);
       }
       int index = random.Next(ProblemSize);
       if (nonZeroDiagonalDistances[index, index] == 0)
-        nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize);
+        nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize * 100);
       index = random.Next(ProblemSize);
       if (nonZeroDiagonalWeights[index, index] == 0)
-        nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize);
+        nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize * 100);
       assignment = new Permutation(PermutationTypes.Absolute, ProblemSize, random);
+    }
+
+    [TestMethod]
+    public void Swap2MoveEvaluatorFastEvaluationTest() {
+
+      for (int i = 0; i < 500; i++) {
+        Swap2Move lastMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
+        Permutation prevAssignment = (Permutation)assignment.Clone();
+        Swap2Manipulator.Apply(assignment, lastMove.Index1, lastMove.Index2);
+        Permutation nextAssignment = (Permutation)assignment.Clone();
+        Swap2Move currentMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
+        Swap2Manipulator.Apply(nextAssignment, currentMove.Index1, currentMove.Index2);
+
+        double moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, symmetricWeights, symmetricDistances);
+        double moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
+                moveBefore, symmetricWeights, symmetricDistances, lastMove);
+        double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances);
+        double after = QAPEvaluator.Apply(nextAssignment, symmetricWeights, symmetricDistances);
+
+        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on symmetric matrices: " + Environment.NewLine
+          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
+
+        moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, asymmetricWeights, asymmetricDistances);
+        moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
+                moveBefore, asymmetricWeights, asymmetricDistances, lastMove);
+        before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances);
+        after = QAPEvaluator.Apply(nextAssignment, asymmetricWeights, asymmetricDistances);
+
+        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on asymmetric matrices: " + Environment.NewLine
+          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
+
+        moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
+        moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
+                moveBefore, nonZeroDiagonalWeights, nonZeroDiagonalDistances, lastMove);
+        before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
+        after = QAPEvaluator.Apply(nextAssignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
+
+        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on non-zero diagonal matrices: " + Environment.NewLine
+          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
+      }
     }
 
Index: trunk/sources/HeuristicLab/3.3/Files.txt
===================================================================
--- trunk/sources/HeuristicLab/3.3/Files.txt	(revision 6614)
+++ trunk/sources/HeuristicLab/3.3/Files.txt	(revision 6628)
@@ -81,4 +81,5 @@
 HeuristicLab.Problems.OneMax.Views\3.3:HeuristicLab.Problems.OneMax.Views-3.3.dll
 HeuristicLab.Problems.QuadraticAssignment\3.3:HeuristicLab.Problems.QuadraticAssignment-3.3.dll
+HeuristicLab.Problems.QuadraticAssignment.Algorithms\3.3:HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.dll
 HeuristicLab.Problems.QuadraticAssignment.Views\3.3:HeuristicLab.Problems.QuadraticAssignment.Views-3.3.dll
 HeuristicLab.Problems.TestFunctions\3.3:HeuristicLab.Problems.TestFunctions-3.3.dll
