Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/EstimatedPTSP.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/EstimatedPTSP.cs	(revision 12269)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/EstimatedPTSP.cs	(revision 12272)
@@ -95,5 +95,15 @@
       Operators.Add(new PTSPExhaustiveInversionLocalImprovement());
       Operators.Add(new PTSPExhaustiveInsertionLocalImprovement());
+
+      Operators.Add(new Exhaustive25MoveGenerator());
+      Operators.Add(new Stochastic25MultiMoveGenerator());
+      Operators.Add(new Stochastic25SingleMoveGenerator());
+      Operators.Add(new TwoPointFiveMoveMaker());
+      Operators.Add(new PTSP25MoveEvaluator());
+
       Encoding.ConfigureOperators(Operators.OfType<IOperator>());
+      foreach (var twopointfiveMoveOperator in Operators.OfType<I25MoveOperator>()) {
+        twopointfiveMoveOperator.TwoPointFiveMoveParameter.ActualName = "Permutation.TwoPointFiveMove";
+      }
     }
 
@@ -156,4 +166,8 @@
         op.RealizationsParameter.Value = realizations;
       }
+      foreach (var op in Operators.OfType<PTSP25MoveEvaluator>()) {
+        op.RealizationsParameter.Value = realizations;
+      }
+
     }
   }
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/HeuristicLab.Problems.PTSP-3.3.csproj
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/HeuristicLab.Problems.PTSP-3.3.csproj	(revision 12269)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/HeuristicLab.Problems.PTSP-3.3.csproj	(revision 12272)
@@ -119,4 +119,5 @@
     <Compile Include="Improvers\PTSPExhaustiveInsertionLocalImprovement.cs" />
     <Compile Include="Improvers\PTSPExhaustiveInversionLocalImprovement.cs" />
+    <Compile Include="Interfaces\I25MoveOperator.cs" />
     <Compile Include="Interfaces\IPTSPPathMoveEvaluator.cs" />
     <Compile Include="Interfaces\IPTSPMoveEvaluator.cs" />
@@ -126,4 +127,11 @@
     <Compile Include="MoveEvaluators\TwoOpt\PTSPAnalyticalInversionMovePathEvaluator.cs" />
     <Compile Include="MoveEvaluators\TwoOpt\PTSPEstimatedInversionMovePathEvaluator.cs" />
+    <Compile Include="MoveEvaluators\TwoPointFiveOpt\PTSP25MoveEvaluator.cs" />
+    <Compile Include="MoveGenerators\Exhaustive25MoveGenerator.cs" />
+    <Compile Include="MoveGenerators\Stochastic25MultiMoveGenerator.cs" />
+    <Compile Include="MoveGenerators\Stochastic25SingleMoveGenerator.cs" />
+    <Compile Include="MoveGenerators\TwoPointFiveMoveGenerator.cs" />
+    <Compile Include="MoveMakers\TwoPointFiveMoveMaker.cs" />
+    <Compile Include="Moves\TwoPointFiveOpt\TwoPointFiveMove.cs" />
     <Compile Include="PathPTSPTour.cs" />
     <Compile Include="PTSP.cs" />
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Interfaces/I25MoveOperator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Interfaces/I25MoveOperator.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Interfaces/I25MoveOperator.cs	(revision 12272)
@@ -0,0 +1,13 @@
+﻿using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Problems.PTSP {
+  public interface I25MoveOperator : IMoveOperator {
+    ILookupParameter<TwoPointFiveMove> TwoPointFiveMoveParameter { get; }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/OneShift/PTSPEstimatedInsertionEvaluator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/OneShift/PTSPEstimatedInsertionEvaluator.cs	(revision 12269)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/OneShift/PTSPEstimatedInsertionEvaluator.cs	(revision 12272)
@@ -157,5 +157,5 @@
       }
       // return average of cost differences
-      return Math.Abs(moveQuality) / realizations.Capacity;
+      return moveQuality / realizations.Capacity;
     }
 
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/TwoOpt/PTSPEstimatedInversionMovePathEvaluator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/TwoOpt/PTSPEstimatedInversionMovePathEvaluator.cs	(revision 12269)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/TwoOpt/PTSPEstimatedInversionMovePathEvaluator.cs	(revision 12272)
@@ -119,5 +119,5 @@
       }
       // return average of cost differences
-      return Math.Abs(moveQuality) / realizations.Capacity;
+      return moveQuality / realizations.Capacity;
     }
 
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/TwoPointFiveOpt/PTSP25MoveEvaluator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/TwoPointFiveOpt/PTSP25MoveEvaluator.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveEvaluators/TwoPointFiveOpt/PTSP25MoveEvaluator.cs	(revision 12272)
@@ -0,0 +1,280 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Optimization;
+using HeuristicLab.Operators;
+
+namespace HeuristicLab.Problems.PTSP {
+  /// <summary>
+  /// A base class for operators which evaluate TSP solutions.
+  /// </summary>
+  [Item("PTSP25MoveEvaluator", "Operator that evaluates 2.5-p-opt moves of PTSP")]
+  [StorableClass]
+  public class PTSP25MoveEvaluator : SingleSuccessorOperator, I25MoveOperator, ISingleObjectiveMoveEvaluator {
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrix> CoordinatesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Coordinates"]; }
+    }
+    public ILookupParameter<DistanceMatrix> DistanceMatrixParameter {
+      get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; }
+    }
+    public ILookupParameter<BoolValue> UseDistanceMatrixParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["UseDistanceMatrix"]; }
+    }
+    public IValueParameter<ItemList<ItemList<IntValue>>> RealizationsParameter {
+      get { return (IValueParameter<ItemList<ItemList<IntValue>>>)Parameters["Realizations"]; }
+    }
+    public ILookupParameter<TwoPointFiveMove> TwoPointFiveMoveParameter {
+      get { return (ILookupParameter<TwoPointFiveMove>)Parameters["TwoPointFiveMove"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+
+    [StorableConstructor]
+    protected PTSP25MoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected PTSP25MoveEvaluator(PTSP25MoveEvaluator original, Cloner cloner) : base(original, cloner) { }
+    public PTSP25MoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Coordinates", "The city's coordinates."));
+      Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities."));
+      Parameters.Add(new LookupParameter<BoolValue>("UseDistanceMatrix", "True if a distance matrix should be calculated (if it does not exist already) and used for evaluation, otherwise false."));
+      Parameters.Add(new ValueParameter<ItemList<ItemList<IntValue>>>("Realizations", "The concrete..."));
+      Parameters.Add(new LookupParameter<TwoPointFiveMove>("TwoPointFiveMove", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of a TSP solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The evaluated quality of a move on a TSP solution."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PTSP25MoveEvaluator(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code (remove with 3.4)
+      LookupParameter<DoubleMatrix> oldDistanceMatrixParameter = Parameters["DistanceMatrix"] as LookupParameter<DoubleMatrix>;
+      if (oldDistanceMatrixParameter != null) {
+        Parameters.Remove(oldDistanceMatrixParameter);
+        Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities."));
+        DistanceMatrixParameter.ActualName = oldDistanceMatrixParameter.ActualName;
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      Permutation permutation = PermutationParameter.ActualValue;
+      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
+      double relativeQualityDifference = 0;
+      if (UseDistanceMatrixParameter.ActualValue.Value) {
+        DistanceMatrix distanceMatrix = DistanceMatrixParameter.ActualValue;
+        if (distanceMatrix == null) {
+          if (coordinates == null) throw new InvalidOperationException("Neither a distance matrix nor coordinates were given.");
+          distanceMatrix = CalculateDistanceMatrix(coordinates);
+          DistanceMatrixParameter.ActualValue = distanceMatrix;
+        }
+        relativeQualityDifference = EvaluateByDistanceMatrix(permutation, distanceMatrix);
+      } 
+      DoubleValue moveQuality = MoveQualityParameter.ActualValue;
+      if (moveQuality == null) MoveQualityParameter.ActualValue = new DoubleValue(QualityParameter.ActualValue.Value + relativeQualityDifference);
+      else moveQuality.Value = QualityParameter.ActualValue.Value + relativeQualityDifference;
+      return base.Apply();
+    }
+
+    protected double CalculateDistance(double x1, double y1, double x2, double y2) {
+      return Math.Round(Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
+    }
+
+    private static int decreaseCircularIndex(int length, int index) {
+      int result = index - 1;
+      if (result == -1) {
+        result = length - 1;
+      }
+      return result;
+    }
+
+    private static int increaseCircularIndex(int length, int index) {
+      int result = index + 1;
+      if (result == length + 1) {
+        result = 0;
+      }
+      return result;
+    }
+    
+
+    public static double EvaluateInversionByDistanceMatrix(Permutation permutation, TwoPointFiveMove move, DistanceMatrix distanceMatrix, ItemList<ItemList<IntValue>> realizations) {
+      double moveQuality = 0;
+      int[] edges = new int[4];
+      int[] indices = new int[4];
+      edges[0] = permutation.GetCircular(move.Index1 - 1);
+      indices[0] = decreaseCircularIndex(permutation.Length, move.Index1);
+      edges[1] = permutation[move.Index1];
+      indices[1] = move.Index1;
+      edges[2] = permutation[move.Index2];
+      indices[2] = move.Index2;
+      edges[3] = permutation.GetCircular(move.Index2 + 1);
+      indices[3] = increaseCircularIndex(permutation.Length, move.Index2);
+      int[] aPosteriori = new int[4];
+      foreach (ItemList<IntValue> realization in realizations) {
+        for (int i = 0; i < edges.Length; i++) {
+          if (realization[edges[i]].Value == 1) {
+            aPosteriori[i] = edges[i];
+          } else {
+            int j = 1;
+            if (i % 2 == 0) {
+              // find nearest predecessor in realization if source edge
+              while (realization[permutation.GetCircular(indices[i] - j)].Value == 0) {
+                j++;
+              }
+              aPosteriori[i] = permutation.GetCircular(indices[i] - j);
+            } else {
+              // find nearest successor in realization if target edge
+              while (realization[permutation.GetCircular(indices[i] + j)].Value == 0) {
+                j++;
+              }
+              aPosteriori[i] = permutation.GetCircular(indices[i] + j);
+            }
+          }
+        }
+        // compute cost difference between the two a posteriori solutions
+        if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3])) {
+          moveQuality = moveQuality + distanceMatrix[aPosteriori[0], aPosteriori[2]] + distanceMatrix[aPosteriori[1], aPosteriori[3]] - distanceMatrix[aPosteriori[0], aPosteriori[1]] - distanceMatrix[aPosteriori[2], aPosteriori[3]];
+        }
+        Array.Clear(aPosteriori, 0, aPosteriori.Length);
+      }
+      // return average of cost differences
+      return moveQuality / realizations.Capacity;
+    }
+    public static double EvaluateInsertionByDistanceMatrix(Permutation permutation, TwoPointFiveMove move, DistanceMatrix distanceMatrix, ItemList<ItemList<IntValue>> realizations) {
+      Permutation afterMove = new Permutation(PermutationTypes.RelativeUndirected, permutation);
+      TranslocationManipulator.Apply(afterMove, move.Index1, move.Index1, move.Index2);
+      double moveQuality = 0;
+      int[] edges = new int[12];
+      int[] indices = new int[12];
+      edges[0] = permutation.GetCircular(move.Index1 - 1);
+      indices[0] = decreaseCircularIndex(permutation.Length, move.Index1);
+      edges[1] = permutation[move.Index1];
+      indices[1] = move.Index1;
+      edges[2] = permutation[move.Index1];
+      indices[2] = move.Index1;
+      edges[3] = permutation.GetCircular(move.Index1 + 1);
+      indices[3] = increaseCircularIndex(permutation.Length, move.Index1);
+
+      edges[6] = afterMove.GetCircular(move.Index2 - 1);
+      indices[6] = decreaseCircularIndex(afterMove.Length, move.Index2);
+      edges[7] = afterMove[move.Index2];
+      indices[7] = move.Index2;
+      edges[8] = afterMove[move.Index2];
+      indices[8] = move.Index2;
+      edges[9] = afterMove.GetCircular(move.Index2 + 1);
+      indices[9] = increaseCircularIndex(afterMove.Length, move.Index2);
+
+      if (move.Index2 > move.Index1) {
+        edges[4] = permutation[move.Index2];
+        indices[4] = move.Index2;
+        edges[5] = permutation.GetCircular(move.Index2 + 1);
+        indices[5] = indices[9];
+        edges[10] = afterMove.GetCircular(move.Index1 - 1);
+        indices[10] = indices[0];
+        edges[11] = afterMove[move.Index1];
+        indices[11] = move.Index1;
+      } else {
+        edges[4] = permutation.GetCircular(move.Index2 - 1);
+        indices[4] = indices[6];
+        edges[5] = permutation[move.Index2];
+        indices[5] = move.Index2;
+        edges[10] = afterMove[move.Index1];
+        indices[10] = move.Index1;
+        edges[11] = afterMove.GetCircular(move.Index1 + 1);
+        indices[11] = indices[3];
+      }
+      int[] aPosteriori = new int[12];
+      Permutation tempPermutation;
+      foreach (ItemList<IntValue> realization in realizations) {
+        for (int i = 0; i < edges.Length; i++) {
+          if (i < 6) {
+            tempPermutation = permutation;
+          } else {
+            tempPermutation = afterMove;
+          }
+          if (realization[edges[i]].Value == 1) {
+            aPosteriori[i] = edges[i];
+          } else {
+            int j = 1;
+            if (i % 2 == 0) {
+              // find nearest predecessor in realization if source edge
+              while (realization[tempPermutation.GetCircular(indices[i] - j)].Value == 0) {
+                j++;
+              }
+              aPosteriori[i] = tempPermutation.GetCircular(indices[i] - j);
+            } else {
+              // find nearest successor in realization if target edge
+              while (realization[tempPermutation.GetCircular(indices[i] + j)].Value == 0) {
+                j++;
+              }
+              aPosteriori[i] = tempPermutation.GetCircular(indices[i] + j);
+            }
+          }
+        }
+        if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3]) &&
+          !(aPosteriori[0] == aPosteriori[4] && aPosteriori[1] == aPosteriori[5]) &&
+          !(aPosteriori[2] == aPosteriori[4] && aPosteriori[3] == aPosteriori[5])) {
+          // compute cost difference between the two a posteriori solutions
+          moveQuality = moveQuality + distanceMatrix[aPosteriori[6], aPosteriori[7]] + distanceMatrix[aPosteriori[8], aPosteriori[9]] + distanceMatrix[aPosteriori[10], aPosteriori[11]];
+          moveQuality = moveQuality - distanceMatrix[aPosteriori[0], aPosteriori[1]] - distanceMatrix[aPosteriori[2], aPosteriori[3]] - distanceMatrix[aPosteriori[4], aPosteriori[5]];
+        }
+        Array.Clear(aPosteriori, 0, aPosteriori.Length);
+      }
+      // return average of cost differences
+      return moveQuality / realizations.Capacity;
+    }
+    protected double EvaluateByDistanceMatrix(Permutation permutation, DistanceMatrix distanceMatrix) {
+      TwoPointFiveMove currentMove = TwoPointFiveMoveParameter.ActualValue;
+      if (currentMove.IsInvert) {
+        return EvaluateInversionByDistanceMatrix(permutation, currentMove, distanceMatrix, RealizationsParameter.Value);
+      } else {
+        return EvaluateInsertionByDistanceMatrix(permutation, currentMove, distanceMatrix, RealizationsParameter.Value);
+      } 
+    }
+
+    private DistanceMatrix CalculateDistanceMatrix(DoubleMatrix c) {
+      DistanceMatrix distanceMatrix = new DistanceMatrix(c.Rows, c.Rows);
+      for (int i = 0; i < distanceMatrix.Rows; i++) {
+        for (int j = 0; j < distanceMatrix.Columns; j++)
+          distanceMatrix[i, j] = CalculateDistance(c[i, 0], c[i, 1], c[j, 0], c[j, 1]);
+      }
+      return (DistanceMatrix)distanceMatrix.AsReadOnly();
+    }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Exhaustive25MoveGenerator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Exhaustive25MoveGenerator.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Exhaustive25MoveGenerator.cs	(revision 12272)
@@ -0,0 +1,66 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Operators;
+
+namespace HeuristicLab.Problems.PTSP {
+  [Item("Exhaustive25MoveGenerator", "Generates all possible inversion and shift moves (2.5-opt) from a given permutation.")]
+  [StorableClass]
+  class Exhaustive25MoveGenerator : TwoPointFiveMoveGenerator, IExhaustiveMoveGenerator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    [StorableConstructor]
+    protected Exhaustive25MoveGenerator(bool deserializing) : base(deserializing) { }
+    protected Exhaustive25MoveGenerator(Exhaustive25MoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public Exhaustive25MoveGenerator() 
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Exhaustive25MoveGenerator(this, cloner);
+    }
+    
+    public static TwoPointFiveMove[] Apply(Permutation permutation) {
+      return Generate(permutation).ToArray();
+    }
+
+    public static IEnumerable<TwoPointFiveMove> Generate(Permutation permutation) {
+      int length = permutation.Length;
+      if (length == 1) throw new ArgumentException("Exhaustive25MoveGenerator: There cannot be a 2.5 move given a permutation of length 1.", "permutation");
+      int totalMoves = (length) * (length - 1) / 2;
+
+      if (permutation.PermutationType == PermutationTypes.RelativeUndirected) {
+        if (totalMoves - 3 > 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 in case of relative undirected permutations
+              if (j - i >= length - 2) continue;
+              yield return new TwoPointFiveMove(i, j,true);
+              yield return new TwoPointFiveMove(i, j, false);
+            }
+          }
+        } else { // when length is 3 or less, there's actually no difference, but for the sake of not crashing the algorithm create a dummy move
+          yield return new TwoPointFiveMove(0, 1,true);
+        }
+      } else {
+        for (int i = 0; i < length - 1; i++)
+          for (int j = i + 1; j < length; j++) {
+            yield return new TwoPointFiveMove(i, j,true);
+            yield return new TwoPointFiveMove(i, j, false);
+          }
+      }
+    }
+
+    protected override TwoPointFiveMove[] GenerateMoves(Permutation permutation) {
+      return Apply(permutation);
+    }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Stochastic25MultiMoveGenerator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Stochastic25MultiMoveGenerator.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Stochastic25MultiMoveGenerator.cs	(revision 12272)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.PTSP {
+  [Item("Stochastic25MultiMoveGenerator", "Randomly samples n from all possible inversion and shift moves (2.5-opt) from a given permutation.")]
+  [StorableClass]
+  class Stochastic25MultiMoveGenerator : TwoPointFiveMoveGenerator, 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 Stochastic25MultiMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected Stochastic25MultiMoveGenerator(Stochastic25MultiMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public Stochastic25MultiMoveGenerator()
+      : 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 Stochastic25MultiMoveGenerator(this, cloner);
+    }
+
+    public static TwoPointFiveMove[] Apply(Permutation permutation, IRandom random, int sampleSize) {
+      int length = permutation.Length;
+      TwoPointFiveMove[] moves = new TwoPointFiveMove[sampleSize];
+      for (int i = 0; i < sampleSize; i++) {
+        moves[i] = Stochastic25SingleMoveGenerator.Apply(permutation, random);
+      }
+      return moves;
+    }
+
+    protected override TwoPointFiveMove[] GenerateMoves(Permutation permutation) {
+      IRandom random = RandomParameter.ActualValue;
+      return Apply(permutation, random, SampleSizeParameter.ActualValue.Value);
+    }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Stochastic25SingleMoveGenerator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Stochastic25SingleMoveGenerator.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/Stochastic25SingleMoveGenerator.cs	(revision 12272)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Operators;
+using HeuristicLab.Encodings.PermutationEncoding;
+
+
+namespace HeuristicLab.Problems.PTSP {
+  [Item("Stochastic25SingleMoveGenerator", "Randomly samples a single from all possible inversion and shift moves (2.5-opt) from a given permutation.")]
+  [StorableClass]
+  class Stochastic25SingleMoveGenerator : TwoPointFiveMoveGenerator, IStochasticOperator, ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected Stochastic25SingleMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected Stochastic25SingleMoveGenerator(Stochastic25SingleMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public Stochastic25SingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Stochastic25SingleMoveGenerator(this, cloner);
+    }
+
+    public static TwoPointFiveMove Apply(Permutation permutation, IRandom random) {
+      int length = permutation.Length;
+      if (length == 1) throw new ArgumentException("Stochastic25SingleMoveGenerator: There cannot be an inversion move given a permutation of length 1.", "permutation");
+      int index1 = random.Next(length - 1);
+      int index2 = random.Next(index1 + 1, length);
+      if (permutation.PermutationType == PermutationTypes.RelativeUndirected) {
+        if (length > 3) {
+          while (index2 - index1 >= length - 2)
+            index2 = random.Next(index1 + 1, length);
+        }
+      }
+      bool isInvert = random.NextDouble() > 0.5;
+      return new TwoPointFiveMove(index1, index2, isInvert);
+      
+    }
+
+    protected override TwoPointFiveMove[] GenerateMoves(Permutation permutation) {
+      IRandom random = RandomParameter.ActualValue;
+      return new TwoPointFiveMove[] { Apply(permutation, random) };
+    }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/TwoPointFiveMoveGenerator.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/TwoPointFiveMoveGenerator.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveGenerators/TwoPointFiveMoveGenerator.cs	(revision 12272)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+
+namespace HeuristicLab.Problems.PTSP {
+  [Item("TwoPointFiveMoveGenerator", "Base class for all inversion and shift (2.5-opt) move generators.")]
+  [StorableClass]
+  public abstract class TwoPointFiveMoveGenerator : SingleSuccessorOperator, I25MoveOperator, IMoveGenerator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<TwoPointFiveMove> TwoPointFiveMoveParameter {
+      get { return (LookupParameter<TwoPointFiveMove>)Parameters["TwoPointFiveMove"]; }
+    }
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected TwoPointFiveMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected TwoPointFiveMoveGenerator(TwoPointFiveMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public TwoPointFiveMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation for which moves should be generated."));
+      Parameters.Add(new LookupParameter<TwoPointFiveMove>("TwoPointFiveMove", "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;
+      TwoPointFiveMove[] 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(TwoPointFiveMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+      return base.Apply();
+    }
+
+    protected abstract TwoPointFiveMove[] GenerateMoves(Permutation permutation);
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveMakers/TwoPointFiveMoveMaker.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveMakers/TwoPointFiveMoveMaker.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/MoveMakers/TwoPointFiveMoveMaker.cs	(revision 12272)
@@ -0,0 +1,61 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.PTSP {
+  [Item("TwoPointFiveMoveMaker", "Peforms an inversion and shift (2.5-opt) on a given permutation and updates the quality.")]
+  [StorableClass]
+  public class TwoPointFiveMoveMaker : SingleSuccessorOperator, I25MoveOperator, 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<TwoPointFiveMove> TwoPointFiveMoveParameter {
+      get { return (ILookupParameter<TwoPointFiveMove>)Parameters["TwoPointFiveMove"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    [StorableConstructor]
+    protected TwoPointFiveMoveMaker(bool deserializing) : base(deserializing) { }
+    protected TwoPointFiveMoveMaker(TwoPointFiveMoveMaker original, Cloner cloner) : base(original, cloner) { }
+    public TwoPointFiveMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<TwoPointFiveMove>("TwoPointFiveMove", "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 TwoPointFiveMoveMaker(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      TwoPointFiveMove move = TwoPointFiveMoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      DoubleValue moveQuality = MoveQualityParameter.ActualValue;
+      DoubleValue quality = QualityParameter.ActualValue;
+
+      if (move.IsInvert) {
+        InversionManipulator.Apply(permutation, move.Index1, move.Index2);
+      } else {
+        TranslocationManipulator.Apply(permutation, move.Index1, move.Index1, move.Index2);
+      }
+      
+      quality.Value = moveQuality.Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Moves/TwoPointFiveOpt/TwoPointFiveMove.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Moves/TwoPointFiveOpt/TwoPointFiveMove.cs	(revision 12272)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Moves/TwoPointFiveOpt/TwoPointFiveMove.cs	(revision 12272)
@@ -0,0 +1,49 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.PTSP {
+  public class TwoPointFiveMove : Item {
+    
+    [StorableConstructor]
+    public TwoPointFiveMove() : this(-1, -1,null, true) { }
+    protected TwoPointFiveMove(bool deserializing) : base(deserializing) { }
+    protected TwoPointFiveMove(TwoPointFiveMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.Index1 = original.Index1;
+      this.Index2 = original.Index2;
+      this.IsInvert = original.IsInvert;
+      if (original.Permutation != null)
+        this.Permutation = cloner.Clone(original.Permutation);
+    }
+    public TwoPointFiveMove(int index1, int index2, Permutation permutation, bool isinvert)
+      : base() {
+      Index1 = index1;
+      Index2 = index2;
+      IsInvert = isinvert;
+      Permutation = permutation;
+    }
+
+    public TwoPointFiveMove(int index1, int index2, bool isinvert)
+      : base() {
+      Index1 = index1;
+      Index2 = index2;
+      IsInvert = isinvert;
+      Permutation = null;
+    }
+
+    [Storable]
+    public int Index1 { get; protected set; }
+    [Storable]
+    public int Index2 { get; protected set; }
+    [Storable]
+    public Permutation Permutation { get; protected set; }
+    [Storable]
+    public bool IsInvert { get; protected set; }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TwoPointFiveMove(this, cloner);
+    }
+  }
+}
