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 5809)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj	(revision 5933)
@@ -118,4 +118,5 @@
     <Compile Include="Crossovers\PositionBasedCrossover.cs" />
     <Compile Include="HeuristicLabEncodingsPermutationEncodingPlugin.cs" />
+    <Compile Include="Interfaces\IPermutationSwap2MoveOperator.cs" />
     <Compile Include="Interfaces\IPermutationCreator.cs" />
     <Compile Include="Interfaces\IPermutationCrossover.cs" />
@@ -133,5 +134,18 @@
     <Compile Include="Manipulators\TranslocationInversionManipulator.cs" />
     <Compile Include="Manipulators\TranslocationManipulator.cs" />
+    <Compile Include="Moves\Edge.cs" />
     <Compile Include="Moves\PermutationMoveAttribute.cs" />
+    <Compile Include="Moves\StandardEdgeEqualityComparer.cs" />
+    <Compile Include="Moves\Swap2\ExhaustiveSwap2MoveGenerator.cs" />
+    <Compile Include="Moves\Swap2\StochasticSwap2MultiMoveGenerator.cs" />
+    <Compile Include="Moves\Swap2\StochasticSwap2SingleMoveGenerator.cs" />
+    <Compile Include="Moves\Swap2\Swap2Move.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveAbsoluteAttribute.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveGenerator.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveHardTabuCriterion.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveMaker.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveRelativeAttribute.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveSoftTabuCriterion.cs" />
+    <Compile Include="Moves\Swap2\Swap2MoveTabuMaker.cs" />
     <Compile Include="Moves\ThreeIndexMove.cs" />
     <Compile Include="Moves\ThreeOpt\StochasticSingleInsertionMoveGenerator.cs" />
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Interfaces/IPermutationSwap2MoveOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Interfaces/IPermutationSwap2MoveOperator.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Interfaces/IPermutationSwap2MoveOperator.cs	(revision 5933)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  public interface IPermutationSwap2MoveOperator : IPermutationMoveOperator {
+    ILookupParameter<Swap2Move> Swap2MoveParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Manipulators/Swap2Manipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Manipulators/Swap2Manipulator.cs	(revision 5809)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Manipulators/Swap2Manipulator.cs	(revision 5933)
@@ -49,10 +49,14 @@
     /// <param name="permutation">The permutation to manipulate.</param>
     public static void Apply(IRandom random, Permutation permutation) {
-      int index1, index2, temp;
+      int index1, index2;
 
       index1 = random.Next(permutation.Length);
       index2 = random.Next(permutation.Length);
 
-      temp = permutation[index1];
+      Apply(permutation, index1, index2);
+    }
+
+    public static void Apply(Permutation permutation, int index1, int index2) {
+      int temp = permutation[index1];
       permutation[index1] = permutation[index2];
       permutation[index2] = temp;
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Edge.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Edge.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Edge.cs	(revision 5933)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Edge", "An edge between two integer nodes and a flag for the direction.")]
+  [StorableClass]
+  public class Edge : Item {
+    [Storable]
+    public int Source { get; private set; }
+    [Storable]
+    public int Target { get; private set; }
+    [Storable]
+    public bool Bidirectional { get; private set; }
+
+    [StorableConstructor]
+    protected Edge(bool deserializing) : base(deserializing) { }
+    protected Edge(Edge original, Cloner cloner)
+      : base(original, cloner) {
+      Source = original.Source;
+      Target = original.Target;
+      Bidirectional = original.Bidirectional;
+    }
+    public Edge(int source, int target, bool bidirectional)
+      : base() {
+      Source = source;
+      Target = target;
+      Bidirectional = bidirectional;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Edge(this, cloner);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/StandardEdgeEqualityComparer.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/StandardEdgeEqualityComparer.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/StandardEdgeEqualityComparer.cs	(revision 5933)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  public class StandardEdgeEqualityComparer : EqualityComparer<Edge> {
+    public override bool Equals(Edge x, Edge y) {
+      bool inDirection = x.Source == y.Source && x.Target == y.Target;
+      if (!x.Bidirectional && !y.Bidirectional) return inDirection;
+      else return inDirection || x.Source == y.Target && x.Target == y.Source;
+    }
+
+    public override int GetHashCode(Edge edge) {
+      return (int)((long)edge.Source.GetHashCode() + (long)edge.Target.GetHashCode());
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/ExhaustiveSwap2MoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/ExhaustiveSwap2MoveGenerator.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/ExhaustiveSwap2MoveGenerator.cs	(revision 5933)
@@ -0,0 +1,59 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("ExhaustiveSwap2MoveGenerator", "Generates all possible swap-2 moves from a given permutation.")]
+  [StorableClass]
+  public class ExhaustiveSwap2MoveGenerator : Swap2MoveGenerator, IExhaustiveMoveGenerator {
+    [StorableConstructor]
+    protected ExhaustiveSwap2MoveGenerator(bool deserializing) : base(deserializing) { }
+    protected ExhaustiveSwap2MoveGenerator(ExhaustiveSwap2MoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public ExhaustiveSwap2MoveGenerator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExhaustiveSwap2MoveGenerator(this, cloner);
+    }
+
+    public static Swap2Move[] Apply(Permutation permutation) {
+      int length = permutation.Length;
+      if (length == 1) throw new ArgumentException("ExhaustiveSwap2MoveGenerator: There cannot be an Swap move given a permutation of length 1.", "permutation");
+      int totalMoves = (length) * (length - 1) / 2;
+      Swap2Move[] moves = new Swap2Move[totalMoves];
+      int count = 0;
+
+      for (int i = 0; i < length - 1; i++)
+        for (int j = i + 1; j < length; j++) {
+          moves[count++] = new Swap2Move(i, j);
+        }
+      return moves;
+    }
+
+    protected override Swap2Move[] GenerateMoves(Permutation permutation) {
+      return Apply(permutation);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/StochasticSwap2MultiMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/StochasticSwap2MultiMoveGenerator.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/StochasticSwap2MultiMoveGenerator.cs	(revision 5933)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("StochasticSwap2MultiMoveGenerator", "Randomly samples n from all possible swap-2 moves from a given permutation.")]
+  [StorableClass]
+  public class StochasticSwap2MultiMoveGenerator : Swap2MoveGenerator, IMultiMoveGenerator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public IntValue SampleSize {
+      get { return SampleSizeParameter.Value; }
+      set { SampleSizeParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected StochasticSwap2MultiMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected StochasticSwap2MultiMoveGenerator(StochasticSwap2MultiMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public StochasticSwap2MultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticSwap2MultiMoveGenerator(this, cloner);
+    }
+
+    public static Swap2Move[] Apply(Permutation permutation, IRandom random, int sampleSize) {
+      int length = permutation.Length;
+      Swap2Move[] moves = new Swap2Move[sampleSize];
+      for (int i = 0; i < sampleSize; i++) {
+        moves[i] = StochasticSwap2SingleMoveGenerator.Apply(permutation, random);
+      }
+      return moves;
+    }
+
+    protected override Swap2Move[] GenerateMoves(Permutation permutation) {
+      IRandom random = RandomParameter.ActualValue;
+      return Apply(permutation, random, SampleSizeParameter.ActualValue.Value);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/StochasticSwap2SingleMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/StochasticSwap2SingleMoveGenerator.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/StochasticSwap2SingleMoveGenerator.cs	(revision 5933)
@@ -0,0 +1,64 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("StochasticSwap2SingleMoveGenerator", "Randomly samples a single from all possible swap-2 moves from a given permutation.")]
+  [StorableClass]
+  public class StochasticSwap2SingleMoveGenerator : Swap2MoveGenerator, IStochasticOperator, ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected StochasticSwap2SingleMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected StochasticSwap2SingleMoveGenerator(StochasticSwap2SingleMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public StochasticSwap2SingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticSwap2SingleMoveGenerator(this, cloner);
+    }
+
+    public static Swap2Move Apply(Permutation permutation, IRandom random) {
+      int length = permutation.Length;
+      if (length < 2) throw new ArgumentException("StochasticSwap2SingleMoveGenerator: There cannot be a swap-2 move given a permutation of length less than 2.", "permutation");
+      int index1 = random.Next(length), index2 = 0;
+      do {
+        index2 = random.Next(length);
+      } while (index1 == index2);
+      return new Swap2Move(index1, index2);
+    }
+
+    protected override Swap2Move[] GenerateMoves(Permutation permutation) {
+      IRandom random = RandomParameter.ActualValue;
+      return new Swap2Move[] { Apply(permutation, random) };
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2Move.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2Move.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2Move.cs	(revision 5933)
@@ -0,0 +1,41 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Swap2Move", "Item that describes a swap-2 move.")]
+  [StorableClass]
+  public class Swap2Move : TwoIndexMove {
+    [StorableConstructor]
+    protected Swap2Move(bool deserializing) : base(deserializing) { }
+    protected Swap2Move(Swap2Move original, Cloner cloner) : base(original, cloner) { }
+    public Swap2Move() : base() { }
+    public Swap2Move(int index1, int index2) : base(index1, index2, null) { }
+    public Swap2Move(int index1, int index2, Permutation permutation) : base(index1, index2, permutation) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2Move(this, cloner);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveAbsoluteAttribute.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveAbsoluteAttribute.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveAbsoluteAttribute.cs	(revision 5933)
@@ -0,0 +1,61 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Swap2MoveAbsoluteAttribute", "Specifies the tabu attributes for a swap-2 move on an absolute position permutation.")]
+  [StorableClass]
+  public class Swap2MoveAbsoluteAttribute : PermutationMoveAttribute {
+    [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]
+    protected Swap2MoveAbsoluteAttribute(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveAbsoluteAttribute(Swap2MoveAbsoluteAttribute original, Cloner cloner)
+      : base(original, cloner) {
+      this.Index1 = original.Index1;
+      this.Number1 = original.Number1;
+      this.Index2 = original.Index2;
+      this.Number2 = original.Number2;
+    }
+    public Swap2MoveAbsoluteAttribute() : this(-1, -1, -1, -1, -1) { }
+    public Swap2MoveAbsoluteAttribute(int index1, int number1, int index2, int number2, double moveQuality)
+      : base(moveQuality) {
+      Index1 = index1;
+      Number1 = number1;
+      Index2 = index2;
+      Number2 = number2;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveAbsoluteAttribute(this, cloner);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveGenerator.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveGenerator.cs	(revision 5933)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Swap2MoveGenerator", "Base class for all swap-2 move generators.")]
+  [StorableClass]
+  public abstract class Swap2MoveGenerator : SingleSuccessorOperator, IPermutationSwap2MoveOperator, IMoveGenerator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (LookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveGenerator(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveGenerator(Swap2MoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation for which moves should be generated."));
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The moves that should be generated in subscopes."));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
+    }
+
+    public override IOperation Apply() {
+      Permutation p = PermutationParameter.ActualValue;
+      Swap2Move[] moves = GenerateMoves(p);
+      Scope[] moveScopes = new Scope[moves.Length];
+      for (int i = 0; i < moveScopes.Length; i++) {
+        moveScopes[i] = new Scope(i.ToString());
+        moveScopes[i].Variables.Add(new Variable(Swap2MoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+      return base.Apply();
+    }
+
+    protected abstract Swap2Move[] GenerateMoves(Permutation permutation);
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveHardTabuCriterion.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveHardTabuCriterion.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveHardTabuCriterion.cs	(revision 5933)
@@ -0,0 +1,169 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+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("Swap2MoveHardTabuCriterion", @"For relative postion encoded permutations it prevents readding of previously deleted edges as well as deleting previously added edges.
+  For absolute position encoded permutations it prevents moving a number if it was previously moved.
+
+If the aspiration condition is activated, a move will not be considered tabu against a move in the tabu list if it leads to a better solution than the quality recorded with the move in the tabu list.")]
+  [StorableClass]
+  public class Swap2MoveHardTabuCriterion : SingleSuccessorOperator, IPermutationSwap2MoveOperator, ITabuChecker {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (LookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+    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"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ValueParameter<BoolValue> UseAspirationCriterionParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; }
+    }
+
+    public BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveHardTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveHardTabuCriterion(Swap2MoveHardTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveHardTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "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 ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveHardTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      Swap2Move move = Swap2MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      int length = permutation.Length;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+
+      if (permutation.PermutationType != PermutationTypes.Absolute)
+        isTabu = EvaluateRelativeTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration);
+      else isTabu = EvaluateAbsoluteTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration);
+
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+
+    private static bool EvaluateRelativeTabuState(ItemList<IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) {
+      bool isTabu = false;
+      StandardEdgeEqualityComparer eq = new StandardEdgeEqualityComparer();
+      bool bidirectional = permutation.PermutationType == PermutationTypes.RelativeUndirected;
+      List<Edge> deleted = new List<Edge>();
+      deleted.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index1], bidirectional));
+      deleted.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index1 + 1), bidirectional));
+      deleted.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index2], bidirectional));
+      deleted.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index2 + 1), bidirectional));
+      List<Edge> added = new List<Edge>();
+      added.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index2], bidirectional));
+      added.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index1 + 1), bidirectional));
+      added.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index1], bidirectional));
+      added.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index2 + 1), bidirectional));
+
+      foreach (IItem tabuMove in tabuList) {
+        Swap2MoveRelativeAttribute relAttrib = (tabuMove as Swap2MoveRelativeAttribute);
+        if (relAttrib != null
+          && (!useAspiration
+              || maximization && moveQuality <= relAttrib.MoveQuality
+              || !maximization && moveQuality >= relAttrib.MoveQuality)) {
+          for (int i = 0; i < relAttrib.AddedEdges.Count; i++) {
+            isTabu = eq.Equals(relAttrib.AddedEdges[i], deleted[0])
+                  || eq.Equals(relAttrib.AddedEdges[i], deleted[1])
+                  || eq.Equals(relAttrib.AddedEdges[i], deleted[2])
+                  || eq.Equals(relAttrib.AddedEdges[i], deleted[3]);
+            if (isTabu) break;
+          }
+          if (isTabu) break;
+          for (int i = 0; i < relAttrib.DeletedEdges.Count; i++) {
+            isTabu = eq.Equals(relAttrib.DeletedEdges[i], added[0])
+                  || eq.Equals(relAttrib.DeletedEdges[i], added[1])
+                  || eq.Equals(relAttrib.DeletedEdges[i], added[2])
+                  || eq.Equals(relAttrib.DeletedEdges[i], added[3]);
+            if (isTabu) break;
+          }
+        }
+        if (isTabu) break;
+      }
+      return isTabu;
+    }
+
+    private bool EvaluateAbsoluteTabuState(ItemList<IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) {
+      bool isTabu = false;
+      foreach (IItem tabuMove in tabuList) {
+        Swap2MoveAbsoluteAttribute attrib = (tabuMove as Swap2MoveAbsoluteAttribute);
+        if (attrib != null
+          && (!useAspiration
+              || maximization && moveQuality <= attrib.MoveQuality
+              || !maximization && moveQuality >= attrib.MoveQuality)) {
+          int i1 = move.Index1;
+          int n1 = permutation[move.Index1];
+          int i2 = move.Index2;
+          int n2 = permutation[move.Index2];
+          if (attrib != null) {
+            if (attrib.Number1 == n1 || attrib.Number1 == n2
+              || attrib.Number2 == n2 || attrib.Number2 == n1)
+              isTabu = true;
+          }
+        }
+        if (isTabu) break;
+      }
+      return isTabu;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveMaker.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveMaker.cs	(revision 5933)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Swap2MoveMaker", "Peforms a swap-2 move on a given permutation and updates the quality.")]
+  [StorableClass]
+  public class Swap2MoveMaker : SingleSuccessorOperator, IPermutationSwap2MoveOperator, IMoveMaker {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (ILookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveMaker(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveMaker(Swap2MoveMaker original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The relative quality of the move."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveMaker(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      Swap2Move move = Swap2MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      DoubleValue moveQuality = MoveQualityParameter.ActualValue;
+      DoubleValue quality = QualityParameter.ActualValue;
+
+      Swap2Manipulator.Apply(permutation, move.Index1, move.Index2);
+      quality.Value = moveQuality.Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveRelativeAttribute.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveRelativeAttribute.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveRelativeAttribute.cs	(revision 5933)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Swap2MoveRelativeAttribute", "Specifies the tabu attributes for a swap-2 move on a relative position permutation.")]
+  [StorableClass]
+  public class Swap2MoveRelativeAttribute : PermutationMoveAttribute {
+    [Storable]
+    public ItemList<Edge> DeletedEdges { get; private set; }
+    [Storable]
+    public ItemList<Edge> AddedEdges { get; private set; }
+
+    [StorableConstructor]
+    protected Swap2MoveRelativeAttribute(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveRelativeAttribute(Swap2MoveRelativeAttribute original, Cloner cloner)
+      : base(original, cloner) {
+      this.DeletedEdges = cloner.Clone(original.DeletedEdges);
+      this.AddedEdges = cloner.Clone(original.AddedEdges);
+    }
+    public Swap2MoveRelativeAttribute(double moveQuality)
+      : base(moveQuality) {
+      DeletedEdges = new ItemList<Edge>();
+      AddedEdges = new ItemList<Edge>();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveRelativeAttribute(this, cloner);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveSoftTabuCriterion.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveSoftTabuCriterion.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveSoftTabuCriterion.cs	(revision 5933)
@@ -0,0 +1,154 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+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("Swap2MoveSoftTabuCriterion", @"For relative postion encoded permutations it just prevents readding of previously deleted edges, but allows deleting previously added edges.
+  For absolute position encoded permutations it prevents moving a number to a position it has previously occupied.
+
+If the aspiration condition is activated, a move will not be considered tabu against a move in the tabu list if it leads to a better solution than the quality recorded with the move in the tabu list.")]
+  [StorableClass]
+  public class Swap2MoveSoftTabuCriterion : SingleSuccessorOperator, IPermutationSwap2MoveOperator, ITabuChecker {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (LookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+    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"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ValueParameter<BoolValue> UseAspirationCriterionParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; }
+    }
+
+    public BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveSoftTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveSoftTabuCriterion(Swap2MoveSoftTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveSoftTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "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 ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveSoftTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      Swap2Move move = Swap2MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      int length = permutation.Length;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+
+      if (permutation.PermutationType != PermutationTypes.Absolute)
+        isTabu = EvaluateRelativeTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration);
+      else isTabu = EvaluateAbsoluteTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration);
+
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+
+    private static bool EvaluateRelativeTabuState(ItemList<IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) {
+      bool isTabu = false;
+      StandardEdgeEqualityComparer eq = new StandardEdgeEqualityComparer();
+      bool bidirectional = permutation.PermutationType == PermutationTypes.RelativeUndirected;
+      List<Edge> added = new List<Edge>();
+      added.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index2], bidirectional));
+      added.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index1 + 1), bidirectional));
+      added.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index1], bidirectional));
+      added.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index2 + 1), bidirectional));
+
+      foreach (IItem tabuMove in tabuList) {
+        Swap2MoveRelativeAttribute relAttrib = (tabuMove as Swap2MoveRelativeAttribute);
+        if (relAttrib != null
+          && (!useAspiration
+              || maximization && moveQuality <= relAttrib.MoveQuality
+              || !maximization && moveQuality >= relAttrib.MoveQuality)) {
+          for (int i = 0; i < relAttrib.DeletedEdges.Count; i++) {
+            isTabu = eq.Equals(relAttrib.DeletedEdges[i], added[0])
+                  || eq.Equals(relAttrib.DeletedEdges[i], added[1])
+                  || eq.Equals(relAttrib.DeletedEdges[i], added[2])
+                  || eq.Equals(relAttrib.DeletedEdges[i], added[3]);
+            if (isTabu) break;
+          }
+        }
+        if (isTabu) break;
+      }
+      return isTabu;
+    }
+
+    private bool EvaluateAbsoluteTabuState(ItemList<IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) {
+      bool isTabu = false;
+      foreach (IItem tabuMove in tabuList) {
+        Swap2MoveAbsoluteAttribute attrib = (tabuMove as Swap2MoveAbsoluteAttribute);
+        if (attrib != null
+          && (!useAspiration
+              || maximization && moveQuality <= attrib.MoveQuality
+              || !maximization && moveQuality >= attrib.MoveQuality)) {
+          int i1 = move.Index1;
+          int n1 = permutation[move.Index1];
+          int i2 = move.Index2;
+          int n2 = permutation[move.Index2];
+          if ((attrib.Index1 == i1 || attrib.Index1 == i2) && (attrib.Number1 == n1 || attrib.Number1 == n2)
+            || (attrib.Index2 == i2 || attrib.Index2 == i1) && (attrib.Number2 == n2 || attrib.Number2 == n1))
+            isTabu = true;
+        }
+        if (isTabu) break;
+      }
+      return isTabu;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveTabuMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveTabuMaker.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/Swap2MoveTabuMaker.cs	(revision 5933)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("Swap2MoveTabuMaker", "Declares a given swap-2 move as tabu, by adding its attributes to the tabu list and also store the solution quality or the move quality (whichever is better).")]
+  [StorableClass]
+  public class Swap2MoveTabuMaker : TabuMaker, IPermutationSwap2MoveOperator {
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (LookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveTabuMaker(Swap2MoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The move that was made."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      Swap2Move move = Swap2MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      double baseQuality = moveQuality;
+      if (maximization && quality > moveQuality || !maximization && quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality
+      if (permutation.PermutationType == PermutationTypes.Absolute)
+        return new Swap2MoveAbsoluteAttribute(move.Index1, permutation[move.Index1], move.Index2, permutation[move.Index2], baseQuality);
+      else {
+        Swap2MoveRelativeAttribute attrib = new Swap2MoveRelativeAttribute(baseQuality);
+        bool bidirectional = permutation.PermutationType == PermutationTypes.RelativeUndirected;
+        attrib.DeletedEdges.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index1], bidirectional));
+        attrib.DeletedEdges.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index1 + 1), bidirectional));
+        attrib.DeletedEdges.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index2], bidirectional));
+        attrib.DeletedEdges.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index2 + 1), bidirectional));
+        attrib.AddedEdges.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index2], bidirectional));
+        attrib.AddedEdges.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index1 + 1), bidirectional));
+        attrib.AddedEdges.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index1], bidirectional));
+        attrib.AddedEdges.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index2 + 1), bidirectional));
+        return attrib;
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeIndexMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeIndexMove.cs	(revision 5809)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeIndexMove.cs	(revision 5933)
@@ -25,5 +25,5 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("ThreeIndexMove", "A move on a permutation that is specified by 3 indices")]
+  [Item("ThreeIndexMove", "A move on a permutation that is specified by 3 indices.")]
   [StorableClass]
   public class ThreeIndexMove : Item {
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoIndexMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoIndexMove.cs	(revision 5809)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoIndexMove.cs	(revision 5933)
@@ -25,5 +25,5 @@
 
 namespace HeuristicLab.Encodings.PermutationEncoding {
-  [Item("TwoIndexMove", "A move on a permutation that is specified by 2 indices")]
+  [Item("TwoIndexMove", "A move on a permutation that is specified by 2 indices.")]
   [StorableClass]
   public class TwoIndexMove : Item {
