Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/BestQAPSolutionAnalyzer.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/BestQAPSolutionAnalyzer.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/BestQAPSolutionAnalyzer.cs	(revision 9284)
@@ -0,0 +1,164 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// An operator for analyzing the best solution of Quadratic Assignment Problems.
+  /// </summary>
+  [Item("BestQAPSolutionAnalyzer", "An operator for analyzing the best solution of Quadratic Assignment Problems.")]
+  [StorableClass]
+  public sealed class BestQAPSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer {
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public LookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public LookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public ScopeTreeLookupParameter<Permutation> PermutationParameter {
+      get { return (ScopeTreeLookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public LookupParameter<QAPAssignment> BestSolutionParameter {
+      get { return (LookupParameter<QAPAssignment>)Parameters["BestSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public LookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public LookupParameter<ItemSet<Permutation>> BestKnownSolutionsParameter {
+      get { return (LookupParameter<ItemSet<Permutation>>)Parameters["BestKnownSolutions"]; }
+    }
+    public LookupParameter<Permutation> BestKnownSolutionParameter {
+      get { return (LookupParameter<Permutation>)Parameters["BestKnownSolution"]; }
+    }
+
+    [StorableConstructor]
+    private BestQAPSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+    private BestQAPSolutionAnalyzer(BestQAPSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestQAPSolutionAnalyzer(this, cloner);
+    }
+    public BestQAPSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances between the locations."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights between the facilities."));
+      Parameters.Add(new ScopeTreeLookupParameter<Permutation>("Permutation", "The QAP solutions from which the best solution should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the QAP solutions which should be analyzed."));
+      Parameters.Add(new LookupParameter<QAPAssignment>("BestSolution", "The best QAP solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the best QAP solution should be stored."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this QAP instance."));
+      Parameters.Add(new LookupParameter<ItemSet<Permutation>>("BestKnownSolutions", "The best known solutions (there may be multiple) of this QAP instance."));
+      Parameters.Add(new LookupParameter<Permutation>("BestKnownSolution", "The best known solution of this QAP instance."));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("BestKnownSolutions")) {
+        Parameters.Add(new LookupParameter<ItemSet<Permutation>>("BestKnownSolutions", "The best known solutions of this QAP instance."));
+      } else if (Parameters["BestKnownSolutions"].GetType().Equals(typeof(LookupParameter<ItemList<Permutation>>))) {
+        string actualName = (Parameters["BestKnownSolutions"] as LookupParameter<ItemList<Permutation>>).ActualName;
+        Parameters.Remove("BestKnownSolutions");
+        Parameters.Add(new LookupParameter<ItemSet<Permutation>>("BestKnownSolutions", "The best known solutions of this QAP instance.", actualName));
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      ItemArray<Permutation> permutations = PermutationParameter.ActualValue;
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      bool max = MaximizationParameter.ActualValue.Value;
+      DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
+
+      var sorted = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).ToArray();
+      if (max) sorted = sorted.Reverse().ToArray();
+      int i = sorted.First().index;
+
+      if (bestKnownQuality == null
+          || max && qualities[i].Value > bestKnownQuality.Value
+          || !max && qualities[i].Value < bestKnownQuality.Value) {
+        // if there isn't a best-known quality or we improved the best-known quality we'll add the current solution as best-known
+        BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value);
+        BestKnownSolutionParameter.ActualValue = (Permutation)permutations[i].Clone();
+        BestKnownSolutionsParameter.ActualValue = new ItemSet<Permutation>(new PermutationEqualityComparer());
+        BestKnownSolutionsParameter.ActualValue.Add((Permutation)permutations[i].Clone());
+      } else if (bestKnownQuality.Value == qualities[i].Value) {
+        // if we matched the best-known quality we'll try to set the best-known solution if it isn't null
+        // and try to add it to the pool of best solutions if it is different
+        if (BestKnownSolutionParameter.ActualValue == null)
+          BestKnownSolutionParameter.ActualValue = (Permutation)permutations[i].Clone();
+        if (BestKnownSolutionsParameter.ActualValue == null)
+          BestKnownSolutionsParameter.ActualValue = new ItemSet<Permutation>(new PermutationEqualityComparer());
+        foreach (var k in sorted) { // for each solution that we found check if it is in the pool of best-knowns
+          if (!max && k.Value > qualities[i].Value
+            || max && k.Value < qualities[i].Value) break; // stop when we reached a solution worse than the best-known quality
+          Permutation p = permutations[k.index];
+          if (!BestKnownSolutionsParameter.ActualValue.Contains(p))
+            BestKnownSolutionsParameter.ActualValue.Add((Permutation)permutations[k.index].Clone());
+        }
+      }
+
+      QAPAssignment assignment = BestSolutionParameter.ActualValue;
+      if (assignment == null) {
+        assignment = new QAPAssignment(weights, (Permutation)permutations[i].Clone(), new DoubleValue(qualities[i].Value));
+        assignment.Distances = distances;
+        BestSolutionParameter.ActualValue = assignment;
+        results.Add(new Result("Best QAP Solution", assignment));
+      } else {
+        if (max && assignment.Quality.Value < qualities[i].Value ||
+          !max && assignment.Quality.Value > qualities[i].Value) {
+          assignment.Distances = distances;
+          assignment.Weights = weights;
+          assignment.Assignment = (Permutation)permutations[i].Clone();
+          assignment.Quality.Value = qualities[i].Value;
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs	(revision 9284)
@@ -0,0 +1,79 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// An operator for analyzing the frequency of alleles in solutions of Quadratic Assignment Problems.
+  /// </summary>
+  [Item("QAPAlleleFrequencyAnalyzer", "An operator for analyzing the frequency of alleles in solutions of Quadratic Assignment Problems.")]
+  [StorableClass]
+  public sealed class QAPAlleleFrequencyAnalyzer : AlleleFrequencyAnalyzer<Permutation> {
+    public LookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public LookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    [StorableConstructor]
+    private QAPAlleleFrequencyAnalyzer(bool deserializing) : base(deserializing) { }
+    private QAPAlleleFrequencyAnalyzer(QAPAlleleFrequencyAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public QAPAlleleFrequencyAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The matrix contains the weights between the facilities."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The matrix which contains the distances between the locations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPAlleleFrequencyAnalyzer(this, cloner);
+    }
+
+    protected override Allele[] CalculateAlleles(Permutation solution) {
+      Allele[] alleles = new Allele[solution.Length * solution.Length];
+      Dictionary<string, int> allelesDict = new Dictionary<string, int>();
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      double 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);
+        }
+      }
+
+      return alleles;
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs	(revision 9284)
@@ -0,0 +1,92 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// An operator for analyzing the diversity of solutions of Quadratic Assignment Problems regarding their structural identity (number of equal facilty->location assignments).
+  /// </summary>
+  [Item("QAPPopulationDiversityAnalyzer", "An operator for analyzing the diversity of solutions of Quadratic Assignment Problems regarding their structural identity (number of equal facilty->location assignments).")]
+  [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() {
+      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) {
+      return new QAPPopulationDiversityAnalyzer(this, cloner);
+    }
+
+    [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];
+
+      for (int i = 0; i < count; i++) {
+        similarities[i, i] = 1;
+        for (int j = i + 1; j < count; 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];
+        }
+      }
+      return similarities;
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/BoundsCalculators/GilmoreLawlerBoundCalculator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/BoundsCalculators/GilmoreLawlerBoundCalculator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/BoundsCalculators/GilmoreLawlerBoundCalculator.cs	(revision 9284)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Problems.LinearAssignment;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  public static class GilmoreLawlerBoundCalculator {
+    public static double CalculateLowerBound(DoubleMatrix weights, DoubleMatrix distances) {
+      Permutation tmp;
+      return CalculateLowerBound(weights, distances, out tmp);
+    }
+
+    public static double CalculateLowerBound(DoubleMatrix weights, DoubleMatrix distances, out Permutation solution) {
+      int N = weights.Rows;
+      DoubleMatrix sortedWeights = SortEachRowExceptDiagonal(weights), sortedDistances = SortEachRowExceptDiagonal(distances);
+
+      DoubleMatrix costs = new DoubleMatrix(N, N);
+      for (int i = 0; i < N; i++) {
+        for (int j = 0; j < N; j++) {
+          for (int k = 0; k < N - 1; k++)
+            costs[i, j] += sortedWeights[i, k] * sortedDistances[j, N - 2 - k];
+          costs[i, j] += sortedWeights[i, N - 1] * sortedDistances[j, N - 1];
+        }
+      }
+
+      double result;
+      solution = new Permutation(PermutationTypes.Absolute, LinearAssignmentProblemSolver.Solve(costs, out result));
+      return result;
+    }
+
+    private static DoubleMatrix SortEachRowExceptDiagonal(DoubleMatrix matrix) {
+      var result = new DoubleMatrix(matrix.Rows, matrix.Columns);
+
+      double[] row = new double[matrix.Rows - 1];
+      for (int i = 0; i < matrix.Rows; i++) {
+        int counter = 0;
+        for (int j = 0; j < matrix.Columns; j++)
+          if (i != j) row[counter++] = matrix[i, j];
+        Array.Sort(row);
+        for (int k = 0; k < matrix.Columns - 1; k++)
+          result[i, k] = row[k];
+        result[i, matrix.Columns - 1] = matrix[i, i];
+      }
+      return result;
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPEvaluator.cs	(revision 9284)
@@ -0,0 +1,91 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [StorableClass]
+  public class QAPEvaluator : SingleSuccessorOperator, IQAPEvaluator {
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPEvaluator(bool deserializing) : base(deserializing) { }
+    protected QAPEvaluator(QAPEvaluator original, Cloner cloner) : base(original, cloner) { }
+    public QAPEvaluator() {
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation that represents the current solution."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distance matrix that contains the distances between the locations."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The matrix with the weights between the facilities, that is how strongly they're connected to each other."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value aka fitness value of the solution."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPEvaluator(this, cloner);
+    }
+
+    public static double Apply(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances) {
+      double quality = 0;
+      for (int i = 0; i < assignment.Length; i++) {
+        for (int j = 0; j < assignment.Length; j++) {
+          quality += weights[i, j] * distances[assignment[i], assignment[j]];
+        }
+      }
+      return quality;
+    }
+
+    public static double Impact(int facility, Permutation assignment, DoubleMatrix weights, DoubleMatrix distances) {
+      double impact = 0;
+      for (int i = 0; i < assignment.Length; i++) {
+        impact += weights[facility, i] * distances[assignment[facility], assignment[i]];
+        impact += weights[i, facility] * distances[assignment[i], assignment[facility]];
+      }
+      return impact;
+    }
+
+    public override IOperation Apply() {
+      Permutation assignment = PermutationParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distanceMatrix = DistancesParameter.ActualValue;
+
+      double quality = Apply(assignment, weights, distanceMatrix);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPInversionMoveEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPInversionMoveEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPInversionMoveEvaluator.cs	(revision 9284)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("QAPInversionMoveEvaluator", "Evaluated an inversion move on a QAP solution.")]
+  [StorableClass]
+  public class QAPInversionMoveEvaluator : QAPMoveEvaluator, IPermutationInversionMoveOperator {
+    public ILookupParameter<InversionMove> InversionMoveParameter {
+      get { return (ILookupParameter<InversionMove>)Parameters["InversionMove"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPInversionMoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected QAPInversionMoveEvaluator(QAPInversionMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QAPInversionMoveEvaluator() {
+      Parameters.Add(new LookupParameter<InversionMove>("InversionMove", "The move to evaluate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPInversionMoveEvaluator(this, cloner);
+    }
+
+    public static double Apply(Permutation assignment, InversionMove move, DoubleMatrix weights, DoubleMatrix distances) {
+      if (move.Index1 == move.Index2) return 0;
+      double moveQuality = 0;
+      int min = Math.Min(move.Index1, move.Index2);
+      int max = Math.Max(move.Index1, move.Index2);
+
+      for (int i = min; i <= max; i++) {
+        int locI = assignment[i];
+        int newlocI = assignment[max - i + min];
+
+        for (int j = 0; j < assignment.Length; j++) {
+          int locJ = assignment[j];
+          if (j >= min && j <= max) {
+            int newlocJ = assignment[max - j + min];
+            moveQuality += weights[i, j] * (distances[newlocI, newlocJ] - distances[locI, locJ]);
+          } else {
+            moveQuality += weights[i, j] * (distances[newlocI, locJ] - distances[locI, locJ]);
+            moveQuality += weights[j, i] * (distances[locJ, newlocI] - distances[locJ, locI]);
+          }
+        }
+      }
+      return moveQuality;
+    }
+
+    public override IOperation Apply() {
+      InversionMove move = InversionMoveParameter.ActualValue;
+      if (move == null) throw new InvalidOperationException("Inversion move is not found.");
+      Permutation assignment = PermutationParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+
+      double moveQuality = QualityParameter.ActualValue.Value;
+      moveQuality += Apply(assignment, move, weights, distances);
+      MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPMoveEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPMoveEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPMoveEvaluator.cs	(revision 9284)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// A base class for operators which evaluate QAP solutions.
+  /// </summary>
+  [Item("QAPMoveEvaluator", "A base class for operators which evaluate moves.")]
+  [StorableClass]
+  public abstract class QAPMoveEvaluator : SingleSuccessorOperator, IQAPMoveEvaluator {
+
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPMoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected QAPMoveEvaluator(QAPMoveEvaluator original, Cloner cloner) : base(original, cloner) { }
+    protected QAPMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of a QAP solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The evaluated quality of a move on a QAP solution."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The matrix which contains the distances between the facilities."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The matrix with the weights between the facilities, that is how strongly they're connected to each other."));
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPScrambleMoveEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPScrambleMoveEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPScrambleMoveEvaluator.cs	(revision 9284)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("QAPScrambleMoveEvaluator", "Evaluated a scramble move on a QAP solution.")]
+  [StorableClass]
+  public class QAPScrambleMoveEvaluator : QAPMoveEvaluator, IPermutationScrambleMoveOperator {
+    public ILookupParameter<ScrambleMove> ScrambleMoveParameter {
+      get { return (ILookupParameter<ScrambleMove>)Parameters["ScrambleMove"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPScrambleMoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected QAPScrambleMoveEvaluator(QAPScrambleMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QAPScrambleMoveEvaluator() {
+      Parameters.Add(new LookupParameter<ScrambleMove>("ScrambleMove", "The move to evaluate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPScrambleMoveEvaluator(this, cloner);
+    }
+
+    /// <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, ScrambleMove move, DoubleMatrix weights, DoubleMatrix distances) {
+      double moveQuality = 0;
+      int min = move.StartIndex;
+      int max = min + move.ScrambledIndices.Length - 1;
+
+      for (int i = min; i <= max; i++) {
+        int locI = assignment[i];
+        int newlocI = assignment[min + move.ScrambledIndices[i - min]];
+        if (locI == newlocI) continue;
+
+        for (int j = 0; j < assignment.Length; j++) {
+          int locJ = assignment[j];
+          if (j >= min && j <= max) {
+            int newlocJ = assignment[min + move.ScrambledIndices[j - min]];
+            moveQuality += weights[i, j] * (distances[newlocI, newlocJ] - distances[locI, locJ]);
+            if (locJ == newlocJ)
+              moveQuality += weights[j, i] * (distances[newlocJ, newlocI] - distances[locJ, locI]);
+          } else {
+            moveQuality += weights[i, j] * (distances[newlocI, locJ] - distances[locI, locJ]);
+            moveQuality += weights[j, i] * (distances[locJ, newlocI] - distances[locJ, locI]);
+          }
+        }
+      }
+      return moveQuality;
+    }
+
+    public override IOperation Apply() {
+      ScrambleMove move = ScrambleMoveParameter.ActualValue;
+      if (move == null) throw new InvalidOperationException("Scramble move is not found.");
+      Permutation assignment = PermutationParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+
+      double moveQuality = QualityParameter.ActualValue.Value;
+      moveQuality += Apply(assignment, move, weights, distances);
+      MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs	(revision 9284)
@@ -0,0 +1,135 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("QAPSwap2MoveEvaluator", "Evaluated a swap-2 move on a QAP solution.")]
+  [StorableClass]
+  public class QAPSwap2MoveEvaluator : QAPMoveEvaluator, IPermutationSwap2MoveOperator {
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (ILookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPSwap2MoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected QAPSwap2MoveEvaluator(QAPSwap2MoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QAPSwap2MoveEvaluator() {
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The move to evaluate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPSwap2MoveEvaluator(this, cloner);
+    }
+
+    /// <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;
+      double moveQuality = 0;
+      int fac1 = move.Index1, fac2 = move.Index2;
+      int loc1 = assignment[fac1], loc2 = assignment[fac2];
+
+      for (int j = 0; j < assignment.Length; j++) {
+        if (j == fac1) {
+          moveQuality += weights[fac1, fac1] * (distances[loc2, loc2] - distances[loc1, loc1]);
+          moveQuality += weights[fac1, fac2] * (distances[loc2, loc1] - distances[loc1, loc2]);
+        } else if (j == fac2) {
+          moveQuality += weights[fac2, fac2] * (distances[loc1, loc1] - distances[loc2, loc2]);
+          moveQuality += weights[fac2, fac1] * (distances[loc1, loc2] - distances[loc2, loc1]);
+        } else {
+          int locJ = assignment[j];
+          moveQuality += weights[fac1, j] * (distances[loc2, locJ] - distances[loc1, locJ]);
+          moveQuality += weights[j, fac1] * (distances[locJ, loc2] - distances[locJ, loc1]);
+          moveQuality += weights[fac2, j] * (distances[loc1, locJ] - distances[loc2, locJ]);
+          moveQuality += weights[j, fac2] * (distances[locJ, loc1] - distances[locJ, loc2]);
+        }
+      }
+      return moveQuality;
+    }
+
+    /// <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;
+      if (move == null) throw new InvalidOperationException("Swap-2 move is not found.");
+      Permutation assignment = PermutationParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+
+      double moveQuality = QualityParameter.ActualValue.Value;
+      moveQuality += Apply(assignment, move, weights, distances);
+      MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPTranslocationMoveEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPTranslocationMoveEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPTranslocationMoveEvaluator.cs	(revision 9284)
@@ -0,0 +1,96 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("QAPTranslocationMoveEvaluator", "Evaluates translocation moves on a QAP solution.")]
+  [StorableClass]
+  public class QAPTranslocationMoveEvaluator : QAPMoveEvaluator, IPermutationTranslocationMoveOperator {
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return (ILookupParameter<TranslocationMove>)Parameters["TranslocationMove"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPTranslocationMoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected QAPTranslocationMoveEvaluator(QAPTranslocationMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QAPTranslocationMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<TranslocationMove>("TranslocationMove", "A move which takes part of a permutation and inserts it in a different part."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPTranslocationMoveEvaluator(this, cloner);
+    }
+
+    public static double Apply(Permutation assignment, TranslocationMove move, DoubleMatrix weights, DoubleMatrix distances) {
+      double moveQuality = 0;
+      int min = Math.Min(move.Index1, move.Index3);
+      int max = Math.Max(move.Index2, move.Index3 + (move.Index2 - move.Index1));
+      int iOffset, changeOffset;
+      if (move.Index1 < move.Index3) {
+        iOffset = move.Index2 - move.Index1 + 1;
+        changeOffset = min + max - move.Index2;
+      } else {
+        iOffset = move.Index1 - move.Index3;
+        changeOffset = min + move.Index2 - move.Index1 + 1;
+      }
+      for (int i = min; i <= max; i++) {
+        if (i == changeOffset) iOffset -= (max - min + 1);
+        int jOffset = ((move.Index1 < move.Index3) ? (move.Index2 - move.Index1 + 1) : (move.Index1 - move.Index3));
+        for (int j = 0; j < assignment.Length; j++) {
+          moveQuality -= weights[i, j] * distances[assignment[i], assignment[j]];
+          if (j < min || j > max) {
+            moveQuality -= weights[j, i] * distances[assignment[j], assignment[i]];
+            moveQuality += weights[i, j] * distances[assignment[i + iOffset], assignment[j]];
+            moveQuality += weights[j, i] * distances[assignment[j], assignment[i + iOffset]];
+          } else {
+            if (j == changeOffset) jOffset -= (max - min + 1);
+            moveQuality += weights[i, j] * distances[assignment[i + iOffset], assignment[j + jOffset]];
+          }
+        }
+      }
+      return moveQuality;
+    }
+
+    public override IOperation Apply() {
+      TranslocationMove move = TranslocationMoveParameter.ActualValue;
+      if (move == null) throw new InvalidOperationException("Translocation move is not found.");
+      Permutation assignment = PermutationParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+
+      double moveQuality = QualityParameter.ActualValue.Value;
+      moveQuality += Apply(assignment, move, weights, distances);
+      MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj	(revision 9284)
@@ -0,0 +1,245 @@
+﻿<?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>{79271BC8-4446-40E2-BB89-9BE4E17174FE}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.QuadraticAssignment</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.QuadraticAssignment-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>$(SolutionDir)\bin\</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>$(SolutionDir)\bin\</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>$(SolutionDir)\bin\</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>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>$(SolutionDir)\bin\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>$(SolutionDir)\bin\</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>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>$(SolutionDir)\bin\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" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.ServiceModel" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Analyzers\BestQAPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzers\QAPAlleleFrequencyAnalyzer.cs" />
+    <Compile Include="Analyzers\QAPPopulationDiversityAnalyzer.cs" />
+    <Compile Include="BoundsCalculators\GilmoreLawlerBoundCalculator.cs" />
+    <Compile Include="Evaluators\QAPScrambleMoveEvaluator.cs" />
+    <Compile Include="Evaluators\QAPSwap2MoveEvaluator.cs" />
+    <Compile Include="Evaluators\QAPEvaluator.cs" />
+    <Compile Include="Evaluators\QAPInversionMoveEvaluator.cs" />
+    <Compile Include="Evaluators\QAPMoveEvaluator.cs" />
+    <Compile Include="Evaluators\QAPTranslocationMoveEvaluator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Interfaces\IQAPEvaluator.cs" />
+    <Compile Include="Interfaces\IQAPMoveEvaluator.cs" />
+    <Compile Include="LocalImprovement\QAPExhaustiveInsertionLocalImprovement.cs" />
+    <Compile Include="LocalImprovement\QAPStochasticScrambleLocalImprovement.cs" />
+    <Compile Include="LocalImprovement\QAPExhaustiveSwap2LocalImprovement.cs" />
+    <Compile Include="LocalImprovement\QAPExhaustiveInversionLocalImprovement.cs" />
+    <Compile Include="QAPAssignment.cs" />
+    <Compile Include="QAPPermutationProximityCalculator.cs" />
+    <Compile Include="QuadraticAssignmentProblem.cs" />
+    <Compile Include="QAPSimilarityCalculator.cs" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <None Include="Properties\AssemblyInfo.cs.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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </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>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances\3.3\HeuristicLab.Problems.Instances-3.3.csproj">
+      <Project>{3540E29E-4793-49E7-8EE2-FEA7F61C3994}</Project>
+      <Name>HeuristicLab.Problems.Instances-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.LinearAssignment\3.3\HeuristicLab.Problems.LinearAssignment-3.3.csproj">
+      <Project>{7250653F-DE83-4069-8D34-8050E8E45EA1}</Project>
+      <Name>HeuristicLab.Problems.LinearAssignment-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+  <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: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Interfaces/IQAPEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Interfaces/IQAPEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Interfaces/IQAPEvaluator.cs	(revision 9284)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  public interface IQAPEvaluator : ISingleObjectiveEvaluator {
+    ILookupParameter<Permutation> PermutationParameter { get; }
+    ILookupParameter<DoubleMatrix> DistancesParameter { get; }
+    ILookupParameter<DoubleMatrix> WeightsParameter { get; }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Interfaces/IQAPMoveEvaluator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Interfaces/IQAPMoveEvaluator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Interfaces/IQAPMoveEvaluator.cs	(revision 9284)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  public interface IQAPMoveEvaluator : ISingleObjectiveMoveEvaluator, IMoveOperator {
+    ILookupParameter<Permutation> PermutationParameter { get; }
+    ILookupParameter<DoubleMatrix> DistancesParameter { get; }
+    ILookupParameter<DoubleMatrix> WeightsParameter { get; }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveInsertionLocalImprovement.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveInsertionLocalImprovement.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveInsertionLocalImprovement.cs	(revision 9284)
@@ -0,0 +1,154 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Threading;
+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 {
+  [Item("QAPExhaustiveInsertionLocalImprovement", "Takes a solution and finds the local optimum with respect to the insertion neighborhood by decending along the steepest gradient.")]
+  [StorableClass]
+  public class QAPExhaustiveInsertionLocalImprovement : SingleSuccessorOperator, ILocalImprovementOperator {
+
+    public Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+
+    [Storable]
+    private QuadraticAssignmentProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set { problem = (QuadraticAssignmentProblem)value; }
+    }
+
+    public ILookupParameter<IntValue> LocalIterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LocalIterations"]; }
+    }
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<Permutation> AssignmentParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Assignment"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPExhaustiveInsertionLocalImprovement(bool deserializing) : base(deserializing) { }
+    protected QAPExhaustiveInsertionLocalImprovement(QAPExhaustiveInsertionLocalImprovement original, Cloner cloner)
+      : base(original, cloner) {
+      this.problem = cloner.Clone(original.problem);
+    }
+    public QAPExhaustiveInsertionLocalImprovement()
+      : base() {
+      Parameters.Add(new LookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum amount of iterations that should be performed (note that this operator will abort earlier when a local optimum is reached).", new IntValue(10000)));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The amount of evaluated solutions (here a move is counted only as 4/n evaluated solutions with n being the length of the permutation)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection where to store results."));
+      Parameters.Add(new LookupParameter<Permutation>("Assignment", "The permutation that is to be locally optimized."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value of the assignment."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem should be maximized or minimized."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPExhaustiveInsertionLocalImprovement(this, cloner);
+    }
+
+    public static void Improve(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) {
+      for (int i = localIterations.Value; i < maxIterations; i++) {
+        TranslocationMove bestMove = null;
+        double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
+        double evaluations = 0.0;
+        foreach (var move in ExhaustiveInsertionMoveGenerator.Generate(assignment)) {
+          double moveQuality = QAPTranslocationMoveEvaluator.Apply(assignment, move, weights, distances);
+          int min = Math.Min(move.Index1, move.Index3);
+          int max = Math.Max(move.Index2, move.Index3 + (move.Index2 - move.Index1));
+          evaluations += 2.0 * (max - min + 1) / assignment.Length
+            + 4.0 * (assignment.Length - (max - min + 1)) / assignment.Length;
+          if (maximization && moveQuality > bestQuality
+            || !maximization && moveQuality < bestQuality) {
+            bestQuality = moveQuality;
+            bestMove = move;
+          }
+        }
+        evaluatedSolutions.Value += (int)Math.Ceiling(evaluations);
+        if (bestMove == null) break;
+        TranslocationManipulator.Apply(assignment, bestMove.Index1, bestMove.Index2, bestMove.Index3);
+        quality.Value += bestQuality;
+        localIterations.Value++;
+        cancellation.ThrowIfCancellationRequested();
+      }
+    }
+
+    public override IOperation Apply() {
+      var maxIterations = MaximumIterationsParameter.ActualValue.Value;
+      var assignment = AssignmentParameter.ActualValue;
+      var maximization = MaximizationParameter.ActualValue.Value;
+      var weights = WeightsParameter.ActualValue;
+      var distances = DistancesParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var localIterations = LocalIterationsParameter.ActualValue;
+      var evaluations = EvaluatedSolutionsParameter.ActualValue;
+      if (localIterations == null) {
+        localIterations = new IntValue(0);
+        LocalIterationsParameter.ActualValue = localIterations;
+      }
+
+      Improve(assignment, weights, distances, quality, localIterations, evaluations, maximization, maxIterations, CancellationToken);
+
+      localIterations.Value = 0;
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveInversionLocalImprovement.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveInversionLocalImprovement.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveInversionLocalImprovement.cs	(revision 9284)
@@ -0,0 +1,151 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Threading;
+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 {
+  [Item("QAPExhaustiveInversionLocalImprovement", "Takes a solution and finds the local optimum with respect to the inversion neighborhood by decending along the steepest gradient.")]
+  [StorableClass]
+  public class QAPExhaustiveInversionLocalImprovement : SingleSuccessorOperator, ILocalImprovementOperator {
+
+    public Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+
+    [Storable]
+    private QuadraticAssignmentProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set { problem = (QuadraticAssignmentProblem)value; }
+    }
+
+    public ILookupParameter<IntValue> LocalIterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LocalIterations"]; }
+    }
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<Permutation> AssignmentParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Assignment"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPExhaustiveInversionLocalImprovement(bool deserializing) : base(deserializing) { }
+    protected QAPExhaustiveInversionLocalImprovement(QAPExhaustiveInversionLocalImprovement original, Cloner cloner)
+      : base(original, cloner) {
+      this.problem = cloner.Clone(original.problem);
+    }
+    public QAPExhaustiveInversionLocalImprovement()
+      : base() {
+      Parameters.Add(new LookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum amount of iterations that should be performed (note that this operator will abort earlier when a local optimum is reached).", new IntValue(10000)));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The amount of evaluated solutions (here a move is counted only as 4/n evaluated solutions with n being the length of the permutation)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection where to store results."));
+      Parameters.Add(new LookupParameter<Permutation>("Assignment", "The permutation that is to be locally optimized."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value of the assignment."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem should be maximized or minimized."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPExhaustiveInversionLocalImprovement(this, cloner);
+    }
+
+    public static void Improve(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) {
+      for (int i = localIterations.Value; i < maxIterations; i++) {
+        InversionMove bestMove = null;
+        double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
+        double evaluations = 0.0;
+        foreach (var move in ExhaustiveInversionMoveGenerator.Generate(assignment)) {
+          double moveQuality = QAPInversionMoveEvaluator.Apply(assignment, move, weights, distances);
+          evaluations += 2 * (move.Index2 - move.Index1 + 1) / (double)assignment.Length;
+          if (maximization && moveQuality > bestQuality
+            || !maximization && moveQuality < bestQuality) {
+            bestQuality = moveQuality;
+            bestMove = move;
+          }
+        }
+        evaluatedSolutions.Value = (int)Math.Ceiling(evaluations);
+        if (bestMove == null) break;
+        InversionManipulator.Apply(assignment, bestMove.Index1, bestMove.Index2);
+        quality.Value += bestQuality;
+        localIterations.Value++;
+        cancellation.ThrowIfCancellationRequested();
+      }
+    }
+
+    public override IOperation Apply() {
+      var maxIterations = MaximumIterationsParameter.ActualValue.Value;
+      var assignment = AssignmentParameter.ActualValue;
+      var maximization = MaximizationParameter.ActualValue.Value;
+      var weights = WeightsParameter.ActualValue;
+      var distances = DistancesParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var localIterations = LocalIterationsParameter.ActualValue;
+      var evaluations = EvaluatedSolutionsParameter.ActualValue;
+      if (localIterations == null) {
+        localIterations = new IntValue(0);
+        LocalIterationsParameter.ActualValue = localIterations;
+      }
+
+      Improve(assignment, weights, distances, quality, localIterations, evaluations, maximization, maxIterations, CancellationToken);
+
+      localIterations.Value = 0;
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveSwap2LocalImprovement.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveSwap2LocalImprovement.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveSwap2LocalImprovement.cs	(revision 9284)
@@ -0,0 +1,209 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Threading;
+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 {
+  [Item("QAPExhaustiveSwap2LocalImprovement", "Takes a solution and finds the local optimum with respect to the swap2 neighborhood by decending along the steepest gradient.")]
+  [StorableClass]
+  public class QAPExhaustiveSwap2LocalImprovement : SingleSuccessorOperator, ILocalImprovementOperator {
+
+    public Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+
+    [Storable]
+    private QuadraticAssignmentProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set { problem = (QuadraticAssignmentProblem)value; }
+    }
+
+    public ILookupParameter<IntValue> LocalIterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LocalIterations"]; }
+    }
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<Permutation> AssignmentParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Assignment"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    public IValueLookupParameter<BoolValue> UseFastEvaluationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["UseFastEvaluation"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPExhaustiveSwap2LocalImprovement(bool deserializing) : base(deserializing) { }
+    protected QAPExhaustiveSwap2LocalImprovement(QAPExhaustiveSwap2LocalImprovement original, Cloner cloner)
+      : base(original, cloner) {
+      this.problem = cloner.Clone(original.problem);
+    }
+    public QAPExhaustiveSwap2LocalImprovement()
+      : base() {
+      Parameters.Add(new LookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum amount of iterations that should be performed (note that this operator will abort earlier when a local optimum is reached).", new IntValue(10000)));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The amount of evaluated solutions (here a move is counted only as 4/n evaluated solutions with n being the length of the permutation)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection where to store results."));
+      Parameters.Add(new LookupParameter<Permutation>("Assignment", "The permutation that is to be locally optimized."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value of the assignment."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem should be maximized or minimized."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("UseFastEvaluation", "Enabling this option will use a NxN double matrix to save the last move qualities. The moves of the first iteration will then be evaluated in O(N) while all further moves will be evaluated in O(1).", new BoolValue(true)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPExhaustiveSwap2LocalImprovement(this, cloner);
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("LocalIterations"))
+        Parameters.Add(new LookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed."));
+      if (!Parameters.ContainsKey("UseFastEvaluation"))
+        Parameters.Add(new ValueLookupParameter<BoolValue>("UseFastEvaluation", "Enabling this option will use a NxN double matrix to save the last move qualities. The moves of the first iteration will then be evaluated in O(N) while all further moves will be evaluated in O(1).", new BoolValue(false)));
+    }
+    #endregion
+
+    public static void Improve(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) {
+      double evalSolPerMove = 4.0 / assignment.Length;
+
+      for (int i = localIterations.Value; i < maxIterations; i++) {
+        Swap2Move bestMove = null;
+        double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
+        double evaluations = 0.0;
+        foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment)) {
+          double moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances);
+          evaluations += evalSolPerMove;
+          if (maximization && moveQuality > bestQuality
+            || !maximization && moveQuality < bestQuality) {
+            bestQuality = moveQuality;
+            bestMove = move;
+          }
+        }
+        evaluatedSolutions.Value += (int)Math.Ceiling(evaluations);
+        if (bestMove == null) break;
+        Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2);
+        quality.Value += bestQuality;
+        localIterations.Value++;
+        cancellation.ThrowIfCancellationRequested();
+      }
+    }
+
+    public static void ImproveFast(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) {
+      Swap2Move bestMove = null;
+      double evaluations = 0.0;
+      var lastQuality = new double[assignment.Length, assignment.Length];
+      for (int i = localIterations.Value; i < maxIterations; i++) {
+        double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
+        var lastMove = bestMove;
+        bestMove = null;
+        foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment)) {
+          double moveQuality;
+          if (lastMove == null) {
+            moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances);
+            evaluations += 4.0 / assignment.Length;
+          } else {
+            moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, lastQuality[move.Index1, move.Index2], weights, distances, lastMove);
+            if (move.Index1 == lastMove.Index1 || move.Index2 == lastMove.Index1 || move.Index1 == lastMove.Index2 || move.Index2 == lastMove.Index2)
+              evaluations += 4.0 / assignment.Length;
+            else evaluations += 2.0 / (assignment.Length * assignment.Length);
+          }
+          lastQuality[move.Index1, move.Index2] = moveQuality;
+          if (maximization && moveQuality > bestQuality
+            || !maximization && moveQuality < bestQuality) {
+            bestQuality = moveQuality;
+            bestMove = move;
+          }
+        }
+        if (bestMove == null) break;
+        Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2);
+        quality.Value += bestQuality;
+        localIterations.Value++;
+        if (cancellation.IsCancellationRequested) {
+          evaluatedSolutions.Value += (int)Math.Round(evaluations);
+          throw new OperationCanceledException();
+        }
+      }
+      evaluatedSolutions.Value += (int)Math.Round(evaluations);
+    }
+
+    public override IOperation Apply() {
+      var maxIterations = MaximumIterationsParameter.ActualValue.Value;
+      var assignment = AssignmentParameter.ActualValue;
+      var maximization = MaximizationParameter.ActualValue.Value;
+      var weights = WeightsParameter.ActualValue;
+      var distances = DistancesParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var localIterations = LocalIterationsParameter.ActualValue;
+      var evaluations = EvaluatedSolutionsParameter.ActualValue;
+      if (localIterations == null) {
+        localIterations = new IntValue(0);
+        LocalIterationsParameter.ActualValue = localIterations;
+      }
+
+      if (UseFastEvaluationParameter.ActualValue.Value)
+        ImproveFast(assignment, weights, distances, quality, localIterations, evaluations, maximization, maxIterations, CancellationToken);
+      else Improve(assignment, weights, distances, quality, localIterations, evaluations, maximization, maxIterations, CancellationToken);
+
+      localIterations.Value = 0;
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPStochasticScrambleLocalImprovement.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPStochasticScrambleLocalImprovement.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPStochasticScrambleLocalImprovement.cs	(revision 9284)
@@ -0,0 +1,164 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Threading;
+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 {
+  [Item("QAPStochasticScrambleLocalImprovement", "Takes a solution and finds the local optimum with respect to the scramble neighborhood by decending along the steepest gradient.")]
+  [StorableClass]
+  public class QAPStochasticScrambleLocalImprovement : SingleSuccessorOperator, ILocalImprovementOperator, IStochasticOperator {
+
+    public Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+
+    [Storable]
+    private QuadraticAssignmentProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set { problem = (QuadraticAssignmentProblem)value; }
+    }
+
+    public ILookupParameter<IntValue> LocalIterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LocalIterations"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<Permutation> AssignmentParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Assignment"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    public IValueLookupParameter<IntValue> NeighborhoodSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["NeighborhoodSize"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPStochasticScrambleLocalImprovement(bool deserializing) : base(deserializing) { }
+    protected QAPStochasticScrambleLocalImprovement(QAPStochasticScrambleLocalImprovement original, Cloner cloner)
+      : base(original, cloner) {
+      this.problem = cloner.Clone(original.problem);
+    }
+    public QAPStochasticScrambleLocalImprovement()
+      : base() {
+      Parameters.Add(new LookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum amount of iterations that should be performed (note that this operator will abort earlier when a local optimum is reached).", new IntValue(10000)));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The amount of evaluated solutions (here a move is counted only as 4/n evaluated solutions with n being the length of the permutation)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection where to store results."));
+      Parameters.Add(new LookupParameter<Permutation>("Assignment", "The permutation that is to be locally optimized."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value of the assignment."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem should be maximized or minimized."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("NeighborhoodSize", "The number of moves to sample from the neighborhood.", new IntValue(100)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPStochasticScrambleLocalImprovement(this, cloner);
+    }
+
+    public static void Improve(IRandom random, Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, int neighborhoodSize, CancellationToken cancellation) {
+      for (int i = localIterations.Value; i < maxIterations; i++) {
+        ScrambleMove bestMove = null;
+        double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
+        double evaluations = 0.0;
+        for (int j = 0; j < neighborhoodSize; j++) {
+          var move = StochasticScrambleMultiMoveGenerator.GenerateRandomMove(assignment, random);
+          double moveQuality = QAPScrambleMoveEvaluator.Apply(assignment, move, weights, distances);
+          evaluations += 2.0 * move.ScrambledIndices.Length / assignment.Length;
+          if (maximization && moveQuality > bestQuality
+            || !maximization && moveQuality < bestQuality) {
+            bestQuality = moveQuality;
+            bestMove = move;
+          }
+        }
+        evaluatedSolutions.Value = (int)Math.Ceiling(evaluations);
+        if (bestMove == null) break;
+        ScrambleManipulator.Apply(assignment, bestMove.StartIndex, bestMove.ScrambledIndices);
+        quality.Value += bestQuality;
+        localIterations.Value++;
+        cancellation.ThrowIfCancellationRequested();
+      }
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var maxIterations = MaximumIterationsParameter.ActualValue.Value;
+      var neighborhoodSize = NeighborhoodSizeParameter.ActualValue.Value;
+      var assignment = AssignmentParameter.ActualValue;
+      var maximization = MaximizationParameter.ActualValue.Value;
+      var weights = WeightsParameter.ActualValue;
+      var distances = DistancesParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var localIterations = LocalIterationsParameter.ActualValue;
+      var evaluations = EvaluatedSolutionsParameter.ActualValue;
+      if (localIterations == null) {
+        localIterations = new IntValue(0);
+        LocalIterationsParameter.ActualValue = localIterations;
+      }
+
+      Improve(random, assignment, weights, distances, quality, localIterations, evaluations, maximization, maxIterations, neighborhoodSize, CancellationToken);
+
+      localIterations.Value = 0;
+      return base.Apply();
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Plugin.cs.frame
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Plugin.cs.frame	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Plugin.cs.frame	(revision 9284)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 {
+  [Plugin("HeuristicLab.Problems.QuadraticAssignment", "3.3.7.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.QuadraticAssignment-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.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.LinearAssignment", "3.3")]
+  public class HeuristicLabProblemsQuadraticAssignmentPlugin : PluginBase { }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Properties/AssemblyInfo.cs.frame	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/Properties/AssemblyInfo.cs.frame	(revision 9284)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2012 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.7.$WCREV$")]
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPAssignment.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPAssignment.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPAssignment.cs	(revision 9284)
@@ -0,0 +1,107 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.ComponentModel;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("QAP Assignment", "Represents a solution to the QAP.")]
+  [StorableClass]
+  public sealed class QAPAssignment : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private DoubleMatrix distances;
+    public DoubleMatrix Distances {
+      get { return distances; }
+      set {
+        bool changed = (distances != value);
+        distances = value;
+        if (changed) OnPropertyChanged("Distances");
+      }
+    }
+
+    [Storable]
+    private DoubleMatrix weights;
+    public DoubleMatrix Weights {
+      get { return weights; }
+      set {
+        bool changed = (weights != value);
+        weights = value;
+        if (changed) OnPropertyChanged("Weights");
+      }
+    }
+
+    [Storable]
+    private Permutation assignment;
+    public Permutation Assignment {
+      get { return assignment; }
+      set {
+        bool changed = (assignment != value);
+        assignment = value;
+        if (changed) OnPropertyChanged("Assignment");
+      }
+    }
+
+    [Storable]
+    private DoubleValue quality;
+    public DoubleValue Quality {
+      get { return quality; }
+      set {
+        bool changed = (quality != value);
+        quality = value;
+        if (changed) OnPropertyChanged("Quality");
+      }
+    }
+
+    [StorableConstructor]
+    private QAPAssignment(bool deserializing) : base(deserializing) { }
+    private QAPAssignment(QAPAssignment original, Cloner cloner)
+      : base(original, cloner) {
+      distances = cloner.Clone(original.distances);
+      weights = cloner.Clone(original.weights);
+      assignment = cloner.Clone(original.assignment);
+      quality = cloner.Clone(original.quality);
+    }
+    public QAPAssignment(DoubleMatrix weights, Permutation assignment) {
+      this.weights = weights;
+      this.assignment = assignment;
+    }
+    public QAPAssignment(DoubleMatrix weights, Permutation assignment, DoubleValue quality)
+      : this(weights, assignment) {
+      this.quality = quality;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPAssignment(this, cloner);
+    }
+
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    private void OnPropertyChanged(string propertyName) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPPermutationProximityCalculator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPPermutationProximityCalculator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPPermutationProximityCalculator.cs	(revision 9284)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPSimilarityCalculator.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPSimilarityCalculator.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPSimilarityCalculator.cs	(revision 9284)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization.Operators;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// An operator that performs similarity calculation between two quadratic assignment solutions.
+  /// </summary>
+  /// <remarks>
+  /// The operator calculates the similarity based on the number of edges the two solutions have in common.
+  /// </remarks>
+  [Item("QAPSimilarityCalculator", "An operator that performs similarity calculation between two quadratic assignment solutions. The operator calculates the similarity based on the number of edges the two solutions have in common.")]
+  public sealed class QAPSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    private QAPSimilarityCalculator(bool deserializing) : base(deserializing) { }
+    private QAPSimilarityCalculator(QAPSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
+    public QAPSimilarityCalculator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPSimilarityCalculator(this, cloner);
+    }
+
+    public static double CalculateSimilarity(Permutation left, Permutation right) {
+      if (left == null || right == null)
+        throw new ArgumentException("Cannot calculate similarity because one of the provided solutions or both are null.");
+      if (left.Length != right.Length)
+        throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths.");
+      if (object.ReferenceEquals(left, right)) return 1.0;
+
+      return QAPPermutationProximityCalculator.CalculateGenotypeSimilarity(left, right);
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var sol1 = leftSolution.Variables[SolutionVariableName].Value as Permutation;
+      var sol2 = rightSolution.Variables[SolutionVariableName].Value as Permutation;
+
+      return CalculateSimilarity(sol1, sol2);
+    }
+  }
+}
Index: /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs
===================================================================
--- /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs	(revision 9284)
+++ /branches/ImprovingStringConvertibleMatrix/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs	(revision 9284)
@@ -0,0 +1,498 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.Instances;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("Quadratic Assignment Problem", "The Quadratic Assignment Problem (QAP) can be described as the problem of assigning N facilities to N fixed locations such that there is exactly one facility in each location and that the sum of the distances multiplied by the connection strength between the facilities becomes minimal.")]
+  [Creatable("Problems")]
+  [StorableClass]
+  public sealed class QuadraticAssignmentProblem : SingleObjectiveHeuristicOptimizationProblem<IQAPEvaluator, IPermutationCreator>, IStorableContent,
+    IProblemInstanceConsumer<QAPData>,
+    IProblemInstanceConsumer<TSPData> {
+    public string Filename { get; set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
+    }
+
+    #region Parameter Properties
+    public IValueParameter<ItemSet<Permutation>> BestKnownSolutionsParameter {
+      get { return (IValueParameter<ItemSet<Permutation>>)Parameters["BestKnownSolutions"]; }
+    }
+    public IValueParameter<Permutation> BestKnownSolutionParameter {
+      get { return (IValueParameter<Permutation>)Parameters["BestKnownSolution"]; }
+    }
+    public IValueParameter<DoubleMatrix> WeightsParameter {
+      get { return (IValueParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public IValueParameter<DoubleMatrix> DistancesParameter {
+      get { return (IValueParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public IValueParameter<DoubleValue> LowerBoundParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["LowerBound"]; }
+    }
+    public IValueParameter<DoubleValue> AverageQualityParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["AverageQuality"]; }
+    }
+    #endregion
+
+    #region Properties
+    public ItemSet<Permutation> BestKnownSolutions {
+      get { return BestKnownSolutionsParameter.Value; }
+      set { BestKnownSolutionsParameter.Value = value; }
+    }
+    public Permutation BestKnownSolution {
+      get { return BestKnownSolutionParameter.Value; }
+      set { BestKnownSolutionParameter.Value = value; }
+    }
+    public DoubleMatrix Weights {
+      get { return WeightsParameter.Value; }
+      set { WeightsParameter.Value = value; }
+    }
+    public DoubleMatrix Distances {
+      get { return DistancesParameter.Value; }
+      set { DistancesParameter.Value = value; }
+    }
+    public DoubleValue LowerBound {
+      get { return LowerBoundParameter.Value; }
+      set { LowerBoundParameter.Value = value; }
+    }
+    public DoubleValue AverageQuality {
+      get { return AverageQualityParameter.Value; }
+      set { AverageQualityParameter.Value = value; }
+    }
+
+    private BestQAPSolutionAnalyzer BestQAPSolutionAnalyzer {
+      get { return Operators.OfType<BestQAPSolutionAnalyzer>().FirstOrDefault(); }
+    }
+
+    private QAPAlleleFrequencyAnalyzer QAPAlleleFrequencyAnalyzer {
+      get { return Operators.OfType<QAPAlleleFrequencyAnalyzer>().FirstOrDefault(); }
+    }
+
+    private QAPPopulationDiversityAnalyzer QAPPopulationDiversityAnalyzer {
+      get { return Operators.OfType<QAPPopulationDiversityAnalyzer>().FirstOrDefault(); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private QuadraticAssignmentProblem(bool deserializing) : base(deserializing) { }
+    private QuadraticAssignmentProblem(QuadraticAssignmentProblem original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+    public QuadraticAssignmentProblem()
+      : base(new QAPEvaluator(), new RandomPermutationCreator()) {
+      Parameters.Add(new OptionalValueParameter<ItemSet<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
+      Parameters.Add(new OptionalValueParameter<Permutation>("BestKnownSolution", "The best known solution which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
+      Parameters.Add(new ValueParameter<DoubleMatrix>("Weights", "The strength of the connection between the facilities.", new DoubleMatrix(5, 5)));
+      Parameters.Add(new ValueParameter<DoubleMatrix>("Distances", "The distance matrix which can either be specified directly without the coordinates, or can be calculated automatically from the coordinates.", new DoubleMatrix(5, 5)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("LowerBound", "The Gilmore-Lawler lower bound to the solution quality."));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("AverageQuality", "The expected quality of a random solution."));
+
+      Maximization.Value = false;
+      MaximizationParameter.Hidden = true;
+
+      WeightsParameter.GetsCollected = false;
+      Weights = new DoubleMatrix(new double[,] {
+        { 0, 1, 0, 0, 1 },
+        { 1, 0, 1, 0, 0 },
+        { 0, 1, 0, 1, 0 },
+        { 0, 0, 1, 0, 1 },
+        { 1, 0, 0, 1, 0 }
+      });
+
+      DistancesParameter.GetsCollected = false;
+      Distances = new DoubleMatrix(new double[,] {
+        {   0, 360, 582, 582, 360 },
+        { 360,   0, 360, 582, 582 },
+        { 582, 360,   0, 360, 582 },
+        { 582, 582, 360,   0, 360 },
+        { 360, 582, 582, 360,   0 }
+      });
+
+      SolutionCreator.PermutationParameter.ActualName = "Assignment";
+      ParameterizeSolutionCreator();
+      ParameterizeEvaluator();
+
+      InitializeOperators();
+      RegisterEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QuadraticAssignmentProblem(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("BestKnownSolutions")) {
+        Parameters.Add(new OptionalValueParameter<ItemSet<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
+      } else if (Parameters["BestKnownSolutions"].GetType().Equals(typeof(OptionalValueParameter<ItemList<Permutation>>))) {
+        ItemList<Permutation> list = ((OptionalValueParameter<ItemList<Permutation>>)Parameters["BestKnownSolutions"]).Value;
+        Parameters.Remove("BestKnownSolutions");
+        Parameters.Add(new OptionalValueParameter<ItemSet<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", (list != null ? new ItemSet<Permutation>(list) : null)));
+      }
+      if (Parameters.ContainsKey("DistanceMatrix")) {
+        DoubleMatrix d = ((ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]).Value;
+        Parameters.Remove("DistanceMatrix");
+        Parameters.Add(new ValueParameter<DoubleMatrix>("Distances", "The distance matrix which can either be specified directly without the coordinates, or can be calculated automatically from the coordinates.", d));
+      }
+      if (!Parameters.ContainsKey("LowerBound")) {
+        Parameters.Add(new OptionalValueParameter<DoubleValue>("LowerBound", "The Gilmore-Lawler lower bound to the solution quality."));
+        LowerBound = new DoubleValue(GilmoreLawlerBoundCalculator.CalculateLowerBound(Weights, Distances));
+      }
+      if (!Parameters.ContainsKey("AverageQuality")) {
+        Parameters.Add(new OptionalValueParameter<DoubleValue>("AverageQuality", "The expected quality of a random solution."));
+        AverageQuality = new DoubleValue(ComputeAverageQuality());
+      }
+      #endregion
+      RegisterEventHandlers();
+    }
+
+    #region Events
+    protected override void OnSolutionCreatorChanged() {
+      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
+      ParameterizeSolutionCreator();
+      ParameterizeEvaluator();
+      ParameterizeAnalyzers();
+      ParameterizeOperators();
+      base.OnSolutionCreatorChanged();
+    }
+    protected override void OnEvaluatorChanged() {
+      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      ParameterizeEvaluator();
+      ParameterizeAnalyzers();
+      ParameterizeOperators();
+      base.OnEvaluatorChanged();
+    }
+
+    private void SolutionCreator_PermutationParameter_ActualNameChanged(object sender, EventArgs e) {
+      ParameterizeEvaluator();
+      ParameterizeAnalyzers();
+      ParameterizeOperators();
+    }
+    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
+      ParameterizeAnalyzers();
+      ParameterizeOperators();
+    }
+    private void WeightsParameter_ValueChanged(object sender, EventArgs e) {
+      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
+      Weights.ColumnsChanged += new EventHandler(Weights_ColumnsChanged);
+      Weights.ToStringChanged += new EventHandler(Weights_ToStringChanged);
+      ParameterizeSolutionCreator();
+      ParameterizeEvaluator();
+      ParameterizeOperators();
+      AdjustDistanceMatrix();
+    }
+    private void Weights_RowsChanged(object sender, EventArgs e) {
+      if (Weights.Rows != Weights.Columns)
+        ((IStringConvertibleMatrix)Weights).Columns = Weights.Rows;
+      else {
+        ParameterizeSolutionCreator();
+        ParameterizeEvaluator();
+        ParameterizeOperators();
+        AdjustDistanceMatrix();
+      }
+    }
+    private void Weights_ColumnsChanged(object sender, EventArgs e) {
+      if (Weights.Rows != Weights.Columns)
+        ((IStringConvertibleMatrix)Weights).Rows = Weights.Columns;
+      else {
+        ParameterizeSolutionCreator();
+        ParameterizeEvaluator();
+        ParameterizeOperators();
+        AdjustDistanceMatrix();
+      }
+    }
+    private void Weights_ToStringChanged(object sender, EventArgs e) {
+      UpdateParameterValues();
+    }
+    private void DistancesParameter_ValueChanged(object sender, EventArgs e) {
+      Distances.RowsChanged += new EventHandler(Distances_RowsChanged);
+      Distances.ColumnsChanged += new EventHandler(Distances_ColumnsChanged);
+      Distances.ToStringChanged += new EventHandler(Distances_ToStringChanged);
+      ParameterizeSolutionCreator();
+      ParameterizeEvaluator();
+      ParameterizeOperators();
+      AdjustWeightsMatrix();
+    }
+    private void Distances_RowsChanged(object sender, EventArgs e) {
+      if (Distances.Rows != Distances.Columns)
+        ((IStringConvertibleMatrix)Distances).Columns = Distances.Rows;
+      else {
+        ParameterizeSolutionCreator();
+        ParameterizeEvaluator();
+        ParameterizeOperators();
+        AdjustWeightsMatrix();
+      }
+    }
+    private void Distances_ColumnsChanged(object sender, EventArgs e) {
+      if (Distances.Rows != Distances.Columns)
+        ((IStringConvertibleMatrix)Distances).Rows = Distances.Columns;
+      else {
+        ParameterizeSolutionCreator();
+        ParameterizeEvaluator();
+        ParameterizeOperators();
+        AdjustWeightsMatrix();
+      }
+    }
+    private void Distances_ToStringChanged(object sender, EventArgs e) {
+      UpdateParameterValues();
+    }
+    #endregion
+
+    private void RegisterEventHandlers() {
+      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
+      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      WeightsParameter.ValueChanged += new EventHandler(WeightsParameter_ValueChanged);
+      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
+      Weights.ColumnsChanged += new EventHandler(Weights_ColumnsChanged);
+      Weights.ToStringChanged += new EventHandler(Weights_ToStringChanged);
+      DistancesParameter.ValueChanged += new EventHandler(DistancesParameter_ValueChanged);
+      Distances.RowsChanged += new EventHandler(Distances_RowsChanged);
+      Distances.ColumnsChanged += new EventHandler(Distances_ColumnsChanged);
+      Distances.ToStringChanged += new EventHandler(Distances_ToStringChanged);
+    }
+
+    #region Helpers
+    private void InitializeOperators() {
+      var defaultOperators = new HashSet<IPermutationOperator>(new IPermutationOperator[] {
+        new PartiallyMatchedCrossover(),
+        new Swap2Manipulator(),
+        new ExhaustiveSwap2MoveGenerator()
+      });
+      Operators.AddRange(defaultOperators);
+      Operators.AddRange(ApplicationManager.Manager.GetInstances<IPermutationOperator>().Except(defaultOperators, new TypeEqualityComparer<IPermutationOperator>()));
+      Operators.RemoveAll(x => x is ISingleObjectiveMoveEvaluator);
+      Operators.AddRange(ApplicationManager.Manager.GetInstances<IQAPMoveEvaluator>());
+      Operators.Add(new BestQAPSolutionAnalyzer());
+      Operators.Add(new QAPAlleleFrequencyAnalyzer());
+      Operators.Add(new QAPPopulationDiversityAnalyzer());
+      Operators.Add(new QAPExhaustiveSwap2LocalImprovement());
+      Operators.Add(new QAPSimilarityCalculator());
+      ParameterizeAnalyzers();
+      ParameterizeOperators();
+    }
+    private void ParameterizeSolutionCreator() {
+      if (SolutionCreator != null) {
+        SolutionCreator.PermutationTypeParameter.Value = new PermutationType(PermutationTypes.Absolute);
+        SolutionCreator.LengthParameter.Value = new IntValue(Weights.Rows);
+      }
+    }
+    private void ParameterizeEvaluator() {
+      if (Evaluator != null) {
+        Evaluator.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        Evaluator.DistancesParameter.ActualName = DistancesParameter.Name;
+        Evaluator.WeightsParameter.ActualName = WeightsParameter.Name;
+      }
+    }
+    private void ParameterizeAnalyzers() {
+      if (BestQAPSolutionAnalyzer != null) {
+        BestQAPSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        BestQAPSolutionAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
+        BestQAPSolutionAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
+        BestQAPSolutionAnalyzer.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        BestQAPSolutionAnalyzer.ResultsParameter.ActualName = "Results";
+        BestQAPSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
+        BestQAPSolutionAnalyzer.BestKnownSolutionsParameter.ActualName = BestKnownSolutionsParameter.Name;
+        BestQAPSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      }
+      if (QAPAlleleFrequencyAnalyzer != null) {
+        QAPAlleleFrequencyAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        QAPAlleleFrequencyAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
+        QAPAlleleFrequencyAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
+        QAPAlleleFrequencyAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        QAPAlleleFrequencyAnalyzer.ResultsParameter.ActualName = "Results";
+        QAPAlleleFrequencyAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        QAPAlleleFrequencyAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
+      }
+      if (QAPPopulationDiversityAnalyzer != null) {
+        QAPPopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        QAPPopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        QAPPopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
+        QAPPopulationDiversityAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+      }
+    }
+    private void ParameterizeOperators() {
+      foreach (IPermutationCrossover op in Operators.OfType<IPermutationCrossover>()) {
+        op.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        op.ChildParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+      }
+      foreach (IPermutationManipulator op in Operators.OfType<IPermutationManipulator>()) {
+        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+      }
+      foreach (IPermutationMoveOperator op in Operators.OfType<IPermutationMoveOperator>()) {
+        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+      }
+      if (Operators.OfType<IMoveGenerator>().Any()) {
+        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().Any()) {
+          string inversionMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().First().InversionMoveParameter.ActualName;
+          foreach (IPermutationInversionMoveOperator op in Operators.OfType<IPermutationInversionMoveOperator>())
+            op.InversionMoveParameter.ActualName = inversionMove;
+        }
+        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().Any()) {
+          string translocationMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().First().TranslocationMoveParameter.ActualName;
+          foreach (IPermutationTranslocationMoveOperator op in Operators.OfType<IPermutationTranslocationMoveOperator>())
+            op.TranslocationMoveParameter.ActualName = translocationMove;
+        }
+        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationSwap2MoveOperator>().Any()) {
+          string swapMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationSwap2MoveOperator>().First().Swap2MoveParameter.ActualName;
+          foreach (IPermutationSwap2MoveOperator op in Operators.OfType<IPermutationSwap2MoveOperator>()) {
+            op.Swap2MoveParameter.ActualName = swapMove;
+          }
+        }
+      }
+      foreach (var op in Operators.OfType<IPermutationMultiNeighborhoodShakingOperator>())
+        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+
+      QAPExhaustiveSwap2LocalImprovement localOpt = Operators.OfType<QAPExhaustiveSwap2LocalImprovement>().SingleOrDefault();
+      if (localOpt != null) {
+        localOpt.AssignmentParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        localOpt.DistancesParameter.ActualName = DistancesParameter.Name;
+        localOpt.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        localOpt.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        localOpt.WeightsParameter.ActualName = WeightsParameter.Name;
+      }
+
+      QAPSimilarityCalculator similarityCalculator = Operators.OfType<QAPSimilarityCalculator>().SingleOrDefault();
+      if (similarityCalculator != null) {
+        similarityCalculator.SolutionVariableName = SolutionCreator.PermutationParameter.ActualName;
+        similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName;
+      }
+    }
+
+    private void AdjustDistanceMatrix() {
+      if (Distances.Rows != Weights.Rows || Distances.Columns != Weights.Columns) {
+        ((IStringConvertibleMatrix)Distances).Rows = Weights.Rows;
+      }
+    }
+
+    private void AdjustWeightsMatrix() {
+      if (Weights.Rows != Distances.Rows || Weights.Columns != Distances.Columns) {
+        ((IStringConvertibleMatrix)Weights).Rows = Distances.Rows;
+      }
+    }
+
+    private void UpdateParameterValues() {
+      Permutation lbSolution;
+      // calculate the optimum of a LAP relaxation and use it as lower bound of our QAP
+      LowerBound = new DoubleValue(GilmoreLawlerBoundCalculator.CalculateLowerBound(Weights, Distances, out lbSolution));
+      // evalute the LAP optimal solution as if it was a QAP solution
+      var lbSolutionQuality = QAPEvaluator.Apply(lbSolution, Weights, Distances);
+      // in case both qualities are the same it means that the LAP optimum is also a QAP optimum
+      if (LowerBound.Value.IsAlmost(lbSolutionQuality)) {
+        BestKnownSolution = lbSolution;
+        BestKnownQuality = new DoubleValue(LowerBound.Value);
+      }
+      AverageQuality = new DoubleValue(ComputeAverageQuality());
+    }
+
+    private double ComputeAverageQuality() {
+      double rt = 0, rd = 0, wt = 0, wd = 0;
+      int n = Weights.Rows;
+      for (int i = 0; i < n; i++)
+        for (int j = 0; j < n; j++) {
+          if (i == j) {
+            rd += Distances[i, i];
+            wd += Weights[i, i];
+          } else {
+            rt += Distances[i, j];
+            wt += Weights[i, j];
+          }
+        }
+
+      return rt * wt / (n * (n - 1)) + rd * wd / n;
+    }
+    #endregion
+
+    public void Load(QAPData data) {
+      var weights = new DoubleMatrix(data.Weights);
+      var distances = new DoubleMatrix(data.Distances);
+      Name = data.Name;
+      Description = data.Description;
+      Load(weights, distances);
+      if (data.BestKnownQuality.HasValue) BestKnownQuality = new DoubleValue(data.BestKnownQuality.Value);
+      EvaluateAndLoadAssignment(data.BestKnownAssignment);
+      OnReset();
+    }
+
+    public void Load(TSPData data) {
+      if (data.Dimension > 1000)
+        throw new System.IO.InvalidDataException("Instances with more than 1000 customers are not supported by the QAP.");
+      var weights = new DoubleMatrix(data.Dimension, data.Dimension);
+      for (int i = 0; i < data.Dimension; i++)
+        weights[i, (i + 1) % data.Dimension] = 1;
+      var distances = new DoubleMatrix(data.GetDistanceMatrix());
+      Name = data.Name;
+      Description = data.Description;
+      Load(weights, distances);
+      if (data.BestKnownQuality.HasValue) BestKnownQuality = new DoubleValue(data.BestKnownQuality.Value);
+      EvaluateAndLoadAssignment(data.BestKnownTour);
+      OnReset();
+    }
+
+    public void Load(DoubleMatrix weights, DoubleMatrix distances) {
+      if (weights == null || weights.Rows == 0)
+        throw new System.IO.InvalidDataException("The given instance does not contain weights!");
+      if (weights.Rows != weights.Columns)
+        throw new System.IO.InvalidDataException("The weights matrix is not a square matrix!");
+      if (distances == null || distances.Rows == 0)
+        throw new System.IO.InvalidDataException("The given instance does not contain distances!");
+      if (distances.Rows != distances.Columns)
+        throw new System.IO.InvalidDataException("The distances matrix is not a square matrix!");
+      if (weights.Rows != distances.Columns)
+        throw new System.IO.InvalidDataException("The weights matrix and the distance matrix are not of equal size!");
+
+      Weights = weights;
+      Distances = distances;
+
+      BestKnownQuality = null;
+      BestKnownSolution = null;
+      BestKnownSolutions = null;
+      UpdateParameterValues();
+    }
+
+    public void EvaluateAndLoadAssignment(int[] assignment) {
+      if (assignment == null || assignment.Length == 0) return;
+      var vector = new Permutation(PermutationTypes.Absolute, assignment);
+      var result = QAPEvaluator.Apply(vector, Weights, Distances);
+      BestKnownQuality = new DoubleValue(result);
+      BestKnownSolution = vector;
+      BestKnownSolutions = new ItemSet<Permutation>();
+      BestKnownSolutions.Add((Permutation)vector.Clone());
+    }
+  }
+}
