Index: /trunk/sources/HeuristicLab.Algorithms.TabuSearch/3.3/TabuSearch.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.TabuSearch/3.3/TabuSearch.cs	(revision 3103)
+++ /trunk/sources/HeuristicLab.Algorithms.TabuSearch/3.3/TabuSearch.cs	(revision 3104)
@@ -180,6 +180,9 @@
         op.MoveQualityParameter.ActualNameChanged += new EventHandler(MoveEvaluator_MoveQualityParameter_ActualNameChanged);
       }
+      foreach (ITabuMoveEvaluator op in Problem.Operators.OfType<ITabuMoveEvaluator>()) {
+        op.MoveTabuParameter.ActualNameChanged += new EventHandler(TabuMoveEvaluator_MoveTabuParameter_ActualNameChanged);
+      }
       ParameterizeSolutionsCreator();
-      ParameterizeTSMainLoop();
+      ParameterizeMainLoop();
       ParameterizeMoveEvaluator();
       ParameterizeMoveMaker();
@@ -196,5 +199,5 @@
       ParameterizeStochasticOperator(Problem.Evaluator);
       ParameterizeSolutionsCreator();
-      ParameterizeTSMainLoop();
+      ParameterizeMainLoop();
       ParameterizeMoveEvaluator();
       ParameterizeMoveMaker();
@@ -210,9 +213,13 @@
         op.MoveQualityParameter.ActualNameChanged += new EventHandler(MoveEvaluator_MoveQualityParameter_ActualNameChanged);
       }
+      foreach (ITabuMoveEvaluator op in Problem.Operators.OfType<ITabuMoveEvaluator>()) {
+        op.MoveTabuParameter.ActualNameChanged -= new EventHandler(TabuMoveEvaluator_MoveTabuParameter_ActualNameChanged);
+        op.MoveTabuParameter.ActualNameChanged += new EventHandler(TabuMoveEvaluator_MoveTabuParameter_ActualNameChanged);
+      }
       IMoveGenerator oldMoveGenerator = MoveGenerator;
       UpdateMoveGenerator();
       if (oldMoveGenerator == MoveGenerator) // in this case MoveGeneratorParameter_ValueChanged did not fire
         UpdateMoveParameters();
-      ParameterizeTSMainLoop();
+      ParameterizeMainLoop();
       ParameterizeMoveEvaluator();
       ParameterizeMoveMaker();
@@ -220,5 +227,5 @@
     }
     private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
-      ParameterizeTSMainLoop();
+      ParameterizeMainLoop();
       ParameterizeMoveEvaluator();
       ParameterizeMoveMaker();
@@ -228,12 +235,18 @@
     }
     private void MoveEvaluatorParameter_ValueChanged(object sender, EventArgs e) {
-      ParameterizeTSMainLoop();
+      ParameterizeMainLoop();
       ParameterizeMoveEvaluator();
       ParameterizeMoveMaker();
     }
     private void MoveEvaluator_MoveQualityParameter_ActualNameChanged(object sender, EventArgs e) {
-      ParameterizeTSMainLoop();
-      ParameterizeMoveEvaluator();
-      ParameterizeMoveMaker();
+      ParameterizeMainLoop();
+      ParameterizeMoveEvaluator();
+      ParameterizeMoveMaker();
+    }
+    private void TabuMoveEvaluatorParameter_ValueChanged(object sender, EventArgs e) {
+      ParameterizeMainLoop();
+    }
+    private void TabuMoveEvaluator_MoveTabuParameter_ActualNameChanged(object sender, EventArgs e) {
+      ParameterizeMainLoop();
     }
     #endregion
@@ -250,4 +263,5 @@
       MoveGeneratorParameter.ValueChanged += new EventHandler(MoveGeneratorParameter_ValueChanged);
       MoveEvaluatorParameter.ValueChanged += new EventHandler(MoveEvaluatorParameter_ValueChanged);
+      TabuMoveEvaluatorParameter.ValueChanged += new EventHandler(TabuMoveEvaluatorParameter_ValueChanged);
     }
     private void UpdateMoveGenerator() {
@@ -313,9 +327,11 @@
       SolutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
     }
-    private void ParameterizeTSMainLoop() {
+    private void ParameterizeMainLoop() {
       MainLoop.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
       MainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
       if (MoveEvaluator != null)
         MainLoop.MoveQualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
+      if (TabuMoveEvaluator != null)
+        MainLoop.MoveTabuParameter.ActualName = TabuMoveEvaluator.MoveTabuParameter.ActualName;
     }
     private void ParameterizeStochasticOperator(IOperator op) {
Index: /trunk/sources/HeuristicLab.Algorithms.TabuSearch/3.3/TabuSearchMainLoop.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.TabuSearch/3.3/TabuSearchMainLoop.cs	(revision 3103)
+++ /trunk/sources/HeuristicLab.Algorithms.TabuSearch/3.3/TabuSearchMainLoop.cs	(revision 3104)
@@ -48,4 +48,7 @@
       get { return (LookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
     }
+    public LookupParameter<BoolValue> MoveTabuParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
     public ValueLookupParameter<IntValue> MaximumIterationsParameter {
       get { return (ValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
@@ -88,4 +91,5 @@
       Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
       Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The value which represents the quality of a move."));
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The value that indicates if a move is tabu or not."));
       Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum number of generations which should be processed."));
       Parameters.Add(new ValueLookupParameter<IntValue>("TabuTenure", "The length of the tabu list, and also means the number of iterations a move is kept tabu"));
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj	(revision 3103)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj	(revision 3104)
@@ -111,4 +111,5 @@
     <Compile Include="Moves\ThreeOpt\ThreeOptMove.cs" />
     <Compile Include="Moves\ThreeOpt\ThreeOptMoveGenerator.cs" />
+    <Compile Include="Moves\TwoOpt\PreventReaddTwoOptTabuMoveEvaluator.cs" />
     <Compile Include="Moves\TwoOpt\StochasticTwoOptSingleMoveGenerator.cs" />
     <Compile Include="Moves\TwoOpt\ExhaustiveTwoOptMoveGenerator.cs">
@@ -127,5 +128,5 @@
     </Compile>
     <Compile Include="Moves\TwoOpt\TwoOptTabuMoveAttribute.cs" />
-    <Compile Include="Moves\TwoOpt\TwoOptTabuMoveEvaluator.cs" />
+    <Compile Include="Moves\TwoOpt\PreventReaddDeleteTwoOptTabuMoveEvaluator.cs" />
     <Compile Include="Moves\TwoOpt\TwoOptTabuMoveMaker.cs" />
     <Compile Include="PermutationManipulator.cs" />
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddDeleteTwoOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddDeleteTwoOptTabuMoveEvaluator.cs	(revision 3104)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddDeleteTwoOptTabuMoveEvaluator.cs	(revision 3104)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("PreventReaddDeleteTwoOptTabuMoveEvaluator", "Prevents readding of previously deleted edges as well as deleting previously added edges.")]
+  [StorableClass]
+  public class PreventReaddDeleteTwoOptTabuMoveEvaluator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public ILookupParameter<TwoOptMove> TwoOptMoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["TwoOptMove"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (LookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
+    private ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    public PreventReaddDeleteTwoOptTabuMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<TwoOptMove>("TwoOptMove", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope."));
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      TwoOptMove move = TwoOptMoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      int length = permutation.Length;
+      int E1S = permutation.GetCircular(move.Index1 - 1);
+      int E1T = permutation[move.Index1];
+      int E2S = permutation[move.Index2];
+      int E2T = permutation.GetCircular(move.Index2 + 1);
+      bool isTabu = false;
+      foreach (IItem tabuMove in tabuList) {
+        TwoOptTabuMoveAttribute attribute = (tabuMove as TwoOptTabuMoveAttribute);
+        if (attribute != null) {
+          // if previously deleted Edge1Source-Target is readded
+          if (attribute.Edge1Source == E1S && attribute.Edge1Target == E2S || attribute.Edge1Source == E2S && attribute.Edge1Target == E1S
+            || attribute.Edge1Source == E1T && attribute.Edge1Target == E2T || attribute.Edge1Source == E2T && attribute.Edge1Target == E1T
+            // if previously deleted Edge2Source-Target is readded
+            || attribute.Edge2Source == E1T && attribute.Edge2Target == E2T || attribute.Edge2Source == E2T && attribute.Edge2Target == E1T
+            || attribute.Edge2Source == E1S && attribute.Edge2Target == E2S || attribute.Edge2Source == E2S && attribute.Edge2Target == E1S
+            // if previously added Edge1Source-Edge2Source is deleted
+            || attribute.Edge1Source == E1S && attribute.Edge2Source == E1T || attribute.Edge1Source == E1T && attribute.Edge2Source == E1S
+            || attribute.Edge1Source == E2S && attribute.Edge2Source == E2T || attribute.Edge1Source == E2T && attribute.Edge2Source == E2S
+            // if previously added Edge1Target-Edge2Target is deleted
+            || attribute.Edge1Target == E2S && attribute.Edge2Target == E2T || attribute.Edge1Target == E2T && attribute.Edge2Target == E2S
+            || attribute.Edge1Target == E1S && attribute.Edge2Target == E1T || attribute.Edge1Target == E1T && attribute.Edge2Target == E1S) {
+            isTabu = true;
+            break;
+          }
+        }
+      }
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+
+    public override bool CanChangeName {
+      get { return false; }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddTwoOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddTwoOptTabuMoveEvaluator.cs	(revision 3104)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddTwoOptTabuMoveEvaluator.cs	(revision 3104)
@@ -0,0 +1,91 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("PreventReaddTwoOptTabuMoveEvaluator", "Prevents readding of previously deleted edges, but allows deleting previously added edges.")]
+  [StorableClass]
+  public class PreventReaddTwoOptTabuMoveEvaluator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public ILookupParameter<TwoOptMove> TwoOptMoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["TwoOptMove"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (LookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
+    private ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    public PreventReaddTwoOptTabuMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<TwoOptMove>("TwoOptMove", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope."));
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      TwoOptMove move = TwoOptMoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      int length = permutation.Length;
+      int E1S = permutation.GetCircular(move.Index1 - 1);
+      int E1T = permutation[move.Index1];
+      int E2S = permutation[move.Index2];
+      int E2T = permutation.GetCircular(move.Index2 + 1);
+      bool isTabu = false;
+      foreach (IItem tabuMove in tabuList) {
+        TwoOptTabuMoveAttribute attribute = (tabuMove as TwoOptTabuMoveAttribute);
+        if (attribute != null) {
+          // if previously deleted Edge1Source-Target is readded
+          if (attribute.Edge1Source == E1S && attribute.Edge1Target == E2S || attribute.Edge1Source == E2S && attribute.Edge1Target == E1S
+            || attribute.Edge1Source == E1T && attribute.Edge1Target == E2T || attribute.Edge1Source == E2T && attribute.Edge1Target == E1T
+            // if previously deleted Edge2Source-Target is readded
+            || attribute.Edge2Source == E1T && attribute.Edge2Target == E2T || attribute.Edge2Source == E2T && attribute.Edge2Target == E1T
+            || attribute.Edge2Source == E1S && attribute.Edge2Target == E2S || attribute.Edge2Source == E2S && attribute.Edge2Target == E1S) {
+            isTabu = true;
+            break;
+          }
+        }
+      }
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+
+    public override bool CanChangeName {
+      get { return false; }
+    }
+  }
+}
Index: unk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptTabuMoveEvaluator.cs	(revision 3103)
+++ 	(revision )
@@ -1,93 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2010 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.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Operators;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("TwoOptTabuMoveEvaluator", "Evaluates whether a given 2-opt move is tabu.")]
-  [StorableClass]
-  public class TwoOptTabuMoveEvaluator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveEvaluator {
-    public ILookupParameter<TwoOptMove> TwoOptMoveParameter {
-      get { return (LookupParameter<TwoOptMove>)Parameters["TwoOptMove"]; }
-    }
-    public ILookupParameter<Permutation> PermutationParameter {
-      get { return (LookupParameter<Permutation>)Parameters["Permutation"]; }
-    }
-    public LookupParameter<ItemList<IItem>> TabuListParameter {
-      get { return (LookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
-    }
-    public LookupParameter<BoolValue> MoveTabuParameter {
-      get { return (LookupParameter<BoolValue>)Parameters["MoveTabu"]; }
-    }
-    private ScopeParameter CurrentScopeParameter {
-      get { return (ScopeParameter)Parameters["CurrentScope"]; }
-    }
-
-    public TwoOptTabuMoveEvaluator()
-      : base() {
-      Parameters.Add(new LookupParameter<TwoOptMove>("TwoOptMove", "The move to evaluate."));
-      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu."));
-      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
-      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
-      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope."));
-    }
-
-    public override IOperation Apply() {
-      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
-      TwoOptMove move = TwoOptMoveParameter.ActualValue;
-      Permutation permutation = PermutationParameter.ActualValue;
-      int length = permutation.Length;
-      int E1S = permutation.GetCircular(move.Index1 - 1);
-      int E1T = permutation[move.Index1];
-      int E2S = permutation[move.Index2];
-      int E2T = permutation.GetCircular(move.Index2 + 1);
-      bool isTabu = false;
-      foreach (IItem tabuMove in tabuList) {
-        TwoOptTabuMoveAttribute attribute = (tabuMove as TwoOptTabuMoveAttribute);
-        if (attribute != null) {
-          // if previously deleted Edge1Source-Target is readded
-          if (attribute.Edge1Source == E1S && attribute.Edge1Target == E2S || attribute.Edge1Source == E2S && attribute.Edge1Target == E1S
-            // if previously deleted Edge2Source-Target is readded
-            || attribute.Edge2Source == E1T && attribute.Edge2Target == E2T || attribute.Edge2Source == E2T && attribute.Edge2Target == E1T
-            // if previously added Edge1Source-Edge2Source is deleted
-            || attribute.Edge1Source == E1S && attribute.Edge2Source == E1T || attribute.Edge1Source == E1T && attribute.Edge2Source == E1S
-            // if previously added Edge1Target-Edge2Target is deleted
-            || attribute.Edge1Target == E2S && attribute.Edge2Target == E2T || attribute.Edge1Target == E2T && attribute.Edge2Target == E2S) {
-            isTabu = true;
-            break;
-          }
-        }
-      }
-      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
-      return base.Apply();
-    }
-
-    public override bool CanChangeName {
-      get { return false; }
-    }
-  }
-}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptTabuMoveMaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptTabuMoveMaker.cs	(revision 3103)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptTabuMoveMaker.cs	(revision 3104)
@@ -31,5 +31,5 @@
   [Item("TwoOptTabuMoveMaker", "Declares a given 2-opt move as tabu, by adding its attributes to the tabu list. It also removes the oldest entry in the tabu list when its size is greater than tenure.")]
   [StorableClass]
-  public class TwoOptTabuMoveMaker : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveMaker {
+  public class TwoOptTabuMoveMaker : TabuMoveMaker, ITwoOptPermutationMoveOperator {
     public ILookupParameter<Permutation> PermutationParameter {
       get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
@@ -38,36 +38,18 @@
       get { return (LookupParameter<TwoOptMove>)Parameters["TwoOptMove"]; }
     }
-    public LookupParameter<ItemList<IItem>> TabuListParameter {
-      get { return (LookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
-    }
-    public ValueLookupParameter<IntValue> TabuTenureParameter {
-      get { return (ValueLookupParameter<IntValue>)Parameters["TabuTenure"]; }
-    }
 
     public TwoOptTabuMoveMaker()
       : base() {
       Parameters.Add(new LookupParameter<TwoOptMove>("TwoOptMove", "The move that was made."));
-      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list where move attributes are stored."));
-      Parameters.Add(new ValueLookupParameter<IntValue>("TabuTenure", "The tenure of the tabu list."));
       Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
     }
 
-    public override IOperation Apply() {
-      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+    protected override IItem GetTabuAttribute() {
       TwoOptMove move = TwoOptMoveParameter.ActualValue;
-      IntValue tabuTenure = TabuTenureParameter.ActualValue;
       Permutation permutation = PermutationParameter.ActualValue;
-      
-      if (tabuList.Count >= tabuTenure.Value) {
-        for (int i = 0; i < tabuTenure.Value - 1; i++)
-          tabuList[i] = tabuList[i + 1];
-        tabuList.RemoveAt(tabuList.Count - 1);
-      }
-
-      TwoOptTabuMoveAttribute attribute = new TwoOptTabuMoveAttribute(
-        permutation.GetCircular(move.Index1 - 1), permutation[move.Index1],
-        permutation[move.Index2], permutation.GetCircular(move.Index2 + 1));
-      tabuList.Add(attribute);
-      return base.Apply();
+      return new TwoOptTabuMoveAttribute( permutation.GetCircular(move.Index1 - 1),
+        permutation[move.Index1],
+        permutation[move.Index2],
+        permutation.GetCircular(move.Index2 + 1));
     }
 
Index: /trunk/sources/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 3103)
+++ /trunk/sources/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 3104)
@@ -112,4 +112,5 @@
     <Compile Include="Interfaces\ITabuMoveEvaluator.cs" />
     <Compile Include="Interfaces\ITabuMoveMaker.cs" />
+    <Compile Include="TabuMoveMaker.cs" />
     <Compile Include="UserDefinedAlgorithm.cs" />
     <Compile Include="EngineAlgorithm.cs" />
Index: /trunk/sources/HeuristicLab.Optimization/3.3/Interfaces/ITabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization/3.3/Interfaces/ITabuMoveEvaluator.cs	(revision 3103)
+++ /trunk/sources/HeuristicLab.Optimization/3.3/Interfaces/ITabuMoveEvaluator.cs	(revision 3104)
@@ -21,7 +21,9 @@
 
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 
 namespace HeuristicLab.Optimization {
   public interface ITabuMoveEvaluator : IOperator {
+    ILookupParameter<BoolValue> MoveTabuParameter { get; }
   }
 }
Index: /trunk/sources/HeuristicLab.Optimization/3.3/TabuMoveMaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization/3.3/TabuMoveMaker.cs	(revision 3104)
+++ /trunk/sources/HeuristicLab.Optimization/3.3/TabuMoveMaker.cs	(revision 3104)
@@ -0,0 +1,61 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  public abstract class TabuMoveMaker : SingleSuccessorOperator, ITabuMoveMaker {
+    public LookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (LookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ValueLookupParameter<IntValue> TabuTenureParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["TabuTenure"]; }
+    }
+
+    protected TabuMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list where move attributes are stored."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("TabuTenure", "The tenure of the tabu list."));
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      int tabuTenure = TabuTenureParameter.ActualValue.Value;
+
+      int overlength = tabuList.Count - tabuTenure;
+      if (overlength >= 0) {
+        for (int i = 0; i < tabuTenure - 1; i++)
+          tabuList[i] = tabuList[i + overlength + 1];
+        while (tabuList.Count >= tabuTenure)
+          tabuList.RemoveAt(tabuList.Count - 1);
+      }
+
+      tabuList.Add(GetTabuAttribute());
+      return base.Apply();
+    }
+
+    protected abstract IItem GetTabuAttribute();
+  }
+}
