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 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj	(revision 3221)
@@ -108,10 +108,26 @@
     <Compile Include="Manipulators\TranslocationManipulator.cs" />
     <Compile Include="Moves\ThreeIndexMove.cs" />
-    <Compile Include="Moves\ThreeOpt\StochasticThreeOptMultiMoveGenerator.cs" />
+    <Compile Include="Moves\ThreeOpt\PreventDeleteThreeOptTabuMoveEvaluator.cs" />
+    <Compile Include="Moves\ThreeOpt\PreventReaddThreeOptTabuMoveEvaluator.cs" />
+    <Compile Include="Moves\ThreeOpt\PreventReaddDeleteThreeOptTabuMoveEvaluator.cs" />
+    <Compile Include="Moves\ThreeOpt\StochasticThreeOptSingleMoveGenerator.cs" />
+    <Compile Include="Moves\ThreeOpt\Insertion\ExhaustiveInsertionMoveGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\ThreeOpt\StochasticThreeOptMultiMoveGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Moves\ThreeOpt\ThreeOptMove.cs">
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Moves\ThreeOpt\ThreeOptMoveGenerator.cs" />
-    <Compile Include="Moves\ThreeOpt\ThreeOptMoveMaker.cs" />
+    <Compile Include="Moves\ThreeOpt\ThreeOptMoveGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\ThreeOpt\ThreeOptMoveMaker.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\ThreeOpt\ThreeOptTabuMoveAttribute.cs" />
+    <Compile Include="Moves\ThreeOpt\ThreeOptTabuMoveMaker.cs" />
+    <Compile Include="Moves\TwoOpt\PreventDeleteTwoOptTabuMoveEvaluator.cs" />
     <Compile Include="Moves\TwoOpt\PreventReaddTwoOptTabuMoveEvaluator.cs" />
     <Compile Include="Moves\TwoOpt\StochasticTwoOptSingleMoveGenerator.cs" />
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/Insertion/ExhaustiveInsertionMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/Insertion/ExhaustiveInsertionMoveGenerator.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/Insertion/ExhaustiveInsertionMoveGenerator.cs	(revision 3221)
@@ -0,0 +1,50 @@
+﻿#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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Collections.Generic;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("ExhaustiveInsertionMoveGenerator", "Generates all possible insertion moves from a given permutation. Insertion is a 3-opt move.")]
+  [StorableClass]
+  public class ExhaustiveInsertionMoveGenerator : ThreeOptMoveGenerator, IExhaustiveMoveGenerator {
+    public static ThreeOptMove[] Apply(Permutation permutation) {
+      int length = permutation.Length;
+      ThreeOptMove[] moves = new ThreeOptMove[length * (length - 1)];
+      int count = 0;
+      for (int i = 0; i < length; i++) {
+        for (int j = 1; j <= length - 1; j++) {
+          moves[count++] = new ThreeOptMove(i, i, (i + j) % length);
+        }
+      }
+      return moves;
+    }
+
+    protected override ThreeOptMove[] GenerateMoves(Permutation permutation) {
+      return Apply(permutation);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventDeleteThreeOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventDeleteThreeOptTabuMoveEvaluator.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventDeleteThreeOptTabuMoveEvaluator.cs	(revision 3221)
@@ -0,0 +1,109 @@
+﻿#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("ThreeOptPreventEdgeRemoval", "Prevents deleting of previously added edges.")]
+  [StorableClass]
+  public class PreventDeleteThreeOptTabuMoveEvaluator : SingleSuccessorOperator, IThreeOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<ThreeOptMove> ThreeOptMoveParameter {
+      get { return (LookupParameter<ThreeOptMove>)Parameters["ThreeOptMove"]; }
+    }
+    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 PreventDeleteThreeOptTabuMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<ThreeOptMove>("ThreeOptMove", "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;
+      ThreeOptMove move = ThreeOptMoveParameter.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);
+      int E3S, E3T;
+      if (move.Index3 > move.Index1) {
+        E3S = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1);
+        E3T = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1);
+      } else {
+        E3S = permutation.GetCircular(move.Index3 - 1);
+        E3T = permutation[move.Index3];
+      }
+      bool isTabu = (move.Index1 == move.Index3
+        || move.Index2 - move.Index1 >= permutation.Length - 2
+        || move.Index1 == permutation.Length - 1 && move.Index3 == 0
+        || move.Index3 == permutation.Length - 1 && move.Index1 == 0);
+      if (!isTabu) {
+        foreach (IItem tabuMove in tabuList) {
+          ThreeOptTabuMoveAttribute attribute = (tabuMove as ThreeOptTabuMoveAttribute);
+          if (attribute != null) {
+            // if previously added Edge3Source-Edge1Target is deleted
+            if (attribute.Edge3Source == E1S && attribute.Edge1Target == E1T || attribute.Edge3Source == E1T && attribute.Edge1Target == E1S
+              || attribute.Edge3Source == E2S && attribute.Edge1Target == E2T || attribute.Edge3Source == E2T && attribute.Edge1Target == E2S
+              || attribute.Edge3Source == E3S && attribute.Edge1Target == E3T || attribute.Edge3Source == E3T && attribute.Edge1Target == E3S
+              // if previously added Edge2Source-Edge3Target is deleted
+              || attribute.Edge2Source == E1S && attribute.Edge3Target == E1T || attribute.Edge2Source == E1T && attribute.Edge3Target == E1S
+              || attribute.Edge2Source == E2S && attribute.Edge3Target == E2T || attribute.Edge2Source == E2T && attribute.Edge3Target == E2S
+              || attribute.Edge2Source == E3S && attribute.Edge3Target == E3T || attribute.Edge2Source == E3T && attribute.Edge3Target == E3S
+              // if previously added Edge1Source-Edge2Target is deleted
+              || attribute.Edge1Source == E1S && attribute.Edge2Target == E1T || attribute.Edge1Source == E1T && attribute.Edge2Target == E1S
+              || attribute.Edge1Source == E2S && attribute.Edge2Target == E2T || attribute.Edge1Source == E2T && attribute.Edge2Target == E2S
+              || attribute.Edge1Source == E3S && attribute.Edge2Target == E3T || attribute.Edge1Source == E3T && attribute.Edge2Target == E3S) {
+              isTabu = true;
+              break;
+            }
+          }
+        }
+      }
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventReaddDeleteThreeOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventReaddDeleteThreeOptTabuMoveEvaluator.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventReaddDeleteThreeOptTabuMoveEvaluator.cs	(revision 3221)
@@ -0,0 +1,121 @@
+﻿#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("ThreeOptPreventEdgeRemovalAndReadding", "Prevents readding of previously deleted edges as well as deleting previously added edges.")]
+  [StorableClass]
+  public class PreventReaddDeleteThreeOptTabuMoveEvaluator : SingleSuccessorOperator, IThreeOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<ThreeOptMove> ThreeOptMoveParameter {
+      get { return (LookupParameter<ThreeOptMove>)Parameters["ThreeOptMove"]; }
+    }
+    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 PreventReaddDeleteThreeOptTabuMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<ThreeOptMove>("ThreeOptMove", "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;
+      ThreeOptMove move = ThreeOptMoveParameter.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);
+      int E3S, E3T;
+      if (move.Index3 > move.Index1) {
+        E3S = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1);
+        E3T = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1);
+      } else {
+        E3S = permutation.GetCircular(move.Index3 - 1);
+        E3T = permutation[move.Index3];
+      }
+      bool isTabu = (move.Index1 == move.Index3
+        || move.Index2 - move.Index1 >= permutation.Length - 2
+        || move.Index1 == permutation.Length - 1 && move.Index3 == 0
+        || move.Index3 == permutation.Length - 1 && move.Index1 == 0);
+      if (!isTabu) {
+        foreach (IItem tabuMove in tabuList) {
+          ThreeOptTabuMoveAttribute attribute = (tabuMove as ThreeOptTabuMoveAttribute);
+          if (attribute != null) {
+            // if previously deleted Edge1Source-Target is readded
+            if (attribute.Edge1Source == E3S && attribute.Edge1Target == E1T || attribute.Edge1Source == E1T && attribute.Edge1Target == E3S
+              || attribute.Edge1Source == E2S && attribute.Edge1Target == E3T || attribute.Edge1Source == E3T && attribute.Edge1Target == E2S
+              || attribute.Edge1Source == E1S && attribute.Edge1Target == E2T || attribute.Edge1Source == E2T && attribute.Edge1Target == E1S
+              // if previously deleted Edge2Source-Target is readded
+              || attribute.Edge2Source == E3S && attribute.Edge2Target == E1T || attribute.Edge2Source == E1T && attribute.Edge2Target == E3S
+              || attribute.Edge2Source == E2S && attribute.Edge2Target == E3T || attribute.Edge2Source == E3T && attribute.Edge2Target == E2S
+              || attribute.Edge2Source == E1S && attribute.Edge2Target == E2T || attribute.Edge2Source == E2T && attribute.Edge2Target == E1S
+              // if previously deleted Edge3Source-Target is readded
+              || attribute.Edge3Source == E3S && attribute.Edge3Target == E1T || attribute.Edge3Source == E1T && attribute.Edge3Target == E3S
+              || attribute.Edge3Source == E2S && attribute.Edge3Target == E3T || attribute.Edge3Source == E3T && attribute.Edge3Target == E2S
+              || attribute.Edge3Source == E1S && attribute.Edge3Target == E2T || attribute.Edge3Source == E2T && attribute.Edge3Target == E1S
+              // if previously added Edge3Source-Edge1Target is deleted
+              || attribute.Edge3Source == E1S && attribute.Edge1Target == E1T || attribute.Edge3Source == E1T && attribute.Edge1Target == E1S
+              || attribute.Edge3Source == E2S && attribute.Edge1Target == E2T || attribute.Edge3Source == E2T && attribute.Edge1Target == E2S
+              || attribute.Edge3Source == E3S && attribute.Edge1Target == E3T || attribute.Edge3Source == E3T && attribute.Edge1Target == E3S
+              // if previously added Edge2Source-Edge3Target is deleted
+              || attribute.Edge2Source == E1S && attribute.Edge3Target == E1T || attribute.Edge2Source == E1T && attribute.Edge3Target == E1S
+              || attribute.Edge2Source == E2S && attribute.Edge3Target == E2T || attribute.Edge2Source == E2T && attribute.Edge3Target == E2S
+              || attribute.Edge2Source == E3S && attribute.Edge3Target == E3T || attribute.Edge2Source == E3T && attribute.Edge3Target == E3S
+              // if previously added Edge1Source-Edge2Target is deleted
+              || attribute.Edge1Source == E1S && attribute.Edge2Target == E1T || attribute.Edge1Source == E1T && attribute.Edge2Target == E1S
+              || attribute.Edge1Source == E2S && attribute.Edge2Target == E2T || attribute.Edge1Source == E2T && attribute.Edge2Target == E2S
+              || attribute.Edge1Source == E3S && attribute.Edge2Target == E3T || attribute.Edge1Source == E3T && attribute.Edge2Target == E3S) {
+              isTabu = true;
+              break;
+            }
+          }
+        }
+      }
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventReaddThreeOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventReaddThreeOptTabuMoveEvaluator.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/PreventReaddThreeOptTabuMoveEvaluator.cs	(revision 3221)
@@ -0,0 +1,109 @@
+﻿#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("ThreeOptPreventEdgeReadding", "Prevents readding of previously deleted edges.")]
+  [StorableClass]
+  public class PreventReaddThreeOptTabuMoveEvaluator : SingleSuccessorOperator, IThreeOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<ThreeOptMove> ThreeOptMoveParameter {
+      get { return (LookupParameter<ThreeOptMove>)Parameters["ThreeOptMove"]; }
+    }
+    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 PreventReaddThreeOptTabuMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<ThreeOptMove>("ThreeOptMove", "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;
+      ThreeOptMove move = ThreeOptMoveParameter.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);
+      int E3S, E3T;
+      if (move.Index3 > move.Index1) {
+        E3S = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1);
+        E3T = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1);
+      } else {
+        E3S = permutation.GetCircular(move.Index3 - 1);
+        E3T = permutation[move.Index3];
+      }
+      bool isTabu = (move.Index1 == move.Index3
+        || move.Index2 - move.Index1 >= permutation.Length - 2
+        || move.Index1 == permutation.Length - 1 && move.Index3 == 0
+        || move.Index3 == permutation.Length - 1 && move.Index1 == 0);
+      if (!isTabu) {
+        foreach (IItem tabuMove in tabuList) {
+          ThreeOptTabuMoveAttribute attribute = (tabuMove as ThreeOptTabuMoveAttribute);
+          if (attribute != null) {
+            // if previously deleted Edge1Source-Target is readded
+            if (attribute.Edge1Source == E3S && attribute.Edge1Target == E1T || attribute.Edge1Source == E1T && attribute.Edge1Target == E3S
+              || attribute.Edge1Source == E2S && attribute.Edge1Target == E3T || attribute.Edge1Source == E3T && attribute.Edge1Target == E2S
+              || attribute.Edge1Source == E1S && attribute.Edge1Target == E2T || attribute.Edge1Source == E2T && attribute.Edge1Target == E1S
+              // if previously deleted Edge2Source-Target is readded
+              || attribute.Edge2Source == E3S && attribute.Edge2Target == E1T || attribute.Edge2Source == E1T && attribute.Edge2Target == E3S
+              || attribute.Edge2Source == E2S && attribute.Edge2Target == E3T || attribute.Edge2Source == E3T && attribute.Edge2Target == E2S
+              || attribute.Edge2Source == E1S && attribute.Edge2Target == E2T || attribute.Edge2Source == E2T && attribute.Edge2Target == E1S
+              // if previously deleted Edge3Source-Target is readded
+              || attribute.Edge3Source == E3S && attribute.Edge3Target == E1T || attribute.Edge3Source == E1T && attribute.Edge3Target == E3S
+              || attribute.Edge3Source == E2S && attribute.Edge3Target == E3T || attribute.Edge3Source == E3T && attribute.Edge3Target == E2S
+              || attribute.Edge3Source == E1S && attribute.Edge3Target == E2T || attribute.Edge3Source == E2T && attribute.Edge3Target == E1S) {
+              isTabu = true;
+              break;
+            }
+          }
+        }
+      }
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptMultiMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptMultiMoveGenerator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptMultiMoveGenerator.cs	(revision 3221)
@@ -53,14 +53,5 @@
       ThreeOptMove[] moves = new ThreeOptMove[sampleSize];
       for (int i = 0; i < sampleSize; i++) {
-        int index1, index2, index3;
-        index1 = random.Next(length - 1);
-        do {
-          index2 = random.Next(index1, length);
-        } while (index2 - index1 >= length - 2);
-        do {
-          index3 = random.Next(length - index2 + index1 - 1);
-        } while (index3 == index1);
-        
-        moves[i] = new ThreeOptMove(index1, index2, index3);
+        moves[i] = StochasticThreeOptSingleMoveGenerator.Apply(permutation, random);
       }
       return moves;
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptSingleMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptSingleMoveGenerator.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptSingleMoveGenerator.cs	(revision 3221)
@@ -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 System;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("StochasticThreeOptSingleMoveGenerator", "Randomly samples one from all possible 3-opt moves from a given permutation.")]
+  [StorableClass]
+  public class StochasticThreeOptSingleMoveGenerator : ThreeOptMoveGenerator, IStochasticOperator, ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public StochasticThreeOptSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public static ThreeOptMove Apply(Permutation permutation, IRandom random) {
+      int length = permutation.Length;
+      int index1, index2, index3;
+      index1 = random.Next(length - 1);
+      do {
+        index2 = random.Next(index1, length);
+      } while (index2 - index1 >= length - 2);
+      do {
+        index3 = random.Next(length - index2 + index1);
+      } while (index3 == index1);
+      
+      return new ThreeOptMove(index1, index2, index3);
+    }
+
+    protected override ThreeOptMove[] GenerateMoves(Permutation permutation) {
+      IRandom random = RandomParameter.ActualValue;
+      return new ThreeOptMove[] { Apply(permutation, random) };
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveGenerator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveGenerator.cs	(revision 3221)
@@ -31,9 +31,12 @@
   [StorableClass]
   public abstract class ThreeOptMoveGenerator : SingleSuccessorOperator, IThreeOptPermutationMoveOperator, IMoveGenerator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<Permutation> PermutationParameter {
       get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
     }
     public ILookupParameter<ThreeOptMove> ThreeOptMoveParameter {
-      get { return (LookupParameter<ThreeOptMove>)Parameters["Move"]; }
+      get { return (LookupParameter<ThreeOptMove>)Parameters["ThreeOptMove"]; }
     }
     protected ScopeParameter CurrentScopeParameter {
@@ -44,5 +47,5 @@
       : base() {
       Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation for which moves should be generated."));
-      Parameters.Add(new LookupParameter<ThreeOptMove>("Move", "The moves that should be generated in subscopes."));
+      Parameters.Add(new LookupParameter<ThreeOptMove>("ThreeOptMove", "The moves that should be generated in subscopes."));
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
     }
@@ -61,8 +64,4 @@
 
     protected abstract ThreeOptMove[] GenerateMoves(Permutation permutation);
-
-    public override bool CanChangeName {
-      get { return false; }
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveMaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveMaker.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveMaker.cs	(revision 3221)
@@ -32,4 +32,7 @@
   [StorableClass]
   public class ThreeOptMoveMaker : SingleSuccessorOperator, IThreeOptPermutationMoveOperator, IMoveMaker {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<DoubleValue> QualityParameter {
       get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
@@ -64,8 +67,4 @@
       return base.Apply();
     }
-
-    public override bool CanChangeName {
-      get { return false; }
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptTabuMoveAttribute.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptTabuMoveAttribute.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptTabuMoveAttribute.cs	(revision 3221)
@@ -0,0 +1,71 @@
+﻿#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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("ThreeOptTabuMoveAttribute", "Specifies the tabu attributes for a 3-opt move.")]
+  [StorableClass]
+  public class ThreeOptTabuMoveAttribute : Item {
+    [Storable]
+    public int Edge1Source { get; private set; }
+    [Storable]
+    public int Edge1Target { get; private set; }
+    [Storable]
+    public int Edge2Source { get; private set; }
+    [Storable]
+    public int Edge2Target { get; private set; }
+    [Storable]
+    public int Edge3Source { get; private set; }
+    [Storable]
+    public int Edge3Target { get; private set; }
+
+    [StorableConstructor]
+    private ThreeOptTabuMoveAttribute(bool deserializing)
+      : base() {
+    }
+
+    public ThreeOptTabuMoveAttribute()
+      : this(-1, -1, -1, -1, -1, -1) { }
+
+    public ThreeOptTabuMoveAttribute(int edge1Source, int edge1Target, int edge2Source, int edge2Target, int edge3Source, int edge3Target)
+      : base() {
+      Edge1Source = edge1Source;
+      Edge1Target = edge1Target;
+      Edge2Source = edge2Source;
+      Edge2Target = edge2Target;
+      Edge3Source = edge3Source;
+      Edge3Target = edge3Target;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      ThreeOptTabuMoveAttribute clone = (ThreeOptTabuMoveAttribute)base.Clone(cloner);
+      clone.Edge1Source = Edge1Source;
+      clone.Edge1Target = Edge1Target;
+      clone.Edge2Source = Edge2Source;
+      clone.Edge2Target = Edge2Target;
+      clone.Edge3Source = Edge3Source;
+      clone.Edge3Target = Edge3Target;
+      return clone;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptTabuMoveMaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptTabuMoveMaker.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptTabuMoveMaker.cs	(revision 3221)
@@ -0,0 +1,69 @@
+﻿#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("ThreeOptTabuMoveMaker", "Declares a given 3-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 ThreeOptTabuMoveMaker : TabuMoveMaker, IThreeOptPermutationMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<ThreeOptMove> ThreeOptMoveParameter {
+      get { return (LookupParameter<ThreeOptMove>)Parameters["ThreeOptMove"]; }
+    }
+
+    public ThreeOptTabuMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<ThreeOptMove>("ThreeOptMove", "The move that was made."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+    }
+
+    protected override IItem GetTabuAttribute() {
+      ThreeOptMove move = ThreeOptMoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      if (move.Index3 > move.Index1)
+        return new ThreeOptTabuMoveAttribute(permutation.GetCircular(move.Index1 - 1),
+        permutation[move.Index1],
+        permutation[move.Index2],
+        permutation.GetCircular(move.Index2 + 1),
+        permutation.GetCircular(move.Index3 + move.Index2 - move.Index1),
+        permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1));
+      else
+        return new ThreeOptTabuMoveAttribute(permutation.GetCircular(move.Index1 - 1),
+        permutation[move.Index1],
+        permutation[move.Index2],
+        permutation.GetCircular(move.Index2 + 1),
+        permutation.GetCircular(move.Index3 - 1),
+        permutation.GetCircular(move.Index3));
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveTwoOptMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveTwoOptMoveGenerator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveTwoOptMoveGenerator.cs	(revision 3221)
@@ -26,10 +26,10 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("ExhaustiveTwoOptMoveGenerator", "Generates all possible 2-opt moves from a given permutation.")]
+  [Item("ExhaustiveTwoOptMoveGenerator", "Generates all possible 2-opt moves (inversion) from a given permutation.")]
   [StorableClass]
   public class ExhaustiveTwoOptMoveGenerator : TwoOptMoveGenerator, IExhaustiveMoveGenerator {
     public static TwoOptMove[] Apply(Permutation permutation) {
       int length = permutation.Length;
-      int totalMoves = (length) * (length - 1) / 2 - 3;
+      int totalMoves = (length) * (length - 1) / 2; // - 3;
       TwoOptMove[] moves = new TwoOptMove[totalMoves];
       int count = 0;
@@ -37,6 +37,6 @@
         for (int j = i + 1; j < length; j++) {
           // doesn't make sense to inverse the whole permutation or the whole but one
-          if (i == 0 && j >= length - 2) continue;
-          else if (i == 1 && j >= length - 1) continue;
+          /*if (i == 0 && j >= length - 2) continue;
+          else if (i == 1 && j >= length - 1) continue;*/
           moves[count++] = new TwoOptMove(i, j);
         }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventDeleteTwoOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventDeleteTwoOptTabuMoveEvaluator.cs	(revision 3221)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventDeleteTwoOptTabuMoveEvaluator.cs	(revision 3221)
@@ -0,0 +1,92 @@
+﻿#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("TwoOptPreventEdgeRemoval", "Prevents deleting of previously added edges.")]
+  [StorableClass]
+  public class PreventDeleteTwoOptTabuMoveEvaluator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    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 PreventDeleteTwoOptTabuMoveEvaluator()
+      : 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 = (move.Index2 - move.Index1 >= length - 2); // doesn't change the solution
+      if (!isTabu) {
+        foreach (IItem tabuMove in tabuList) {
+          TwoOptTabuMoveAttribute attribute = (tabuMove as TwoOptTabuMoveAttribute);
+          if (attribute != null) {
+            // if previously added Edge1Source-Edge2Source is deleted
+            if (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();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddDeleteTwoOptTabuMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddDeleteTwoOptTabuMoveEvaluator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddDeleteTwoOptTabuMoveEvaluator.cs	(revision 3221)
@@ -29,7 +29,10 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("PreventReaddDeleteTwoOptTabuMoveEvaluator", "Prevents readding of previously deleted edges as well as deleting previously added edges.")]
+  [Item("TwoOptPreventEdgeRemovalAndReadding", "Prevents readding of previously deleted edges as well as deleting previously added edges.")]
   [StorableClass]
   public class PreventReaddDeleteTwoOptTabuMoveEvaluator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<TwoOptMove> TwoOptMoveParameter {
       get { return (LookupParameter<TwoOptMove>)Parameters["TwoOptMove"]; }
@@ -66,22 +69,24 @@
       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;
+      bool isTabu = (move.Index2 - move.Index1 >= length - 2); // doesn't change the solution;
+      if (!isTabu) {
+        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;
+            }
           }
         }
@@ -90,8 +95,4 @@
       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 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddTwoOptTabuMoveEvaluator.cs	(revision 3221)
@@ -29,7 +29,10 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("PreventReaddTwoOptTabuMoveEvaluator", "Prevents readding of previously deleted edges, but allows deleting previously added edges.")]
+  [Item("TwoOptPreventEdgeReadding", "Prevents readding of previously deleted edges, but allows deleting previously added edges.")]
   [StorableClass]
   public class PreventReaddTwoOptTabuMoveEvaluator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, ITabuMoveEvaluator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<TwoOptMove> TwoOptMoveParameter {
       get { return (LookupParameter<TwoOptMove>)Parameters["TwoOptMove"]; }
@@ -66,16 +69,18 @@
       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;
+      bool isTabu = (move.Index2 - move.Index1 >= length - 2); // doesn't change the solution;
+      if (!isTabu) {
+        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;
+            }
           }
         }
@@ -84,8 +89,4 @@
       return base.Apply();
     }
-
-    public override bool CanChangeName {
-      get { return false; }
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticTwoOptMultiMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticTwoOptMultiMoveGenerator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticTwoOptMultiMoveGenerator.cs	(revision 3221)
@@ -28,7 +28,10 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("StochasticTwoOptMultiMoveGenerator", "Randomly samples n from all possible 2-opt moves from a given permutation.")]
+  [Item("StochasticTwoOptMultiMoveGenerator", "Randomly samples n from all possible 2-opt moves (inversion) from a given permutation.")]
   [StorableClass]
-  public class StochasticTwoOptMultiMoveGenerator : StochasticTwoOptSingleMoveGenerator, IMultiMoveGenerator {
+  public class StochasticTwoOptMultiMoveGenerator : TwoOptMoveGenerator, IMultiMoveGenerator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
     public IValueLookupParameter<IntValue> SampleSizeParameter {
       get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
@@ -42,4 +45,5 @@
     public StochasticTwoOptMultiMoveGenerator()
       : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
       Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
     }
@@ -49,5 +53,5 @@
       TwoOptMove[] moves = new TwoOptMove[sampleSize];
       for (int i = 0; i < sampleSize; i++) {
-        moves[i] = Apply(permutation, random);
+        moves[i] = StochasticTwoOptSingleMoveGenerator.Apply(permutation, random);
       }
       return moves;
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticTwoOptSingleMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticTwoOptSingleMoveGenerator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticTwoOptSingleMoveGenerator.cs	(revision 3221)
@@ -28,5 +28,5 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("StochasticTwoOptSingleMoveGenerator", "Randomly samples a single from all possible 2-opt moves from a given permutation.")]
+  [Item("StochasticTwoOptSingleMoveGenerator", "Randomly samples a single from all possible 2-opt moves (inversion) from a given permutation.")]
   [StorableClass]
   public class StochasticTwoOptSingleMoveGenerator : TwoOptMoveGenerator, IStochasticOperator, ISingleMoveGenerator {
@@ -42,8 +42,6 @@
     public static TwoOptMove Apply(Permutation permutation, IRandom random) {
       int length = permutation.Length;
-      int index1 = random.Next(length - 1), index2;
-      if (index1 >= 2)
-        index2 = random.Next(index1 + 1, length);
-      else index2 = random.Next(index1 + 1, length - (2 - index1));
+      int index1 = random.Next(length - 1);
+      int index2 = random.Next(index1 + 1, length);
       return new TwoOptMove(index1, index2);;
     }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptMoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptMoveGenerator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptMoveGenerator.cs	(revision 3221)
@@ -31,4 +31,7 @@
   [StorableClass]
   public abstract class TwoOptMoveGenerator : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, IMoveGenerator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<Permutation> PermutationParameter {
       get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
@@ -61,8 +64,4 @@
 
     protected abstract TwoOptMove[] GenerateMoves(Permutation permutation);
-
-    public override bool CanChangeName {
-      get { return false; }
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptMoveMaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptMoveMaker.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptMoveMaker.cs	(revision 3221)
@@ -32,4 +32,7 @@
   [StorableClass]
   public class TwoOptMoveMaker : SingleSuccessorOperator, ITwoOptPermutationMoveOperator, IMoveMaker {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<DoubleValue> QualityParameter {
       get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
@@ -64,8 +67,4 @@
       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 3220)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/TwoOptTabuMoveMaker.cs	(revision 3221)
@@ -32,4 +32,7 @@
   [StorableClass]
   public class TwoOptTabuMoveMaker : TabuMoveMaker, ITwoOptPermutationMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
     public ILookupParameter<Permutation> PermutationParameter {
       get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
@@ -53,8 +56,4 @@
         permutation.GetCircular(move.Index2 + 1));
     }
-
-    public override bool CanChangeName {
-      get { return false; }
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/HeuristicLabEncodingsSymbolicExpressionTreePlugin.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/HeuristicLabEncodingsSymbolicExpressionTreePlugin.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/HeuristicLabEncodingsSymbolicExpressionTreePlugin.cs	(revision 3221)
@@ -26,5 +26,5 @@
 
 namespace HeuristicLab.Encodings.SymbolicExpressionTree {
-  [Plugin("HeuristicLab.Encodings.SymbolicExpressionTree", "3.3.0.3218")]
+  [Plugin("HeuristicLab.Encodings.SymbolicExpressionTree", "3.3.0.3219")]
   [PluginFile("HeuristicLab.Encodings.SymbolicExpressionTree-3.3.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.Core", "3.3.0.0")]
Index: /trunk/sources/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs	(revision 3221)
@@ -35,5 +35,5 @@
 
 namespace HeuristicLab.Problems.TestFunctions {
-  [Item("SingleObjective TestFunction", "Test function with real valued inputs and a single objective.")]
+  [Item("Single Objective Test Function", "Test function with real valued inputs and a single objective.")]
   [StorableClass]
   [Creatable("Problems")]
Index: /trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/MoveEvaluators/ThreeOpt/TSPThreeOptPathMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/MoveEvaluators/ThreeOpt/TSPThreeOptPathMoveEvaluator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/MoveEvaluators/ThreeOpt/TSPThreeOptPathMoveEvaluator.cs	(revision 3221)
@@ -58,4 +58,8 @@
         edge3target = permutation[move.Index3];
       }
+      if (move.Index1 == move.Index3
+        || move.Index2 - move.Index1 >= permutation.Length - 2
+        || move.Index1 == permutation.Length - 1 && move.Index3 == 0
+        || move.Index1 == 0 && move.Index3 == permutation.Length - 1) return 0;
       double moveQuality = 0;
       // remove three edges
@@ -91,5 +95,7 @@
       }
       if (move.Index1 == move.Index3
-        || move.Index2 - move.Index1 >= permutation.Length - 2) return 0;
+        || move.Index2 - move.Index1 >= permutation.Length - 2
+        || move.Index1 == permutation.Length - 1 && move.Index3 == 0
+        || move.Index1 == 0 && move.Index3 == permutation.Length - 1) return 0;
       double moveQuality = 0;
       // remove three edges
Index: /trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/MoveEvaluators/TwoOpt/TSPTwoOptPathMoveEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/MoveEvaluators/TwoOpt/TSPTwoOptPathMoveEvaluator.cs	(revision 3220)
+++ /trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/MoveEvaluators/TwoOpt/TSPTwoOptPathMoveEvaluator.cs	(revision 3221)
@@ -45,9 +45,10 @@
 
     protected override double EvaluateByCoordinates(Permutation permutation, DoubleMatrix coordinates) {
-      TwoOptMove m = TwoOptMoveParameter.ActualValue;
-      int edge1source = permutation.GetCircular(m.Index1 - 1);
-      int edge1target = permutation[m.Index1];
-      int edge2source = permutation[m.Index2];
-      int edge2target = permutation.GetCircular(m.Index2 + 1);
+      TwoOptMove move = TwoOptMoveParameter.ActualValue;
+      int edge1source = permutation.GetCircular(move.Index1 - 1);
+      int edge1target = permutation[move.Index1];
+      int edge2source = permutation[move.Index2];
+      int edge2target = permutation.GetCircular(move.Index2 + 1);
+      if (move.Index2 - move.Index1 >= permutation.Length - 2) return 0;
       double moveQuality = 0;
       // remove two edges
@@ -65,9 +66,10 @@
 
     protected override double EvaluateByDistanceMatrix(Permutation permutation, DoubleMatrix distanceMatrix) {
-      TwoOptMove m = TwoOptMoveParameter.ActualValue;
-      int edge1source = permutation.GetCircular(m.Index1 - 1);
-      int edge1target = permutation[m.Index1];
-      int edge2source = permutation[m.Index2];
-      int edge2target = permutation.GetCircular(m.Index2 + 1);
+      TwoOptMove move = TwoOptMoveParameter.ActualValue;
+      int edge1source = permutation.GetCircular(move.Index1 - 1);
+      int edge1target = permutation[move.Index1];
+      int edge2source = permutation[move.Index2];
+      int edge2target = permutation.GetCircular(move.Index2 + 1);
+      if (move.Index2 - move.Index1 >= permutation.Length - 2) return 0;
       double moveQuality = 0;
       // remove two edges
