Index: branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj
===================================================================
--- branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj	(revision 6570)
+++ branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.QuadraticAssignment.Algorithms-3.3.csproj	(revision 6586)
@@ -107,5 +107,5 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="QAPRobustTabooSeachOperator.cs" />
+    <Compile Include="RobustTabooSeachOperator.cs" />
     <Compile Include="RobustTabooSearch.cs" />
     <None Include="Plugin.cs.frame" />
Index: branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/QAPRobustTabooSeachOperator.cs
===================================================================
--- branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/QAPRobustTabooSeachOperator.cs	(revision 6570)
+++ 	(revision )
@@ -1,177 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Encodings.PermutationEncoding;
-using HeuristicLab.Operators;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
-  [Item("QAPRobustTabooSearchOperator", "Performs an iteration of the robust taboo search algorithm as descrbied in Taillard 1991.")]
-  public sealed class QAPRobustTabooSeachOperator : SingleSuccessorOperator, IIterationBasedOperator, IStochasticOperator {
-
-    #region Parameter Properties
-    public ILookupParameter<IntValue> IterationsParameter {
-      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
-    }
-    public ILookupParameter<IntValue> TabuTenureParameter {
-      get { return (ILookupParameter<IntValue>)Parameters["TabuTenure"]; }
-    }
-    public ILookupParameter<Permutation> PermutationParameter {
-      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
-    }
-    public ILookupParameter<DoubleMatrix> WeightsParameter {
-      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
-    }
-    public ILookupParameter<DoubleMatrix> DistancesParameter {
-      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
-    }
-    public ILookupParameter<DoubleMatrix> ShortTermMemoryParameter {
-      get { return (ILookupParameter<DoubleMatrix>)Parameters["ShortTermMemory"]; }
-    }
-    public ILookupParameter<DoubleMatrix> LongTermMemoryParameter {
-      get { return (ILookupParameter<DoubleMatrix>)Parameters["LongTermMemory"]; }
-    }
-    public ILookupParameter<DoubleValue> QualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
-    }
-    public ILookupParameter<DoubleValue> BestQualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters["BestQuality"]; }
-    }
-
-    public ILookupParameter<IRandom> RandomParameter {
-      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
-    }
-    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
-    }
-    public IValueLookupParameter<IntValue> MinimumTabuTenureParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters["MinimumTabuTenure"]; }
-    }
-    public IValueLookupParameter<IntValue> MaximumTabuTenureParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
-    }
-    public IValueLookupParameter<IntValue> TabuTenureAdaptionIntervalParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters["TabuTenureAdaptionInterval"]; }
-    }
-    public IValueLookupParameter<BoolValue> UseAlternativeAspirationParameter {
-      get { return (IValueLookupParameter<BoolValue>)Parameters["UseAlternativeAspiration"]; }
-    }
-    public IValueLookupParameter<IntValue> AlternativeAspirationTenureParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters["AlternativeAspirationTenure"]; }
-    }
-    #endregion
-
-    [StorableConstructor]
-    private QAPRobustTabooSeachOperator(bool deserializing) : base(deserializing) { }
-    private QAPRobustTabooSeachOperator(QAPRobustTabooSeachOperator original, Cloner cloner)
-      : base(original, cloner) {
-    }
-    public QAPRobustTabooSeachOperator() {
-      Parameters.Add(new LookupParameter<IntValue>("Iterations", "The current iteration."));
-      Parameters.Add(new LookupParameter<IntValue>("TabuTenure", "The current tabu tenure."));
-      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
-      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation solution."));
-      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
-      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
-      Parameters.Add(new LookupParameter<DoubleMatrix>("ShortTermMemory", "The table that stores the iteration at which a certain facility has been assigned to a certain location."));
-      Parameters.Add(new LookupParameter<DoubleMatrix>("LongTermMemory", "Same as the tabu table, but constantly updates the information given the current solution."));
-      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value."));
-      Parameters.Add(new LookupParameter<DoubleValue>("BestQuality", "The best quality value."));
-      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run."));
-      Parameters.Add(new ValueLookupParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure."));
-      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure."));
-      Parameters.Add(new ValueLookupParameter<IntValue>("TabuTenureAdaptionInterval", "The amount of iterations that have to pass before the tabu tenure is adapted."));
-      Parameters.Add(new ValueLookupParameter<BoolValue>("UseAlternativeAspiration", "True if the alternative aspiration condition should be used that takes moves that have not been made for some time above others."));
-      Parameters.Add(new ValueLookupParameter<IntValue>("AlternativeAspirationTenure", "The time t that a move will be remembered for the alternative aspiration condition."));
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new QAPRobustTabooSeachOperator(this, cloner);
-    }
-
-    public override IOperation Apply() {
-      IRandom random = RandomParameter.ActualValue;
-      int iteration = IterationsParameter.ActualValue.Value;
-      if (iteration % TabuTenureAdaptionIntervalParameter.ActualValue.Value == 0)
-        TabuTenureParameter.ActualValue.Value = MinimumTabuTenureParameter.ActualValue.Value
-          + random.Next(MaximumTabuTenureParameter.ActualValue.Value - MinimumTabuTenureParameter.ActualValue.Value + 1);
-
-      DoubleMatrix longTermMemory = LongTermMemoryParameter.ActualValue;
-      DoubleMatrix shortTermMemory = ShortTermMemoryParameter.ActualValue;
-      DoubleMatrix weights = WeightsParameter.ActualValue;
-      DoubleMatrix distances = DistancesParameter.ActualValue;
-
-      DoubleValue quality = QualityParameter.ActualValue;
-      DoubleValue bestQuality = BestQualityParameter.ActualValue;
-      if (bestQuality == null) {
-        BestQualityParameter.ActualValue = (DoubleValue)quality.Clone();
-        bestQuality = BestQualityParameter.ActualValue;
-      }
-
-      int tabuTenure = TabuTenureParameter.ActualValue.Value;
-      int alternativeAspirationTenure = AlternativeAspirationTenureParameter.ActualValue.Value;
-      Permutation solution = PermutationParameter.ActualValue;
-
-      for (int i = 0; i < solution.Length; i++)
-        longTermMemory[i, solution[i]] = iteration;
-
-      double bestMoveQuality = double.MaxValue;
-      Swap2Move bestMove = null;
-
-      foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(solution)) {
-        double moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances);
-        if (UseAlternativeAspirationParameter.ActualValue.Value
-          && longTermMemory[move.Index1, solution[move.Index2]] < iteration - alternativeAspirationTenure
-          && longTermMemory[move.Index2, solution[move.Index1]] < iteration - alternativeAspirationTenure) {
-          bestMove = move;
-          bestMoveQuality = moveQuality;
-          break;
-        }
-        bool isTabu = shortTermMemory[move.Index1, solution[move.Index2]] > 0
-          && shortTermMemory[move.Index2, solution[move.Index1]] > 0
-          && ((iteration - shortTermMemory[move.Index1, solution[move.Index2]]) <= tabuTenure)
-          && ((iteration - shortTermMemory[move.Index2, solution[move.Index1]]) <= tabuTenure);
-        if (!isTabu || quality.Value + moveQuality < bestQuality.Value) {
-          if (moveQuality < bestMoveQuality) {
-            bestMoveQuality = moveQuality;
-            bestMove = move;
-          }
-        }
-      }
-
-      if (bestMove == null) return base.Apply();
-
-      shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = iteration;
-      shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = iteration;
-      Swap2Manipulator.Apply(solution, bestMove.Index1, bestMove.Index2);
-      quality.Value += bestMoveQuality;
-
-      if (quality.Value < bestQuality.Value) bestQuality.Value = quality.Value;
-
-      return base.Apply();
-    }
-  }
-}
Index: branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSeachOperator.cs
===================================================================
--- branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSeachOperator.cs	(revision 6586)
+++ branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSeachOperator.cs	(revision 6586)
@@ -0,0 +1,192 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
+  [Item("RobustTabooSearchOperator", "Performs an iteration of the robust taboo search algorithm as descrbied in Taillard 1991.")]
+  public sealed class RobustTabooSeachOperator : SingleSuccessorOperator, IIterationBasedOperator, IStochasticOperator {
+
+    #region Parameter Properties
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public ILookupParameter<IntMatrix> ShortTermMemoryParameter {
+      get { return (ILookupParameter<IntMatrix>)Parameters["ShortTermMemory"]; }
+    }
+    public ILookupParameter<DoubleMatrix> MoveQualityMatrixParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["MoveQualityMatrix"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ILookupParameter<Swap2Move> LastMoveParameter {
+      get { return (ILookupParameter<Swap2Move>)Parameters["LastMove"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    public IValueLookupParameter<IntValue> MinimumTabuTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MinimumTabuTenure"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumTabuTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
+    }
+    public IValueLookupParameter<BoolValue> UseAlternativeAspirationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["UseAlternativeAspiration"]; }
+    }
+    public IValueLookupParameter<IntValue> AlternativeAspirationTenureParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["AlternativeAspirationTenure"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private RobustTabooSeachOperator(bool deserializing) : base(deserializing) { }
+    private RobustTabooSeachOperator(RobustTabooSeachOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public RobustTabooSeachOperator() {
+      Parameters.Add(new LookupParameter<IntValue>("Iterations", "The current iteration."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation solution."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+      Parameters.Add(new LookupParameter<IntMatrix>("ShortTermMemory", "The table that stores the iteration at which a certain facility has been assigned to a certain location."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("MoveQualityMatrix", "The quality of all swap moves as evaluated on the current permutation."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestQuality", "The best quality value."));
+      Parameters.Add(new LookupParameter<Swap2Move>("LastMove", "The last move that was applied."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "Collection that houses the results of the algorithm."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("UseAlternativeAspiration", "True if the alternative aspiration condition should be used that takes moves that have not been made for some time above others."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("AlternativeAspirationTenure", "The time t that a move will be remembered for the alternative aspiration condition."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RobustTabooSeachOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      IRandom random = RandomParameter.ActualValue;
+      int iteration = IterationsParameter.ActualValue.Value;
+      IntMatrix shortTermMemory = ShortTermMemoryParameter.ActualValue;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      DoubleMatrix moveQualityMatrix = MoveQualityMatrixParameter.ActualValue;
+
+      DoubleValue quality = QualityParameter.ActualValue;
+      DoubleValue bestQuality = BestQualityParameter.ActualValue;
+      if (bestQuality == null) {
+        BestQualityParameter.ActualValue = (DoubleValue)quality.Clone();
+        bestQuality = BestQualityParameter.ActualValue;
+      }
+
+      int minTenure = MinimumTabuTenureParameter.ActualValue.Value;
+      int maxTenure = MaximumTabuTenureParameter.ActualValue.Value;
+      int alternativeAspirationTenure = AlternativeAspirationTenureParameter.ActualValue.Value;
+      bool useAlternativeAspiration = UseAlternativeAspirationParameter.ActualValue.Value;
+      Permutation solution = PermutationParameter.ActualValue;
+      Swap2Move lastMove = LastMoveParameter.ActualValue;
+
+      double bestMoveQuality = double.MaxValue;
+      Swap2Move bestMove = null;
+      bool already_aspired = false;
+
+      foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(solution)) {
+        double moveQuality;
+        if (lastMove == null)
+          moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances);
+        else moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, moveQualityMatrix[move.Index1, move.Index2], weights, distances, lastMove);
+
+        moveQualityMatrix[move.Index1, move.Index2] = moveQuality;
+        moveQualityMatrix[move.Index2, move.Index1] = moveQuality;
+
+        bool autorized = shortTermMemory[move.Index1, solution[move.Index2]] < iteration
+                      || shortTermMemory[move.Index2, solution[move.Index1]] < iteration;
+
+        bool aspired = shortTermMemory[move.Index1, solution[move.Index2]] < iteration - alternativeAspirationTenure
+                    || shortTermMemory[move.Index2, solution[move.Index1]] < iteration - alternativeAspirationTenure
+                    || quality.Value + moveQuality < bestQuality.Value;
+
+        if ((aspired && !already_aspired) // the first alternative move is aspired
+          || (aspired && already_aspired && moveQuality < bestMoveQuality) // an alternative move was already aspired, but this is better
+          || (autorized && !aspired && !already_aspired && moveQuality < bestMoveQuality)) { // a regular better move is found
+          bestMove = move;
+          bestMoveQuality = moveQuality;
+          if (aspired) already_aspired = true;
+        }
+      }
+
+      ResultCollection results = ResultsParameter.ActualValue;
+      if (results != null) {
+        IntValue aspiredMoves = null;
+        if (!results.ContainsKey("AspiredMoves")) {
+          aspiredMoves = new IntValue(already_aspired ? 1 : 0);
+          results.Add(new Result("AspiredMoves", aspiredMoves));
+        } else if (already_aspired) {
+          aspiredMoves = (IntValue)results["AspiredMoves"].Value;
+          aspiredMoves.Value++;
+        }
+      }
+
+      LastMoveParameter.ActualValue = bestMove;
+
+      if (bestMove == null) return base.Apply();
+
+      shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = iteration + random.Next(minTenure, maxTenure);
+      shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = iteration + random.Next(minTenure, maxTenure);
+      Swap2Manipulator.Apply(solution, bestMove.Index1, bestMove.Index2);
+      quality.Value += bestMoveQuality;
+
+      if (quality.Value < bestQuality.Value) bestQuality.Value = quality.Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSearch.cs
===================================================================
--- branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSearch.cs	(revision 6570)
+++ branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment.Algorithms/3.3/RobustTabooSearch.cs	(revision 6586)
@@ -26,5 +26,4 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
-using HeuristicLab.Encodings.PermutationEncoding;
 using HeuristicLab.Operators;
 using HeuristicLab.Optimization;
@@ -35,8 +34,8 @@
 
 namespace HeuristicLab.Problems.QuadraticAssignment.Algorithms {
-  [Item("Robust Taboo Search (QAP)", "The algorithm is described in Taillard, E. 1991. Robust Taboo Search for the Quadratic Assignment Problem. Parallel Computing 17, pp. 443-455.")]
+  [Item("Robust Taboo Search", "The algorithm is described in Taillard, E. 1991. Robust Taboo Search for the Quadratic Assignment Problem. Parallel Computing 17, pp. 443-455.")]
   [Creatable("Algorithms")]
   [StorableClass]
-  public sealed class RobustTabooSearchQAP : HeuristicOptimizationEngineAlgorithm, IStorableContent {
+  public sealed class RobustTabooSearch : HeuristicOptimizationEngineAlgorithm, IStorableContent {
     public string Filename { get; set; }
 
@@ -69,7 +68,4 @@
     private FixedValueParameter<IntValue> MaximumTabuTenureParameter {
       get { return (FixedValueParameter<IntValue>)Parameters["MaximumTabuTenure"]; }
-    }
-    private FixedValueParameter<IntValue> TabuTenureAdaptionIntervalParameter {
-      get { return (FixedValueParameter<IntValue>)Parameters["TabuTenureAdaptionInterval"]; }
     }
     private FixedValueParameter<BoolValue> UseAlternativeAspirationParameter {
@@ -102,8 +98,4 @@
       set { MaximumTabuTenureParameter.Value.Value = value; }
     }
-    public int TabuTenureAdaptionInterval {
-      get { return TabuTenureAdaptionIntervalParameter.Value.Value; }
-      set { TabuTenureAdaptionIntervalParameter.Value.Value = value; }
-    }
     public bool UseAlternativeAspiration {
       get { return UseAlternativeAspirationParameter.Value.Value; }
@@ -119,17 +111,18 @@
     private SolutionsCreator solutionsCreator;
     [Storable]
-    private QAPRobustTabooSeachOperator mainOperator;
+    private RobustTabooSeachOperator mainOperator;
     [Storable]
     private BestAverageWorstQualityAnalyzer qualityAnalyzer;
 
     [StorableConstructor]
-    private RobustTabooSearchQAP(bool deserializing) : base(deserializing) { }
-    private RobustTabooSearchQAP(RobustTabooSearchQAP original, Cloner cloner)
+    private RobustTabooSearch(bool deserializing) : base(deserializing) { }
+    private RobustTabooSearch(RobustTabooSearch original, Cloner cloner)
       : base(original, cloner) {
       solutionsCreator = cloner.Clone(original.solutionsCreator);
       mainOperator = cloner.Clone(original.mainOperator);
       qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
-    }
-    public RobustTabooSearchQAP() {
+      RegisterEventHandlers();
+    }
+    public RobustTabooSearch() {
       Parameters.Add(new FixedValueParameter<MultiAnalyzer>("Analyzer", "The analyzers that are applied after each iteration.", new MultiAnalyzer()));
       Parameters.Add(new FixedValueParameter<IntValue>("Seed", "The seed value of the random number generator.", new IntValue(0)));
@@ -138,7 +131,7 @@
       Parameters.Add(new FixedValueParameter<IntValue>("MinimumTabuTenure", "The minimum tabu tenure.", new IntValue(20)));
       Parameters.Add(new FixedValueParameter<IntValue>("MaximumTabuTenure", "The maximum tabu tenure.", new IntValue(10)));
-      Parameters.Add(new FixedValueParameter<IntValue>("TabuTenureAdaptionInterval", "The amount of iterations that have to pass before the tabu tenure is adapted.", new IntValue(60)));
       Parameters.Add(new FixedValueParameter<BoolValue>("UseAlternativeAspiration", "True if the alternative aspiration condition should be used that takes moves that have not been made for some time above others.", new BoolValue(false)));
       Parameters.Add(new FixedValueParameter<IntValue>("AlternativeAspirationTenure", "The time t that a move will be remembered for the alternative aspiration condition.", new IntValue(10000)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("TerminateOnOptimalSolution", "True when the algorithm should stop if it reached a quality equal or smaller to the BestKnownQuality.", new BoolValue(true)));
 
       qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
@@ -153,47 +146,49 @@
       randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
 
-      OperatorGraph.InitialOperator = randomCreator;
-
       VariableCreator variableCreator = new VariableCreator();
       variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Iterations", new IntValue(0)));
-      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("TabuTenure", new IntValue(0)));
-      randomCreator.Successor = variableCreator;
 
       ResultsCollector resultsCollector = new ResultsCollector();
       resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Iterations", "The actual iteration."));
-      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("TabuTenure", "The actual tabu tenure."));
-      variableCreator.Successor = resultsCollector;
 
       solutionsCreator = new SolutionsCreator();
       solutionsCreator.NumberOfSolutions = new IntValue(1);
-      resultsCollector.Successor = solutionsCreator;
 
       Placeholder analyzer = new Placeholder();
       analyzer.Name = "(Analyzer)";
       analyzer.OperatorParameter.ActualName = AnalyzerParameter.Name;
-      solutionsCreator.Successor = analyzer;
 
       UniformSubScopesProcessor ussp = new UniformSubScopesProcessor();
-      analyzer.Successor = ussp;
-
-      mainOperator = new QAPRobustTabooSeachOperator();
+
+      mainOperator = new RobustTabooSeachOperator();
       mainOperator.AlternativeAspirationTenureParameter.ActualName = AlternativeAspirationTenureParameter.Name;
       mainOperator.BestQualityParameter.ActualName = "BestSoFarQuality";
       mainOperator.IterationsParameter.ActualName = "Iterations";
-      mainOperator.LongTermMemoryParameter.ActualName = "LongTermMemory";
+      mainOperator.LastMoveParameter.ActualName = "LastMove";
       mainOperator.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
       mainOperator.MaximumTabuTenureParameter.ActualName = MaximumTabuTenureParameter.Name;
       mainOperator.MinimumTabuTenureParameter.ActualName = MinimumTabuTenureParameter.Name;
+      mainOperator.MoveQualityMatrixParameter.ActualName = "MoveQualityMatrix";
       mainOperator.RandomParameter.ActualName = "Random";
+      mainOperator.ResultsParameter.ActualName = "Results";
       mainOperator.ShortTermMemoryParameter.ActualName = "ShortTermMemory";
-      mainOperator.TabuTenureAdaptionIntervalParameter.ActualName = TabuTenureAdaptionIntervalParameter.Name;
-      mainOperator.TabuTenureParameter.ActualName = "TabuTenure";
       mainOperator.UseAlternativeAspirationParameter.ActualName = UseAlternativeAspirationParameter.Name;
-      ussp.Operator = mainOperator;
+
+      ConditionalBranch qualityStopBranch = new ConditionalBranch();
+      qualityStopBranch.Name = "Terminate on optimal quality?";
+      qualityStopBranch.ConditionParameter.ActualName = "TerminateOnOptimalSolution";
+
+      Comparator qualityComparator = new Comparator();
+      qualityComparator.Comparison = new Comparison(ComparisonType.Greater);
+      qualityComparator.LeftSideParameter.ActualName = "BestQuality";
+      qualityComparator.RightSideParameter.ActualName = "BestKnownQuality";
+      qualityComparator.ResultParameter.ActualName = "ContinueByQuality";
+
+      ConditionalBranch continueByQualityBranch = new ConditionalBranch();
+      continueByQualityBranch.ConditionParameter.ActualName = "ContinueByQuality";
 
       IntCounter iterationsCounter = new IntCounter();
       iterationsCounter.ValueParameter.ActualName = "Iterations";
       iterationsCounter.Increment = new IntValue(1);
-      ussp.Successor = iterationsCounter;
 
       Comparator comparator = new Comparator();
@@ -203,10 +198,28 @@
       comparator.Comparison = new Comparison(ComparisonType.Less);
       comparator.ResultParameter.ActualName = "ContinueByIteration";
+
+      ConditionalBranch continueByIterationBranch = new ConditionalBranch();
+      continueByIterationBranch.ConditionParameter.ActualName = "ContinueByIteration";
+
+      OperatorGraph.InitialOperator = randomCreator;
+      randomCreator.Successor = variableCreator;
+      variableCreator.Successor = resultsCollector;
+      resultsCollector.Successor = solutionsCreator;
+      solutionsCreator.Successor = analyzer;
+      analyzer.Successor = ussp;
+      ussp.Operator = mainOperator;
+      ussp.Successor = qualityStopBranch;
+      qualityStopBranch.FalseBranch = iterationsCounter;
+      qualityStopBranch.TrueBranch = qualityComparator;
+      qualityStopBranch.Successor = null;
+      qualityComparator.Successor = continueByQualityBranch;
+      continueByQualityBranch.TrueBranch = iterationsCounter;
+      continueByQualityBranch.FalseBranch = null;
+      continueByQualityBranch.Successor = null;
       iterationsCounter.Successor = comparator;
-
-      ConditionalBranch branch = new ConditionalBranch();
-      branch.ConditionParameter.ActualName = "ContinueByIteration";
-      branch.TrueBranch = analyzer;
-      comparator.Successor = branch;
+      comparator.Successor = continueByIterationBranch;
+      continueByIterationBranch.TrueBranch = analyzer;
+      continueByIterationBranch.FalseBranch = null;
+      continueByIterationBranch.Successor = null;
 
       RegisterEventHandlers();
@@ -214,5 +227,5 @@
 
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new RobustTabooSearchQAP(this, cloner);
+      return new RobustTabooSearch(this, cloner);
     }
 
@@ -246,22 +259,53 @@
     }
 
+    private void UseAlternativeAspirationParameter_ValueChanged(object sender, EventArgs e) {
+      UpdateAlternativeAspirationTenure();
+    }
+
+    private void AlternativeAspirationTenureParameter_ValueChanged(object sender, EventArgs e) {
+      if (AlternativeAspirationTenure < MaximumIterations
+        && !UseAlternativeAspiration) {
+        UseAlternativeAspirationParameter.Value.ValueChanged -= new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+        UseAlternativeAspiration = true;
+        UseAlternativeAspirationParameter.Value.ValueChanged += new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+      } else if (AlternativeAspirationTenure >= MaximumIterations
+        && UseAlternativeAspiration) {
+        UseAlternativeAspirationParameter.Value.ValueChanged -= new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+        UseAlternativeAspiration = false;
+        UseAlternativeAspirationParameter.Value.ValueChanged += new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+      }
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
     private void RegisterEventHandlers() {
-      if (Problem != null) {
-        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
-      }
+      UseAlternativeAspirationParameter.Value.ValueChanged += new EventHandler(UseAlternativeAspirationParameter_ValueChanged);
+      AlternativeAspirationTenureParameter.Value.ValueChanged += new EventHandler(AlternativeAspirationTenureParameter_ValueChanged);
+    }
+
+    protected override void RegisterProblemEvents() {
+      base.RegisterProblemEvents();
+      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+    }
+
+    protected override void DeregisterProblemEvents() {
+      Problem.Evaluator.QualityParameter.ActualNameChanged -= new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      base.DeregisterProblemEvents();
     }
 
     public override void Start() {
       if (ExecutionState == ExecutionState.Prepared) {
-        DoubleMatrix shortTermMemory = new DoubleMatrix(Problem.Weights.Rows, Problem.Weights.Rows);
-        DoubleMatrix longTermMemory = new DoubleMatrix(Problem.Weights.Rows, Problem.Weights.Rows);
-        for (int i = 0; i < shortTermMemory.Rows; i++)
-          for (int j = 0; j < shortTermMemory.Rows; j++) {
-            shortTermMemory[i, j] = -1;
-            longTermMemory[i, j] = -1;
+        int dim = Problem.Weights.Rows;
+        IntMatrix shortTermMemory = new IntMatrix(dim, dim);
+        for (int i = 0; i < dim; i++)
+          for (int j = 0; j < dim; j++) {
+            shortTermMemory[i, j] = -(dim * (i + 1) + j + 1);
           }
 
         GlobalScope.Variables.Add(new Variable("ShortTermMemory", shortTermMemory));
-        GlobalScope.Variables.Add(new Variable("LongTermMemory", longTermMemory));
+        GlobalScope.Variables.Add(new Variable("MoveQualityMatrix", new DoubleMatrix(dim, dim)));
       }
       base.Start();
@@ -271,5 +315,13 @@
       MinimumTabuTenure = (int)(0.9 * Problem.Weights.Rows);
       MaximumTabuTenure = (int)(1.1 * Problem.Weights.Rows);
-      TabuTenureAdaptionInterval = 2 * MaximumTabuTenure;
+      UpdateAlternativeAspirationTenure();
+    }
+
+    private void UpdateAlternativeAspirationTenure() {
+      if (UseAlternativeAspiration) {
+        AlternativeAspirationTenure = Problem.Weights.Rows * Problem.Weights.Rows / 2;
+      } else {
+        AlternativeAspirationTenure = int.MaxValue;
+      }
     }
 
@@ -277,7 +329,9 @@
       AnalyzerParameter.Value.Operators.Clear();
       if (Problem != null) {
-        foreach (IAnalyzer analyzer in ((IProblem)Problem).Operators.OfType<IAnalyzer>())
-          if (!(analyzer is AlleleFrequencyAnalyzer<Permutation>) && !(analyzer is PopulationDiversityAnalyzer<Permutation>))
-            AnalyzerParameter.Value.Operators.Add(analyzer);
+        foreach (IAnalyzer analyzer in ((IProblem)Problem).Operators.OfType<IAnalyzer>()) {
+          AnalyzerParameter.Value.Operators.Add(analyzer);
+          if (!(analyzer is BestQAPSolutionAnalyzer))
+            AnalyzerParameter.Value.Operators.SetItemCheckedState(analyzer, false);
+        }
       }
       AnalyzerParameter.Value.Operators.Add(qualityAnalyzer);
Index: branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs
===================================================================
--- branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs	(revision 6570)
+++ branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs	(revision 6586)
@@ -49,4 +49,13 @@
     }
 
+    /// <summary>
+    /// Calculates the quality of the move <paramref name="move"/> by evaluating the changes.
+    /// The runtime complexity of this method is O(N) with N being the size of the permutation.
+    /// </summary>
+    /// <param name="assignment">The current permutation.</param>
+    /// <param name="move">The move that is to be evaluated if it was applied to the current permutation.</param>
+    /// <param name="weights">The weights matrix.</param>
+    /// <param name="distances">The distances matrix.</param>
+    /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
     public static double Apply(Permutation assignment, Swap2Move move, DoubleMatrix weights, DoubleMatrix distances) {
       if (move.Index1 == move.Index2) return 0;
@@ -73,4 +82,42 @@
     }
 
+    /// <summary>
+    /// Is able to compute the move qualities faster O(1) in some cases if it knows the quality of
+    /// performing the move <paramref name="move"/> previously. In other cases it performs a
+    /// standard move quality calculation with runtime complexity O(N).
+    /// </summary>
+    /// <remarks>
+    /// The number of cases that the calculation can be performed faster grows with N^2
+    /// while the number of cases which require a larger recalculation grows linearly with N.
+    /// Larger problem instances thus benefit from this faster method to a larger degree.
+    /// </remarks>
+    /// <param name="assignment">The current permutation.</param>
+    /// <param name="move">The current move that is to be evaluated.</param>
+    /// <param name="previousQuality">The quality of that move as evaluated for the previous permutation.</param>
+    /// <param name="weights">The weigths matrix.</param>
+    /// <param name="distances">The distances matrix.</param>
+    /// <param name="lastMove">The move that was applied to transform the permutation from the previous to the current one.</param>
+    /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
+    public static double Apply(Permutation assignment, Swap2Move move, double previousQuality,
+      DoubleMatrix weights, DoubleMatrix distances, Swap2Move lastMove) {
+      bool overlapsLastMove = move.Index1 == lastMove.Index1
+                           || move.Index2 == lastMove.Index1
+                           || move.Index1 == lastMove.Index2
+                           || move.Index2 == lastMove.Index2;
+
+      if (!overlapsLastMove) {
+        int r = lastMove.Index1, u = move.Index1, s = lastMove.Index2, v = move.Index2;
+        int pR = assignment[lastMove.Index1], pU = assignment[move.Index1], pS = assignment[lastMove.Index2], pV = assignment[move.Index2];
+
+        return previousQuality
+          + (weights[r, u] - weights[r, v] + weights[s, v] - weights[s, u])
+            * (distances[pS, pU] - distances[pS, pV] + distances[pR, pV] - distances[pR, pU])
+          + (weights[u, r] - weights[v, r] + weights[v, s] - weights[u, s])
+            * (distances[pU, pS] - distances[pV, pS] + distances[pV, pR] - distances[pU, pR]);
+      } else {
+        return Apply(assignment, move, weights, distances);
+      }
+    }
+
     public override IOperation Apply() {
       Swap2Move move = Swap2MoveParameter.ActualValue;
Index: branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs
===================================================================
--- branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs	(revision 6570)
+++ branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs	(revision 6586)
@@ -60,27 +60,67 @@
       for (int i = 0; i < ProblemSize - 1; i++) {
         for (int j = i + 1; j < ProblemSize; j++) {
-          symmetricDistances[i, j] = random.Next(ProblemSize);
+          symmetricDistances[i, j] = random.Next(ProblemSize * 100);
           symmetricDistances[j, i] = symmetricDistances[i, j];
-          symmetricWeights[i, j] = random.Next(ProblemSize);
+          symmetricWeights[i, j] = random.Next(ProblemSize * 100);
           symmetricWeights[j, i] = symmetricWeights[i, j];
-          asymmetricDistances[i, j] = random.Next(ProblemSize);
-          asymmetricDistances[j, i] = random.Next(ProblemSize);
-          asymmetricWeights[i, j] = random.Next(ProblemSize);
-          asymmetricWeights[j, i] = random.Next(ProblemSize);
-          nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize);
-          nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize);
-          nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize);
-          nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize);
+          asymmetricDistances[i, j] = random.Next(ProblemSize * 100);
+          asymmetricDistances[j, i] = random.Next(ProblemSize * 100);
+          asymmetricWeights[i, j] = random.Next(ProblemSize * 100);
+          asymmetricWeights[j, i] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize * 100);
+          nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize * 100);
         }
-        nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize);
-        nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize);
+        nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize * 100);
+        nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize * 100);
       }
       int index = random.Next(ProblemSize);
       if (nonZeroDiagonalDistances[index, index] == 0)
-        nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize);
+        nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize * 100);
       index = random.Next(ProblemSize);
       if (nonZeroDiagonalWeights[index, index] == 0)
-        nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize);
+        nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize * 100);
       assignment = new Permutation(PermutationTypes.Absolute, ProblemSize, random);
+    }
+
+    [TestMethod]
+    public void Swap2MoveEvaluatorFastEvaluationTest() {
+
+      for (int i = 0; i < 500; i++) {
+        Swap2Move lastMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
+        Permutation prevAssignment = (Permutation)assignment.Clone();
+        Swap2Manipulator.Apply(assignment, lastMove.Index1, lastMove.Index2);
+        Permutation nextAssignment = (Permutation)assignment.Clone();
+        Swap2Move currentMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
+        Swap2Manipulator.Apply(nextAssignment, currentMove.Index1, currentMove.Index2);
+
+        double moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, symmetricWeights, symmetricDistances);
+        double moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
+                moveBefore, symmetricWeights, symmetricDistances, lastMove);
+        double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances);
+        double after = QAPEvaluator.Apply(nextAssignment, symmetricWeights, symmetricDistances);
+
+        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on symmetric matrices: " + Environment.NewLine
+          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
+
+        moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, asymmetricWeights, asymmetricDistances);
+        moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
+                moveBefore, asymmetricWeights, asymmetricDistances, lastMove);
+        before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances);
+        after = QAPEvaluator.Apply(nextAssignment, asymmetricWeights, asymmetricDistances);
+
+        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on asymmetric matrices: " + Environment.NewLine
+          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
+
+        moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
+        moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
+                moveBefore, nonZeroDiagonalWeights, nonZeroDiagonalDistances, lastMove);
+        before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
+        after = QAPEvaluator.Apply(nextAssignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
+
+        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on non-zero diagonal matrices: " + Environment.NewLine
+          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
+      }
     }
 
