Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveInversionMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveInversionMoveGenerator.cs	(revision 3232)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveInversionMoveGenerator.cs	(revision 3233)
@@ -34,11 +34,19 @@
       InversionMove[] moves = new InversionMove[totalMoves];
       int count = 0;
-      for (int i = 0; i < length - 1; i++)
-        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;*/
-          moves[count++] = new InversionMove(i, j);
+
+      if (permutation.PermutationType == PermutationTypes.RelativeUndirected) {
+        for (int i = 0; i < length - 1; i++) {
+          for (int j = i + 1; j < length; j++) {
+            // doesn't make sense to inverse the whole permutation or the whole but one in case of relative undirected permutations
+            if (j - i >= length - 2) continue;
+            moves[count++] = new InversionMove(i, j);
+          }
         }
+      } else {
+          for (int i = 0; i < length - 1; i++)
+            for (int j = i + 1; j < length; j++) {
+              moves[count++] = new InversionMove(i, j);
+            }
+      }
       return moves;
     }
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveAbsoluteAttribute.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveAbsoluteAttribute.cs	(revision 3233)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveAbsoluteAttribute.cs	(revision 3233)
@@ -0,0 +1,63 @@
+﻿#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("InversionMoveAbsoluteAttribute", "Specifies the tabu attributes for an inversion move (2-opt) on an absolute position permutation.")]
+  [StorableClass]
+  public class InversionMoveAbsoluteAttribute : Item {
+    [Storable]
+    public int Index1 { get; private set; }
+    [Storable]
+    public int Number1 { get; private set; }
+    [Storable]
+    public int Index2 { get; private set; }
+    [Storable]
+    public int Number2 { get; private set; }
+
+    [StorableConstructor]
+    private InversionMoveAbsoluteAttribute(bool deserializing)
+      : base() {
+    }
+
+    public InversionMoveAbsoluteAttribute()
+      : this(-1, -1, -1, -1) { }
+
+    public InversionMoveAbsoluteAttribute(int index1, int number1, int index2, int number2)
+      : base() {
+      Index1 = index1;
+      Number1 = number1;
+      Index2 = index2;
+      Number2 = number2;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      InversionMoveAbsoluteAttribute clone = (InversionMoveAbsoluteAttribute)base.Clone(cloner);
+      clone.Index1 = Index1;
+      clone.Number1 = Number1;
+      clone.Index2 = Index2;
+      clone.Number2 = Number2;
+      return clone;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveAttribute.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveAttribute.cs	(revision 3232)
+++ 	(revision )
@@ -1,63 +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 HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("InversionMoveAttribute", "Specifies the tabu attributes for an inversion move (2-opt).")]
-  [StorableClass]
-  public class InversionMoveAttribute : 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; }
-
-    [StorableConstructor]
-    private InversionMoveAttribute(bool deserializing)
-      : base() {
-    }
-
-    public InversionMoveAttribute()
-      : this(-1, -1, -1, -1) { }
-
-    public InversionMoveAttribute(int edge1Source, int edge1Target, int edge2Source, int edge2Target)
-      : base() {
-      Edge1Source = edge1Source;
-      Edge1Target = edge1Target;
-      Edge2Source = edge2Source;
-      Edge2Target = edge2Target;
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      InversionMoveAttribute clone = (InversionMoveAttribute)base.Clone(cloner);
-      clone.Edge1Source = Edge1Source;
-      clone.Edge1Target = Edge1Target;
-      clone.Edge2Source = Edge2Source;
-      clone.Edge2Target = Edge2Target;
-      return clone;
-    }
-  }
-}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveRelativeAttribute.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveRelativeAttribute.cs	(revision 3233)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveRelativeAttribute.cs	(revision 3233)
@@ -0,0 +1,63 @@
+﻿#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("InversionMoveRelativeAttribute", "Specifies the tabu attributes for an inversion move (2-opt) on a relative position permutation.")]
+  [StorableClass]
+  public class InversionMoveRelativeAttribute : 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; }
+
+    [StorableConstructor]
+    private InversionMoveRelativeAttribute(bool deserializing)
+      : base() {
+    }
+
+    public InversionMoveRelativeAttribute()
+      : this(-1, -1, -1, -1) { }
+
+    public InversionMoveRelativeAttribute(int edge1Source, int edge1Target, int edge2Source, int edge2Target)
+      : base() {
+      Edge1Source = edge1Source;
+      Edge1Target = edge1Target;
+      Edge2Source = edge2Source;
+      Edge2Target = edge2Target;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      InversionMoveRelativeAttribute clone = (InversionMoveRelativeAttribute)base.Clone(cloner);
+      clone.Edge1Source = Edge1Source;
+      clone.Edge1Target = Edge1Target;
+      clone.Edge2Source = Edge2Source;
+      clone.Edge2Target = Edge2Target;
+      return clone;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveTabuMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveTabuMaker.cs	(revision 3232)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveTabuMaker.cs	(revision 3233)
@@ -51,8 +51,11 @@
       InversionMove move = InversionMoveParameter.ActualValue;
       Permutation permutation = PermutationParameter.ActualValue;
-      return new InversionMoveAttribute( permutation.GetCircular(move.Index1 - 1),
-        permutation[move.Index1],
-        permutation[move.Index2],
-        permutation.GetCircular(move.Index2 + 1));
+      if (permutation.PermutationType == PermutationTypes.Absolute)
+        return new InversionMoveAbsoluteAttribute(move.Index1, permutation[move.Index1], move.Index2, permutation[move.Index2]);
+      else
+        return new InversionMoveRelativeAttribute(permutation.GetCircular(move.Index1 - 1),
+          permutation[move.Index1],
+          permutation[move.Index2],
+          permutation.GetCircular(move.Index2 + 1));
     }
   }
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddAndRemovalInversionMoveTabuChecker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddAndRemovalInversionMoveTabuChecker.cs	(revision 3232)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddAndRemovalInversionMoveTabuChecker.cs	(revision 3233)
@@ -65,30 +65,73 @@
       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) {
-          InversionMoveAttribute attribute = (tabuMove as InversionMoveAttribute);
-          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 = false;
+      foreach (IItem tabuMove in tabuList) {
+        switch (permutation.PermutationType) {
+          case PermutationTypes.RelativeUndirected: {
+            int E1S = permutation.GetCircular(move.Index1 - 1);
+            int E1T = permutation[move.Index1];
+            int E2S = permutation[move.Index2];
+            int E2T = permutation.GetCircular(move.Index2 + 1);
+            InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);
+            if (relAttrib != null) {
+              // if previously deleted Edge1Source-Target is readded
+              if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S || relAttrib.Edge1Source == E2S && relAttrib.Edge1Target == E1S
+                || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge1Target == E1T
+                // if previously deleted Edge2Source-Target is readded
+                || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T || relAttrib.Edge2Source == E2T && relAttrib.Edge2Target == E1T
+                || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S || relAttrib.Edge2Source == E2S && relAttrib.Edge2Target == E1S
+                // if previously added Edge1Source-Edge2Source is deleted
+                || relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T || relAttrib.Edge1Source == E1T && relAttrib.Edge2Source == E1S
+                || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge2Source == E2S
+                // if previously added Edge1Target-Edge2Target is deleted
+                || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T || relAttrib.Edge1Target == E2T && relAttrib.Edge2Target == E2S
+                || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T || relAttrib.Edge1Target == E1T && relAttrib.Edge2Target == E1S) {
+                isTabu = true;
+              }
             }
           }
+          break;
+          case PermutationTypes.RelativeDirected: {
+            int E1S = permutation.GetCircular(move.Index1 - 1);
+            int E1T = permutation[move.Index1];
+            int E2S = permutation[move.Index2];
+            int E2T = permutation.GetCircular(move.Index2 + 1);
+            InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);
+            if (relAttrib != null) {
+              if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S
+                || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T
+                // if previously deleted Edge2Source-Target is readded
+                || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T
+                || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S
+                // if previously added Edge1Source-Edge2Source is deleted
+                || relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T
+                || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T
+                // if previously added Edge1Target-Edge2Target is deleted
+                || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T
+                || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T) {
+                isTabu = true;
+              }
+            }
+          }
+          break;
+          case PermutationTypes.Absolute: {
+            int i1 = move.Index1;
+            int n1 = permutation[move.Index1];
+            int i2 = move.Index2;
+            int n2 = permutation[move.Index2];
+            InversionMoveAbsoluteAttribute absAttrib = (tabuMove as InversionMoveAbsoluteAttribute);
+            if (absAttrib != null) {
+              if (absAttrib.Number1 == n1 || absAttrib.Number1 == n2
+                || absAttrib.Number2 == n2 || absAttrib.Number2 == n1)
+                isTabu = true;
+              
+            }
+          }
+          break;
+          default: {
+            throw new InvalidOperationException(Name + ": Unknown permutation type.");
+          }
         }
+        if (isTabu) break;
       }
       MoveTabuParameter.ActualValue = new BoolValue(isTabu);
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddInversionMoveTabuChecker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddInversionMoveTabuChecker.cs	(revision 3232)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventReaddInversionMoveTabuChecker.cs	(revision 3233)
@@ -65,24 +65,61 @@
       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) {
-          InversionMoveAttribute attribute = (tabuMove as InversionMoveAttribute);
-          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 = false;
+      foreach (IItem tabuMove in tabuList) {
+        switch (permutation.PermutationType) {
+          case PermutationTypes.RelativeUndirected: {
+              int E1S = permutation.GetCircular(move.Index1 - 1);
+              int E1T = permutation[move.Index1];
+              int E2S = permutation[move.Index2];
+              int E2T = permutation.GetCircular(move.Index2 + 1);
+              InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);
+              if (relAttrib != null) {
+                // if previously deleted Edge1Source-Target is readded
+                if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S || relAttrib.Edge1Source == E2S && relAttrib.Edge1Target == E1S
+                  || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge1Target == E1T
+                  // if previously deleted Edge2Source-Target is readded
+                  || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T || relAttrib.Edge2Source == E2T && relAttrib.Edge2Target == E1T
+                  || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S || relAttrib.Edge2Source == E2S && relAttrib.Edge2Target == E1S) {
+                  isTabu = true;
+                }
+              }
             }
-          }
+            break;
+          case PermutationTypes.RelativeDirected: {
+              int E1S = permutation.GetCircular(move.Index1 - 1);
+              int E1T = permutation[move.Index1];
+              int E2S = permutation[move.Index2];
+              int E2T = permutation.GetCircular(move.Index2 + 1);
+              InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);
+              if (relAttrib != null) {
+                if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S
+                  || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T
+                  // if previously deleted Edge2Source-Target is readded
+                  || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T
+                  || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S) {
+                  isTabu = true;
+                }
+              }
+            }
+            break;
+          case PermutationTypes.Absolute: {
+              int i1 = move.Index1;
+              int n1 = permutation[move.Index1];
+              int i2 = move.Index2;
+              int n2 = permutation[move.Index2];
+              InversionMoveAbsoluteAttribute absAttrib = (tabuMove as InversionMoveAbsoluteAttribute);
+              if (absAttrib != null) {
+                if ((absAttrib.Index1 == i1 || absAttrib.Index1 == i2) && (absAttrib.Number1 == n1 || absAttrib.Number1 == n2)
+                  || (absAttrib.Index2 == i2 || absAttrib.Index2 == i1) && (absAttrib.Number2 == n2 || absAttrib.Number2 == n1))
+                  isTabu = true;
+
+              }
+            }
+            break;
+          default: {
+              throw new InvalidOperationException(Name + ": Unknown permutation type.");
+            }
         }
+        if (isTabu) break;
       }
       MoveTabuParameter.ActualValue = new BoolValue(isTabu);
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventRemovalInversionMoveTabuChecker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventRemovalInversionMoveTabuChecker.cs	(revision 3232)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/PreventRemovalInversionMoveTabuChecker.cs	(revision 3233)
@@ -65,24 +65,60 @@
       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) {
-          InversionMoveAttribute attribute = (tabuMove as InversionMoveAttribute);
-          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;
+      bool isTabu = false;
+      foreach (IItem tabuMove in tabuList) {
+        switch (permutation.PermutationType) {
+          case PermutationTypes.RelativeUndirected: {
+              int E1S = permutation.GetCircular(move.Index1 - 1);
+              int E1T = permutation[move.Index1];
+              int E2S = permutation[move.Index2];
+              int E2T = permutation.GetCircular(move.Index2 + 1);
+              InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);
+              if (relAttrib != null) {
+                if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T || relAttrib.Edge1Source == E1T && relAttrib.Edge2Source == E1S
+                  || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge2Source == E2S
+                  // if previously added Edge1Target-Edge2Target is deleted
+                  || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T || relAttrib.Edge1Target == E2T && relAttrib.Edge2Target == E2S
+                  || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T || relAttrib.Edge1Target == E1T && relAttrib.Edge2Target == E1S) {
+                  isTabu = true;
+                }
+              }
             }
-          }
+            break;
+          case PermutationTypes.RelativeDirected: {
+              int E1S = permutation.GetCircular(move.Index1 - 1);
+              int E1T = permutation[move.Index1];
+              int E2S = permutation[move.Index2];
+              int E2T = permutation.GetCircular(move.Index2 + 1);
+              InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);
+              if (relAttrib != null) {
+                if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T
+                  || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T
+                  // if previously added Edge1Target-Edge2Target is deleted
+                  || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T
+                  || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T) {
+                  isTabu = true;
+                }
+              }
+            }
+            break;
+          case PermutationTypes.Absolute: {
+              int i1 = move.Index1;
+              int n1 = permutation[move.Index1];
+              int i2 = move.Index2;
+              int n2 = permutation[move.Index2];
+              InversionMoveAbsoluteAttribute absAttrib = (tabuMove as InversionMoveAbsoluteAttribute);
+              if (absAttrib != null) {
+                if (absAttrib.Number1 == n1 || absAttrib.Number1 == n2
+                  || absAttrib.Number2 == n2 || absAttrib.Number2 == n1)
+                  isTabu = true;
+
+              }
+            }
+            break;
+          default: {
+              throw new InvalidOperationException(Name + ": Unknown permutation type.");
+            }
         }
+        if (isTabu) break;
       }
       MoveTabuParameter.ActualValue = new BoolValue(isTabu);
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticInversionSingleMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticInversionSingleMoveGenerator.cs	(revision 3232)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/StochasticInversionSingleMoveGenerator.cs	(revision 3233)
@@ -44,5 +44,9 @@
       int index1 = random.Next(length - 1);
       int index2 = random.Next(index1 + 1, length);
-      return new InversionMove(index1, index2);;
+      if (permutation.PermutationType == PermutationTypes.RelativeUndirected) {
+        while (index2 - index1 >= length - 2)
+          index2 = random.Next(index1 + 1, length);
+      }
+      return new InversionMove(index1, index2);
     }
 
